xf86-video-intel: 681 commits - configure.ac .gitignore man/.cvsignore man/i810.man man/intel.man src/bios_reader/bios_dumper.c src/bios_reader/bios_reader.c src/bios_reader/.gitignore src/bios_reader/Makefile.am src/brw_structs.h src/ch7017/ch7017.c src/ch7017/ch7017_module.c src/ch7017/ch7017_reg.h src/ch7017/Makefile.am src/ch7xxx/ch7xxx.c src/ch7xxx/ch7xxx.h src/ch7xxx/ch7xxx_module.c src/ch7xxx/ch7xxx_reg.h src/ch7xxx/Makefile.am src/common.h src/exa_sf.g4a src/exa_sf_mask.g4a src/exa_sf_mask_prog.h src/exa_sf_prog.h src/exa_wm_maskca.g4a src/exa_wm_maskca_prog.h src/exa_wm_maskca_srcalpha.g4a src/exa_wm_maskca_srcalpha_prog.h src/exa_wm_masknoca.g4a src/exa_wm_masknoca_prog.h src/exa_wm_nomask.g4a src/exa_wm_nomask_prog.h src/fix.5c src/.gitignore src/i2c_vid.h src/i810_dri.c src/i810_driver.c src/i810.h src/i810_reg.h src/i810_video.c src/i810_wmark.c src/i830_3d.c src/i830_accel.c src/i830_bios.c src/i830_bios.h src/i830_crt.c src/i830_cursor.c src/i830_debug.c src/i830_debug.h src/i830_dga.c src/i830_display.c src/i830_display.h src/i830_dri.c src/i830_driver.c src/i830_dvo.c src/i830_exa.c src/i830.h src/i830_i2c.c src/i830_lvds.c src/i830_memory.c src/i830_modes.c src/i830_randr.c src/i830_reg.h src/i830_render.c src/i830_rotate.c src/i830_sdvo.c src/i830_sdvo.h src/i830_sdvo_regs.h src/i830_tv.c src/i830_video.c src/i830_video.h src/i830_xaa.c src/i915_3d.c src/i915_3d.h src/i915_reg.h src/i915_render.c src/i915_video.c src/i965_render.c src/i965_video.c src/ivch/ivch.c src/ivch/ivch_module.c src/ivch/ivch_reg.h src/ivch/Makefile.am src/local_xf86Rename.h src/Makefile.am src/reg_dumper/.gitignore src/reg_dumper/main.c src/reg_dumper/Makefile.am src/reg_dumper/reg_dumper.h src/reg_dumper/xprintf.c src/sil164/Makefile.am src/sil164/sil164.c src/sil164/sil164.h src/sil164/sil164_module.c src/sil164/sil164_reg.h src/tv.5c src/xvmc/.cvsignore src/xvmc/.gitignore src/xvmc/I810XvMC.c TODO

Eric Anholt anholt at kemper.freedesktop.org
Mon Mar 5 08:18:25 EET 2007


 .gitignore                        |    2 
 TODO                              |    3 
 configure.ac                      |   71 
 man/.cvsignore                    |    2 
 man/i810.man                      |  241 
 man/intel.man                     |  179 
 src/Makefile.am                   |  140 
 src/bios_reader/.gitignore        |    2 
 src/bios_reader/Makefile.am       |   13 
 src/bios_reader/bios_dumper.c     |   98 
 src/bios_reader/bios_reader.c     |  163 
 src/brw_structs.h                 |    2 
 src/ch7017/Makefile.am            |   15 
 src/ch7017/ch7017.c               |  302 +
 src/ch7017/ch7017_module.c        |   36 
 src/ch7017/ch7017_reg.h           |  150 
 src/ch7xxx/Makefile.am            |   16 
 src/ch7xxx/ch7xxx.c               |  314 +
 src/ch7xxx/ch7xxx.h               |   31 
 src/ch7xxx/ch7xxx_module.c        |   35 
 src/ch7xxx/ch7xxx_reg.h           |   80 
 src/common.h                      |   62 
 src/exa_sf.g4a                    |   17 
 src/exa_sf_mask.g4a               |   53 
 src/exa_sf_mask_prog.h            |   25 
 src/exa_sf_prog.h                 |   17 
 src/exa_wm_maskca.g4a             |  202 
 src/exa_wm_maskca_prog.h          |   95 
 src/exa_wm_maskca_srcalpha.g4a    |  202 
 src/exa_wm_maskca_srcalpha_prog.h |   95 
 src/exa_wm_masknoca.g4a           |  202 
 src/exa_wm_masknoca_prog.h        |   95 
 src/exa_wm_nomask.g4a             |  143 
 src/exa_wm_nomask_prog.h          |   70 
 src/fix.5c                        |   14 
 src/i2c_vid.h                     |   16 
 src/i810.h                        |    5 
 src/i810_dri.c                    |   22 
 src/i810_driver.c                 |   73 
 src/i810_reg.h                    |  993 +++
 src/i810_video.c                  |    4 
 src/i810_wmark.c                  |   17 
 src/i830.h                        |  598 +-
 src/i830_3d.c                     |   10 
 src/i830_accel.c                  |  702 --
 src/i830_bios.c                   |  243 
 src/i830_bios.h                   |  116 
 src/i830_crt.c                    |  375 +
 src/i830_cursor.c                 |  655 +-
 src/i830_debug.c                  |  814 +++
 src/i830_debug.h                  |   34 
 src/i830_dga.c                    |  442 -
 src/i830_display.c                | 1436 +++++
 src/i830_display.h                |   45 
 src/i830_dri.c                    |  191 
 src/i830_driver.c                 | 9570 +++++++-------------------------------
 src/i830_dvo.c                    |  322 +
 src/i830_exa.c                    |  529 ++
 src/i830_i2c.c                    |  381 +
 src/i830_lvds.c                   |  533 ++
 src/i830_memory.c                 | 3136 +++++-------
 src/i830_modes.c                  |  823 ---
 src/i830_randr.c                  |  355 -
 src/i830_reg.h                    |  117 
 src/i830_render.c                 |  603 ++
 src/i830_rotate.c                 | 1246 ----
 src/i830_sdvo.c                   | 1238 ++++
 src/i830_sdvo.h                   |   35 
 src/i830_sdvo_regs.h              |  317 +
 src/i830_tv.c                     | 1472 +++++
 src/i830_video.c                  | 1532 +-----
 src/i830_video.h                  |   31 
 src/i830_xaa.c                    |  874 +++
 src/i915_3d.c                     |   38 
 src/i915_3d.h                     |   27 
 src/i915_reg.h                    |   12 
 src/i915_render.c                 |  481 +
 src/i915_video.c                  |  109 
 src/i965_render.c                 | 1118 ++++
 src/i965_video.c                  |  865 +++
 src/ivch/Makefile.am              |   15 
 src/ivch/ivch.c                   |  234 
 src/ivch/ivch_module.c            |   64 
 src/ivch/ivch_reg.h               |   97 
 src/local_xf86Rename.h            |   23 
 src/reg_dumper/.gitignore         |    1 
 src/reg_dumper/Makefile.am        |   12 
 src/reg_dumper/main.c             |  105 
 src/reg_dumper/reg_dumper.h       |   89 
 src/reg_dumper/xprintf.c          |   60 
 src/sil164/Makefile.am            |   16 
 src/sil164/sil164.c               |  245 
 src/sil164/sil164.h               |   31 
 src/sil164/sil164_module.c        |   38 
 src/sil164/sil164_reg.h           |   74 
 src/tv.5c                         |  128 
 src/xvmc/I810XvMC.c               |  325 -
 97 files changed, 21793 insertions(+), 15506 deletions(-)

New commits:
diff-tree 015027034e970f1e3bb6ab239f7e0119235e404f (from parents)
Merge: 9a5106401a65c90df32cb71987fca7126dc22e81 bc20b54c34088356a277beaebcc90bb4a7063e19
Author: Eric Anholt <eric at anholt.net>
Date:   Sun Mar 4 21:49:00 2007 -0800

    Merge branch 'modesetting'
    
    Conflicts:
    
    	configure.ac
    	src/i830_driver.c
    	src/i830_modes.c
    	src/i830_video.c

diff --cc src/i830_driver.c
index f7c700a,d8924cf..ac4e38c
@@@ -7113,14 -2001,25 +2001,25 @@@
  {
     I830Ptr pI830 = I830PTR(pScrn);
     CARD32 ctx_addr;
+ #ifdef XF86DRI
+    drmI830Sarea *sarea;
+ #endif
  
 -   if (pI830->noAccel)
 +   if (pI830->noAccel || !I830IsPrimary(pScrn))
        return;
  
-    ctx_addr = pI830->ContextMem.Start;
-    /* Align to a 2k boundry */
-    ctx_addr = ((ctx_addr + 2048 - 1) / 2048) * 2048;
+ #ifdef XF86DRI
+    if (pI830->directRenderingEnabled) {
+       sarea = DRIGetSAREAPrivate(pScrn->pScreen);
+ 
+       /* Mark that the X Server was the last holder of the context */
+       if (sarea)
+ 	 sarea->ctxOwner = DRIGetContext(pScrn->pScreen);
+    }
+ #endif
  
+    ctx_addr = pI830->logical_context->offset;
+    assert((pI830->logical_context->offset & 2047) == 0);
     {
        BEGIN_LP_RING(2);
        OUT_RING(MI_SET_CONTEXT);
diff --cc src/i830_video.c
index 1a1b968,e580dab..d2f9724
@@@ -933,18 -944,23 +944,26 @@@
  	 return BadValue;
        pPriv->brightness = value;
        overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff);
-       ErrorF("BRIGHTNESS\n");
 +      if (*pI830->overlayOn)
 +         OVERLAY_UPDATE;
+       OVERLAY_DEBUG("BRIGHTNESS\n");
+       OVERLAY_UPDATE;
     } else if (attribute == xvContrast) {
        if ((value < 0) || (value > 255))
  	 return BadValue;
        pPriv->contrast = value;
        overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff);
-       ErrorF("CONTRAST\n");
+       OVERLAY_DEBUG("CONTRAST\n");
 -      OVERLAY_UPDATE;
 +      if (*pI830->overlayOn)
 +         OVERLAY_UPDATE;
-    } else if (pI830->Clone && attribute == xvPipe) {
+    } else if (attribute == xvSaturation) {
+       if ((value < 0) || (value > 1023))
+ 	 return BadValue;
+       pPriv->saturation = value;
+       overlay->OCLRC1 = pPriv->saturation;
+       overlay->OCMD &= ~OVERLAY_ENABLE;
+       OVERLAY_UPDATE;
+    } else if (attribute == xvPipe) {
        if ((value < 0) || (value > 1))
           return BadValue;
        pPriv->pipe = value;
@@@ -956,9 -972,8 +975,9 @@@
           overlay->OCONFIG |= OVERLAY_PIPE_A;
        else 
           overlay->OCONFIG |= OVERLAY_PIPE_B;
-       ErrorF("PIPE CHANGE\n");
+       OVERLAY_DEBUG("PIPE CHANGE\n");
 -      OVERLAY_UPDATE;
 +      if (*pI830->overlayOn)
 +         OVERLAY_UPDATE;
     } else if (attribute == xvGamma0 && (IS_I9XX(pI830))) {
        pPriv->gamma0 = value; 
     } else if (attribute == xvGamma1 && (IS_I9XX(pI830))) {
@@@ -984,9 -999,8 +1003,9 @@@
  	 overlay->DCLRKV = pPriv->colorKey;
  	 break;
        }
-       ErrorF("COLORKEY\n");
+       OVERLAY_DEBUG("COLORKEY\n");
 -      OVERLAY_UPDATE;
 +      if (*pI830->overlayOn)
 +         OVERLAY_UPDATE;
        REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
     } else if(attribute == xvDoubleBuffer) {
        if ((value < 0) || (value > 1))
@@@ -1004,8 -1018,13 +1023,8 @@@
          attribute == xvGamma3 ||
          attribute == xvGamma4 ||
          attribute == xvGamma5) && (IS_I9XX(pI830))) {
-         ErrorF("GAMMA\n");
 -	CARD32 r = overlay->OCMD & OVERLAY_ENABLE;
+         OVERLAY_DEBUG("GAMMA\n");
 -        overlay->OCMD &= ~OVERLAY_ENABLE;
 -        OVERLAY_UPDATE;
  	I830UpdateGamma(pScrn);
 -        overlay->OCMD |= r;
 -        OVERLAY_UPDATE;
     }
  
     return Success;
diff-tree bc20b54c34088356a277beaebcc90bb4a7063e19 (from b27fa2c257ccc49c6f29a20a3e672ebaaf58e7aa)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Sun Mar 4 19:35:44 2007 -0800

    Support new CRTC/Output prepare/commit hooks.
    
    New hooks replace explicit invocation of DPMS functions to manage mode
    setting sequencing.

diff --git a/src/i830_crt.c b/src/i830_crt.c
index 7706165..fbb4adc 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -341,7 +341,9 @@ static const xf86OutputFuncsRec i830_crt
     .restore = i830_crt_restore,
     .mode_valid = i830_crt_mode_valid,
     .mode_fixup = i830_crt_mode_fixup,
+    .prepare = i830_output_prepare,
     .mode_set = i830_crt_mode_set,
+    .commit = i830_output_commit,
     .detect = i830_crt_detect,
     .get_modes = i830_ddc_get_modes,
     .destroy = i830_crt_destroy
diff --git a/src/i830_display.c b/src/i830_display.c
index 67744d5..d0b21a9 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -613,6 +613,30 @@ i830_crtc_unlock (xf86CrtcPtr crtc)
 #endif
 }
 
+static void
+i830_crtc_prepare (xf86CrtcPtr crtc)
+{
+    crtc->funcs->dpms (crtc, DPMSModeOff);
+}
+
+static void
+i830_crtc_commit (xf86CrtcPtr crtc)
+{
+    crtc->funcs->dpms (crtc, DPMSModeOn);
+}
+
+void
+i830_output_prepare (xf86OutputPtr output)
+{
+    output->funcs->dpms (output, DPMSModeOff);
+}
+
+void
+i830_output_commit (xf86OutputPtr output)
+{
+    output->funcs->dpms (output, DPMSModeOn);
+}
+
 static Bool
 i830_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode,
 		     DisplayModePtr adjusted_mode)
@@ -1377,7 +1401,9 @@ static const xf86CrtcFuncsRec i830_crtc_
     .lock = i830_crtc_lock,
     .unlock = i830_crtc_unlock,
     .mode_fixup = i830_crtc_mode_fixup,
+    .prepare = i830_crtc_prepare,
     .mode_set = i830_crtc_mode_set,
+    .commit = i830_crtc_commit,
     .gamma_set = i830_crtc_gamma_set,
     .shadow_create = i830_crtc_shadow_create,
     .shadow_allocate = i830_crtc_shadow_allocate,
diff --git a/src/i830_display.h b/src/i830_display.h
index dbd1ea8..31ab615 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -40,3 +40,6 @@ void i830ReleaseLoadDetectPipe(xf86Outpu
 void i830_crtc_init(ScrnInfoPtr pScrn, int pipe);
 void i830_crtc_load_lut(xf86CrtcPtr crtc);
 DisplayModePtr i830_crtc_mode_get(ScrnInfoPtr pScrn, xf86CrtcPtr crtc);
+void i830_output_prepare (xf86OutputPtr output);
+void i830_output_commit (xf86OutputPtr output);
+
diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index d938f46..629e9c7 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -31,6 +31,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #include "xf86.h"
 #include "i830.h"
+#include "i830_display.h"
 #include "i810_reg.h"
 
 #include "sil164/sil164.h"
@@ -226,7 +227,9 @@ static const xf86OutputFuncsRec i830_dvo
     .restore = i830_dvo_restore,
     .mode_valid = i830_dvo_mode_valid,
     .mode_fixup = i830_dvo_mode_fixup,
+    .prepare = i830_output_prepare,
     .mode_set = i830_dvo_mode_set,
+    .commit = i830_output_commit,
     .detect = i830_dvo_detect,
     .get_modes = i830_ddc_get_modes,
     .destroy = i830_dvo_destroy
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index 642dd8a..f554b38 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -392,7 +392,9 @@ static const xf86OutputFuncsRec i830_lvd
     .restore = i830_lvds_restore,
     .mode_valid = i830_lvds_mode_valid,
     .mode_fixup = i830_lvds_mode_fixup,
+    .prepare = i830_output_prepare,
     .mode_set = i830_lvds_mode_set,
+    .commit = i830_output_commit,
     .detect = i830_lvds_detect,
     .get_modes = i830_lvds_get_modes,
 #ifdef RANDR_12_INTERFACE
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 46a35f1..b7cf843 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -1060,7 +1060,9 @@ static const xf86OutputFuncsRec i830_sdv
     .restore = i830_sdvo_restore,
     .mode_valid = i830_sdvo_mode_valid,
     .mode_fixup = i830_sdvo_mode_fixup,
+    .prepare = i830_output_prepare,
     .mode_set = i830_sdvo_mode_set,
+    .commit = i830_output_commit,
     .detect = i830_sdvo_detect,
     .get_modes = i830_sdvo_get_modes,
     .destroy = i830_sdvo_destroy
diff --git a/src/i830_tv.c b/src/i830_tv.c
index 95612e4..d7f4f56 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -1406,7 +1406,9 @@ static const xf86OutputFuncsRec i830_tv_
     .restore = i830_tv_restore,
     .mode_valid = i830_tv_mode_valid,
     .mode_fixup = i830_tv_mode_fixup,
+    .prepare = i830_output_prepare,
     .mode_set = i830_tv_mode_set,
+    .commit = i830_output_commit,
     .detect = i830_tv_detect,
     .get_modes = i830_tv_get_modes,
     .destroy = i830_tv_destroy
diff-tree b27fa2c257ccc49c6f29a20a3e672ebaaf58e7aa (from fc7d43c2b6b98be597152fbd88024273edd931d0)
Author: Eric Anholt <eric at anholt.net>
Date:   Sun Mar 4 17:15:45 2007 -0800

    Fix a crash with XAA and DRI disabled after the allocation rework.

diff --git a/src/i830_xaa.c b/src/i830_xaa.c
index f095138..9ecf706 100644
--- a/src/i830_xaa.c
+++ b/src/i830_xaa.c
@@ -279,12 +279,14 @@ CheckTiling(ScrnInfoPtr pScrn)
    if (IS_I965G(pI830)) {
       if (pI830->bufferOffset == pScrn->fbOffset && pI830->front_tiled == FENCE_XMAJOR)
          tiled = 1;
-      if (pI830->bufferOffset == pI830->back_buffer->offset &&
+      if (pI830->back_buffer != NULL &&
+	  pI830->bufferOffset == pI830->back_buffer->offset &&
 	  pI830->back_tiled == FENCE_XMAJOR) {
          tiled = 1;
       }
       /* not really supported as it's always YMajor tiled */
-      if (pI830->bufferOffset == pI830->depth_buffer->offset &&
+      if (pI830->depth_buffer != NULL &&
+	  pI830->bufferOffset == pI830->depth_buffer->offset &&
 	  pI830->depth_tiled == FENCE_XMAJOR) {
          tiled = 1;
       }
diff-tree fc7d43c2b6b98be597152fbd88024273edd931d0 (from b7b6063e62927dd135e118c433f48b4d0b5fe246)
Author: Eric Anholt <eric at anholt.net>
Date:   Sun Mar 4 17:14:30 2007 -0800

    Use -f for ln of server source. Otherwise, changing paths didn't take effect.

diff --git a/configure.ac b/configure.ac
index 775e87f..772b40b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -145,13 +145,13 @@ if test -d "$XSERVER_SOURCE"; then
 	if test -f src/modes/xf86Modes.h; then
 		:
 	else
-		ln -s $XSERVER_SOURCE/hw/xfree86/modes src/modes
+		ln -sf $XSERVER_SOURCE/hw/xfree86/modes src/modes
 	fi
 	
 	if test -f src/parser/xf86Parser.h; then
 		:
 	else
-		ln -s $XSERVER_SOURCE/hw/xfree86/parser src/parser
+		ln -sf $XSERVER_SOURCE/hw/xfree86/parser src/parser
 	fi
 fi
 AC_SUBST([XMODES_CFLAGS])
diff-tree b7b6063e62927dd135e118c433f48b4d0b5fe246 (from 6aeb855b9d4e03d458773240a9c0c9c1edd3e403)
Author: Eric Anholt <eric at anholt.net>
Date:   Sun Mar 4 15:53:50 2007 -0800

    Add a little BIOS dumper program.
    
    This isn't actually tested yet as libpciaccess doesn't do rom access on
    non-linux yet.

diff --git a/src/bios_reader/.gitignore b/src/bios_reader/.gitignore
index 3e32507..49312f2 100644
--- a/src/bios_reader/.gitignore
+++ b/src/bios_reader/.gitignore
@@ -1 +1,2 @@
+bios_dumper
 bios_reader
diff --git a/src/bios_reader/Makefile.am b/src/bios_reader/Makefile.am
index a5c81a6..bba969b 100644
--- a/src/bios_reader/Makefile.am
+++ b/src/bios_reader/Makefile.am
@@ -1,4 +1,13 @@
 AM_CFLAGS = @XORG_CFLAGS@ @XMODES_CFLAGS@
 
-noinst_PROGRAMS = bios_reader
+noinst_PROGRAMS = bios_reader  $(BIOS_DUMPER)
 
+if HAVE_PCIACCESS
+BIOS_DUMPER = bios_dumper
+
+bios_dumper_SOURCES = bios_dumper.c
+
+bios_dumper_CFLAGS = $(PCIACCESS_CFLAGS)
+bios_dumper_LDADD = $(PCIACCESS_LIBS)
+
+endif
diff --git a/src/bios_reader/bios_dumper.c b/src/bios_reader/bios_dumper.c
new file mode 100644
index 0000000..071419b
--- /dev/null
+++ b/src/bios_reader/bios_dumper.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <pciaccess.h>
+#include <err.h>
+
+static void usage(void)
+{
+    fprintf(stderr, "usage: bios_dumper <filename>\n");
+    exit(1);
+}
+
+int main(int argc, char **argv)
+{
+    struct pci_device *dev;
+    void *bios;
+    int err, fd;
+
+    if (argc != 2)
+	usage();
+
+    err = pci_system_init();
+    if (err != 0) {
+	fprintf(stderr, "Couldn't initialize PCI system: %s\n", strerror(err));
+	exit(1);
+    }
+
+    /* Grab the graphics card */
+    dev = pci_device_find_by_slot(0, 0, 2, 0);
+    if (dev == NULL)
+	errx(1, "Couldn't find graphics card");
+
+    if (dev->vendor_id != 0x8086)
+	errx(1, "Graphics card is non-intel");
+
+    err = pci_device_probe(dev);
+    if (err != 0) {
+	fprintf(stderr, "Couldn't probe graphics card: %s\n", strerror(err));
+	exit(1);
+    }
+
+    bios = malloc(dev->rom_size);
+    if (bios == NULL)
+	errx(1, "Couldn't allocate memory for BIOS data\n");
+
+    err = pci_device_read_rom(dev, bios);
+    if (err != 0) {
+	fprintf(stderr, "Couldn't read graphics card ROM: %s\n",
+		strerror(err));
+	exit(1);
+    }
+
+    fd = open(argv[1], O_RDWR | O_CREAT | O_TRUNC);
+    if (fd < 0) {
+	fprintf(stderr, "Couldn't open output: %s\n", strerror(errno));
+	exit(1);
+    }
+
+    if (write(fd, bios, dev->rom_size) < dev->rom_size) {
+	fprintf(stderr, "Couldn't write BIOS data: %s\n", strerror(errno));
+	exit(1);
+    }
+
+    close(fd);
+    pci_system_cleanup();
+
+    return 0;
+}
diff-tree 6aeb855b9d4e03d458773240a9c0c9c1edd3e403 (from 7d08f720a95499e8d00dcd7174f06731de420017)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Sun Mar 4 17:11:40 2007 -0800

    Shadow pixmaps use fixed offset of 0.
    
    Shadow pixmap contents are copied from the main frame buffer and contain
    only the bits displayed by the crtc, not the whole frame buffer. The crtc
    origin is always interpreted by the shadow copying code, the frame buffer
    itself doesn't move.

diff --git a/src/i830_display.c b/src/i830_display.c
index e9666de..67744d5 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -359,10 +359,11 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x,
     I830Ptr pI830 = I830PTR(pScrn);
     I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
     int pipe = intel_crtc->pipe;
-    unsigned long Start;
+    unsigned long Start, Offset;
     int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE);
     int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
 
+    Offset = ((y * pScrn->displayWidth + x) * pI830->cpp);
     if (pI830->front_buffer == NULL) {
 	/* During startup we may be called as part of monitor detection while
 	 * there is no memory allocation done, so just supply a dummy base
@@ -370,7 +371,9 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x,
 	 */
 	Start = 0;
     } else if (crtc->rotatedData != NULL) {
+	/* offset is done by shadow painting code, not here */
 	Start = (char *)crtc->rotatedData - (char *)pI830->FbBase;
+	Offset = 0;
     } else if (I830IsPrimary(pScrn)) {
 	Start = pI830->front_buffer->offset;
     } else {
@@ -379,12 +382,12 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x,
     }
 
     if (IS_I965G(pI830)) {
-        OUTREG(dspbase, ((y * pScrn->displayWidth + x) * pI830->cpp));
+        OUTREG(dspbase, Offset);
 	(void) INREG(dspbase);
         OUTREG(dspsurf, Start);
 	(void) INREG(dspsurf);
     } else {
-	OUTREG(dspbase, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
+	OUTREG(dspbase, Start + Offset);
 	(void) INREG(dspbase);
     }
 }
diff-tree 7d08f720a95499e8d00dcd7174f06731de420017 (from parents)
Merge: dd24d2a082b41abc466391c37a9b3d066586dc55 435d35558d8135a2c1724dfd813fb4a9a4e14178
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Sat Mar 3 23:13:03 2007 -0800

    Merge branch 'modesetting-origin' into modesetting

diff-tree 435d35558d8135a2c1724dfd813fb4a9a4e14178 (from fd52d635603b7093c5a2b7fa9c987cf59f9be27c)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Sat Mar 3 22:46:31 2007 -0800

    Update for Aaron's xserver changes.
    
    Add xf86CrtcConfigFuncs to xf86CrtcConfigInit
    Add canGrow option to xf86InitialConfiguration

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 5ba96a5..3c10ffc 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -778,6 +778,18 @@ I830IsPrimary(ScrnInfoPtr pScrn)
    return TRUE;
 }
 
+static Bool
+i830_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
+{
+    scrn->virtualX = width;
+    scrn->virtualY = height;
+    return TRUE;
+}
+
+static const xf86CrtcConfigFuncsRec i830_xf86crtc_config_funcs = {
+    i830_xf86crtc_resize
+};
+
 #define HOTKEY_BIOS_SWITCH	0
 #define HOTKEY_DRIVER_NOTIFY	1
 
@@ -1091,7 +1103,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 	      (unsigned long)pI830->MMIOAddr);
 
    /* Allocate an xf86CrtcConfig */
-   xf86CrtcConfigInit (pScrn);
+   xf86CrtcConfigInit (pScrn, &i830_xf86crtc_config_funcs);
    xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
 
    /* See i830_exa.c comments for why we limit the framebuffer size like this.
@@ -1282,7 +1294,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       output->status = (*output->funcs->detect) (output);
    }
 
-   if (!xf86InitialConfiguration (pScrn))
+   if (!xf86InitialConfiguration (pScrn, FALSE))
    {
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
       RestoreHWState(pScrn);
diff-tree fd52d635603b7093c5a2b7fa9c987cf59f9be27c (from ca0fa875e8bb5cb778d4db7d8053ec0a5ae34ef4)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Mar 2 13:44:57 2007 -0800

    Add a WIP UploadToScreen implementation.  This almost displays right.

diff --git a/src/common.h b/src/common.h
index 8f42bde..6e8ddbd 100644
--- a/src/common.h
+++ b/src/common.h
@@ -131,6 +131,43 @@ extern void I830DPRINTF_stub(const char 
    outring &= ringmask;							\
 } while (0)
 
+static inline void memset_volatile(volatile void *b, int c, size_t len)
+{
+    int i;
+    
+    for (i = 0; i < len; i++)
+	((volatile char *)b)[i] = c;
+}
+
+static inline void memcpy_volatile(volatile void *dst, const void *src,
+				   size_t len)
+{
+    int i;
+    
+    for (i = 0; i < len; i++)
+	((volatile char *)dst)[i] = ((volatile char *)src)[i];
+}
+
+/** Copies a given number of bytes to the ring */
+#define OUT_RING_COPY(n, ptr) do {					\
+    if (I810_DEBUG & DEBUG_VERBOSE_RING)				\
+	ErrorF("OUT_RING_DATA %d bytes\n", n);				\
+    memcpy_volatile(virt + outring, ptr, n);				\
+    outring += n;							\
+    ringused += n;							\
+    outring &= ringmask;						\
+} while (0)
+
+/** Pads the ring with a given number of zero bytes */
+#define OUT_RING_PAD(n) do {						\
+    if (I810_DEBUG & DEBUG_VERBOSE_RING)				\
+	ErrorF("OUT_RING_PAD %d bytes\n", n);				\
+    memset_volatile(virt + outring, 0, n);				\
+    outring += n;							\
+    ringused += n;							\
+    outring &= ringmask;						\
+} while (0)
+
 union intfloat {
 	float f;
 	unsigned int ui;
diff --git a/src/i810_reg.h b/src/i810_reg.h
index 6a9c11e..d63be02 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -1906,6 +1906,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define SRC_COPY_BLT_WRITE_ALPHA	(1<<21)
 #define SRC_COPY_BLT_WRITE_RGB		(1<<20)
 
+#define XY_PAT_BLT_IMMEDIATE		((2<<29)|(0x72<<22))
+
 #define XY_MONO_PAT_BLT_CMD		((0x2<<29)|(0x52<<22)|0x7)
 #define XY_MONO_PAT_VERT_SEED		((1<<10)|(1<<9)|(1<<8))
 #define XY_MONO_PAT_HORT_SEED		((1<<14)|(1<<13)|(1<<12))
diff --git a/src/i830_exa.c b/src/i830_exa.c
index 37fd284..bef8fae 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -297,6 +297,93 @@ i830_get_transformed_coordinates(int x, 
     }
 }
 
+/**
+ * Uploads data from system memory to the framebuffer using a series of
+ * 8x8 pattern blits.
+ */
+static Bool
+i830_upload_to_screen(PixmapPtr pDst, int x, int y, int w, int h, char *src,
+		      int src_pitch)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+    const int uts_width_max = 16, uts_height_max = 16;
+    int cpp = pDst->drawable.bitsPerPixel / 8;
+    int sub_x, sub_y;
+    CARD32 br13;
+    CARD32 offset;
+
+    if (w > uts_width_max || h > uts_height_max)
+	I830FALLBACK("too large for upload to screen (%d,%d)", w, h);
+
+    offset = exaGetPixmapOffset(pDst);
+
+    br13 = exaGetPixmapPitch(pDst);
+    br13 |= ((I830PatternROP[GXcopy] & 0xff) << 16);
+    switch (pDst->drawable.bitsPerPixel) {
+    case 16:
+	br13 |= 1 << 24;
+	break;
+    case 32:
+	br13 |= 3 << 24;
+	break;
+    }
+
+    for (sub_y = 0; sub_y < uts_height_max && sub_y < h; sub_y += 8) {
+	int sub_height;
+
+	if (sub_y + 8 > h)
+	    sub_height = h - sub_y;
+	else
+	    sub_height = 8;
+
+	for (sub_x = 0; sub_x < uts_width_max && sub_x < w; sub_x += 8) {
+	    int sub_width, line;
+	    char *src_line = src + sub_y * src_pitch + sub_x * cpp;
+
+	    if (sub_x + 8 > w)
+		sub_width = w - sub_x;
+	    else
+		sub_width = 8;
+
+	    BEGIN_LP_RING(6 + (cpp * 8 * 8 / 4));
+
+	    /* XXX We may need a pattern offset here for {x,y} % 8 != 0*/
+	    OUT_RING(XY_PAT_BLT_IMMEDIATE |
+		     XY_SRC_COPY_BLT_WRITE_ALPHA |
+		     XY_SRC_COPY_BLT_WRITE_RGB |
+		     (3 + cpp * 8 * 8 / 4));
+	    OUT_RING(br13);
+	    OUT_RING(((y + sub_y) << 16) | (x + sub_x));
+	    OUT_RING(((y + sub_y + sub_height) << 16) |
+		     (x + sub_x + sub_width));
+	    OUT_RING(offset);
+
+	    /* Write out the lines with valid data, followed by any needed
+	     * padding
+	     */
+	    for (line = 0; line < sub_height; line++) {
+		OUT_RING_COPY(sub_width * cpp, src_line);
+		src_line += src_pitch;
+		if (sub_width != 8)
+		    OUT_RING_PAD((8 - sub_width) * cpp);
+	    }
+	    /* Write out any full padding lines to follow */
+	    if (sub_height != 8)
+		OUT_RING_PAD(8 * cpp * (8 - sub_height));
+
+	    OUT_RING(MI_NOOP);
+	    ADVANCE_LP_RING();
+	}
+    }
+
+    exaMarkSync(pDst->drawable.pScreen);
+    /* exaWaitSync(pDst->drawable.pScreen); */
+
+    return TRUE;
+}
+
+
 /*
  * TODO:
  *   - Dual head?
@@ -421,6 +508,10 @@ I830EXAInit(ScreenPtr pScreen)
  	pI830->EXADriverPtr->DoneComposite = i830_done_composite;
     }
 
+    /* UploadToScreen/DownloadFromScreen */
+    if (0)
+	pI830->EXADriverPtr->UploadToScreen = i830_upload_to_screen;
+
     if(!exaDriverInit(pScreen, pI830->EXADriverPtr)) {
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		   "EXA initialization failed; trying older version\n");
diff-tree ca0fa875e8bb5cb778d4db7d8053ec0a5ae34ef4 (from 5a73624b9bcce0004e5b72c74667c9dd504b9c3e)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Mar 2 11:46:45 2007 -0800

    Move EXA offscreen memory back after framebuffer to avoid fallbacks.
    
    Without this, the EXA code decides that the framebuffer is not in video
    memory because it's not located between the start of video memory and the end
    of EXA allocator memory.  We should either have EXA let the driver decide if a
    pointer is in video memory, or add a new field for "end of video memory" (not
    just end of EXA offscreen allocation), but this fixes things for now.

diff --git a/src/i830_memory.c b/src/i830_memory.c
index b83078a..5cddf17 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -945,6 +945,21 @@ i830_allocate_2d_memory(ScrnInfoPtr pScr
 	i830_allocate_overlay(pScrn);
 #endif
 
+    if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) {
+	I830EntPtr pI830Ent = pI830->entityPrivate;
+	I830Ptr pI8302 = I830PTR(pI830Ent->pScrn_2);
+
+	pI830->front_buffer_2 =
+	    i830_allocate_framebuffer(pI830Ent->pScrn_2, pI8302,
+				      &pI830->FbMemBox2, TRUE, 0);
+	if (pI830->front_buffer_2 == NULL)
+	    return FALSE;
+    }
+    pI830->front_buffer =
+	i830_allocate_framebuffer(pScrn, pI830, &pI830->FbMemBox, FALSE, 0);
+    if (pI830->front_buffer == NULL)
+	return FALSE;
+
 #ifdef I830_USE_EXA
     if (pI830->useEXA) {
 	if (pI830->exa_offscreen == NULL) {
@@ -981,21 +996,6 @@ i830_allocate_2d_memory(ScrnInfoPtr pScr
     }
 #endif /* I830_USE_EXA */
 
-    if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) {
-	I830EntPtr pI830Ent = pI830->entityPrivate;
-	I830Ptr pI8302 = I830PTR(pI830Ent->pScrn_2);
-
-	pI830->front_buffer_2 =
-	    i830_allocate_framebuffer(pI830Ent->pScrn_2, pI8302,
-				      &pI830->FbMemBox2, TRUE, 0);
-	if (pI830->front_buffer_2 == NULL)
-	    return FALSE;
-    }
-    pI830->front_buffer =
-	i830_allocate_framebuffer(pScrn, pI830, &pI830->FbMemBox, FALSE, 0);
-    if (pI830->front_buffer == NULL)
-	return FALSE;
-
     if (!pI830->noAccel && !pI830->useEXA) {
 	pI830->xaa_scratch =
 	    i830_allocate_memory(pScrn, "xaa scratch", MAX_SCRATCH_BUFFER_SIZE,
diff-tree 5a73624b9bcce0004e5b72c74667c9dd504b9c3e (from d5df52be59a7dd950e73336ce5698e73480108b0)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Mar 2 11:03:16 2007 -0800

    Fix a crash when an ARGB cursor allocation had failed.

diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index 0cfd229..8578511 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -372,7 +372,7 @@ static Bool I830UseHWCursorARGB (ScreenP
    for (i = 0; i < xf86_config->num_crtc; i++) {
       I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private;
 
-      if (!intel_crtc->cursor_mem_argb->offset)
+      if (intel_crtc->cursor_mem_argb == NULL)
 	 return FALSE;
    }
 
diff-tree d5df52be59a7dd950e73336ce5698e73480108b0 (from 1f5d1666c8386ca4597c6f2c1ec239f9d821da4c)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Mar 1 08:35:13 2007 -0800

    Actually add the files for reg_dumper.

diff --git a/src/reg_dumper/.gitignore b/src/reg_dumper/.gitignore
new file mode 100644
index 0000000..1b38d5c
--- /dev/null
+++ b/src/reg_dumper/.gitignore
@@ -0,0 +1 @@
+intel_reg_dumper
diff --git a/src/reg_dumper/Makefile.am b/src/reg_dumper/Makefile.am
new file mode 100644
index 0000000..aee26d0
--- /dev/null
+++ b/src/reg_dumper/Makefile.am
@@ -0,0 +1,12 @@
+noinst_PROGRAMS = intel_reg_dumper
+
+intel_reg_dumper_SOURCES = \
+	main.c \
+	reg_dumper.h \
+	xprintf.c \
+	../i830_debug.c
+
+intel_reg_dumper_LDADD = $(PCIACCESS_LIBS)
+
+intel_reg_dumper_CFLAGS = $(PCIACCESS_CFLAGS) $(WARN_CFLAGS) \
+	-I$(srcdir)/.. -DREG_DUMPER
diff --git a/src/reg_dumper/main.c b/src/reg_dumper/main.c
new file mode 100644
index 0000000..50c7923
--- /dev/null
+++ b/src/reg_dumper/main.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <pciaccess.h>
+#include <err.h>
+
+#include "reg_dumper.h"
+
+int main(int argc, char **argv)
+{
+    struct pci_device *dev;
+    I830Rec i830;
+    ScrnInfoRec scrn;
+    int err, mmio_bar;
+
+    err = pci_system_init();
+    if (err != 0) {
+	fprintf(stderr, "Couldn't initialize PCI system: %s\n", strerror(err));
+	exit(1);
+    }
+
+    /* Grab the graphics card */
+    dev = pci_device_find_by_slot(0, 0, 2, 0);
+    if (dev == NULL)
+	errx(1, "Couldn't find graphics card");
+
+    if (dev->vendor_id != 0x8086)
+	errx(1, "Graphics card is non-intel");
+
+    err = pci_device_probe(dev);
+    if (err != 0) {
+	fprintf(stderr, "Couldn't probe graphics card: %s\n", strerror(err));
+	exit(1);
+    }
+
+    i830.PciInfo = &i830.pci_info_rec;
+    i830.PciInfo->chipType = dev->device_id;
+
+    i830.pci_dev = dev;
+
+    mmio_bar = IS_I9XX((&i830)) ? 0 : 1;
+
+    err = pci_device_map_region(dev, mmio_bar, 1);
+    if (err != 0) {
+	fprintf(stderr, "Couldn't map MMIO region: %s\n", strerror(err));
+	exit(1);
+    }
+    i830.mmio = i830.pci_dev->regions[mmio_bar].memory;
+
+    scrn.scrnIndex = 0;
+    scrn.pI830 = &i830;
+
+    i830DumpRegs(&scrn);
+
+    return 0;
+}
+
+void xf86DrvMsg(int scrnIndex, int severity, const char *format, ...)
+{
+    va_list va;
+
+    switch (severity) {
+    case X_INFO:
+	printf("(II): ");
+	break;
+    case X_WARNING:
+	printf("(WW): ");
+	break;
+    case X_ERROR:
+	printf("(EE): ");
+	break;
+    }
+
+    va_start(va, format);
+    vprintf(format, va);
+    va_end(va);
+}
diff --git a/src/reg_dumper/reg_dumper.h b/src/reg_dumper/reg_dumper.h
new file mode 100644
index 0000000..a52d662
--- /dev/null
+++ b/src/reg_dumper/reg_dumper.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
+#include <sys/types.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "common.h"
+
+/** @file
+ * This file defines the typedefs and stub structures necessary for us to
+ * use i830_debug.c mostly unmodified.
+ */
+
+typedef uint32_t CARD32;
+typedef char Bool;
+
+#define FALSE 0
+#define TRUE 1
+
+#define X_INFO 0
+#define X_WARNING 1
+#define X_ERROR 2
+
+struct pci_info_rec {
+    uint16_t chipType;
+};
+
+typedef struct _i830 {
+    /* Fields in common with the real pI830 */
+    struct pci_info_rec *PciInfo;
+
+    /* Fields used for setting up reg_dumper */
+    struct pci_device *pci_dev;
+    struct pci_info_rec pci_info_rec;
+    volatile unsigned char *mmio;
+} I830Rec, *I830Ptr;
+
+typedef struct _scrn {
+    /* Fields in common with the real pScrn */
+    int scrnIndex;
+
+    /* Fields used for setting up reg_dumper */
+    I830Ptr pI830;
+} ScrnInfoRec, *ScrnInfoPtr;
+
+#define I830PTR(pScrn) (pScrn->pI830)
+
+#define INREG8(reg) (*(volatile uint8_t *)((pI830)->mmio + (reg)))
+#define INREG16(reg) (*(volatile uint16_t *)((pI830)->mmio + (reg)))
+#define INREG(reg) (*(volatile uint32_t *)((pI830)->mmio + (reg)))
+#define OUTREG8(reg, val) \
+	*(volatile uint8_t *)((pI830)->mmio + (reg)) = (val)
+#define OUTREG16(reg, val) \
+	*(volatile uint16_t *)((pI830)->mmio + (reg)) = (val)
+#define OUTREG(reg, val) \
+	*(volatile uint32_t *)((pI830)->mmio + (reg)) = (val)
+
+#define xalloc malloc
+#define xfree free
+#define ErrorF printf
+
+char *XNFprintf(const char *format, ...);
+void xf86DrvMsg(int scrnIndex, int severity, const char *format, ...);
+void i830DumpRegs(ScrnInfoPtr pScrn);
diff --git a/src/reg_dumper/xprintf.c b/src/reg_dumper/xprintf.c
new file mode 100644
index 0000000..125ae87
--- /dev/null
+++ b/src/reg_dumper/xprintf.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2004 Alexander Gottwald
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+
+#include <string.h>
+#include <stdarg.h>
+#include "reg_dumper.h"
+
+static char *
+XNFvprintf(const char *format, va_list va)
+{
+    char *ret;
+    int size;
+    va_list va2;
+
+    va_copy(va2, va);
+    size = vsnprintf(NULL, 0, format, va2);
+    va_end(va2);
+
+    ret = (char *)malloc(size + 1);
+    if (ret == NULL)
+        return NULL;
+
+    vsnprintf(ret, size + 1, format, va);
+    ret[size] = 0;
+    return ret;
+}
+
+char *
+XNFprintf(const char *format, ...)
+{
+    char *ret;
+    va_list va;
+    va_start(va, format);
+    ret = XNFvprintf(format, va);
+    va_end(va);
+    return ret;
+}
diff-tree 1f5d1666c8386ca4597c6f2c1ec239f9d821da4c (from cd1d4b398ec91d551bdaaa26c769e5e6a9442df1)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Feb 28 16:27:55 2007 -0800

    Add a non-installed command line tool using libpciaccess to dump registers.
    
    This reuses the i830_debug.c code, so we can run that from the console or from
    the BIOS-based X server to debug some remaining issues.

diff --git a/configure.ac b/configure.ac
index 395e9d4..775e87f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -87,6 +87,9 @@ XORG_DRIVER_CHECK_EXT(DPMSExtension, xex
 PKG_CHECK_MODULES(XORG, [xorg-server xproto xvmc fontsproto $REQUIRED_MODULES])
 sdkdir=$(pkg-config --variable=sdkdir xorg-server)
 
+PKG_CHECK_MODULES([PCIACCESS], [pciaccess >= 0.5.0], have_pciaccess=yes, have_pciaccess=no)
+AM_CONDITIONAL(HAVE_PCIACCESS, test "x$have_pciaccess" = xyes)
+
 # Checks for libraries.
 
 # Checks for header files.
@@ -200,6 +203,7 @@ AC_OUTPUT([
 	src/ch7017/Makefile
 	src/ch7xxx/Makefile
 	src/ivch/Makefile
+	src/reg_dumper/Makefile
 	src/sil164/Makefile
 	man/Makefile
 ])
diff --git a/src/Makefile.am b/src/Makefile.am
index adb4c42..c65c1e7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -18,7 +18,11 @@
 #  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 #  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
-SUBDIRS = xvmc bios_reader ch7017 ch7xxx ivch sil164
+if HAVE_PCIACCESS
+REGDUMPER = reg_dumper
+endif
+
+SUBDIRS = xvmc bios_reader ch7017 ch7xxx ivch sil164 $(REGDUMPER)
 
 # this is obnoxious:
 # -module lets us name the module exactly how we want
diff --git a/src/common.h b/src/common.h
index 91e31b5..8f42bde 100644
--- a/src/common.h
+++ b/src/common.h
@@ -72,6 +72,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define DELAY(x) do {;} while (0)
 #endif
 
+#ifndef REG_DUMPER
 /* I830 hooks for the I810 driver setup/probe. */
 extern const OptionInfoRec *I830AvailableOptions(int chipid, int busid);
 extern void I830InitpScrn(ScrnInfoPtr pScrn);
@@ -242,6 +243,7 @@ extern int I810_DEBUG;
 #define DEBUG_ALWAYS_SYNC    0x80
 #define DEBUG_VERBOSE_DRI    0x100
 #define DEBUG_VERBOSE_BIOS   0x200
+#endif /* !REG_DUMPER */
 
 /* Size of the mmio region.
  */
diff --git a/src/i830_debug.c b/src/i830_debug.c
index de36a04..dccaa7e 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -25,6 +25,11 @@
  *
  */
 
+#ifdef REG_DUMPER
+#include "reg_dumper/reg_dumper.h"
+
+#else
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
@@ -34,6 +39,10 @@
 #include "i830_debug.h"
 #include <strings.h>
 
+#endif
+
+#include "i810_reg.h"
+
 #define DEBUGSTRING(func) static char *func(I830Ptr pI830, int reg, CARD32 val)
 
 DEBUGSTRING(i830_debug_xyminus1)
@@ -410,6 +419,7 @@ static struct i830SnapshotRec {
 #undef DEFINEREG
 #define NUM_I830_SNAPSHOTREGS (sizeof(i830_snapshot) / sizeof(i830_snapshot[0]))
 
+#ifndef REG_DUMPER
 void i830TakeRegSnapshot(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
@@ -454,6 +464,7 @@ void i830CompareRegsToSnapshot(ScrnInfoP
 	}
     }
 }
+#endif /* !REG_DUMPER */
 
 static void i830DumpIndexed (ScrnInfoPtr pScrn, char *name, int id, int val, int min, int max)
 {
@@ -587,6 +598,7 @@ void i830DumpRegs (ScrnInfoPtr pScrn)
     xf86DrvMsg (pScrn->scrnIndex, X_INFO, "DumpRegsEnd\n");
 }
 
+#ifndef REG_DUMPER
 /* Famous last words
  */
 void
@@ -799,3 +811,4 @@ i830_check_error_state(ScrnInfoPtr pScrn
 
     return (errors != 0);
 }
+#endif /* !REG_DUMPER */
diff-tree cd1d4b398ec91d551bdaaa26c769e5e6a9442df1 (from 3e8e75e5d83a2fa7e9fc6e9a3fbb07dac548ea5a)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Feb 28 09:47:38 2007 -0800

    Many fixes to mode_get, mode_set, clock limits, and register dumps on i855.
    
    This should fix a number of issues with i855s, particularly with integrated
    LVDS panels.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index 46d473d..6a9c11e 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -299,6 +299,20 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define VCLK_DIVISOR_VGA0   0x6000
 #define VCLK_DIVISOR_VGA1   0x6004
 #define VCLK_POST_DIV	    0x6010
+/** Selects a post divisor of 4 instead of 2. */
+# define VGA1_PD_P2_DIV_4	(1 << 15)
+/** Overrides the p2 post divisor field */
+# define VGA1_PD_P1_DIV_2	(1 << 13)
+# define VGA1_PD_P1_SHIFT	8
+/** P1 value is 2 greater than this field */
+# define VGA1_PD_P1_MASK	(0x1f << 8)
+/** Selects a post divisor of 4 instead of 2. */
+# define VGA0_PD_P2_DIV_4	(1 << 7)
+/** Overrides the p2 post divisor field */
+# define VGA0_PD_P1_DIV_2	(1 << 5)
+# define VGA0_PD_P1_SHIFT	0
+/** P1 value is 2 greater than this field */
+# define VGA0_PD_P1_MASK	(0x1f << 0)
 
 #define POST_DIV_SELECT        0x70
 #define POST_DIV_1             0x00
@@ -847,9 +861,18 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 # define DPLLB_LVDS_P2_CLOCK_DIV_7		(1 << 24) /* i915 */
 # define DPLL_P2_CLOCK_DIV_MASK			0x03000000 /* i915 */
 # define DPLL_FPA01_P1_POST_DIV_MASK		0x00ff0000 /* i915 */
+/**
+ *  The i830 generation, in DAC/serial mode, defines p1 as two plus this
+ * bitfield, or just 2 if PLL_P1_DIVIDE_BY_TWO is set.
+ */
+# define DPLL_FPA01_P1_POST_DIV_MASK_I830	0x001f0000
+/**
+ * The i830 generation, in LVDS mode, defines P1 as the bit number set within
+ * this field (only one bit may be set).
+ */
+# define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS	0x003f0000
 # define DPLL_FPA01_P1_POST_DIV_SHIFT		16
 # define PLL_P2_DIVIDE_BY_4			(1 << 23) /* i830, required in DVO non-gang */
-# define DPLL_FPA01_P1_POS_DIV_MASK_I830	0x001f0000 /* i830 */
 # define PLL_P1_DIVIDE_BY_TWO			(1 << 21) /* i830 */
 # define PLL_REF_INPUT_DREFCLK			(0 << 13)
 # define PLL_REF_INPUT_TVCLKINA			(1 << 13) /* i830 */
diff --git a/src/i830_debug.c b/src/i830_debug.c
index 6716eaa..de36a04 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -102,6 +102,28 @@ DEBUGSTRING(i830_debug_fp)
 		     ((val & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT));
 }
 
+DEBUGSTRING(i830_debug_vga_pd)
+{
+    int vga0_p1, vga0_p2, vga1_p1, vga1_p2;
+
+    /* XXX: i9xx version */
+
+    if (val & VGA0_PD_P1_DIV_2)
+	vga0_p1 = 2;
+    else
+	vga0_p1 = ((val & VGA0_PD_P1_MASK) >> VGA0_PD_P1_SHIFT) + 2;
+    vga0_p2 = (val & VGA0_PD_P2_DIV_4) ? 4 : 2;
+
+    if (val & VGA1_PD_P1_DIV_2)
+	vga1_p1 = 2;
+    else
+	vga1_p1 = ((val & VGA1_PD_P1_MASK) >> VGA1_PD_P1_SHIFT) + 2;
+    vga1_p2 = (val & VGA1_PD_P2_DIV_4) ? 4 : 2;
+
+    return XNFprintf("vga0 p1 = %d, p2 = %d, vga1 p1 = %d, p2 = %d",
+		     vga0_p1, vga0_p2, vga1_p1, vga1_p2);
+}
+
 DEBUGSTRING(i830_debug_pp_status)
 {
     char *status = val & PP_ON ? "on" : "off";
@@ -140,18 +162,44 @@ DEBUGSTRING(i830_debug_dpll)
     char sdvoextra[20];
     int p1, p2 = 0;
 
-    p1 = ffs((val & DPLL_FPA01_P1_POST_DIV_MASK) >>
-	     DPLL_FPA01_P1_POST_DIV_SHIFT);
-    switch (val & DPLL_MODE_MASK) {
-    case DPLLB_MODE_DAC_SERIAL:
-	mode = "dac/serial";
-	p2 = val & DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 ? 5 : 10;
-	break;
-    case DPLLB_MODE_LVDS:
-	mode = "LVDS";
-	p2 = val & DPLLB_LVDS_P2_CLOCK_DIV_7 ? 7 : 14;
-	break;
+    if (IS_I9XX(pI830)) {
+	p1 = ffs((val & DPLL_FPA01_P1_POST_DIV_MASK) >>
+		 DPLL_FPA01_P1_POST_DIV_SHIFT);
+	switch (val & DPLL_MODE_MASK) {
+	case DPLLB_MODE_DAC_SERIAL:
+	    mode = "DAC/serial";
+	    p2 = val & DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 ? 5 : 10;
+	    break;
+	case DPLLB_MODE_LVDS:
+	    mode = "LVDS";
+	    p2 = val & DPLLB_LVDS_P2_CLOCK_DIV_7 ? 7 : 14;
+	    break;
+	}
+    } else {
+	Bool is_lvds = (INREG(LVDS) & LVDS_PORT_EN) && (reg == DPLL_B);
+
+	if (val & PLL_P2_DIVIDE_BY_4)
+	    p2 = 4;
+	else
+	    p2 = 2;
+
+	if (is_lvds) {
+	    mode = "LVDS";
+	    /* Map the bit number set from (1, 6) to (-1, 4). */
+	    p1 = ffs((val & DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >>
+		     DPLL_FPA01_P1_POST_DIV_SHIFT);
+	} else {
+	    mode = "DAC/serial";
+	    if (val & PLL_P1_DIVIDE_BY_TWO) {
+		p1 = 2;
+	    } else {
+		/* Map the number in the field to (1, 31) */
+		p1 = ((val & DPLL_FPA01_P1_POST_DIV_MASK_I830) >>
+		      DPLL_FPA01_P1_POST_DIV_SHIFT) + 2;
+	    }
+	}
     }
+
     switch (val & PLL_REF_INPUT_MASK) {
     case PLL_REF_INPUT_DREFCLK:
 	clock = "default";
@@ -162,7 +210,12 @@ DEBUGSTRING(i830_debug_dpll)
     case PLL_REF_INPUT_TVCLKINBC:
 	clock = "TV B/C";
 	break;
+    case PLLB_REF_INPUT_SPREADSPECTRUMIN:
+	if (reg == DPLL_B)
+	    clock = "spread spectrum";
+	break;
     }
+
     if (IS_I945G(pI830) || IS_I945GM(pI830)) {
 	sprintf(sdvoextra, ", SDVO mult %d",
 		(int)((val & SDVO_MULTIPLIER_MASK) >>
@@ -171,9 +224,9 @@ DEBUGSTRING(i830_debug_dpll)
 	sdvoextra[0] = '\0';
     }
 
-    return XNFprintf("%s, %s%s, %s mode, %s clock, p1 = %d, "
+    return XNFprintf("%s, %s%s, %s clock, %s mode, p1 = %d, "
 		     "p2 = %d%s%s",
-		     enabled, dvomode, vgamode, mode, clock, p1, p2,
+		     enabled, dvomode, vgamode, clock, mode, p1, p2,
 		     fpextra, sdvoextra);
 }
 
@@ -233,9 +286,9 @@ static struct i830SnapshotRec {
     char *(*debug_output)(I830Ptr pI830, int reg, CARD32 val);
     CARD32 val;
 } i830_snapshot[] = {
-    DEFINEREG(VCLK_DIVISOR_VGA0),
-    DEFINEREG(VCLK_DIVISOR_VGA1),
-    DEFINEREG(VCLK_POST_DIV),
+    DEFINEREG2(VCLK_DIVISOR_VGA0, i830_debug_fp),
+    DEFINEREG2(VCLK_DIVISOR_VGA1, i830_debug_fp),
+    DEFINEREG2(VCLK_POST_DIV, i830_debug_vga_pd),
     DEFINEREG2(DPLL_TEST, i830_debug_dpll_test),
     DEFINEREG(D_STATE),
     DEFINEREG(DSPCLK_GATE_D),
diff --git a/src/i830_display.c b/src/i830_display.c
index a1660e3..e9666de 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -85,10 +85,15 @@ typedef struct {
 #define I8XX_M2_MAX		     16
 #define I8XX_P_MIN		      4
 #define I8XX_P_MAX		    128
+/* LVDS p1 value can go from 1 to 6, while DAC goes from 2 to 33.  These
+ * values below get 2 added in the clock calculations.
+ */
 #define I8XX_P1_MIN		      0
-#define I8XX_P1_MAX		     30
-#define I8XX_P2_SLOW		      1
-#define I8XX_P2_FAST		      0
+#define I8XX_P1_MAX		     31
+#define I8XX_P1_LVDS_MIN	      -1
+#define I8XX_P1_LVDS_MAX	      4
+#define I8XX_P2_SLOW		      1	/* this is a bit shift amount */
+#define I8XX_P2_FAST		      0	/* this is a bit shift amount */
 #define I8XX_P2_SLOW_LIMIT	 165000
 
 #define I9XX_DOT_MIN		  20000
@@ -116,12 +121,13 @@ typedef struct {
 #define I9XX_P2_LVDS_FAST		      7
 #define I9XX_P2_LVDS_SLOW_LIMIT		 112000
 
-#define INTEL_LIMIT_I8XX	    0
-#define INTEL_LIMIT_I9XX_SDVO_DAC   1
-#define INTEL_LIMIT_I9XX_LVDS	    2
+#define INTEL_LIMIT_I8XX_DVO_DAC    0
+#define INTEL_LIMIT_I8XX_LVDS	    1
+#define INTEL_LIMIT_I9XX_SDVO_DAC   2
+#define INTEL_LIMIT_I9XX_LVDS	    3
 
 static const intel_limit_t intel_limits[] = {
-    {
+    { /* INTEL_LIMIT_I8XX_DVO_DAC */
         .dot = { .min = I8XX_DOT_MIN,		.max = I8XX_DOT_MAX },
         .vco = { .min = I8XX_VCO_MIN,		.max = I8XX_VCO_MAX },
         .n   = { .min = I8XX_N_MIN,		.max = I8XX_N_MAX },
@@ -133,7 +139,19 @@ static const intel_limit_t intel_limits[
 	.p2  = { .dot_limit = I8XX_P2_SLOW_LIMIT,
 		 .p2_slow = I8XX_P2_SLOW,	.p2_fast = I8XX_P2_FAST },
     },
-    {
+    { /* INTEL_LIMIT_I8XX_LVDS */
+        .dot = { .min = I8XX_DOT_MIN,		.max = I8XX_DOT_MAX },
+        .vco = { .min = I8XX_VCO_MIN,		.max = I8XX_VCO_MAX },
+        .n   = { .min = I8XX_N_MIN,		.max = I8XX_N_MAX },
+        .m   = { .min = I8XX_M_MIN,		.max = I8XX_M_MAX },
+        .m1  = { .min = I8XX_M1_MIN,		.max = I8XX_M1_MAX },
+        .m2  = { .min = I8XX_M2_MIN,		.max = I8XX_M2_MAX },
+        .p   = { .min = I8XX_P_MIN,		.max = I8XX_P_MAX },
+        .p1  = { .min = I8XX_P1_LVDS_MIN,	.max = I8XX_P1_LVDS_MAX },
+	.p2  = { .dot_limit = I8XX_P2_SLOW_LIMIT,
+		 .p2_slow = I8XX_P2_FAST,	.p2_fast = I8XX_P2_FAST },
+    },
+    { /* INTEL_LIMIT_I9XX_SDVO_DAC */
         .dot = { .min = I9XX_DOT_MIN,		.max = I9XX_DOT_MAX },
         .vco = { .min = I9XX_VCO_MIN,		.max = I9XX_VCO_MAX },
         .n   = { .min = I9XX_N_MIN,		.max = I9XX_N_MAX },
@@ -145,7 +163,7 @@ static const intel_limit_t intel_limits[
 	.p2  = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT,
 		 .p2_slow = I9XX_P2_SDVO_DAC_SLOW,	.p2_fast = I9XX_P2_SDVO_DAC_FAST },
     },
-    {
+    { /* INTEL_LIMIT_I9XX_LVDS */
         .dot = { .min = I9XX_DOT_MIN,		.max = I9XX_DOT_MAX },
         .vco = { .min = I9XX_VCO_MIN,		.max = I9XX_VCO_MAX },
         .n   = { .min = I9XX_N_MIN,		.max = I9XX_N_MAX },
@@ -168,15 +186,18 @@ static const intel_limit_t *intel_limit 
     I830Ptr	pI830 = I830PTR(pScrn);
     const intel_limit_t *limit;
 
-    if (IS_I9XX(pI830)) 
-    {
+    if (IS_I9XX(pI830)) {
 	if (i830PipeHasType (crtc, I830_OUTPUT_LVDS))
 	    limit = &intel_limits[INTEL_LIMIT_I9XX_LVDS];
 	else
 	    limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC];
+    } else {
+	if (i830PipeHasType (crtc, I830_OUTPUT_LVDS))
+	    limit = &intel_limits[INTEL_LIMIT_I8XX_LVDS];
+	else
+	    limit = &intel_limits[INTEL_LIMIT_I8XX_DVO_DAC];
     }
-    else
-        limit = &intel_limits[INTEL_LIMIT_I8XX];
+
     return limit;
 }
 
@@ -792,7 +813,15 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
 	if (IS_I965G(pI830))
 	    dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT);
     } else {
-	dpll |= clock.p1 << 16;
+	if (is_lvds) {
+	    /* map (-1 to 4) to ((1 << 0) to (1 << 5)). */
+	    dpll |= (1 << (clock.p1 + 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
+	} else {
+	    if (clock.p1 == 0)
+		dpll |= PLL_P1_DIVIDE_BY_TWO;
+	    else
+		dpll |= clock.p1 << DPLL_FPA01_P1_POST_DIV_SHIFT;
+	}
 	dpll |= clock.p2 << 23;
     }
 
@@ -1250,35 +1279,59 @@ i830_crtc_clock_get(ScrnInfoPtr pScrn, x
     clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT;
     clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT;
     clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT;
-    clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK) >>
-		   DPLL_FPA01_P1_POST_DIV_SHIFT);
-    switch (dpll & DPLL_MODE_MASK) {
-    case DPLLB_MODE_DAC_SERIAL:
-	clock.p2 = dpll & DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 ? 5 : 10;
-	break;
-    case DPLLB_MODE_LVDS:
-	clock.p2 = dpll & DPLLB_LVDS_P2_CLOCK_DIV_7 ? 7 : 14;
-	break;
-    default:
-	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		   "Unknown DPLL mode %08x in programmed mode\n",
-		   (int)(dpll & DPLL_MODE_MASK));
-	return 0;
-    }
-    
-    /* XXX: Handle the 100Mhz refclk */
-    if (IS_I9XX(pI830))
+    if (IS_I9XX(pI830)) {
+	clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK) >>
+		       DPLL_FPA01_P1_POST_DIV_SHIFT);
+
+	switch (dpll & DPLL_MODE_MASK) {
+	case DPLLB_MODE_DAC_SERIAL:
+	    clock.p2 = dpll & DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 ? 5 : 10;
+	    break;
+	case DPLLB_MODE_LVDS:
+	    clock.p2 = dpll & DPLLB_LVDS_P2_CLOCK_DIV_7 ? 7 : 14;
+	    break;
+	default:
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		       "Unknown DPLL mode %08x in programmed mode\n",
+		       (int)(dpll & DPLL_MODE_MASK));
+	    return 0;
+	}
+
+	/* XXX: Handle the 100Mhz refclk */
 	i9xx_clock(96000, &clock);
-    else
-	i9xx_clock(48000, &clock);
+    } else {
+	Bool is_lvds = (pipe == 1) && (INREG(LVDS) & LVDS_PORT_EN);
 
-    if (!i830PllIsValid(crtc, &clock)) {
-	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		   "Bad clock found programmed in pipe %c\n",
-		   pipe == 0 ? 'A' : 'B');
-	i830PrintPll("", &clock);
+	if (is_lvds) {
+	    /* Map the bit number set from (1, 6) to (-1, 4). */
+	    clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >>
+			   DPLL_FPA01_P1_POST_DIV_SHIFT) - 2;
+	    clock.p2 = 0;
+	} else {
+	    if (dpll & PLL_P1_DIVIDE_BY_TWO) {
+		clock.p1 = 0;
+	    } else {
+		/* Map the number in the field to (1, 31) */
+		clock.p1 = ((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830) >>
+		    DPLL_FPA01_P1_POST_DIV_SHIFT);
+	    }
+	    if (dpll & PLL_P2_DIVIDE_BY_4)
+		clock.p2 = 1;
+	    else
+		clock.p2 = 0;
+	}
+
+	/* XXX: Deal with other refclocks */
+	i8xx_clock(48000, &clock);
     }
 
+    /* XXX: It would be nice to validate the clocks, but we can't reuse
+     * i830PllIsValid() because it relies on the xf86_config output
+     * configuration being accurate, which it isn't necessarily.
+     */
+    if (0)
+	i830PrintPll("probed", &clock);
+
     return clock.dot;
 }
 
@@ -1299,8 +1352,6 @@ i830_crtc_mode_get(ScrnInfoPtr pScrn, xf
     if (mode == NULL)
 	return NULL;
 
-    memset(mode, 0, sizeof(*mode));
-
     mode->Clock = i830_crtc_clock_get(pScrn, crtc);
     mode->HDisplay = (htot & 0xffff) + 1;
     mode->HTotal = ((htot & 0xffff0000) >> 16) + 1;
diff-tree 3e8e75e5d83a2fa7e9fc6e9a3fbb07dac548ea5a (from 1ac83f51ee46d65237eae1b5c767e106ac9e29bc)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Tue Feb 27 16:48:48 2007 +0800

    Revert "EXA: enlarge 965 exa state buffer size"
    
    This reverts commit 1ac83f51ee46d65237eae1b5c767e106ac9e29bc.
    oops, current exa state + kernel program size + scratch space
    is actually ~36KB.

diff --git a/src/i830.h b/src/i830.h
index 5cf9f0d..08d9e3e 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -73,7 +73,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #ifdef I830_USE_EXA
 #include "exa.h"
 Bool I830EXAInit(ScreenPtr pScreen);
-#define EXA_LINEAR_EXTRA	(80*1024)
+#define EXA_LINEAR_EXTRA	(64*1024)
 #endif
 
 #ifdef I830_USE_XAA
diff-tree 1ac83f51ee46d65237eae1b5c767e106ac9e29bc (from acd9f3e28fcf5e91e09d8bdca4cc58681b1fc92a)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Tue Feb 27 13:58:47 2007 +0800

    EXA: enlarge 965 exa state buffer size
    
    Origin size seems break all render, be sure to assign enough
    mem. 80k works fine for me.

diff --git a/src/i830.h b/src/i830.h
index 08d9e3e..5cf9f0d 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -73,7 +73,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #ifdef I830_USE_EXA
 #include "exa.h"
 Bool I830EXAInit(ScreenPtr pScreen);
-#define EXA_LINEAR_EXTRA	(64*1024)
+#define EXA_LINEAR_EXTRA	(80*1024)
 #endif
 
 #ifdef I830_USE_XAA
diff-tree acd9f3e28fcf5e91e09d8bdca4cc58681b1fc92a (from 5b765065c0bdf671b60d8a2fe512f6307f753eab)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Tue Feb 27 13:56:31 2007 +0800

    Fix typo when assign overlay reg mem pointer

diff --git a/src/i830_video.c b/src/i830_video.c
index 4c64b30..e580dab 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -2175,7 +2175,8 @@ I830PutImage(ScrnInfoPtr pScrn,
    if (pPriv->textured)
        overlay = NULL;
    else
-       (I830OverlayRegPtr) (pI830->FbBase + pI830->overlay_regs->offset);
+       overlay = (I830OverlayRegPtr) (pI830->FbBase + 
+	       pI830->overlay_regs->offset);
 
 #if 0
    ErrorF("I830PutImage: src: (%d,%d)(%d,%d), dst: (%d,%d)(%d,%d)\n"
diff-tree 5b765065c0bdf671b60d8a2fe512f6307f753eab (from 6ed28c5aa34ff1d8b99a8d4721ddac7b9cac41ed)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Feb 26 17:25:57 2007 -0800

    Consolidate shared structure allocation to the start of ScreenInit.
    
    Previously, the structures would get allocated unnecessarily once, and
    wouldn't get reallocated in time at server regen.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 135e6fa..5ba96a5 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -752,15 +752,6 @@ PreInitCleanup(ScrnInfoPtr pScrn)
    if (I830IsPrimary(pScrn)) {
       if (pI830->entityPrivate)
 	 pI830->entityPrivate->pScrn_1 = NULL;
-      if (pI830->LpRing)
-         xfree(pI830->LpRing);
-      pI830->LpRing = NULL;
-      if (pI830->overlayOn)
-         xfree(pI830->overlayOn);
-      pI830->overlayOn = NULL;
-      if (pI830->used3D)
-         xfree(pI830->used3D);
-      pI830->used3D = NULL;
    } else {
       if (pI830->entityPrivate)
          pI830->entityPrivate->pScrn_2 = NULL;
@@ -1370,22 +1361,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       }
    }
 
-   /* Alloc our pointers for the primary head */
-   if (I830IsPrimary(pScrn)) {
-      pI830->LpRing = xcalloc(1, sizeof(I830RingBuffer));
-      pI830->overlayOn = xalloc(sizeof(Bool));
-      pI830->used3D = xalloc(sizeof(int));
-      if (!pI830->LpRing || !pI830->overlayOn || !pI830->used3D) {
-         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		 "Could not allocate primary data structures.\n");
-         PreInitCleanup(pScrn);
-         return FALSE;
-      }
-      *pI830->overlayOn = FALSE;
-      if (pI830->entityPrivate)
-         pI830->entityPrivate->XvInUse = -1;
-   }
-
    /* Check if the HW cursor needs physical address. */
    if (IS_MOBILE(pI830) || IS_I9XX(pI830))
       pI830->CursorNeedsPhysical = TRUE;
@@ -2237,6 +2212,31 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 
    pI830->disableTiling = FALSE;
 
+   if (I830IsPrimary(pScrn)) {
+      /* Alloc our pointers for the primary head */
+      if (!pI830->LpRing)
+         pI830->LpRing = xcalloc(1, sizeof(I830RingBuffer));
+      if (!pI830->overlayOn)
+         pI830->overlayOn = xalloc(sizeof(Bool));
+      if (!pI830->used3D)
+         pI830->used3D = xalloc(sizeof(int));
+      if (!pI830->LpRing || !pI830->overlayOn || !pI830->used3D) {
+         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		 "Could not allocate primary data structures.\n");
+         return FALSE;
+      }
+      *pI830->overlayOn = FALSE;
+      if (pI830->entityPrivate)
+         pI830->entityPrivate->XvInUse = -1;
+   } else {
+      /* Make our second head point to the first heads structures */
+      pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
+      pI830->LpRing = pI8301->LpRing;
+      pI830->overlay_regs = pI8301->overlay_regs;
+      pI830->overlayOn = pI8301->overlayOn;
+      pI830->used3D = pI8301->used3D;
+   }
+
 #if defined(XF86DRI)
    /*
     * If DRI is potentially usable, check if there is enough memory available
@@ -2412,33 +2412,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 
    pI830->starting = TRUE;
 
-   /* Alloc our pointers for the primary head */
-   if (I830IsPrimary(pScrn)) {
-      if (!pI830->LpRing)
-         pI830->LpRing = xalloc(sizeof(I830RingBuffer));
-      if (!pI830->overlayOn)
-         pI830->overlayOn = xalloc(sizeof(Bool));
-      if (!pI830->used3D)
-         pI830->used3D = xalloc(sizeof(int));
-      if (!pI830->LpRing || !pI830->overlayOn || !pI830->used3D) {
-         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		 "Could not allocate primary data structures.\n");
-         return FALSE;
-      }
-      *pI830->overlayOn = FALSE;
-      if (pI830->entityPrivate)
-         pI830->entityPrivate->XvInUse = -1;
-   }
-
-   /* Make our second head point to the first heads structures */
-   if (!I830IsPrimary(pScrn)) {
-      pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
-      pI830->LpRing = pI8301->LpRing;
-      pI830->overlay_regs = pI8301->overlay_regs;
-      pI830->overlayOn = pI8301->overlayOn;
-      pI830->used3D = pI8301->used3D;
-   }
-
    miClearVisualTypes();
    if (!miSetVisualTypes(pScrn->depth,
 			    miGetDefaultVisualMask(pScrn->depth),
diff-tree 6ed28c5aa34ff1d8b99a8d4721ddac7b9cac41ed (from 36bfeb890aeb17a8ee058790dd69b4e9aba644a1)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Feb 26 17:12:44 2007 -0800

    Fix XV issues on 965 after the allocation rework

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 1dfd7a8..135e6fa 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2482,7 +2482,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 		    "needs 2D acceleration.\n");
 	 pI830->XvEnabled = FALSE;
       }
-      if (pI830->overlay_regs == NULL) {
+      if (!IS_I9XX(pI830) && pI830->overlay_regs == NULL) {
 	  xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		     "Disabling Xv because the overlay register buffer "
 		      "allocation failed.\n");
diff --git a/src/i830_video.c b/src/i830_video.c
index 92f094f..4c64b30 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -472,7 +472,9 @@ I830InitVideo(ScreenPtr pScreen)
    }
 
    /* Set up overlay video if we can do it at this depth. */
-   if (!IS_I965G(pI830) && pScrn->bitsPerPixel != 8) {
+   if (!IS_I965G(pI830) && pScrn->bitsPerPixel != 8 &&
+       pI830->overlay_regs != NULL)
+   {
       overlayAdaptor = I830SetupImageVideoOverlay(pScreen);
       if (overlayAdaptor != NULL) {
 	 adaptors[num_adaptors++] = overlayAdaptor;
@@ -925,8 +927,7 @@ I830SetPortAttribute(ScrnInfoPtr pScrn,
 {
    I830PortPrivPtr pPriv = (I830PortPrivPtr) data;
    I830Ptr pI830 = I830PTR(pScrn);
-   I830OverlayRegPtr overlay =
-	 (I830OverlayRegPtr) (pI830->FbBase + pI830->overlay_regs->offset);
+   I830OverlayRegPtr overlay;
 
    if (pPriv->textured) {
       /* XXX: Currently the brightness/saturation attributes aren't hooked up.
@@ -936,6 +937,8 @@ I830SetPortAttribute(ScrnInfoPtr pScrn,
       return Success;
    }
 
+   overlay = (I830OverlayRegPtr) (pI830->FbBase + pI830->overlay_regs->offset);
+
    if (attribute == xvBrightness) {
       if ((value < -128) || (value > 127))
 	 return BadValue;
@@ -2160,8 +2163,7 @@ I830PutImage(ScrnInfoPtr pScrn,
    I830Ptr pI830 = I830PTR(pScrn);
    I830PortPrivPtr pPriv = (I830PortPrivPtr) data;
    ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
-   I830OverlayRegPtr overlay =
-	 (I830OverlayRegPtr) (pI830->FbBase + pI830->overlay_regs->offset);
+   I830OverlayRegPtr overlay;
    PixmapPtr pPixmap;
    INT32 x1, x2, y1, y2;
    int srcPitch, srcPitch2 = 0, dstPitch, destId;
@@ -2170,6 +2172,11 @@ I830PutImage(ScrnInfoPtr pScrn,
    int pitchAlignMask;
    int extraLinear;
 
+   if (pPriv->textured)
+       overlay = NULL;
+   else
+       (I830OverlayRegPtr) (pI830->FbBase + pI830->overlay_regs->offset);
+
 #if 0
    ErrorF("I830PutImage: src: (%d,%d)(%d,%d), dst: (%d,%d)(%d,%d)\n"
 	   "width %d, height %d\n", src_x, src_y, src_w, src_h, drw_x, drw_y,
diff-tree 36bfeb890aeb17a8ee058790dd69b4e9aba644a1 (from 732885c08daaf17034da8f4855d0b957ec3df9d7)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Feb 26 16:58:33 2007 -0800

    Move the initial EnterVT to after we've set up acceleration.
    
    This fixes a crash with initial rotation and EXA due to EXA not being
    initialized in time for the shadow pixmap setup.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 4746c72..1dfd7a8 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2579,8 +2579,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 	 }
       }
    }
-   if (!I830EnterVT(scrnIndex, 0))
-      return FALSE;
 
     if (pScrn->virtualX > pScrn->displayWidth)
 	pScrn->displayWidth = pScrn->virtualX;
@@ -2623,6 +2621,9 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       }
    }
 
+   if (!I830EnterVT(scrnIndex, 0))
+      return FALSE;
+
    miInitializeBackingStore(pScreen);
    xf86SetBackingStore(pScreen);
    xf86SetSilkenMouse(pScreen);
diff-tree 732885c08daaf17034da8f4855d0b957ec3df9d7 (from 0bfaeaab2838184827236c5c0fcc17f06d9e1372)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Feb 26 15:04:56 2007 -0800

    Bug #9604: Align the sizes of allocations to page increments as well.
    
    Without this, the 965 DRI driver fell over when pitch * height wasn't
    page-size aligned.  Since the allocator only allocates at page-aligned offsets
    anyway this shouldn't hurt us at all.

diff --git a/src/i830_dri.c b/src/i830_dri.c
index e14880f..f81251a 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1449,7 +1449,8 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, 
    /* Don't use front_buffer->size here as it includes the pixmap cache area
     * Instead, calculate the entire framebuffer.
     */
-   sarea->front_size = pScrn->displayWidth * pScrn->virtualY * pI830->cpp;
+   sarea->front_size = ROUND_TO_PAGE(pScrn->displayWidth * pScrn->virtualY *
+				     pI830->cpp);
 
    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
               "[drm] init sarea width,height = %d x %d (pitch %d)\n",
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 79c1b4d..b83078a 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -338,6 +338,8 @@ i830_allocate_aperture(ScrnInfoPtr pScrn
 	xfree(mem);
 	return NULL;
     }
+    /* Only allocate page-sized increments. */
+    size = ALIGN(size, GTT_PAGE_SIZE);
     mem->size = size;
 
     if (alignment < GTT_PAGE_SIZE)
@@ -466,6 +468,9 @@ i830_allocate_memory_tiled(ScrnInfoPtr p
     if (tile_format == TILING_NONE)
 	return i830_allocate_memory(pScrn, name, size, alignment, flags);
 
+    /* Only allocate page-sized increments. */
+    size = ALIGN(size, GTT_PAGE_SIZE);
+
     /* Check for maximum tiled region size */
     if (IS_I9XX(pI830)) {
 	if (size > MB(128))
diff-tree 0bfaeaab2838184827236c5c0fcc17f06d9e1372 (from 5732dd7221b7bb24bf21e16066f014a0c7cb6b2a)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Feb 26 11:11:56 2007 -0800

    Fix physical memory allocations, including description in log.

diff --git a/src/i830_memory.c b/src/i830_memory.c
index 3e84a90..79c1b4d 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -344,7 +344,14 @@ i830_allocate_aperture(ScrnInfoPtr pScrn
 	alignment = GTT_PAGE_SIZE;
 
     for (scan = pI830->memory_list; scan->next != NULL; scan = scan->next) {
-	mem->offset = ROUND_TO(scan->end, alignment);
+	mem->offset = scan->end;
+	/* For allocations requiring physical addresses, we have to use AGP
+	 * memory, so move the allocation up out of stolen memory.
+	 */
+	if ((flags & NEED_PHYSICAL_ADDR) && mem->offset < pI830->stolen_size)
+	    mem->offset = pI830->stolen_size;
+	mem->offset = ROUND_TO(mem->offset, alignment);
+
 	mem->end = mem->offset + size;
 	if (flags & ALIGN_BOTH_ENDS)
 	    mem->end = ROUND_TO(mem->end, alignment);
@@ -381,8 +388,11 @@ i830_allocate_agp_memory(ScrnInfoPtr pSc
     if (mem->key != -1)
 	return TRUE;
 
-    if (mem->offset + mem->size <= pI830->stolen_size)
+    if (mem->offset + mem->size <= pI830->stolen_size &&
+	!(flags & NEED_PHYSICAL_ADDR))
+    {
 	return TRUE;
+    }
 
     if (mem->offset < pI830->stolen_size)
 	mem->agp_offset = pI830->stolen_size;
@@ -564,7 +574,7 @@ i830_describe_allocations(ScrnInfoPtr pS
     for (mem = pI830->memory_list->next; mem->next != NULL; mem = mem->next) {
 
 	if (mem->offset >= pI830->stolen_size &&
-	    mem->prev->offset <= pI830->stolen_size)
+	    mem->prev->offset < pI830->stolen_size)
 	{
 	    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
 			   "%s0x%08lx:            end of stolen memory\n",
@@ -578,7 +588,7 @@ i830_describe_allocations(ScrnInfoPtr pS
 			   mem->size / 1024);
 	} else {
 	    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-			   "%s0x%08lx-0x%08lx: %s (%ld kB, %08lx physical)\n",
+			   "%s0x%08lx-0x%08lx: %s (%ld kB, 0x%08lx physical)\n",
 			   prefix,
 			   mem->offset, mem->end - 1, mem->name,
 			   mem->size / 1024, mem->bus_addr);
diff-tree 5732dd7221b7bb24bf21e16066f014a0c7cb6b2a (from aeeae1b40fc012bcc01fcd2243d4993de819b7cf)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Feb 26 09:54:04 2007 -0800

    Fix some texture memory allocation issues.

diff --git a/src/i830.h b/src/i830.h
index 38d49be..08d9e3e 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -579,6 +579,7 @@ void i830_describe_allocations(ScrnInfoP
 			       const char *prefix);
 void i830_reset_allocations(ScrnInfoPtr pScrn);
 void i830_free_3d_memory(ScrnInfoPtr pScrn);
+void i830_free_memory(ScrnInfoPtr pScrn, i830_memory *mem);
 extern long I830CheckAvailableMemory(ScrnInfoPtr pScrn);
 Bool i830_allocate_2d_memory(ScrnInfoPtr pScrn);
 Bool i830_allocate_3d_memory(ScrnInfoPtr pScrn);
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 9ea86ae..e14880f 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -654,21 +654,18 @@ I830DRIScreenInit(ScreenPtr pScreen)
 	    return FALSE;
 	 }
 	 pI830->drmMinor = version->version_minor;
-	 if (!(pI830->mmModeFlags & I830_KERNEL_TEX)) {
-#ifdef XF86DRI_MM	    
-	    if ((version->version_major > 1) ||
-		((version->version_minor >= 7) && 
-		 (version->version_major == 1))) {
-	       pI830->mmModeFlags |= I830_KERNEL_MM;
-	    } else 
-#endif
-	    {
-	       pI830->mmModeFlags |= I830_KERNEL_TEX;
-	    }		
-	 } else {
-	    xf86DrvMsg(pScreen->myNum, X_INFO, 
-		       "Not enabling the DRM memory manager.\n");
-	 } 
+	 if (version->version_minor < 7) {
+	    if (pI830->mmModeFlags & I830_KERNEL_MM) {
+	       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+			  "DRM version %d.%d older than required 1.7 for "
+			  "DRM memory manager.  Disabling.\n",
+			  version->version_major, version->version_minor);
+	       pI830->mmModeFlags &= ~I830_KERNEL_MM;
+
+	       i830_free_memory(pScrn, pI830->memory_manager);
+	       pI830->memory_manager = NULL;
+	    }
+	 }
 	 drmFreeVersion(version);
       }
    }
@@ -1464,8 +1461,13 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, 
    sarea->back_size = pI830->back_buffer->size;
    sarea->depth_offset = pI830->depth_buffer->offset;
    sarea->depth_size = pI830->depth_buffer->size;
-   sarea->tex_offset = pI830->textures->offset;
-   sarea->tex_size = pI830->textures->size;
+   if (pI830->textures != NULL) {
+      sarea->tex_offset = pI830->textures->offset;
+      sarea->tex_size = pI830->textures->size;
+   } else {
+      sarea->tex_offset = 0;
+      sarea->tex_size = 0;
+   }
    sarea->log_tex_granularity = pI830->TexGranularity;
    sarea->pitch = pScrn->displayWidth;
    sarea->virtualX = pScrn->virtualX;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index c660a35..4746c72 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1229,8 +1229,11 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       if (!pI830->directRenderingDisabled) {
 	 Bool tmp = FALSE;
 
-	 if (IS_I965G(pI830))
-	    pI830->mmModeFlags |= I830_KERNEL_TEX;
+	 pI830->mmModeFlags |= I830_KERNEL_TEX;
+#ifdef XF86DRI_MM
+	 if (!IS_I965G(pI830))
+	    pI830->mmModeFlags |= I830_KERNEL_MM;
+#endif
 
 	 from = X_PROBED;
 	 if (xf86GetOptValBool(pI830->Options, 
@@ -1242,14 +1245,12 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 	       pI830->mmModeFlags &= ~I830_KERNEL_TEX;
 	    }	       
 	 }
-	 if (from == X_CONFIG || 
-	     (pI830->mmModeFlags & I830_KERNEL_TEX)) { 
-	    xf86DrvMsg(pScrn->scrnIndex, from, 
-		       "Will %stry to allocate texture pool "
-		       "for old Mesa 3D driver.\n",
-		       (pI830->mmModeFlags & I830_KERNEL_TEX) ? 
-		       "" : "not ");
-	 }
+	 xf86DrvMsg(pScrn->scrnIndex, from,
+		    "Will %stry to allocate texture pool "
+		    "for old Mesa 3D driver.\n",
+		    (pI830->mmModeFlags & I830_KERNEL_TEX) ?
+		    "" : "not ");
+
 	 pI830->mmSize = I830_MM_MAXSIZE;
 	 from = X_INFO;
 	 if (xf86GetOptValInteger(pI830->Options, OPTION_INTELMMSIZE,
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 7461070..3e84a90 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -180,7 +180,7 @@ i830_unbind_memory(ScrnInfoPtr pScrn, i8
     }
 }
 
-static void
+void
 i830_free_memory(ScrnInfoPtr pScrn, i830_memory *mem)
 {
     if (mem == NULL)
@@ -1133,7 +1133,7 @@ i830_allocate_texture_memory(ScrnInfoPtr
     if (pI830->mmModeFlags & I830_KERNEL_MM) {
 	pI830->memory_manager =
 	    i830_allocate_aperture(pScrn, "DRI memory manager",
-				   pI830->mmSize, GTT_PAGE_SIZE,
+				   pI830->mmSize * KB(1), GTT_PAGE_SIZE,
 				   ALIGN_BOTH_ENDS);
 	/* XXX: try memory manager size backoff here? */
 	if (pI830->memory_manager == NULL)
diff-tree aeeae1b40fc012bcc01fcd2243d4993de819b7cf (from 84a7429730ddd29072d696accb9fdd8fea40731a)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Feb 26 09:13:17 2007 -0800

    Fix a crash in startup monitor detect.

diff --git a/src/i830_display.c b/src/i830_display.c
index f3beb57..a1660e3 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -342,7 +342,13 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x,
     int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE);
     int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
 
-    if (crtc->rotatedData != NULL) {
+    if (pI830->front_buffer == NULL) {
+	/* During startup we may be called as part of monitor detection while
+	 * there is no memory allocation done, so just supply a dummy base
+	 * address.
+	 */
+	Start = 0;
+    } else if (crtc->rotatedData != NULL) {
 	Start = (char *)crtc->rotatedData - (char *)pI830->FbBase;
     } else if (I830IsPrimary(pScrn)) {
 	Start = pI830->front_buffer->offset;
diff-tree 84a7429730ddd29072d696accb9fdd8fea40731a (from 7bb725dee9ef0ccdc478ed4931dc267bcb80203f)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Feb 23 14:59:24 2007 -0800

    Always allocate logical_context, since we use it in emitting invariants.

diff --git a/src/i830_memory.c b/src/i830_memory.c
index 5050a7a..7461070 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -255,8 +255,6 @@ i830_free_3d_memory(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
 
-    i830_free_memory(pScrn, pI830->logical_context);
-    pI830->logical_context = NULL;
     i830_free_memory(pScrn, pI830->back_buffer);
     pI830->back_buffer = NULL;
     i830_free_memory(pScrn, pI830->depth_buffer);
@@ -915,6 +913,15 @@ i830_allocate_2d_memory(ScrnInfoPtr pScr
 	}
     }
 
+    /* Space for the X Server's 3D context.  32k is fine for right now. */
+    pI830->logical_context = i830_allocate_memory(pScrn, "logical 3D context",
+						  KB(32), GTT_PAGE_SIZE, 0);
+    if (pI830->logical_context == NULL) {
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		   "Failed to allocate logical context space.\n");
+	return FALSE;
+    }
+
 #ifdef I830_XV
     /* Allocate overlay register space and optional XAA linear allocator
      * space.  The second head in zaphod mode will share the space.
@@ -1165,18 +1172,7 @@ i830_allocate_texture_memory(ScrnInfoPtr
 Bool
 i830_allocate_3d_memory(ScrnInfoPtr pScrn)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
-
-    DPRINTF(PFX, "I830Allocate3DMemory\n");
-
-    /* Space for logical context.  32k is fine for right now. */
-    pI830->logical_context = i830_allocate_memory(pScrn, "logical 3D context",
-						  KB(32), GTT_PAGE_SIZE, 0);
-    if (pI830->logical_context == NULL) {
-	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		   "Failed to allocate logical context space.\n");
-	return FALSE;
-    }
+    DPRINTF(PFX, "i830_allocate_3d_memory\n");
 
     if (!i830_allocate_backbuffer(pScrn))
 	return FALSE;
diff-tree 7bb725dee9ef0ccdc478ed4931dc267bcb80203f (from 54198b26e87baa180208932b97f10b27d9c0fddc)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Feb 23 14:56:58 2007 -0800

    Improve logging of memory allocation passes, and clean the code up a bit.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 88fee86..c660a35 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -812,27 +812,6 @@ i830SetHotkeyControl(ScrnInfoPtr pScrn, 
    pI830->writeControl(pI830, GRX, 0x18, gr18);
 }
 
-#ifdef XF86DRI
-static void 
-I830ReduceMMSize(ScrnInfoPtr pScrn, unsigned long newSize,
-		 const char *reason)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-
-   newSize = ROUND_DOWN_TO(newSize, GTT_PAGE_SIZE);
-   if (newSize / GTT_PAGE_SIZE > I830_MM_MINPAGES) {
-      pI830->mmSize = newSize / 1024;
-      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		 "DRM memory manager aperture size is reduced to %d kiB\n"
-		 "\t%s\n", pI830->mmSize, reason);
-   } else {
-      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		 "DRM memory manager will be disabled\n\t%s\n", reason);
-      pI830->mmSize = 0;
-   }
-}
-#endif
-
 /**
  * This is called per zaphod head (so usually just once) to do initialization
  * before the Screen is created.
@@ -2158,7 +2137,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    I830Ptr pI8301 = NULL;
    unsigned long sys_mem;
    int i;
-   Bool allocation_done;
+   Bool allocation_done = FALSE;
    MessageType from;
 #ifdef XF86DRI
    Bool driDisabled;
@@ -2268,7 +2247,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       pI830->mmSize = 0;
    }
 
-   if (I830IsPrimary(pScrn) && !pI830->directRenderingDisabled) {
+   if (!pI830->directRenderingDisabled) {
       int savedDisplayWidth = pScrn->displayWidth;
       Bool tiled = FALSE;
 
@@ -2306,70 +2285,80 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 	 }
       }
 
-      allocation_done = FALSE;
-      /*
-       * If the displayWidth is a tilable pitch, test if there's enough
-       * memory available to enable tiling.
+      /* Attempt several rounds of allocation to get 2d and 3d memory to fit:
+       *
+       * 0: tiled, large memory manager
+       * 1: tiled, small memory manager
+       * 2: untiled, large
+       * 3: untiled, small
        */
+
+      pI830->disableTiling = FALSE;
       savedMMSize = pI830->mmSize;
-      if (tiled) {
-retry_dryrun:
-	 i830_reset_allocations(pScrn);
-	 if (!i830_allocate_2d_memory(pScrn) ||
-	     !i830_allocate_3d_memory(pScrn))
-	 {
-	    /* Failure to set up allocations, so try reducing the DRI memory
-	     * manager's size if we haven't yet.
-	     */
-	    if (KB(pI830->mmSize) > I830_MM_MINPAGES * GTT_PAGE_SIZE) {
-	       I830ReduceMMSize(pScrn, I830_MM_MINPAGES * GTT_PAGE_SIZE,
-				"to make room for tiling.");
-	       goto retry_dryrun;
-	    }
-	    /* Otherwise, disable tiling. */
+      for (i = 0; i < 4; i++) {
+	 if (!tiled && i < 2)
+	    continue;
+
+	 if (i >= 2) {
+	    /* For further allocations, disable tiling */
+	    pI830->disableTiling = TRUE;
 	    pScrn->displayWidth = savedDisplayWidth;
 	    pI830->allowPageFlip = FALSE;
-	 } else if (pScrn->displayWidth != savedDisplayWidth) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		       "Increasing the scanline pitch to allow tiling mode "
-		       "(%d -> %d).\n",
-		       savedDisplayWidth, pScrn->displayWidth);
-	    allocation_done = TRUE;
 	 }
-      }
-      if (!allocation_done) {
-	 /*
-	  * Tiling can't be enabled.  Check if there's enough memory for DRI
-	  * without tiling.
-	  */
-	 pI830->mmSize = savedMMSize;
-	 pI830->disableTiling = TRUE;
-retry_dryrun2:
-	 i830_reset_allocations(pScrn);
-	 if (!i830_allocate_2d_memory(pScrn) ||
-	     !i830_allocate_3d_memory(pScrn))
-	 {
-	    /* Failure to set up allocations, so try reducing the DRI memory
-	     * manager's size if we haven't yet.
+
+	 if (i & 1) {
+	    /* For this allocation, switch to a smaller DRI memory manager
+	     * size.
 	     */
-	    if (KB(pI830->mmSize) > I830_MM_MINPAGES * GTT_PAGE_SIZE) {
-	       I830ReduceMMSize(pScrn, I830_MM_MINPAGES * GTT_PAGE_SIZE,
-				"to save AGP aperture space for video "
-				"memory.");
-	       goto retry_dryrun2;
-	    }
-	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		       "Not enough video memory.  Disabling DRI.");
-	    pI830->mmSize = 0;
-	    pI830->directRenderingDisabled = TRUE;
+	    pI830->mmSize = I830_MM_MINPAGES * GTT_PAGE_SIZE;
 	 } else {
+	    pI830->mmSize = savedMMSize;
+	 }
+
+	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		    "Attempting memory allocation with %s buffers and \n"
+		    "\t       %s DRI memory manager reservation:\n",
+		    (i & 2) ? "untiled" : "tiled",
+		    (i & 1) ? "small" : "large");
+
+	 if (i830_allocate_2d_memory(pScrn) &&
+	     i830_allocate_3d_memory(pScrn))
+	 {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Success.\n");
+	    if (pScrn->displayWidth != savedDisplayWidth) {
+	       xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+			  "Increasing the scanline pitch to allow tiling mode "
+			  "(%d -> %d).\n",
+			  savedDisplayWidth, pScrn->displayWidth);
+	    }
 	    allocation_done = TRUE;
+	    break;
 	 }
+
+	 i830_reset_allocations(pScrn);
+      }
+
+      if (i == 4) {
+	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		    "Not enough video memory.  Disabling DRI.\n");
+	 pI830->mmSize = 0;
+	 pI830->directRenderingDisabled = TRUE;
       }
    } else
 #endif
       pI830->disableTiling = TRUE; /* no DRI - so disableTiling */
 
+   if (!allocation_done) {
+      if (!i830_allocate_2d_memory(pScrn)) {
+	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		    "Couldn't allocate video memory\n");
+	 return FALSE;
+      }
+      allocation_done = TRUE;
+   }
+
+   i830_describe_allocations(pScrn, 1, "");
+
    if (!IS_I965G(pI830) && pScrn->displayWidth > 2048) {
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		 "Cannot support DRI with frame buffer width > 2048.\n");
@@ -2537,7 +2526,6 @@ retry_dryrun2:
    pI830->directRenderingEnabled = FALSE;
 #endif
 
-   i830_describe_allocations(pScrn, 1, "");
 #ifdef XF86DRI
    if (pI830->directRenderingEnabled)
       pI830->directRenderingEnabled = I830DRIDoMappings(pScreen);
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 5603c48..5050a7a 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -183,6 +183,9 @@ i830_unbind_memory(ScrnInfoPtr pScrn, i8
 static void
 i830_free_memory(ScrnInfoPtr pScrn, i830_memory *mem)
 {
+    if (mem == NULL)
+	return;
+
     i830_unbind_memory(pScrn, mem);
 
     /* Disconnect from the list of allocations */
@@ -641,7 +644,7 @@ i830_allocate_overlay(ScrnInfoPtr pScrn)
 						   OVERLAY_SIZE, GTT_PAGE_SIZE,
 						   NEED_PHYSICAL_ADDR);
 	if (pI830->overlay_regs == NULL) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		       "Failed to allocate Overlay register space.\n");
 	    /* This failure isn't fatal. */
 	}
@@ -652,7 +655,7 @@ i830_allocate_overlay(ScrnInfoPtr pScrn)
 						 KB(pI830->LinearAlloc),
 						 GTT_PAGE_SIZE, 0);
 	if (pI830->xaa_linear == NULL) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		       "Failed to allocate linear buffer space\n");
 	}
     }
@@ -937,8 +940,8 @@ i830_allocate_2d_memory(ScrnInfoPtr pScr
 	    pI830->exa_offscreen = i830_allocate_memory(pScrn, "exa offscreen",
 							size, 1, 0);
 	    if (pI830->exa_offscreen == NULL) {
-		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate "
-			   "offscreen memory.  Not enough VRAM?\n");
+		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+			   "Failed to allocate EXA offscreen memory.");
 		return FALSE;
 	    }
 	}
@@ -948,9 +951,8 @@ i830_allocate_2d_memory(ScrnInfoPtr pScr
 		i830_allocate_memory(pScrn, "exa G965 state buffer",
 				     EXA_LINEAR_EXTRA, GTT_PAGE_SIZE, 0);
 	    if (pI830->exa_965_state == NULL) {
-		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-			   "G965: Failed to allocate exa state buffer "
-			   "space.\n");
+		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+			   "Failed to allocate exa state buffer for 965.\n");
 		return FALSE;
 	    }
 	}
@@ -982,9 +984,8 @@ i830_allocate_2d_memory(ScrnInfoPtr pScr
 				     MIN_SCRATCH_BUFFER_SIZE, GTT_PAGE_SIZE,
 				     0);
 	    if (pI830->xaa_scratch == NULL) {
-		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-			   "Failed to allocate scratch buffer "
-			   "space\n");
+		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+			   "Failed to allocate scratch buffer space\n");
 		return FALSE;
 	    }
 	}
@@ -1003,7 +1004,7 @@ i830_allocate_2d_memory(ScrnInfoPtr pScr
 					 MIN_SCRATCH_BUFFER_SIZE,
 					 GTT_PAGE_SIZE, 0);
 		if (pI830->xaa_scratch_2 == NULL) {
-		    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 			       "Failed to allocate secondary scratch "
 			       "buffer space\n");
 		    return FALSE;
@@ -1063,7 +1064,7 @@ i830_allocate_backbuffer(ScrnInfoPtr pSc
     }
 
     if (pI830->back_buffer == NULL) {
-	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		   "Failed to allocate back buffer space.\n");
 	return FALSE;
     }
@@ -1107,7 +1108,7 @@ i830_allocate_depthbuffer(ScrnInfoPtr pS
     }
 
     if (pI830->depth_buffer == NULL) {
-	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		   "Failed to allocate depth buffer space.\n");
 	return FALSE;
     }
@@ -1152,7 +1153,7 @@ i830_allocate_texture_memory(ScrnInfoPtr
 	pI830->textures = i830_allocate_memory(pScrn, "textures", size,
 					       GTT_PAGE_SIZE, 0);
 	if (pI830->textures == NULL) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		       "Failed to allocate texture space.\n");
 	    return FALSE;
 	}
@@ -1172,7 +1173,7 @@ i830_allocate_3d_memory(ScrnInfoPtr pScr
     pI830->logical_context = i830_allocate_memory(pScrn, "logical 3D context",
 						  KB(32), GTT_PAGE_SIZE, 0);
     if (pI830->logical_context == NULL) {
-	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		   "Failed to allocate logical context space.\n");
 	return FALSE;
     }
diff-tree 54198b26e87baa180208932b97f10b27d9c0fddc (from 828deff6453872ef0f9fa35c08c9f95f464b1785)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Feb 23 14:17:07 2007 -0800

    Move memory allocation to ScreenInit rather than PreInit.
    
    This lets us do memory allocation just once rather than having several passes
    (as long as things succeed), avoids trouble with zaphod mode, and will let us
    do better automatic sizing of allocations soon.

diff --git a/src/i830.h b/src/i830.h
index f779978..38d49be 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -291,7 +291,6 @@ typedef struct _I830Rec {
    unsigned long LinearAlloc;
    XF86ModReqInfo shadowReq; /* to test for later libshadow */
    Rotation rotation;
-   int displayWidth;
    void (*PointerMoved)(int, int, int);
    CreateScreenResourcesProcPtr    CreateScreenResources;
    int *used3D;
@@ -579,9 +578,10 @@ Bool i830_allocator_init(ScrnInfoPtr pSc
 void i830_describe_allocations(ScrnInfoPtr pScrn, int verbosity,
 			       const char *prefix);
 void i830_reset_allocations(ScrnInfoPtr pScrn);
+void i830_free_3d_memory(ScrnInfoPtr pScrn);
 extern long I830CheckAvailableMemory(ScrnInfoPtr pScrn);
-Bool i830_allocate_2d_memory(ScrnInfoPtr pScrn, const int flags);
-Bool i830_allocate_3d_memory(ScrnInfoPtr pScrn, const int flags);
+Bool i830_allocate_2d_memory(ScrnInfoPtr pScrn);
+Bool i830_allocate_3d_memory(ScrnInfoPtr pScrn);
 
 extern Bool I830IsPrimary(ScrnInfoPtr pScrn);
 
@@ -666,11 +666,6 @@ extern const int I830CopyROP[16];
 #define NEED_PHYSICAL_ADDR		0x00000001
 #define ALIGN_BOTH_ENDS			0x00000002
 
-#define ALLOC_NO_TILING			0x00001000
-#define ALLOC_INITIAL			0x00002000
-
-#define ALLOCATE_DRY_RUN		0x80000000
-
 /* Chipset registers for VIDEO BIOS memory RW access */
 #define _855_DRAM_RW_CONTROL 0x58
 #define _845_DRAM_RW_CONTROL 0x90
diff --git a/src/i830_display.c b/src/i830_display.c
index a09d96a..f3beb57 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -972,7 +972,7 @@ i830_crtc_shadow_allocate (xf86CrtcPtr c
     unsigned long rotate_offset;
     int align = KB(4), size;
 
-    rotate_pitch = pI830->displayWidth * pI830->cpp;
+    rotate_pitch = pScrn->displayWidth * pI830->cpp;
     size = rotate_pitch * height;
 
 #ifdef I830_USE_EXA
@@ -1034,7 +1034,7 @@ i830_crtc_shadow_create(xf86CrtcPtr crtc
     if (!data)
 	data = i830_crtc_shadow_allocate (crtc, width, height);
     
-    rotate_pitch = pI830->displayWidth * pI830->cpp;
+    rotate_pitch = pScrn->displayWidth * pI830->cpp;
 
     rotate_pixmap = GetScratchPixmapHeader(pScrn->pScreen,
 					   width, height,
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 9e3f378..9ea86ae 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -158,9 +158,9 @@ I830InitDma(ScrnInfoPtr pScrn)
    info.depth_offset = pI830->depth_buffer->offset;
    info.w = pScrn->virtualX;
    info.h = pScrn->virtualY;
-   info.pitch = pI830->displayWidth;
-   info.back_pitch = pI830->displayWidth;
-   info.depth_pitch = pI830->displayWidth;
+   info.pitch = pScrn->displayWidth;
+   info.back_pitch = pScrn->displayWidth;
+   info.depth_pitch = pScrn->displayWidth;
    info.cpp = pI830->cpp;
 
    if (drmCommandWrite(pI830->drmSubFD, DRM_I830_INIT,
@@ -1452,7 +1452,7 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, 
    /* Don't use front_buffer->size here as it includes the pixmap cache area
     * Instead, calculate the entire framebuffer.
     */
-   sarea->front_size = pI830->displayWidth * pScrn->virtualY * pI830->cpp;
+   sarea->front_size = pScrn->displayWidth * pScrn->virtualY * pI830->cpp;
 
    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
               "[drm] init sarea width,height = %d x %d (pitch %d)\n",
@@ -1477,7 +1477,7 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, 
    sarea->rotation = 0;
    sarea->rotated_offset = -1;
    sarea->rotated_size = 0;
-   sarea->rotated_pitch = pI830->displayWidth;
+   sarea->rotated_pitch = pScrn->displayWidth;
 
    success = I830DRIMapScreenRegions(pScrn, sarea);
 
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 50fe2a6..88fee86 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -837,8 +837,8 @@ I830ReduceMMSize(ScrnInfoPtr pScrn, unsi
  * This is called per zaphod head (so usually just once) to do initialization
  * before the Screen is created.
  *
- * This code generally covers probing, module loading, option handling,
- * initial memory layout measurement, card mapping, and RandR setup.
+ * This code generally covers probing, module loading, option handling
+ * card mapping, and RandR setup.
  */
 static Bool
 I830PreInit(ScrnInfoPtr pScrn, int flags)
@@ -850,18 +850,14 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    rgb defaultWeight = { 0, 0, 0 };
    EntityInfoPtr pEnt;
    I830EntPtr pI830Ent = NULL;					
-   int sys_mem;
    int flags24;
    int i;
    char *s;
    pointer pVBEModule = NULL;
-   Bool enable, allocation_done;
    const char *chipname;
+   Bool enable;
    int num_pipe;
    int max_width, max_height;
-#ifdef XF86DRI
-   unsigned long savedMMSize;
-#endif
 
    if (pScrn->numEntities != 1)
       return FALSE;
@@ -900,7 +896,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    pI830->SaveGeneration = -1;
    pI830->pEnt = pEnt;
 
-   pI830->displayWidth = 640; /* default it */
+   pScrn->displayWidth = 640; /* default it */
 
    if (pI830->pEnt->location.type != BUS_PCI)
       return FALSE;
@@ -1293,10 +1289,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    pI830->LinearAlloc = 0;
    if (xf86GetOptValULong(pI830->Options, OPTION_LINEARALLOC,
 			    &(pI830->LinearAlloc))) {
-      if (pI830->LinearAlloc > 0)
-         xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Allocating %luKbytes of memory\n",
-		 pI830->LinearAlloc);
-      else 
+      if (pI830->LinearAlloc < 0)
          pI830->LinearAlloc = 0;
    }
 
@@ -1351,91 +1344,8 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    } else
       pI830->checkDevices = FALSE;
 
-   pScrn->displayWidth = (pScrn->virtualX + 63) & ~63;
-
    pI830->stolen_size = I830DetectMemory(pScrn);
 
-   /*
-    * The "VideoRam" config file parameter specifies the maximum amount of
-    * memory that will be used/allocated.  When not present, we allow the
-    * driver to allocate as much memory as it wishes to satisfy its
-    * allocations, but if agpgart support isn't available, it gets limited
-    * to the amount of pre-allocated ("stolen") memory.
-    *
-    * Note that in using this value for allocator initialization, we're
-    * limiting aperture allocation to the VideoRam option, rather than limiting
-    * actual memory allocation, so alignment and things will cause less than
-    * VideoRam to be actually used.
-    */
-   if (!pI830->pEnt->device->videoRam) {
-      from = X_DEFAULT;
-      pScrn->videoRam = pI830->FbMapSize / KB(1);
-   } else {
-      from = X_CONFIG;
-      pScrn->videoRam = pI830->pEnt->device->videoRam;
-   }
-
-   sys_mem = I830CheckAvailableMemory(pScrn);
-   if (sys_mem == -1) {
-      if (pScrn->videoRam > pI830->stolen_size / KB(1)) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		    "/dev/agpgart is either not available, or no memory "
-		    "is available\nfor allocation.  "
-		    "Using pre-allocated memory only.\n");
-	 pScrn->videoRam = pI830->stolen_size / KB(1);
-      }
-      pI830->StolenOnly = TRUE;
-   } else {
-      if (sys_mem + (pI830->stolen_size / 1024) < pScrn->videoRam) {
-	 pScrn->videoRam = sys_mem + (pI830->stolen_size / 1024);
-	 from = X_PROBED;
-	 if (sys_mem + (pI830->stolen_size / 1024) <
-	     pI830->pEnt->device->videoRam)
-	 {
-	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		       "VideoRAM reduced to %d kByte "
-		       "(limited to available sysmem)\n", pScrn->videoRam);
-	 }
-      }
-   }
-
-   if (pScrn->videoRam > pI830->FbMapSize / 1024) {
-      pScrn->videoRam = pI830->FbMapSize / 1024;
-      if (pI830->FbMapSize / 1024 < pI830->pEnt->device->videoRam) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		    "VideoRam reduced to %d kByte (limited to aperture "
-		    "size)\n",
-		    pScrn->videoRam);
-      }
-   }
-
-   /* Make sure it's on a page boundary */
-   if (pScrn->videoRam & 3) {
-      xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VideoRam reduced to %d KB "
-		 "(page aligned - was %d KB)\n",
-		 pScrn->videoRam & ~3, pScrn->videoRam);
-      pScrn->videoRam &= ~3;
-   }
-
-   if (!i830_allocator_init(pScrn, 0, pScrn->videoRam * KB(1))) {
-      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		 "Couldn't initialize video memory allocator\n");
-      PreInitCleanup(pScrn);
-      return FALSE;
-   }
-
-   xf86DrvMsg(pScrn->scrnIndex,
-	      pI830->pEnt->device->videoRam ? X_CONFIG : X_DEFAULT,
-	      "VideoRam: %d KB\n", pScrn->videoRam);
-
-   if (xf86GetOptValInteger(pI830->Options, OPTION_CACHE_LINES,
-			    &(pI830->CacheLines))) {
-      xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Requested %d cache lines\n",
-		 pI830->CacheLines);
-   } else {
-      pI830->CacheLines = -1;
-   }
-
    pI830->XvDisabled =
 	!xf86ReturnOptValBool(pI830->Options, OPTION_XVIDEO, TRUE);
 
@@ -1537,137 +1447,11 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    }
    pScrn->currentMode = pScrn->modes;
 
-   pI830->disableTiling = FALSE;
-
-#if defined(XF86DRI)
-   /*
-    * If DRI is potentially usable, check if there is enough memory available
-    * for it, and if there's also enough to allow tiling to be enabled.
-    */
-
-   if (!I830CheckDRIAvailable(pScrn)) {
-      pI830->directRenderingDisabled = TRUE;
-      pI830->mmSize = 0;
-   }
-
-   if (I830IsPrimary(pScrn) && !pI830->directRenderingDisabled) {
-      int savedDisplayWidth = pScrn->displayWidth;
-      Bool tiled = FALSE;
-
-#ifdef I830_XV
-      /*
-       * Set this so that the overlay allocation is factored in when
-       * appropriate.
-       */
-      pI830->XvEnabled = !pI830->XvDisabled;
-#endif
-
-      if (IS_I965G(pI830)) {
-	 int tile_pixels = 512 / pI830->cpp;
-	 pScrn->displayWidth = (pScrn->displayWidth + tile_pixels - 1) &
-	    ~(tile_pixels - 1);
-	 tiled = TRUE;
-      } else {
-	 /* Good pitches to allow tiling.  Don't care about pitches < 1024
-	  * pixels.
-	  */
-	 static const int pitches[] = {
-	    1024,
-	    2048,
-	    4096,
-	    8192,
-	    0
-	 };
-
-	 for (i = 0; pitches[i] != 0; i++) {
-	    if (pitches[i] >= pScrn->displayWidth) {
-	       pScrn->displayWidth = pitches[i];
-	       tiled = TRUE;
-	       break;
-	    }
-	 }
-      }
-
-      allocation_done = FALSE;
-      /*
-       * If the displayWidth is a tilable pitch, test if there's enough
-       * memory available to enable tiling.
-       */
-      savedMMSize = pI830->mmSize;
-      if (tiled) {
-retry_dryrun:
-	 i830_reset_allocations(pScrn);
-	 if (!i830_allocate_2d_memory(pScrn,
-				      ALLOCATE_DRY_RUN | ALLOC_INITIAL) ||
-	     !i830_allocate_3d_memory(pScrn, ALLOCATE_DRY_RUN))
-	 {
-	    /* Failure to set up allocations, so try reducing the DRI memory
-	     * manager's size if we haven't yet.
-	     */
-	    if (KB(pI830->mmSize) > I830_MM_MINPAGES * GTT_PAGE_SIZE) {
-	       I830ReduceMMSize(pScrn, I830_MM_MINPAGES * GTT_PAGE_SIZE,
-				"to make room for tiling.");
-	       goto retry_dryrun;
-	    }
-	    /* Otherwise, disable tiling. */
-	    pScrn->displayWidth = savedDisplayWidth;
-	    pI830->allowPageFlip = FALSE;
-	 } else if (pScrn->displayWidth != savedDisplayWidth) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		       "Increasing the scanline pitch to allow tiling mode "
-		       "(%d -> %d).\n",
-		       savedDisplayWidth, pScrn->displayWidth);
-	    allocation_done = TRUE;
-	 }
-      }
-      if (!allocation_done) {
-	 /*
-	  * Tiling can't be enabled.  Check if there's enough memory for DRI
-	  * without tiling.
-	  */
-	 pI830->mmSize = savedMMSize;
-	 pI830->disableTiling = TRUE;
-retry_dryrun2:
-	 i830_reset_allocations(pScrn);
-	 if (!i830_allocate_2d_memory(pScrn,
-				      ALLOCATE_DRY_RUN | ALLOC_INITIAL) ||
-	     !i830_allocate_3d_memory(pScrn, ALLOCATE_DRY_RUN))
-	 {
-	    /* Failure to set up allocations, so try reducing the DRI memory
-	     * manager's size if we haven't yet.
-	     */
-	    if (KB(pI830->mmSize) > I830_MM_MINPAGES * GTT_PAGE_SIZE) {
-	       I830ReduceMMSize(pScrn, I830_MM_MINPAGES * GTT_PAGE_SIZE,
-				"to save AGP aperture space for video "
-				"memory.");
-	       goto retry_dryrun2;
-	    }
-	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		       "Not enough video memory.  Disabling DRI.");
-	    pI830->mmSize = 0;
-	    pI830->directRenderingDisabled = TRUE;
-	 } else {
-	    allocation_done = TRUE;
-	 }
-      }
-   } else
-#endif
-      pI830->disableTiling = TRUE; /* no DRI - so disableTiling */
-
-   if (!IS_I965G(pI830) && pScrn->displayWidth > 2048) {
-      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		 "Cannot support DRI with frame buffer width > 2048.\n");
-      pI830->disableTiling = TRUE;
-      pI830->directRenderingDisabled = TRUE;
-   }
-
    if (!IS_I965G(pI830) && pScrn->virtualY > 2048) {
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot support > 2048 vertical lines. disabling acceleration.\n");
       pI830->noAccel = TRUE;
    }
 
-   pI830->displayWidth = pScrn->displayWidth;
-
    /* Don't need MMIO access anymore. */
    if (pI830->swfSaved) {
       OUTREG(SWF0, pI830->saveSWF0);
@@ -2372,15 +2156,228 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    I830Ptr pI830;
    VisualPtr visual;
    I830Ptr pI8301 = NULL;
+   unsigned long sys_mem;
+   int i;
+   Bool allocation_done;
+   MessageType from;
 #ifdef XF86DRI
    Bool driDisabled;
+   unsigned long savedMMSize;
 #endif
 
    pScrn = xf86Screens[pScreen->myNum];
    pI830 = I830PTR(pScrn);
    hwp = VGAHWPTR(pScrn);
 
-   pScrn->displayWidth = pI830->displayWidth;
+   pScrn->displayWidth = (pScrn->virtualX + 63) & ~63;
+
+   /*
+    * The "VideoRam" config file parameter specifies the maximum amount of
+    * memory that will be used/allocated.  When not present, we allow the
+    * driver to allocate as much memory as it wishes to satisfy its
+    * allocations, but if agpgart support isn't available, it gets limited
+    * to the amount of pre-allocated ("stolen") memory.
+    *
+    * Note that in using this value for allocator initialization, we're
+    * limiting aperture allocation to the VideoRam option, rather than limiting
+    * actual memory allocation, so alignment and things will cause less than
+    * VideoRam to be actually used.
+    */
+   if (pI830->pEnt->device->videoRam == 0) {
+      from = X_DEFAULT;
+      pScrn->videoRam = pI830->FbMapSize / KB(1);
+   } else {
+      from = X_CONFIG;
+      pScrn->videoRam = pI830->pEnt->device->videoRam;
+   }
+
+   /* Limit videoRam to how much we might be able to allocate from AGP */
+   sys_mem = I830CheckAvailableMemory(pScrn);
+   if (sys_mem == -1) {
+      if (pScrn->videoRam > pI830->stolen_size / KB(1)) {
+	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		    "/dev/agpgart is either not available, or no memory "
+		    "is available\nfor allocation.  "
+		    "Using pre-allocated memory only.\n");
+	 pScrn->videoRam = pI830->stolen_size / KB(1);
+      }
+      pI830->StolenOnly = TRUE;
+   } else {
+      if (sys_mem + (pI830->stolen_size / 1024) < pScrn->videoRam) {
+	 pScrn->videoRam = sys_mem + (pI830->stolen_size / 1024);
+	 from = X_PROBED;
+	 if (sys_mem + (pI830->stolen_size / 1024) <
+	     pI830->pEnt->device->videoRam)
+	 {
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		       "VideoRAM reduced to %d kByte "
+		       "(limited to available sysmem)\n", pScrn->videoRam);
+	 }
+      }
+   }
+
+   /* Limit video RAM to the actual aperture size */
+   if (pScrn->videoRam > pI830->FbMapSize / 1024) {
+      pScrn->videoRam = pI830->FbMapSize / 1024;
+      if (pI830->FbMapSize / 1024 < pI830->pEnt->device->videoRam) {
+	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		    "VideoRam reduced to %d kByte (limited to aperture "
+		    "size)\n",
+		    pScrn->videoRam);
+      }
+   }
+
+   /* Make sure it's on a page boundary */
+   if (pScrn->videoRam & 3) {
+      xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VideoRam reduced to %d KB "
+		 "(page aligned - was %d KB)\n",
+		 pScrn->videoRam & ~3, pScrn->videoRam);
+      pScrn->videoRam &= ~3;
+   }
+
+   /* Set up our video memory allocator for the chosen videoRam */
+   if (!i830_allocator_init(pScrn, 0, pScrn->videoRam * KB(1))) {
+      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		 "Couldn't initialize video memory allocator\n");
+      PreInitCleanup(pScrn);
+      return FALSE;
+   }
+
+   xf86DrvMsg(pScrn->scrnIndex,
+	      pI830->pEnt->device->videoRam ? X_CONFIG : X_DEFAULT,
+	      "VideoRam: %d KB\n", pScrn->videoRam);
+
+   if (xf86GetOptValInteger(pI830->Options, OPTION_CACHE_LINES,
+			    &(pI830->CacheLines))) {
+      xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Requested %d cache lines\n",
+		 pI830->CacheLines);
+   } else {
+      pI830->CacheLines = -1;
+   }
+
+   pI830->disableTiling = FALSE;
+
+#if defined(XF86DRI)
+   /*
+    * If DRI is potentially usable, check if there is enough memory available
+    * for it, and if there's also enough to allow tiling to be enabled.
+    */
+
+   if (!I830CheckDRIAvailable(pScrn)) {
+      pI830->directRenderingDisabled = TRUE;
+      pI830->mmSize = 0;
+   }
+
+   if (I830IsPrimary(pScrn) && !pI830->directRenderingDisabled) {
+      int savedDisplayWidth = pScrn->displayWidth;
+      Bool tiled = FALSE;
+
+#ifdef I830_XV
+      /*
+       * Set this so that the overlay allocation is factored in when
+       * appropriate.
+       */
+      pI830->XvEnabled = !pI830->XvDisabled;
+#endif
+
+      if (IS_I965G(pI830)) {
+	 int tile_pixels = 512 / pI830->cpp;
+	 pScrn->displayWidth = (pScrn->displayWidth + tile_pixels - 1) &
+	    ~(tile_pixels - 1);
+	 tiled = TRUE;
+      } else {
+	 /* Good pitches to allow tiling.  Don't care about pitches < 1024
+	  * pixels.
+	  */
+	 static const int pitches[] = {
+	    1024,
+	    2048,
+	    4096,
+	    8192,
+	    0
+	 };
+
+	 for (i = 0; pitches[i] != 0; i++) {
+	    if (pitches[i] >= pScrn->displayWidth) {
+	       pScrn->displayWidth = pitches[i];
+	       tiled = TRUE;
+	       break;
+	    }
+	 }
+      }
+
+      allocation_done = FALSE;
+      /*
+       * If the displayWidth is a tilable pitch, test if there's enough
+       * memory available to enable tiling.
+       */
+      savedMMSize = pI830->mmSize;
+      if (tiled) {
+retry_dryrun:
+	 i830_reset_allocations(pScrn);
+	 if (!i830_allocate_2d_memory(pScrn) ||
+	     !i830_allocate_3d_memory(pScrn))
+	 {
+	    /* Failure to set up allocations, so try reducing the DRI memory
+	     * manager's size if we haven't yet.
+	     */
+	    if (KB(pI830->mmSize) > I830_MM_MINPAGES * GTT_PAGE_SIZE) {
+	       I830ReduceMMSize(pScrn, I830_MM_MINPAGES * GTT_PAGE_SIZE,
+				"to make room for tiling.");
+	       goto retry_dryrun;
+	    }
+	    /* Otherwise, disable tiling. */
+	    pScrn->displayWidth = savedDisplayWidth;
+	    pI830->allowPageFlip = FALSE;
+	 } else if (pScrn->displayWidth != savedDisplayWidth) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		       "Increasing the scanline pitch to allow tiling mode "
+		       "(%d -> %d).\n",
+		       savedDisplayWidth, pScrn->displayWidth);
+	    allocation_done = TRUE;
+	 }
+      }
+      if (!allocation_done) {
+	 /*
+	  * Tiling can't be enabled.  Check if there's enough memory for DRI
+	  * without tiling.
+	  */
+	 pI830->mmSize = savedMMSize;
+	 pI830->disableTiling = TRUE;
+retry_dryrun2:
+	 i830_reset_allocations(pScrn);
+	 if (!i830_allocate_2d_memory(pScrn) ||
+	     !i830_allocate_3d_memory(pScrn))
+	 {
+	    /* Failure to set up allocations, so try reducing the DRI memory
+	     * manager's size if we haven't yet.
+	     */
+	    if (KB(pI830->mmSize) > I830_MM_MINPAGES * GTT_PAGE_SIZE) {
+	       I830ReduceMMSize(pScrn, I830_MM_MINPAGES * GTT_PAGE_SIZE,
+				"to save AGP aperture space for video "
+				"memory.");
+	       goto retry_dryrun2;
+	    }
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		       "Not enough video memory.  Disabling DRI.");
+	    pI830->mmSize = 0;
+	    pI830->directRenderingDisabled = TRUE;
+	 } else {
+	    allocation_done = TRUE;
+	 }
+      }
+   } else
+#endif
+      pI830->disableTiling = TRUE; /* no DRI - so disableTiling */
+
+   if (!IS_I965G(pI830) && pScrn->displayWidth > 2048) {
+      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		 "Cannot support DRI with frame buffer width > 2048.\n");
+      pI830->disableTiling = TRUE;
+      pI830->directRenderingDisabled = TRUE;
+   }
+
+   pScrn->displayWidth = pScrn->displayWidth;
 
 #ifdef HAS_MTRR_SUPPORT
    {
@@ -2479,13 +2476,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    pI830->XvEnabled = FALSE;
 #endif
 
-   if (I830IsPrimary(pScrn)) {
-      i830_reset_allocations(pScrn);
-
-      if (!i830_allocate_2d_memory(pScrn, ALLOC_INITIAL))
-	return FALSE;
-   }
-
    if (!pI830->noAccel) {
       if (pI830->LpRing->mem->size == 0) {
 	  xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
@@ -2530,6 +2520,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 	 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DRI is disabled because it "
 		    "needs HW cursor, 2D accel and AGPGART.\n");
 	 pI830->directRenderingEnabled = FALSE;
+	 i830_free_3d_memory(pScrn);
       }
    }
 
@@ -2538,26 +2529,14 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    if (pI830->directRenderingEnabled)
       pI830->directRenderingEnabled = I830DRIScreenInit(pScreen);
 
-   if (pI830->directRenderingEnabled) {
-      pI830->directRenderingEnabled =
-	 i830_allocate_3d_memory(pScrn,
-				 pI830->disableTiling ? ALLOC_NO_TILING : 0);
-      if (!pI830->directRenderingEnabled)
-	  I830DRICloseScreen(pScreen);
+   if (!pI830->directRenderingEnabled) {
+      i830_free_3d_memory(pScrn);
    }
 
 #else
    pI830->directRenderingEnabled = FALSE;
 #endif
 
-   /* XXX:
-    * After the 3D allocations have been done, see if there's any free space
-    * that can be added to the framebuffer allocation.
-    */
-   if (I830IsPrimary(pScrn)) {
-      i830_allocate_2d_memory(pScrn, 0);
-   }
-
    i830_describe_allocations(pScrn, 1, "");
 #ifdef XF86DRI
    if (pI830->directRenderingEnabled)
diff --git a/src/i830_memory.c b/src/i830_memory.c
index c88261e..5603c48 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -247,6 +247,23 @@ i830_reset_allocations(ScrnInfoPtr pScrn
     memset(pI830->fence, 0, sizeof(pI830->fence));
 }
 
+void
+i830_free_3d_memory(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    i830_free_memory(pScrn, pI830->logical_context);
+    pI830->logical_context = NULL;
+    i830_free_memory(pScrn, pI830->back_buffer);
+    pI830->back_buffer = NULL;
+    i830_free_memory(pScrn, pI830->depth_buffer);
+    pI830->depth_buffer = NULL;
+    i830_free_memory(pScrn, pI830->textures);
+    pI830->textures = NULL;
+    i830_free_memory(pScrn, pI830->memory_manager);
+    pI830->memory_manager = NULL;
+}
+
 /**
  * Initialize's the driver's video memory allocator to allocate in the
  * given range.
@@ -585,10 +602,9 @@ i830_describe_allocations(ScrnInfoPtr pS
 }
 
 static Bool
-i830_allocate_ringbuffer(ScrnInfoPtr pScrn, int flags)
+i830_allocate_ringbuffer(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
 
     if (pI830->noAccel || pI830->LpRing->mem != NULL)
 	return TRUE;
@@ -597,10 +613,8 @@ i830_allocate_ringbuffer(ScrnInfoPtr pSc
 					      PRIMARY_RINGBUFFER_SIZE,
 					      GTT_PAGE_SIZE, 0);
     if (pI830->LpRing->mem == NULL) {
-	if (!dryrun) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		       "Failed to allocate Ring Buffer space\n");
-	}
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "Failed to allocate Ring Buffer space\n");
 	return FALSE;
     }
 
@@ -614,10 +628,9 @@ i830_allocate_ringbuffer(ScrnInfoPtr pSc
  * requested)
  */
 static Bool
-i830_allocate_overlay(ScrnInfoPtr pScrn, int flags)
+i830_allocate_overlay(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
 
     /* Only allocate if overlay is going to be enabled. */
     if (!pI830->XvEnabled || IS_I965G(pI830))
@@ -628,11 +641,9 @@ i830_allocate_overlay(ScrnInfoPtr pScrn,
 						   OVERLAY_SIZE, GTT_PAGE_SIZE,
 						   NEED_PHYSICAL_ADDR);
 	if (pI830->overlay_regs == NULL) {
-	    if (!dryrun) {
-		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-			   "Failed to allocate Overlay register space.\n");
-		/* This failure isn't fatal. */
-	    }
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Failed to allocate Overlay register space.\n");
+	    /* This failure isn't fatal. */
 	}
     }
 
@@ -641,10 +652,8 @@ i830_allocate_overlay(ScrnInfoPtr pScrn,
 						 KB(pI830->LinearAlloc),
 						 GTT_PAGE_SIZE, 0);
 	if (pI830->xaa_linear == NULL) {
-	    if (!dryrun) {
-		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-			   "Failed to allocate linear buffer space\n");
-	    }
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Failed to allocate linear buffer space\n");
 	}
     }
 
@@ -707,12 +716,9 @@ static i830_memory *
 i830_allocate_framebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox,
 			  Bool secondary, int flags)
 {
-    Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
     unsigned int pitch = pScrn->displayWidth * pI830->cpp;
     unsigned long minspace, avail;
     int cacheLines, maxCacheLines;
-    int verbosity = dryrun ? 4 : 1;
-    const char *s = dryrun ? "[dryrun] " : "";
     int align;
     long size, fb_height;
     char *name;
@@ -770,9 +776,9 @@ i830_allocate_framebuffer(ScrnInfoPtr pS
 
 	FbMemBox->y2 += cacheLines;
 
-	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-		       "%sAllocating at least %d scanlines for pixmap cache\n",
-		       s, cacheLines);
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		   "Allocating %d scanlines for pixmap cache\n",
+		   cacheLines);
     } else {
 	/* For EXA, we have a separate allocation for the linear allocator
 	 * which also does the pixmap cache.
@@ -786,7 +792,7 @@ i830_allocate_framebuffer(ScrnInfoPtr pS
     name = secondary ? "secondary front buffer" : "front buffer";
 
     /* Attempt to allocate it tiled first if we have page flipping on. */
-    if (!flags & ALLOC_NO_TILING && pI830->allowPageFlip &&
+    if (!pI830->disableTiling && pI830->allowPageFlip &&
 	IsTileable(pScrn, pitch))
     {
 	/* XXX: probably not the case on 965 */
@@ -796,7 +802,7 @@ i830_allocate_framebuffer(ScrnInfoPtr pS
 	    align = KB(512);
 	front_buffer = i830_allocate_memory_tiled(pScrn, name, size,
 						  pitch, align,
-						  flags, TILING_XMAJOR);
+						  0, TILING_XMAJOR);
 	pI830->front_tiled = FENCE_XMAJOR;
     }
 
@@ -807,11 +813,9 @@ i830_allocate_framebuffer(ScrnInfoPtr pS
     }
 
     if (front_buffer == NULL) {
-	if (!dryrun) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate "
-		       "%sframebuffer. Is your VideoRAM set too low?\n",
-		       secondary ? "secondary " : "");
-	}
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate "
+		   "%sframebuffer. Is your VideoRAM set too low?\n",
+		   secondary ? "secondary " : "");
 	return NULL;
     }
 
@@ -819,13 +823,13 @@ i830_allocate_framebuffer(ScrnInfoPtr pS
 }
 
 static Bool
-i830_allocate_cursor_buffers(xf86CrtcPtr crtc, int flags)
+i830_allocate_cursor_buffers(xf86CrtcPtr crtc)
 {
     ScrnInfoPtr pScrn = crtc->scrn;
     I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
     I830Ptr pI830 = I830PTR(pScrn);
-    Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
     long size;
+    int flags = pI830->CursorNeedsPhysical ? NEED_PHYSICAL_ADDR : 0;
 
     if (pI830->SWCursor)
 	return FALSE;
@@ -836,18 +840,14 @@ i830_allocate_cursor_buffers(xf86CrtcPtr
      */
 
     size = HWCURSOR_SIZE;
-    if (pI830->CursorNeedsPhysical)
-	flags |= NEED_PHYSICAL_ADDR;
 
     if (intel_crtc->cursor_mem == NULL) {
 	intel_crtc->cursor_mem = i830_allocate_memory(pScrn, "HW cursor",
 						      size, GTT_PAGE_SIZE,
 						      flags);
 	if (intel_crtc->cursor_mem == NULL) {
-	    if (!dryrun) {
-		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-			   "Failed to allocate HW cursor space.\n");
-	    }
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Failed to allocate HW cursor space.\n");
 	    return FALSE;
 	}
     }
@@ -862,10 +862,8 @@ i830_allocate_cursor_buffers(xf86CrtcPtr
 							   GTT_PAGE_SIZE,
 							   flags);
 	if (intel_crtc->cursor_mem_argb == NULL) {
-	    if (!dryrun) {
-		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-			   "Failed to allocate HW (ARGB) cursor space.\n");
-	    }
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Failed to allocate HW (ARGB) cursor space.\n");
 	}
     }
 
@@ -877,38 +875,32 @@ i830_allocate_cursor_buffers(xf86CrtcPtr
  * ring buffer, scratch memory, HW cursor.
  */
 Bool
-i830_allocate_2d_memory(ScrnInfoPtr pScrn, const int flags)
+i830_allocate_2d_memory(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     unsigned int pitch = pScrn->displayWidth * pI830->cpp;
     long size;
-    Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
     int i;
 
-    DPRINTF(PFX, "i830_allocate_2d_memory: inital is %s\n",
-	    BOOLTOSTRING(flags & ALLOC_INITIAL));
-
     if (!pI830->StolenOnly &&
 	(!xf86AgpGARTSupported() || !xf86AcquireGART(pScrn->scrnIndex))) {
-	if (!dryrun) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		       "AGP GART support is either not available or cannot "
-		       "be used.\n"
-		       "\tMake sure your kernel has agpgart support or has\n"
-		       "\tthe agpgart module loaded.\n");
-	}
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "AGP GART support is either not available or cannot "
+		   "be used.\n"
+		   "\tMake sure your kernel has agpgart support or has\n"
+		   "\tthe agpgart module loaded.\n");
 	return FALSE;
     }
 
     /* Allocate the ring buffer first, so it ends up in stolen mem. */
-    i830_allocate_ringbuffer(pScrn, flags);
+    i830_allocate_ringbuffer(pScrn);
 
     /* Next, allocate other fixed-size allocations we have. */
     if (!pI830->SWCursor) {
 	/* Allocate cursor memory */
 	for (i = 0; i < xf86_config->num_crtc; i++) {
-	    if (!i830_allocate_cursor_buffers(xf86_config->crtc[i], flags) &&
+	    if (!i830_allocate_cursor_buffers(xf86_config->crtc[i]) &&
 		!pI830->SWCursor)
 		{
 		    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
@@ -925,7 +917,7 @@ i830_allocate_2d_memory(ScrnInfoPtr pScr
      * space.  The second head in zaphod mode will share the space.
      */
     if (I830IsPrimary(pScrn))
-	i830_allocate_overlay(pScrn, flags);
+	i830_allocate_overlay(pScrn);
 #endif
 
 #ifdef I830_USE_EXA
@@ -943,12 +935,10 @@ i830_allocate_2d_memory(ScrnInfoPtr pScr
 	    size = ROUND_TO_PAGE(size);
 
 	    pI830->exa_offscreen = i830_allocate_memory(pScrn, "exa offscreen",
-							size, 1, flags);
+							size, 1, 0);
 	    if (pI830->exa_offscreen == NULL) {
-		if (!dryrun) {
-		    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate "
-			       "offscreen memory.  Not enough VRAM?\n");
-		}
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate "
+			   "offscreen memory.  Not enough VRAM?\n");
 		return FALSE;
 	    }
 	}
@@ -956,86 +946,66 @@ i830_allocate_2d_memory(ScrnInfoPtr pScr
 	if (IS_I965G(pI830) && pI830->exa_965_state == NULL) {
 	    pI830->exa_965_state =
 		i830_allocate_memory(pScrn, "exa G965 state buffer",
-				     EXA_LINEAR_EXTRA, GTT_PAGE_SIZE,
-				     flags);
+				     EXA_LINEAR_EXTRA, GTT_PAGE_SIZE, 0);
 	    if (pI830->exa_965_state == NULL) {
-		if (!dryrun) {
-		    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-			       "G965: Failed to allocate exa state buffer "
-			       "space.\n");
-		}
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			   "G965: Failed to allocate exa state buffer "
+			   "space.\n");
 		return FALSE;
 	    }
 	}
     }
 #endif /* I830_USE_EXA */
 
-    if (flags & ALLOC_INITIAL) {
-
-	/* Unfortunately this doesn't run on the DRY_RUN pass because our
-	 * second head hasn't been created yet..... */
-	if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) {
-	    I830EntPtr pI830Ent = pI830->entityPrivate;
-	    I830Ptr pI8302 = I830PTR(pI830Ent->pScrn_2);
-
-	    pI830->front_buffer_2 =
-		i830_allocate_framebuffer(pI830Ent->pScrn_2, pI8302,
-					  &pI830->FbMemBox2,
-					  TRUE, flags);
-	    if (pI830->front_buffer_2 == NULL)
-		return FALSE;
-	}
-	pI830->front_buffer =
-	    i830_allocate_framebuffer(pScrn, pI830, &pI830->FbMemBox,
-				      FALSE, flags);
-	if (pI830->front_buffer == NULL)
+    if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) {
+	I830EntPtr pI830Ent = pI830->entityPrivate;
+	I830Ptr pI8302 = I830PTR(pI830Ent->pScrn_2);
+
+	pI830->front_buffer_2 =
+	    i830_allocate_framebuffer(pI830Ent->pScrn_2, pI8302,
+				      &pI830->FbMemBox2, TRUE, 0);
+	if (pI830->front_buffer_2 == NULL)
 	    return FALSE;
     }
+    pI830->front_buffer =
+	i830_allocate_framebuffer(pScrn, pI830, &pI830->FbMemBox, FALSE, 0);
+    if (pI830->front_buffer == NULL)
+	return FALSE;
 
     if (!pI830->noAccel && !pI830->useEXA) {
+	pI830->xaa_scratch =
+	    i830_allocate_memory(pScrn, "xaa scratch", MAX_SCRATCH_BUFFER_SIZE,
+				 GTT_PAGE_SIZE, 0);
 	if (pI830->xaa_scratch == NULL) {
 	    pI830->xaa_scratch =
 		i830_allocate_memory(pScrn, "xaa scratch",
-				     MAX_SCRATCH_BUFFER_SIZE, GTT_PAGE_SIZE,
-				     flags);
+				     MIN_SCRATCH_BUFFER_SIZE, GTT_PAGE_SIZE,
+				     0);
 	    if (pI830->xaa_scratch == NULL) {
-		pI830->xaa_scratch =
-		    i830_allocate_memory(pScrn, "xaa scratch",
-					 MIN_SCRATCH_BUFFER_SIZE,
-					 GTT_PAGE_SIZE,
-					 flags);
-		if (pI830->xaa_scratch == NULL) {
-		    if (!dryrun) {
-			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-				   "Failed to allocate scratch buffer "
-				   "space\n");
-		    }
-		    return FALSE;
-		}
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			   "Failed to allocate scratch buffer "
+			   "space\n");
+		return FALSE;
 	    }
 	}
 
 	/* Let's allocate another scratch buffer for the second head */
 	/* Again, this code won't execute on the dry run pass */
-	if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2 &&
-	    pI830->xaa_scratch_2 == NULL)
+	if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2)
 	{
 	    pI830->xaa_scratch_2 =
 		i830_allocate_memory(pScrn, "xaa scratch 2",
 				     MAX_SCRATCH_BUFFER_SIZE, GTT_PAGE_SIZE,
-				     flags);
+				     0);
 	    if (pI830->xaa_scratch_2 == NULL) {
 		pI830->xaa_scratch_2 =
 		    i830_allocate_memory(pScrn, "xaa scratch 2",
 					 MIN_SCRATCH_BUFFER_SIZE,
-					 GTT_PAGE_SIZE,
-					 flags);
+					 GTT_PAGE_SIZE, 0);
 		if (pI830->xaa_scratch_2 == NULL) {
-		    if (!dryrun) {
-			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-				   "Failed to allocate secondary scratch "
-				   "buffer space\n");
-		    }
+		    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			       "Failed to allocate secondary scratch "
+			       "buffer space\n");
 		    return FALSE;
 		}
 	    }
@@ -1059,12 +1029,11 @@ myLog2(unsigned int n)
 }
 
 static Bool
-i830_allocate_backbuffer(ScrnInfoPtr pScrn, const int flags)
+i830_allocate_backbuffer(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     unsigned int pitch = pScrn->displayWidth * pI830->cpp;
     unsigned long size;
-    Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
     int height;
 
     if (pI830->rotation & (RR_Rotate_0 | RR_Rotate_180))
@@ -1073,13 +1042,13 @@ i830_allocate_backbuffer(ScrnInfoPtr pSc
 	height = pScrn->virtualX;
 
     /* Try to allocate on the best tile-friendly boundaries. */
-    if (!(flags & ALLOC_NO_TILING) && IsTileable(pScrn, pitch))
+    if (!pI830->disableTiling && IsTileable(pScrn, pitch))
     {
 	size = ROUND_TO_PAGE(pitch * ALIGN(height, 16));
 	pI830->back_buffer =
 	    i830_allocate_memory_tiled(pScrn, "back buffer",
 				       size, pitch, GTT_PAGE_SIZE,
-				       flags | ALIGN_BOTH_ENDS,
+				       ALIGN_BOTH_ENDS,
 				       TILING_XMAJOR);
 	pI830->back_tiled = FENCE_XMAJOR;
     }
@@ -1089,15 +1058,13 @@ i830_allocate_backbuffer(ScrnInfoPtr pSc
 	size = ROUND_TO_PAGE(pitch * height);
 	pI830->back_buffer = i830_allocate_memory(pScrn, "back buffer",
 						  size, GTT_PAGE_SIZE,
-						  flags | ALIGN_BOTH_ENDS);
+						  ALIGN_BOTH_ENDS);
 	pI830->back_tiled = FENCE_LINEAR;
     }
 
     if (pI830->back_buffer == NULL) {
-	if (!dryrun) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		       "Failed to allocate back buffer space.\n");
-	}
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "Failed to allocate back buffer space.\n");
 	return FALSE;
     }
 
@@ -1105,11 +1072,10 @@ i830_allocate_backbuffer(ScrnInfoPtr pSc
 }
 
 static Bool
-i830_allocate_depthbuffer(ScrnInfoPtr pScrn, const int flags)
+i830_allocate_depthbuffer(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     unsigned long size;
-    Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
     unsigned int pitch = pScrn->displayWidth * pI830->cpp;
     int height;
 
@@ -1120,13 +1086,13 @@ i830_allocate_depthbuffer(ScrnInfoPtr pS
 	height = pScrn->virtualX;
 
     /* First try allocating it tiled */
-    if (!(flags & ALLOC_NO_TILING) && IsTileable(pScrn, pitch))
+    if (!pI830->disableTiling && IsTileable(pScrn, pitch))
     {
 	size = ROUND_TO_PAGE(pitch * ALIGN(height, 16));
 
 	pI830->depth_buffer =
 	    i830_allocate_memory_tiled(pScrn, "depth buffer", size, pitch,
-				       GTT_PAGE_SIZE, flags | ALIGN_BOTH_ENDS,
+				       GTT_PAGE_SIZE, ALIGN_BOTH_ENDS,
 				       TILING_YMAJOR);
 	pI830->depth_tiled = FENCE_YMAJOR;
     }
@@ -1136,15 +1102,13 @@ i830_allocate_depthbuffer(ScrnInfoPtr pS
 	size = ROUND_TO_PAGE(pitch * height);
 	pI830->depth_buffer =
 	    i830_allocate_memory(pScrn, "depth buffer", size, GTT_PAGE_SIZE,
-				 flags);
+				 0);
 	pI830->depth_tiled = FENCE_LINEAR;
     }
 
     if (pI830->depth_buffer == NULL) {
-	if (!dryrun) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		       "Failed to allocate depth buffer space.\n");
-	}
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "Failed to allocate depth buffer space.\n");
 	return FALSE;
     }
 
@@ -1152,18 +1116,17 @@ i830_allocate_depthbuffer(ScrnInfoPtr pS
 }
 
 static Bool
-i830_allocate_texture_memory(ScrnInfoPtr pScrn, const int flags)
+i830_allocate_texture_memory(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     unsigned long size;
     int i;
-    Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
 
     if (pI830->mmModeFlags & I830_KERNEL_MM) {
 	pI830->memory_manager =
 	    i830_allocate_aperture(pScrn, "DRI memory manager",
 				   pI830->mmSize, GTT_PAGE_SIZE,
-				   flags | ALIGN_BOTH_ENDS);
+				   ALIGN_BOTH_ENDS);
 	/* XXX: try memory manager size backoff here? */
 	if (pI830->memory_manager == NULL)
 	    return FALSE;
@@ -1172,8 +1135,6 @@ i830_allocate_texture_memory(ScrnInfoPtr
     if (pI830->mmModeFlags & I830_KERNEL_TEX) {
 	/* XXX: auto-sizing */
 	size = MB(32);
-	if (dryrun && (size < MB(1)))
-	    size = MB(1);
 	i = myLog2(size / I830_NR_TEX_REGIONS);
 	if (i < I830_LOG_MIN_TEX_REGION_SIZE)
 	    i = I830_LOG_MIN_TEX_REGION_SIZE;
@@ -1182,21 +1143,17 @@ i830_allocate_texture_memory(ScrnInfoPtr
 	size >>= i;
 	size <<= i;
 	if (size < KB(512)) {
-	    if (!dryrun) {
-		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-			   "Less than 512 kBytes for texture space (real %ld"
-			   "kBytes).\n",
-			   size / 1024);
-	    }
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Less than 512 kBytes for texture space (real %ld"
+		       "kBytes).\n",
+		       size / 1024);
 	    return FALSE;
 	}
 	pI830->textures = i830_allocate_memory(pScrn, "textures", size,
-					       GTT_PAGE_SIZE, flags);
+					       GTT_PAGE_SIZE, 0);
 	if (pI830->textures == NULL) {
-	    if (!dryrun) {
-		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-			   "Failed to allocate texture space.\n");
-	    }
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Failed to allocate texture space.\n");
 	    return FALSE;
 	}
     }
@@ -1205,32 +1162,28 @@ i830_allocate_texture_memory(ScrnInfoPtr
 }
 
 Bool
-i830_allocate_3d_memory(ScrnInfoPtr pScrn, const int flags)
+i830_allocate_3d_memory(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
 
     DPRINTF(PFX, "I830Allocate3DMemory\n");
 
     /* Space for logical context.  32k is fine for right now. */
     pI830->logical_context = i830_allocate_memory(pScrn, "logical 3D context",
-						  KB(32), GTT_PAGE_SIZE,
-						  flags);
+						  KB(32), GTT_PAGE_SIZE, 0);
     if (pI830->logical_context == NULL) {
-	if (!dryrun) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		       "Failed to allocate logical context space.\n");
-	}
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "Failed to allocate logical context space.\n");
 	return FALSE;
     }
 
-    if (!i830_allocate_backbuffer(pScrn, flags))
+    if (!i830_allocate_backbuffer(pScrn))
 	return FALSE;
 
-    if (!i830_allocate_depthbuffer(pScrn, flags))
+    if (!i830_allocate_depthbuffer(pScrn))
 	return FALSE;
 
-    if (!i830_allocate_texture_memory(pScrn, flags))
+    if (!i830_allocate_texture_memory(pScrn))
 	return FALSE;
 
     return TRUE;
diff-tree 828deff6453872ef0f9fa35c08c9f95f464b1785 (from d3ac440e127c8a7716062852cd3b5e7943e289e4)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Feb 23 13:16:02 2007 -0800

    Fix fence allocations on 965.

diff --git a/src/i830_memory.c b/src/i830_memory.c
index 93429fb..c88261e 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -241,6 +241,10 @@ i830_reset_allocations(ScrnInfoPtr pScrn
     pI830->textures = NULL;
     pI830->memory_manager = NULL;
     pI830->LpRing->mem = NULL;
+
+    /* Reset the fence register allocation. */
+    pI830->next_fence = 0;
+    memset(pI830->fence, 0, sizeof(pI830->fence));
 }
 
 /**
@@ -1278,8 +1282,8 @@ i830_set_fence(ScrnInfoPtr pScrn, int nr
             break;
 	}
 
-	/* XXX Is it the next page, or the last page of the fenced region? */
-	pI830->fence[FENCE_NEW_NR + nr] = offset + size;
+	/* The end marker is the address of the last page in the allocation. */
+	pI830->fence[FENCE_NEW_NR + nr] = offset + size - 4096;
 	return;
     }
 
diff-tree d3ac440e127c8a7716062852cd3b5e7943e289e4 (from a61a6b1db610a07060d0dcca54b66a4b2b3686cc)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Feb 22 10:41:09 2007 -0800

    Rework the video memory allocation.
    
    The previous allocator worked in multiple passes, with (at least) one of
    setting up allocations, another to attempt to adjust those for tiling, and
    then a pass to set up the offsets and fix them in memory.
    
    The new allocator is simpler, allocating memory immediately if possible,
    setting up tiling up front, and choosing offsets immediately.  AGP memory
    is only allocated to back actual memory used, saving some memory that would
    have been allocated for padding previous. It will also allow dynamic freeing
    and reallocation of memory, which will be useful for framebuffer resizing.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index 455c226..46d473d 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -488,6 +488,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define I915G_FENCE_SIZE_32M      0x00000500
 #define I915G_FENCE_SIZE_64M	0x00000600
 #define I915G_FENCE_SIZE_128M	0x00000700
+#define I965_FENCE_X_MAJOR	0x00000000
+#define I965_FENCE_Y_MAJOR	0x00000002
 #define FENCE_PITCH_1       0x00000000
 #define FENCE_PITCH_2       0x00000010
 #define FENCE_PITCH_4       0x00000020
diff --git a/src/i830.h b/src/i830.h
index f52f149..f779978 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -113,30 +113,52 @@ typedef CARD8(*I830ReadIndexedByteFunc)(
 typedef void (*I830WriteByteFunc)(I830Ptr pI830, IOADDRESS addr, CARD8 value);
 typedef CARD8(*I830ReadByteFunc)(I830Ptr pI830, IOADDRESS addr);
 
-/* Linear region allocated in framebuffer. */
-typedef struct _I830MemPool *I830MemPoolPtr;
-typedef struct _I830MemRange *I830MemRangePtr;
-typedef struct _I830MemRange {
-   long Start;
-   long End;
-   long Size;
-   unsigned long Physical;
-   unsigned long Offset;		/* Offset of AGP-allocated portion */
-   unsigned long Alignment;
-   int Key;
-   I830MemPoolPtr Pool;
-} I830MemRange;
-
-typedef struct _I830MemPool {
-   I830MemRange Total;
-   I830MemRange Free;
-   I830MemRange Fixed;
-   I830MemRange Allocated;
-} I830MemPool;
+/** Record of a linear allocation in the aperture. */
+typedef struct _i830_memory i830_memory;
+struct _i830_memory {
+    /** Offset of the allocation in card VM */
+    unsigned long offset;
+    /** End of the allocation in card VM */
+    unsigned long end;
+    /**
+     * Requested size of the allocation: doesn't count padding.
+     *
+     * Any bound memory will cover offset to (offset + size).
+     */
+    unsigned long size;
+    /**
+     * Physical (or more properly, bus) address of the allocation.
+     * Only set if requested during allocation.
+     */
+    unsigned long bus_addr;
+    /** AGP memory handle */
+    int key;
+    /**
+     * Whether or not the AGP memory (if any) is currently bound.
+     */
+    Bool bound;
+    /**
+     * Offset that the AGP-allocated memory (if any) is to be bound to.
+     *
+     * This is either @offset or pI830->stolen_size
+     */
+    unsigned long agp_offset;
+
+    /** Description of the allocation, for logging */
+    char *name;
+
+    /** @{
+     * Memory allocator linked list pointers
+     */
+    i830_memory *next;
+    i830_memory *prev;
+    /** @} */
+
+};
 
 typedef struct {
    int tail_mask;
-   I830MemRange mem;
+   i830_memory *mem;
    unsigned char *virtual_start;
    int head;
    int tail;
@@ -144,10 +166,6 @@ typedef struct {
 } I830RingBuffer;
 
 typedef struct {
-   unsigned int Fence[FENCE_NEW_NR * 2];
-} I830RegRec, *I830RegPtr;
-
-typedef struct {
    int            lastInstance;
    int            refCount;
    ScrnInfoPtr    pScrn_1;
@@ -206,8 +224,8 @@ typedef struct _I830CrtcPrivateRec {
     ExaOffscreenArea *rotate_mem_exa;
 #endif
 
-    I830MemRange cursor_mem;
-    I830MemRange cursor_mem_argb;
+    i830_memory *cursor_mem;
+    i830_memory *cursor_mem_argb;
 } I830CrtcPrivateRec, *I830CrtcPrivatePtr;
 
 #define I830CrtcPrivate(c) ((I830CrtcPrivatePtr) (c)->driver_private)
@@ -249,36 +267,26 @@ typedef struct _I830Rec {
 
    /* These are set in PreInit and never changed. */
    long FbMapSize;
-   long TotalVideoRam;
-   I830MemRange StolenMemory;		/* pre-allocated memory */
-
-   /* These change according to what has been allocated. */
-   long FreeMemory;
-   I830MemRange MemoryAperture;
-   I830MemPool StolenPool;
-   long allocatedMemory;
 
-   /* Regions allocated either from the above pools, or from agpgart. */
-   /* for single and dual head configurations */
-   I830MemRange FrontBuffer;
-   I830MemRange FrontBuffer2;
-   I830MemRange Scratch;
-   I830MemRange Scratch2;
+   i830_memory *memory_list;	/**< Linked list of video memory allocations */
+   long stolen_size;		/**< bytes of pre-bound stolen memory */
+   int gtt_acquired;		/**< whether we currently own the AGP */
+
+   i830_memory *front_buffer;
+   i830_memory *front_buffer_2;
+   i830_memory *xaa_scratch;
+   i830_memory *xaa_scratch_2;
 #ifdef I830_USE_EXA
-   I830MemRange Offscreen;
-   I830MemRange EXAStateMem;  /* specific exa state for G965 */
+   i830_memory *exa_offscreen;
+   i830_memory *exa_965_state;
 #endif
    /* Regions allocated either from the above pools, or from agpgart. */
    I830RingBuffer *LpRing;
 
-#if REMAP_RESERVED
-   I830MemRange Dummy;
-#endif
-
 #ifdef I830_XV
    /* For Xvideo */
-   I830MemRange *OverlayMem;
-   I830MemRange LinearMem;
+   i830_memory *overlay_regs;
+   i830_memory *xaa_linear;
 #endif
    unsigned long LinearAlloc;
    XF86ModReqInfo shadowReq; /* to test for later libshadow */
@@ -288,11 +296,13 @@ typedef struct _I830Rec {
    CreateScreenResourcesProcPtr    CreateScreenResources;
    int *used3D;
 
-   I830MemRange ContextMem;
+   i830_memory *logical_context;
 #ifdef XF86DRI
-   I830MemRange BackBuffer;
-   I830MemRange DepthBuffer;
-   I830MemRange TexMem;
+   i830_memory *back_buffer;
+   i830_memory *depth_buffer;
+   i830_memory *textures;		/**< Compatibility texture memory */
+   i830_memory *memory_manager;		/**< DRI memory manager aperture */
+
    int TexGranularity;
    int drmMinor;
    Bool have3DWindows;
@@ -330,13 +340,21 @@ typedef struct _I830Rec {
 
    unsigned int BR[20];
 
-   int GttBound;
-
    unsigned char **ScanlineColorExpandBuffers;
    int NumScanlineColorExpandBuffers;
    int nextColorExpandBuf;
 
-   I830RegRec ModeReg;
+    /**
+     * Values to be programmed into the fence registers.
+     *
+     * Pre-965, this is a list of FENCE_NR (8) CARD32 registers that
+     * contain their start, size, and pitch.  On the 965, it is a list of
+     * FENCE_NEW_NR CARD32s for the start and pitch fields (low 32 bits) of
+     * the fence registers followed by FENCE_NEW_NR CARD32s for the end fields
+     * (high 32 bits) of the fence registers.
+     */
+   unsigned int fence[FENCE_NEW_NR * 2];
+   unsigned int next_fence;
 
    Bool useEXA;
    Bool noAccel;
@@ -407,7 +425,6 @@ typedef struct _I830Rec {
    /* Broken-out options. */
    OptionInfoPtr Options;
 
-   /* Stolen memory support */
    Bool StolenOnly;
 
    Bool swfSaved;
@@ -499,7 +516,6 @@ typedef struct _I830Rec {
 } I830Rec;
 
 #define I830PTR(p) ((I830Ptr)((p)->driverPrivate))
-#define I830REGPTR(p) (&(I830PTR(p)->ModeReg))
 
 #define I830_SELECT_FRONT	0
 #define I830_SELECT_BACK	1
@@ -528,9 +544,6 @@ extern void i830_crtc_dpms_video(xf86Crt
 
 #ifdef XF86DRI
 extern Bool I830Allocate3DMemory(ScrnInfoPtr pScrn, const int flags);
-extern Bool I830AllocateBackBuffer(ScrnInfoPtr pScrn, const int flags);
-extern Bool I830AllocateDepthBuffer(ScrnInfoPtr pScrn, const int flags);
-extern Bool I830AllocateTextureMemory(ScrnInfoPtr pScrn, const int flags);
 extern void I830SetupMemoryTiling(ScrnInfoPtr pScrn);
 extern Bool I830DRIScreenInit(ScreenPtr pScreen);
 extern Bool I830CheckDRIAvailable(ScrnInfoPtr pScrn);
@@ -561,26 +574,17 @@ extern void I830SetupForSolidFill(ScrnIn
 extern void I830SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y,
 					int w, int h);
 
-extern void I830ResetAllocations(ScrnInfoPtr pScrn, const int flags);
+Bool i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset,
+			 unsigned long size);
+void i830_describe_allocations(ScrnInfoPtr pScrn, int verbosity,
+			       const char *prefix);
+void i830_reset_allocations(ScrnInfoPtr pScrn);
 extern long I830CheckAvailableMemory(ScrnInfoPtr pScrn);
-extern long I830GetExcessMemoryAllocations(ScrnInfoPtr pScrn);
-extern Bool I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags);
-extern Bool I830DoPoolAllocation(ScrnInfoPtr pScrn, I830MemPool *pool);
-extern Bool I830FixupOffsets(ScrnInfoPtr pScrn);
-extern Bool I830BindAGPMemory(ScrnInfoPtr pScrn);
-extern Bool I830UnbindAGPMemory(ScrnInfoPtr pScrn);
-extern unsigned long I830AllocVidMem(ScrnInfoPtr pScrn, I830MemRange *result,
-				     I830MemPool *pool, long size,
-				     unsigned long alignment, int flags);
-extern void I830FreeVidMem(ScrnInfoPtr pScrn, I830MemRange *range);
-
-extern void I830PrintAllRegisters(I830RegPtr i830Reg);
-extern void I830ReadAllRegisters(I830Ptr pI830, I830RegPtr i830Reg);
+Bool i830_allocate_2d_memory(ScrnInfoPtr pScrn, const int flags);
+Bool i830_allocate_3d_memory(ScrnInfoPtr pScrn, const int flags);
 
-extern void I830ChangeFrontbuffer(ScrnInfoPtr pScrn,int buffer);
 extern Bool I830IsPrimary(ScrnInfoPtr pScrn);
 
-extern Bool I830FixOffset(ScrnInfoPtr pScrn, I830MemRange *mem);
 extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg,
 			char *name);
 
@@ -607,6 +611,9 @@ extern void i830MarkSync(ScrnInfoPtr pSc
 extern void i830WaitSync(ScrnInfoPtr pScrn);
 
 /* i830_memory.c */
+Bool i830_bind_all_memory(ScrnInfoPtr pScrn);
+Bool i830_unbind_all_memory(ScrnInfoPtr pScrn);
+
 Bool I830BindAGPMemory(ScrnInfoPtr pScrn);
 Bool I830UnbindAGPMemory(ScrnInfoPtr pScrn);
 #ifdef I830_USE_XAA
@@ -656,18 +663,8 @@ extern const int I830PatternROP[16];
 extern const int I830CopyROP[16];
 
 /* Flags for memory allocation function */
-#define FROM_ANYWHERE			0x00000000
-#define FROM_POOL_ONLY			0x00000001
-#define FROM_NEW_ONLY			0x00000002
-#define FROM_MASK			0x0000000f
-
-#define ALLOCATE_AT_TOP			0x00000010
-#define ALLOCATE_AT_BOTTOM		0x00000020
-#define FORCE_GAPS			0x00000040
-
-#define NEED_PHYSICAL_ADDR		0x00000100
-#define ALIGN_BOTH_ENDS			0x00000200
-#define FORCE_LOW			0x00000400
+#define NEED_PHYSICAL_ADDR		0x00000001
+#define ALIGN_BOTH_ENDS			0x00000002
 
 #define ALLOC_NO_TILING			0x00001000
 #define ALLOC_INITIAL			0x00002000
diff --git a/src/i830_accel.c b/src/i830_accel.c
index db3168a..49a9c13 100644
--- a/src/i830_accel.c
+++ b/src/i830_accel.c
@@ -117,7 +117,7 @@ I830WaitLpRing(ScrnInfoPtr pScrn, int n,
       ring->space = ring->head - (ring->tail + 8);
 
       if (ring->space < 0)
-	 ring->space += ring->mem.Size;
+	 ring->space += ring->mem->size;
 
       iters++;
       now = GetTimeInMillis();
@@ -195,9 +195,9 @@ I830Sync(ScrnInfoPtr pScrn)
       ADVANCE_LP_RING();
    }
 
-   I830WaitLpRing(pScrn, pI830->LpRing->mem.Size - 8, 0);
+   I830WaitLpRing(pScrn, pI830->LpRing->mem->size - 8, 0);
 
-   pI830->LpRing->space = pI830->LpRing->mem.Size - 8;
+   pI830->LpRing->space = pI830->LpRing->mem->size - 8;
    pI830->nextColorExpandBuf = 0;
 }
 
@@ -226,10 +226,10 @@ I830SelectBuffer(ScrnInfoPtr pScrn, int 
    switch (buffer) {
 #ifdef XF86DRI
    case I830_SELECT_BACK:
-      pI830->bufferOffset = pI830->BackBuffer.Start;
+      pI830->bufferOffset = pI830->back_buffer->offset;
       break;
    case I830_SELECT_DEPTH:
-      pI830->bufferOffset = pI830->DepthBuffer.Start;
+      pI830->bufferOffset = pI830->depth_buffer->offset;
       break;
 #endif
    default:
@@ -252,7 +252,7 @@ I830RefreshRing(ScrnInfoPtr pScrn)
    pI830->LpRing->tail = INREG(LP_RING + RING_TAIL);
    pI830->LpRing->space = pI830->LpRing->head - (pI830->LpRing->tail + 8);
    if (pI830->LpRing->space < 0)
-      pI830->LpRing->space += pI830->LpRing->mem.Size;
+      pI830->LpRing->space += pI830->LpRing->mem->size;
    i830MarkSync(pScrn);
 }
 
diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index 70a8d52..0cfd229 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -88,20 +88,20 @@ I830SetPipeCursorBase (xf86CrtcPtr crtc)
     I830Ptr		pI830 = I830PTR(pScrn);
     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     int			cursor_base = (pipe == 0 ? CURSOR_A_BASE : CURSOR_B_BASE);
-    I830MemRange	*cursor_mem;
+    i830_memory		*cursor_mem;
 
     if (pipe >= xf86_config->num_crtc)
 	FatalError("Bad pipe number for cursor base setting\n");
 
     if (pI830->CursorIsARGB)
-	cursor_mem = &intel_crtc->cursor_mem_argb;
+	cursor_mem = intel_crtc->cursor_mem_argb;
     else
-	cursor_mem = &intel_crtc->cursor_mem;
+	cursor_mem = intel_crtc->cursor_mem;
 
     if (pI830->CursorNeedsPhysical) {
-	OUTREG(cursor_base, cursor_mem->Physical);
+	OUTREG(cursor_base, cursor_mem->bus_addr);
     } else {
-	OUTREG(cursor_base, cursor_mem->Start);
+	OUTREG(cursor_base, cursor_mem->offset);
     }
 }
 
@@ -281,7 +281,7 @@ I830CRTCLoadCursorImage(xf86CrtcPtr crtc
    ScrnInfoPtr pScrn = crtc->scrn;
    I830Ptr pI830 = I830PTR(pScrn);
    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
-   CARD8 *pcurs = (CARD8 *) (pI830->FbBase + intel_crtc->cursor_mem.Start);
+   CARD8 *pcurs = (CARD8 *) (pI830->FbBase + intel_crtc->cursor_mem->offset);
    int x, y;
 
    DPRINTF(PFX, "I830LoadCursorImage\n");
@@ -372,7 +372,7 @@ static Bool I830UseHWCursorARGB (ScreenP
    for (i = 0; i < xf86_config->num_crtc; i++) {
       I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private;
 
-      if (!intel_crtc->cursor_mem_argb.Start)
+      if (!intel_crtc->cursor_mem_argb->offset)
 	 return FALSE;
    }
 
@@ -389,7 +389,8 @@ static void I830CRTCLoadCursorARGB (xf86
 {
    I830Ptr pI830 = I830PTR(crtc->scrn);
    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
-   CARD32 *dst = (CARD32 *) (pI830->FbBase + intel_crtc->cursor_mem_argb.Start);
+   CARD32 *dst = (CARD32 *) (pI830->FbBase +
+			     intel_crtc->cursor_mem_argb->offset);
    CARD32 *image = (CARD32 *)pCurs->bits->argb;
    int x, y, w, h;
 
diff --git a/src/i830_display.c b/src/i830_display.c
index 2e84705..a09d96a 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -345,10 +345,10 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x,
     if (crtc->rotatedData != NULL) {
 	Start = (char *)crtc->rotatedData - (char *)pI830->FbBase;
     } else if (I830IsPrimary(pScrn)) {
-	Start = pI830->FrontBuffer.Start;
+	Start = pI830->front_buffer->offset;
     } else {
 	I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
-	Start = pI8301->FrontBuffer2.Start;
+	Start = pI8301->front_buffer_2->offset;
     }
 
     if (IS_I965G(pI830)) {
@@ -1012,7 +1012,7 @@ i830_crtc_shadow_allocate (xf86CrtcPtr c
 		       "Couldn't allocate shadow memory for rotated CRTC\n");
 	    return NULL;
 	}
-	rotate_offset = pI830->FrontBuffer.Start +
+	rotate_offset = pI830->front_buffer->offset +
 	    intel_crtc->rotate_mem_xaa->offset * pI830->cpp;
     }
 #endif /* I830_USE_XAA */
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 70e7e49..9e3f378 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -145,17 +145,17 @@ I830InitDma(ScrnInfoPtr pScrn)
    memset(&info, 0, sizeof(drmI830Init));
    info.func = I830_INIT_DMA;
 
-   info.ring_start = ring->mem.Start + pI830->LinearAddr;
-   info.ring_end = ring->mem.End + pI830->LinearAddr;
-   info.ring_size = ring->mem.Size;
+   info.ring_start = ring->mem->offset + pI830->LinearAddr;
+   info.ring_end = ring->mem->end + pI830->LinearAddr;
+   info.ring_size = ring->mem->size;
 
    info.mmio_offset = (unsigned int)pI830DRI->regs;
 
    info.sarea_priv_offset = sizeof(XF86DRISAREARec);
 
-   info.front_offset = pI830->FrontBuffer.Start;
-   info.back_offset = pI830->BackBuffer.Start;
-   info.depth_offset = pI830->DepthBuffer.Start;
+   info.front_offset = pI830->front_buffer->offset;
+   info.back_offset = pI830->back_buffer->offset;
+   info.depth_offset = pI830->depth_buffer->offset;
    info.w = pScrn->virtualX;
    info.h = pScrn->virtualY;
    info.pitch = pI830->displayWidth;
@@ -509,7 +509,7 @@ I830DRIScreenInit(ScreenPtr pScreen)
    pDRIInfo->ddxDriverPatchVersion = I830_PATCHLEVEL;
 #if 1 /* Remove this soon - see bug 5714 */
    pDRIInfo->frameBufferPhysicalAddress = (char *) pI830->LinearAddr +
-					  pI830->FrontBuffer.Start;
+					  pI830->front_buffer->offset;
    pDRIInfo->frameBufferSize = ROUND_TO_PAGE(pScrn->displayWidth *
 					     pScrn->virtualY * pI830->cpp);
 #else
@@ -829,8 +829,8 @@ I830DRIDoMappings(ScreenPtr pScreen)
 	      (int)pI830DRI->regs);
 
    if (drmAddMap(pI830->drmSubFD,
-		 (drm_handle_t)pI830->LpRing->mem.Start + pI830->LinearAddr,
-		 pI830->LpRing->mem.Size, DRM_AGP, 0,
+		 (drm_handle_t)pI830->LpRing->mem->offset + pI830->LinearAddr,
+		 pI830->LpRing->mem->size, DRM_AGP, 0,
 		 (drmAddress) &pI830->ring_map) < 0) {
       xf86DrvMsg(pScreen->myNum, X_ERROR,
 		 "[drm] drmAddMap(ring_map) failed. Disabling DRI\n");
@@ -1325,10 +1325,10 @@ I830DRIShadowUpdate (ScreenPtr pScreen, 
       OUT_RING(br13);
       OUT_RING((pbox->y1 << 16) | pbox->x1);
       OUT_RING((pbox->y2 << 16) | pbox->x2);
-      OUT_RING(pI830->BackBuffer.Start);
+      OUT_RING(pI830->back_buffer->offset);
       OUT_RING((pbox->y1 << 16) | pbox->x1);
       OUT_RING(br13 & 0xffff);
-      OUT_RING(pI830->FrontBuffer.Start);
+      OUT_RING(pI830->front_buffer->offset);
       ADVANCE_LP_RING();
    }
 }
@@ -1360,10 +1360,10 @@ I830EnablePageFlip(ScreenPtr pScreen)
       OUT_RING(br13);
       OUT_RING(0);
       OUT_RING((pScrn->virtualY << 16) | pScrn->virtualX);
-      OUT_RING(pI830->BackBuffer.Start);
+      OUT_RING(pI830->back_buffer->offset);
       OUT_RING(0);
       OUT_RING(br13 & 0xffff);
-      OUT_RING(pI830->FrontBuffer.Start);
+      OUT_RING(pI830->front_buffer->offset);
       ADVANCE_LP_RING();
 
       pSAREAPriv->pf_active = 1;
@@ -1448,8 +1448,8 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, 
    sarea->depth_tiled = pI830->depth_tiled;
    sarea->rotated_tiled = FALSE;
 
-   sarea->front_offset = pI830->FrontBuffer.Start;
-   /* Don't use FrontBuffer.Size here as it includes the pixmap cache area
+   sarea->front_offset = pI830->front_buffer->offset;
+   /* Don't use front_buffer->size here as it includes the pixmap cache area
     * Instead, calculate the entire framebuffer.
     */
    sarea->front_size = pI830->displayWidth * pScrn->virtualY * pI830->cpp;
@@ -1460,12 +1460,12 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, 
 
    sarea->width = pScreen->width;
    sarea->height = pScreen->height;
-   sarea->back_offset = pI830->BackBuffer.Start;
-   sarea->back_size = pI830->BackBuffer.Size;
-   sarea->depth_offset = pI830->DepthBuffer.Start;
-   sarea->depth_size = pI830->DepthBuffer.Size;
-   sarea->tex_offset = pI830->TexMem.Start;
-   sarea->tex_size = pI830->TexMem.Size;
+   sarea->back_offset = pI830->back_buffer->offset;
+   sarea->back_size = pI830->back_buffer->size;
+   sarea->depth_offset = pI830->depth_buffer->offset;
+   sarea->depth_size = pI830->depth_buffer->size;
+   sarea->tex_offset = pI830->textures->offset;
+   sarea->tex_size = pI830->textures->size;
    sarea->log_tex_granularity = pI830->TexGranularity;
    sarea->pitch = pScrn->displayWidth;
    sarea->virtualX = pScrn->virtualX;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index e46c057..50fe2a6 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -534,7 +534,7 @@ I830MapMem(ScrnInfoPtr pScrn)
       return FALSE;
 
    if (I830IsPrimary(pScrn))
-   pI830->LpRing->virtual_start = pI830->FbBase + pI830->LpRing->mem.Start;
+   pI830->LpRing->virtual_start = pI830->FbBase + pI830->LpRing->mem->offset;
 
    return TRUE;
 }
@@ -755,9 +755,6 @@ PreInitCleanup(ScrnInfoPtr pScrn)
       if (pI830->LpRing)
          xfree(pI830->LpRing);
       pI830->LpRing = NULL;
-      if (pI830->OverlayMem)
-         xfree(pI830->OverlayMem);
-      pI830->OverlayMem = NULL;
       if (pI830->overlayOn)
          xfree(pI830->overlayOn);
       pI830->overlayOn = NULL;
@@ -836,6 +833,13 @@ I830ReduceMMSize(ScrnInfoPtr pScrn, unsi
 }
 #endif
 
+/**
+ * This is called per zaphod head (so usually just once) to do initialization
+ * before the Screen is created.
+ *
+ * This code generally covers probing, module loading, option handling,
+ * initial memory layout measurement, card mapping, and RandR setup.
+ */
 static Bool
 I830PreInit(ScrnInfoPtr pScrn, int flags)
 {
@@ -846,12 +850,12 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    rgb defaultWeight = { 0, 0, 0 };
    EntityInfoPtr pEnt;
    I830EntPtr pI830Ent = NULL;					
-   int mem;
+   int sys_mem;
    int flags24;
    int i;
    char *s;
    pointer pVBEModule = NULL;
-   Bool enable;
+   Bool enable, allocation_done;
    const char *chipname;
    int num_pipe;
    int max_width, max_height;
@@ -1187,41 +1191,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%d display pipe%s available.\n",
 	      num_pipe, num_pipe > 1 ? "s" : "");
 
-   /*
-    * Get the pre-allocated (stolen) memory size.
-    */
-   pI830->StolenMemory.Size = I830DetectMemory(pScrn);
-   pI830->StolenMemory.Start = 0;
-   pI830->StolenMemory.End = pI830->StolenMemory.Size;
-
-   /* Find the maximum amount of agpgart memory available. */
-   if (I830IsPrimary(pScrn)) {
-      mem = I830CheckAvailableMemory(pScrn);
-      pI830->StolenOnly = FALSE;
-   } else {
-      /* videoRam isn't used on the second head, but faked */
-      mem = pI830->entityPrivate->pScrn_1->videoRam;
-      pI830->StolenOnly = TRUE;
-   }
-
-   if (mem <= 0) {
-      if (pI830->StolenMemory.Size <= 0) {
-	 /* Shouldn't happen. */
-	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		 "/dev/agpgart is either not available, or no memory "
-		 "is available\nfor allocation, "
-		 "and no pre-allocated memory is available.\n");
-	 PreInitCleanup(pScrn);
-	 return FALSE;
-      }
-      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		 "/dev/agpgart is either not available, or no memory "
-		 "is available\nfor allocation.  "
-		 "Using pre-allocated memory only.\n");
-      mem = 0;
-      pI830->StolenOnly = TRUE;
-   }
-
    if (xf86ReturnOptValBool(pI830->Options, OPTION_NOACCEL, FALSE)) {
       pI830->noAccel = TRUE;
    }
@@ -1358,8 +1327,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    }
    RestoreHWState(pScrn);
 
-   pScrn->displayWidth = (pScrn->virtualX + 63) & ~63;
-
    /* XXX This should go away, replaced by xf86Crtc.c support for it */
    pI830->rotation = RR_Rotate_0;
 
@@ -1384,12 +1351,21 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    } else
       pI830->checkDevices = FALSE;
 
+   pScrn->displayWidth = (pScrn->virtualX + 63) & ~63;
+
+   pI830->stolen_size = I830DetectMemory(pScrn);
+
    /*
     * The "VideoRam" config file parameter specifies the maximum amount of
     * memory that will be used/allocated.  When not present, we allow the
     * driver to allocate as much memory as it wishes to satisfy its
-    * allocations, but if agpgart support isn't available (StolenOnly == TRUE),
-    * it gets limited to the amount of pre-allocated ("stolen") memory.
+    * allocations, but if agpgart support isn't available, it gets limited
+    * to the amount of pre-allocated ("stolen") memory.
+    *
+    * Note that in using this value for allocator initialization, we're
+    * limiting aperture allocation to the VideoRam option, rather than limiting
+    * actual memory allocation, so alignment and things will cause less than
+    * VideoRam to be actually used.
     */
    if (!pI830->pEnt->device->videoRam) {
       from = X_DEFAULT;
@@ -1399,55 +1375,59 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       pScrn->videoRam = pI830->pEnt->device->videoRam;
    }
 
-   /* Make sure it's on a page boundary */
-   if (pScrn->videoRam & 3) {
-      xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VideoRam reduced to %d KB "
-		 "(page aligned - was %d KB)\n",
-		 pScrn->videoRam & ~3, pScrn->videoRam);
-      pScrn->videoRam &= ~3;
-   }
-
-   DPRINTF(PFX,
-	   "Available memory: %dk\n"
-	   "Requested memory: %dk\n", mem, pScrn->videoRam);
-
-
-   if (mem + (pI830->StolenMemory.Size / 1024) < pScrn->videoRam) {
-      pScrn->videoRam = mem + (pI830->StolenMemory.Size / 1024);
-      from = X_PROBED;
-      if (mem + (pI830->StolenMemory.Size / 1024) <
-	  pI830->pEnt->device->videoRam) {
+   sys_mem = I830CheckAvailableMemory(pScrn);
+   if (sys_mem == -1) {
+      if (pScrn->videoRam > pI830->stolen_size / KB(1)) {
 	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		    "VideoRAM reduced to %d kByte "
-		    "(limited to available sysmem)\n", pScrn->videoRam);
+		    "/dev/agpgart is either not available, or no memory "
+		    "is available\nfor allocation.  "
+		    "Using pre-allocated memory only.\n");
+	 pScrn->videoRam = pI830->stolen_size / KB(1);
+      }
+      pI830->StolenOnly = TRUE;
+   } else {
+      if (sys_mem + (pI830->stolen_size / 1024) < pScrn->videoRam) {
+	 pScrn->videoRam = sys_mem + (pI830->stolen_size / 1024);
+	 from = X_PROBED;
+	 if (sys_mem + (pI830->stolen_size / 1024) <
+	     pI830->pEnt->device->videoRam)
+	 {
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		       "VideoRAM reduced to %d kByte "
+		       "(limited to available sysmem)\n", pScrn->videoRam);
+	 }
       }
    }
 
    if (pScrn->videoRam > pI830->FbMapSize / 1024) {
       pScrn->videoRam = pI830->FbMapSize / 1024;
-      if (pI830->FbMapSize / 1024 < pI830->pEnt->device->videoRam)
+      if (pI830->FbMapSize / 1024 < pI830->pEnt->device->videoRam) {
 	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		    "VideoRam reduced to %d kByte (limited to aperture size)\n",
+		    "VideoRam reduced to %d kByte (limited to aperture "
+		    "size)\n",
 		    pScrn->videoRam);
+      }
    }
 
-   xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
-	      "Pre-allocated VideoRam: %ld kByte\n",
-	      pI830->StolenMemory.Size / 1024);
-   xf86DrvMsg(pScrn->scrnIndex, from, "Potential VideoRam: %d kByte\n",
-	      pScrn->videoRam);
-
-   pI830->TotalVideoRam = KB(pScrn->videoRam);
+   /* Make sure it's on a page boundary */
+   if (pScrn->videoRam & 3) {
+      xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VideoRam reduced to %d KB "
+		 "(page aligned - was %d KB)\n",
+		 pScrn->videoRam & ~3, pScrn->videoRam);
+      pScrn->videoRam &= ~3;
+   }
 
-   /*
-    * If the requested videoRam amount is less than the stolen memory size,
-    * reduce the stolen memory size accordingly.
-    */
-   if (pI830->StolenMemory.Size > pI830->TotalVideoRam) {
-      pI830->StolenMemory.Size = pI830->TotalVideoRam;
-      pI830->StolenMemory.End = pI830->TotalVideoRam;
+   if (!i830_allocator_init(pScrn, 0, pScrn->videoRam * KB(1))) {
+      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		 "Couldn't initialize video memory allocator\n");
+      PreInitCleanup(pScrn);
+      return FALSE;
    }
 
+   xf86DrvMsg(pScrn->scrnIndex,
+	      pI830->pEnt->device->videoRam ? X_CONFIG : X_DEFAULT,
+	      "VideoRam: %d KB\n", pScrn->videoRam);
+
    if (xf86GetOptValInteger(pI830->Options, OPTION_CACHE_LINES,
 			    &(pI830->CacheLines))) {
       xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Requested %d cache lines\n",
@@ -1502,12 +1482,10 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 
    /* Alloc our pointers for the primary head */
    if (I830IsPrimary(pScrn)) {
-      pI830->LpRing = xalloc(sizeof(I830RingBuffer));
-      pI830->OverlayMem = xalloc(sizeof(I830MemRange));
+      pI830->LpRing = xcalloc(1, sizeof(I830RingBuffer));
       pI830->overlayOn = xalloc(sizeof(Bool));
       pI830->used3D = xalloc(sizeof(int));
-      if (!pI830->LpRing ||
-          !pI830->OverlayMem || !pI830->overlayOn || !pI830->used3D) {
+      if (!pI830->LpRing || !pI830->overlayOn || !pI830->used3D) {
          xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		 "Could not allocate primary data structures.\n");
          PreInitCleanup(pScrn);
@@ -1527,9 +1505,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    if (IS_I965G(pI830))
       pI830->CursorNeedsPhysical = FALSE;
 
-   /* Force ring buffer to be in low memory for all chipsets */
-   pI830->NeedRingBufferLow = TRUE;
-
    /*
     * XXX If we knew the pre-initialised GTT format for certain, we could
     * probably figure out the physical address even in the StolenOnly case.
@@ -1548,21 +1523,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       pI830->SWCursor = TRUE;
    }
 
-   /*
-    * Reduce the maximum videoram available for video modes by the ring buffer,
-    * minimum scratch space and HW cursor amounts.
-    */
-   if (!pI830->SWCursor) {
-      pScrn->videoRam -= (HWCURSOR_SIZE / 1024);
-      pScrn->videoRam -= (HWCURSOR_SIZE_ARGB / 1024);
-   }
-   if (!pI830->XvDisabled)
-      pScrn->videoRam -= (OVERLAY_SIZE / 1024);
-   if (!pI830->noAccel) {
-      pScrn->videoRam -= (PRIMARY_RINGBUFFER_SIZE / 1024);
-      pScrn->videoRam -= (MIN_SCRATCH_BUFFER_SIZE / 1024);
-   }
-
    if (!xf86RandR12PreInit (pScrn))
    {
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "RandR initialization failure\n");
@@ -1579,23 +1539,19 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 
    pI830->disableTiling = FALSE;
 
+#if defined(XF86DRI)
    /*
     * If DRI is potentially usable, check if there is enough memory available
     * for it, and if there's also enough to allow tiling to be enabled.
     */
 
-#if defined(XF86DRI)
    if (!I830CheckDRIAvailable(pScrn)) {
       pI830->directRenderingDisabled = TRUE;
       pI830->mmSize = 0;
-   } else if (pScrn->videoRam > pI830->FbMapSize / 1024 - pI830->mmSize) {
-      I830ReduceMMSize(pScrn, pI830->FbMapSize - KB(pScrn->videoRam), 
-		       "to make room for video memory");
    }
 
    if (I830IsPrimary(pScrn) && !pI830->directRenderingDisabled) {
       int savedDisplayWidth = pScrn->displayWidth;
-      int memNeeded = 0;
       Bool tiled = FALSE;
 
 #ifdef I830_XV
@@ -1612,12 +1568,14 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 	    ~(tile_pixels - 1);
 	 tiled = TRUE;
       } else {
-	 /* Good pitches to allow tiling.  Don't care about pitches < 1024. */
+	 /* Good pitches to allow tiling.  Don't care about pitches < 1024
+	  * pixels.
+	  */
 	 static const int pitches[] = {
-	    KB(1),
-	    KB(2),
-	    KB(4),
-	    KB(8),
+	    1024,
+	    2048,
+	    4096,
+	    8192,
 	    0
 	 };
 
@@ -1630,120 +1588,72 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 	 }
       }
 
+      allocation_done = FALSE;
       /*
        * If the displayWidth is a tilable pitch, test if there's enough
        * memory available to enable tiling.
        */
       savedMMSize = pI830->mmSize;
       if (tiled) {
-      retry_dryrun:
-	 I830ResetAllocations(pScrn, 0);
-	 if (I830Allocate2DMemory(pScrn, ALLOCATE_DRY_RUN | ALLOC_INITIAL) &&
-	     I830Allocate3DMemory(pScrn, ALLOCATE_DRY_RUN)) {
-	    memNeeded = I830GetExcessMemoryAllocations(pScrn);
-	    if (memNeeded > 0 || pI830->MemoryAperture.Size < 0) {
-	       if (memNeeded > 0) {
-		  xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-			     "%d kBytes additional video memory is "
-			     "required to\n\tenable tiling mode for DRI.\n",
-			     (memNeeded + 1023) / 1024);
-	       }
-	       if (pI830->MemoryAperture.Size < 0) {		  
-		  if (KB(pI830->mmSize) > I830_MM_MINPAGES * GTT_PAGE_SIZE) {
-		     I830ReduceMMSize(pScrn, I830_MM_MINPAGES * GTT_PAGE_SIZE,
-				      "to make room in AGP aperture for tiling.");
-		     goto retry_dryrun;
-		  }
-		  /* XXX */
-		  xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-			     "Allocation with DRI tiling enabled would "
-			     "exceed the\n"
-			     "\tmemory aperture size (%ld kB) by %ld kB.\n"
-			     "\tReduce VideoRam amount to avoid this!\n",
-			     pI830->FbMapSize / 1024,
-			     -pI830->MemoryAperture.Size / 1024);
-	       }
-	       pScrn->displayWidth = savedDisplayWidth;
-	       pI830->allowPageFlip = FALSE;
-	    } else if (pScrn->displayWidth != savedDisplayWidth) {
-	       xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-			  "Increasing the scanline pitch to allow tiling mode "
-			  "(%d -> %d).\n",
-			  savedDisplayWidth, pScrn->displayWidth);
+retry_dryrun:
+	 i830_reset_allocations(pScrn);
+	 if (!i830_allocate_2d_memory(pScrn,
+				      ALLOCATE_DRY_RUN | ALLOC_INITIAL) ||
+	     !i830_allocate_3d_memory(pScrn, ALLOCATE_DRY_RUN))
+	 {
+	    /* Failure to set up allocations, so try reducing the DRI memory
+	     * manager's size if we haven't yet.
+	     */
+	    if (KB(pI830->mmSize) > I830_MM_MINPAGES * GTT_PAGE_SIZE) {
+	       I830ReduceMMSize(pScrn, I830_MM_MINPAGES * GTT_PAGE_SIZE,
+				"to make room for tiling.");
+	       goto retry_dryrun;
 	    }
-	 } else {
-	    memNeeded = 0;
-	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		       "Unexpected dry run allocation failure (1).\n");
+	    /* Otherwise, disable tiling. */
+	    pScrn->displayWidth = savedDisplayWidth;
+	    pI830->allowPageFlip = FALSE;
+	 } else if (pScrn->displayWidth != savedDisplayWidth) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		       "Increasing the scanline pitch to allow tiling mode "
+		       "(%d -> %d).\n",
+		       savedDisplayWidth, pScrn->displayWidth);
+	    allocation_done = TRUE;
 	 }
       }
-      if (memNeeded > 0 || pI830->MemoryAperture.Size < 0) {
+      if (!allocation_done) {
 	 /*
 	  * Tiling can't be enabled.  Check if there's enough memory for DRI
 	  * without tiling.
 	  */
 	 pI830->mmSize = savedMMSize;
 	 pI830->disableTiling = TRUE;
-      retry_dryrun2:
-	 I830ResetAllocations(pScrn, 0);
-	 if (I830Allocate2DMemory(pScrn, ALLOCATE_DRY_RUN | ALLOC_INITIAL) &&
-	     I830Allocate3DMemory(pScrn, ALLOCATE_DRY_RUN | ALLOC_NO_TILING)) {
-	    memNeeded = I830GetExcessMemoryAllocations(pScrn);
-	    if (memNeeded > 0 || pI830->MemoryAperture.Size < 0) {
-	       if (memNeeded > 0) {
-		  xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-			     "%d kBytes additional video memory is required "
-			     "to enable DRI.\n",
-			     (memNeeded + 1023) / 1024);
-	       }
-	       if (pI830->MemoryAperture.Size < 0) {
-		  if (KB(pI830->mmSize) > I830_MM_MINPAGES * GTT_PAGE_SIZE) {
-		     I830ReduceMMSize(pScrn, I830_MM_MINPAGES * GTT_PAGE_SIZE,
-				      "to save AGP aperture space for video memory.");
-		     goto retry_dryrun2;
-		  }
-		  xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-			     "Allocation with DRI enabled would "
-			     "exceed the\n"
-			     "\tmemory aperture size (%ld kB) by %ld kB.\n"
-			     "\tReduce VideoRam amount to avoid this!\n",
-			     pI830->FbMapSize / 1024,
-			     -pI830->MemoryAperture.Size / 1024);
-	       }
-	       pI830->mmSize = 0;
-	       pI830->directRenderingDisabled = TRUE;
-	       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling DRI.\n");
+retry_dryrun2:
+	 i830_reset_allocations(pScrn);
+	 if (!i830_allocate_2d_memory(pScrn,
+				      ALLOCATE_DRY_RUN | ALLOC_INITIAL) ||
+	     !i830_allocate_3d_memory(pScrn, ALLOCATE_DRY_RUN))
+	 {
+	    /* Failure to set up allocations, so try reducing the DRI memory
+	     * manager's size if we haven't yet.
+	     */
+	    if (KB(pI830->mmSize) > I830_MM_MINPAGES * GTT_PAGE_SIZE) {
+	       I830ReduceMMSize(pScrn, I830_MM_MINPAGES * GTT_PAGE_SIZE,
+				"to save AGP aperture space for video "
+				"memory.");
+	       goto retry_dryrun2;
 	    }
-	 } else {
 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		       "Unexpected dry run allocation failure (2).\n");
+		       "Not enough video memory.  Disabling DRI.");
+	    pI830->mmSize = 0;
+	    pI830->directRenderingDisabled = TRUE;
+	 } else {
+	    allocation_done = TRUE;
 	 }
       }
    } else
 #endif
       pI830->disableTiling = TRUE; /* no DRI - so disableTiling */
 
-   if (pI830->pEnt->device->videoRam == 0) {
-      int default_videoram;
-
-      /* Now that we've sized the allocations, reduce our default VideoRam
-       * allocation from the aperture size to just what we need to cover our
-       * allocations.  Only, put in some slop for alignment and such.
-       */
-      default_videoram = pI830->StolenPool.Total.Size + pI830->allocatedMemory;
-      default_videoram += KB(512); /* slop */
-      /* align to 1MB increments */
-      default_videoram = (default_videoram + MB(1) - 1) / MB(1) * MB(1);
-
-      if (default_videoram < KB(pScrn->videoRam)) {
-	 pScrn->videoRam = default_videoram / KB(1);
-	 pI830->TotalVideoRam = KB(pScrn->videoRam);
-      }
-   }
-   xf86DrvMsg(pScrn->scrnIndex,
-	      pI830->pEnt->device->videoRam ? X_CONFIG : X_DEFAULT,
-	      "VideoRam: %d KB\n", pScrn->videoRam);
-
    if (!IS_I965G(pI830) && pScrn->displayWidth > 2048) {
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		 "Cannot support DRI with frame buffer width > 2048.\n");
@@ -1934,18 +1844,18 @@ SetFenceRegs(ScrnInfoPtr pScrn)
 
    if (IS_I965G(pI830)) {
       for (i = 0; i < FENCE_NEW_NR; i++) {
-         OUTREG(FENCE_NEW + i * 8, pI830->ModeReg.Fence[i]);
-         OUTREG(FENCE_NEW + 4 + i * 8, pI830->ModeReg.Fence[i+FENCE_NEW_NR]);
+         OUTREG(FENCE_NEW + i * 8, pI830->fence[i]);
+         OUTREG(FENCE_NEW + 4 + i * 8, pI830->fence[i+FENCE_NEW_NR]);
          if (I810_DEBUG & DEBUG_VERBOSE_VGA) {
-	    ErrorF("Fence Start Register : %x\n", pI830->ModeReg.Fence[i]);
-	    ErrorF("Fence End Register : %x\n", pI830->ModeReg.Fence[i+FENCE_NEW_NR]);
+	    ErrorF("Fence Start Register : %x\n", pI830->fence[i]);
+	    ErrorF("Fence End Register : %x\n", pI830->fence[i+FENCE_NEW_NR]);
          }
       }
    } else {
       for (i = 0; i < FENCE_NR; i++) {
-         OUTREG(FENCE + i * 4, pI830->ModeReg.Fence[i]);
+         OUTREG(FENCE + i * 4, pI830->fence[i]);
          if (I810_DEBUG & DEBUG_VERBOSE_VGA)
-	    ErrorF("Fence Register : %x\n", pI830->ModeReg.Fence[i]);
+	    ErrorF("Fence Register : %x\n", pI830->fence[i]);
       }
    }
 }
@@ -1970,25 +1880,22 @@ SetRingRegs(ScrnInfoPtr pScrn)
    OUTREG(LP_RING + RING_TAIL, 0);
    OUTREG(LP_RING + RING_HEAD, 0);
 
-   if ((long)(pI830->LpRing->mem.Start & I830_RING_START_MASK) !=
-       pI830->LpRing->mem.Start) {
-      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		 "I830SetRingRegs: Ring buffer start (%lx) violates its "
-		 "mask (%x)\n", pI830->LpRing->mem.Start, I830_RING_START_MASK);
-   }
+   assert((pI830->LpRing->mem->offset & I830_RING_START_MASK) ==
+	   pI830->LpRing->mem->offset);
+
    /* Don't care about the old value.  Reserved bits must be zero anyway. */
-   itemp = pI830->LpRing->mem.Start & I830_RING_START_MASK;
+   itemp = pI830->LpRing->mem->offset;
    OUTREG(LP_RING + RING_START, itemp);
 
-   if (((pI830->LpRing->mem.Size - 4096) & I830_RING_NR_PAGES) !=
-       pI830->LpRing->mem.Size - 4096) {
+   if (((pI830->LpRing->mem->size - 4096) & I830_RING_NR_PAGES) !=
+       pI830->LpRing->mem->size - 4096) {
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		 "I830SetRingRegs: Ring buffer size - 4096 (%lx) violates its "
-		 "mask (%x)\n", pI830->LpRing->mem.Size - 4096,
+		 "mask (%x)\n", pI830->LpRing->mem->size - 4096,
 		 I830_RING_NR_PAGES);
    }
    /* Don't care about the old value.  Reserved bits must be zero anyway. */
-   itemp = (pI830->LpRing->mem.Size - 4096) & I830_RING_NR_PAGES;
+   itemp = (pI830->LpRing->mem->size - 4096) & I830_RING_NR_PAGES;
    itemp |= (RING_NO_REPORT | RING_VALID);
    OUTREG(LP_RING + RING_LEN, itemp);
    I830RefreshRing(pScrn);
@@ -2246,13 +2153,12 @@ static void
 InitRegisterRec(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
-   I830RegPtr i830Reg = &pI830->ModeReg;
    int i;
 
    if (!I830IsPrimary(pScrn)) return;
 
    for (i = 0; i < 8; i++)
-      i830Reg->Fence[i] = 0;
+      pI830->fence[i] = 0;
 }
 
 static void
@@ -2361,14 +2267,12 @@ IntelEmitInvarientState(ScrnInfoPtr pScr
    }
 #endif
 
-   ctx_addr = pI830->ContextMem.Start;
-   /* Align to a 2k boundry */
-   ctx_addr = ((ctx_addr + 2048 - 1) / 2048) * 2048;
-
+   ctx_addr = pI830->logical_context->offset;
+   assert((pI830->logical_context->offset & 2047) == 0);
    {
       BEGIN_LP_RING(2);
       OUT_RING(MI_SET_CONTEXT);
-      OUT_RING(ctx_addr |
+      OUT_RING(pI830->logical_context->offset |
 	       CTXT_NO_RESTORE |
 	       CTXT_PALETTE_SAVE_DISABLE | CTXT_PALETTE_RESTORE_DISABLE);
       ADVANCE_LP_RING();
@@ -2525,14 +2429,11 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    if (I830IsPrimary(pScrn)) {
       if (!pI830->LpRing)
          pI830->LpRing = xalloc(sizeof(I830RingBuffer));
-      if (!pI830->OverlayMem)
-         pI830->OverlayMem = xalloc(sizeof(I830MemRange));
       if (!pI830->overlayOn)
          pI830->overlayOn = xalloc(sizeof(Bool));
       if (!pI830->used3D)
          pI830->used3D = xalloc(sizeof(int));
-      if (!pI830->LpRing ||
-          !pI830->OverlayMem || !pI830->overlayOn || !pI830->used3D) {
+      if (!pI830->LpRing || !pI830->overlayOn || !pI830->used3D) {
          xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		 "Could not allocate primary data structures.\n");
          return FALSE;
@@ -2546,7 +2447,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    if (!I830IsPrimary(pScrn)) {
       pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
       pI830->LpRing = pI8301->LpRing;
-      pI830->OverlayMem = pI8301->OverlayMem;
+      pI830->overlay_regs = pI8301->overlay_regs;
       pI830->overlayOn = pI8301->overlayOn;
       pI830->used3D = pI8301->used3D;
    }
@@ -2579,14 +2480,14 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 #endif
 
    if (I830IsPrimary(pScrn)) {
-      I830ResetAllocations(pScrn, 0);
+      i830_reset_allocations(pScrn);
 
-      if (!I830Allocate2DMemory(pScrn, ALLOC_INITIAL))
+      if (!i830_allocate_2d_memory(pScrn, ALLOC_INITIAL))
 	return FALSE;
    }
 
    if (!pI830->noAccel) {
-      if (pI830->LpRing->mem.Size == 0) {
+      if (pI830->LpRing->mem->size == 0) {
 	  xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		     "Disabling acceleration because the ring buffer "
 		      "allocation failed.\n");
@@ -2601,7 +2502,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 		    "needs 2D acceleration.\n");
 	 pI830->XvEnabled = FALSE;
       }
-      if (pI830->OverlayMem->Physical == 0) {
+      if (pI830->overlay_regs == NULL) {
 	  xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		     "Disabling Xv because the overlay register buffer "
 		      "allocation failed.\n");
@@ -2639,8 +2540,8 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 
    if (pI830->directRenderingEnabled) {
       pI830->directRenderingEnabled =
-	 I830Allocate3DMemory(pScrn,
-			      pI830->disableTiling ? ALLOC_NO_TILING : 0);
+	 i830_allocate_3d_memory(pScrn,
+				 pI830->disableTiling ? ALLOC_NO_TILING : 0);
       if (!pI830->directRenderingEnabled)
 	  I830DRICloseScreen(pScreen);
    }
@@ -2649,27 +2550,18 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    pI830->directRenderingEnabled = FALSE;
 #endif
 
-   /*
+   /* XXX:
     * After the 3D allocations have been done, see if there's any free space
     * that can be added to the framebuffer allocation.
     */
    if (I830IsPrimary(pScrn)) {
-      I830Allocate2DMemory(pScrn, 0);
-
-      DPRINTF(PFX, "assert(if(!I830DoPoolAllocation(pScrn, pI830->StolenPool)))\n");
-      if (!I830DoPoolAllocation(pScrn, &(pI830->StolenPool)))
-         return FALSE;
-
-      DPRINTF(PFX, "assert( if(!I830FixupOffsets(pScrn)) )\n");
-      if (!I830FixupOffsets(pScrn))
-         return FALSE;
+      i830_allocate_2d_memory(pScrn, 0);
    }
 
+   i830_describe_allocations(pScrn, 1, "");
 #ifdef XF86DRI
-   if (pI830->directRenderingEnabled) {
-      I830SetupMemoryTiling(pScrn);
+   if (pI830->directRenderingEnabled)
       pI830->directRenderingEnabled = I830DRIDoMappings(pScreen);
-   }
 #endif
 
    DPRINTF(PFX, "assert( if(!I830MapMem(pScrn)) )\n");
@@ -2679,9 +2571,9 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    pScrn->memPhysBase = (unsigned long)pI830->FbBase;
 
    if (I830IsPrimary(pScrn)) {
-      pScrn->fbOffset = pI830->FrontBuffer.Start;
+      pScrn->fbOffset = pI830->front_buffer->offset;
    } else {
-      pScrn->fbOffset = pI8301->FrontBuffer2.Start;
+      pScrn->fbOffset = pI8301->front_buffer_2->offset;
    }
 
    pI830->xoffset = (pScrn->fbOffset / pI830->cpp) % pScrn->displayWidth;
@@ -2704,13 +2596,13 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 
 	 if (pI830->LinearAlloc &&
 	     xf86InitFBManagerLinear(pScreen,
-				     pI830->LinearMem.Offset / pI830->cpp,
-				     pI830->LinearMem.Size / pI830->cpp))
+				     pI830->xaa_linear->offset / pI830->cpp,
+				     pI830->xaa_linear->size / pI830->cpp))
 	 {
             xf86DrvMsg(scrnIndex, X_INFO,
 		       "Using %ld bytes of offscreen memory for linear "
-		       "(offset=0x%lx)\n", pI830->LinearMem.Size,
-		       pI830->LinearMem.Offset);
+		       "(offset=0x%lx)\n", pI830->xaa_linear->size,
+		       pI830->xaa_linear->offset);
 	 }
       } else {
 	 if (!I830InitFBManager(pScreen, &(pI8301->FbMemBox2))) {
@@ -2877,27 +2769,24 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    pI830->suspended = FALSE;
 
 #ifdef XF86DRI_MM
-   if (pI830->directRenderingEnabled && (pI830->mmModeFlags & I830_KERNEL_MM)) {
-      unsigned long aperEnd = ROUND_DOWN_TO(pI830->FbMapSize, GTT_PAGE_SIZE) 
-	 / GTT_PAGE_SIZE;
-      unsigned long aperStart = ROUND_TO(pI830->FbMapSize - KB(pI830->mmSize), GTT_PAGE_SIZE) 
-	 / GTT_PAGE_SIZE;
-
-      if (aperEnd < aperStart || aperEnd - aperStart < I830_MM_MINPAGES) {
+   if (pI830->directRenderingEnabled && (pI830->mmModeFlags & I830_KERNEL_MM))
+   {
+      if (pI830->memory_manager == NULL) {
 	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 
 		    "Too little AGP aperture space for DRM memory manager.\n"
-		    "\tPlease increase AGP aperture size from BIOS configuration screen\n"
-		    "\tor decrease the amount of video RAM using option \"VideoRam\".\n"
+		    "\tPlease increase AGP aperture size from BIOS configuration screen.\n"
 		    "\tDisabling DRI.\n");
 	 pI830->directRenderingOpen = FALSE;
 	 I830DRICloseScreen(pScreen);
 	 pI830->directRenderingEnabled = FALSE;
       } else {
 #ifndef XSERVER_LIBDRM_MM
-	 if (I830DrmMMInit(pI830->drmSubFD, aperStart, aperEnd - aperStart,
+	 if (I830DrmMMInit(pI830->drmSubFD, pI830->memory_manager->offset,
+			   pI830->memory_manager->size,
 			   DRM_BO_MEM_TT)) {
 #else
-	 if (drmMMInit(pI830->drmSubFD, aperStart, aperEnd - aperStart,
+	 if (drmMMInit(pI830->drmSubFD, pI830->memory_manager->offset,
+		       pI830->memory_manager->size,
 		       DRM_BO_MEM_TT)) {
 #endif	   
 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 
@@ -2906,12 +2795,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 	    pI830->directRenderingOpen = FALSE;
 	    I830DRICloseScreen(pScreen);
 	    pI830->directRenderingEnabled = FALSE;
-	 } else {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
-		       "Initialized DRM memory manager, %ld AGP pages\n"
-		       "\tat AGP offset 0x%lx\n", 
-		       aperEnd - aperStart,
-		       aperStart);
 	 }
       }
    }
@@ -2968,7 +2851,7 @@ I830LeaveVT(int scrnIndex, int flags)
 
    if (!I830IsPrimary(pScrn)) {
    	I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
-	if (!pI8301->GttBound) {
+	if (!pI8301->gtt_acquired) {
 		return;
 	}
    }
@@ -3002,7 +2885,7 @@ I830LeaveVT(int scrnIndex, int flags)
    i830DumpRegs (pScrn);
 
    if (I830IsPrimary(pScrn))
-      I830UnbindAGPMemory(pScrn);
+      i830_unbind_all_memory(pScrn);
    if (pI830->AccelInfoRec)
       pI830->AccelInfoRec->NeedToSync = FALSE;
 }
@@ -3038,7 +2921,7 @@ I830EnterVT(int scrnIndex, int flags)
 #endif
 
    if (I830IsPrimary(pScrn))
-      if (!I830BindAGPMemory(pScrn))
+      if (!i830_bind_all_memory(pScrn))
          return FALSE;
 
    if (i830_check_error_state(pScrn)) {
@@ -3223,8 +3106,6 @@ I830CloseScreen(int scrnIndex, ScreenPtr
 
       xfree(pI830->LpRing);
       pI830->LpRing = NULL;
-      xfree(pI830->OverlayMem);
-      pI830->OverlayMem = NULL;
       xfree(pI830->overlayOn);
       pI830->overlayOn = NULL;
       xfree(pI830->used3D);
diff --git a/src/i830_exa.c b/src/i830_exa.c
index 42552d4..37fd284 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -318,8 +318,9 @@ I830EXAInit(ScreenPtr pScreen)
     pI830->EXADriverPtr->exa_major = 2;
     pI830->EXADriverPtr->exa_minor = 1;
     pI830->EXADriverPtr->memoryBase = pI830->FbBase;
-    pI830->EXADriverPtr->offScreenBase = pI830->Offscreen.Start;
-    pI830->EXADriverPtr->memorySize = pI830->Offscreen.End;
+    pI830->EXADriverPtr->offScreenBase = pI830->exa_offscreen->offset;
+    pI830->EXADriverPtr->memorySize = pI830->exa_offscreen->offset +
+	pI830->exa_offscreen->size;
 	   
     DPRINTF(PFX, "EXA Mem: memoryBase 0x%x, end 0x%x, offscreen base 0x%x, memorySize 0x%x\n",
 		pI830->EXADriverPtr->memoryBase,
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 1b2af12..93429fb 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -50,6 +50,51 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
  *   Alan Hourihane <alanh at tungstengraphics.com>
  */
 
+/**
+ * @file i830_memory.c
+ *
+ * This is the video memory allocator.  Our memory allocation is different from
+ * other graphics chips, where you have a fixed amount of graphics memory
+ * available that you want to put to the best use.  Instead, we have almost no
+ * memory pre-allocated, and we have to choose an appropriate amount of sytem
+ * memory to use.
+ *
+ * The allocations we might do:
+ *
+ * - Ring buffer
+ * - HW cursor 1
+ * - HW cursor 2
+ * - HW ARGB cursor 1
+ * - HW ARGB cursor 2
+ * - Overlay registers
+ * - XAA linear allocator (optional)
+ * - EXA 965 state buffer
+ * - XAA scratch (screen 1)
+ * - XAA scratch (screen 2, only in zaphod mode)
+ * - Front buffer (screen 1, more is better for XAA)
+ * - Front buffer (screen 2, only in zaphod mode, more is better for XAA)
+ * - Back/depth buffer (3D only)
+ * - Compatibility texture pool (optional, more is always better)
+ * - New texture pool (optional, more is always better.  aperture allocation
+ *     only)
+ * - EXA offscreen pool (more is always better)
+ *
+ * We also want to be able to resize the front/back/depth buffers, and then
+ * resize the EXA and texture memory pools appropriately.
+ *
+ * The user may request a specific amount of memory to be used
+ * (pI830->pEnt->videoRam != 0), in which case allocations have to fit within
+ * that much aperture.  If not, the individual allocations will be
+ * automatically sized, and will be fit within the maximum aperture size.
+ * Only the actual memory used (not alignment padding) will get actual AGP
+ * memory allocated.
+ *
+ * Given that the allocations listed are generally a page or more than a page,
+ * our allocator will only return page-aligned offsets, simplifying the memory
+ * binding process.  For smaller allocations, the acceleration architecture's
+ * linear allocator is preferred.
+ */
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
@@ -62,383 +107,541 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "i830.h"
 #include "i810_reg.h"
 
-static int nextTile = 0;
-static unsigned int tileGeneration = -1;
+#define ALIGN(i,m)    (((i) + (m) - 1) & ~((m) - 1))
+
+enum tile_format {
+    TILING_NONE,
+    TILING_XMAJOR,
+    TILING_YMAJOR
+};
+
+static void i830_set_fence(ScrnInfoPtr pScrn, int nr, unsigned int offset,
+			   unsigned int pitch, unsigned int size,
+			   enum tile_format tile_format);
 
+/**
+ * Returns the fence size for a tiled area of the given size.
+ */
 static unsigned long
-GetBestTileAlignment(unsigned long size)
+i830_get_fence_size(ScrnInfoPtr pScrn, unsigned long size)
 {
+    I830Ptr pI830 = I830PTR(pScrn);
     unsigned long i;
+    unsigned long start;
 
-    for (i = KB(512); i < size; i <<= 1)
-	;
+    if (IS_I965G(pI830)) {
+	/* The 965 can have fences at any page boundary. */
+	return ALIGN(size, GTT_PAGE_SIZE);
+    } else {
+	/* Align the size to a power of two greater than the smallest fence
+	 * size.
+	 */
+	if (IS_I9XX(pI830))
+	    start = MB(1);
+	else
+	    start = KB(512);
 
-    if (i > MB(64))
-	i = MB(64);
+	for (i = start; i < size; i <<= 1)
+	    ;
 
-    return i;
+	return i;
+    }
 }
 
-/*
- * Allocate memory from the given pool.  Grow the pool if needed and if
- * possible.
- */
-static unsigned long
-AllocFromPool(ScrnInfoPtr pScrn, I830MemRange *result, I830MemPool *pool,
-	      long size, unsigned long alignment, int flags)
+static Bool
+i830_bind_memory(ScrnInfoPtr pScrn, i830_memory *mem)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    long needed, start, end;
-    Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
 
-    if (!result || !pool || !size)
-	return 0;
+    if (mem == NULL || mem->key == -1 || mem->bound || !pI830->gtt_acquired)
+	return TRUE;
 
-    /* Calculate how much space is needed. */
-    if (alignment <= GTT_PAGE_SIZE)
-	needed = size;
-    else {
-	if (flags & ALLOCATE_AT_BOTTOM) {
-	    start = ROUND_TO(pool->Free.Start, alignment);
-	    if (flags & ALIGN_BOTH_ENDS)
-		end = ROUND_TO(start + size, alignment);
-	    else
-		end = start + size;
-	    needed = end - pool->Free.Start;
-	} else {				/* allocate at top */
-	    if (flags & ALIGN_BOTH_ENDS)
-		end = ROUND_DOWN_TO(pool->Free.End, alignment);
-	    else
-		end = pool->Free.End;
-
-	    start = ROUND_DOWN_TO(end - size, alignment);
-	    needed = end - start;
-	}
-    }
-    if (needed > pool->Free.Size) {
-	long extra;
-	/* See if the pool can be grown. */
-	if (pI830->StolenOnly && !dryrun)
-	    return 0;
-	extra = needed - pool->Free.Size;
-	extra = ROUND_TO_PAGE(extra);
-	if (extra > pI830->FreeMemory) {
-	    if (dryrun)
-		pI830->FreeMemory = extra;
-	    else
-		return 0;
-	}
-
-	if (!dryrun && ((long)extra > pI830->MemoryAperture.Size))
-	    return 0;
-
-	pool->Free.Size += extra;
-	pool->Free.End += extra;
-	pool->Total.Size += extra;
-	pool->Total.End += extra;
-	pI830->FreeMemory -= extra;
-	pI830->MemoryAperture.Start += extra;
-	pI830->MemoryAperture.Size -= extra;
-    }
-    if (flags & ALLOCATE_AT_BOTTOM) {
-	result->Start = ROUND_TO(pool->Free.Start, alignment);
-	pool->Free.Start += needed;
-	result->End = pool->Free.Start;
+    if (xf86BindGARTMemory(pScrn->scrnIndex, mem->key, mem->agp_offset)) {
+	mem->bound = TRUE;
+	return TRUE;
     } else {
-	result->Start = ROUND_DOWN_TO(pool->Free.End - size, alignment);
-	pool->Free.End -= needed;
-	result->End = result->Start + needed;
-    }
-    pool->Free.Size = pool->Free.End - pool->Free.Start;
-    result->Size = result->End - result->Start;
-    result->Pool = pool;
-    result->Alignment = alignment;
-    return needed;
+	return FALSE;
+    }
+
+    return TRUE;
 }
 
-static unsigned long
-AllocFromAGP(ScrnInfoPtr pScrn, I830MemRange *result, long size,
-	     unsigned long alignment, int flags)
+static Bool
+i830_unbind_memory(ScrnInfoPtr pScrn, i830_memory *mem)
+{
+    if (mem == NULL || mem->key == -1 || !mem->bound)
+	return TRUE;
+
+    if (xf86UnbindGARTMemory(pScrn->scrnIndex, mem->key)) {
+	mem->bound = FALSE;
+	return TRUE;
+    } else {
+	return FALSE;
+    }
+}
+
+static void
+i830_free_memory(ScrnInfoPtr pScrn, i830_memory *mem)
+{
+    i830_unbind_memory(pScrn, mem);
+
+    /* Disconnect from the list of allocations */
+    if (mem->prev != NULL)
+	mem->prev->next = mem->next;
+    if (mem->next != NULL)
+	mem->next->prev = mem->prev;
+
+    /* Free any AGP memory. */
+    i830_unbind_memory(pScrn, mem);
+
+    if (mem->key != -1) {
+	xf86DeallocateGARTMemory(pScrn->scrnIndex, mem->key);
+	mem->key = -1;
+    }
+
+    xfree(mem->name);
+    xfree(mem);
+}
+
+/* Resets the state of the aperture allocator, freeing all memory that had
+ * been allocated.
+ */
+void
+i830_reset_allocations(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    unsigned long start, end;
-    unsigned long newApStart, newApEnd;
-    Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
+    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int i;
 
-    if (!result || !size)
-	return 0;
+    /* While there is any memory between the start and end markers, free it. */
+    while (pI830->memory_list->next->next != NULL)
+	i830_free_memory(pScrn, pI830->memory_list->next);
 
-    if ((flags & ALLOCATE_AT_BOTTOM) && pI830->StolenMemory.Size != 0) {
-	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		   "AllocFromAGP(): can't allocate from "
-		   "bottom when there is stolen memory\n");
-	return 0;
+    /* Null out the pointers for all the allocations we just freed.  This is
+     * kind of gross, but at least it's just one place now.
+     */
+    for (i = 0; i < xf86_config->num_crtc; i++) {
+	I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private;
+
+	intel_crtc->cursor_mem = NULL;
+	intel_crtc->cursor_mem_argb = NULL;
     }
 
-    if (size > pI830->FreeMemory) {
-	if (dryrun)
-	    pI830->FreeMemory = size;
-	else
-	    return 0;
+    pI830->front_buffer = NULL;
+    pI830->front_buffer_2 = NULL;
+    pI830->xaa_scratch = NULL;
+    pI830->xaa_scratch_2 = NULL;
+    pI830->exa_offscreen = NULL;
+    pI830->exa_965_state = NULL;
+    pI830->overlay_regs = NULL;
+    pI830->xaa_linear = NULL;
+    pI830->logical_context = NULL;
+    pI830->back_buffer = NULL;
+    pI830->depth_buffer = NULL;
+    pI830->textures = NULL;
+    pI830->memory_manager = NULL;
+    pI830->LpRing->mem = NULL;
+}
+
+/**
+ * Initialize's the driver's video memory allocator to allocate in the
+ * given range.
+ */
+Bool
+i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset,
+		    unsigned long size)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    i830_memory *start, *end;
+
+    start = xcalloc(1, sizeof(*start));
+    if (start == NULL)
+	return FALSE;
+    start->name = xstrdup("start marker");
+    if (start->name == NULL) {
+	xfree(start);
+	return FALSE;
+    }
+    end = xcalloc(1, sizeof(*end));
+    if (end == NULL) {
+	xfree(start->name);
+	xfree(start);
+	return FALSE;
+    }
+    end->name = xstrdup("end marker");
+    if (end->name == NULL) {
+	xfree(start->name);
+	xfree(start);
+	xfree(end);
+	return FALSE;
     }
 
-    /* Calculate offset */
-    if (flags & ALLOCATE_AT_BOTTOM) {
-	start = ROUND_TO(pI830->MemoryAperture.Start, alignment);
-	if (flags & ALIGN_BOTH_ENDS)
-	    end = ROUND_TO(start + size, alignment);
-	else
-	    end = start + size;
-	newApStart = end;
-	newApEnd = pI830->MemoryAperture.End;
-    } else {
+    start->key = -1;
+    start->offset = offset;
+    start->end = start->offset;
+    start->size = 0;
+    start->next = end;
+    end->key = -1;
+    end->offset = offset + size;
+    end->end = end->offset;
+    end->size = 0;
+    end->prev = start;
+
+    pI830->memory_list = start;
+
+    return TRUE;
+}
+
+/* Allocate aperture space for the given size and alignment, and returns the
+ * memory allocation.
+ *
+ * Allocations are a minimum of a page, and will be at least page-aligned.
+ */
+static i830_memory *
+i830_allocate_aperture(ScrnInfoPtr pScrn, const char *name,
+		       long size, unsigned long alignment, int flags)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    i830_memory *mem, *scan;
+
+    mem = xcalloc(1, sizeof(*mem));
+    if (mem == NULL)
+	return NULL;
+
+    /* No memory allocated to back the region */
+    mem->key = -1;
+
+    mem->name = xstrdup(name);
+    if (mem->name == NULL) {
+	xfree(mem);
+	return NULL;
+    }
+    mem->size = size;
+
+    if (alignment < GTT_PAGE_SIZE)
+	alignment = GTT_PAGE_SIZE;
+
+    for (scan = pI830->memory_list; scan->next != NULL; scan = scan->next) {
+	mem->offset = ROUND_TO(scan->end, alignment);
+	mem->end = mem->offset + size;
 	if (flags & ALIGN_BOTH_ENDS)
-	    end = ROUND_DOWN_TO(pI830->MemoryAperture.End, alignment);
-	else
-	    end = pI830->MemoryAperture.End;
-	start = ROUND_DOWN_TO(end - size, alignment);
-	newApStart = pI830->MemoryAperture.Start;
-	newApEnd = start;
+	    mem->end = ROUND_TO(mem->end, alignment);
+	if (mem->end <= scan->next->offset)
+	    break;
+    }
+    if (scan->next == NULL) {
+	/* Reached the end of the list, and didn't find space */
+	xfree(mem->name);
+	xfree(mem);
+	return NULL;
     }
+    /* Insert new allocation into the list */
+    mem->prev = scan;
+    mem->next = scan->next;
+    scan->next = mem;
+    mem->next->prev = scan;
 
-    if (!dryrun) {
-	if (newApStart > newApEnd)
-	    return 0;
-
-	if (flags & NEED_PHYSICAL_ADDR) {
-	    result->Key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 2,
-						 &(result->Physical));
-	} else {
-	    result->Key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 0,
-						 NULL);
-	}
+    return mem;
+}
+
+/**
+ * Allocates the AGP memory necessary for the part of a memory allocation not
+ * already covered by the stolen memory.
+ *
+ * The memory is automatically bound if we have the VT.
+ */
+static Bool
+i830_allocate_agp_memory(ScrnInfoPtr pScrn, i830_memory *mem, int flags)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    unsigned long size;
+
+    if (mem->key != -1)
+	return TRUE;
+
+    if (mem->offset + mem->size <= pI830->stolen_size)
+	return TRUE;
+
+    if (mem->offset < pI830->stolen_size)
+	mem->agp_offset = pI830->stolen_size;
+    else
+	mem->agp_offset = mem->offset;
+
+    size = mem->size - (mem->agp_offset - mem->offset);
 
-	if (result->Key == -1)
-	    return 0;
+    if (flags & NEED_PHYSICAL_ADDR)
+	mem->key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 2,
+					  &mem->bus_addr);
+    else
+	mem->key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 0, NULL);
+    if (mem->key == -1 || ((flags & NEED_PHYSICAL_ADDR) && mem->bus_addr == 0))
+    {
+	return FALSE;
     }
 
-    pI830->allocatedMemory += size;
-    pI830->MemoryAperture.Start = newApStart;
-    pI830->MemoryAperture.End = newApEnd;
-    pI830->MemoryAperture.Size = newApEnd - newApStart;
-    pI830->FreeMemory -= size;
-    result->Start = start;
-    result->End = start + size;
-    result->Size = size;
-    result->Offset = start;
-    result->Alignment = alignment;
-    result->Pool = NULL;
+    if (!i830_bind_memory(pScrn, mem)) {
+	return FALSE;
+    }
 
-    return size;
+    return TRUE;
 }
 
-void
-I830FreeVidMem(ScrnInfoPtr pScrn, I830MemRange *range)
+
+/* Allocates video memory at the given size and alignment.
+ *
+ * The memory will be bound automatically when the driver is in control of the
+ * VT.
+ */
+static i830_memory *
+i830_allocate_memory(ScrnInfoPtr pScrn, const char *name,
+		     unsigned long size, unsigned long alignment, int flags)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
+    i830_memory *mem;
 
-    if (!range || range->Size == 0)
-	return;
+    mem = i830_allocate_aperture(pScrn, name, size, alignment, flags);
+    if (mem == NULL)
+	return NULL;
 
-    if (range->Key != -1)
-	xf86DeallocateGARTMemory(pScrn->scrnIndex, range->Key);
+    if (!i830_allocate_agp_memory(pScrn, mem, flags)) {
+	i830_free_memory(pScrn, mem);
+	return NULL;
+    }
 
-    if (range->Pool) {
-	/*
-	 * This code essentially resets what I830DoPoolAllocation() did.
-	 * And if things are freed in the wrong order this can break wildly!
-	 * USE CAUTION when changing anything here...
-	 */
-	I830MemPool *Pool = range->Pool;
-	Pool->Total.End = pI830->StolenMemory.End;
+    return mem;
+}
 
-	if (pI830->StolenOnly)
-	    Pool->Free.End += range->Size;
-	else
-	    Pool->Free.End = Pool->Total.End;
+/* Allocate a tiled region with the given size and pitch.
+ *
+ * As is, we might miss out on tiling some allocations on older hardware with
+ * large framebuffer size and a small aperture size, where the first
+ * allocations use a large alignment even though we've got fences to spare, and
+ * the later allocations can't find enough aperture space left.  We could do
+ * some search across all allocation options to fix this, probably, but that
+ * would be another rewrite.
+ */
+static i830_memory *
+i830_allocate_memory_tiled(ScrnInfoPtr pScrn, const char *name,
+			   unsigned long size, unsigned long pitch,
+			   unsigned long alignment, int flags,
+			   enum tile_format tile_format)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    unsigned long aper_size;
+    unsigned long aper_align;
+    i830_memory *mem;
+    int fence_divide, i;
 
-	if (Pool->Free.End < Pool->Free.Start) {
-	    Pool->Free.End = Pool->Free.Start;
-	}
+    if (tile_format == TILING_NONE)
+	return i830_allocate_memory(pScrn, name, size, alignment, flags);
 
-	Pool->Free.Size = Pool->Free.End - Pool->Free.Start;
-	Pool->Total.Size = Pool->Total.End - Pool->Total.Start;
+    /* Check for maximum tiled region size */
+    if (IS_I9XX(pI830)) {
+	if (size > MB(128))
+	    return NULL;
+    } else {
+	if (size > MB(64))
+	    return NULL;
+    }
 
-	if (!pI830->StolenOnly) {
-	    pI830->FreeMemory -= Pool->Free.Size;
-	    pI830->MemoryAperture.Start -= (range->Size - Pool->Free.Size);
-	    pI830->MemoryAperture.Size += (range->Size - Pool->Free.Size);
-	}
+    aper_size = i830_get_fence_size(pScrn, size);
+    if (IS_I965G(pI830)) {
+	aper_align = GTT_PAGE_SIZE;
     } else {
-	if (range->Alignment == GTT_PAGE_SIZE)
-	    pI830->MemoryAperture.End = range->End;
-	else {
-	    pI830->MemoryAperture.End = range->End - range->Size +
-		range->Alignment;
+	/* The offset has to be aligned to at least the size of the fence
+	 * region.
+	 */
+	aper_align = aper_size;
+    }
+    if (aper_align < alignment)
+	aper_align = alignment;
+
+    fence_divide = 1;
+    mem = i830_allocate_aperture(pScrn, name, aper_size, aper_align, flags);
+    if (mem == NULL && !IS_I965G(pI830)) {
+	/* For the older hardware with stricter fencing limits, if we
+	 * couldn't allocate with the large alignment, try relaxing the
+	 * alignment requirements and using more fences to cover the area.
+	 */
+	for (fence_divide = 2; fence_divide <= 4 && mem == NULL;
+	     fence_divide *= 2)
+	{
+	    /* Check that it's not too small for fencing. */
+	    if (i830_get_fence_size(pScrn, aper_align / fence_divide) !=
+		aper_align / fence_divide)
+	    {
+		break;
+	    }
+
+	    mem = i830_allocate_aperture(pScrn, name, aper_size,
+					 aper_align / fence_divide, flags);
 	}
-	pI830->MemoryAperture.Size = pI830->MemoryAperture.End -
-	    pI830->MemoryAperture.Start;
     }
 
-    if (!pI830->StolenOnly)
-	pI830->FreeMemory += range->Size;
-    pI830->allocatedMemory -= range->Size;
+    if (mem == NULL)
+	return NULL;
+
+    /* Make sure we've got enough free fence regs.  It's pretty hard to run
+     * out, luckily, with 8 even on older hardware and us only tiling
+     * front/back/depth buffers.
+     */
+    if (pI830->next_fence + fence_divide >
+	(IS_I965G(pI830) ? FENCE_NEW_NR : FENCE_NR))
+    {
+	i830_free_memory(pScrn, mem);
+	return NULL;
+    }
+
+    /* Allocate any necessary AGP memory to back this allocation */
+    if (!i830_allocate_agp_memory(pScrn, mem, flags)) {
+	i830_free_memory(pScrn, mem);
+	return NULL;
+    }
+
+    /* Set up the fence registers. */
+    for (i = 0; i < fence_divide; i++) {
+	i830_set_fence(pScrn, pI830->next_fence++,
+		       mem->offset + mem->size * i / fence_divide, pitch,
+		       mem->size / fence_divide, tile_format);
+    }
+
+    mem->size = size;
+
+    return mem;
+}
+
+static void
+i830_describe_tiling(ScrnInfoPtr pScrn, int verbosity, const char *prefix,
+		     i830_memory *mem, unsigned int tiling_mode)
+{
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		   "%s%s is %stiled\n", prefix, mem->name,
+		   (tiling_mode == FENCE_LINEAR) ? "not " : "");
 }
 
-unsigned long
-I830AllocVidMem(ScrnInfoPtr pScrn, I830MemRange *result, I830MemPool *pool,
-		long size, unsigned long alignment, int flags)
+void
+i830_describe_allocations(ScrnInfoPtr pScrn, int verbosity, const char *prefix)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
+    i830_memory *mem;
 
-    if (!result)
-	return 0;
+    if (pI830->memory_list == NULL) {
+	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		       "%sMemory allocator not initialized\n", prefix);
+	return;
+    }
 
-    /* Make sure these are initialised. */
-    result->Size = 0;
-    result->Key = -1;
-
-    if (!size) {
-	return 0;
-    }
-
-    switch (flags & FROM_MASK) {
-    case FROM_POOL_ONLY:
-	return AllocFromPool(pScrn, result, pool, size, alignment, flags);
-    case FROM_NEW_ONLY:
-	if (!dryrun && (pI830->StolenOnly || (pI830->FreeMemory <= 0)))
-	    return 0;
-	return AllocFromAGP(pScrn, result, size, alignment, flags);
-    case FROM_ANYWHERE:
-	if ((!(flags & ALLOCATE_AT_BOTTOM) && (pI830->FreeMemory >= size)) ||
-	    (flags & NEED_PHYSICAL_ADDR))
-	    return AllocFromAGP(pScrn, result, size, alignment, flags);
-	else
-	    return AllocFromPool(pScrn, result, pool, size, alignment, flags);
-    default:
-	/* Shouldn't happen. */
-	return 0;
+    if (pI830->memory_list->next->next == NULL) {
+	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		       "%sNo memory allocations\n", prefix);
+	return;
+    }
+
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		   "%sMemory allocation layout:\n", prefix);
+
+    for (mem = pI830->memory_list->next; mem->next != NULL; mem = mem->next) {
+
+	if (mem->offset >= pI830->stolen_size &&
+	    mem->prev->offset <= pI830->stolen_size)
+	{
+	    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+			   "%s0x%08lx:            end of stolen memory\n",
+			   prefix, pI830->stolen_size);
+	}
+
+	if (mem->bus_addr == 0) {
+	    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+			   "%s0x%08lx-0x%08lx: %s (%ld kB)\n", prefix,
+			   mem->offset, mem->end - 1, mem->name,
+			   mem->size / 1024);
+	} else {
+	    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+			   "%s0x%08lx-0x%08lx: %s (%ld kB, %08lx physical)\n",
+			   prefix,
+			   mem->offset, mem->end - 1, mem->name,
+			   mem->size / 1024, mem->bus_addr);
+	}
+    }
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		   "%s0x%08lx:            end of aperture\n",
+		   prefix, pI830->FbMapSize);
+
+    if (pI830->front_buffer != NULL) {
+	i830_describe_tiling(pScrn, verbosity, prefix, pI830->front_buffer,
+			     pI830->front_tiled);
+    }
+    if (pI830->back_buffer != NULL) {
+	i830_describe_tiling(pScrn, verbosity, prefix, pI830->back_buffer,
+			     pI830->back_tiled);
+    }
+    if (pI830->depth_buffer != NULL) {
+	i830_describe_tiling(pScrn, verbosity, prefix, pI830->depth_buffer,
+			     pI830->depth_tiled);
     }
 }
 
 static Bool
-AllocateRingBuffer(ScrnInfoPtr pScrn, int flags)
+i830_allocate_ringbuffer(ScrnInfoPtr pScrn, int flags)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    unsigned long size, alloced;
     Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
-    int verbosity = dryrun ? 4 : 1;
-    const char *s = dryrun ? "[dryrun] " : "";
 
-    /* Clear ring buffer  info */
-    memset(pI830->LpRing, 0, sizeof(I830RingBuffer));
-    pI830->LpRing->mem.Key = -1;
-
-    if (pI830->noAccel)
+    if (pI830->noAccel || pI830->LpRing->mem != NULL)
 	return TRUE;
 
-    /* Ring buffer */
-    size = PRIMARY_RINGBUFFER_SIZE;
-    if (flags & FORCE_LOW)
-	flags |= FROM_POOL_ONLY | ALLOCATE_AT_BOTTOM;
-    else
-	flags |= FROM_ANYWHERE | ALLOCATE_AT_TOP;
-
-    alloced = I830AllocVidMem(pScrn, &(pI830->LpRing->mem),
-			      &(pI830->StolenPool), size,
-			      GTT_PAGE_SIZE, flags);
-    if (alloced < size) {
+    pI830->LpRing->mem = i830_allocate_memory(pScrn, "ring buffer",
+					      PRIMARY_RINGBUFFER_SIZE,
+					      GTT_PAGE_SIZE, 0);
+    if (pI830->LpRing->mem == NULL) {
 	if (!dryrun) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		       "Failed to allocate Ring Buffer space\n");
 	}
 	return FALSE;
     }
-    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-		   "%sAllocated %ld kB for the ring buffer at 0x%lx\n", s,
-		   alloced / 1024, pI830->LpRing->mem.Start);
-    pI830->LpRing->tail_mask = pI830->LpRing->mem.Size - 1;
+
+    pI830->LpRing->tail_mask = pI830->LpRing->mem->size - 1;
     return TRUE;
 }
 
 #ifdef I830_XV
-/*
- * Note, the FORCE_LOW flag is currently not used or supported.
+/**
+ * Allocate space for overlay registers and XAA linear allocator (if
+ * requested)
  */
 static Bool
-AllocateOverlay(ScrnInfoPtr pScrn, int flags)
+i830_allocate_overlay(ScrnInfoPtr pScrn, int flags)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    unsigned long size, alloced;
     Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
-    int verbosity = dryrun ? 4 : 1;
-    const char *s = dryrun ? "[dryrun] " : "";
-
-    /* Clear overlay info */
-    memset(pI830->OverlayMem, 0, sizeof(I830MemRange));
-    pI830->OverlayMem->Key = -1;
 
-    if (!pI830->XvEnabled)
+    /* Only allocate if overlay is going to be enabled. */
+    if (!pI830->XvEnabled || IS_I965G(pI830))
 	return TRUE;
 
-    /*
-     * The overlay register space needs a physical address in
-     * system memory.  We get this from the agpgart module using
-     * a special memory type.
-     */
-
-    size = OVERLAY_SIZE;
-    if (flags & FORCE_LOW)
-	flags |= FROM_POOL_ONLY | ALLOCATE_AT_BOTTOM | NEED_PHYSICAL_ADDR;
-    else
-	flags |= FROM_ANYWHERE | ALLOCATE_AT_TOP | NEED_PHYSICAL_ADDR;
-
-    alloced = I830AllocVidMem(pScrn, pI830->OverlayMem,
-			      &(pI830->StolenPool), size, GTT_PAGE_SIZE,
-			      flags);
-
-    /*
-     * XXX For testing only.  Don't enable this unless you know how to set
-     * physBase.
-     */
-    if (flags & FORCE_LOW) {
-	ErrorF("AllocateOverlay() doesn't support setting FORCE_LOW\n");
-	return FALSE;
+    if (!IS_I965G(pI830)) {
+	pI830->overlay_regs = i830_allocate_memory(pScrn, "overlay registers",
+						   OVERLAY_SIZE, GTT_PAGE_SIZE,
+						   NEED_PHYSICAL_ADDR);
+	if (pI830->overlay_regs == NULL) {
+	    if (!dryrun) {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			   "Failed to allocate Overlay register space.\n");
+		/* This failure isn't fatal. */
+	    }
+	}
     }
 
-    if (!dryrun && (alloced < size)) {
-	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		   "Failed to allocate Overlay register space.\n");
-	/* This failure isn't fatal. */
-    } else {
-	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-		       "%sAllocated %ld kB for Overlay registers at 0x%lx "
-		       "(0x%08lx).\n", s,
-		       alloced / 1024, pI830->OverlayMem->Start,
-		       pI830->OverlayMem->Physical);
-    }
-
-    /* Clear linearmem info */
-    if (pI830->LinearAlloc) {
-	memset(&(pI830->LinearMem), 0, sizeof(I830MemRange));
-	pI830->LinearMem.Key = -1;
-
-	size = KB(pI830->LinearAlloc);
-	alloced = I830AllocVidMem(pScrn, &(pI830->LinearMem),
-				  &(pI830->StolenPool),
-				  size, GTT_PAGE_SIZE,
-				  FROM_ANYWHERE | ALLOCATE_AT_TOP);
-	if (alloced < size) {
+    if (!pI830->useEXA && pI830->LinearAlloc) {
+	pI830->xaa_linear = i830_allocate_memory(pScrn, "XAA linear memory",
+						 KB(pI830->LinearAlloc),
+						 GTT_PAGE_SIZE, 0);
+	if (pI830->xaa_linear == NULL) {
 	    if (!dryrun) {
 		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 			   "Failed to allocate linear buffer space\n");
 	    }
-	} else
-	    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-			   "%sAllocated %ld kB for the linear buffer at "
-			   "0x%lx\n", s,
-			   alloced / 1024, pI830->LinearMem.Start);
+	}
     }
 
     return TRUE;
@@ -479,22 +682,6 @@ IsTileable(ScrnInfoPtr pScrn, int pitch)
     }
 }
 
-static unsigned long
-GetFreeSpace(ScrnInfoPtr pScrn)
-{
-    I830Ptr pI830 = I830PTR(pScrn);
-    unsigned long extra = 0;
-
-    /* First check for free space in StolenPool. */
-    if (pI830->StolenPool.Free.Size > 0)
-	extra = pI830->StolenPool.Free.Size;
-    /* Next check for unallocated space. */
-    if (pI830->FreeMemory > 0)
-	extra += pI830->FreeMemory;
-
-    return extra;
-}
-
 /* This is the 2D rendering vertical coordinate limit.  We can ignore
  * the 3D rendering limits in our 2d pixmap cache allocation, because XAA
  * doesn't do any 3D rendering to/from the cache lines when using an offset
@@ -512,24 +699,23 @@ GetFreeSpace(ScrnInfoPtr pScrn)
  * \param pI830 I830Ptr for the screen being allocated.
  * \param FbMemBox
  */
-static Bool
-I830AllocateFramebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox,
-			I830MemRange *FrontBuffer, I830MemPool *StolenPool,
-			Bool secondary, const int flags)
+static i830_memory *
+i830_allocate_framebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox,
+			  Bool secondary, int flags)
 {
     Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
-    unsigned long minspace, avail, lineSize;
+    unsigned int pitch = pScrn->displayWidth * pI830->cpp;
+    unsigned long minspace, avail;
     int cacheLines, maxCacheLines;
     int verbosity = dryrun ? 4 : 1;
     const char *s = dryrun ? "[dryrun] " : "";
-    Bool tileable;
-    int align, alignflags;
-    long size, alloced, fb_height;
+    int align;
+    long size, fb_height;
+    char *name;
+    i830_memory *front_buffer = NULL;
 
     /* Clear everything first. */
     memset(FbMemBox, 0, sizeof(*FbMemBox));
-    memset(FrontBuffer, 0, sizeof(*FrontBuffer));
-    FrontBuffer->Key = -1;
 
     /* We'll allocate the fb such that the root window will fit regardless of
      * rotation.
@@ -549,18 +735,16 @@ I830AllocateFramebuffer(ScrnInfoPtr pScr
      * enough for the virtual screen size, plus some pixmap cache
      * space if we're using XAA.
      */
-
-    lineSize = pScrn->displayWidth * pI830->cpp;
-    minspace = lineSize * pScrn->virtualY;
+    minspace = pitch * pScrn->virtualY;
     avail = pScrn->videoRam * 1024;
 
     if (!pI830->useEXA) {
-	maxCacheLines = (avail - minspace) / lineSize;
+	maxCacheLines = (avail - minspace) / pitch;
 	/* This shouldn't happen. */
 	if (maxCacheLines < 0) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		       "Internal Error: "
-		       "maxCacheLines < 0 in I830Allocate2DMemory()\n");
+		       "maxCacheLines < 0 in i830_allocate_2d_memory()\n");
 	    maxCacheLines = 0;
 	}
 	if (maxCacheLines > (MAX_2D_HEIGHT - pScrn->virtualY))
@@ -571,11 +755,11 @@ I830AllocateFramebuffer(ScrnInfoPtr pScr
 	} else {
 	    int size;
 
-	    size = 3 * lineSize * pScrn->virtualY;
+	    size = 3 * pitch * pScrn->virtualY;
 	    size += 1920 * 1088 * 2 * 2;
 	    size = ROUND_TO_PAGE(size);
 
-	    cacheLines = (size + lineSize - 1) / lineSize;
+	    cacheLines = (size + pitch - 1) / pitch;
 	}
 	if (cacheLines > maxCacheLines)
 	    cacheLines = maxCacheLines;
@@ -592,125 +776,96 @@ I830AllocateFramebuffer(ScrnInfoPtr pScr
 	cacheLines = 0;
     }
 
-    tileable = !(flags & ALLOC_NO_TILING) && pI830->allowPageFlip &&
-	IsTileable(pScrn, pScrn->displayWidth * pI830->cpp);
-    if (tileable) {
+    size = pitch * (fb_height + cacheLines);
+    size = ROUND_TO_PAGE(size);
+
+    name = secondary ? "secondary front buffer" : "front buffer";
+
+    /* Attempt to allocate it tiled first if we have page flipping on. */
+    if (!flags & ALLOC_NO_TILING && pI830->allowPageFlip &&
+	IsTileable(pScrn, pitch))
+    {
+	/* XXX: probably not the case on 965 */
 	if (IS_I9XX(pI830))
 	    align = MB(1);
 	else
 	    align = KB(512);
-	alignflags = ALIGN_BOTH_ENDS;
-    } else {
-	align = KB(64);
-	alignflags = 0;
+	front_buffer = i830_allocate_memory_tiled(pScrn, name, size,
+						  pitch, align,
+						  flags, TILING_XMAJOR);
+	pI830->front_tiled = FENCE_XMAJOR;
     }
 
-    size = lineSize * (fb_height + cacheLines);
-    size = ROUND_TO_PAGE(size);
-    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-		   "%sInitial %sframebuffer allocation size: %ld kByte\n",
-		   s, secondary ? "secondary " : "",
-		   size / 1024);
-    alloced = I830AllocVidMem(pScrn, FrontBuffer,
-			      StolenPool, size, align,
-			      flags | alignflags |
-			      FROM_ANYWHERE | ALLOCATE_AT_BOTTOM);
-    if (alloced < size) {
+    /* If not, attempt it linear */
+    if (front_buffer == NULL) {
+	front_buffer = i830_allocate_memory(pScrn, name, size, KB(64), flags);
+	pI830->front_tiled = FENCE_LINEAR;
+    }
+
+    if (front_buffer == NULL) {
 	if (!dryrun) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate "
 		       "%sframebuffer. Is your VideoRAM set too low?\n",
 		       secondary ? "secondary " : "");
 	}
-	return FALSE;
+	return NULL;
     }
 
-    return TRUE;
+    return front_buffer;
 }
 
 static Bool
-I830AllocateCursorBuffers(xf86CrtcPtr crtc, const int flags)
+i830_allocate_cursor_buffers(xf86CrtcPtr crtc, int flags)
 {
     ScrnInfoPtr pScrn = crtc->scrn;
     I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
     I830Ptr pI830 = I830PTR(pScrn);
     Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
-    int verbosity = dryrun ? 4 : 1;
-    const char *s = dryrun ? "[dryrun] " : "";
-    long size, alloced;
-    int cursFlags = 0;
-
-    /* Clear cursor info */
-    memset(&intel_crtc->cursor_mem, 0, sizeof(I830MemRange));
-    intel_crtc->cursor_mem.Key = -1;
-    memset(&intel_crtc->cursor_mem_argb, 0, sizeof(I830MemRange));
-    intel_crtc->cursor_mem_argb.Key = -1;
+    long size;
 
     if (pI830->SWCursor)
 	return FALSE;
 
-    /*
-     * Mouse cursor -- The i810-i830 need a physical address in system
+    /* Mouse cursor -- The i810-i830 need a physical address in system
      * memory from which to upload the cursor.  We get this from
      * the agpgart module using a special memory type.
      */
 
     size = HWCURSOR_SIZE;
-    cursFlags = FROM_ANYWHERE | ALLOCATE_AT_TOP;
     if (pI830->CursorNeedsPhysical)
-	cursFlags |= NEED_PHYSICAL_ADDR;
+	flags |= NEED_PHYSICAL_ADDR;
 
-    alloced = I830AllocVidMem(pScrn, &intel_crtc->cursor_mem,
-			      &pI830->StolenPool, size,
-			      GTT_PAGE_SIZE, flags | cursFlags);
-    if (alloced < size ||
-	(pI830->CursorNeedsPhysical && !intel_crtc->cursor_mem.Physical))
-    {
-	if (!dryrun) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		       "Failed to allocate HW cursor space.\n");
+    if (intel_crtc->cursor_mem == NULL) {
+	intel_crtc->cursor_mem = i830_allocate_memory(pScrn, "HW cursor",
+						      size, GTT_PAGE_SIZE,
+						      flags);
+	if (intel_crtc->cursor_mem == NULL) {
+	    if (!dryrun) {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			   "Failed to allocate HW cursor space.\n");
+	    }
 	    return FALSE;
 	}
-    } else {
-	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-		       "%sAllocated %ld kB for HW cursor at 0x%lx", s,
-		       alloced / 1024, intel_crtc->cursor_mem.Start);
-	if (pI830->CursorNeedsPhysical) {
-	    xf86ErrorFVerb(verbosity, " (0x%08lx)",
-			   intel_crtc->cursor_mem.Physical);
-	}
-	xf86ErrorFVerb(verbosity, "\n");
     }
 
-    /* Allocate the ARGB cursor space.  Its success is optional -- we won't set
-     * SWCursor if it fails.
-     */
-    size = HWCURSOR_SIZE_ARGB;
-    cursFlags = FROM_ANYWHERE | ALLOCATE_AT_TOP;
-    if (pI830->CursorNeedsPhysical)
-	cursFlags |= NEED_PHYSICAL_ADDR;
-
-    alloced = I830AllocVidMem(pScrn, &intel_crtc->cursor_mem_argb,
-			      &pI830->StolenPool, size,
-			      GTT_PAGE_SIZE, flags | cursFlags);
-    if (alloced < size ||
-	(pI830->CursorNeedsPhysical && !intel_crtc->cursor_mem_argb.Physical))
-    {
-	if (!dryrun) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		       "Failed to allocate HW (ARGB) cursor space.\n");
-	}
-    } else {
-	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-		       "%sAllocated %ld kB for HW (ARGB) cursor at 0x%lx", s,
-		       alloced / 1024, intel_crtc->cursor_mem_argb.Start);
-	if (pI830->CursorNeedsPhysical) {
-	    xf86ErrorFVerb(verbosity, " (0x%08lx)",
-			   intel_crtc->cursor_mem_argb.Physical);
+    if (intel_crtc->cursor_mem_argb == NULL) {
+	/* Allocate the ARGB cursor space.  Its success is optional -- we won't
+	 * set SWCursor if it fails.
+	 */
+	intel_crtc->cursor_mem_argb = i830_allocate_memory(pScrn,
+							   "HW ARGB cursor",
+							   HWCURSOR_SIZE_ARGB,
+							   GTT_PAGE_SIZE,
+							   flags);
+	if (intel_crtc->cursor_mem_argb == NULL) {
+	    if (!dryrun) {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			   "Failed to allocate HW (ARGB) cursor space.\n");
+	    }
 	}
-	xf86ErrorFVerb(verbosity, "\n");
     }
 
-    return FALSE;
+    return TRUE;
 }
 
 /*
@@ -718,18 +873,16 @@ I830AllocateCursorBuffers(xf86CrtcPtr cr
  * ring buffer, scratch memory, HW cursor.
  */
 Bool
-I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags)
+i830_allocate_2d_memory(ScrnInfoPtr pScrn, const int flags)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-    long size, alloced;
+    unsigned int pitch = pScrn->displayWidth * pI830->cpp;
+    long size;
     Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
-    int verbosity = dryrun ? 4 : 1;
-    const char *s = dryrun ? "[dryrun] " : "";
-    Bool tileable;
-    int align, alignflags, i;
+    int i;
 
-    DPRINTF(PFX, "I830Allocate2DMemory: inital is %s\n",
+    DPRINTF(PFX, "i830_allocate_2d_memory: inital is %s\n",
 	    BOOLTOSTRING(flags & ALLOC_INITIAL));
 
     if (!pI830->StolenOnly &&
@@ -738,88 +891,70 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		       "AGP GART support is either not available or cannot "
 		       "be used.\n"
-		       "\tMake sure your kernel has agpgart support or has "
-		       "the\n"
-		       "\tagpgart module loaded.\n");
+		       "\tMake sure your kernel has agpgart support or has\n"
+		       "\tthe agpgart module loaded.\n");
 	}
 	return FALSE;
     }
 
+    /* Allocate the ring buffer first, so it ends up in stolen mem. */
+    i830_allocate_ringbuffer(pScrn, flags);
 
-    /*
-     * The I830 is slightly different from the I830/I815, it has no
-     * dcache and it has stolen memory by default in its gtt.  All
-     * additional memory must go after it.
-     */
-
-    DPRINTF(PFX,
-	    "size == %luk (%lu bytes == pScrn->videoRam)\n"
-	    "pI830->StolenSize == %luk (%lu bytes)\n",
-	    pScrn->videoRam, pScrn->videoRam * 1024,
-	    pI830->StolenPool.Free.Size / 1024,
-	    pI830->StolenPool.Free.Size);
-
-    if (flags & ALLOC_INITIAL) {
-	if (pI830->NeedRingBufferLow)
-	    AllocateRingBuffer(pScrn, flags | FORCE_LOW);
-
-	/* Unfortunately this doesn't run on the DRY_RUN pass because our
-	 * second head hasn't been created yet..... */
-	if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) {
-	    I830EntPtr pI830Ent = pI830->entityPrivate;
-	    I830Ptr pI8302 = I830PTR(pI830Ent->pScrn_2);
-
-	    if (!I830AllocateFramebuffer(pI830Ent->pScrn_2, pI8302,
-					 &pI830->FbMemBox2,
-					 &pI830->FrontBuffer2,
-					 &pI830->StolenPool,
-					 TRUE, flags))
-	    {
-		return FALSE;
-	    }
-	}
-	if (!I830AllocateFramebuffer(pScrn, pI830, &pI830->FbMemBox,
-				     &pI830->FrontBuffer, &pI830->StolenPool,
-				     FALSE, flags))
-	{
-	    return FALSE;
+    /* Next, allocate other fixed-size allocations we have. */
+    if (!pI830->SWCursor) {
+	/* Allocate cursor memory */
+	for (i = 0; i < xf86_config->num_crtc; i++) {
+	    if (!i830_allocate_cursor_buffers(xf86_config->crtc[i], flags) &&
+		!pI830->SWCursor)
+		{
+		    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+			       "Disabling HW cursor because the cursor memory "
+			       "allocation failed.\n");
+		    pI830->SWCursor = TRUE;
+		    break;
+		}
 	}
+    }
+
+#ifdef I830_XV
+    /* Allocate overlay register space and optional XAA linear allocator
+     * space.  The second head in zaphod mode will share the space.
+     */
+    if (I830IsPrimary(pScrn))
+	i830_allocate_overlay(pScrn, flags);
+#endif
 
 #ifdef I830_USE_EXA
-	if (pI830->useEXA) {
+    if (pI830->useEXA) {
+	if (pI830->exa_offscreen == NULL) {
 	    /* Default EXA to having 3 screens worth of offscreen memory space
 	     * (for pixmaps), plus a double-buffered, 1920x1088 video's worth.
+	     *
+	     * XXX: It would be nice to auto-size it larger if the user
+	     * specified a larger size, or to fit along with texture and FB
+	     * memory if a low videoRam is specified.
 	     */
-	    size = 3 * pScrn->displayWidth * pI830->cpp * pScrn->virtualY;
+	    size = 3 * pitch * pScrn->virtualY;
 	    size += 1920 * 1088 * 2 * 2;
 	    size = ROUND_TO_PAGE(size);
 
-	    alloced = I830AllocVidMem(pScrn, &(pI830->Offscreen),
-				      &(pI830->StolenPool), size, 1,
-				      flags |
-				      FROM_ANYWHERE | ALLOCATE_AT_BOTTOM);
-	    if (alloced < size) {
+	    pI830->exa_offscreen = i830_allocate_memory(pScrn, "exa offscreen",
+							size, 1, flags);
+	    if (pI830->exa_offscreen == NULL) {
 		if (!dryrun) {
 		    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate "
 			       "offscreen memory.  Not enough VRAM?\n");
 		}
 		return FALSE;
-	    } else {
-		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-			   "Successful allocation of "
-			   "EXA offscreen memory at 0x%lx, size %ld KB\n",
-			   pI830->Offscreen.Start, pI830->Offscreen.Size/1024);
 	    }
 	}
-	if (pI830->useEXA && IS_I965G(pI830)) {
-	    memset(&(pI830->EXAStateMem), 0, sizeof(I830MemRange));
-	    pI830->EXAStateMem.Key = -1;
-	    size = ROUND_TO_PAGE(EXA_LINEAR_EXTRA);
-	    align = GTT_PAGE_SIZE;
-	    alloced = I830AllocVidMem(pScrn, &(pI830->EXAStateMem),
-				      &(pI830->StolenPool), size, align,
-				      flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
-	    if (alloced < size) {
+
+	if (IS_I965G(pI830) && pI830->exa_965_state == NULL) {
+	    pI830->exa_965_state =
+		i830_allocate_memory(pScrn, "exa G965 state buffer",
+				     EXA_LINEAR_EXTRA, GTT_PAGE_SIZE,
+				     flags);
+	    if (pI830->exa_965_state == NULL) {
 		if (!dryrun) {
 		    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 			       "G965: Failed to allocate exa state buffer "
@@ -827,228 +962,85 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
 		}
 		return FALSE;
 	    }
-	    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-			   "%sAllocated %ld kB for the G965 exa state buffer "
-			   "at 0x%lx - 0x%lx.\n", s,
-			   alloced / 1024, pI830->EXAStateMem.Start,
-			   pI830->EXAStateMem.End);
-	}
-#endif
-    } else {
-	long lineSize;
-	long extra = 0;
-	long maxFb = 0;
-
-	/*
-	 * XXX Need to "free" up any 3D allocations if the DRI ended up
-	 * and make them available for 2D.  The best way to do this would
-	 * be position all of those regions contiguously at the end of the
-	 * StolenPool.
-	 */
-	extra = GetFreeSpace(pScrn);
-
-	if (extra == 0)
-	    return TRUE;
-
-	maxFb = pI830->FrontBuffer.Size + extra;
-	lineSize = pScrn->displayWidth * pI830->cpp;
-	maxFb = ROUND_DOWN_TO(maxFb, lineSize);
-	if (maxFb > lineSize * MAX_2D_HEIGHT)
-	    maxFb = lineSize * MAX_2D_HEIGHT;
-	if (0/*maxFb > pI830->FrontBuffer.Size*/) {
-	    unsigned long oldsize;
-	    /*
-	     * Sanity check -- the fb should be the last thing allocated at
-	     * the bottom of the stolen pool.
-	     */
-	    if (pI830->StolenPool.Free.Start != pI830->FrontBuffer.End) {
-		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-			   "Internal error in I830Allocate2DMemory():\n\t"
-			   "Framebuffer isn't the last allocation at the "
-			   "bottom of StolenPool\n\t(%lx != %lx).\n",
-			   pI830->FrontBuffer.End,
-			   pI830->StolenPool.Free.Start);
-		return FALSE;
-	    }
-	    /*
-	     * XXX Maybe should have a "Free" function.  This should be
-	     * the only place where a region is resized, and we know that
-	     * the fb is always at the bottom of the aperture/stolen pool,
-	     * and is the only region that is allocated bottom-up.
-	     * Allowing for more general realloction would require a smarter
-	     * allocation system.
-	     */
-	    oldsize = pI830->FrontBuffer.Size;
-	    pI830->StolenPool.Free.Size += pI830->FrontBuffer.Size;
-	    pI830->StolenPool.Free.Start -= pI830->FrontBuffer.Size;
-	    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-			   "%sUpdated framebuffer allocation size from %ld "
-			   "to %ld kByte\n", s, oldsize / 1024, maxFb / 1024);
-	    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-			   "%sUpdated pixmap cache from %ld scanlines to %ld "
-			   "scanlines\n", s,
-			   oldsize / lineSize - pScrn->virtualY,
-			   maxFb / lineSize - pScrn->virtualY);
-	    pI830->FbMemBox.y2 = maxFb / lineSize;
-	    tileable = !(flags & ALLOC_NO_TILING) && pI830->allowPageFlip &&
-		IsTileable(pScrn, pScrn->displayWidth * pI830->cpp);
-	    if (tileable) {
-		if (IS_I9XX(pI830))
-		    align = MB(1);
-		else
-		    align = KB(512);
-		alignflags = ALIGN_BOTH_ENDS;
-	    } else {
-		align = KB(64);
-		alignflags = 0;
-	    }
-	    alloced = I830AllocVidMem(pScrn, &(pI830->FrontBuffer),
-				      &(pI830->StolenPool), maxFb, align,
-				      flags | alignflags |
-				      FROM_ANYWHERE | ALLOCATE_AT_BOTTOM);
-	    if (alloced < maxFb) {
-		if (!dryrun) {
-		    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-			       "Failed to re-allocate framebuffer\n");
-		}
-		return FALSE;
-	    }
 	}
-	return TRUE;
     }
+#endif /* I830_USE_EXA */
 
-#if REMAP_RESERVED
-    /*
-     * Allocate a dummy page to pass when attempting to rebind the
-     * pre-allocated region.
-     */
-    if (!dryrun) {
-	memset(&(pI830->Dummy), 0, sizeof(pI830->Dummy));
-	pI830->Dummy.Key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 0,
-						  NULL);
-	pI830->Dummy.Offset = 0;
-    }
-#endif
+    if (flags & ALLOC_INITIAL) {
 
-    if (!pI830->SWCursor && !dryrun) {
-	for (i = 0; i < xf86_config->num_crtc; i++) {
-	    if (!I830AllocateCursorBuffers(xf86_config->crtc[i], flags) &&
-		pI830->SWCursor)
-	    {
-		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-			   "Disabling HW cursor because the cursor memory "
-			   "allocation failed.\n");
-		pI830->SWCursor = TRUE;
-		break;
-	    }
+	/* Unfortunately this doesn't run on the DRY_RUN pass because our
+	 * second head hasn't been created yet..... */
+	if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) {
+	    I830EntPtr pI830Ent = pI830->entityPrivate;
+	    I830Ptr pI8302 = I830PTR(pI830Ent->pScrn_2);
+
+	    pI830->front_buffer_2 =
+		i830_allocate_framebuffer(pI830Ent->pScrn_2, pI8302,
+					  &pI830->FbMemBox2,
+					  TRUE, flags);
+	    if (pI830->front_buffer_2 == NULL)
+		return FALSE;
 	}
+	pI830->front_buffer =
+	    i830_allocate_framebuffer(pScrn, pI830, &pI830->FbMemBox,
+				      FALSE, flags);
+	if (pI830->front_buffer == NULL)
+	    return FALSE;
     }
 
-#ifdef I830_XV
-    AllocateOverlay(pScrn, flags);
-#endif
-
-    if (!pI830->NeedRingBufferLow)
-	AllocateRingBuffer(pScrn, flags);
-
-    /* Clear scratch info */
-    memset(&(pI830->Scratch), 0, sizeof(I830MemRange));
-    pI830->Scratch.Key = -1;
-    memset(&(pI830->Scratch2), 0, sizeof(I830MemRange));
-    pI830->Scratch2.Key = -1;
-
-    if (!pI830->noAccel) {
-	size = MAX_SCRATCH_BUFFER_SIZE;
-	alloced = I830AllocVidMem(pScrn, &(pI830->Scratch),
-				  &(pI830->StolenPool),
-				  size, GTT_PAGE_SIZE,
-				  flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
-	if (alloced < size) {
-	    size = MIN_SCRATCH_BUFFER_SIZE;
-	    alloced = I830AllocVidMem(pScrn, &(pI830->Scratch),
-				      &(pI830->StolenPool), size,
-				      GTT_PAGE_SIZE,
-				      flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
-	}
-	if (alloced < size) {
-	    if (!dryrun) {
-		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-			   "Failed to allocate scratch buffer space\n");
+    if (!pI830->noAccel && !pI830->useEXA) {
+	if (pI830->xaa_scratch == NULL) {
+	    pI830->xaa_scratch =
+		i830_allocate_memory(pScrn, "xaa scratch",
+				     MAX_SCRATCH_BUFFER_SIZE, GTT_PAGE_SIZE,
+				     flags);
+	    if (pI830->xaa_scratch == NULL) {
+		pI830->xaa_scratch =
+		    i830_allocate_memory(pScrn, "xaa scratch",
+					 MIN_SCRATCH_BUFFER_SIZE,
+					 GTT_PAGE_SIZE,
+					 flags);
+		if (pI830->xaa_scratch == NULL) {
+		    if (!dryrun) {
+			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+				   "Failed to allocate scratch buffer "
+				   "space\n");
+		    }
+		    return FALSE;
+		}
 	    }
-	    return FALSE;
 	}
-	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-		       "%sAllocated %ld kB for the scratch buffer at 0x%lx\n",
-		       s, alloced / 1024, pI830->Scratch.Start);
 
 	/* Let's allocate another scratch buffer for the second head */
 	/* Again, this code won't execute on the dry run pass */
-	if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) {
-	    size = MAX_SCRATCH_BUFFER_SIZE;
-	    alloced = I830AllocVidMem(pScrn, &(pI830->Scratch2),
-				      &(pI830->StolenPool),
-				      size, GTT_PAGE_SIZE,
-				      flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
-	    if (alloced < size) {
-		size = MIN_SCRATCH_BUFFER_SIZE;
-		alloced = I830AllocVidMem(pScrn, &(pI830->Scratch2),
-					  &(pI830->StolenPool), size,
-					  GTT_PAGE_SIZE,
-					  flags | FROM_ANYWHERE |
-					  ALLOCATE_AT_TOP);
-	    }
-	    if (alloced < size) {
-		if (!dryrun) {
-		    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-			       "Failed to allocate second scratch buffer "
-			       "space\n");
+	if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2 &&
+	    pI830->xaa_scratch_2 == NULL)
+	{
+	    pI830->xaa_scratch_2 =
+		i830_allocate_memory(pScrn, "xaa scratch 2",
+				     MAX_SCRATCH_BUFFER_SIZE, GTT_PAGE_SIZE,
+				     flags);
+	    if (pI830->xaa_scratch_2 == NULL) {
+		pI830->xaa_scratch_2 =
+		    i830_allocate_memory(pScrn, "xaa scratch 2",
+					 MIN_SCRATCH_BUFFER_SIZE,
+					 GTT_PAGE_SIZE,
+					 flags);
+		if (pI830->xaa_scratch_2 == NULL) {
+		    if (!dryrun) {
+			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+				   "Failed to allocate secondary scratch "
+				   "buffer space\n");
+		    }
+		    return FALSE;
 		}
-		return FALSE;
 	    }
-	    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-			   "%sAllocated %ld kB for the second scratch buffer "
-			   "at 0x%lx\n", s,
-			   alloced / 1024, pI830->Scratch2.Start);
 	}
     }
 
     return TRUE;
 }
 
-void
-I830ResetAllocations(ScrnInfoPtr pScrn, const int flags)
-{
-    I830Ptr pI830 = I830PTR(pScrn);
-
-    pI830->MemoryAperture.Start = pI830->StolenMemory.End;
-    pI830->MemoryAperture.End = pI830->FbMapSize;
-    pI830->MemoryAperture.Size = pI830->FbMapSize - pI830->StolenMemory.Size;
-#ifdef XF86DRI
-    if (!pI830->directRenderingDisabled) {
-	pI830->MemoryAperture.End -= KB(pI830->mmSize);
-	pI830->MemoryAperture.Size -= KB(pI830->mmSize);
-    }
-#endif
-    pI830->StolenPool.Fixed = pI830->StolenMemory;
-    pI830->StolenPool.Total = pI830->StolenMemory;
-    pI830->StolenPool.Free = pI830->StolenPool.Total;
-    pI830->FreeMemory = pI830->TotalVideoRam - pI830->StolenPool.Total.Size;
-    pI830->allocatedMemory = 0;
-}
-
-long
-I830GetExcessMemoryAllocations(ScrnInfoPtr pScrn)
-{
-    I830Ptr pI830 = I830PTR(pScrn);
-    long allocated;
-
-    allocated = pI830->StolenPool.Total.Size + pI830->allocatedMemory;
-    if (allocated > pI830->TotalVideoRam)
-	return allocated - pI830->TotalVideoRam;
-    else
-       return 0;
-}
-
 #ifdef XF86DRI
 static unsigned int
 myLog2(unsigned int n)
@@ -1062,16 +1054,13 @@ myLog2(unsigned int n)
     return log2;
 }
 
-Bool
-I830AllocateBackBuffer(ScrnInfoPtr pScrn, const int flags)
+static Bool
+i830_allocate_backbuffer(ScrnInfoPtr pScrn, const int flags)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    unsigned long size, alloced, align = 0;
-    Bool tileable;
+    unsigned int pitch = pScrn->displayWidth * pI830->cpp;
+    unsigned long size;
     Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
-    int verbosity = dryrun ? 4 : 1;
-    const char *s = dryrun ? "[dryrun] " : "";
-    int lines;
     int height;
 
     if (pI830->rotation & (RR_Rotate_0 | RR_Rotate_180))
@@ -1079,152 +1068,106 @@ I830AllocateBackBuffer(ScrnInfoPtr pScrn
     else
 	height = pScrn->virtualX;
 
-    /* Back Buffer */
-    memset(&(pI830->BackBuffer), 0, sizeof(pI830->BackBuffer));
-    pI830->BackBuffer.Key = -1;
-    tileable = !(flags & ALLOC_NO_TILING) &&
-	IsTileable(pScrn, pScrn->displayWidth * pI830->cpp);
-    if (tileable) {
-	/* Make the height a multiple of the tile height (16) */
-	lines = (height + 15) / 16 * 16;
-    } else {
-	lines = height;
+    /* Try to allocate on the best tile-friendly boundaries. */
+    if (!(flags & ALLOC_NO_TILING) && IsTileable(pScrn, pitch))
+    {
+	size = ROUND_TO_PAGE(pitch * ALIGN(height, 16));
+	pI830->back_buffer =
+	    i830_allocate_memory_tiled(pScrn, "back buffer",
+				       size, pitch, GTT_PAGE_SIZE,
+				       flags | ALIGN_BOTH_ENDS,
+				       TILING_XMAJOR);
+	pI830->back_tiled = FENCE_XMAJOR;
+    }
+
+    /* Otherwise, just allocate it linear */
+    if (pI830->back_buffer == NULL) {
+	size = ROUND_TO_PAGE(pitch * height);
+	pI830->back_buffer = i830_allocate_memory(pScrn, "back buffer",
+						  size, GTT_PAGE_SIZE,
+						  flags | ALIGN_BOTH_ENDS);
+	pI830->back_tiled = FENCE_LINEAR;
     }
 
-    size = ROUND_TO_PAGE(pScrn->displayWidth * lines * pI830->cpp);
-    /*
-     * Try to allocate on the best tile-friendly boundaries.
-     */
-    alloced = 0;
-    if (tileable) {
-	align = GetBestTileAlignment(size);
-	for (align = GetBestTileAlignment(size);
-	     align >= (IS_I9XX(pI830) ? MB(1) : KB(512)); align >>= 1)
-	{
-	    alloced = I830AllocVidMem(pScrn, &(pI830->BackBuffer),
-				      &(pI830->StolenPool), size, align,
-				      flags | FROM_ANYWHERE | ALLOCATE_AT_TOP |
-				      ALIGN_BOTH_ENDS);
-	    if (alloced >= size)
-		break;
-	}
-    }
-    if (alloced < size) {
-	/* Give up on trying to tile */
-	tileable = FALSE;
-	size = ROUND_TO_PAGE(pScrn->displayWidth * height * pI830->cpp);
-	align = GTT_PAGE_SIZE;
-	alloced = I830AllocVidMem(pScrn, &(pI830->BackBuffer),
-				  &(pI830->StolenPool), size, align,
-				  flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
-    }
-    if (alloced < size) {
+    if (pI830->back_buffer == NULL) {
 	if (!dryrun) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		       "Failed to allocate back buffer space.\n");
 	}
 	return FALSE;
     }
-    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-		   "%sAllocated %ld kB for the back buffer at 0x%lx.\n", s,
-		   alloced / 1024, pI830->BackBuffer.Start);
 
     return TRUE;
 }
 
-Bool
-I830AllocateDepthBuffer(ScrnInfoPtr pScrn, const int flags)
+static Bool
+i830_allocate_depthbuffer(ScrnInfoPtr pScrn, const int flags)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    unsigned long size, alloced, align = 0;
-    Bool tileable;
+    unsigned long size;
     Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
-    int verbosity = dryrun ? 4 : 1;
-    const char *s = dryrun ? "[dryrun] " : "";
-    int lines;
+    unsigned int pitch = pScrn->displayWidth * pI830->cpp;
     int height;
 
+    /* XXX: this rotation stuff is bogus */
     if (pI830->rotation & (RR_Rotate_0 | RR_Rotate_180))
 	height = pScrn->virtualY;
     else
 	height = pScrn->virtualX;
 
-    /* Depth Buffer -- same size as the back buffer */
-    memset(&(pI830->DepthBuffer), 0, sizeof(pI830->DepthBuffer));
-    pI830->DepthBuffer.Key = -1;
-    tileable = !(flags & ALLOC_NO_TILING) &&
-	IsTileable(pScrn, pScrn->displayWidth * pI830->cpp);
-    if (tileable) {
-	/* Make the height a multiple of the tile height (16) */
-	lines = (height + 15) / 16 * 16;
-    } else {
-	lines = height;
-    }
+    /* First try allocating it tiled */
+    if (!(flags & ALLOC_NO_TILING) && IsTileable(pScrn, pitch))
+    {
+	size = ROUND_TO_PAGE(pitch * ALIGN(height, 16));
 
-    size = ROUND_TO_PAGE(pScrn->displayWidth * lines * pI830->cpp);
-    /*
-     * Try to allocate on the best tile-friendly boundaries.
-     */
-    alloced = 0;
-    if (tileable) {
-	align = GetBestTileAlignment(size);
-	for (align = GetBestTileAlignment(size);
-	     align >= (IS_I9XX(pI830) ? MB(1) : KB(512)); align >>= 1)
-	{
-	    alloced = I830AllocVidMem(pScrn, &(pI830->DepthBuffer),
-				      &(pI830->StolenPool), size, align,
-				      flags | FROM_ANYWHERE | ALLOCATE_AT_TOP |
-				      ALIGN_BOTH_ENDS);
-	    if (alloced >= size)
-		break;
-	}
+	pI830->depth_buffer =
+	    i830_allocate_memory_tiled(pScrn, "depth buffer", size, pitch,
+				       GTT_PAGE_SIZE, flags | ALIGN_BOTH_ENDS,
+				       TILING_YMAJOR);
+	pI830->depth_tiled = FENCE_YMAJOR;
     }
-    if (alloced < size) {
-	/* Give up on trying to tile */
-	tileable = FALSE;
-	size = ROUND_TO_PAGE(pScrn->displayWidth * height * pI830->cpp);
-	align = GTT_PAGE_SIZE;
-	alloced = I830AllocVidMem(pScrn, &(pI830->DepthBuffer),
-				  &(pI830->StolenPool), size, align,
-				  flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
+
+    /* Otherwise, allocate it linear. */
+    if (pI830->depth_buffer == NULL) {
+	size = ROUND_TO_PAGE(pitch * height);
+	pI830->depth_buffer =
+	    i830_allocate_memory(pScrn, "depth buffer", size, GTT_PAGE_SIZE,
+				 flags);
+	pI830->depth_tiled = FENCE_LINEAR;
     }
-    if (alloced < size) {
+
+    if (pI830->depth_buffer == NULL) {
 	if (!dryrun) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		       "Failed to allocate depth buffer space.\n");
 	}
 	return FALSE;
     }
-    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-		   "%sAllocated %ld kB for the depth buffer at 0x%lx.\n", s,
-		   alloced / 1024, pI830->DepthBuffer.Start);
 
     return TRUE;
 }
 
-Bool
-I830AllocateTextureMemory(ScrnInfoPtr pScrn, const int flags)
+static Bool
+i830_allocate_texture_memory(ScrnInfoPtr pScrn, const int flags)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    unsigned long size, alloced;
+    unsigned long size;
     int i;
     Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
-    int verbosity = dryrun ? 4 : 1;
-    const char *s = dryrun ? "[dryrun] " : "";
 
-    /* Allocate the remaining space for textures. */
-    memset(&(pI830->TexMem), 0, sizeof(pI830->TexMem));
-    pI830->TexMem.Key = -1;
+    if (pI830->mmModeFlags & I830_KERNEL_MM) {
+	pI830->memory_manager =
+	    i830_allocate_aperture(pScrn, "DRI memory manager",
+				   pI830->mmSize, GTT_PAGE_SIZE,
+				   flags | ALIGN_BOTH_ENDS);
+	/* XXX: try memory manager size backoff here? */
+	if (pI830->memory_manager == NULL)
+	    return FALSE;
+    }
 
     if (pI830->mmModeFlags & I830_KERNEL_TEX) {
-	if (dryrun && pI830->pEnt->device->videoRam == 0) {
-	    /* If we're laying out a default-sized allocation, then don't be
-	     * too greedy and just ask for 32MB.
-	     */
-	    size = MB(32);
-	} else {
-	    size = GetFreeSpace(pScrn);
-	}
+	/* XXX: auto-sizing */
+	size = MB(32);
 	if (dryrun && (size < MB(1)))
 	    size = MB(1);
 	i = myLog2(size / I830_NR_TEX_REGIONS);
@@ -1237,306 +1180,157 @@ I830AllocateTextureMemory(ScrnInfoPtr pS
 	if (size < KB(512)) {
 	    if (!dryrun) {
 		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-			   "Less than 512 kBytes for texture space (real %ld "
+			   "Less than 512 kBytes for texture space (real %ld"
 			   "kBytes).\n",
 			   size / 1024);
 	    }
 	    return FALSE;
 	}
-	alloced = I830AllocVidMem(pScrn, &(pI830->TexMem),
-				  &(pI830->StolenPool), size, GTT_PAGE_SIZE,
-				  flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
-	if (alloced < size) {
+	pI830->textures = i830_allocate_memory(pScrn, "textures", size,
+					       GTT_PAGE_SIZE, flags);
+	if (pI830->textures == NULL) {
 	    if (!dryrun) {
 		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 			   "Failed to allocate texture space.\n");
 	    }
 	    return FALSE;
 	}
-	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-		       "%sAllocated %ld kB for textures at 0x%lx\n", s,
-		       alloced / 1024, pI830->TexMem.Start);
     }
 
     return TRUE;
 }
 
 Bool
-I830Allocate3DMemory(ScrnInfoPtr pScrn, const int flags)
+i830_allocate_3d_memory(ScrnInfoPtr pScrn, const int flags)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    unsigned long size, alloced;
     Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
-    int verbosity = dryrun ? 4 : 1;
-    const char *s = dryrun ? "[dryrun] " : "";
 
     DPRINTF(PFX, "I830Allocate3DMemory\n");
 
     /* Space for logical context.  32k is fine for right now. */
-    memset(&(pI830->ContextMem), 0, sizeof(pI830->ContextMem));
-    pI830->ContextMem.Key = -1;
-    size = KB(32);
-    alloced = I830AllocVidMem(pScrn, &(pI830->ContextMem),
-			      &(pI830->StolenPool), size, GTT_PAGE_SIZE,
-			      flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
-    if (alloced < size) {
+    pI830->logical_context = i830_allocate_memory(pScrn, "logical 3D context",
+						  KB(32), GTT_PAGE_SIZE,
+						  flags);
+    if (pI830->logical_context == NULL) {
 	if (!dryrun) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		       "Failed to allocate logical context space.\n");
 	}
 	return FALSE;
     }
-    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-		   "%sAllocated %ld kB for the logical context at 0x%lx.\n", s,
-		   alloced / 1024, pI830->ContextMem.Start);
 
-    if (!I830AllocateBackBuffer(pScrn, flags))
+    if (!i830_allocate_backbuffer(pScrn, flags))
 	return FALSE;
 
-    if (!I830AllocateDepthBuffer(pScrn, flags))
+    if (!i830_allocate_depthbuffer(pScrn, flags))
 	return FALSE;
 
-    if (!I830AllocateTextureMemory(pScrn, flags))
+    if (!i830_allocate_texture_memory(pScrn, flags))
 	return FALSE;
 
     return TRUE;
 }
 #endif
 
-/* Allocate pool space that isn't pre-allocated */
-Bool
-I830DoPoolAllocation(ScrnInfoPtr pScrn, I830MemPool *pool)
-{
-    I830Ptr pI830 = I830PTR(pScrn);
-
-    DPRINTF(PFX, "I830DoPoolAllocation\n");
-
-    if (!pool)
-	return FALSE;
-
-    /*
-     * Sanity check: there shouldn't be an allocation required when
-     * there is only stolen memory.
-     */
-    if (pI830->StolenOnly && (pool->Total.Size > pool->Fixed.Size)) {
-	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		   "I830DoPoolAllocation(): pool size is greater than the "
-		   "preallocated size,\n\t"
-		   "and there is no allocatable memory.\n");
-	return FALSE;
-    }
-
-    if (pool->Total.Size > pool->Fixed.Size) {
-	pool->Allocated.Size = pool->Total.Size - pool->Fixed.Size;
-	pool->Allocated.Key = xf86AllocateGARTMemory(pScrn->scrnIndex,
-						     pool->Allocated.Size, 0,
-						     NULL);
-	if (pool->Allocated.Key == -1) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Pool allocation failed\n");
-	    return FALSE;
-	}
-	pool->Allocated.Start = pool->Fixed.End;
-	pool->Allocated.End = pool->Total.Size;
-	pool->Allocated.Offset = pool->Allocated.Start;
-    } else
-	pool->Allocated.Key = -1;
-    return TRUE;
-}
-
-static unsigned long topOfMem = 0;
-
-/*
- * These modify the way memory is positioned within the aperture.
- *
- * By default, memory allocated from the bottom or specifically within
- * the pool at the bottom gets allocated from the "stolen pool", which is
- * actually the stolen memory plus any extra allocated to make it a larger
- * contiguous region.  Memory allocated from the AGP is allocated top-down
- * from the end of the aperture space.  Memory allocated "from top" defaults
- * to AGP if there is enough "free space".  The total allocation (stolen +
- * extra) doesn't exceed the orignal pScrn->videoRam amount (this isn't true
- * when memory allocated from AGP gets moved into the pool by one of the
- * following options.
- *
- * XXX Write a better description.
- *
- */
-#define PACK_RANGES 0
-#define POOL_RANGES 0
-
-Bool
-I830FixOffset(ScrnInfoPtr pScrn, I830MemRange *mem)
-{
-#if POOL_RANGES
-    I830Ptr pI830 = I830PTR(pScrn);
-#endif
-
-    if (!mem)
-	return FALSE;
-
-    if (mem->Pool && mem->Key == -1 && mem->Start < 0) {
-	mem->Start = mem->Pool->Total.End + mem->Start;
-	mem->End = mem->Start + mem->Size;
-    }
-#if PACK_RANGES
-    /*
-     * Map AGP-allocated areas at the top of the stolen area, resulting in
-     * a contiguous region in the aperture.  Normally most AGP-allocated areas
-     * will be at the top of the aperture, making alignment requirements
-     * easier to achieve.  This optin is primarily for debugging purposes,
-     * and using this option can break any special alignment requirements.
-     */
-    if (!mem->Pool && mem->Start != 0 && mem->Key != -1 &&
-	mem->Physical == 0 && mem->Offset != 0)
-    {
-	long diff;
-	if (mem->Offset != mem->Start)
-	    ErrorF("mem %p, Offset != Start\n", mem);
-	diff = mem->Offset - topOfMem;
-	mem->Start -= diff;
-	mem->End -= diff;
-	mem->Offset -= diff;
-	topOfMem += mem->Size;
-    }
-#elif POOL_RANGES
-    /*
-     * Move AGP-allocated regions (that don't need a physical address) into
-     * the pre-allocated pool when there's enough space to do so.  Note: the
-     * AGP-allocated areas aren't freed.  This option is primarily for
-     * debugging purposes, and using it can break any special alignment
-     * requirements.
-     */
-    if (!mem->Pool && mem->Start >= pI830->StolenPool.Free.End &&
-	mem->Key != -1 && mem->Physical == 0 && mem->Offset != 0 &&
-	pI830->StolenPool.Free.Size >= mem->Size)
-    {
-	long diff;
-
-	if (mem->Offset != mem->Start)
-	    ErrorF("mem %p, Offset != Start\n", mem);
-	diff = mem->Offset - pI830->StolenPool.Free.Start;
-	mem->Start -= diff;
-	mem->End -= diff;
-	mem->Offset -= diff;
-	mem->Key = -1;
-	pI830->StolenPool.Free.Start += mem->Size;
-	pI830->StolenPool.Free.Size -= mem->Size;
-    }
-#endif
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-	       "%p: Memory at offset 0x%08lx, size %ld kBytes\n", (void *)mem,
-	       mem->Start, mem->Size / 1024);
-    return TRUE;
-}
-
-Bool
-I830FixupOffsets(ScrnInfoPtr pScrn)
-{
-    I830Ptr pI830 = I830PTR(pScrn);
-    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-    int i;
-
-    DPRINTF(PFX, "I830FixupOffsets\n");
-
-    topOfMem = pI830->StolenPool.Total.End;
-    if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2)
-	I830FixOffset(pScrn, &(pI830->FrontBuffer2));
-    I830FixOffset(pScrn, &(pI830->FrontBuffer));
-
-    for (i = 0; i < xf86_config->num_crtc; i++) {
-	I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private;
-
-	I830FixOffset(pScrn, &intel_crtc->cursor_mem);
-	I830FixOffset(pScrn, &intel_crtc->cursor_mem_argb);
-    }
-
-    I830FixOffset(pScrn, &(pI830->LpRing->mem));
-    I830FixOffset(pScrn, &(pI830->Scratch));
-    if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2)
-	I830FixOffset(pScrn, &(pI830->Scratch2));
-#ifdef I830_XV
-    if (pI830->XvEnabled) {
-	I830FixOffset(pScrn, pI830->OverlayMem);
-	if (pI830->LinearAlloc)
-	    I830FixOffset(pScrn, &(pI830->LinearMem));
-    }
-#endif
-#ifdef XF86DRI
-    if (pI830->directRenderingEnabled) {
-	I830FixOffset(pScrn, &(pI830->ContextMem));
-	I830FixOffset(pScrn, &(pI830->BackBuffer));
-	I830FixOffset(pScrn, &(pI830->DepthBuffer));
-	if (pI830->mmModeFlags & I830_KERNEL_TEX) {
-	    I830FixOffset(pScrn, &(pI830->TexMem));
-	}
-    }
-#endif
-#ifdef I830_USE_EXA
-    if (pI830->useEXA) {
-	I830FixOffset(pScrn, &(pI830->Offscreen));
-	if (IS_I965G(pI830))
-	    I830FixOffset(pScrn, &(pI830->EXAStateMem));
-    }
-#endif
-    return TRUE;
-}
-
 #ifdef XF86DRI
-/* Tiled memory is good... really, really good...
+/**
+ * Sets up a fence area for the hardware.
  *
- * Need to make it less likely that we miss out on this - probably
- * need to move the frontbuffer away from the 'guarenteed' alignment
- * of the first memory segment, or perhaps allocate a discontigous
- * framebuffer to get more alignment 'sweet spots'.
+ * The fences control automatic tiled address swizzling for CPU access of the
+ * framebuffer.
  */
 static void
-SetFence(ScrnInfoPtr pScrn, int nr, unsigned int start, unsigned int pitch,
-         unsigned int size)
+i830_set_fence(ScrnInfoPtr pScrn, int nr, unsigned int offset,
+	       unsigned int pitch, unsigned int size,
+	       enum tile_format tile_format)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    I830RegPtr i830Reg = &pI830->ModeReg;
     CARD32 val;
     CARD32 fence_mask = 0;
     unsigned int fence_pitch;
 
-    DPRINTF(PFX, "SetFence: %d, 0x%08x, %d, %d kByte\n",
-	    nr, start, pitch, size / 1024);
+    DPRINTF(PFX, "i830_set_fence(): %d, 0x%08x, %d, %d kByte\n",
+	    nr, offset, pitch, size / 1024);
+
+    assert(tile_format != TILING_NONE);
+
+    if (IS_I965G(pI830)) {
+	if (nr < 0 || nr >= FENCE_NEW_NR) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		       "i830_set_fence(): fence %d out of range\n",nr);
+	    return;
+	}
+
+	switch (tile_format) {
+	case TILING_XMAJOR:
+            pI830->fence[nr] = (((pitch / 128) - 1) << 2) | offset | 1;
+	    pI830->fence[nr] |= I965_FENCE_X_MAJOR;
+            break;
+	case TILING_YMAJOR:
+            /* YMajor can be 128B aligned but the current code dictates
+             * otherwise. This isn't a problem apart from memory waste.
+             * FIXME */
+            pI830->fence[nr] = (((pitch / 128) - 1) << 2) | offset | 1;
+	    pI830->fence[nr] |= I965_FENCE_Y_MAJOR;
+            break;
+	case TILING_NONE:
+            break;
+	}
+
+	/* XXX Is it the next page, or the last page of the fenced region? */
+	pI830->fence[FENCE_NEW_NR + nr] = offset + size;
+	return;
+    }
 
-    if (nr < 0 || nr > 7) {
+    if (nr < 0 || nr >= FENCE_NR) {
 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		   "SetFence: fence %d out of range\n",nr);
+		   "i830_set_fence(): fence %d out of range\n",nr);
 	return;
     }
 
-    i830Reg->Fence[nr] = 0;
+    pI830->fence[nr] = 0;
 
     if (IS_I9XX(pI830))
    	fence_mask = ~I915G_FENCE_START_MASK;
     else
    	fence_mask = ~I830_FENCE_START_MASK;
 
-    if (start & fence_mask) {
+    if (offset & fence_mask) {
 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		   "SetFence: %d: start (0x%08x) is not %s aligned\n",
-		   nr, start, (IS_I9XX(pI830)) ? "1MB" : "512k");
+		   "i830_set_fence(): %d: offset (0x%08x) is not %s aligned\n",
+		   nr, offset, (IS_I9XX(pI830)) ? "1MB" : "512k");
 	return;
     }
 
-    if (start % size) {
+    if (offset % size) {
 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		   "SetFence: %d: start (0x%08x) is not size (%dk) aligned\n",
-		   nr, start, size / 1024);
+		   "i830_set_fence(): %d: offset (0x%08x) is not size (%dk) "
+		   "aligned\n",
+		   nr, offset, size / 1024);
 	return;
     }
 
     if (pitch & 127) {
 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		   "SetFence: %d: pitch (%d) not a multiple of 128 bytes\n",
+		   "i830_set_fence(): %d: pitch (%d) not a multiple of 128 "
+		   "bytes\n",
 		   nr, pitch);
 	return;
     }
 
-    val = (start | FENCE_X_MAJOR | FENCE_VALID);
+    val = offset | FENCE_VALID;
+
+    switch (tile_format) {
+    case TILING_XMAJOR:
+	val |= FENCE_X_MAJOR;
+	break;
+    case TILING_YMAJOR:
+	val |= FENCE_Y_MAJOR;
+	break;
+    case TILING_NONE:
+	break;
+    }
 
     if (IS_I9XX(pI830)) {
    	switch (size) {
@@ -1552,9 +1346,9 @@ SetFence(ScrnInfoPtr pScrn, int nr, unsi
 	case MB(8):
 	    val |= I915G_FENCE_SIZE_8M;
 	    break;
-   	   case MB(16):
-	       val |= I915G_FENCE_SIZE_16M;
-	       break;
+	case MB(16):
+	    val |= I915G_FENCE_SIZE_16M;
+	    break;
 	case MB(32):
 	    val |= I915G_FENCE_SIZE_32M;
 	    break;
@@ -1562,8 +1356,8 @@ SetFence(ScrnInfoPtr pScrn, int nr, unsi
 	    val |= I915G_FENCE_SIZE_64M;
 	    break;
 	default:
-	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		       "SetFence: %d: illegal size (%d kByte)\n",
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "i830_set_fence(): %d: illegal size (%d kByte)\n",
 		       nr, size / 1024);
 	    return;
    	}
@@ -1594,8 +1388,8 @@ SetFence(ScrnInfoPtr pScrn, int nr, unsi
 	    val |= FENCE_SIZE_64M;
 	    break;
 	default:
-	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		       "SetFence: %d: illegal size (%d kByte)\n",
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "i830_set_fence(): %d: illegal size (%d kByte)\n",
 		       nr, size / 1024);
 	    return;
    	}
@@ -1620,8 +1414,8 @@ SetFence(ScrnInfoPtr pScrn, int nr, unsi
 	val |= FENCE_PITCH_8;
 	break;
     case 16:
-       val |= FENCE_PITCH_16;
-       break;
+	val |= FENCE_PITCH_16;
+	break;
     case 32:
 	val |= FENCE_PITCH_32;
 	break;
@@ -1629,352 +1423,82 @@ SetFence(ScrnInfoPtr pScrn, int nr, unsi
 	val |= FENCE_PITCH_64;
 	break;
     default:
-	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		   "SetFence: %d: illegal pitch (%d)\n", nr, pitch);
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "i830_set_fence(): %d: illegal pitch (%d)\n", nr, pitch);
 	return;
     }
 
-    i830Reg->Fence[nr] = val;
+    pI830->fence[nr] = val;
 }
-
-static Bool
-MakeTiles(ScrnInfoPtr pScrn, I830MemRange *pMem, unsigned int fence)
-{
-    I830Ptr pI830 = I830PTR(pScrn);
-    int pitch, ntiles, i;
-
-#if 0
-    /* Hack to "improve" the alignment of the front buffer. */
-    while (!(pMem->Start & ~pMem->Alignment) && pMem->Alignment < 0x00400000 )
-	pMem->Alignment <<= 1;
 #endif
 
-    if (tileGeneration != serverGeneration) {
-	tileGeneration = serverGeneration;
-	nextTile = 0;
-    }
-
-    pitch = pScrn->displayWidth * pI830->cpp;
-
-    if (IS_I965G(pI830)) {
-	I830RegPtr i830Reg = &pI830->ModeReg;
-
-	switch (fence) {
-	case FENCE_XMAJOR:
-            i830Reg->Fence[nextTile] = (((pitch / 128) - 1) << 2) |
-		pMem->Start | 1;
-            break;
-	case FENCE_YMAJOR:
-            /* YMajor can be 128B aligned but the current code dictates
-             * otherwise. This isn't a problem apart from memory waste.
-             * FIXME */
-            i830Reg->Fence[nextTile] = (((pitch / 128) - 1) << 2) |
-		pMem->Start | 1;
-	    i830Reg->Fence[nextTile] |= (1<<1);
-            break;
-	default:
-	case FENCE_LINEAR:
-            break;
-	}
-
-	i830Reg->Fence[nextTile+FENCE_NEW_NR] = pMem->End;
-	nextTile++;
-	return TRUE;
-    }
-
-    /*
-     * Simply try to break the region up into at most four pieces of size
-     * equal to the alignment.
-     */
-    ntiles = ROUND_TO(pMem->Size, pMem->Alignment) / pMem->Alignment;
-    if (ntiles >= 4) {
-	return FALSE;
-    }
-
-    for (i = 0; i < ntiles; i++, nextTile++) {
-	SetFence(pScrn, nextTile, pMem->Start + i * pMem->Alignment,
-		 pitch, pMem->Alignment);
-    }
-    return TRUE;
-}
-
-void
-I830SetupMemoryTiling(ScrnInfoPtr pScrn)
-{
-    I830Ptr pI830 = I830PTR(pScrn);
-    int i;
-
-    /* Clear out */
-    if (IS_I965G(pI830)) {
-	for (i = 0; i < FENCE_NEW_NR*2; i++)
-	    pI830->ModeReg.Fence[i] = 0;
-    } else {
-	for (i = 0; i < 8; i++)
-	    pI830->ModeReg.Fence[i] = 0;
-    }
-
-    nextTile = 0;
-    tileGeneration = -1;
-
-    /* We currently only attempt to tile the back and depth buffers. */
-    if (!pI830->directRenderingEnabled)
-	return;
-
-    if (!IsTileable(pScrn, pScrn->displayWidth * pI830->cpp)) {
-	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		   "I830SetupMemoryTiling: Not tileable 0x%x\n",
-		   pScrn->displayWidth * pI830->cpp);
-	pI830->allowPageFlip = FALSE;
-	return;
-    }
-
-    pI830->front_tiled = FENCE_LINEAR;
-    pI830->back_tiled = FENCE_LINEAR;
-    pI830->depth_tiled = FENCE_LINEAR;
-
-    if (pI830->allowPageFlip) {
-	if (pI830->allowPageFlip && pI830->FrontBuffer.Alignment >= KB(512)) {
-	    if (MakeTiles(pScrn, &(pI830->FrontBuffer), FENCE_XMAJOR)) {
-		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-			   "Activating tiled memory for the front buffer\n");
-		pI830->front_tiled = FENCE_XMAJOR;
-	    } else {
-		pI830->allowPageFlip = FALSE;
-		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-			   "MakeTiles failed for the front buffer\n");
-	    }
-	} else {
-	    pI830->allowPageFlip = FALSE;
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		       "Alignment bad for the front buffer\n");
-	}
-    }
-
-    /*
-     * We tried to get the best alignment during the allocation.  Check
-     * the alignment values to tell.  If well-aligned allocations were
-     * successful, the address range reserved is a multiple of the align
-     * value.
-     */
-    if (pI830->BackBuffer.Alignment >= KB(512)) {
-	if (MakeTiles(pScrn, &(pI830->BackBuffer), FENCE_XMAJOR)) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		       "Activating tiled memory for the back buffer.\n");
-	    pI830->back_tiled = FENCE_XMAJOR;
-	} else {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		       "MakeTiles failed for the back buffer.\n");
-	    pI830->allowPageFlip = FALSE;
-	}
-    }
-
-    if (pI830->DepthBuffer.Alignment >= KB(512)) {
-	if (MakeTiles(pScrn, &(pI830->DepthBuffer), FENCE_YMAJOR)) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		       "Activating tiled memory for the depth buffer.\n");
-	    pI830->depth_tiled = FENCE_YMAJOR;
-	} else {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		       "MakeTiles failed for the depth buffer.\n");
-	}
-    }
-}
-#endif /* XF86DRI */
-
-static Bool
-BindMemRange(ScrnInfoPtr pScrn, I830MemRange *mem)
-{
-    if (!mem)
-	return FALSE;
-
-    if (mem->Key == -1)
-	return TRUE;
-
-    return xf86BindGARTMemory(pScrn->scrnIndex, mem->Key, mem->Offset);
-}
-
+/**
+ * Called at EnterVT to grab the AGP GART and bind our allocations.
+ *
+ * In zaphod mode, this will walk the list trying to bind twice, since each
+ * pI830 points to the same allocation list, but the bind_memory will just
+ * no-op then.
+ */
 Bool
-I830BindAGPMemory(ScrnInfoPtr pScrn)
+i830_bind_all_memory(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
 
-    DPRINTF(PFX,
-	    "I830BindAGPMemory: StolenOnly is %s, pI830->GttBound is %s\n",
-	    BOOLTOSTRING(pI830->StolenOnly), BOOLTOSTRING(pI830->GttBound));
-
-    if (pI830->StolenOnly == TRUE)
+    if (pI830->StolenOnly == TRUE || pI830->memory_list == NULL)
 	return TRUE;
 
-    if (xf86AgpGARTSupported() && !pI830->GttBound) {
-	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-	int i;
+    if (xf86AgpGARTSupported() && !pI830->gtt_acquired) {
+	i830_memory *mem;
 
 	if (!xf86AcquireGART(pScrn->scrnIndex))
 	    return FALSE;
 
-#if REMAP_RESERVED
-	/* Rebind the pre-allocated region. */
-	BindMemRange(pScrn, &(pI830->Dummy));
-#endif
-
-	if (!BindMemRange(pScrn, &(pI830->StolenPool.Allocated)))
-	    return FALSE;
-	if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2)
-	    if (!BindMemRange(pScrn, &(pI830->FrontBuffer2)))
-		return FALSE;
-	if (!BindMemRange(pScrn, &(pI830->FrontBuffer)))
-	    return FALSE;
-
-	for (i = 0; i < xf86_config->num_crtc; i++) {
-	  I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private;
+	pI830->gtt_acquired = TRUE;
 
-	  if (!BindMemRange(pScrn, &intel_crtc->cursor_mem))
-	      return FALSE;
-	  if (!BindMemRange(pScrn, &intel_crtc->cursor_mem_argb))
-	      return FALSE;
-	}
-	if (!BindMemRange(pScrn, &(pI830->LpRing->mem)))
-	    return FALSE;
-	if (!BindMemRange(pScrn, &(pI830->Scratch)))
-	    return FALSE;
-	if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2)
-	    if (!BindMemRange(pScrn, &(pI830->Scratch2)))
-		return FALSE;
-#ifdef I830_XV
-	if (pI830->XvEnabled) {
-	    if (!BindMemRange(pScrn, pI830->OverlayMem))
-		return FALSE;
-	    if (pI830->LinearAlloc)
-		if (!BindMemRange(pScrn, &(pI830->LinearMem)))
-		    return FALSE;
-      }
-#endif
-#ifdef XF86DRI
-	if (pI830->directRenderingEnabled) {
-	    if (!BindMemRange(pScrn, &(pI830->ContextMem)))
-		return FALSE;
-	    if (!BindMemRange(pScrn, &(pI830->BackBuffer)))
-		return FALSE;
-	    if (!BindMemRange(pScrn, &(pI830->DepthBuffer)))
-		return FALSE;
-	    if ((pI830->mmModeFlags & I830_KERNEL_TEX) &&
-		!BindMemRange(pScrn, &(pI830->TexMem)))
-		return FALSE;
-      }
-#endif
-#ifdef I830_USE_EXA
-	if (pI830->useEXA) {
-	    if (!BindMemRange(pScrn, &(pI830->Offscreen)))
-		return FALSE;
-	    if (IS_I965G(pI830) && !BindMemRange(pScrn, &(pI830->EXAStateMem)))
-		return FALSE;
+	for (mem = pI830->memory_list->next; mem->next != NULL;
+	     mem = mem->next)
+	{
+	    if (!i830_bind_memory(pScrn, mem)) {
+		/* This shouldn't happen */
+		FatalError("Couldn't bind memory for %s\n", mem->name);
+	    }
 	}
-#endif
-	pI830->GttBound = 1;
     }
 
     return TRUE;
 }
 
-static Bool
-UnbindMemRange(ScrnInfoPtr pScrn, I830MemRange *mem)
-{
-    if (!mem)
-	return FALSE;
-
-    if (mem->Key == -1)
-	return TRUE;
-
-    return xf86UnbindGARTMemory(pScrn->scrnIndex, mem->Key);
-}
-
-
+/** Called at LeaveVT, to unbind all of our AGP allocations. */
 Bool
-I830UnbindAGPMemory(ScrnInfoPtr pScrn)
+i830_unbind_all_memory(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
 
-    DPRINTF(PFX,
-	    "I830UnbindAGPMemory: StolenOnly is %s, pI830->GttBound is %s\n",
-	    BOOLTOSTRING(pI830->StolenOnly), BOOLTOSTRING(pI830->GttBound));
-
     if (pI830->StolenOnly == TRUE)
 	return TRUE;
 
-    if (xf86AgpGARTSupported() && pI830->GttBound) {
-	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-	int i;
-
-#if REMAP_RESERVED
-	/* "unbind" the pre-allocated region. */
-	UnbindMemRange(pScrn, &(pI830->Dummy));
-#endif
+    if (xf86AgpGARTSupported() && pI830->gtt_acquired) {
+	i830_memory *mem;
 
-	if (!UnbindMemRange(pScrn, &(pI830->StolenPool.Allocated)))
-	    return FALSE;
-	if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2)
-	    if (!UnbindMemRange(pScrn, &(pI830->FrontBuffer2)))
-		return FALSE;
-	if (!UnbindMemRange(pScrn, &(pI830->FrontBuffer)))
-	    return FALSE;
-
-	for (i = 0; i < xf86_config->num_crtc; i++) {
-	    I830CrtcPrivatePtr intel_crtc =
-		xf86_config->crtc[i]->driver_private;
-
-	    if (!UnbindMemRange(pScrn, &intel_crtc->cursor_mem))
-		return FALSE;
-	    if (!UnbindMemRange(pScrn, &intel_crtc->cursor_mem_argb))
-		return FALSE;
+	for (mem = pI830->memory_list->next; mem->next != NULL;
+	     mem = mem->next)
+	{
+	    i830_unbind_memory(pScrn, mem);
 	}
 
-	if (!UnbindMemRange(pScrn, &(pI830->LpRing->mem)))
-	    return FALSE;
-	if (!UnbindMemRange(pScrn, &(pI830->Scratch)))
-	    return FALSE;
-	if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2)
-	    if (!UnbindMemRange(pScrn, &(pI830->Scratch2)))
-		return FALSE;
-#ifdef I830_XV
-	if (pI830->XvEnabled) {
-	    if (!UnbindMemRange(pScrn, pI830->OverlayMem))
-		return FALSE;
-	    if (pI830->LinearAlloc)
-		if (!UnbindMemRange(pScrn, &(pI830->LinearMem)))
-		    return FALSE;
-	}
-#endif
-#ifdef XF86DRI
-	if (pI830->directRenderingEnabled) {
-	    if (!UnbindMemRange(pScrn, &(pI830->ContextMem)))
-		return FALSE;
-	    if (!UnbindMemRange(pScrn, &(pI830->BackBuffer)))
-		return FALSE;
-	    if (!UnbindMemRange(pScrn, &(pI830->DepthBuffer)))
-		return FALSE;
-	    if ((pI830->mmModeFlags & I830_KERNEL_TEX) &&
-		!UnbindMemRange(pScrn, &(pI830->TexMem)))
-		return FALSE;
-	}
-#endif
-#ifdef I830_USE_EXA
-	if (pI830->useEXA) {
-	    if (!UnbindMemRange(pScrn, &(pI830->Offscreen)))
-		return FALSE;
-	    if (IS_I965G(pI830) && !UnbindMemRange(pScrn,
-						   &(pI830->EXAStateMem)))
-		return FALSE;
-	}
-#endif
+	pI830->gtt_acquired = FALSE;
+
 	if (!xf86ReleaseGART(pScrn->scrnIndex))
 	    return FALSE;
-
-	pI830->GttBound = 0;
     }
 
     return TRUE;
 }
 
+/**
+ * Returns the amount of system memory that could potentially be allocated
+ * from AGP, in kB.
+ */
 long
 I830CheckAvailableMemory(ScrnInfoPtr pScrn)
 {
diff --git a/src/i830_video.c b/src/i830_video.c
index 22f5bee..92f094f 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -184,9 +184,9 @@ void exaMoveInPixmap (PixmapPtr pPixmap)
 	 OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_CONTINUE);		\
       }									\
       if (IS_I965G(pI830)) 						\
-         OUT_RING(pI830->OverlayMem->Start | OFC_UPDATE); 		\
+         OUT_RING(pI830->overlay_regs->offset | OFC_UPDATE); 		\
       else								\
-	 OUT_RING(pI830->OverlayMem->Physical | OFC_UPDATE);		\
+	 OUT_RING(pI830->overlay_regs->bus_addr | OFC_UPDATE);		\
       OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);		\
       OUT_RING(MI_NOOP);						\
       ADVANCE_LP_RING();						\
@@ -202,9 +202,9 @@ void exaMoveInPixmap (PixmapPtr pPixmap)
          OUT_RING(MI_NOOP);    						\
 	 OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_OFF);		\
          if (IS_I965G(pI830)) 						\
-            OUT_RING(pI830->OverlayMem->Start | OFC_UPDATE); 		\
+            OUT_RING(pI830->overlay_regs->offset | OFC_UPDATE);		\
          else								\
-	    OUT_RING(pI830->OverlayMem->Physical | OFC_UPDATE);		\
+	    OUT_RING(pI830->overlay_regs->bus_addr | OFC_UPDATE);	\
 	 OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);	\
 	 OUT_RING(MI_NOOP);						\
 	 ADVANCE_LP_RING();						\
@@ -496,10 +496,10 @@ I830ResetVideo(ScrnInfoPtr pScrn)
    I830Ptr pI830 = I830PTR(pScrn);
    I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr;
    I830OverlayRegPtr overlay =
-	 (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start);
+	 (I830OverlayRegPtr) (pI830->FbBase + pI830->overlay_regs->offset);
 
    OVERLAY_DEBUG("I830ResetVideo: base: %p, offset: 0x%lx, obase: %p\n",
-	   pI830->FbBase, pI830->OverlayMem->Start, overlay);
+	   pI830->FbBase, pI830->overlay_regs->offset, overlay);
    /*
     * Default to maximum image size in YV12
     */
@@ -926,7 +926,7 @@ I830SetPortAttribute(ScrnInfoPtr pScrn,
    I830PortPrivPtr pPriv = (I830PortPrivPtr) data;
    I830Ptr pI830 = I830PTR(pScrn);
    I830OverlayRegPtr overlay =
-	 (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start);
+	 (I830OverlayRegPtr) (pI830->FbBase + pI830->overlay_regs->offset);
 
    if (pPriv->textured) {
       /* XXX: Currently the brightness/saturation attributes aren't hooked up.
@@ -1553,7 +1553,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
    I830Ptr pI830 = I830PTR(pScrn);
    I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr;
    I830OverlayRegPtr overlay =
-	 (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start);
+	 (I830OverlayRegPtr) (pI830->FbBase + pI830->overlay_regs->offset);
    unsigned int swidth;
    unsigned int mask, shift, offsety, offsetu;
    int tmp;
@@ -2076,7 +2076,8 @@ I830AllocateMemory(ScrnInfoPtr pScrn, st
       /* Converts an offset from XAA's linear allocator to an offset from the
        * start of fb.
        */
-#define XAA_OFFSET_TO_OFFSET(x) (pI830->FrontBuffer.Start + (x * pI830->cpp))
+#define XAA_OFFSET_TO_OFFSET(x) \
+	(pI830->front_buffer->offset + (x * pI830->cpp))
 
       /* The XFree86 linear allocator operates in units of screen pixels,
        * sadly.
@@ -2160,7 +2161,7 @@ I830PutImage(ScrnInfoPtr pScrn,
    I830PortPrivPtr pPriv = (I830PortPrivPtr) data;
    ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
    I830OverlayRegPtr overlay =
-	 (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start);
+	 (I830OverlayRegPtr) (pI830->FbBase + pI830->overlay_regs->offset);
    PixmapPtr pPixmap;
    INT32 x1, x2, y1, y2;
    int srcPitch, srcPitch2 = 0, dstPitch, destId;
@@ -2700,7 +2701,7 @@ I830DisplaySurface(XF86SurfacePtr surfac
    I830Ptr pI830 = I830PTR(pScrn);
    I830PortPrivPtr pI830Priv = GET_PORT_PRIVATE(pScrn);
    I830OverlayRegPtr overlay =
-	 (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start);
+	 (I830OverlayRegPtr) (pI830->FbBase + pI830->overlay_regs->offset);
    INT32 x1, y1, x2, y2;
    INT32 loops = 0;
    BoxRec dstBox;
diff --git a/src/i830_xaa.c b/src/i830_xaa.c
index 5ef5d3c..f095138 100644
--- a/src/i830_xaa.c
+++ b/src/i830_xaa.c
@@ -162,20 +162,20 @@ I830XAAInit(ScreenPtr pScreen)
 
     /* On the primary screen */
     if (pI830->init == 0) {
-	if (pI830->Scratch.Size != 0) {
+	if (pI830->xaa_scratch->size != 0) {
 	    width = ((pScrn->displayWidth + 31) & ~31) / 8;
-	    nr_buffers = pI830->Scratch.Size / width;
-	    ptr = pI830->FbBase + pI830->Scratch.Start;
+	    nr_buffers = pI830->xaa_scratch->size / width;
+	    ptr = pI830->FbBase + pI830->xaa_scratch->offset;
 	}
     } else {
 	/* On the secondary screen */
 	I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
-	if (pI8301->Scratch2.Size != 0) {
+	if (pI8301->xaa_scratch_2->size != 0) {
 	    width = ((pScrn->displayWidth + 31) & ~31) / 8;
-	    nr_buffers = pI8301->Scratch2.Size / width;
+	    nr_buffers = pI8301->xaa_scratch_2->size / width;
 	    /* We have to use the primary screen's FbBase, as that's where
-	     * we allocated Scratch2, so we get the correct pointer */
-	    ptr = pI8301->FbBase + pI8301->Scratch2.Start;
+	     * we allocated xaa_scratch_2, so we get the correct pointer */
+	    ptr = pI8301->FbBase + pI8301->xaa_scratch_2->offset;
 	}
     }
 
@@ -279,11 +279,15 @@ CheckTiling(ScrnInfoPtr pScrn)
    if (IS_I965G(pI830)) {
       if (pI830->bufferOffset == pScrn->fbOffset && pI830->front_tiled == FENCE_XMAJOR)
          tiled = 1;
-      if (pI830->bufferOffset == pI830->BackBuffer.Start && pI830->back_tiled == FENCE_XMAJOR)
+      if (pI830->bufferOffset == pI830->back_buffer->offset &&
+	  pI830->back_tiled == FENCE_XMAJOR) {
          tiled = 1;
+      }
       /* not really supported as it's always YMajor tiled */
-      if (pI830->bufferOffset == pI830->DepthBuffer.Start && pI830->depth_tiled == FENCE_XMAJOR)
+      if (pI830->bufferOffset == pI830->depth_buffer->offset &&
+	  pI830->depth_tiled == FENCE_XMAJOR) {
          tiled = 1;
+      }
    }
 
    return tiled;
@@ -600,7 +604,7 @@ I830SubsequentColorExpandScanline(ScrnIn
 	I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
 
 	/* We have to use the primary screen's FbBase, as that's where
-	 * we allocated Scratch2, so we get the correct pointer */
+	 * we allocated xaa_scratch_2, so we get the correct pointer */
 	pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] -
 			 pI8301->FbBase);
     }
@@ -700,7 +704,7 @@ I830SubsequentImageWriteScanline(ScrnInf
 	I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
 
 	/* We have to use the primary screen's FbBase, as that's where
-	 * we allocated Scratch2, so we get the correct pointer */
+	 * we allocated xaa_scratch_2, so we get the correct pointer */
 	pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] -
 			 pI8301->FbBase);
     }
diff --git a/src/i965_render.c b/src/i965_render.c
index 5c3f61d..78f1146 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -501,9 +501,9 @@ i965_prepare_composite(int op, PicturePt
     next_offset = default_color_offset + sizeof(*default_color_state);
 
     total_state_size = next_offset;
-    assert(total_state_size < EXA_LINEAR_EXTRA);
+    assert(total_state_size < pI830->exa_965_state->size);
 
-    state_base_offset = pI830->EXAStateMem.Start;
+    state_base_offset = pI830->exa_965_state->offset;
     state_base_offset = ALIGN(state_base_offset, 64);
     state_base = (char *)(pI830->FbBase + state_base_offset);
 
diff-tree a61a6b1db610a07060d0dcca54b66a4b2b3686cc (from 3bce8bf0e95e5842399959a5d6f6413e96f03adb)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Feb 21 09:43:24 2007 -0800

    Reformat to 4-space indents, no trailing whitespace, and 80 columns.
    
    I'm in the process of rewriting this file, and wanted to separate my whitespace
    changes.

diff --git a/src/i830_memory.c b/src/i830_memory.c
index 6ceb05b..1b2af12 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -68,15 +68,15 @@ static unsigned int tileGeneration = -1;
 static unsigned long
 GetBestTileAlignment(unsigned long size)
 {
-   unsigned long i;
+    unsigned long i;
 
-   for (i = KB(512); i < size; i <<= 1)
-      ;
+    for (i = KB(512); i < size; i <<= 1)
+	;
 
-   if (i > MB(64))
-      i = MB(64);
+    if (i > MB(64))
+	i = MB(64);
 
-   return i;
+    return i;
 }
 
 /*
@@ -87,274 +87,279 @@ static unsigned long
 AllocFromPool(ScrnInfoPtr pScrn, I830MemRange *result, I830MemPool *pool,
 	      long size, unsigned long alignment, int flags)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
-   long needed, start, end;
-   Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
-
-   if (!result || !pool || !size)
-      return 0;
-
-   /* Calculate how much space is needed. */
-   if (alignment <= GTT_PAGE_SIZE)
-      needed = size;
-   else {
-      if (flags & ALLOCATE_AT_BOTTOM) {
-	 start = ROUND_TO(pool->Free.Start, alignment);
-	 if (flags & ALIGN_BOTH_ENDS)
-	    end = ROUND_TO(start + size, alignment);
-	 else
-	    end = start + size;
-	 needed = end - pool->Free.Start;
-      } else {				/* allocate at top */
-	 if (flags & ALIGN_BOTH_ENDS)
-	    end = ROUND_DOWN_TO(pool->Free.End, alignment);
-	 else
-	    end = pool->Free.End;
-
-	 start = ROUND_DOWN_TO(end - size, alignment);
-	 needed = end - start;
-      }
-   }
-   if (needed > pool->Free.Size) {
-      long extra;
-      /* See if the pool can be grown. */
-      if (pI830->StolenOnly && !dryrun)
-	 return 0;
-      extra = needed - pool->Free.Size;
-      extra = ROUND_TO_PAGE(extra);
-      if (extra > pI830->FreeMemory) {
-	 if (dryrun)
-	    pI830->FreeMemory = extra;
-	 else
+    I830Ptr pI830 = I830PTR(pScrn);
+    long needed, start, end;
+    Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
+
+    if (!result || !pool || !size)
+	return 0;
+
+    /* Calculate how much space is needed. */
+    if (alignment <= GTT_PAGE_SIZE)
+	needed = size;
+    else {
+	if (flags & ALLOCATE_AT_BOTTOM) {
+	    start = ROUND_TO(pool->Free.Start, alignment);
+	    if (flags & ALIGN_BOTH_ENDS)
+		end = ROUND_TO(start + size, alignment);
+	    else
+		end = start + size;
+	    needed = end - pool->Free.Start;
+	} else {				/* allocate at top */
+	    if (flags & ALIGN_BOTH_ENDS)
+		end = ROUND_DOWN_TO(pool->Free.End, alignment);
+	    else
+		end = pool->Free.End;
+
+	    start = ROUND_DOWN_TO(end - size, alignment);
+	    needed = end - start;
+	}
+    }
+    if (needed > pool->Free.Size) {
+	long extra;
+	/* See if the pool can be grown. */
+	if (pI830->StolenOnly && !dryrun)
 	    return 0;
-      }
+	extra = needed - pool->Free.Size;
+	extra = ROUND_TO_PAGE(extra);
+	if (extra > pI830->FreeMemory) {
+	    if (dryrun)
+		pI830->FreeMemory = extra;
+	    else
+		return 0;
+	}
 
-      if (!dryrun && ((long)extra > pI830->MemoryAperture.Size))
-	 return 0;
+	if (!dryrun && ((long)extra > pI830->MemoryAperture.Size))
+	    return 0;
 
-      pool->Free.Size += extra;
-      pool->Free.End += extra;
-      pool->Total.Size += extra;
-      pool->Total.End += extra;
-      pI830->FreeMemory -= extra;
-      pI830->MemoryAperture.Start += extra;
-      pI830->MemoryAperture.Size -= extra;
-   }
-   if (flags & ALLOCATE_AT_BOTTOM) {
-      result->Start = ROUND_TO(pool->Free.Start, alignment);
-      pool->Free.Start += needed;
-      result->End = pool->Free.Start;
-   } else {
-      result->Start = ROUND_DOWN_TO(pool->Free.End - size, alignment);
-      pool->Free.End -= needed;
-      result->End = result->Start + needed;
-   }
-   pool->Free.Size = pool->Free.End - pool->Free.Start;
-   result->Size = result->End - result->Start;
-   result->Pool = pool;
-   result->Alignment = alignment;
-   return needed;
+	pool->Free.Size += extra;
+	pool->Free.End += extra;
+	pool->Total.Size += extra;
+	pool->Total.End += extra;
+	pI830->FreeMemory -= extra;
+	pI830->MemoryAperture.Start += extra;
+	pI830->MemoryAperture.Size -= extra;
+    }
+    if (flags & ALLOCATE_AT_BOTTOM) {
+	result->Start = ROUND_TO(pool->Free.Start, alignment);
+	pool->Free.Start += needed;
+	result->End = pool->Free.Start;
+    } else {
+	result->Start = ROUND_DOWN_TO(pool->Free.End - size, alignment);
+	pool->Free.End -= needed;
+	result->End = result->Start + needed;
+    }
+    pool->Free.Size = pool->Free.End - pool->Free.Start;
+    result->Size = result->End - result->Start;
+    result->Pool = pool;
+    result->Alignment = alignment;
+    return needed;
 }
 
 static unsigned long
 AllocFromAGP(ScrnInfoPtr pScrn, I830MemRange *result, long size,
 	     unsigned long alignment, int flags)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
-   unsigned long start, end;
-   unsigned long newApStart, newApEnd;
-   Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
-
-   if (!result || !size)
-      return 0;
-
-   if ((flags & ALLOCATE_AT_BOTTOM) && pI830->StolenMemory.Size != 0) {
-      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		 "AllocFromAGP(): can't allocate from "
-		 "bottom when there is stolen memory\n");
-      return 0;
-   }
-
-   if (size > pI830->FreeMemory) {
-      if (dryrun)
-	 pI830->FreeMemory = size;
-      else
-	 return 0;
-   }
-
-   /* Calculate offset */
-   if (flags & ALLOCATE_AT_BOTTOM) {
-      start = ROUND_TO(pI830->MemoryAperture.Start, alignment);
-      if (flags & ALIGN_BOTH_ENDS)
-	 end = ROUND_TO(start + size, alignment);
-      else
-	 end = start + size;
-      newApStart = end;
-      newApEnd = pI830->MemoryAperture.End;
-   } else {
-      if (flags & ALIGN_BOTH_ENDS)
-	 end = ROUND_DOWN_TO(pI830->MemoryAperture.End, alignment);
-      else
-	 end = pI830->MemoryAperture.End;
-      start = ROUND_DOWN_TO(end - size, alignment);
-      newApStart = pI830->MemoryAperture.Start;
-      newApEnd = start;
-   }
-
-   if (!dryrun) {
-      if (newApStart > newApEnd)
-	 return 0;
-
-      if (flags & NEED_PHYSICAL_ADDR) 
-	 result->Key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 2,
-					      &(result->Physical));
-      else 
-	 result->Key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 0, NULL);
-
-      if (result->Key == -1)
-	 return 0;
-   }
-
-   pI830->allocatedMemory += size;
-   pI830->MemoryAperture.Start = newApStart;
-   pI830->MemoryAperture.End = newApEnd;
-   pI830->MemoryAperture.Size = newApEnd - newApStart;
-   pI830->FreeMemory -= size;
-   result->Start = start;
-   result->End = start + size;
-   result->Size = size;
-   result->Offset = start;
-   result->Alignment = alignment;
-   result->Pool = NULL;
+    I830Ptr pI830 = I830PTR(pScrn);
+    unsigned long start, end;
+    unsigned long newApStart, newApEnd;
+    Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
+
+    if (!result || !size)
+	return 0;
+
+    if ((flags & ALLOCATE_AT_BOTTOM) && pI830->StolenMemory.Size != 0) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "AllocFromAGP(): can't allocate from "
+		   "bottom when there is stolen memory\n");
+	return 0;
+    }
+
+    if (size > pI830->FreeMemory) {
+	if (dryrun)
+	    pI830->FreeMemory = size;
+	else
+	    return 0;
+    }
+
+    /* Calculate offset */
+    if (flags & ALLOCATE_AT_BOTTOM) {
+	start = ROUND_TO(pI830->MemoryAperture.Start, alignment);
+	if (flags & ALIGN_BOTH_ENDS)
+	    end = ROUND_TO(start + size, alignment);
+	else
+	    end = start + size;
+	newApStart = end;
+	newApEnd = pI830->MemoryAperture.End;
+    } else {
+	if (flags & ALIGN_BOTH_ENDS)
+	    end = ROUND_DOWN_TO(pI830->MemoryAperture.End, alignment);
+	else
+	    end = pI830->MemoryAperture.End;
+	start = ROUND_DOWN_TO(end - size, alignment);
+	newApStart = pI830->MemoryAperture.Start;
+	newApEnd = start;
+    }
 
-   return size;
+    if (!dryrun) {
+	if (newApStart > newApEnd)
+	    return 0;
+
+	if (flags & NEED_PHYSICAL_ADDR) {
+	    result->Key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 2,
+						 &(result->Physical));
+	} else {
+	    result->Key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 0,
+						 NULL);
+	}
+
+	if (result->Key == -1)
+	    return 0;
+    }
+
+    pI830->allocatedMemory += size;
+    pI830->MemoryAperture.Start = newApStart;
+    pI830->MemoryAperture.End = newApEnd;
+    pI830->MemoryAperture.Size = newApEnd - newApStart;
+    pI830->FreeMemory -= size;
+    result->Start = start;
+    result->End = start + size;
+    result->Size = size;
+    result->Offset = start;
+    result->Alignment = alignment;
+    result->Pool = NULL;
+
+    return size;
 }
 
 void
 I830FreeVidMem(ScrnInfoPtr pScrn, I830MemRange *range)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
-
-   if (!range || range->Size == 0)
-      return;
+    I830Ptr pI830 = I830PTR(pScrn);
 
-   if (range->Key != -1)
-      xf86DeallocateGARTMemory(pScrn->scrnIndex, range->Key);
+    if (!range || range->Size == 0)
+	return;
 
-   if (range->Pool) {
-      /* 
-       * This code essentially resets what I830DoPoolAllocation() did.
-       * And if things are freed in the wrong order this can break wildly!
-       * USE CAUTION when changing anything here...
-       */
-      I830MemPool *Pool = range->Pool;
-      Pool->Total.End = pI830->StolenMemory.End;
-
-      if (pI830->StolenOnly)
-         Pool->Free.End += range->Size;
-      else
-         Pool->Free.End = Pool->Total.End;
+    if (range->Key != -1)
+	xf86DeallocateGARTMemory(pScrn->scrnIndex, range->Key);
 
-      if (Pool->Free.End < Pool->Free.Start) {
-         Pool->Free.End = Pool->Free.Start;
-      }
-
-      Pool->Free.Size = Pool->Free.End - Pool->Free.Start;
-      Pool->Total.Size = Pool->Total.End - Pool->Total.Start;
+    if (range->Pool) {
+	/*
+	 * This code essentially resets what I830DoPoolAllocation() did.
+	 * And if things are freed in the wrong order this can break wildly!
+	 * USE CAUTION when changing anything here...
+	 */
+	I830MemPool *Pool = range->Pool;
+	Pool->Total.End = pI830->StolenMemory.End;
+
+	if (pI830->StolenOnly)
+	    Pool->Free.End += range->Size;
+	else
+	    Pool->Free.End = Pool->Total.End;
+
+	if (Pool->Free.End < Pool->Free.Start) {
+	    Pool->Free.End = Pool->Free.Start;
+	}
+
+	Pool->Free.Size = Pool->Free.End - Pool->Free.Start;
+	Pool->Total.Size = Pool->Total.End - Pool->Total.Start;
+
+	if (!pI830->StolenOnly) {
+	    pI830->FreeMemory -= Pool->Free.Size;
+	    pI830->MemoryAperture.Start -= (range->Size - Pool->Free.Size);
+	    pI830->MemoryAperture.Size += (range->Size - Pool->Free.Size);
+	}
+    } else {
+	if (range->Alignment == GTT_PAGE_SIZE)
+	    pI830->MemoryAperture.End = range->End;
+	else {
+	    pI830->MemoryAperture.End = range->End - range->Size +
+		range->Alignment;
+	}
+	pI830->MemoryAperture.Size = pI830->MemoryAperture.End -
+	    pI830->MemoryAperture.Start;
+    }
 
-      if (!pI830->StolenOnly) {
-         pI830->FreeMemory -= Pool->Free.Size;
-         pI830->MemoryAperture.Start -= (range->Size - Pool->Free.Size);
-         pI830->MemoryAperture.Size += (range->Size - Pool->Free.Size);
-      }
-   } else {
-      if (range->Alignment == GTT_PAGE_SIZE)
-         pI830->MemoryAperture.End = range->End;
-      else
-         pI830->MemoryAperture.End = range->End - range->Size + range->Alignment;
-      pI830->MemoryAperture.Size = pI830->MemoryAperture.End - pI830->MemoryAperture.Start;
-   }
-
-   if (!pI830->StolenOnly)
-      pI830->FreeMemory += range->Size;
-   pI830->allocatedMemory -= range->Size;
+    if (!pI830->StolenOnly)
+	pI830->FreeMemory += range->Size;
+    pI830->allocatedMemory -= range->Size;
 }
 
 unsigned long
 I830AllocVidMem(ScrnInfoPtr pScrn, I830MemRange *result, I830MemPool *pool,
 		long size, unsigned long alignment, int flags)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
-   Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
+    I830Ptr pI830 = I830PTR(pScrn);
+    Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
+
+    if (!result)
+	return 0;
+
+    /* Make sure these are initialised. */
+    result->Size = 0;
+    result->Key = -1;
 
-   if (!result)
-      return 0;
+    if (!size) {
+	return 0;
+    }
 
-   /* Make sure these are initialised. */
-   result->Size = 0;
-   result->Key = -1;
-
-   if (!size) {
-      return 0;
-   }
-
-   switch (flags & FROM_MASK) {
-   case FROM_POOL_ONLY:
-      return AllocFromPool(pScrn, result, pool, size, alignment, flags);
-   case FROM_NEW_ONLY:
-      if (!dryrun && (pI830->StolenOnly || (pI830->FreeMemory <= 0)))
-	 return 0;
-      return AllocFromAGP(pScrn, result, size, alignment, flags);
-   case FROM_ANYWHERE:
-      if ((!(flags & ALLOCATE_AT_BOTTOM) && (pI830->FreeMemory >= size)) ||
-	  (flags & NEED_PHYSICAL_ADDR))
-	 return AllocFromAGP(pScrn, result, size, alignment, flags);
-      else
-	 return AllocFromPool(pScrn, result, pool, size, alignment, flags);
-   default:
-      /* Shouldn't happen. */
-      return 0;
-   }
+    switch (flags & FROM_MASK) {
+    case FROM_POOL_ONLY:
+	return AllocFromPool(pScrn, result, pool, size, alignment, flags);
+    case FROM_NEW_ONLY:
+	if (!dryrun && (pI830->StolenOnly || (pI830->FreeMemory <= 0)))
+	    return 0;
+	return AllocFromAGP(pScrn, result, size, alignment, flags);
+    case FROM_ANYWHERE:
+	if ((!(flags & ALLOCATE_AT_BOTTOM) && (pI830->FreeMemory >= size)) ||
+	    (flags & NEED_PHYSICAL_ADDR))
+	    return AllocFromAGP(pScrn, result, size, alignment, flags);
+	else
+	    return AllocFromPool(pScrn, result, pool, size, alignment, flags);
+    default:
+	/* Shouldn't happen. */
+	return 0;
+    }
 }
 
 static Bool
 AllocateRingBuffer(ScrnInfoPtr pScrn, int flags)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
-   unsigned long size, alloced;
-   Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
-   int verbosity = dryrun ? 4 : 1;
-   const char *s = dryrun ? "[dryrun] " : "";
-
-   /* Clear ring buffer  info */
-   memset(pI830->LpRing, 0, sizeof(I830RingBuffer));
-   pI830->LpRing->mem.Key = -1;
-
-   if (pI830->noAccel)
-      return TRUE;
-
-   /* Ring buffer */
-   size = PRIMARY_RINGBUFFER_SIZE;
-   if (flags & FORCE_LOW)
-      flags |= FROM_POOL_ONLY | ALLOCATE_AT_BOTTOM;
-   else
-      flags |= FROM_ANYWHERE | ALLOCATE_AT_TOP;
-
-   alloced = I830AllocVidMem(pScrn, &(pI830->LpRing->mem),
-				&(pI830->StolenPool), size,
-				GTT_PAGE_SIZE, flags);
-   if (alloced < size) {
-      if (!dryrun) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		    "Failed to allocate Ring Buffer space\n");
-      }
-      return FALSE;
-   }
-   xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-		  "%sAllocated %ld kB for the ring buffer at 0x%lx\n", s,
-		  alloced / 1024, pI830->LpRing->mem.Start);
-   pI830->LpRing->tail_mask = pI830->LpRing->mem.Size - 1;
-   return TRUE;
+    I830Ptr pI830 = I830PTR(pScrn);
+    unsigned long size, alloced;
+    Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
+    int verbosity = dryrun ? 4 : 1;
+    const char *s = dryrun ? "[dryrun] " : "";
+
+    /* Clear ring buffer  info */
+    memset(pI830->LpRing, 0, sizeof(I830RingBuffer));
+    pI830->LpRing->mem.Key = -1;
+
+    if (pI830->noAccel)
+	return TRUE;
+
+    /* Ring buffer */
+    size = PRIMARY_RINGBUFFER_SIZE;
+    if (flags & FORCE_LOW)
+	flags |= FROM_POOL_ONLY | ALLOCATE_AT_BOTTOM;
+    else
+	flags |= FROM_ANYWHERE | ALLOCATE_AT_TOP;
+
+    alloced = I830AllocVidMem(pScrn, &(pI830->LpRing->mem),
+			      &(pI830->StolenPool), size,
+			      GTT_PAGE_SIZE, flags);
+    if (alloced < size) {
+	if (!dryrun) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Failed to allocate Ring Buffer space\n");
+	}
+	return FALSE;
+    }
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		   "%sAllocated %ld kB for the ring buffer at 0x%lx\n", s,
+		   alloced / 1024, pI830->LpRing->mem.Start);
+    pI830->LpRing->tail_mask = pI830->LpRing->mem.Size - 1;
+    return TRUE;
 }
 
 #ifdef I830_XV
@@ -364,127 +369,130 @@ AllocateRingBuffer(ScrnInfoPtr pScrn, in
 static Bool
 AllocateOverlay(ScrnInfoPtr pScrn, int flags)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
-   unsigned long size, alloced;
-   Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
-   int verbosity = dryrun ? 4 : 1;
-   const char *s = dryrun ? "[dryrun] " : "";
-
-   /* Clear overlay info */
-   memset(pI830->OverlayMem, 0, sizeof(I830MemRange));
-   pI830->OverlayMem->Key = -1;
-
-   if (!pI830->XvEnabled)
-      return TRUE;
-
-   /*
-    * The overlay register space needs a physical address in
-    * system memory.  We get this from the agpgart module using
-    * a special memory type.
-    */
-
-   size = OVERLAY_SIZE;
-   if (flags & FORCE_LOW)
-      flags |= FROM_POOL_ONLY | ALLOCATE_AT_BOTTOM | NEED_PHYSICAL_ADDR;
-   else
-      flags |= FROM_ANYWHERE | ALLOCATE_AT_TOP | NEED_PHYSICAL_ADDR;
-
-   alloced = I830AllocVidMem(pScrn, pI830->OverlayMem,
-			     &(pI830->StolenPool), size, GTT_PAGE_SIZE, flags);
-
-   /*
-    * XXX For testing only.  Don't enable this unless you know how to set
-    * physBase.
-    */
-   if (flags & FORCE_LOW) {
-      ErrorF("AllocateOverlay() doesn't support setting FORCE_LOW\n");
-      return FALSE;
-   }
-
-   if (!dryrun && (alloced < size)) {
-      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		 "Failed to allocate Overlay register space.\n");
-	 /* This failure isn't fatal. */
-   } else {
-      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-		     "%sAllocated %ld kB for Overlay registers at 0x%lx "
-		     "(0x%08lx).\n", s,
-		     alloced / 1024, pI830->OverlayMem->Start,
-		     pI830->OverlayMem->Physical);
-   }
-
-   /* Clear linearmem info */
-   if (pI830->LinearAlloc) {
-      memset(&(pI830->LinearMem), 0, sizeof(I830MemRange));
-      pI830->LinearMem.Key = -1;
-
-      size = KB(pI830->LinearAlloc);
-      alloced = I830AllocVidMem(pScrn, &(pI830->LinearMem), &(pI830->StolenPool),
-				size, GTT_PAGE_SIZE,
-				FROM_ANYWHERE | ALLOCATE_AT_TOP);
-      if (alloced < size) {
-         if (!dryrun) {
-            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		       "Failed to allocate linear buffer space\n");
-         }
-      } else
-         xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-		    "%sAllocated %ld kB for the linear buffer at 0x%lx\n", s,
-		    alloced / 1024, pI830->LinearMem.Start);
-   }
+    I830Ptr pI830 = I830PTR(pScrn);
+    unsigned long size, alloced;
+    Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
+    int verbosity = dryrun ? 4 : 1;
+    const char *s = dryrun ? "[dryrun] " : "";
+
+    /* Clear overlay info */
+    memset(pI830->OverlayMem, 0, sizeof(I830MemRange));
+    pI830->OverlayMem->Key = -1;
+
+    if (!pI830->XvEnabled)
+	return TRUE;
+
+    /*
+     * The overlay register space needs a physical address in
+     * system memory.  We get this from the agpgart module using
+     * a special memory type.
+     */
+
+    size = OVERLAY_SIZE;
+    if (flags & FORCE_LOW)
+	flags |= FROM_POOL_ONLY | ALLOCATE_AT_BOTTOM | NEED_PHYSICAL_ADDR;
+    else
+	flags |= FROM_ANYWHERE | ALLOCATE_AT_TOP | NEED_PHYSICAL_ADDR;
+
+    alloced = I830AllocVidMem(pScrn, pI830->OverlayMem,
+			      &(pI830->StolenPool), size, GTT_PAGE_SIZE,
+			      flags);
+
+    /*
+     * XXX For testing only.  Don't enable this unless you know how to set
+     * physBase.
+     */
+    if (flags & FORCE_LOW) {
+	ErrorF("AllocateOverlay() doesn't support setting FORCE_LOW\n");
+	return FALSE;
+    }
+
+    if (!dryrun && (alloced < size)) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "Failed to allocate Overlay register space.\n");
+	/* This failure isn't fatal. */
+    } else {
+	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		       "%sAllocated %ld kB for Overlay registers at 0x%lx "
+		       "(0x%08lx).\n", s,
+		       alloced / 1024, pI830->OverlayMem->Start,
+		       pI830->OverlayMem->Physical);
+    }
+
+    /* Clear linearmem info */
+    if (pI830->LinearAlloc) {
+	memset(&(pI830->LinearMem), 0, sizeof(I830MemRange));
+	pI830->LinearMem.Key = -1;
+
+	size = KB(pI830->LinearAlloc);
+	alloced = I830AllocVidMem(pScrn, &(pI830->LinearMem),
+				  &(pI830->StolenPool),
+				  size, GTT_PAGE_SIZE,
+				  FROM_ANYWHERE | ALLOCATE_AT_TOP);
+	if (alloced < size) {
+	    if (!dryrun) {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			   "Failed to allocate linear buffer space\n");
+	    }
+	} else
+	    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+			   "%sAllocated %ld kB for the linear buffer at "
+			   "0x%lx\n", s,
+			   alloced / 1024, pI830->LinearMem.Start);
+    }
 
-   return TRUE;
+    return TRUE;
 }
 #endif
 
 static Bool
 IsTileable(ScrnInfoPtr pScrn, int pitch)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    if (IS_I965G(pI830)) {
+	if (pitch / 512 * 512 == pitch && pitch <= KB(128))
+	    return TRUE;
+	else
+	    return FALSE;
+    }
 
-   if (IS_I965G(pI830)) {
-      if (pitch / 512 * 512 == pitch && pitch <= KB(128))
-	 return TRUE;
-      else
-	 return FALSE;
-   }
-
-   /*
-    * Allow tiling for pitches that are a power of 2 multiple of 128 bytes,
-    * up to 64 * 128 (= 8192) bytes.
-    */
-   switch (pitch) {
-   case 128:
-   case 256:
-      if (IS_I945G(pI830) || IS_I945GM(pI830))
-	 return TRUE;
-      else
-	 return FALSE;
-   case 512:
-   case KB(1):
-   case KB(2):
-   case KB(4):
-   case KB(8):
-      return TRUE;
-   default:
-      return FALSE;
-   }
+    /*
+     * Allow tiling for pitches that are a power of 2 multiple of 128 bytes,
+     * up to 64 * 128 (= 8192) bytes.
+     */
+    switch (pitch) {
+    case 128:
+    case 256:
+	if (IS_I945G(pI830) || IS_I945GM(pI830))
+	    return TRUE;
+	else
+	    return FALSE;
+    case 512:
+    case KB(1):
+    case KB(2):
+    case KB(4):
+    case KB(8):
+	return TRUE;
+    default:
+	return FALSE;
+    }
 }
 
 static unsigned long
 GetFreeSpace(ScrnInfoPtr pScrn)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
-   unsigned long extra = 0;
+    I830Ptr pI830 = I830PTR(pScrn);
+    unsigned long extra = 0;
 
-   /* First check for free space in StolenPool. */
-   if (pI830->StolenPool.Free.Size > 0)
-      extra = pI830->StolenPool.Free.Size;
-   /* Next check for unallocated space. */
-   if (pI830->FreeMemory > 0)
-      extra += pI830->FreeMemory;
+    /* First check for free space in StolenPool. */
+    if (pI830->StolenPool.Free.Size > 0)
+	extra = pI830->StolenPool.Free.Size;
+    /* Next check for unallocated space. */
+    if (pI830->FreeMemory > 0)
+	extra += pI830->FreeMemory;
 
-   return extra;
+    return extra;
 }
 
 /* This is the 2D rendering vertical coordinate limit.  We can ignore
@@ -509,199 +517,200 @@ I830AllocateFramebuffer(ScrnInfoPtr pScr
 			I830MemRange *FrontBuffer, I830MemPool *StolenPool,
 			Bool secondary, const int flags)
 {
-   Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
-   unsigned long minspace, avail, lineSize;
-   int cacheLines, maxCacheLines;
-   int verbosity = dryrun ? 4 : 1;
-   const char *s = dryrun ? "[dryrun] " : "";
-   Bool tileable;
-   int align, alignflags;
-   long size, alloced, fb_height;
-
-   /* Clear everything first. */
-   memset(FbMemBox, 0, sizeof(*FbMemBox));
-   memset(FrontBuffer, 0, sizeof(*FrontBuffer));
-   FrontBuffer->Key = -1;
-
-   /* We'll allocate the fb such that the root window will fit regardless of
-    * rotation.
-    */
-   if (pScrn->virtualX > pScrn->virtualY)
-      fb_height = pScrn->virtualX;
-   else
-      fb_height = pScrn->virtualY;
-
-   FbMemBox->x1 = 0;
-   FbMemBox->x2 = pScrn->displayWidth;
-   FbMemBox->y1 = 0;
-   FbMemBox->y2 = fb_height;
-
-   /* Calculate how much framebuffer memory to allocate.  For the
-    * initial allocation, calculate a reasonable minimum.  This is
-    * enough for the virtual screen size, plus some pixmap cache
-    * space if we're using XAA.
-    */
-
-   lineSize = pScrn->displayWidth * pI830->cpp;
-   minspace = lineSize * pScrn->virtualY;
-   avail = pScrn->videoRam * 1024;
-
-   if (!pI830->useEXA) {
-      maxCacheLines = (avail - minspace) / lineSize;
-      /* This shouldn't happen. */
-      if (maxCacheLines < 0) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		    "Internal Error: "
-		    "maxCacheLines < 0 in I830Allocate2DMemory()\n");
-	 maxCacheLines = 0;
-      }
-      if (maxCacheLines > (MAX_2D_HEIGHT - pScrn->virtualY))
-	 maxCacheLines = MAX_2D_HEIGHT - pScrn->virtualY;
-
-      if (pI830->CacheLines >= 0) {
-	 cacheLines = pI830->CacheLines;
-      } else {
-	 int size;
-
-	 size = 3 * lineSize * pScrn->virtualY;
-	 size += 1920 * 1088 * 2 * 2;
-	 size = ROUND_TO_PAGE(size);
-
-	 cacheLines = (size + lineSize - 1) / lineSize;
-      }
-      if (cacheLines > maxCacheLines)
-	 cacheLines = maxCacheLines;
+    Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
+    unsigned long minspace, avail, lineSize;
+    int cacheLines, maxCacheLines;
+    int verbosity = dryrun ? 4 : 1;
+    const char *s = dryrun ? "[dryrun] " : "";
+    Bool tileable;
+    int align, alignflags;
+    long size, alloced, fb_height;
+
+    /* Clear everything first. */
+    memset(FbMemBox, 0, sizeof(*FbMemBox));
+    memset(FrontBuffer, 0, sizeof(*FrontBuffer));
+    FrontBuffer->Key = -1;
+
+    /* We'll allocate the fb such that the root window will fit regardless of
+     * rotation.
+     */
+    if (pScrn->virtualX > pScrn->virtualY)
+	fb_height = pScrn->virtualX;
+    else
+	fb_height = pScrn->virtualY;
+
+    FbMemBox->x1 = 0;
+    FbMemBox->x2 = pScrn->displayWidth;
+    FbMemBox->y1 = 0;
+    FbMemBox->y2 = fb_height;
+
+    /* Calculate how much framebuffer memory to allocate.  For the
+     * initial allocation, calculate a reasonable minimum.  This is
+     * enough for the virtual screen size, plus some pixmap cache
+     * space if we're using XAA.
+     */
+
+    lineSize = pScrn->displayWidth * pI830->cpp;
+    minspace = lineSize * pScrn->virtualY;
+    avail = pScrn->videoRam * 1024;
+
+    if (!pI830->useEXA) {
+	maxCacheLines = (avail - minspace) / lineSize;
+	/* This shouldn't happen. */
+	if (maxCacheLines < 0) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Internal Error: "
+		       "maxCacheLines < 0 in I830Allocate2DMemory()\n");
+	    maxCacheLines = 0;
+	}
+	if (maxCacheLines > (MAX_2D_HEIGHT - pScrn->virtualY))
+	    maxCacheLines = MAX_2D_HEIGHT - pScrn->virtualY;
+
+	if (pI830->CacheLines >= 0) {
+	    cacheLines = pI830->CacheLines;
+	} else {
+	    int size;
+
+	    size = 3 * lineSize * pScrn->virtualY;
+	    size += 1920 * 1088 * 2 * 2;
+	    size = ROUND_TO_PAGE(size);
+
+	    cacheLines = (size + lineSize - 1) / lineSize;
+	}
+	if (cacheLines > maxCacheLines)
+	    cacheLines = maxCacheLines;
+
+	FbMemBox->y2 += cacheLines;
+
+	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		       "%sAllocating at least %d scanlines for pixmap cache\n",
+		       s, cacheLines);
+    } else {
+	/* For EXA, we have a separate allocation for the linear allocator
+	 * which also does the pixmap cache.
+	 */
+	cacheLines = 0;
+    }
 
-      FbMemBox->y2 += cacheLines;
+    tileable = !(flags & ALLOC_NO_TILING) && pI830->allowPageFlip &&
+	IsTileable(pScrn, pScrn->displayWidth * pI830->cpp);
+    if (tileable) {
+	if (IS_I9XX(pI830))
+	    align = MB(1);
+	else
+	    align = KB(512);
+	alignflags = ALIGN_BOTH_ENDS;
+    } else {
+	align = KB(64);
+	alignflags = 0;
+    }
 
-      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-		     "%sAllocating at least %d scanlines for pixmap cache\n",
-		     s, cacheLines);
-   } else {
-     /* For EXA, we have a separate allocation for the linear allocator which
-      * also does the pixmap cache.
-      */
-     cacheLines = 0;
-   }
-
-   tileable = !(flags & ALLOC_NO_TILING) && pI830->allowPageFlip &&
-      IsTileable(pScrn, pScrn->displayWidth * pI830->cpp);
-   if (tileable) {
-      if (IS_I9XX(pI830))
-	 align = MB(1);
-      else
-	 align = KB(512);
-      alignflags = ALIGN_BOTH_ENDS;
-   } else {
-      align = KB(64);
-      alignflags = 0;
-   }
-
-   size = lineSize * (fb_height + cacheLines);
-   size = ROUND_TO_PAGE(size);
-   xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-		  "%sInitial %sframebuffer allocation size: %ld kByte\n",
-		  s, secondary ? "secondary " : "",
-		  size / 1024);
-   alloced = I830AllocVidMem(pScrn, FrontBuffer,
-			     StolenPool, size, align,
-			     flags | alignflags |
-			     FROM_ANYWHERE | ALLOCATE_AT_BOTTOM);
-   if (alloced < size) {
-      if (!dryrun) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate "
-		    "%sframebuffer. Is your VideoRAM set too low?\n",
-		    secondary ? "secondary " : "");
-      }
-      return FALSE;
-   }
+    size = lineSize * (fb_height + cacheLines);
+    size = ROUND_TO_PAGE(size);
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		   "%sInitial %sframebuffer allocation size: %ld kByte\n",
+		   s, secondary ? "secondary " : "",
+		   size / 1024);
+    alloced = I830AllocVidMem(pScrn, FrontBuffer,
+			      StolenPool, size, align,
+			      flags | alignflags |
+			      FROM_ANYWHERE | ALLOCATE_AT_BOTTOM);
+    if (alloced < size) {
+	if (!dryrun) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate "
+		       "%sframebuffer. Is your VideoRAM set too low?\n",
+		       secondary ? "secondary " : "");
+	}
+	return FALSE;
+    }
 
-   return TRUE;
+    return TRUE;
 }
 
 static Bool
 I830AllocateCursorBuffers(xf86CrtcPtr crtc, const int flags)
 {
-   ScrnInfoPtr pScrn = crtc->scrn;
-   I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
-   I830Ptr pI830 = I830PTR(pScrn);
-   Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
-   int verbosity = dryrun ? 4 : 1;
-   const char *s = dryrun ? "[dryrun] " : "";
-   long size, alloced;
-   int cursFlags = 0;
-
-   /* Clear cursor info */
-   memset(&intel_crtc->cursor_mem, 0, sizeof(I830MemRange));
-   intel_crtc->cursor_mem.Key = -1;
-   memset(&intel_crtc->cursor_mem_argb, 0, sizeof(I830MemRange));
-   intel_crtc->cursor_mem_argb.Key = -1;
-
-   if (pI830->SWCursor)
-      return FALSE;
-
-   /*
-    * Mouse cursor -- The i810-i830 need a physical address in system
-    * memory from which to upload the cursor.  We get this from
-    * the agpgart module using a special memory type.
-    */
-
-   size = HWCURSOR_SIZE;
-   cursFlags = FROM_ANYWHERE | ALLOCATE_AT_TOP;
-   if (pI830->CursorNeedsPhysical)
-      cursFlags |= NEED_PHYSICAL_ADDR;
-
-   alloced = I830AllocVidMem(pScrn, &intel_crtc->cursor_mem,
-			     &pI830->StolenPool, size,
-			     GTT_PAGE_SIZE, flags | cursFlags);
-   if (alloced < size ||
-       (pI830->CursorNeedsPhysical && !intel_crtc->cursor_mem.Physical))
-   {
-      if (!dryrun) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		    "Failed to allocate HW cursor space.\n");
-	 return FALSE;
-      }
-   } else {
-      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-		     "%sAllocated %ld kB for HW cursor at 0x%lx", s,
-		     alloced / 1024, intel_crtc->cursor_mem.Start);
-      if (pI830->CursorNeedsPhysical) {
-	 xf86ErrorFVerb(verbosity, " (0x%08lx)",
-			intel_crtc->cursor_mem.Physical);
-      }
-      xf86ErrorFVerb(verbosity, "\n");
-   }
+    ScrnInfoPtr pScrn = crtc->scrn;
+    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+    I830Ptr pI830 = I830PTR(pScrn);
+    Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
+    int verbosity = dryrun ? 4 : 1;
+    const char *s = dryrun ? "[dryrun] " : "";
+    long size, alloced;
+    int cursFlags = 0;
+
+    /* Clear cursor info */
+    memset(&intel_crtc->cursor_mem, 0, sizeof(I830MemRange));
+    intel_crtc->cursor_mem.Key = -1;
+    memset(&intel_crtc->cursor_mem_argb, 0, sizeof(I830MemRange));
+    intel_crtc->cursor_mem_argb.Key = -1;
+
+    if (pI830->SWCursor)
+	return FALSE;
+
+    /*
+     * Mouse cursor -- The i810-i830 need a physical address in system
+     * memory from which to upload the cursor.  We get this from
+     * the agpgart module using a special memory type.
+     */
+
+    size = HWCURSOR_SIZE;
+    cursFlags = FROM_ANYWHERE | ALLOCATE_AT_TOP;
+    if (pI830->CursorNeedsPhysical)
+	cursFlags |= NEED_PHYSICAL_ADDR;
+
+    alloced = I830AllocVidMem(pScrn, &intel_crtc->cursor_mem,
+			      &pI830->StolenPool, size,
+			      GTT_PAGE_SIZE, flags | cursFlags);
+    if (alloced < size ||
+	(pI830->CursorNeedsPhysical && !intel_crtc->cursor_mem.Physical))
+    {
+	if (!dryrun) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Failed to allocate HW cursor space.\n");
+	    return FALSE;
+	}
+    } else {
+	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		       "%sAllocated %ld kB for HW cursor at 0x%lx", s,
+		       alloced / 1024, intel_crtc->cursor_mem.Start);
+	if (pI830->CursorNeedsPhysical) {
+	    xf86ErrorFVerb(verbosity, " (0x%08lx)",
+			   intel_crtc->cursor_mem.Physical);
+	}
+	xf86ErrorFVerb(verbosity, "\n");
+    }
 
-   /* Allocate the ARGB cursor space.  Its success is optional -- we won't set
-    * SWCursor if it fails.
-    */
-   size = HWCURSOR_SIZE_ARGB;
-   cursFlags = FROM_ANYWHERE | ALLOCATE_AT_TOP;
-   if (pI830->CursorNeedsPhysical)
-      cursFlags |= NEED_PHYSICAL_ADDR;
-
-   alloced = I830AllocVidMem(pScrn, &intel_crtc->cursor_mem_argb,
-			     &pI830->StolenPool, size,
-			     GTT_PAGE_SIZE, flags | cursFlags);
-   if (alloced < size ||
-       (pI830->CursorNeedsPhysical && !intel_crtc->cursor_mem_argb.Physical)) {
-      if (!dryrun) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		    "Failed to allocate HW (ARGB) cursor space.\n");
-      }
-   } else {
-      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-		     "%sAllocated %ld kB for HW (ARGB) cursor at 0x%lx", s,
-		     alloced / 1024, intel_crtc->cursor_mem_argb.Start);
-      if (pI830->CursorNeedsPhysical) {
-	 xf86ErrorFVerb(verbosity, " (0x%08lx)",
-			intel_crtc->cursor_mem_argb.Physical);
-      }
-      xf86ErrorFVerb(verbosity, "\n");
-   }
+    /* Allocate the ARGB cursor space.  Its success is optional -- we won't set
+     * SWCursor if it fails.
+     */
+    size = HWCURSOR_SIZE_ARGB;
+    cursFlags = FROM_ANYWHERE | ALLOCATE_AT_TOP;
+    if (pI830->CursorNeedsPhysical)
+	cursFlags |= NEED_PHYSICAL_ADDR;
+
+    alloced = I830AllocVidMem(pScrn, &intel_crtc->cursor_mem_argb,
+			      &pI830->StolenPool, size,
+			      GTT_PAGE_SIZE, flags | cursFlags);
+    if (alloced < size ||
+	(pI830->CursorNeedsPhysical && !intel_crtc->cursor_mem_argb.Physical))
+    {
+	if (!dryrun) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Failed to allocate HW (ARGB) cursor space.\n");
+	}
+    } else {
+	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		       "%sAllocated %ld kB for HW (ARGB) cursor at 0x%lx", s,
+		       alloced / 1024, intel_crtc->cursor_mem_argb.Start);
+	if (pI830->CursorNeedsPhysical) {
+	    xf86ErrorFVerb(verbosity, " (0x%08lx)",
+			   intel_crtc->cursor_mem_argb.Physical);
+	}
+	xf86ErrorFVerb(verbosity, "\n");
+    }
 
-   return FALSE;
+    return FALSE;
 }
 
 /*
@@ -711,561 +720,586 @@ I830AllocateCursorBuffers(xf86CrtcPtr cr
 Bool
 I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
-   xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-   long size, alloced;
-   Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
-   int verbosity = dryrun ? 4 : 1;
-   const char *s = dryrun ? "[dryrun] " : "";
-   Bool tileable;
-   int align, alignflags, i;
-
-   DPRINTF(PFX, "I830Allocate2DMemory: inital is %s\n",
-	   BOOLTOSTRING(flags & ALLOC_INITIAL));
-
-   if (!pI830->StolenOnly &&
-       (!xf86AgpGARTSupported() || !xf86AcquireGART(pScrn->scrnIndex))) {
-      if (!dryrun) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		    "AGP GART support is either not available or cannot "
-		    "be used.\n"
-		    "\tMake sure your kernel has agpgart support or has the\n"
-		    "\tagpgart module loaded.\n");
-      }
-      return FALSE;
-   }
+    I830Ptr pI830 = I830PTR(pScrn);
+    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    long size, alloced;
+    Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
+    int verbosity = dryrun ? 4 : 1;
+    const char *s = dryrun ? "[dryrun] " : "";
+    Bool tileable;
+    int align, alignflags, i;
+
+    DPRINTF(PFX, "I830Allocate2DMemory: inital is %s\n",
+	    BOOLTOSTRING(flags & ALLOC_INITIAL));
+
+    if (!pI830->StolenOnly &&
+	(!xf86AgpGARTSupported() || !xf86AcquireGART(pScrn->scrnIndex))) {
+	if (!dryrun) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "AGP GART support is either not available or cannot "
+		       "be used.\n"
+		       "\tMake sure your kernel has agpgart support or has "
+		       "the\n"
+		       "\tagpgart module loaded.\n");
+	}
+	return FALSE;
+    }
 
 
-   /*
-    * The I830 is slightly different from the I830/I815, it has no
-    * dcache and it has stolen memory by default in its gtt.  All
-    * additional memory must go after it.
-    */
-
-   DPRINTF(PFX,
-	   "size == %luk (%lu bytes == pScrn->videoRam)\n"
-	   "pI830->StolenSize == %luk (%lu bytes)\n",
-	   pScrn->videoRam, pScrn->videoRam * 1024,
-	   pI830->StolenPool.Free.Size / 1024,
-	   pI830->StolenPool.Free.Size);
-
-   if (flags & ALLOC_INITIAL) {
-      if (pI830->NeedRingBufferLow)
-	 AllocateRingBuffer(pScrn, flags | FORCE_LOW);
-
-      /* Unfortunately this doesn't run on the DRY_RUN pass because our
-       * second head hasn't been created yet..... */
-      if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) {
-         I830EntPtr pI830Ent = pI830->entityPrivate;
-         I830Ptr pI8302 = I830PTR(pI830Ent->pScrn_2);
-
-	 if (!I830AllocateFramebuffer(pI830Ent->pScrn_2, pI8302,
-				      &pI830->FbMemBox2,
-				      &pI830->FrontBuffer2, &pI830->StolenPool,
-				      TRUE, flags))
-	 {
+    /*
+     * The I830 is slightly different from the I830/I815, it has no
+     * dcache and it has stolen memory by default in its gtt.  All
+     * additional memory must go after it.
+     */
+
+    DPRINTF(PFX,
+	    "size == %luk (%lu bytes == pScrn->videoRam)\n"
+	    "pI830->StolenSize == %luk (%lu bytes)\n",
+	    pScrn->videoRam, pScrn->videoRam * 1024,
+	    pI830->StolenPool.Free.Size / 1024,
+	    pI830->StolenPool.Free.Size);
+
+    if (flags & ALLOC_INITIAL) {
+	if (pI830->NeedRingBufferLow)
+	    AllocateRingBuffer(pScrn, flags | FORCE_LOW);
+
+	/* Unfortunately this doesn't run on the DRY_RUN pass because our
+	 * second head hasn't been created yet..... */
+	if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) {
+	    I830EntPtr pI830Ent = pI830->entityPrivate;
+	    I830Ptr pI8302 = I830PTR(pI830Ent->pScrn_2);
+
+	    if (!I830AllocateFramebuffer(pI830Ent->pScrn_2, pI8302,
+					 &pI830->FbMemBox2,
+					 &pI830->FrontBuffer2,
+					 &pI830->StolenPool,
+					 TRUE, flags))
+	    {
+		return FALSE;
+	    }
+	}
+	if (!I830AllocateFramebuffer(pScrn, pI830, &pI830->FbMemBox,
+				     &pI830->FrontBuffer, &pI830->StolenPool,
+				     FALSE, flags))
+	{
 	    return FALSE;
-	 }
-      }
-      if (!I830AllocateFramebuffer(pScrn, pI830, &pI830->FbMemBox,
-				   &pI830->FrontBuffer, &pI830->StolenPool,
-				   FALSE, flags))
-      {
-	 return FALSE;
-      }
+	}
 
 #ifdef I830_USE_EXA
-      if (pI830->useEXA) {
-	 /* Default EXA to having 3 screens worth of offscreen memory space
-	  * (for pixmaps), plus a double-buffered, 1920x1088 video's worth.
-	  */
-	 size = 3 * pScrn->displayWidth * pI830->cpp * pScrn->virtualY;
-	 size += 1920 * 1088 * 2 * 2;
-	 size = ROUND_TO_PAGE(size);
-
-	 alloced = I830AllocVidMem(pScrn, &(pI830->Offscreen),
-				   &(pI830->StolenPool), size, 1,
-				   flags |
-				   FROM_ANYWHERE | ALLOCATE_AT_BOTTOM);
-	 if (alloced < size) {
-	    if (!dryrun) {
-	       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate "
-			  "offscreen memory.  Not enough VRAM?\n");
+	if (pI830->useEXA) {
+	    /* Default EXA to having 3 screens worth of offscreen memory space
+	     * (for pixmaps), plus a double-buffered, 1920x1088 video's worth.
+	     */
+	    size = 3 * pScrn->displayWidth * pI830->cpp * pScrn->virtualY;
+	    size += 1920 * 1088 * 2 * 2;
+	    size = ROUND_TO_PAGE(size);
+
+	    alloced = I830AllocVidMem(pScrn, &(pI830->Offscreen),
+				      &(pI830->StolenPool), size, 1,
+				      flags |
+				      FROM_ANYWHERE | ALLOCATE_AT_BOTTOM);
+	    if (alloced < size) {
+		if (!dryrun) {
+		    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate "
+			       "offscreen memory.  Not enough VRAM?\n");
+		}
+		return FALSE;
+	    } else {
+		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+			   "Successful allocation of "
+			   "EXA offscreen memory at 0x%lx, size %ld KB\n",
+			   pI830->Offscreen.Start, pI830->Offscreen.Size/1024);
 	    }
-	    return FALSE;
-	 } else {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Successful allocation of "
-		       "EXA offscreen memory at 0x%lx, size %ld KB\n",
-		       pI830->Offscreen.Start, pI830->Offscreen.Size/1024);
-	 }
-      }
-      if (pI830->useEXA && IS_I965G(pI830)) {
-          memset(&(pI830->EXAStateMem), 0, sizeof(I830MemRange));
-          pI830->EXAStateMem.Key = -1;
-          size = ROUND_TO_PAGE(EXA_LINEAR_EXTRA);
-          align = GTT_PAGE_SIZE;
-          alloced = I830AllocVidMem(pScrn, &(pI830->EXAStateMem),
-				&(pI830->StolenPool), size, align,
-				flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
-          if (alloced < size) {
-             if (!dryrun) {
-         	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		    "G965: Failed to allocate exa state buffer space.\n");
-             }
-             return FALSE;
-          }
-          xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
- 		  "%sAllocated %ld kB for the G965 exa state buffer at 0x%lx - 0x%lx.\n", s, 
- 		alloced / 1024, pI830->EXAStateMem.Start, pI830->EXAStateMem.End);
-      }
+	}
+	if (pI830->useEXA && IS_I965G(pI830)) {
+	    memset(&(pI830->EXAStateMem), 0, sizeof(I830MemRange));
+	    pI830->EXAStateMem.Key = -1;
+	    size = ROUND_TO_PAGE(EXA_LINEAR_EXTRA);
+	    align = GTT_PAGE_SIZE;
+	    alloced = I830AllocVidMem(pScrn, &(pI830->EXAStateMem),
+				      &(pI830->StolenPool), size, align,
+				      flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
+	    if (alloced < size) {
+		if (!dryrun) {
+		    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			       "G965: Failed to allocate exa state buffer "
+			       "space.\n");
+		}
+		return FALSE;
+	    }
+	    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+			   "%sAllocated %ld kB for the G965 exa state buffer "
+			   "at 0x%lx - 0x%lx.\n", s,
+			   alloced / 1024, pI830->EXAStateMem.Start,
+			   pI830->EXAStateMem.End);
+	}
 #endif
-   } else {
-      long lineSize;
-      long extra = 0;
-      long maxFb = 0;
-
-      /*
-       * XXX Need to "free" up any 3D allocations if the DRI ended up
-       * and make them available for 2D.  The best way to do this would
-       * be position all of those regions contiguously at the end of the
-       * StolenPool.
-       */
-      extra = GetFreeSpace(pScrn);
-
-      if (extra == 0)
-	 return TRUE;
-
-      maxFb = pI830->FrontBuffer.Size + extra;
-      lineSize = pScrn->displayWidth * pI830->cpp;
-      maxFb = ROUND_DOWN_TO(maxFb, lineSize);
-      if (maxFb > lineSize * MAX_2D_HEIGHT)
-	 maxFb = lineSize * MAX_2D_HEIGHT;
-      if (0/*maxFb > pI830->FrontBuffer.Size*/) {
-	 unsigned long oldsize;
-	 /*
-	  * Sanity check -- the fb should be the last thing allocated at
-	  * the bottom of the stolen pool.
-	  */
-	 if (pI830->StolenPool.Free.Start != pI830->FrontBuffer.End) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		       "Internal error in I830Allocate2DMemory():\n\t"
-		       "Framebuffer isn't the last allocation at the bottom"
-		       " of StolenPool\n\t(%lx != %lx).\n",
-		       pI830->FrontBuffer.End,
-		       pI830->StolenPool.Free.Start);
-	    return FALSE;
-	 }
-	 /*
-	  * XXX Maybe should have a "Free" function.  This should be
-	  * the only place where a region is resized, and we know that
-	  * the fb is always at the bottom of the aperture/stolen pool,
-	  * and is the only region that is allocated bottom-up.
-	  * Allowing for more general realloction would require a smarter
-	  * allocation system.
-	  */
-	 oldsize = pI830->FrontBuffer.Size;
-	 pI830->StolenPool.Free.Size += pI830->FrontBuffer.Size;
-	 pI830->StolenPool.Free.Start -= pI830->FrontBuffer.Size;
-	 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-			"%sUpdated framebuffer allocation size from %ld "
-			"to %ld kByte\n", s, oldsize / 1024, maxFb / 1024);
-	 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-			"%sUpdated pixmap cache from %ld scanlines to %ld "
-			"scanlines\n", s,
-			oldsize / lineSize - pScrn->virtualY,
-			maxFb / lineSize - pScrn->virtualY);
-	 pI830->FbMemBox.y2 = maxFb / lineSize;
-	 tileable = !(flags & ALLOC_NO_TILING) && pI830->allowPageFlip &&
-		 IsTileable(pScrn, pScrn->displayWidth * pI830->cpp);
-	 if (tileable) {
-            if (IS_I9XX(pI830))
-               align = MB(1);
-            else
-	       align = KB(512);
-	    alignflags = ALIGN_BOTH_ENDS;
-	 } else {
-	    align = KB(64);
-	    alignflags = 0;
-	 }
-	 alloced = I830AllocVidMem(pScrn, &(pI830->FrontBuffer),
-				   &(pI830->StolenPool), maxFb, align,
-				   flags | alignflags |
-				   FROM_ANYWHERE | ALLOCATE_AT_BOTTOM);
-	 if (alloced < maxFb) {
-	    if (!dryrun) {
-	       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-			  "Failed to re-allocate framebuffer\n");
+    } else {
+	long lineSize;
+	long extra = 0;
+	long maxFb = 0;
+
+	/*
+	 * XXX Need to "free" up any 3D allocations if the DRI ended up
+	 * and make them available for 2D.  The best way to do this would
+	 * be position all of those regions contiguously at the end of the
+	 * StolenPool.
+	 */
+	extra = GetFreeSpace(pScrn);
+
+	if (extra == 0)
+	    return TRUE;
+
+	maxFb = pI830->FrontBuffer.Size + extra;
+	lineSize = pScrn->displayWidth * pI830->cpp;
+	maxFb = ROUND_DOWN_TO(maxFb, lineSize);
+	if (maxFb > lineSize * MAX_2D_HEIGHT)
+	    maxFb = lineSize * MAX_2D_HEIGHT;
+	if (0/*maxFb > pI830->FrontBuffer.Size*/) {
+	    unsigned long oldsize;
+	    /*
+	     * Sanity check -- the fb should be the last thing allocated at
+	     * the bottom of the stolen pool.
+	     */
+	    if (pI830->StolenPool.Free.Start != pI830->FrontBuffer.End) {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			   "Internal error in I830Allocate2DMemory():\n\t"
+			   "Framebuffer isn't the last allocation at the "
+			   "bottom of StolenPool\n\t(%lx != %lx).\n",
+			   pI830->FrontBuffer.End,
+			   pI830->StolenPool.Free.Start);
+		return FALSE;
 	    }
-	    return FALSE;
-	 }
-      }
-      return TRUE;
-   }
+	    /*
+	     * XXX Maybe should have a "Free" function.  This should be
+	     * the only place where a region is resized, and we know that
+	     * the fb is always at the bottom of the aperture/stolen pool,
+	     * and is the only region that is allocated bottom-up.
+	     * Allowing for more general realloction would require a smarter
+	     * allocation system.
+	     */
+	    oldsize = pI830->FrontBuffer.Size;
+	    pI830->StolenPool.Free.Size += pI830->FrontBuffer.Size;
+	    pI830->StolenPool.Free.Start -= pI830->FrontBuffer.Size;
+	    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+			   "%sUpdated framebuffer allocation size from %ld "
+			   "to %ld kByte\n", s, oldsize / 1024, maxFb / 1024);
+	    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+			   "%sUpdated pixmap cache from %ld scanlines to %ld "
+			   "scanlines\n", s,
+			   oldsize / lineSize - pScrn->virtualY,
+			   maxFb / lineSize - pScrn->virtualY);
+	    pI830->FbMemBox.y2 = maxFb / lineSize;
+	    tileable = !(flags & ALLOC_NO_TILING) && pI830->allowPageFlip &&
+		IsTileable(pScrn, pScrn->displayWidth * pI830->cpp);
+	    if (tileable) {
+		if (IS_I9XX(pI830))
+		    align = MB(1);
+		else
+		    align = KB(512);
+		alignflags = ALIGN_BOTH_ENDS;
+	    } else {
+		align = KB(64);
+		alignflags = 0;
+	    }
+	    alloced = I830AllocVidMem(pScrn, &(pI830->FrontBuffer),
+				      &(pI830->StolenPool), maxFb, align,
+				      flags | alignflags |
+				      FROM_ANYWHERE | ALLOCATE_AT_BOTTOM);
+	    if (alloced < maxFb) {
+		if (!dryrun) {
+		    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			       "Failed to re-allocate framebuffer\n");
+		}
+		return FALSE;
+	    }
+	}
+	return TRUE;
+    }
 
 #if REMAP_RESERVED
-   /*
-    * Allocate a dummy page to pass when attempting to rebind the
-    * pre-allocated region.
-    */
-   if (!dryrun) {
-      memset(&(pI830->Dummy), 0, sizeof(pI830->Dummy));
-      pI830->Dummy.Key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 0, NULL);
-      pI830->Dummy.Offset = 0;
-   }
-#endif
-
-   if (!pI830->SWCursor && !dryrun) {
-       for (i = 0; i < xf86_config->num_crtc; i++) {
-	   if (!I830AllocateCursorBuffers(xf86_config->crtc[i], flags) &&
-	       pI830->SWCursor)
-	   {
-	       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-			  "Disabling HW cursor because the cursor memory "
-			  "allocation failed.\n");
-	       pI830->SWCursor = TRUE;
-	       break;
-	   }
-       }
-   }
+    /*
+     * Allocate a dummy page to pass when attempting to rebind the
+     * pre-allocated region.
+     */
+    if (!dryrun) {
+	memset(&(pI830->Dummy), 0, sizeof(pI830->Dummy));
+	pI830->Dummy.Key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 0,
+						  NULL);
+	pI830->Dummy.Offset = 0;
+    }
+#endif
+
+    if (!pI830->SWCursor && !dryrun) {
+	for (i = 0; i < xf86_config->num_crtc; i++) {
+	    if (!I830AllocateCursorBuffers(xf86_config->crtc[i], flags) &&
+		pI830->SWCursor)
+	    {
+		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+			   "Disabling HW cursor because the cursor memory "
+			   "allocation failed.\n");
+		pI830->SWCursor = TRUE;
+		break;
+	    }
+	}
+    }
 
 #ifdef I830_XV
-   AllocateOverlay(pScrn, flags);
+    AllocateOverlay(pScrn, flags);
 #endif
 
-   if (!pI830->NeedRingBufferLow)
-      AllocateRingBuffer(pScrn, flags);
+    if (!pI830->NeedRingBufferLow)
+	AllocateRingBuffer(pScrn, flags);
 
-   /* Clear scratch info */
-   memset(&(pI830->Scratch), 0, sizeof(I830MemRange));
-   pI830->Scratch.Key = -1;
-   memset(&(pI830->Scratch2), 0, sizeof(I830MemRange));
-   pI830->Scratch2.Key = -1;
-
-   if (!pI830->noAccel) {
-      size = MAX_SCRATCH_BUFFER_SIZE;
-      alloced = I830AllocVidMem(pScrn, &(pI830->Scratch), &(pI830->StolenPool),
-				size, GTT_PAGE_SIZE,
-				flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
-      if (alloced < size) {
-	 size = MIN_SCRATCH_BUFFER_SIZE;
-         alloced = I830AllocVidMem(pScrn, &(pI830->Scratch),
-				   &(pI830->StolenPool), size,
-				   GTT_PAGE_SIZE,
-				   flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
-      }
-      if (alloced < size) {
-	 if (!dryrun) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		       "Failed to allocate scratch buffer space\n");
-	 }
-	 return FALSE;
-      }
-      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-		    "%sAllocated %ld kB for the scratch buffer at 0x%lx\n", s,
-		    alloced / 1024, pI830->Scratch.Start);
-
-      /* Let's allocate another scratch buffer for the second head */
-      /* Again, this code won't execute on the dry run pass */
-      if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) {
-         size = MAX_SCRATCH_BUFFER_SIZE;
-         alloced = I830AllocVidMem(pScrn, &(pI830->Scratch2), 
-				&(pI830->StolenPool),
-				size, GTT_PAGE_SIZE,
-				flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
-         if (alloced < size) {
+    /* Clear scratch info */
+    memset(&(pI830->Scratch), 0, sizeof(I830MemRange));
+    pI830->Scratch.Key = -1;
+    memset(&(pI830->Scratch2), 0, sizeof(I830MemRange));
+    pI830->Scratch2.Key = -1;
+
+    if (!pI830->noAccel) {
+	size = MAX_SCRATCH_BUFFER_SIZE;
+	alloced = I830AllocVidMem(pScrn, &(pI830->Scratch),
+				  &(pI830->StolenPool),
+				  size, GTT_PAGE_SIZE,
+				  flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
+	if (alloced < size) {
 	    size = MIN_SCRATCH_BUFFER_SIZE;
-            alloced = I830AllocVidMem(pScrn, &(pI830->Scratch2),
-				   &(pI830->StolenPool), size,
-				   GTT_PAGE_SIZE,
-				   flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
-         }
-         if (alloced < size) {
+	    alloced = I830AllocVidMem(pScrn, &(pI830->Scratch),
+				      &(pI830->StolenPool), size,
+				      GTT_PAGE_SIZE,
+				      flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
+	}
+	if (alloced < size) {
 	    if (!dryrun) {
-	       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		       "Failed to allocate second scratch buffer space\n");
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			   "Failed to allocate scratch buffer space\n");
 	    }
 	    return FALSE;
-         }
-         xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-	      "%sAllocated %ld kB for the second scratch buffer at 0x%lx\n", s,
-	      alloced / 1024, pI830->Scratch2.Start);
-      }
-   }
+	}
+	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		       "%sAllocated %ld kB for the scratch buffer at 0x%lx\n",
+		       s, alloced / 1024, pI830->Scratch.Start);
+
+	/* Let's allocate another scratch buffer for the second head */
+	/* Again, this code won't execute on the dry run pass */
+	if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) {
+	    size = MAX_SCRATCH_BUFFER_SIZE;
+	    alloced = I830AllocVidMem(pScrn, &(pI830->Scratch2),
+				      &(pI830->StolenPool),
+				      size, GTT_PAGE_SIZE,
+				      flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
+	    if (alloced < size) {
+		size = MIN_SCRATCH_BUFFER_SIZE;
+		alloced = I830AllocVidMem(pScrn, &(pI830->Scratch2),
+					  &(pI830->StolenPool), size,
+					  GTT_PAGE_SIZE,
+					  flags | FROM_ANYWHERE |
+					  ALLOCATE_AT_TOP);
+	    }
+	    if (alloced < size) {
+		if (!dryrun) {
+		    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			       "Failed to allocate second scratch buffer "
+			       "space\n");
+		}
+		return FALSE;
+	    }
+	    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+			   "%sAllocated %ld kB for the second scratch buffer "
+			   "at 0x%lx\n", s,
+			   alloced / 1024, pI830->Scratch2.Start);
+	}
+    }
 
-   return TRUE;
+    return TRUE;
 }
 
 void
 I830ResetAllocations(ScrnInfoPtr pScrn, const int flags)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
+    I830Ptr pI830 = I830PTR(pScrn);
 
-   pI830->MemoryAperture.Start = pI830->StolenMemory.End;
-   pI830->MemoryAperture.End = pI830->FbMapSize;
-   pI830->MemoryAperture.Size = pI830->FbMapSize - pI830->StolenMemory.Size;
+    pI830->MemoryAperture.Start = pI830->StolenMemory.End;
+    pI830->MemoryAperture.End = pI830->FbMapSize;
+    pI830->MemoryAperture.Size = pI830->FbMapSize - pI830->StolenMemory.Size;
 #ifdef XF86DRI
-   if (!pI830->directRenderingDisabled) {
-      pI830->MemoryAperture.End -= KB(pI830->mmSize);
-      pI830->MemoryAperture.Size -= KB(pI830->mmSize);
-   }
-#endif
-   pI830->StolenPool.Fixed = pI830->StolenMemory;
-   pI830->StolenPool.Total = pI830->StolenMemory;
-   pI830->StolenPool.Free = pI830->StolenPool.Total;
-   pI830->FreeMemory = pI830->TotalVideoRam - pI830->StolenPool.Total.Size;
-   pI830->allocatedMemory = 0;
+    if (!pI830->directRenderingDisabled) {
+	pI830->MemoryAperture.End -= KB(pI830->mmSize);
+	pI830->MemoryAperture.Size -= KB(pI830->mmSize);
+    }
+#endif
+    pI830->StolenPool.Fixed = pI830->StolenMemory;
+    pI830->StolenPool.Total = pI830->StolenMemory;
+    pI830->StolenPool.Free = pI830->StolenPool.Total;
+    pI830->FreeMemory = pI830->TotalVideoRam - pI830->StolenPool.Total.Size;
+    pI830->allocatedMemory = 0;
 }
 
 long
 I830GetExcessMemoryAllocations(ScrnInfoPtr pScrn)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
-   long allocated;
+    I830Ptr pI830 = I830PTR(pScrn);
+    long allocated;
 
-   allocated = pI830->StolenPool.Total.Size + pI830->allocatedMemory;
-   if (allocated > pI830->TotalVideoRam)
-      return allocated - pI830->TotalVideoRam;
-   else
-      return 0;
+    allocated = pI830->StolenPool.Total.Size + pI830->allocatedMemory;
+    if (allocated > pI830->TotalVideoRam)
+	return allocated - pI830->TotalVideoRam;
+    else
+       return 0;
 }
 
 #ifdef XF86DRI
 static unsigned int
 myLog2(unsigned int n)
 {
-   unsigned int log2 = 1;
+    unsigned int log2 = 1;
 
-   while (n > 1) {
-      n >>= 1;
-      log2++;
-   }
-   return log2;
+    while (n > 1) {
+	n >>= 1;
+	log2++;
+    }
+    return log2;
 }
 
 Bool
 I830AllocateBackBuffer(ScrnInfoPtr pScrn, const int flags)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
-   unsigned long size, alloced, align = 0;
-   Bool tileable;
-   Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
-   int verbosity = dryrun ? 4 : 1;
-   const char *s = dryrun ? "[dryrun] " : "";
-   int lines;
-   int height = (pI830->rotation & (RR_Rotate_0 | RR_Rotate_180)) ? pScrn->virtualY : pScrn->virtualX;
-
-   /* Back Buffer */
-   memset(&(pI830->BackBuffer), 0, sizeof(pI830->BackBuffer));
-   pI830->BackBuffer.Key = -1;
-   tileable = !(flags & ALLOC_NO_TILING) &&
-	      IsTileable(pScrn, pScrn->displayWidth * pI830->cpp);
-   if (tileable) {
-      /* Make the height a multiple of the tile height (16) */
-      lines = (height + 15) / 16 * 16;
-   } else {
-      lines = height;
-   }
-
-   size = ROUND_TO_PAGE(pScrn->displayWidth * lines * pI830->cpp);
-   /*
-    * Try to allocate on the best tile-friendly boundaries.
-    */
-   alloced = 0;
-   if (tileable) {
-      align = GetBestTileAlignment(size);
-      for (align = GetBestTileAlignment(size); align >= (IS_I9XX(pI830) ? MB(1) : KB(512)); align >>= 1) {
-	 alloced = I830AllocVidMem(pScrn, &(pI830->BackBuffer),
-				   &(pI830->StolenPool), size, align,
-				   flags | FROM_ANYWHERE | ALLOCATE_AT_TOP |
-				   ALIGN_BOTH_ENDS);
-	 if (alloced >= size)
-	    break;
-      }
-   }
-   if (alloced < size) {
-      /* Give up on trying to tile */
-      tileable = FALSE;
-      size = ROUND_TO_PAGE(pScrn->displayWidth * height * pI830->cpp);
-      align = GTT_PAGE_SIZE;
-      alloced = I830AllocVidMem(pScrn, &(pI830->BackBuffer),
-				&(pI830->StolenPool), size, align,
-				flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
-   }
-   if (alloced < size) {
-      if (!dryrun) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		    "Failed to allocate back buffer space.\n");
-      }
-      return FALSE;
-   }
-   xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-		  "%sAllocated %ld kB for the back buffer at 0x%lx.\n", s,
-		  alloced / 1024, pI830->BackBuffer.Start);
+    I830Ptr pI830 = I830PTR(pScrn);
+    unsigned long size, alloced, align = 0;
+    Bool tileable;
+    Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
+    int verbosity = dryrun ? 4 : 1;
+    const char *s = dryrun ? "[dryrun] " : "";
+    int lines;
+    int height;
+
+    if (pI830->rotation & (RR_Rotate_0 | RR_Rotate_180))
+	height = pScrn->virtualY;
+    else
+	height = pScrn->virtualX;
+
+    /* Back Buffer */
+    memset(&(pI830->BackBuffer), 0, sizeof(pI830->BackBuffer));
+    pI830->BackBuffer.Key = -1;
+    tileable = !(flags & ALLOC_NO_TILING) &&
+	IsTileable(pScrn, pScrn->displayWidth * pI830->cpp);
+    if (tileable) {
+	/* Make the height a multiple of the tile height (16) */
+	lines = (height + 15) / 16 * 16;
+    } else {
+	lines = height;
+    }
+
+    size = ROUND_TO_PAGE(pScrn->displayWidth * lines * pI830->cpp);
+    /*
+     * Try to allocate on the best tile-friendly boundaries.
+     */
+    alloced = 0;
+    if (tileable) {
+	align = GetBestTileAlignment(size);
+	for (align = GetBestTileAlignment(size);
+	     align >= (IS_I9XX(pI830) ? MB(1) : KB(512)); align >>= 1)
+	{
+	    alloced = I830AllocVidMem(pScrn, &(pI830->BackBuffer),
+				      &(pI830->StolenPool), size, align,
+				      flags | FROM_ANYWHERE | ALLOCATE_AT_TOP |
+				      ALIGN_BOTH_ENDS);
+	    if (alloced >= size)
+		break;
+	}
+    }
+    if (alloced < size) {
+	/* Give up on trying to tile */
+	tileable = FALSE;
+	size = ROUND_TO_PAGE(pScrn->displayWidth * height * pI830->cpp);
+	align = GTT_PAGE_SIZE;
+	alloced = I830AllocVidMem(pScrn, &(pI830->BackBuffer),
+				  &(pI830->StolenPool), size, align,
+				  flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
+    }
+    if (alloced < size) {
+	if (!dryrun) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Failed to allocate back buffer space.\n");
+	}
+	return FALSE;
+    }
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		   "%sAllocated %ld kB for the back buffer at 0x%lx.\n", s,
+		   alloced / 1024, pI830->BackBuffer.Start);
 
-   return TRUE;
+    return TRUE;
 }
 
 Bool
 I830AllocateDepthBuffer(ScrnInfoPtr pScrn, const int flags)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
-   unsigned long size, alloced, align = 0;
-   Bool tileable;
-   Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
-   int verbosity = dryrun ? 4 : 1;
-   const char *s = dryrun ? "[dryrun] " : "";
-   int lines;
-   int height = (pI830->rotation & (RR_Rotate_0 | RR_Rotate_180)) ? pScrn->virtualY : pScrn->virtualX;
-
-   /* Depth Buffer -- same size as the back buffer */
-   memset(&(pI830->DepthBuffer), 0, sizeof(pI830->DepthBuffer));
-   pI830->DepthBuffer.Key = -1;
-   tileable = !(flags & ALLOC_NO_TILING) &&
-	      IsTileable(pScrn, pScrn->displayWidth * pI830->cpp);
-   if (tileable) {
-      /* Make the height a multiple of the tile height (16) */
-      lines = (height + 15) / 16 * 16;
-   } else {
-      lines = height;
-   }
-
-   size = ROUND_TO_PAGE(pScrn->displayWidth * lines * pI830->cpp);
-   /*
-    * Try to allocate on the best tile-friendly boundaries.
-    */
-   alloced = 0;
-   if (tileable) {
-      align = GetBestTileAlignment(size);
-      for (align = GetBestTileAlignment(size); align >= (IS_I9XX(pI830) ? MB(1) : KB(512)); align >>= 1) {
-	 alloced = I830AllocVidMem(pScrn, &(pI830->DepthBuffer),
-				   &(pI830->StolenPool), size, align,
-				   flags | FROM_ANYWHERE | ALLOCATE_AT_TOP |
-				   ALIGN_BOTH_ENDS);
-	 if (alloced >= size)
-	    break;
-      }
-   }
-   if (alloced < size) {
-      /* Give up on trying to tile */
-      tileable = FALSE;
-      size = ROUND_TO_PAGE(pScrn->displayWidth * height * pI830->cpp);
-      align = GTT_PAGE_SIZE;
-      alloced = I830AllocVidMem(pScrn, &(pI830->DepthBuffer),
-				&(pI830->StolenPool), size, align,
-				flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
-   }
-   if (alloced < size) {
-      if (!dryrun) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		    "Failed to allocate depth buffer space.\n");
-      }
-      return FALSE;
-   }
-   xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-		  "%sAllocated %ld kB for the depth buffer at 0x%lx.\n", s,
-		  alloced / 1024, pI830->DepthBuffer.Start);
+    I830Ptr pI830 = I830PTR(pScrn);
+    unsigned long size, alloced, align = 0;
+    Bool tileable;
+    Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
+    int verbosity = dryrun ? 4 : 1;
+    const char *s = dryrun ? "[dryrun] " : "";
+    int lines;
+    int height;
+
+    if (pI830->rotation & (RR_Rotate_0 | RR_Rotate_180))
+	height = pScrn->virtualY;
+    else
+	height = pScrn->virtualX;
+
+    /* Depth Buffer -- same size as the back buffer */
+    memset(&(pI830->DepthBuffer), 0, sizeof(pI830->DepthBuffer));
+    pI830->DepthBuffer.Key = -1;
+    tileable = !(flags & ALLOC_NO_TILING) &&
+	IsTileable(pScrn, pScrn->displayWidth * pI830->cpp);
+    if (tileable) {
+	/* Make the height a multiple of the tile height (16) */
+	lines = (height + 15) / 16 * 16;
+    } else {
+	lines = height;
+    }
 
-   return TRUE;
+    size = ROUND_TO_PAGE(pScrn->displayWidth * lines * pI830->cpp);
+    /*
+     * Try to allocate on the best tile-friendly boundaries.
+     */
+    alloced = 0;
+    if (tileable) {
+	align = GetBestTileAlignment(size);
+	for (align = GetBestTileAlignment(size);
+	     align >= (IS_I9XX(pI830) ? MB(1) : KB(512)); align >>= 1)
+	{
+	    alloced = I830AllocVidMem(pScrn, &(pI830->DepthBuffer),
+				      &(pI830->StolenPool), size, align,
+				      flags | FROM_ANYWHERE | ALLOCATE_AT_TOP |
+				      ALIGN_BOTH_ENDS);
+	    if (alloced >= size)
+		break;
+	}
+    }
+    if (alloced < size) {
+	/* Give up on trying to tile */
+	tileable = FALSE;
+	size = ROUND_TO_PAGE(pScrn->displayWidth * height * pI830->cpp);
+	align = GTT_PAGE_SIZE;
+	alloced = I830AllocVidMem(pScrn, &(pI830->DepthBuffer),
+				  &(pI830->StolenPool), size, align,
+				  flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
+    }
+    if (alloced < size) {
+	if (!dryrun) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Failed to allocate depth buffer space.\n");
+	}
+	return FALSE;
+    }
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		   "%sAllocated %ld kB for the depth buffer at 0x%lx.\n", s,
+		   alloced / 1024, pI830->DepthBuffer.Start);
+
+    return TRUE;
 }
 
 Bool
 I830AllocateTextureMemory(ScrnInfoPtr pScrn, const int flags)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
-   unsigned long size, alloced;
-   int i;
-   Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
-   int verbosity = dryrun ? 4 : 1;
-   const char *s = dryrun ? "[dryrun] " : "";
-
-   /* Allocate the remaining space for textures. */
-   memset(&(pI830->TexMem), 0, sizeof(pI830->TexMem));
-   pI830->TexMem.Key = -1;
-
-   if (pI830->mmModeFlags & I830_KERNEL_TEX) {
-
-      if (dryrun && pI830->pEnt->device->videoRam == 0) {
-	 /* If we're laying out a default-sized allocation, then don't be
-	  * too greedy and just ask for 32MB.
-	  */
-	 size = MB(32);
-      } else {
-	 size = GetFreeSpace(pScrn);
-      }
-      if (dryrun && (size < MB(1)))
-	 size = MB(1);
-      i = myLog2(size / I830_NR_TEX_REGIONS);
-      if (i < I830_LOG_MIN_TEX_REGION_SIZE)
-	 i = I830_LOG_MIN_TEX_REGION_SIZE;
-      pI830->TexGranularity = i;
-      /* Truncate size */
-      size >>= i;
-      size <<= i;
-      if (size < KB(512)) {
-	 if (!dryrun) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		       "Less than 512 kBytes for texture space (real %ld kBytes).\n", 
-		       size / 1024);
-	 }
-	 return FALSE;
-      }
-      alloced = I830AllocVidMem(pScrn, &(pI830->TexMem),
-				&(pI830->StolenPool), size, GTT_PAGE_SIZE,
-				flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
-      if (alloced < size) {
-	 if (!dryrun) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		       "Failed to allocate texture space.\n");
-	 }
-	 return FALSE;
-      }
-      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-		     "%sAllocated %ld kB for textures at 0x%lx\n", s,
-		     alloced / 1024, pI830->TexMem.Start);
-   }
+    I830Ptr pI830 = I830PTR(pScrn);
+    unsigned long size, alloced;
+    int i;
+    Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
+    int verbosity = dryrun ? 4 : 1;
+    const char *s = dryrun ? "[dryrun] " : "";
+
+    /* Allocate the remaining space for textures. */
+    memset(&(pI830->TexMem), 0, sizeof(pI830->TexMem));
+    pI830->TexMem.Key = -1;
+
+    if (pI830->mmModeFlags & I830_KERNEL_TEX) {
+	if (dryrun && pI830->pEnt->device->videoRam == 0) {
+	    /* If we're laying out a default-sized allocation, then don't be
+	     * too greedy and just ask for 32MB.
+	     */
+	    size = MB(32);
+	} else {
+	    size = GetFreeSpace(pScrn);
+	}
+	if (dryrun && (size < MB(1)))
+	    size = MB(1);
+	i = myLog2(size / I830_NR_TEX_REGIONS);
+	if (i < I830_LOG_MIN_TEX_REGION_SIZE)
+	    i = I830_LOG_MIN_TEX_REGION_SIZE;
+	pI830->TexGranularity = i;
+	/* Truncate size */
+	size >>= i;
+	size <<= i;
+	if (size < KB(512)) {
+	    if (!dryrun) {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			   "Less than 512 kBytes for texture space (real %ld "
+			   "kBytes).\n",
+			   size / 1024);
+	    }
+	    return FALSE;
+	}
+	alloced = I830AllocVidMem(pScrn, &(pI830->TexMem),
+				  &(pI830->StolenPool), size, GTT_PAGE_SIZE,
+				  flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
+	if (alloced < size) {
+	    if (!dryrun) {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			   "Failed to allocate texture space.\n");
+	    }
+	    return FALSE;
+	}
+	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		       "%sAllocated %ld kB for textures at 0x%lx\n", s,
+		       alloced / 1024, pI830->TexMem.Start);
+    }
 
-   return TRUE;
+    return TRUE;
 }
 
 Bool
 I830Allocate3DMemory(ScrnInfoPtr pScrn, const int flags)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
-   unsigned long size, alloced;
-   Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
-   int verbosity = dryrun ? 4 : 1;
-   const char *s = dryrun ? "[dryrun] " : "";
-
-   DPRINTF(PFX, "I830Allocate3DMemory\n");
-
-   /* Space for logical context.  32k is fine for right now. */
-   memset(&(pI830->ContextMem), 0, sizeof(pI830->ContextMem));
-   pI830->ContextMem.Key = -1;
-   size = KB(32);
-   alloced = I830AllocVidMem(pScrn, &(pI830->ContextMem),
-			     &(pI830->StolenPool), size, GTT_PAGE_SIZE,
-			     flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
-   if (alloced < size) {
-      if (!dryrun) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		    "Failed to allocate logical context space.\n");
-      }
-      return FALSE;
-   }
-   xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-		  "%sAllocated %ld kB for the logical context at 0x%lx.\n", s,
-		  alloced / 1024, pI830->ContextMem.Start);
-
-   if (!I830AllocateBackBuffer(pScrn, flags))
-      return FALSE;
+    I830Ptr pI830 = I830PTR(pScrn);
+    unsigned long size, alloced;
+    Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
+    int verbosity = dryrun ? 4 : 1;
+    const char *s = dryrun ? "[dryrun] " : "";
+
+    DPRINTF(PFX, "I830Allocate3DMemory\n");
+
+    /* Space for logical context.  32k is fine for right now. */
+    memset(&(pI830->ContextMem), 0, sizeof(pI830->ContextMem));
+    pI830->ContextMem.Key = -1;
+    size = KB(32);
+    alloced = I830AllocVidMem(pScrn, &(pI830->ContextMem),
+			      &(pI830->StolenPool), size, GTT_PAGE_SIZE,
+			      flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
+    if (alloced < size) {
+	if (!dryrun) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Failed to allocate logical context space.\n");
+	}
+	return FALSE;
+    }
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		   "%sAllocated %ld kB for the logical context at 0x%lx.\n", s,
+		   alloced / 1024, pI830->ContextMem.Start);
 
-   if (!I830AllocateDepthBuffer(pScrn, flags))
-      return FALSE;
+    if (!I830AllocateBackBuffer(pScrn, flags))
+	return FALSE;
 
-   if (!I830AllocateTextureMemory(pScrn, flags))
-      return FALSE;
+    if (!I830AllocateDepthBuffer(pScrn, flags))
+	return FALSE;
 
-   return TRUE;
+    if (!I830AllocateTextureMemory(pScrn, flags))
+	return FALSE;
+
+    return TRUE;
 }
 #endif
 
@@ -1273,39 +1307,40 @@ I830Allocate3DMemory(ScrnInfoPtr pScrn, 
 Bool
 I830DoPoolAllocation(ScrnInfoPtr pScrn, I830MemPool *pool)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
+    I830Ptr pI830 = I830PTR(pScrn);
 
-   DPRINTF(PFX, "I830DoPoolAllocation\n");
+    DPRINTF(PFX, "I830DoPoolAllocation\n");
 
-   if (!pool)
-      return FALSE;
+    if (!pool)
+	return FALSE;
 
-   /*
-    * Sanity check: there shouldn't be an allocation required when
-    * there is only stolen memory.
-    */
-   if (pI830->StolenOnly && (pool->Total.Size > pool->Fixed.Size)) {
-      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		 "I830DoPoolAllocation(): pool size is greater than the "
-		 "preallocated size,\n\t"
-		 "and there is no allocatable memory.\n");
-      return FALSE;
-   }
-
-   if (pool->Total.Size > pool->Fixed.Size) {
-      pool->Allocated.Size = pool->Total.Size - pool->Fixed.Size;
-      pool->Allocated.Key = xf86AllocateGARTMemory(pScrn->scrnIndex, 
-				   pool->Allocated.Size, 0, NULL);
-      if (pool->Allocated.Key == -1) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Pool allocation failed\n");
-	 return FALSE;
-      }
-      pool->Allocated.Start = pool->Fixed.End;
-      pool->Allocated.End = pool->Total.Size;
-      pool->Allocated.Offset = pool->Allocated.Start;
-   } else
-      pool->Allocated.Key = -1;
-   return TRUE;
+    /*
+     * Sanity check: there shouldn't be an allocation required when
+     * there is only stolen memory.
+     */
+    if (pI830->StolenOnly && (pool->Total.Size > pool->Fixed.Size)) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "I830DoPoolAllocation(): pool size is greater than the "
+		   "preallocated size,\n\t"
+		   "and there is no allocatable memory.\n");
+	return FALSE;
+    }
+
+    if (pool->Total.Size > pool->Fixed.Size) {
+	pool->Allocated.Size = pool->Total.Size - pool->Fixed.Size;
+	pool->Allocated.Key = xf86AllocateGARTMemory(pScrn->scrnIndex,
+						     pool->Allocated.Size, 0,
+						     NULL);
+	if (pool->Allocated.Key == -1) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Pool allocation failed\n");
+	    return FALSE;
+	}
+	pool->Allocated.Start = pool->Fixed.End;
+	pool->Allocated.End = pool->Total.Size;
+	pool->Allocated.Offset = pool->Allocated.Start;
+    } else
+	pool->Allocated.Key = -1;
+    return TRUE;
 }
 
 static unsigned long topOfMem = 0;
@@ -1333,114 +1368,117 @@ Bool
 I830FixOffset(ScrnInfoPtr pScrn, I830MemRange *mem)
 {
 #if POOL_RANGES
-   I830Ptr pI830 = I830PTR(pScrn);
+    I830Ptr pI830 = I830PTR(pScrn);
 #endif
 
-   if (!mem)
-      return FALSE;
+    if (!mem)
+	return FALSE;
 
-   if (mem->Pool && mem->Key == -1 && mem->Start < 0) {
-      mem->Start = mem->Pool->Total.End + mem->Start;
-      mem->End = mem->Start + mem->Size;
-   }
+    if (mem->Pool && mem->Key == -1 && mem->Start < 0) {
+	mem->Start = mem->Pool->Total.End + mem->Start;
+	mem->End = mem->Start + mem->Size;
+    }
 #if PACK_RANGES
-   /*
-    * Map AGP-allocated areas at the top of the stolen area, resulting in
-    * a contiguous region in the aperture.  Normally most AGP-allocated areas
-    * will be at the top of the aperture, making alignment requirements
-    * easier to achieve.  This optin is primarily for debugging purposes,
-    * and using this option can break any special alignment requirements.
-    */
-   if (!mem->Pool && mem->Start != 0 && mem->Key != -1 && mem->Physical == 0 &&
-	mem->Offset != 0) {
-      long diff;
-      if (mem->Offset != mem->Start)
-	 ErrorF("mem %p, Offset != Start\n", mem);
-      diff = mem->Offset - topOfMem;
-      mem->Start -= diff;
-      mem->End -= diff;
-      mem->Offset -= diff;
-      topOfMem += mem->Size;
-   }
+    /*
+     * Map AGP-allocated areas at the top of the stolen area, resulting in
+     * a contiguous region in the aperture.  Normally most AGP-allocated areas
+     * will be at the top of the aperture, making alignment requirements
+     * easier to achieve.  This optin is primarily for debugging purposes,
+     * and using this option can break any special alignment requirements.
+     */
+    if (!mem->Pool && mem->Start != 0 && mem->Key != -1 &&
+	mem->Physical == 0 && mem->Offset != 0)
+    {
+	long diff;
+	if (mem->Offset != mem->Start)
+	    ErrorF("mem %p, Offset != Start\n", mem);
+	diff = mem->Offset - topOfMem;
+	mem->Start -= diff;
+	mem->End -= diff;
+	mem->Offset -= diff;
+	topOfMem += mem->Size;
+    }
 #elif POOL_RANGES
-   /*
-    * Move AGP-allocated regions (that don't need a physical address) into
-    * the pre-allocated pool when there's enough space to do so.  Note: the
-    * AGP-allocated areas aren't freed.  This option is primarily for
-    * debugging purposes, and using it can break any special alignment
-    * requirements.
-    */
-   if (!mem->Pool && mem->Start >= pI830->StolenPool.Free.End &&
-       mem->Key != -1 && mem->Physical == 0 && mem->Offset != 0 &&
-       pI830->StolenPool.Free.Size >= mem->Size) {
-      long diff;
-      if (mem->Offset != mem->Start)
-	 ErrorF("mem %p, Offset != Start\n", mem);
-      diff = mem->Offset - pI830->StolenPool.Free.Start;
-      mem->Start -= diff;
-      mem->End -= diff;
-      mem->Offset -= diff;
-      mem->Key = -1;
-      pI830->StolenPool.Free.Start += mem->Size;
-      pI830->StolenPool.Free.Size -= mem->Size;
-   }
-#endif
-   xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-	      "%p: Memory at offset 0x%08lx, size %ld kBytes\n", (void *)mem,
-	      mem->Start, mem->Size / 1024);
-   return TRUE;
+    /*
+     * Move AGP-allocated regions (that don't need a physical address) into
+     * the pre-allocated pool when there's enough space to do so.  Note: the
+     * AGP-allocated areas aren't freed.  This option is primarily for
+     * debugging purposes, and using it can break any special alignment
+     * requirements.
+     */
+    if (!mem->Pool && mem->Start >= pI830->StolenPool.Free.End &&
+	mem->Key != -1 && mem->Physical == 0 && mem->Offset != 0 &&
+	pI830->StolenPool.Free.Size >= mem->Size)
+    {
+	long diff;
+
+	if (mem->Offset != mem->Start)
+	    ErrorF("mem %p, Offset != Start\n", mem);
+	diff = mem->Offset - pI830->StolenPool.Free.Start;
+	mem->Start -= diff;
+	mem->End -= diff;
+	mem->Offset -= diff;
+	mem->Key = -1;
+	pI830->StolenPool.Free.Start += mem->Size;
+	pI830->StolenPool.Free.Size -= mem->Size;
+    }
+#endif
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+	       "%p: Memory at offset 0x%08lx, size %ld kBytes\n", (void *)mem,
+	       mem->Start, mem->Size / 1024);
+    return TRUE;
 }
 
 Bool
 I830FixupOffsets(ScrnInfoPtr pScrn)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
-   xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-   int i;
-
-   DPRINTF(PFX, "I830FixupOffsets\n");
-
-   topOfMem = pI830->StolenPool.Total.End;
-   if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2)
-      I830FixOffset(pScrn, &(pI830->FrontBuffer2));
-   I830FixOffset(pScrn, &(pI830->FrontBuffer));
-
-   for (i = 0; i < xf86_config->num_crtc; i++) {
-      I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private;
-
-      I830FixOffset(pScrn, &intel_crtc->cursor_mem);
-      I830FixOffset(pScrn, &intel_crtc->cursor_mem_argb);
-   }
-
-   I830FixOffset(pScrn, &(pI830->LpRing->mem));
-   I830FixOffset(pScrn, &(pI830->Scratch));
-   if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2)
-      I830FixOffset(pScrn, &(pI830->Scratch2));
+    I830Ptr pI830 = I830PTR(pScrn);
+    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int i;
+
+    DPRINTF(PFX, "I830FixupOffsets\n");
+
+    topOfMem = pI830->StolenPool.Total.End;
+    if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2)
+	I830FixOffset(pScrn, &(pI830->FrontBuffer2));
+    I830FixOffset(pScrn, &(pI830->FrontBuffer));
+
+    for (i = 0; i < xf86_config->num_crtc; i++) {
+	I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private;
+
+	I830FixOffset(pScrn, &intel_crtc->cursor_mem);
+	I830FixOffset(pScrn, &intel_crtc->cursor_mem_argb);
+    }
+
+    I830FixOffset(pScrn, &(pI830->LpRing->mem));
+    I830FixOffset(pScrn, &(pI830->Scratch));
+    if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2)
+	I830FixOffset(pScrn, &(pI830->Scratch2));
 #ifdef I830_XV
-   if (pI830->XvEnabled) {
-      I830FixOffset(pScrn, pI830->OverlayMem);
-      if (pI830->LinearAlloc)
-         I830FixOffset(pScrn, &(pI830->LinearMem));
-   }
+    if (pI830->XvEnabled) {
+	I830FixOffset(pScrn, pI830->OverlayMem);
+	if (pI830->LinearAlloc)
+	    I830FixOffset(pScrn, &(pI830->LinearMem));
+    }
 #endif
 #ifdef XF86DRI
-   if (pI830->directRenderingEnabled) {
-      I830FixOffset(pScrn, &(pI830->ContextMem));
-      I830FixOffset(pScrn, &(pI830->BackBuffer));
-      I830FixOffset(pScrn, &(pI830->DepthBuffer));
-      if (pI830->mmModeFlags & I830_KERNEL_TEX) {
-	 I830FixOffset(pScrn, &(pI830->TexMem));
-      }
-   }
+    if (pI830->directRenderingEnabled) {
+	I830FixOffset(pScrn, &(pI830->ContextMem));
+	I830FixOffset(pScrn, &(pI830->BackBuffer));
+	I830FixOffset(pScrn, &(pI830->DepthBuffer));
+	if (pI830->mmModeFlags & I830_KERNEL_TEX) {
+	    I830FixOffset(pScrn, &(pI830->TexMem));
+	}
+    }
 #endif
 #ifdef I830_USE_EXA
-   if (pI830->useEXA) {
-       I830FixOffset(pScrn, &(pI830->Offscreen));
-       if (IS_I965G(pI830))
-           I830FixOffset(pScrn, &(pI830->EXAStateMem));
+    if (pI830->useEXA) {
+	I830FixOffset(pScrn, &(pI830->Offscreen));
+	if (IS_I965G(pI830))
+	    I830FixOffset(pScrn, &(pI830->EXAStateMem));
     }
 #endif
-   return TRUE;
+    return TRUE;
 }
 
 #ifdef XF86DRI
@@ -1455,499 +1493,505 @@ static void
 SetFence(ScrnInfoPtr pScrn, int nr, unsigned int start, unsigned int pitch,
          unsigned int size)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
-   I830RegPtr i830Reg = &pI830->ModeReg;
-   CARD32 val;
-   CARD32 fence_mask = 0;
-   unsigned int fence_pitch;
-
-   DPRINTF(PFX, "SetFence: %d, 0x%08x, %d, %d kByte\n",
-	   nr, start, pitch, size / 1024);
-
-   if (nr < 0 || nr > 7) {
-      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		 "SetFence: fence %d out of range\n",nr);
-      return;
-   }
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830RegPtr i830Reg = &pI830->ModeReg;
+    CARD32 val;
+    CARD32 fence_mask = 0;
+    unsigned int fence_pitch;
+
+    DPRINTF(PFX, "SetFence: %d, 0x%08x, %d, %d kByte\n",
+	    nr, start, pitch, size / 1024);
+
+    if (nr < 0 || nr > 7) {
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		   "SetFence: fence %d out of range\n",nr);
+	return;
+    }
 
-   i830Reg->Fence[nr] = 0;
+    i830Reg->Fence[nr] = 0;
 
-   if (IS_I9XX(pI830))
+    if (IS_I9XX(pI830))
    	fence_mask = ~I915G_FENCE_START_MASK;
-   else
+    else
    	fence_mask = ~I830_FENCE_START_MASK;
 
-   if (start & fence_mask) {
-      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		 "SetFence: %d: start (0x%08x) is not %s aligned\n",
-		 nr, start, (IS_I9XX(pI830)) ? "1MB" : "512k");
-      return;
-   }
-
-   if (start % size) {
-      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		 "SetFence: %d: start (0x%08x) is not size (%dk) aligned\n",
-		 nr, start, size / 1024);
-      return;
-   }
-
-   if (pitch & 127) {
-      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		 "SetFence: %d: pitch (%d) not a multiple of 128 bytes\n",
-		 nr, pitch);
-      return;
-   }
+    if (start & fence_mask) {
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		   "SetFence: %d: start (0x%08x) is not %s aligned\n",
+		   nr, start, (IS_I9XX(pI830)) ? "1MB" : "512k");
+	return;
+    }
+
+    if (start % size) {
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		   "SetFence: %d: start (0x%08x) is not size (%dk) aligned\n",
+		   nr, start, size / 1024);
+	return;
+    }
+
+    if (pitch & 127) {
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		   "SetFence: %d: pitch (%d) not a multiple of 128 bytes\n",
+		   nr, pitch);
+	return;
+    }
 
-   val = (start | FENCE_X_MAJOR | FENCE_VALID);
+    val = (start | FENCE_X_MAJOR | FENCE_VALID);
 
-   if (IS_I9XX(pI830)) {
+    if (IS_I9XX(pI830)) {
    	switch (size) {
-	   case MB(1):
-      		val |= I915G_FENCE_SIZE_1M;
-      		break;
-   	   case MB(2):
-      		val |= I915G_FENCE_SIZE_2M;
-      		break;
-   	   case MB(4):
-      		val |= I915G_FENCE_SIZE_4M;
-      		break;
-   	   case MB(8):
-      		val |= I915G_FENCE_SIZE_8M;
-      		break;
+	case MB(1):
+	    val |= I915G_FENCE_SIZE_1M;
+	    break;
+	case MB(2):
+	    val |= I915G_FENCE_SIZE_2M;
+	    break;
+	case MB(4):
+	    val |= I915G_FENCE_SIZE_4M;
+	    break;
+	case MB(8):
+	    val |= I915G_FENCE_SIZE_8M;
+	    break;
    	   case MB(16):
-      		val |= I915G_FENCE_SIZE_16M;
-      		break;
-   	   case MB(32):
-      		val |= I915G_FENCE_SIZE_32M;
-      		break;
-   	   case MB(64):
-      		val |= I915G_FENCE_SIZE_64M;
-      		break;
-   	   default:
-      		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		 "SetFence: %d: illegal size (%d kByte)\n", nr, size / 1024);
-      		return;
+	       val |= I915G_FENCE_SIZE_16M;
+	       break;
+	case MB(32):
+	    val |= I915G_FENCE_SIZE_32M;
+	    break;
+	case MB(64):
+	    val |= I915G_FENCE_SIZE_64M;
+	    break;
+	default:
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		       "SetFence: %d: illegal size (%d kByte)\n",
+		       nr, size / 1024);
+	    return;
    	}
     } else {
    	switch (size) {
-	   case KB(512):
-      		val |= FENCE_SIZE_512K;
-      		break;
-	   case MB(1):
-      		val |= FENCE_SIZE_1M;
-      		break;
-   	   case MB(2):
-      		val |= FENCE_SIZE_2M;
-      		break;
-   	   case MB(4):
-      		val |= FENCE_SIZE_4M;
-      		break;
-   	   case MB(8):
-      		val |= FENCE_SIZE_8M;
-      		break;
-   	   case MB(16):
-      		val |= FENCE_SIZE_16M;
-      		break;
-   	   case MB(32):
-      		val |= FENCE_SIZE_32M;
-      		break;
-   	   case MB(64):
-      		val |= FENCE_SIZE_64M;
-      		break;
-   	   default:
-      		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		 "SetFence: %d: illegal size (%d kByte)\n", nr, size / 1024);
-      		return;
+	case KB(512):
+	    val |= FENCE_SIZE_512K;
+	    break;
+	case MB(1):
+	    val |= FENCE_SIZE_1M;
+	    break;
+	case MB(2):
+	    val |= FENCE_SIZE_2M;
+	    break;
+	case MB(4):
+	    val |= FENCE_SIZE_4M;
+	    break;
+	case MB(8):
+	    val |= FENCE_SIZE_8M;
+	    break;
+	case MB(16):
+	    val |= FENCE_SIZE_16M;
+	    break;
+	case MB(32):
+	    val |= FENCE_SIZE_32M;
+	    break;
+	case MB(64):
+	    val |= FENCE_SIZE_64M;
+	    break;
+	default:
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		       "SetFence: %d: illegal size (%d kByte)\n",
+		       nr, size / 1024);
+	    return;
    	}
-   }
+    }
 
-   if (IS_I9XX(pI830))
+    if (IS_I9XX(pI830))
 	fence_pitch = pitch / 512;
-   else
+    else
 	fence_pitch = pitch / 128;
 
-   switch (fence_pitch) {
-   case 1:
-      val |= FENCE_PITCH_1;
-      break;
-   case 2:
-      val |= FENCE_PITCH_2;
-      break;
-   case 4:
-      val |= FENCE_PITCH_4;
-      break;
-   case 8:
-      val |= FENCE_PITCH_8;
-      break;
-   case 16:
-      val |= FENCE_PITCH_16;
-      break;
-   case 32:
-      val |= FENCE_PITCH_32;
-      break;
-   case 64:
-      val |= FENCE_PITCH_64;
-      break;
-   default:
-      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		 "SetFence: %d: illegal pitch (%d)\n", nr, pitch);
-      return;
-   }
+    switch (fence_pitch) {
+    case 1:
+	val |= FENCE_PITCH_1;
+	break;
+    case 2:
+	val |= FENCE_PITCH_2;
+	break;
+    case 4:
+	val |= FENCE_PITCH_4;
+	break;
+    case 8:
+	val |= FENCE_PITCH_8;
+	break;
+    case 16:
+       val |= FENCE_PITCH_16;
+       break;
+    case 32:
+	val |= FENCE_PITCH_32;
+	break;
+    case 64:
+	val |= FENCE_PITCH_64;
+	break;
+    default:
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		   "SetFence: %d: illegal pitch (%d)\n", nr, pitch);
+	return;
+    }
 
-   i830Reg->Fence[nr] = val;
+    i830Reg->Fence[nr] = val;
 }
 
 static Bool
 MakeTiles(ScrnInfoPtr pScrn, I830MemRange *pMem, unsigned int fence)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
-   int pitch, ntiles, i;
+    I830Ptr pI830 = I830PTR(pScrn);
+    int pitch, ntiles, i;
 
 #if 0
-   /* Hack to "improve" the alignment of the front buffer.
-    */
-   while (!(pMem->Start & ~pMem->Alignment) && pMem->Alignment < 0x00400000 )
-      pMem->Alignment <<= 1;
+    /* Hack to "improve" the alignment of the front buffer. */
+    while (!(pMem->Start & ~pMem->Alignment) && pMem->Alignment < 0x00400000 )
+	pMem->Alignment <<= 1;
 #endif
 
-   if (tileGeneration != serverGeneration) {
-      tileGeneration = serverGeneration;
-      nextTile = 0;
-   }
+    if (tileGeneration != serverGeneration) {
+	tileGeneration = serverGeneration;
+	nextTile = 0;
+    }
 
-   pitch = pScrn->displayWidth * pI830->cpp;
+    pitch = pScrn->displayWidth * pI830->cpp;
 
-   if (IS_I965G(pI830)) {
-      I830RegPtr i830Reg = &pI830->ModeReg;
+    if (IS_I965G(pI830)) {
+	I830RegPtr i830Reg = &pI830->ModeReg;
 
-      switch (fence) {
-         case FENCE_XMAJOR:
-            i830Reg->Fence[nextTile] = (((pitch / 128) - 1) << 2) | pMem->Start | 1;
+	switch (fence) {
+	case FENCE_XMAJOR:
+            i830Reg->Fence[nextTile] = (((pitch / 128) - 1) << 2) |
+		pMem->Start | 1;
             break;
-         case FENCE_YMAJOR:
+	case FENCE_YMAJOR:
             /* YMajor can be 128B aligned but the current code dictates
              * otherwise. This isn't a problem apart from memory waste.
              * FIXME */
-            i830Reg->Fence[nextTile] = (((pitch / 128) - 1) << 2) | pMem->Start | 1;
+            i830Reg->Fence[nextTile] = (((pitch / 128) - 1) << 2) |
+		pMem->Start | 1;
 	    i830Reg->Fence[nextTile] |= (1<<1);
             break;
-         default:
-         case FENCE_LINEAR:
+	default:
+	case FENCE_LINEAR:
             break;
-      }
+	}
+
+	i830Reg->Fence[nextTile+FENCE_NEW_NR] = pMem->End;
+	nextTile++;
+	return TRUE;
+    }
 
-      i830Reg->Fence[nextTile+FENCE_NEW_NR] = pMem->End;
-      nextTile++;
-      return TRUE;
-   }
-
-   /*
-    * Simply try to break the region up into at most four pieces of size
-    * equal to the alignment.
-    */
-   ntiles = ROUND_TO(pMem->Size, pMem->Alignment) / pMem->Alignment;
-   if (ntiles >= 4) {
-      return FALSE;
-   }
-
-   for (i = 0; i < ntiles; i++, nextTile++) {
-      SetFence(pScrn, nextTile, pMem->Start + i * pMem->Alignment,
-	       pitch, pMem->Alignment);
-   }
-   return TRUE;
+    /*
+     * Simply try to break the region up into at most four pieces of size
+     * equal to the alignment.
+     */
+    ntiles = ROUND_TO(pMem->Size, pMem->Alignment) / pMem->Alignment;
+    if (ntiles >= 4) {
+	return FALSE;
+    }
+
+    for (i = 0; i < ntiles; i++, nextTile++) {
+	SetFence(pScrn, nextTile, pMem->Start + i * pMem->Alignment,
+		 pitch, pMem->Alignment);
+    }
+    return TRUE;
 }
 
 void
 I830SetupMemoryTiling(ScrnInfoPtr pScrn)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
-   int i;
+    I830Ptr pI830 = I830PTR(pScrn);
+    int i;
 
-   /* Clear out */
-   if (IS_I965G(pI830)) {
-      for (i = 0; i < FENCE_NEW_NR*2; i++)
-	 pI830->ModeReg.Fence[i] = 0;
-   } else {
-      for (i = 0; i < 8; i++)
-         pI830->ModeReg.Fence[i] = 0;
-   }
-
-   nextTile = 0;
-   tileGeneration = -1;
-
-   /* We currently only attempt to tile the back and depth buffers. */
-   if (!pI830->directRenderingEnabled)
-      return;
-
-   if (!IsTileable(pScrn, pScrn->displayWidth * pI830->cpp)) {
-      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		 "I830SetupMemoryTiling: Not tileable 0x%x\n",
-		 pScrn->displayWidth * pI830->cpp);
-      pI830->allowPageFlip = FALSE;
-      return;
-   }
-
-   pI830->front_tiled = FENCE_LINEAR;
-   pI830->back_tiled = FENCE_LINEAR;
-   pI830->depth_tiled = FENCE_LINEAR;
-
-   if (pI830->allowPageFlip) {
-      if (pI830->allowPageFlip && pI830->FrontBuffer.Alignment >= KB(512)) {
-	 if (MakeTiles(pScrn, &(pI830->FrontBuffer), FENCE_XMAJOR)) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		       "Activating tiled memory for the front buffer\n");
-            pI830->front_tiled = FENCE_XMAJOR;
-	 } else {
+    /* Clear out */
+    if (IS_I965G(pI830)) {
+	for (i = 0; i < FENCE_NEW_NR*2; i++)
+	    pI830->ModeReg.Fence[i] = 0;
+    } else {
+	for (i = 0; i < 8; i++)
+	    pI830->ModeReg.Fence[i] = 0;
+    }
+
+    nextTile = 0;
+    tileGeneration = -1;
+
+    /* We currently only attempt to tile the back and depth buffers. */
+    if (!pI830->directRenderingEnabled)
+	return;
+
+    if (!IsTileable(pScrn, pScrn->displayWidth * pI830->cpp)) {
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		   "I830SetupMemoryTiling: Not tileable 0x%x\n",
+		   pScrn->displayWidth * pI830->cpp);
+	pI830->allowPageFlip = FALSE;
+	return;
+    }
+
+    pI830->front_tiled = FENCE_LINEAR;
+    pI830->back_tiled = FENCE_LINEAR;
+    pI830->depth_tiled = FENCE_LINEAR;
+
+    if (pI830->allowPageFlip) {
+	if (pI830->allowPageFlip && pI830->FrontBuffer.Alignment >= KB(512)) {
+	    if (MakeTiles(pScrn, &(pI830->FrontBuffer), FENCE_XMAJOR)) {
+		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+			   "Activating tiled memory for the front buffer\n");
+		pI830->front_tiled = FENCE_XMAJOR;
+	    } else {
+		pI830->allowPageFlip = FALSE;
+		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+			   "MakeTiles failed for the front buffer\n");
+	    }
+	} else {
 	    pI830->allowPageFlip = FALSE;
 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		       "MakeTiles failed for the front buffer\n");
-	 }
-      } else {
-	 pI830->allowPageFlip = FALSE;
-	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		 "Alignment bad for the front buffer\n");
-      }
-   }
+		       "Alignment bad for the front buffer\n");
+	}
+    }
 
-   /*
-    * We tried to get the best alignment during the allocation.  Check
-    * the alignment values to tell.  If well-aligned allocations were
-    * successful, the address range reserved is a multiple of the align
-    * value.
-    */
-   if (pI830->BackBuffer.Alignment >= KB(512)) {
-      if (MakeTiles(pScrn, &(pI830->BackBuffer), FENCE_XMAJOR)) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		    "Activating tiled memory for the back buffer.\n");
-         pI830->back_tiled = FENCE_XMAJOR;
-      } else {
-	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		    "MakeTiles failed for the back buffer.\n");
-	 pI830->allowPageFlip = FALSE;
-      }
-   }
+    /*
+     * We tried to get the best alignment during the allocation.  Check
+     * the alignment values to tell.  If well-aligned allocations were
+     * successful, the address range reserved is a multiple of the align
+     * value.
+     */
+    if (pI830->BackBuffer.Alignment >= KB(512)) {
+	if (MakeTiles(pScrn, &(pI830->BackBuffer), FENCE_XMAJOR)) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		       "Activating tiled memory for the back buffer.\n");
+	    pI830->back_tiled = FENCE_XMAJOR;
+	} else {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		       "MakeTiles failed for the back buffer.\n");
+	    pI830->allowPageFlip = FALSE;
+	}
+    }
 
-   if (pI830->DepthBuffer.Alignment >= KB(512)) {
-      if (MakeTiles(pScrn, &(pI830->DepthBuffer), FENCE_YMAJOR)) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-	 	    "Activating tiled memory for the depth buffer.\n");
-         pI830->depth_tiled = FENCE_YMAJOR;
-      } else {
-	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		    "MakeTiles failed for the depth buffer.\n");
-      }
-   }}
+    if (pI830->DepthBuffer.Alignment >= KB(512)) {
+	if (MakeTiles(pScrn, &(pI830->DepthBuffer), FENCE_YMAJOR)) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		       "Activating tiled memory for the depth buffer.\n");
+	    pI830->depth_tiled = FENCE_YMAJOR;
+	} else {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		       "MakeTiles failed for the depth buffer.\n");
+	}
+    }
+}
 #endif /* XF86DRI */
 
 static Bool
 BindMemRange(ScrnInfoPtr pScrn, I830MemRange *mem)
 {
-   if (!mem)
-      return FALSE;
+    if (!mem)
+	return FALSE;
 
-   if (mem->Key == -1)
-      return TRUE;
+    if (mem->Key == -1)
+	return TRUE;
 
-   return xf86BindGARTMemory(pScrn->scrnIndex, mem->Key, mem->Offset);
+    return xf86BindGARTMemory(pScrn->scrnIndex, mem->Key, mem->Offset);
 }
 
 Bool
 I830BindAGPMemory(ScrnInfoPtr pScrn)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
+    I830Ptr pI830 = I830PTR(pScrn);
 
-   DPRINTF(PFX,
-	   "I830BindAGPMemory: StolenOnly is %s, pI830->GttBound is %s\n",
-	   BOOLTOSTRING(pI830->StolenOnly), BOOLTOSTRING(pI830->GttBound));
+    DPRINTF(PFX,
+	    "I830BindAGPMemory: StolenOnly is %s, pI830->GttBound is %s\n",
+	    BOOLTOSTRING(pI830->StolenOnly), BOOLTOSTRING(pI830->GttBound));
 
-   if (pI830->StolenOnly == TRUE)
-      return TRUE;
+    if (pI830->StolenOnly == TRUE)
+	return TRUE;
 
-   if (xf86AgpGARTSupported() && !pI830->GttBound) {
-      xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-      int i;
+    if (xf86AgpGARTSupported() && !pI830->GttBound) {
+	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+	int i;
 
-      if (!xf86AcquireGART(pScrn->scrnIndex))
-	 return FALSE;
+	if (!xf86AcquireGART(pScrn->scrnIndex))
+	    return FALSE;
 
 #if REMAP_RESERVED
-      /* Rebind the pre-allocated region. */
-      BindMemRange(pScrn, &(pI830->Dummy));
+	/* Rebind the pre-allocated region. */
+	BindMemRange(pScrn, &(pI830->Dummy));
 #endif
 
-      if (!BindMemRange(pScrn, &(pI830->StolenPool.Allocated)))
-	 return FALSE;
-      if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2)
-         if (!BindMemRange(pScrn, &(pI830->FrontBuffer2)))
+	if (!BindMemRange(pScrn, &(pI830->StolenPool.Allocated)))
+	    return FALSE;
+	if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2)
+	    if (!BindMemRange(pScrn, &(pI830->FrontBuffer2)))
+		return FALSE;
+	if (!BindMemRange(pScrn, &(pI830->FrontBuffer)))
 	    return FALSE;
-      if (!BindMemRange(pScrn, &(pI830->FrontBuffer)))
-	 return FALSE;
 
-      for (i = 0; i < xf86_config->num_crtc; i++) {
-	 I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private;
+	for (i = 0; i < xf86_config->num_crtc; i++) {
+	  I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private;
 
-	 if (!BindMemRange(pScrn, &intel_crtc->cursor_mem))
-	    return FALSE;
-	 if (!BindMemRange(pScrn, &intel_crtc->cursor_mem_argb))
+	  if (!BindMemRange(pScrn, &intel_crtc->cursor_mem))
+	      return FALSE;
+	  if (!BindMemRange(pScrn, &intel_crtc->cursor_mem_argb))
+	      return FALSE;
+	}
+	if (!BindMemRange(pScrn, &(pI830->LpRing->mem)))
 	    return FALSE;
-      }
-      if (!BindMemRange(pScrn, &(pI830->LpRing->mem)))
-	 return FALSE;
-      if (!BindMemRange(pScrn, &(pI830->Scratch)))
-	 return FALSE;
-      if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2)
-         if (!BindMemRange(pScrn, &(pI830->Scratch2)))
+	if (!BindMemRange(pScrn, &(pI830->Scratch)))
 	    return FALSE;
+	if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2)
+	    if (!BindMemRange(pScrn, &(pI830->Scratch2)))
+		return FALSE;
 #ifdef I830_XV
-      if (pI830->XvEnabled) {
-         if (!BindMemRange(pScrn, pI830->OverlayMem))
-	    return FALSE;
-         if (pI830->LinearAlloc)
-            if (!BindMemRange(pScrn, &(pI830->LinearMem)))
-	       return FALSE;
+	if (pI830->XvEnabled) {
+	    if (!BindMemRange(pScrn, pI830->OverlayMem))
+		return FALSE;
+	    if (pI830->LinearAlloc)
+		if (!BindMemRange(pScrn, &(pI830->LinearMem)))
+		    return FALSE;
       }
 #endif
 #ifdef XF86DRI
-      if (pI830->directRenderingEnabled) {
-	 if (!BindMemRange(pScrn, &(pI830->ContextMem)))
-	    return FALSE;
-	 if (!BindMemRange(pScrn, &(pI830->BackBuffer)))
-	    return FALSE;
-	 if (!BindMemRange(pScrn, &(pI830->DepthBuffer)))
-	    return FALSE;
-	 if ((pI830->mmModeFlags & I830_KERNEL_TEX) && 
-	     !BindMemRange(pScrn, &(pI830->TexMem)))
-	    return FALSE;
+	if (pI830->directRenderingEnabled) {
+	    if (!BindMemRange(pScrn, &(pI830->ContextMem)))
+		return FALSE;
+	    if (!BindMemRange(pScrn, &(pI830->BackBuffer)))
+		return FALSE;
+	    if (!BindMemRange(pScrn, &(pI830->DepthBuffer)))
+		return FALSE;
+	    if ((pI830->mmModeFlags & I830_KERNEL_TEX) &&
+		!BindMemRange(pScrn, &(pI830->TexMem)))
+		return FALSE;
       }
 #endif
 #ifdef I830_USE_EXA
-     if (pI830->useEXA) {
-         if (!BindMemRange(pScrn, &(pI830->Offscreen)))
-	    return FALSE;
-         if (IS_I965G(pI830) && !BindMemRange(pScrn, &(pI830->EXAStateMem)))
-	    return FALSE;
-     }
+	if (pI830->useEXA) {
+	    if (!BindMemRange(pScrn, &(pI830->Offscreen)))
+		return FALSE;
+	    if (IS_I965G(pI830) && !BindMemRange(pScrn, &(pI830->EXAStateMem)))
+		return FALSE;
+	}
 #endif
-      pI830->GttBound = 1;
-   }
+	pI830->GttBound = 1;
+    }
 
-   return TRUE;
+    return TRUE;
 }
 
 static Bool
 UnbindMemRange(ScrnInfoPtr pScrn, I830MemRange *mem)
 {
-   if (!mem)
-      return FALSE;
+    if (!mem)
+	return FALSE;
 
-   if (mem->Key == -1)
-      return TRUE;
+    if (mem->Key == -1)
+	return TRUE;
 
-   return xf86UnbindGARTMemory(pScrn->scrnIndex, mem->Key);
+    return xf86UnbindGARTMemory(pScrn->scrnIndex, mem->Key);
 }
 
 
 Bool
 I830UnbindAGPMemory(ScrnInfoPtr pScrn)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
+    I830Ptr pI830 = I830PTR(pScrn);
 
-   DPRINTF(PFX,
-	   "I830UnbindAGPMemory: StolenOnly is %s, pI830->GttBound is %s\n",
-	   BOOLTOSTRING(pI830->StolenOnly), BOOLTOSTRING(pI830->GttBound));
-
-   if (pI830->StolenOnly == TRUE)
-      return TRUE;
-
-   if (xf86AgpGARTSupported() && pI830->GttBound) {
-      xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-      int i;
+    DPRINTF(PFX,
+	    "I830UnbindAGPMemory: StolenOnly is %s, pI830->GttBound is %s\n",
+	    BOOLTOSTRING(pI830->StolenOnly), BOOLTOSTRING(pI830->GttBound));
+
+    if (pI830->StolenOnly == TRUE)
+	return TRUE;
+
+    if (xf86AgpGARTSupported() && pI830->GttBound) {
+	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+	int i;
 
 #if REMAP_RESERVED
-      /* "unbind" the pre-allocated region. */
-      UnbindMemRange(pScrn, &(pI830->Dummy));
+	/* "unbind" the pre-allocated region. */
+	UnbindMemRange(pScrn, &(pI830->Dummy));
 #endif
 
-      if (!UnbindMemRange(pScrn, &(pI830->StolenPool.Allocated)))
-	 return FALSE;
-      if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2)
-         if (!UnbindMemRange(pScrn, &(pI830->FrontBuffer2)))
+	if (!UnbindMemRange(pScrn, &(pI830->StolenPool.Allocated)))
+	    return FALSE;
+	if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2)
+	    if (!UnbindMemRange(pScrn, &(pI830->FrontBuffer2)))
+		return FALSE;
+	if (!UnbindMemRange(pScrn, &(pI830->FrontBuffer)))
 	    return FALSE;
-      if (!UnbindMemRange(pScrn, &(pI830->FrontBuffer)))
-	 return FALSE;
 
-      for (i = 0; i < xf86_config->num_crtc; i++) {
-	 I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private;
+	for (i = 0; i < xf86_config->num_crtc; i++) {
+	    I830CrtcPrivatePtr intel_crtc =
+		xf86_config->crtc[i]->driver_private;
 
-	 if (!UnbindMemRange(pScrn, &intel_crtc->cursor_mem))
-	    return FALSE;
-	 if (!UnbindMemRange(pScrn, &intel_crtc->cursor_mem_argb))
-	    return FALSE;
-      }
+	    if (!UnbindMemRange(pScrn, &intel_crtc->cursor_mem))
+		return FALSE;
+	    if (!UnbindMemRange(pScrn, &intel_crtc->cursor_mem_argb))
+		return FALSE;
+	}
 
-      if (!UnbindMemRange(pScrn, &(pI830->LpRing->mem)))
-	 return FALSE;
-      if (!UnbindMemRange(pScrn, &(pI830->Scratch)))
-	 return FALSE;
-      if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2)
-         if (!UnbindMemRange(pScrn, &(pI830->Scratch2)))
+	if (!UnbindMemRange(pScrn, &(pI830->LpRing->mem)))
 	    return FALSE;
-#ifdef I830_XV
-      if (pI830->XvEnabled) {
-         if (!UnbindMemRange(pScrn, pI830->OverlayMem))
+	if (!UnbindMemRange(pScrn, &(pI830->Scratch)))
 	    return FALSE;
-         if (pI830->LinearAlloc)
-            if (!UnbindMemRange(pScrn, &(pI830->LinearMem)))
-   	       return FALSE;
-      }
+	if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2)
+	    if (!UnbindMemRange(pScrn, &(pI830->Scratch2)))
+		return FALSE;
+#ifdef I830_XV
+	if (pI830->XvEnabled) {
+	    if (!UnbindMemRange(pScrn, pI830->OverlayMem))
+		return FALSE;
+	    if (pI830->LinearAlloc)
+		if (!UnbindMemRange(pScrn, &(pI830->LinearMem)))
+		    return FALSE;
+	}
 #endif
 #ifdef XF86DRI
-      if (pI830->directRenderingEnabled) {
-	 if (!UnbindMemRange(pScrn, &(pI830->ContextMem)))
-	    return FALSE;
-	 if (!UnbindMemRange(pScrn, &(pI830->BackBuffer)))
-	    return FALSE;
-	 if (!UnbindMemRange(pScrn, &(pI830->DepthBuffer)))
-	    return FALSE;
-	 if ((pI830->mmModeFlags & I830_KERNEL_TEX) && 
-	     !UnbindMemRange(pScrn, &(pI830->TexMem)))
-	    return FALSE;
-      }
+	if (pI830->directRenderingEnabled) {
+	    if (!UnbindMemRange(pScrn, &(pI830->ContextMem)))
+		return FALSE;
+	    if (!UnbindMemRange(pScrn, &(pI830->BackBuffer)))
+		return FALSE;
+	    if (!UnbindMemRange(pScrn, &(pI830->DepthBuffer)))
+		return FALSE;
+	    if ((pI830->mmModeFlags & I830_KERNEL_TEX) &&
+		!UnbindMemRange(pScrn, &(pI830->TexMem)))
+		return FALSE;
+	}
 #endif
 #ifdef I830_USE_EXA
-     if (pI830->useEXA) {
-         if (!UnbindMemRange(pScrn, &(pI830->Offscreen)))
-	    return FALSE;
-         if (IS_I965G(pI830) && !UnbindMemRange(pScrn, &(pI830->EXAStateMem)))
-	    return FALSE;
-     }
+	if (pI830->useEXA) {
+	    if (!UnbindMemRange(pScrn, &(pI830->Offscreen)))
+		return FALSE;
+	    if (IS_I965G(pI830) && !UnbindMemRange(pScrn,
+						   &(pI830->EXAStateMem)))
+		return FALSE;
+	}
 #endif
-      if (!xf86ReleaseGART(pScrn->scrnIndex))
-	 return FALSE;
+	if (!xf86ReleaseGART(pScrn->scrnIndex))
+	    return FALSE;
 
-      pI830->GttBound = 0;
-   }
+	pI830->GttBound = 0;
+    }
 
-   return TRUE;
+    return TRUE;
 }
 
 long
 I830CheckAvailableMemory(ScrnInfoPtr pScrn)
 {
-   AgpInfoPtr agpinf;
-   int maxPages;
+    AgpInfoPtr agpinf;
+    int maxPages;
 
-   if (!xf86AgpGARTSupported() ||
-       !xf86AcquireGART(pScrn->scrnIndex) ||
-       (agpinf = xf86GetAGPInfo(pScrn->scrnIndex)) == NULL ||
-       !xf86ReleaseGART(pScrn->scrnIndex))
-      return -1;
-
-   maxPages = agpinf->totalPages - agpinf->usedPages;
-   xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, "%s: %d kB available\n",
-		  "I830CheckAvailableMemory", maxPages * 4);
+    if (!xf86AgpGARTSupported() ||
+	!xf86AcquireGART(pScrn->scrnIndex) ||
+	(agpinf = xf86GetAGPInfo(pScrn->scrnIndex)) == NULL ||
+	!xf86ReleaseGART(pScrn->scrnIndex))
+	return -1;
+
+    maxPages = agpinf->totalPages - agpinf->usedPages;
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, "%s: %d kB available\n",
+		   "I830CheckAvailableMemory", maxPages * 4);
 
-   return maxPages * 4;
+    return maxPages * 4;
 }
 
 #ifdef I830_USE_XAA
@@ -1962,28 +2006,28 @@ i830_xf86AllocateOffscreenLinear(ScreenP
 				 RemoveLinearCallbackProcPtr removeCB,
 				 pointer privData)
 {
-   FBLinearPtr linear;
-   int max_size;
+    FBLinearPtr linear;
+    int max_size;
 
-   linear = xf86AllocateOffscreenLinear(pScreen, length, granularity, moveCB,
-					removeCB, privData);
-   if (linear != NULL)
-      return linear;
+    linear = xf86AllocateOffscreenLinear(pScreen, length, granularity, moveCB,
+					 removeCB, privData);
+    if (linear != NULL)
+	return linear;
 
-   /* The above allocation didn't succeed, so purge unlocked stuff and try
-    * again.
-    */
-   xf86QueryLargestOffscreenLinear(pScreen, &max_size, granularity,
-				   PRIORITY_EXTREME);
+    /* The above allocation didn't succeed, so purge unlocked stuff and try
+     * again.
+     */
+    xf86QueryLargestOffscreenLinear(pScreen, &max_size, granularity,
+				    PRIORITY_EXTREME);
 
-   if (max_size < length)
-      return NULL;
+    if (max_size < length)
+	return NULL;
 
-   xf86PurgeUnlockedOffscreenAreas(pScreen);
+    xf86PurgeUnlockedOffscreenAreas(pScreen);
 
-   linear = xf86AllocateOffscreenLinear(pScreen, length, granularity, moveCB,
-					removeCB, privData);
+    linear = xf86AllocateOffscreenLinear(pScreen, length, granularity, moveCB,
+					 removeCB, privData);
 
-   return linear;
+    return linear;
 }
 #endif
diff-tree dd24d2a082b41abc466391c37a9b3d066586dc55 (from 681966ce6548c6f47b087eb7e369674b7ddbaade)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Feb 22 11:46:44 2007 -0800

    Remove copied X server headers from driver.
    
    These two headers were copied during mode setting development; as that code
    is now inside the server, these files are no longer needed here.

diff --git a/src/xf86Optrec.h b/src/xf86Optrec.h
deleted file mode 100644
index 183b857..0000000
--- a/src/xf86Optrec.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/* 
- * 
- * Copyright (c) 1997  Metro Link Incorporated
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"), 
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- * 
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- * 
- * Except as contained in this notice, the name of the Metro Link shall not be
- * used in advertising or otherwise to promote the sale, use or other dealings
- * in this Software without prior written authorization from Metro Link.
- * 
- */
-/*
- * Copyright (c) 1997-2001 by The XFree86 Project, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name of the copyright holder(s)
- * and author(s) shall not be used in advertising or otherwise to promote
- * the sale, use or other dealings in this Software without prior written
- * authorization from the copyright holder(s) and author(s).
- */
-
-
-/* 
- * This file contains the Option Record that is passed between the Parser,
- * and Module setup procs.
- */
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#ifndef _xf86Optrec_h_
-#define _xf86Optrec_h_
-#include <stdio.h>
-
-/* 
- * all records that need to be linked lists should contain a GenericList as
- * their first field.
- */
-typedef struct generic_list_rec
-{
-	void *next;
-}
-GenericListRec, *GenericListPtr, *glp;
-
-/*
- * All options are stored using this data type.
- */
-typedef struct
-{
-	GenericListRec list;
-	char *opt_name;
-	char *opt_val;
-	int opt_used;
-	char *opt_comment;
-}
-XF86OptionRec, *XF86OptionPtr;
-
-
-XF86OptionPtr xf86addNewOption(XF86OptionPtr head, char *name, char *val);
-XF86OptionPtr xf86optionListDup(XF86OptionPtr opt);
-void xf86optionListFree(XF86OptionPtr opt);
-char *xf86optionName(XF86OptionPtr opt);
-char *xf86optionValue(XF86OptionPtr opt);
-XF86OptionPtr xf86newOption(char *name, char *value);
-XF86OptionPtr xf86nextOption(XF86OptionPtr list);
-XF86OptionPtr xf86findOption(XF86OptionPtr list, const char *name);
-char *xf86findOptionValue(XF86OptionPtr list, const char *name);
-int xf86findOptionBoolean (XF86OptionPtr, const char *, int);
-XF86OptionPtr xf86optionListCreate(const char **options, int count, int used);
-XF86OptionPtr xf86optionListMerge(XF86OptionPtr head, XF86OptionPtr tail);
-char *xf86configStrdup (const char *s);
-int xf86nameCompare (const char *s1, const char *s2);
-char *xf86uLongToString(unsigned long i);
-void xf86debugListOptions(XF86OptionPtr);
-XF86OptionPtr xf86parseOption(XF86OptionPtr head);
-void xf86printOptionList(FILE *fp, XF86OptionPtr list, int tabs);
-
-
-#endif /* _xf86Optrec_h_ */
diff --git a/src/xf86Parser.h b/src/xf86Parser.h
deleted file mode 100644
index a682927..0000000
--- a/src/xf86Parser.h
+++ /dev/null
@@ -1,483 +0,0 @@
-/* 
- * 
- * Copyright (c) 1997  Metro Link Incorporated
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"), 
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- * 
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- * 
- * Except as contained in this notice, the name of the Metro Link shall not be
- * used in advertising or otherwise to promote the sale, use or other dealings
- * in this Software without prior written authorization from Metro Link.
- * 
- */
-/*
- * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name of the copyright holder(s)
- * and author(s) shall not be used in advertising or otherwise to promote
- * the sale, use or other dealings in this Software without prior written
- * authorization from the copyright holder(s) and author(s).
- */
-
-
-/* 
- * This file contains the external interfaces for the XFree86 configuration
- * file parser.
- */
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#ifndef _xf86Parser_h_
-#define _xf86Parser_h_
-
-#include "xf86Optrec.h"
-
-#define HAVE_PARSER_DECLS
-
-typedef struct
-{
-	char *file_logfile;
-	char *file_rgbpath;
-	char *file_modulepath;
-	char *file_inputdevs;
-	char *file_fontpath;
-	char *file_comment;
-}
-XF86ConfFilesRec, *XF86ConfFilesPtr;
-
-/* Values for load_type */
-#define XF86_LOAD_MODULE	0
-#define XF86_LOAD_DRIVER	1
-
-typedef struct
-{
-	GenericListRec list;
-	int load_type;
-	char *load_name;
-	XF86OptionPtr load_opt;
-	char *load_comment;
-        int ignore;
-}
-XF86LoadRec, *XF86LoadPtr;
-
-typedef struct
-{
-	XF86LoadPtr mod_load_lst;
-	char *mod_comment;
-}
-XF86ConfModuleRec, *XF86ConfModulePtr;
-
-#define CONF_IMPLICIT_KEYBOARD	"Implicit Core Keyboard"
-
-#define CONF_IMPLICIT_POINTER	"Implicit Core Pointer"
-
-#define XF86CONF_PHSYNC    0x0001
-#define XF86CONF_NHSYNC    0x0002
-#define XF86CONF_PVSYNC    0x0004
-#define XF86CONF_NVSYNC    0x0008
-#define XF86CONF_INTERLACE 0x0010
-#define XF86CONF_DBLSCAN   0x0020
-#define XF86CONF_CSYNC     0x0040
-#define XF86CONF_PCSYNC    0x0080
-#define XF86CONF_NCSYNC    0x0100
-#define XF86CONF_HSKEW     0x0200	/* hskew provided */
-#define XF86CONF_BCAST     0x0400
-#define XF86CONF_CUSTOM    0x0800	/* timing numbers customized by editor */
-#define XF86CONF_VSCAN     0x1000
-
-typedef struct
-{
-	GenericListRec list;
-	char *ml_identifier;
-	int ml_clock;
-	int ml_hdisplay;
-	int ml_hsyncstart;
-	int ml_hsyncend;
-	int ml_htotal;
-	int ml_vdisplay;
-	int ml_vsyncstart;
-	int ml_vsyncend;
-	int ml_vtotal;
-	int ml_vscan;
-	int ml_flags;
-	int ml_hskew;
-	char *ml_comment;
-}
-XF86ConfModeLineRec, *XF86ConfModeLinePtr;
-
-typedef struct
-{
-	GenericListRec list;
-	char *vp_identifier;
-	XF86OptionPtr vp_option_lst;
-	char *vp_comment;
-}
-XF86ConfVideoPortRec, *XF86ConfVideoPortPtr;
-
-typedef struct
-{
-	GenericListRec list;
-	char *va_identifier;
-	char *va_vendor;
-	char *va_board;
-	char *va_busid;
-	char *va_driver;
-	XF86OptionPtr va_option_lst;
-	XF86ConfVideoPortPtr va_port_lst;
-	char *va_fwdref;
-	char *va_comment;
-}
-XF86ConfVideoAdaptorRec, *XF86ConfVideoAdaptorPtr;
-
-#define CONF_MAX_HSYNC 8
-#define CONF_MAX_VREFRESH 8
-
-typedef struct
-{
-	float hi, lo;
-}
-parser_range;
-
-typedef struct
-{
-	int red, green, blue;
-}
-parser_rgb;
-
-typedef struct
-{
-	GenericListRec list;
-	char *modes_identifier;
-	XF86ConfModeLinePtr mon_modeline_lst;
-	char *modes_comment;
-}
-XF86ConfModesRec, *XF86ConfModesPtr;
-
-typedef struct
-{
-	GenericListRec list;
-	char *ml_modes_str;
-	XF86ConfModesPtr ml_modes;
-}
-XF86ConfModesLinkRec, *XF86ConfModesLinkPtr;
-
-typedef struct
-{
-	GenericListRec list;
-	char *mon_identifier;
-	char *mon_vendor;
-	char *mon_modelname;
-	int mon_width;				/* in mm */
-	int mon_height;				/* in mm */
-	XF86ConfModeLinePtr mon_modeline_lst;
-	int mon_n_hsync;
-	parser_range mon_hsync[CONF_MAX_HSYNC];
-	int mon_n_vrefresh;
-	parser_range mon_vrefresh[CONF_MAX_VREFRESH];
-	float mon_gamma_red;
-	float mon_gamma_green;
-	float mon_gamma_blue;
-	XF86OptionPtr mon_option_lst;
-	XF86ConfModesLinkPtr mon_modes_sect_lst;
-	char *mon_comment;
-}
-XF86ConfMonitorRec, *XF86ConfMonitorPtr;
-
-#define CONF_MAXDACSPEEDS 4
-#define CONF_MAXCLOCKS    128
-
-typedef struct
-{
-	GenericListRec list;
-	char *dev_identifier;
-	char *dev_vendor;
-	char *dev_board;
-	char *dev_chipset;
-	char *dev_busid;
-	char *dev_card;
-	char *dev_driver;
-	char *dev_ramdac;
-	int dev_dacSpeeds[CONF_MAXDACSPEEDS];
-	int dev_videoram;
-	int dev_textclockfreq;
-	unsigned long dev_bios_base;
-	unsigned long dev_mem_base;
-	unsigned long dev_io_base;
-	char *dev_clockchip;
-	int dev_clocks;
-	int dev_clock[CONF_MAXCLOCKS];
-	int dev_chipid;
-	int dev_chiprev;
-	int dev_irq;
-	int dev_screen;
-	XF86OptionPtr dev_option_lst;
-	char *dev_comment;
-}
-XF86ConfDeviceRec, *XF86ConfDevicePtr;
-
-typedef struct
-{
-	GenericListRec list;
-	char *mode_name;
-}
-XF86ModeRec, *XF86ModePtr;
-
-typedef struct
-{
-	GenericListRec list;
-	int disp_frameX0;
-	int disp_frameY0;
-	int disp_virtualX;
-	int disp_virtualY;
-	int disp_depth;
-	int disp_bpp;
-	char *disp_visual;
-	parser_rgb disp_weight;
-	parser_rgb disp_black;
-	parser_rgb disp_white;
-	XF86ModePtr disp_mode_lst;
-	XF86OptionPtr disp_option_lst;
-	char *disp_comment;
-}
-XF86ConfDisplayRec, *XF86ConfDisplayPtr;
-
-typedef struct
-{
-	XF86OptionPtr flg_option_lst;
-	char *flg_comment;
-}
-XF86ConfFlagsRec, *XF86ConfFlagsPtr;
-
-typedef struct
-{
-	GenericListRec list;
-	char *al_adaptor_str;
-	XF86ConfVideoAdaptorPtr al_adaptor;
-}
-XF86ConfAdaptorLinkRec, *XF86ConfAdaptorLinkPtr;
-
-typedef struct
-{
-	GenericListRec list;
-	char *scrn_identifier;
-	char *scrn_obso_driver;
-	int scrn_defaultdepth;
-	int scrn_defaultbpp;
-	int scrn_defaultfbbpp;
-	char *scrn_monitor_str;
-	XF86ConfMonitorPtr scrn_monitor;
-	char *scrn_device_str;
-	XF86ConfDevicePtr scrn_device;
-	XF86ConfAdaptorLinkPtr scrn_adaptor_lst;
-	XF86ConfDisplayPtr scrn_display_lst;
-	XF86OptionPtr scrn_option_lst;
-	char *scrn_comment;
-}
-XF86ConfScreenRec, *XF86ConfScreenPtr;
-
-typedef struct
-{
-	GenericListRec list;
-	char *inp_identifier;
-	char *inp_driver;
-	XF86OptionPtr inp_option_lst;
-	char *inp_comment;
-}
-XF86ConfInputRec, *XF86ConfInputPtr;
-
-typedef struct
-{
-	GenericListRec list;
-	XF86ConfInputPtr iref_inputdev;
-	char *iref_inputdev_str;
-	XF86OptionPtr iref_option_lst;
-}
-XF86ConfInputrefRec, *XF86ConfInputrefPtr;
-
-/* Values for adj_where */
-#define CONF_ADJ_OBSOLETE	-1
-#define CONF_ADJ_ABSOLUTE	0
-#define CONF_ADJ_RIGHTOF	1
-#define CONF_ADJ_LEFTOF		2
-#define CONF_ADJ_ABOVE		3
-#define CONF_ADJ_BELOW		4
-#define CONF_ADJ_RELATIVE	5
-
-typedef struct
-{
-	GenericListRec list;
-	int adj_scrnum;
-	XF86ConfScreenPtr adj_screen;
-	char *adj_screen_str;
-	XF86ConfScreenPtr adj_top;
-	char *adj_top_str;
-	XF86ConfScreenPtr adj_bottom;
-	char *adj_bottom_str;
-	XF86ConfScreenPtr adj_left;
-	char *adj_left_str;
-	XF86ConfScreenPtr adj_right;
-	char *adj_right_str;
-	int adj_where;
-	int adj_x;
-	int adj_y;
-	char *adj_refscreen;
-}
-XF86ConfAdjacencyRec, *XF86ConfAdjacencyPtr;
-
-typedef struct
-{
-	GenericListRec list;
-	char *inactive_device_str;
-	XF86ConfDevicePtr inactive_device;
-}
-XF86ConfInactiveRec, *XF86ConfInactivePtr;
-
-typedef struct
-{
-	GenericListRec list;
-	char *lay_identifier;
-	XF86ConfAdjacencyPtr lay_adjacency_lst;
-	XF86ConfInactivePtr lay_inactive_lst;
-	XF86ConfInputrefPtr lay_input_lst;
-	XF86OptionPtr lay_option_lst;
-	char *lay_comment;
-}
-XF86ConfLayoutRec, *XF86ConfLayoutPtr;
-
-typedef struct 
-{ 
-	GenericListRec list; 
-	char *vs_name;
-	char *vs_identifier;
-	XF86OptionPtr vs_option_lst;
-	char *vs_comment;
-}
-XF86ConfVendSubRec, *XF86ConfVendSubPtr;
-
-typedef struct
-{
-	GenericListRec list;
-	char *vnd_identifier;
-	XF86OptionPtr vnd_option_lst;
-	XF86ConfVendSubPtr vnd_sub_lst;
-	char *vnd_comment;
-}
-XF86ConfVendorRec, *XF86ConfVendorPtr;
-
-typedef struct
-{
-	GenericListRec list;
-	int buf_count;
-	int buf_size;
-	char *buf_flags;
-	char *buf_comment;
-}
-XF86ConfBuffersRec, *XF86ConfBuffersPtr;
-
-typedef struct
-{
-	char *dri_group_name;
-	int dri_group;
-	int dri_mode;
-	XF86ConfBuffersPtr dri_buffers_lst;
-	char *dri_comment;
-}
-XF86ConfDRIRec, *XF86ConfDRIPtr;
-
-typedef struct
-{
-	XF86OptionPtr ext_option_lst;
-	char *extensions_comment;
-}
-XF86ConfExtensionsRec, *XF86ConfExtensionsPtr;
-
-typedef struct
-{
-	XF86ConfFilesPtr conf_files;
-	XF86ConfModulePtr conf_modules;
-	XF86ConfFlagsPtr conf_flags;
-	XF86ConfVideoAdaptorPtr conf_videoadaptor_lst;
-	XF86ConfModesPtr conf_modes_lst;
-	XF86ConfMonitorPtr conf_monitor_lst;
-	XF86ConfDevicePtr conf_device_lst;
-	XF86ConfScreenPtr conf_screen_lst;
-	XF86ConfInputPtr conf_input_lst;
-	XF86ConfLayoutPtr conf_layout_lst;
-	XF86ConfVendorPtr conf_vendor_lst;
-	XF86ConfDRIPtr conf_dri;
-	XF86ConfExtensionsPtr conf_extensions;
-	char *conf_comment;
-}
-XF86ConfigRec, *XF86ConfigPtr;
-
-typedef struct
-{
-	int token;			/* id of the token */
-	char *name;			/* pointer to the LOWERCASED name */
-}
-xf86ConfigSymTabRec, *xf86ConfigSymTabPtr;
-
-/*
- * prototypes for public functions
- */
-extern const char *xf86openConfigFile (const char *, const char *,
-					const char *);
-extern void xf86setBuiltinConfig(const char *config[]);
-extern XF86ConfigPtr xf86readConfigFile (void);
-extern void xf86closeConfigFile (void);
-extern void xf86freeConfig (XF86ConfigPtr p);
-extern int xf86writeConfigFile (const char *, XF86ConfigPtr);
-XF86ConfDevicePtr xf86findDevice(const char *ident, XF86ConfDevicePtr p);
-XF86ConfLayoutPtr xf86findLayout(const char *name, XF86ConfLayoutPtr list);
-XF86ConfMonitorPtr xf86findMonitor(const char *ident, XF86ConfMonitorPtr p);
-XF86ConfModesPtr xf86findModes(const char *ident, XF86ConfModesPtr p);
-XF86ConfModeLinePtr xf86findModeLine(const char *ident, XF86ConfModeLinePtr p);
-XF86ConfScreenPtr xf86findScreen(const char *ident, XF86ConfScreenPtr p);
-XF86ConfInputPtr xf86findInput(const char *ident, XF86ConfInputPtr p);
-XF86ConfInputPtr xf86findInputByDriver(const char *driver, XF86ConfInputPtr p);
-XF86ConfVendorPtr xf86findVendor(const char *name, XF86ConfVendorPtr list);
-XF86ConfVideoAdaptorPtr xf86findVideoAdaptor(const char *ident,
-						XF86ConfVideoAdaptorPtr p);
-
-GenericListPtr xf86addListItem(GenericListPtr head, GenericListPtr c_new);
-int xf86itemNotSublist(GenericListPtr list_1, GenericListPtr list_2);
-
-int xf86pathIsAbsolute(const char *path);
-int xf86pathIsSafe(const char *path);
-char *xf86addComment(char *cur, char *add);
-
-#endif /* _xf86Parser_h_ */
diff-tree 681966ce6548c6f47b087eb7e369674b7ddbaade (from 3bce8bf0e95e5842399959a5d6f6413e96f03adb)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Feb 22 11:45:43 2007 -0800

    Disable unused functions after configuring the remaining resources.
    
    This eliminates an unsightly flash of the hardware cursor during X server
    startup.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index e46c057..bb80336 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3049,8 +3049,6 @@ I830EnterVT(int scrnIndex, int flags)
    ResetState(pScrn, FALSE);
    SetHWOperatingState(pScrn);
 
-   xf86DisableUnusedFunctions(pScrn);
-
    for (i = 0; i < xf86_config->num_crtc; i++)
    {
       xf86CrtcPtr	crtc = xf86_config->crtc[i];
@@ -3070,6 +3068,8 @@ I830EnterVT(int scrnIndex, int flags)
 	 return FALSE;
    }
 
+   xf86DisableUnusedFunctions(pScrn);
+
    i830DumpRegs (pScrn);
    i830DescribeOutputConfiguration(pScrn);
 
diff-tree 3bce8bf0e95e5842399959a5d6f6413e96f03adb (from 5a1a04649c62aa4b1c0617560b813642ce0c67b5)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Tue Feb 20 23:10:17 2007 -0800

    Pre-965 hardware had fixed pipe 1 for panel fitter.
    
    The pipe mode setting code needs to disable the panel fitter when using the
    pipe for things other than LVDS output. The driver was checking for panel
    fitter conflicts using bits that the 965 chipset defines for selecting which
    pipe the panel fitter is connected to. However, on pre-965 hardware, the
    panel fitter works only with pipe 1 and those bits returned 0.
    
    The result was that when pipe 1 was using the panel fitter, configuring pipe
    0 would disable the panel fitter.
    
    The fix provided uses a model-specific test for the panel fitter pipe.

diff --git a/src/i830_display.c b/src/i830_display.c
index e7a5605..2e84705 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -644,6 +644,33 @@ i830_get_core_clock_speed(ScrnInfoPtr pS
 }
 
 /**
+ * Return the pipe currently connected to the panel fitter,
+ * or -1 if the panel fitter is not present or not in use
+ */
+static int
+i830_panel_fitter_pipe (I830Ptr	pI830)
+{
+    CARD32  pfit_control;
+    
+    /* i830 doesn't have a panel fitter */
+    if (IS_I830(pI830))
+	return -1;
+    
+    pfit_control = INREG(PFIT_CONTROL);
+    
+    /* See if the panel fitter is in use */
+    if ((pfit_control & PFIT_ENABLE) == 0)
+	return -1;
+    
+    /* 965 can place panel fitter on either pipe */
+    if (IS_I965G(pI830))
+	return (pfit_control >> 29) & 0x3;
+
+    /* older chips can only use pipe 1 */
+    return 1;
+}
+
+/**
  * Sets up registers for the given mode/adjusted_mode pair.
  *
  * The clocks, CRTCs and outputs attached to this CRTC must be off.
@@ -830,7 +857,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
     }
     
     /* Disable the panel fitter if it was on our pipe */
-    if (!IS_I830(pI830) && ((INREG(PFIT_CONTROL) >> 29) & 0x3) == pipe)
+    if (i830_panel_fitter_pipe (pI830) == pipe)
 	OUTREG(PFIT_CONTROL, 0);
 
     i830PrintPll("chosen", &clock);
diff-tree 5a1a04649c62aa4b1c0617560b813642ce0c67b5 (from 0ca926e63c7fa9122a8cba1424ce4cdee1c7b215)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Sat Feb 17 17:01:04 2007 -0800

    Make distcheck fixes. Distribute all sources needed even for older servers.
    
    Always allow (but do not require) link to server sources so that needed
    files can be included in the generated tar files.
    
    Add remaining .g4a files and assembly output to distributed file lists.

diff --git a/configure.ac b/configure.ac
index 8a81859..395e9d4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -22,7 +22,7 @@
 
 AC_PREREQ(2.57)
 AC_INIT([xf86-video-intel],
-        1.7.2,
+        1.9.90,
         [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
         xf86-video-intel)
 
@@ -120,6 +120,12 @@ CFLAGS="$save_CFLAGS"
 
 AM_CONDITIONAL(XMODES, test "x$XMODES" = xno)
 
+if test "x$XSERVER_SOURCE" = x; then
+	if test -d ../../xserver; then
+		XSERVER_SOURCE="`cd ../../xserver && pwd`"
+	fi
+fi
+	
 if test "x$XMODES" = xyes; then
 	echo built-in mode code
 	AC_DEFINE(XMODES, 1,[X server has built-in mode code])
@@ -127,12 +133,6 @@ if test "x$XMODES" = xyes; then
 else
 	echo symlink mode code
 	if test "x$XSERVER_SOURCE" = x; then
-		if test -d ../../xserver; then
-			XSERVER_SOURCE="`cd ../../xserver && pwd`"
-		fi
-	fi
-	
-	if test "x$XSERVER_SOURCE" = x; then
 		AC_MSG_ERROR([Must have X server >= 1.3 source tree for mode setting code. Please specify --with-xserver-source])
 	fi
 	XMODES_CFLAGS='-DXF86_MODES_RENAME -I$(top_srcdir)/src/modes -I$(top_srcdir)/src/parser'
diff --git a/src/Makefile.am b/src/Makefile.am
index 1e0505f..adb4c42 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -33,10 +33,8 @@ intel_drv_la_LTLIBRARIES = intel_drv.la
 intel_drv_la_LDFLAGS = -module -avoid-version
 intel_drv_ladir = @moduledir@/drivers
 
-if XMODES
 XMODE_SRCS=\
 	 local_xf86Rename.h \
-	 parser/xf86Rename.h \
 	 parser/xf86Parser.h \
 	 parser/xf86Optrec.h \
 	 modes/xf86Modes.h \
@@ -47,9 +45,16 @@ XMODE_SRCS=\
          modes/xf86EdidModes.c \
 	 modes/xf86RandR12.c \
 	 modes/xf86RandR12.h \
+	 modes/xf86Rename.h \
 	 modes/xf86Rotate.c \
 	 modes/xf86DiDGA.c
-endif
+	 
+INTEL_DRI_SRCS = \
+         i810_dri.c \
+         i810_dri.h \
+         i830_dri.c \
+         i810_hwmc.c \
+         i830_dri.h 
 
 intel_drv_la_SOURCES = \
          brw_defines.h \
@@ -104,43 +109,70 @@ intel_drv_la_SOURCES = \
 	 i830_xaa.c \
 	 i830_render.c \
 	 i915_render.c \
-	 i965_render.c \
-	 $(XMODE_SRCS)
-
-EXTRA_DIST = \
-	packed_yuv_sf.g4a \
-	packed_yuv_wm.g4a
+	 i965_render.c
 
+INTEL_G4A =				\
+	packed_yuv_sf.g4a		\
+	packed_yuv_wm.g4a		\
+	exa_sf.g4a 			\
+	exa_sf_mask.g4a 		\
+	exa_wm_maskca.g4a 		\
+	exa_wm_maskca_srcalpha.g4a 	\
+	exa_wm_masknoca.g4a 		\
+	exa_wm_nomask.g4a
+
+INTEL_G4H = 				\
+	sf_prog.h			\
+	wm_prog.h 			\
+	exa_sf_mask_prog.h		\
+	exa_sf_prog.h 			\
+	exa_wm_maskca_prog.h		\
+	exa_wm_maskca_srcalpha_prog.h	\
+	exa_wm_masknoca_prog.h		\
+	exa_wm_nomask_prog.h
+
+EXTRA_DIST = 		\
+	$(XMODE_SRCS)	\
+	$(INTEL_G4A)	\
+	$(INTEL_G4H)	\
+	$(INTEL_DRI_SRCS)
+	
 if HAVE_GEN4ASM
+
 sf_prog.h: packed_yuv_sf.g4a
 	intel-gen4asm -o sf_prog.h packed_yuv_sf.g4a
+	
 wm_prog.h: packed_yuv_wm.g4a
 	intel-gen4asm -o wm_prog.h packed_yuv_wm.g4a
-exa_sf_prog.h: exa_sf.g4a
-	intel-gen4asm -o exa_sf_prog.h exa_sf.g4a
+	
 exa_sf_mask_prog.h: exa_sf_mask.g4a
 	intel-gen4asm -o exa_sf_mask_prog.h exa_sf_mask.g4a
-exa_wm_nomask_prog.h: exa_wm_nomask.g4a
-	intel-gen4asm -o exa_wm_nomask_prog.h exa_wm_nomask.g4a
+	
+exa_sf_prog.h: exa_sf.g4a
+	intel-gen4asm -o exa_sf_prog.h exa_sf.g4a
+	
+exa_wm_maskca_prog.h: exa_wm_maskca.g4a
+	intel-gen4asm -o exa_wm_maskca_prog.h exa_wm_maskca.g4a
+
+exa_wm_maskca_srcalpha_prog.h: exa_wm_maskca_srcalpha.g4a
+	intel-gen4asm -o exa_wm_maskca_srcalpha_prog.h exa_wm_maskca_srcalpha.g4a
+
 exa_wm_masknoca_prog.h: exa_wm_masknoca.g4a
 	intel-gen4asm -o exa_wm_masknoca_prog.h exa_wm_masknoca.g4a
-else
-EXTRA_DIST += \
-	sf_prog.h		\
-	wm_prog.h 		\
-	exa_sf_prog.h 		\
-	exa_sf_mask_prog.h	\
-	exa_wm_nomask_prog.h 	\
-	exa_wm_masknoca_prog.h
+	
+exa_wm_nomask_prog.h: exa_wm_nomask.g4a
+	intel-gen4asm -o exa_wm_nomask_prog.h exa_wm_nomask.g4a
+	
+endif
+
+if XMODES
+intel_drv_la_SOURCES += \
+	$(XMODE_SRCS)
 endif
 
 if DRI
 intel_drv_la_SOURCES += \
-         i810_dri.c \
-         i810_dri.h \
-         i830_dri.c \
-         i810_hwmc.c \
-         i830_dri.h 
+	$(INTEL_DRI_SRCS)
 endif
 
 install-data-local: install-intel_drv_laLTLIBRARIES
@@ -148,4 +180,3 @@ install-data-local: install-intel_drv_la
 
 uninstall-local:
 	(cd $(DESTDIR)$(intel_drv_ladir) && rm -f i810_drv.so)
-	
diff-tree 0ca926e63c7fa9122a8cba1424ce4cdee1c7b215 (from 972f1109d23c0a3f821fa573e2aa40cd17ce2795)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Fri Feb 16 02:19:10 2007 -0800

    Check for presence of xf86Modes.h file.
    
    xf86Modes.h file signals the availability of the new modes API in the
    server; use that instead of counting on X server version numbers.
    Also, finish eliminating use of local copies of those header files.

diff --git a/configure.ac b/configure.ac
index e0d828e..8a81859 100644
--- a/configure.ac
+++ b/configure.ac
@@ -76,37 +76,6 @@ AC_ARG_WITH(xserver-source,AC_HELP_STRIN
 			   [ XSERVER_SOURCE="" ])
 
 
-PKG_CHECK_MODULES(XORG_XSERVER, xorg-server >= 1.2.99, [XMODES=yes], [XMODES=no])
-
-AM_CONDITIONAL(XMODES, [test "x$XMODES" = xyes])
-
-if test "x$XMODES" = xyes; then
-	AC_DEFINE(XMODES, 1,[X server as built-in mode code])
-else
-	if test "x$XSERVER_SOURCE" = x; then
-		if test -d ../../xserver; then
-			XSERVER_SOURCE="`cd ../../xserver && pwd`"
-		fi
-	fi
-	
-	if test "x$XSERVER_SOURCE" = x; then
-		AC_MSG_ERROR([Must have X server >= 1.3 source tree for mode setting code. Please specify --with-xserver-source])
-	fi
-	
-	if test -f src/modes/xf86Crtc.h; then
-		:
-	else
-		ln -s $XSERVER_SOURCE/hw/xfree86/modes src/modes
-	fi
-	
-	if test -f src/parser/xf86Parser.h; then
-		:
-	else
-		ln -s $XSERVER_SOURCE/hw/xfree86/parser src/parser
-	fi
-
-fi
-
 # Checks for extensions
 XORG_DRIVER_CHECK_EXT(XINERAMA, xineramaproto)
 XORG_DRIVER_CHECK_EXT(RANDR, randrproto)
@@ -144,6 +113,46 @@ if test x$DRI = xauto; then
 fi
 AC_MSG_RESULT([$DRI])
 
+save_CFLAGS="$CFLAGS"
+CFLAGS="$XORG_CFLAGS"
+AC_CHECK_HEADER(xf86Modes.h,[XMODES=yes],[XMODES=no],[#include "xorg-server.h"])
+CFLAGS="$save_CFLAGS"
+
+AM_CONDITIONAL(XMODES, test "x$XMODES" = xno)
+
+if test "x$XMODES" = xyes; then
+	echo built-in mode code
+	AC_DEFINE(XMODES, 1,[X server has built-in mode code])
+	XMODES_CFLAGS=
+else
+	echo symlink mode code
+	if test "x$XSERVER_SOURCE" = x; then
+		if test -d ../../xserver; then
+			XSERVER_SOURCE="`cd ../../xserver && pwd`"
+		fi
+	fi
+	
+	if test "x$XSERVER_SOURCE" = x; then
+		AC_MSG_ERROR([Must have X server >= 1.3 source tree for mode setting code. Please specify --with-xserver-source])
+	fi
+	XMODES_CFLAGS='-DXF86_MODES_RENAME -I$(top_srcdir)/src/modes -I$(top_srcdir)/src/parser'
+fi
+
+if test -d "$XSERVER_SOURCE"; then
+	if test -f src/modes/xf86Modes.h; then
+		:
+	else
+		ln -s $XSERVER_SOURCE/hw/xfree86/modes src/modes
+	fi
+	
+	if test -f src/parser/xf86Parser.h; then
+		:
+	else
+		ln -s $XSERVER_SOURCE/hw/xfree86/parser src/parser
+	fi
+fi
+AC_SUBST([XMODES_CFLAGS])
+
 dnl Use lots of warning flags with GCC
 
 WARN_CFLAGS=""
diff --git a/src/Makefile.am b/src/Makefile.am
index f656270..1e0505f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -25,13 +25,32 @@ SUBDIRS = xvmc bios_reader ch7017 ch7xxx
 # -avoid-version prevents gratuitous .0.0.0 version numbers on the end
 # _ladir passes a dummy rpath to libtool so the thing will actually link
 # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
-AM_CFLAGS = @WARN_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@ -Iparser -Imodes \
-	-DI830_XV -DI830_USE_XAA -DI830_USE_EXA -DXF86_MODES_RENAME
+
+AM_CFLAGS = @WARN_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@ @XMODES_CFLAGS@ \
+	-DI830_XV -DI830_USE_XAA -DI830_USE_EXA
 
 intel_drv_la_LTLIBRARIES = intel_drv.la
 intel_drv_la_LDFLAGS = -module -avoid-version
 intel_drv_ladir = @moduledir@/drivers
 
+if XMODES
+XMODE_SRCS=\
+	 local_xf86Rename.h \
+	 parser/xf86Rename.h \
+	 parser/xf86Parser.h \
+	 parser/xf86Optrec.h \
+	 modes/xf86Modes.h \
+	 modes/xf86Modes.c \
+	 modes/xf86cvt.c \
+	 modes/xf86Crtc.h \
+	 modes/xf86Crtc.c \
+         modes/xf86EdidModes.c \
+	 modes/xf86RandR12.c \
+	 modes/xf86RandR12.h \
+	 modes/xf86Rotate.c \
+	 modes/xf86DiDGA.c
+endif
+
 intel_drv_la_SOURCES = \
          brw_defines.h \
          brw_structs.h \
@@ -86,20 +105,7 @@ intel_drv_la_SOURCES = \
 	 i830_render.c \
 	 i915_render.c \
 	 i965_render.c \
-	 local_xf86Rename.h \
-	 parser/xf86Rename.h \
-	 parser/xf86Parser.h \
-	 parser/xf86Optrec.h \
-	 modes/xf86Modes.h \
-	 modes/xf86Modes.c \
-	 modes/xf86cvt.c \
-	 modes/xf86Crtc.h \
-	 modes/xf86Crtc.c \
-         modes/xf86EdidModes.c \
-	 modes/xf86RandR12.c \
-	 modes/xf86RandR12.h \
-	 modes/xf86Rotate.c \
-	 modes/xf86DiDGA.c
+	 $(XMODE_SRCS)
 
 EXTRA_DIST = \
 	packed_yuv_sf.g4a \
diff --git a/src/bios_reader/Makefile.am b/src/bios_reader/Makefile.am
index f18a00c..a5c81a6 100644
--- a/src/bios_reader/Makefile.am
+++ b/src/bios_reader/Makefile.am
@@ -1,4 +1,4 @@
-AM_CFLAGS = @XORG_CFLAGS@
+AM_CFLAGS = @XORG_CFLAGS@ @XMODES_CFLAGS@
 
 noinst_PROGRAMS = bios_reader
 
diff --git a/src/ch7017/Makefile.am b/src/ch7017/Makefile.am
index 9cf2fa4..7fbb440 100644
--- a/src/ch7017/Makefile.am
+++ b/src/ch7017/Makefile.am
@@ -3,7 +3,7 @@
 # -avoid-version prevents gratuitous .0.0.0 version numbers on the end
 # _ladir passes a dummy rpath to libtool so the thing will actually link
 # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
-AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@
+AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ -I$(srcdir)/.. -I$(srcdir)/../modes
 
 ch7017_la_LTLIBRARIES = ch7017.la
 ch7017_la_LDFLAGS = -module -avoid-version
diff --git a/src/ch7017/ch7017.c b/src/ch7017/ch7017.c
index 28bce0d..019dcea 100644
--- a/src/ch7017/ch7017.c
+++ b/src/ch7017/ch7017.c
@@ -37,7 +37,7 @@
 #include "compiler.h"
 #include "miscstruct.h"
 #include "xf86i2c.h"
-#include "../i830_xf86Crtc.h"
+#include "xf86Crtc.h"
 #define DPMS_SERVER
 #include <X11/extensions/dpms.h>
 
diff --git a/src/ch7xxx/Makefile.am b/src/ch7xxx/Makefile.am
index 7f3b1e1..b827bf8 100644
--- a/src/ch7xxx/Makefile.am
+++ b/src/ch7xxx/Makefile.am
@@ -3,7 +3,7 @@
 # -avoid-version prevents gratuitous .0.0.0 version numbers on the end
 # _ladir passes a dummy rpath to libtool so the thing will actually link
 # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
-AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ -I$(srcdir)/../
+AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ -I$(srcdir)/.. -I$(srcdir)/../modes
 
 ch7xxx_la_LTLIBRARIES = ch7xxx.la
 ch7xxx_la_LDFLAGS = -module -avoid-version
diff --git a/src/ch7xxx/ch7xxx.c b/src/ch7xxx/ch7xxx.c
index 161aebf..9ce581f 100644
--- a/src/ch7xxx/ch7xxx.c
+++ b/src/ch7xxx/ch7xxx.c
@@ -37,7 +37,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "compiler.h"
 #include "miscstruct.h"
 #include "xf86i2c.h"
-#include "i830_xf86Crtc.h"
+#include "xf86Crtc.h"
 #define DPMS_SERVER
 #include <X11/extensions/dpms.h>
 
diff --git a/src/ivch/Makefile.am b/src/ivch/Makefile.am
index fac074d..40e2627 100644
--- a/src/ivch/Makefile.am
+++ b/src/ivch/Makefile.am
@@ -3,7 +3,7 @@
 # -avoid-version prevents gratuitous .0.0.0 version numbers on the end
 # _ladir passes a dummy rpath to libtool so the thing will actually link
 # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
-AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@
+AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ -I$(srcdir)/.. -I$(srcdir)/../modes
 
 ivch_la_LTLIBRARIES = ivch.la
 ivch_la_LDFLAGS = -module -avoid-version
diff --git a/src/ivch/ivch.c b/src/ivch/ivch.c
index 085b542..71f41f5 100644
--- a/src/ivch/ivch.c
+++ b/src/ivch/ivch.c
@@ -35,7 +35,7 @@
 #include "compiler.h"
 #include "miscstruct.h"
 #include "xf86i2c.h"
-#include "../i830_xf86Crtc.h"
+#include "xf86Crtc.h"
 #define DPMS_SERVER
 #include <X11/extensions/dpms.h>
 
diff --git a/src/sil164/Makefile.am b/src/sil164/Makefile.am
index 927f5a7..4cf717c 100644
--- a/src/sil164/Makefile.am
+++ b/src/sil164/Makefile.am
@@ -3,7 +3,7 @@
 # -avoid-version prevents gratuitous .0.0.0 version numbers on the end
 # _ladir passes a dummy rpath to libtool so the thing will actually link
 # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
-AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ -I$(srcdir)/../
+AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ -I$(srcdir)/.. -I$(srcdir)/../modes
 
 sil164_la_LTLIBRARIES = sil164.la
 sil164_la_LDFLAGS = -module -avoid-version
diff --git a/src/sil164/sil164.c b/src/sil164/sil164.c
index 453ed04..80b1b6a 100644
--- a/src/sil164/sil164.c
+++ b/src/sil164/sil164.c
@@ -37,7 +37,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "compiler.h"
 #include "miscstruct.h"
 #include "xf86i2c.h"
-#include "i830_xf86Crtc.h"
+#include "xf86Crtc.h"
 #define DPMS_SERVER
 #include <X11/extensions/dpms.h>
 
diff-tree 972f1109d23c0a3f821fa573e2aa40cd17ce2795 (from 20e146a09e3b4907a6800588ebfa787bfc5b0d89)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Fri Feb 16 01:07:20 2007 -0800

    Remove common code that has moved to xserver/hw/xfree86/modes

diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
deleted file mode 100644
index db05aba..0000000
--- a/src/i830_xf86Crtc.c
+++ /dev/null
@@ -1,1588 +0,0 @@
-/*
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stddef.h>
-#include <string.h>
-#include <stdio.h>
-
-#include "xf86.h"
-#include "xf86DDC.h"
-/*#include "i830.h" */
-#include "i830_xf86Crtc.h"
-#include "i830_xf86Modes.h"
-#include "i830_xf86RandR12.h"
-#include "X11/extensions/render.h"
-#define DPMS_SERVER
-#include "X11/extensions/dpms.h"
-#include "X11/Xatom.h"
-
-/*
- * Initialize xf86CrtcConfig structure
- */
-
-int xf86CrtcConfigPrivateIndex = -1;
-
-void
-xf86CrtcConfigInit (ScrnInfoPtr scrn)
-{
-    xf86CrtcConfigPtr	config;
-    
-    if (xf86CrtcConfigPrivateIndex == -1)
-	xf86CrtcConfigPrivateIndex = xf86AllocateScrnInfoPrivateIndex();
-    config = xnfcalloc (1, sizeof (xf86CrtcConfigRec));
-    scrn->privates[xf86CrtcConfigPrivateIndex].ptr = config;
-}
- 
-void
-xf86CrtcSetSizeRange (ScrnInfoPtr scrn,
-		      int minWidth, int minHeight,
-		      int maxWidth, int maxHeight)
-{
-    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
-
-    config->minWidth = minWidth;
-    config->minHeight = minHeight;
-    config->maxWidth = maxWidth;
-    config->maxHeight = maxHeight;
-}
-
-/*
- * Crtc functions
- */
-xf86CrtcPtr
-xf86CrtcCreate (ScrnInfoPtr		scrn,
-		const xf86CrtcFuncsRec	*funcs)
-{
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
-    xf86CrtcPtr		crtc, *crtcs;
-
-    crtc = xcalloc (sizeof (xf86CrtcRec), 1);
-    if (!crtc)
-	return NULL;
-    crtc->scrn = scrn;
-    crtc->funcs = funcs;
-#ifdef RANDR_12_INTERFACE
-    crtc->randr_crtc = NULL;
-#endif
-    crtc->rotation = RR_Rotate_0;
-    crtc->desiredRotation = RR_Rotate_0;
-    if (xf86_config->crtc)
-	crtcs = xrealloc (xf86_config->crtc,
-			  (xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr));
-    else
-	crtcs = xalloc ((xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr));
-    if (!crtcs)
-    {
-	xfree (crtc);
-	return NULL;
-    }
-    xf86_config->crtc = crtcs;
-    xf86_config->crtc[xf86_config->num_crtc++] = crtc;
-    return crtc;
-}
-
-void
-xf86CrtcDestroy (xf86CrtcPtr crtc)
-{
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
-    int			c;
-    
-    (*crtc->funcs->destroy) (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);
-}
-
-
-/**
- * Return whether any outputs are connected to the specified pipe
- */
-
-Bool
-xf86CrtcInUse (xf86CrtcPtr crtc)
-{
-    ScrnInfoPtr		pScrn = crtc->scrn;
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-    int			o;
-    
-    for (o = 0; o < xf86_config->num_output; o++)
-	if (xf86_config->output[o]->crtc == crtc)
-	    return TRUE;
-    return FALSE;
-}
-
-/**
- * Sets the given video mode on the given crtc
- */
-Bool
-xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
-		 int x, int y)
-{
-    ScrnInfoPtr		scrn = crtc->scrn;
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
-    int			i;
-    Bool		ret = FALSE;
-    Bool		didLock = FALSE;
-    DisplayModePtr	adjusted_mode;
-    DisplayModeRec	saved_mode;
-    int			saved_x, saved_y;
-    Rotation		saved_rotation;
-
-    adjusted_mode = xf86DuplicateMode(mode);
-
-    crtc->enabled = xf86CrtcInUse (crtc);
-    
-    if (!crtc->enabled)
-    {
-	/* XXX disable crtc? */
-	return TRUE;
-    }
-
-    didLock = crtc->funcs->lock (crtc);
-
-    saved_mode = crtc->mode;
-    saved_x = crtc->x;
-    saved_y = crtc->y;
-    saved_rotation = crtc->rotation;
-    /* Update crtc values up front so the driver can rely on them for mode
-     * setting.
-     */
-    crtc->mode = *mode;
-    crtc->x = x;
-    crtc->y = y;
-    crtc->rotation = rotation;
-
-    /* XXX short-circuit changes to base location only */
-    
-    /* Pass our mode to the outputs and the CRTC to give them a chance to
-     * adjust it according to limitations or output properties, and also
-     * a chance to reject the mode entirely.
-     */
-    for (i = 0; i < xf86_config->num_output; i++) {
-	xf86OutputPtr output = xf86_config->output[i];
-
-	if (output->crtc != crtc)
-	    continue;
-
-	if (!output->funcs->mode_fixup(output, mode, adjusted_mode)) {
-	    goto done;
-	}
-    }
-
-    if (!crtc->funcs->mode_fixup(crtc, mode, adjusted_mode)) {
-	goto done;
-    }
-
-    if (!xf86CrtcRotate (crtc, mode, rotation)) {
-	goto done;
-    }
-
-    /* Disable the outputs and CRTCs before setting the mode. */
-    for (i = 0; i < xf86_config->num_output; i++) {
-	xf86OutputPtr output = xf86_config->output[i];
-
-	if (output->crtc != crtc)
-	    continue;
-
-	/* Disable the output as the first thing we do. */
-	output->funcs->dpms(output, DPMSModeOff);
-    }
-
-    crtc->funcs->dpms(crtc, DPMSModeOff);
-
-    /* Set up the DPLL and any output state that needs to adjust or depend
-     * on the DPLL.
-     */
-    crtc->funcs->mode_set(crtc, mode, adjusted_mode, x, y);
-    for (i = 0; i < xf86_config->num_output; i++) 
-    {
-	xf86OutputPtr output = xf86_config->output[i];
-	if (output->crtc == crtc)
-	    output->funcs->mode_set(output, mode, adjusted_mode);
-    }
-
-    /* Now, enable the clocks, plane, pipe, and outputs that we set up. */
-    crtc->funcs->dpms(crtc, DPMSModeOn);
-    for (i = 0; i < xf86_config->num_output; i++) 
-    {
-	xf86OutputPtr output = xf86_config->output[i];
-	if (output->crtc == crtc)
-	    output->funcs->dpms(output, DPMSModeOn);
-    }
-
-    /* XXX free adjustedmode */
-    ret = TRUE;
-done:
-    if (!ret) {
-	crtc->x = saved_x;
-	crtc->y = saved_y;
-	crtc->rotation = saved_rotation;
-	crtc->mode = saved_mode;
-    }
-
-    if (didLock)
-	crtc->funcs->unlock (crtc);
-
-    return ret;
-}
-
-/*
- * Output functions
- */
-
-extern XF86ConfigPtr xf86configptr;
-
-typedef enum {
-    OPTION_PREFERRED_MODE,
-    OPTION_POSITION,
-    OPTION_BELOW,
-    OPTION_RIGHT_OF,
-    OPTION_ABOVE,
-    OPTION_LEFT_OF,
-    OPTION_ENABLE,
-    OPTION_DISABLE,
-    OPTION_MIN_CLOCK,
-    OPTION_MAX_CLOCK,
-    OPTION_IGNORE,
-} OutputOpts;
-
-static OptionInfoRec xf86OutputOptions[] = {
-    {OPTION_PREFERRED_MODE, "PreferredMode",	OPTV_STRING,  {0}, FALSE },
-    {OPTION_POSITION,	    "Position",		OPTV_STRING,  {0}, FALSE },
-    {OPTION_BELOW,	    "Below",		OPTV_STRING,  {0}, FALSE },
-    {OPTION_RIGHT_OF,	    "RightOf",		OPTV_STRING,  {0}, FALSE },
-    {OPTION_ABOVE,	    "Above",		OPTV_STRING,  {0}, FALSE },
-    {OPTION_LEFT_OF,	    "LeftOf",		OPTV_STRING,  {0}, FALSE },
-    {OPTION_ENABLE,	    "Enable",		OPTV_BOOLEAN, {0}, FALSE },
-    {OPTION_DISABLE,	    "Disable",		OPTV_BOOLEAN, {0}, FALSE },
-    {OPTION_MIN_CLOCK,	    "MinClock",		OPTV_FREQ,    {0}, FALSE },
-    {OPTION_MAX_CLOCK,	    "MaxClock",		OPTV_FREQ,    {0}, FALSE },
-    {OPTION_IGNORE,	    "Ignore",		OPTV_BOOLEAN, {0}, FALSE },
-    {-1,		    NULL,		OPTV_NONE,    {0}, FALSE },
-};
-
-static void
-xf86OutputSetMonitor (xf86OutputPtr output)
-{
-    char    *option_name;
-    static const char monitor_prefix[] = "monitor-";
-    char    *monitor;
-
-    if (!output->name)
-	return;
-
-    if (output->options)
-	xfree (output->options);
-
-    output->options = xnfalloc (sizeof (xf86OutputOptions));
-    memcpy (output->options, xf86OutputOptions, sizeof (xf86OutputOptions));
-    
-    option_name = xnfalloc (strlen (monitor_prefix) +
-			    strlen (output->name) + 1);
-    strcpy (option_name, monitor_prefix);
-    strcat (option_name, output->name);
-    monitor = xf86findOptionValue (output->scrn->options, option_name);
-    if (!monitor)
-	monitor = output->name;
-    else
-	xf86MarkOptionUsedByName (output->scrn->options, option_name);
-    xfree (option_name);
-    output->conf_monitor = xf86findMonitor (monitor,
-					    xf86configptr->conf_monitor_lst);
-    if (output->conf_monitor)
-	xf86ProcessOptions (output->scrn->scrnIndex,
-			    output->conf_monitor->mon_option_lst,
-			    output->options);
-}
-
-static Bool
-xf86OutputEnabled (xf86OutputPtr    output)
-{
-    /* Check to see if this output was disabled in the config file */
-    if (xf86ReturnOptValBool (output->options, OPTION_ENABLE, TRUE) == FALSE ||
-	xf86ReturnOptValBool (output->options, OPTION_DISABLE, FALSE) == TRUE)
-    {
-	return FALSE;
-    }
-    return TRUE;
-}
-
-static Bool
-xf86OutputIgnored (xf86OutputPtr    output)
-{
-    return xf86ReturnOptValBool (output->options, OPTION_IGNORE, FALSE);
-}
-
-xf86OutputPtr
-xf86OutputCreate (ScrnInfoPtr		    scrn,
-		  const xf86OutputFuncsRec *funcs,
-		  const char		    *name)
-{
-    xf86OutputPtr	output, *outputs;
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
-    int			len;
-
-    if (name)
-	len = strlen (name) + 1;
-    else
-	len = 0;
-
-    output = xcalloc (sizeof (xf86OutputRec) + len, 1);
-    if (!output)
-	return NULL;
-    output->scrn = scrn;
-    output->funcs = funcs;
-    if (name)
-    {
-	output->name = (char *) (output + 1);
-	strcpy (output->name, name);
-    }
-    output->subpixel_order = SubPixelUnknown;
-#ifdef RANDR_12_INTERFACE
-    output->randr_output = NULL;
-#endif
-    if (name)
-    {
-	xf86OutputSetMonitor (output);
-	if (xf86OutputIgnored (output))
-	{
-	    xfree (output);
-	    return FALSE;
-	}
-    }
-    
-    
-    if (xf86_config->output)
-	outputs = xrealloc (xf86_config->output,
-			  (xf86_config->num_output + 1) * sizeof (xf86OutputPtr));
-    else
-	outputs = xalloc ((xf86_config->num_output + 1) * sizeof (xf86OutputPtr));
-    if (!outputs)
-    {
-	xfree (output);
-	return NULL;
-    }
-    
-    xf86_config->output = outputs;
-    xf86_config->output[xf86_config->num_output++] = output;
-    
-    return output;
-}
-
-Bool
-xf86OutputRename (xf86OutputPtr output, const char *name)
-{
-    int	    len = strlen(name) + 1;
-    char    *newname = xalloc (len);
-    
-    if (!newname)
-	return FALSE;	/* so sorry... */
-    
-    strcpy (newname, name);
-    if (output->name && output->name != (char *) (output + 1))
-	xfree (output->name);
-    output->name = newname;
-    xf86OutputSetMonitor (output);
-    if (xf86OutputIgnored (output))
-	return FALSE;
-    return TRUE;
-}
-
-void
-xf86OutputDestroy (xf86OutputPtr output)
-{
-    ScrnInfoPtr		scrn = output->scrn;
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
-    int			o;
-    
-    (*output->funcs->destroy) (output);
-    while (output->probed_modes)
-	xf86DeleteMode (&output->probed_modes, output->probed_modes);
-    for (o = 0; o < xf86_config->num_output; o++)
-	if (xf86_config->output[o] == output)
-	{
-	    memmove (&xf86_config->output[o],
-		     &xf86_config->output[o+1],
-		     xf86_config->num_output - (o + 1));
-	    xf86_config->num_output--;
-	    break;
-	}
-    if (output->name && output->name != (char *) (output + 1))
-	xfree (output->name);
-    xfree (output);
-}
-
-static DisplayModePtr
-xf86DefaultMode (xf86OutputPtr output, int width, int height)
-{
-    DisplayModePtr  target_mode = NULL;
-    DisplayModePtr  mode;
-    int		    target_diff = 0;
-    int		    target_preferred = 0;
-    int		    mm_height;
-    
-    mm_height = output->mm_height;
-    if (!mm_height)
-	mm_height = 203;	/* 768 pixels at 96dpi */
-    /*
-     * Pick a mode closest to 96dpi 
-     */
-    for (mode = output->probed_modes; mode; mode = mode->next)
-    {
-	int	    dpi;
-	int	    preferred = (mode->type & M_T_PREFERRED) != 0;
-	int	    diff;
-
-	if (mode->HDisplay > width || mode->VDisplay > height) continue;
-	dpi = (mode->HDisplay * 254) / (mm_height * 10);
-	diff = dpi - 96;
-	diff = diff < 0 ? -diff : diff;
-	if (target_mode == NULL || (preferred > target_preferred) ||
-	    (preferred == target_preferred && diff < target_diff))
-	{
-	    target_mode = mode;
-	    target_diff = diff;
-	    target_preferred = preferred;
-	}
-    }
-    return target_mode;
-}
-
-static DisplayModePtr
-xf86ClosestMode (xf86OutputPtr output, DisplayModePtr match,
-		 int width, int height)
-{
-    DisplayModePtr  target_mode = NULL;
-    DisplayModePtr  mode;
-    int		    target_diff = 0;
-    
-    /*
-     * Pick a mode closest to the specified mode
-     */
-    for (mode = output->probed_modes; mode; mode = mode->next)
-    {
-	int	    dx, dy;
-	int	    diff;
-
-	if (mode->HDisplay > width || mode->VDisplay > height) continue;
-	
-	/* exact matches are preferred */
-	if (xf86ModesEqual (mode, match))
-	    return mode;
-	
-	dx = match->HDisplay - mode->HDisplay;
-	dy = match->VDisplay - mode->VDisplay;
-	diff = dx * dx + dy * dy;
-	if (target_mode == NULL || diff < target_diff)
-	{
-	    target_mode = mode;
-	    target_diff = diff;
-	}
-    }
-    return target_mode;
-}
-
-static Bool
-xf86OutputHasPreferredMode (xf86OutputPtr output, int width, int height)
-{
-    DisplayModePtr  mode;
-
-    for (mode = output->probed_modes; mode; mode = mode->next)
-    {
-	if (mode->HDisplay > width || mode->VDisplay > height) continue;
-	if (mode->type & M_T_PREFERRED)
-	    return TRUE;
-    }
-    return FALSE;
-}
-
-static int
-xf86PickCrtcs (ScrnInfoPtr	scrn,
-	       xf86CrtcPtr	*best_crtcs,
-	       DisplayModePtr	*modes,
-	       int		n,
-	       int		width,
-	       int		height)
-{
-    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
-    int		    c, o, l;
-    xf86OutputPtr   output;
-    xf86CrtcPtr	    crtc;
-    xf86CrtcPtr	    *crtcs;
-    xf86CrtcPtr	    best_crtc;
-    int		    best_score;
-    int		    score;
-    int		    my_score;
-    
-    if (n == config->num_output)
-	return 0;
-    output = config->output[n];
-    
-    /*
-     * Compute score with this output disabled
-     */
-    best_crtcs[n] = NULL;
-    best_crtc = NULL;
-    best_score = xf86PickCrtcs (scrn, best_crtcs, modes, n+1, width, height);
-    if (modes[n] == NULL)
-	return best_score;
-    
-    crtcs = xalloc (config->num_output * sizeof (xf86CrtcPtr));
-    if (!crtcs)
-	return best_score;
-
-    my_score = 1;
-    /* Score outputs that are known to be connected higher */
-    if (output->status == XF86OutputStatusConnected)
-	my_score++;
-    /* Score outputs with preferred modes higher */
-    if (xf86OutputHasPreferredMode (output, width, height))
-	my_score++;
-    /*
-     * Select a crtc for this output and
-     * then attempt to configure the remaining
-     * outputs
-     */
-    for (c = 0; c < config->num_crtc; c++)
-    {
-	if ((output->possible_crtcs & (1 << c)) == 0)
-	    continue;
-	
-	crtc = config->crtc[c];
-	/*
-	 * Check to see if some other output is
-	 * using this crtc
-	 */
-	for (o = 0; o < n; o++)
-	    if (best_crtcs[o] == crtc)
-		break;
-	if (o < n)
-	{
-	    /*
-	     * If the two outputs desire the same mode,
-	     * see if they can be cloned
-	     */
-	    if (xf86ModesEqual (modes[o], modes[n]) &&
-		config->output[o]->initial_x == config->output[n]->initial_x &&
-		config->output[o]->initial_y == config->output[n]->initial_y)
-	    {
-		for (l = 0; l < config->num_output; l++)
-		    if (output->possible_clones & (1 << l))
-			break;
-		if (l == config->num_output)
-		    continue;		/* nope, try next CRTC */
-	    }
-	    else
-		continue;		/* different modes, can't clone */
-	}
-	crtcs[n] = crtc;
-	memcpy (crtcs, best_crtcs, n * sizeof (xf86CrtcPtr));
-	score = my_score + xf86PickCrtcs (scrn, crtcs, modes, n+1, width, height);
-	if (score > best_score)
-	{
-	    best_crtc = crtc;
-	    best_score = score;
-	    memcpy (best_crtcs, crtcs, config->num_output * sizeof (xf86CrtcPtr));
-	}
-    }
-    xfree (crtcs);
-    return best_score;
-}
-
-
-/*
- * Compute the virtual size necessary to place all of the available
- * crtcs in the specified configuration and also large enough to
- * resize any crtc to the largest available mode
- */
-
-static void
-xf86DefaultScreenLimits (ScrnInfoPtr scrn, int *widthp, int *heightp)
-{
-    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
-    int	    width = 0, height = 0;
-    int	    o;
-    int	    c;
-    int	    s;
-
-    for (c = 0; c < config->num_crtc; c++)
-    {
-	int	    crtc_width = 0, crtc_height = 0;
-	xf86CrtcPtr crtc = config->crtc[c];
-
-	if (crtc->enabled)
-	{
-	    crtc_width = crtc->x + crtc->desiredMode.HDisplay;
-	    crtc_height = crtc->y + crtc->desiredMode.VDisplay;
-	}
-	for (o = 0; o < config->num_output; o++) 
-	{
-	    xf86OutputPtr   output = config->output[o];
-
-	    for (s = 0; s < config->num_crtc; s++)
-		if (output->possible_crtcs & (1 << s))
-		{
-		    DisplayModePtr  mode;
-		    for (mode = output->probed_modes; mode; mode = mode->next)
-		    {
-			if (mode->HDisplay > crtc_width)
-			    crtc_width = mode->HDisplay;
-			if (mode->VDisplay > crtc_height)
-			    crtc_height = mode->VDisplay;
-		    }
-		}
-	}
-	if (crtc_width > width)
-	    width = crtc_width;
-	if (crtc_height > height)
-	    height = crtc_height;
-    }
-    if (config->maxWidth && width > config->maxWidth) width = config->maxWidth;
-    if (config->maxHeight && height > config->maxHeight) height = config->maxHeight;
-    if (config->minWidth && width < config->minWidth) width = config->minWidth;
-    if (config->minHeight && height < config->minHeight) height = config->minHeight;
-    *widthp = width;
-    *heightp = height;
-}
-
-#define POSITION_UNSET	-100000
-
-static Bool
-xf86InitialOutputPositions (ScrnInfoPtr scrn, DisplayModePtr *modes)
-{
-    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
-    int			o;
-    int			min_x, min_y;
-    
-    for (o = 0; o < config->num_output; o++)
-    {
-	xf86OutputPtr	output = config->output[o];
-
-	output->initial_x = output->initial_y = POSITION_UNSET;
-    }
-    
-    /*
-     * Loop until all outputs are set
-     */
-    for (;;)
-    {
-	Bool	any_set = FALSE;
-	Bool	keep_going = FALSE;
-
-	for (o = 0; o < config->num_output; o++)	
-	{
-	    static const OutputOpts	relations[] = {
-		OPTION_BELOW, OPTION_RIGHT_OF, OPTION_ABOVE, OPTION_LEFT_OF
-	    };
-	    xf86OutputPtr   output = config->output[o];
-	    xf86OutputPtr   relative;
-	    char	    *relative_name;
-	    char	    *position;
-	    OutputOpts	    relation;
-	    int		    r;
-
-	    if (output->initial_x != POSITION_UNSET)
-		continue;
-	    position = xf86GetOptValString (output->options,
-					    OPTION_POSITION);
-	    /*
-	     * Absolute position wins
-	     */
-	    if (position)
-	    {
-		int		    x, y;
-		if (sscanf (position, "%d %d", &x, &y) == 2)
-		{
-		    output->initial_x = x;
-		    output->initial_y = y;
-		}
-		else
-		{
-		    xf86DrvMsg (scrn->scrnIndex, X_ERROR,
-				"Output %s position not of form \"x y\"\n",
-				output->name);
-		    output->initial_x = output->initial_y = 0;
-		}
-		any_set = TRUE;
-		continue;
-	    }
-	    /*
-	     * Next comes relative positions
-	     */
-	    relation = 0;
-	    relative_name = NULL;
-	    for (r = 0; r < 4; r++)
-	    {
-		relation = relations[r];
-		relative_name = xf86GetOptValString (output->options,
-						     relation);
-		if (relative_name)
-		    break;
-	    }
-	    if (relative_name)
-	    {
-		int or;
-		relative = NULL;
-		for (or = 0; or < config->num_output; or++)
-		{
-		    xf86OutputPtr	out_rel = config->output[or];
-		    XF86ConfMonitorPtr	rel_mon = out_rel->conf_monitor;
-		    char		*name;
-
-		    if (rel_mon)
-			name = rel_mon->mon_identifier;
-		    else
-			name = out_rel->name;
-		    if (!strcmp (relative_name, name))
-		    {
-			relative = config->output[or];
-			break;
-		    }
-		}
-		if (!relative)
-		{
-		    xf86DrvMsg (scrn->scrnIndex, X_ERROR,
-				"Cannot position output %s relative to unknown output %s\n",
-				output->name, relative_name);
-		    output->initial_x = 0;
-		    output->initial_y = 0;
-		    any_set = TRUE;
-		    continue;
-		}
-		if (relative->initial_x == POSITION_UNSET)
-		{
-		    keep_going = TRUE;
-		    continue;
-		}
-		output->initial_x = relative->initial_x;
-		output->initial_y = relative->initial_y;
-		switch (relation) {
-		case OPTION_BELOW:
-		    output->initial_y += modes[or]->VDisplay;
-		    break;
-		case OPTION_RIGHT_OF:
-		    output->initial_x += modes[or]->HDisplay;
-		    break;
-		case OPTION_ABOVE:
-		    output->initial_y -= modes[o]->VDisplay;
-		    break;
-		case OPTION_LEFT_OF:
-		    output->initial_x -= modes[o]->HDisplay;
-		    break;
-		default:
-		    break;
-		}
-		any_set = TRUE;
-		continue;
-	    }
-	    
-	    /* Nothing set, just stick them at 0,0 */
-	    output->initial_x = 0;
-	    output->initial_y = 0;
-	    any_set = TRUE;
-	}
-	if (!keep_going)
-	    break;
-	if (!any_set) 
-	{
-	    for (o = 0; o < config->num_output; o++)
-	    {
-		xf86OutputPtr   output = config->output[o];
-		if (output->initial_x == POSITION_UNSET)
-		{
-		    xf86DrvMsg (scrn->scrnIndex, X_ERROR,
-				"Output position loop. Moving %s to 0,0\n",
-				output->name);
-		    output->initial_x = output->initial_y = 0;
-		    break;
-		}
-	    }
-	}
-    }
-
-    /*
-     * normalize positions
-     */
-    min_x = 1000000;
-    min_y = 1000000;
-    for (o = 0; o < config->num_output; o++)
-    {
-	xf86OutputPtr	output = config->output[o];
-
-	if (output->initial_x < min_x)
-	    min_x = output->initial_x;
-	if (output->initial_y < min_y)
-	    min_y = output->initial_y;
-    }
-    
-    for (o = 0; o < config->num_output; o++)
-    {
-	xf86OutputPtr	output = config->output[o];
-
-	output->initial_x -= min_x;
-	output->initial_y -= min_y;
-    }
-    return TRUE;
-}
-
-/*
- * XXX walk the monitor mode list and prune out duplicates that
- * are inserted by xf86DDCMonitorSet. In an ideal world, that
- * function would do this work by itself.
- */
-
-static void
-xf86PruneDuplicateMonitorModes (MonPtr Monitor)
-{
-    DisplayModePtr  master, clone, next;
-
-    for (master = Monitor->Modes; 
-	 master && master != Monitor->Last; 
-	 master = master->next)
-    {
-	for (clone = master->next; clone && clone != Monitor->Modes; clone = next)
-	{
-	    next = clone->next;
-	    if (xf86ModesEqual (master, clone))
-	    {
-		if (Monitor->Last == clone)
-		    Monitor->Last = clone->prev;
-		xf86DeleteMode (&Monitor->Modes, clone);
-	    }
-	}
-    }
-}
-
-/** Return - 0 + if a should be earlier, same or later than b in list
- */
-static int
-xf86ModeCompare (DisplayModePtr a, DisplayModePtr b)
-{
-    int	diff;
-
-    diff = ((b->type & M_T_PREFERRED) != 0) - ((a->type & M_T_PREFERRED) != 0);
-    if (diff)
-	return diff;
-    diff = b->HDisplay * b->VDisplay - a->HDisplay * a->VDisplay;
-    if (diff)
-	return diff;
-    diff = b->Clock - a->Clock;
-    return diff;
-}
-
-/**
- * Insertion sort input in-place and return the resulting head
- */
-static DisplayModePtr
-xf86SortModes (DisplayModePtr input)
-{
-    DisplayModePtr  output = NULL, i, o, n, *op, prev;
-
-    /* sort by preferred status and pixel area */
-    while (input)
-    {
-	i = input;
-	input = input->next;
-	for (op = &output; (o = *op); op = &o->next)
-	    if (xf86ModeCompare (o, i) > 0)
-		break;
-	i->next = *op;
-	*op = i;
-    }
-    /* prune identical modes */
-    for (o = output; o && (n = o->next); o = n)
-    {
-	if (!strcmp (o->name, n->name) && xf86ModesEqual (o, n))
-	{
-	    o->next = n->next;
-	    xfree (n->name);
-	    xfree (n);
-	    n = o;
-	}
-    }
-    /* hook up backward links */
-    prev = NULL;
-    for (o = output; o; o = o->next)
-    {
-	o->prev = prev;
-	prev = o;
-    }
-    return output;
-}
-
-#define DEBUG_REPROBE 1
-
-void
-xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY)
-{
-    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
-    int			o;
-
-    if (maxX == 0 || maxY == 0)
-	xf86RandR12GetOriginalVirtualSize (scrn, &maxX, &maxY);
-
-    /* Elide duplicate modes before defaulting code uses them */
-    xf86PruneDuplicateMonitorModes (scrn->monitor);
-    
-    /* Probe the list of modes for each output. */
-    for (o = 0; o < config->num_output; o++) 
-    {
-	xf86OutputPtr	    output = config->output[o];
-	DisplayModePtr	    mode;
-	DisplayModePtr	    config_modes = NULL, output_modes, default_modes;
-	char		    *preferred_mode;
-	xf86MonPtr	    edid_monitor;
-	XF86ConfMonitorPtr  conf_monitor;
-	MonRec		    mon_rec;
-	int		    min_clock = 0;
-	int		    max_clock = 0;
-	double		    clock;
-	enum { sync_config, sync_edid, sync_default } sync_source = sync_default;
-	
-	while (output->probed_modes != NULL)
-	    xf86DeleteMode(&output->probed_modes, output->probed_modes);
-
-	/*
-	 * Check connection status
-	 */
-	output->status = (*output->funcs->detect)(output);
-
-	if (output->status == XF86OutputStatusDisconnected)
-	    continue;
-
-	memset (&mon_rec, '\0', sizeof (mon_rec));
-	
-	conf_monitor = output->conf_monitor;
-	
-	if (conf_monitor)
-	{
-	    int	i;
-	    
-	    for (i = 0; i < conf_monitor->mon_n_hsync; i++)
-	    {
-		mon_rec.hsync[mon_rec.nHsync].lo = conf_monitor->mon_hsync[i].lo;
-		mon_rec.hsync[mon_rec.nHsync].hi = conf_monitor->mon_hsync[i].hi;
-		mon_rec.nHsync++;
-		sync_source = sync_config;
-	    }
-	    for (i = 0; i < conf_monitor->mon_n_vrefresh; i++)
-	    {
-		mon_rec.vrefresh[mon_rec.nVrefresh].lo = conf_monitor->mon_vrefresh[i].lo;
-		mon_rec.vrefresh[mon_rec.nVrefresh].hi = conf_monitor->mon_vrefresh[i].hi;
-		mon_rec.nVrefresh++;
-		sync_source = sync_config;
-	    }
-	    config_modes = xf86GetMonitorModes (scrn, conf_monitor);
-	}
-	
-	output_modes = (*output->funcs->get_modes) (output);
-	
-	edid_monitor = output->MonInfo;
-	
-	if (edid_monitor)
-	{
-	    int			    i;
-	    Bool		    set_hsync = mon_rec.nHsync == 0;
-	    Bool		    set_vrefresh = mon_rec.nVrefresh == 0;
-
-	    for (i = 0; i < sizeof (edid_monitor->det_mon) / sizeof (edid_monitor->det_mon[0]); i++)
-	    {
-		if (edid_monitor->det_mon[i].type == DS_RANGES)
-		{
-		    struct monitor_ranges   *ranges = &edid_monitor->det_mon[i].section.ranges;
-		    if (set_hsync && ranges->max_h)
-		    {
-			mon_rec.hsync[mon_rec.nHsync].lo = ranges->min_h;
-			mon_rec.hsync[mon_rec.nHsync].hi = ranges->max_h;
-			mon_rec.nHsync++;
-			if (sync_source == sync_default)
-			    sync_source = sync_edid;
-		    }
-		    if (set_vrefresh && ranges->max_v)
-		    {
-			mon_rec.vrefresh[mon_rec.nVrefresh].lo = ranges->min_v;
-			mon_rec.vrefresh[mon_rec.nVrefresh].hi = ranges->max_v;
-			mon_rec.nVrefresh++;
-			if (sync_source == sync_default)
-			    sync_source = sync_edid;
-		    }
-		    if (ranges->max_clock > max_clock)
-			max_clock = ranges->max_clock;
-		}
-	    }
-	}
-
-	if (xf86GetOptValFreq (output->options, OPTION_MIN_CLOCK,
-			       OPTUNITS_KHZ, &clock))
-	    min_clock = (int) clock;
-	if (xf86GetOptValFreq (output->options, OPTION_MAX_CLOCK,
-			       OPTUNITS_KHZ, &clock))
-	    max_clock = (int) clock;
-
-	/*
-	 * These limits will end up setting a 1024x768 at 60Hz mode by default,
-	 * which seems like a fairly good mode to use when nothing else is
-	 * specified
-	 */
-	if (mon_rec.nHsync == 0)
-	{
-	    mon_rec.hsync[0].lo = 31.0;
-	    mon_rec.hsync[0].hi = 55.0;
-	    mon_rec.nHsync = 1;
-	}
-	if (mon_rec.nVrefresh == 0)
-	{
-	    mon_rec.vrefresh[0].lo = 58.0;
-	    mon_rec.vrefresh[0].hi = 62.0;
-	    mon_rec.nVrefresh = 1;
-	}
-	default_modes = xf86GetDefaultModes (output->interlaceAllowed,
-					     output->doubleScanAllowed);
-	
-	if (sync_source == sync_config)
-	{
-	    /* 
-	     * Check output and config modes against sync range from config file
-	     */
-	    xf86ValidateModesSync (scrn, output_modes, &mon_rec);
-	    xf86ValidateModesSync (scrn, config_modes, &mon_rec);
-	}
-	/*
-	 * Check default modes against sync range
-	 */
-        xf86ValidateModesSync (scrn, default_modes, &mon_rec);
-	/*
-	 * Check default modes against monitor max clock
-	 */
-	if (max_clock)
-	    xf86ValidateModesClocks(scrn, default_modes,
-				    &min_clock, &max_clock, 1);
-	
-	output->probed_modes = NULL;
-	output->probed_modes = xf86ModesAdd (output->probed_modes, config_modes);
-	output->probed_modes = xf86ModesAdd (output->probed_modes, output_modes);
-	output->probed_modes = xf86ModesAdd (output->probed_modes, default_modes);
-	
-	/*
-	 * Check all modes against max size
-	 */
-	if (maxX && maxY)
-	    xf86ValidateModesSize (scrn, output->probed_modes,
-				       maxX, maxY, 0);
-	 
-	/*
-	 * Check all modes against output
-	 */
-	for (mode = output->probed_modes; mode != NULL; mode = mode->next) 
-	    if (mode->status == MODE_OK)
-		mode->status = (*output->funcs->mode_valid)(output, mode);
-	
-	xf86PruneInvalidModes(scrn, &output->probed_modes, TRUE);
-	
-	output->probed_modes = xf86SortModes (output->probed_modes);
-	
-	/* Check for a configured preference for a particular mode */
-	preferred_mode = xf86GetOptValString (output->options,
-					      OPTION_PREFERRED_MODE);
-
-	if (preferred_mode)
-	{
-	    for (mode = output->probed_modes; mode; mode = mode->next)
-	    {
-		if (!strcmp (preferred_mode, mode->name))
-		{
-		    if (mode != output->probed_modes)
-		    {
-			if (mode->prev)
-			    mode->prev->next = mode->next;
-			if (mode->next)
-			    mode->next->prev = mode->prev;
-			mode->next = output->probed_modes;
-			output->probed_modes->prev = mode;
-			mode->prev = NULL;
-			output->probed_modes = mode;
-		    }
-		    mode->type |= M_T_PREFERRED;
-		    break;
-		}
-	    }
-	}
-	
-#ifdef DEBUG_REPROBE
-	if (output->probed_modes != NULL) {
-	    xf86DrvMsg(scrn->scrnIndex, X_INFO,
-		       "Printing probed modes for output %s\n",
-		       output->name);
-	} else {
-	    xf86DrvMsg(scrn->scrnIndex, X_INFO,
-		       "No remaining probed modes for output %s\n",
-		       output->name);
-	}
-#endif
-	for (mode = output->probed_modes; mode != NULL; mode = mode->next)
-	{
-	    /* The code to choose the best mode per pipe later on will require
-	     * VRefresh to be set.
-	     */
-	    mode->VRefresh = xf86ModeVRefresh(mode);
-	    xf86SetModeCrtc(mode, INTERLACE_HALVE_V);
-
-#ifdef DEBUG_REPROBE
-	    xf86PrintModeline(scrn->scrnIndex, mode);
-#endif
-	}
-    }
-}
-
-
-/**
- * Copy one of the output mode lists to the ScrnInfo record
- */
-
-/* XXX where does this function belong? Here? */
-void
-xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr scrn, int *x, int *y);
-
-void
-xf86SetScrnInfoModes (ScrnInfoPtr scrn)
-{
-    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
-    xf86OutputPtr	output;
-    xf86CrtcPtr		crtc;
-    DisplayModePtr	last, mode;
-
-    output = config->output[config->compat_output];
-    if (!output->crtc)
-    {
-	int o;
-
-	output = NULL;
-	for (o = 0; o < config->num_output; o++)
-	    if (config->output[o]->crtc)
-	    {
-		config->compat_output = o;
-		output = config->output[o];
-		break;
-	    }
-	/* no outputs are active, punt and leave things as they are */
-	if (!output)
-	    return;
-    }
-    crtc = output->crtc;
-
-    /* Clear any existing modes from scrn->modes */
-    while (scrn->modes != NULL)
-	xf86DeleteMode(&scrn->modes, scrn->modes);
-
-    /* Set scrn->modes to the mode list for the 'compat' output */
-    scrn->modes = xf86DuplicateModes(scrn, output->probed_modes);
-
-    for (mode = scrn->modes; mode; mode = mode->next)
-	if (xf86ModesEqual (mode, &crtc->desiredMode))
-	    break;
-
-    if (scrn->modes != NULL) {
-	/* For some reason, scrn->modes is circular, unlike the other mode
-	 * lists.  How great is that?
-	 */
-	for (last = scrn->modes; last && last->next; last = last->next)
-	    ;
-	last->next = scrn->modes;
-	scrn->modes->prev = last;
-	if (mode) {
-	    while (scrn->modes != mode)
-		scrn->modes = scrn->modes->next;
-	}
-    }
-    scrn->currentMode = scrn->modes;
-}
-
-/**
- * Construct default screen configuration
- *
- * Given auto-detected (and, eventually, configured) values,
- * construct a usable configuration for the system
- */
-
-Bool
-xf86InitialConfiguration (ScrnInfoPtr	    scrn)
-{
-    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
-    int			o, c;
-    DisplayModePtr	target_mode = NULL;
-    xf86CrtcPtr		*crtcs;
-    DisplayModePtr	*modes;
-    Bool		*enabled;
-    int			width;
-    int			height;
-
-    if (scrn->display->virtualX)
-	width = scrn->display->virtualX;
-    else
-	width = config->maxWidth;
-    if (scrn->display->virtualY)
-	height = scrn->display->virtualY;
-    else
-	height = config->maxHeight;
-
-    xf86ProbeOutputModes (scrn, width, height);
-
-    crtcs = xnfcalloc (config->num_output, sizeof (xf86CrtcPtr));
-    modes = xnfcalloc (config->num_output, sizeof (DisplayModePtr));
-    enabled = xnfcalloc (config->num_output, sizeof (Bool));
-    
-    for (o = 0; o < config->num_output; o++)
-    {
-	xf86OutputPtr output = config->output[o];
-	
-	modes[o] = NULL;
-	enabled[o] = (xf86OutputEnabled (output) &&
-		      output->status != XF86OutputStatusDisconnected);
-    }
-    
-    /*
-     * Let outputs with preferred modes drive screen size
-     */
-    for (o = 0; o < config->num_output; o++)
-    {
-	xf86OutputPtr output = config->output[o];
-
-	if (enabled[o] &&
-	    xf86OutputHasPreferredMode (output, width, height))
-	{
-	    target_mode = xf86DefaultMode (output, width, height);
-	    if (target_mode)
-	    {
-		modes[o] = target_mode;
-		config->compat_output = o;
-		break;
-	    }
-	}
-    }
-    if (!target_mode)
-    {
-	for (o = 0; o < config->num_output; o++)
-	{
-	    xf86OutputPtr output = config->output[o];
-	    if (enabled[o])
-	    {
-		target_mode = xf86DefaultMode (output, width, height);
-		if (target_mode)
-		{
-		    modes[o] = target_mode;
-		    config->compat_output = o;
-		    break;
-		}
-	    }
-	}
-    }
-    for (o = 0; o < config->num_output; o++)
-    {
-	xf86OutputPtr output = config->output[o];
-	
-	if (enabled[o] && !modes[o])
-	    modes[o] = xf86ClosestMode (output, target_mode, width, height);
-    }
-
-    /*
-     * Set the position of each output
-     */
-    if (!xf86InitialOutputPositions (scrn, modes))
-    {
-	xfree (crtcs);
-	xfree (modes);
-	return FALSE;
-    }
-	
-    /*
-     * Assign CRTCs to fit output configuration
-     */
-    if (!xf86PickCrtcs (scrn, crtcs, modes, 0, width, height))
-    {
-	xfree (crtcs);
-	xfree (modes);
-	return FALSE;
-    }
-    
-    /* XXX override xf86 common frame computation code */
-    
-    scrn->display->frameX0 = 0;
-    scrn->display->frameY0 = 0;
-    
-    for (c = 0; c < config->num_crtc; c++)
-    {
-	xf86CrtcPtr	crtc = config->crtc[c];
-
-	crtc->enabled = FALSE;
-	memset (&crtc->desiredMode, '\0', sizeof (crtc->desiredMode));
-    }
-    
-    /*
-     * Set initial configuration
-     */
-    for (o = 0; o < config->num_output; o++)
-    {
-	xf86OutputPtr	output = config->output[o];
-	DisplayModePtr	mode = modes[o];
-        xf86CrtcPtr	crtc = crtcs[o];
-
-	if (mode && crtc)
-	{
-	    crtc->desiredMode = *mode;
-	    crtc->enabled = TRUE;
-	    crtc->x = output->initial_x;
-	    crtc->y = output->initial_y;
-	    output->crtc = crtc;
-	}
-    }
-    
-    if (scrn->display->virtualX == 0)
-    {
-	/*
-	 * Expand virtual size to cover potential mode switches
-	 */
-	xf86DefaultScreenLimits (scrn, &width, &height);
-    
-	scrn->display->virtualX = width;
-	scrn->display->virtualY = height;
-    }
-
-    if (width > scrn->virtualX)
-	scrn->virtualX = width;
-    if (height > scrn->virtualY)
-	scrn->virtualY = height;
-    
-    /* Mirror output modes to scrn mode list */
-    xf86SetScrnInfoModes (scrn);
-    
-    xfree (crtcs);
-    xfree (modes);
-    return TRUE;
-}
-
-/**
- * Set the DPMS power mode of all outputs and CRTCs.
- *
- * If the new mode is off, it will turn off outputs and then CRTCs.
- * Otherwise, it will affect CRTCs before outputs.
- */
-void
-xf86DPMSSet(ScrnInfoPtr scrn, int mode, int flags)
-{
-    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
-    int			i;
-
-    if (!scrn->vtSema)
-	return;
-
-    if (mode == DPMSModeOff) {
-	for (i = 0; i < config->num_output; i++) {
-	    xf86OutputPtr output = config->output[i];
-	    if (output->crtc != NULL)
-		(*output->funcs->dpms) (output, mode);
-	}
-    }
-
-    for (i = 0; i < config->num_crtc; i++) {
-	xf86CrtcPtr crtc = config->crtc[i];
-	if (crtc->enabled)
-	    (*crtc->funcs->dpms) (crtc, mode);
-    }
-
-    if (mode != DPMSModeOff) {
-	for (i = 0; i < config->num_output; i++) {
-	    xf86OutputPtr output = config->output[i];
-	    if (output->crtc != NULL)
-		(*output->funcs->dpms) (output, mode);
-	}
-    }
-}
-
-/**
- * Implement the screensaver by just calling down into the driver DPMS hooks.
- *
- * Even for monitors with no DPMS support, by the definition of our DPMS hooks,
- * the outputs will still get disabled (blanked).
- */
-Bool
-xf86SaveScreen(ScreenPtr pScreen, int mode)
-{
-    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-
-    if (xf86IsUnblank(mode))
-	xf86DPMSSet(pScrn, DPMSModeOn, 0);
-    else
-	xf86DPMSSet(pScrn, DPMSModeOff, 0);
-
-    return TRUE;
-}
-
-/**
- * Disable all inactive crtcs and outputs
- */
-void
-xf86DisableUnusedFunctions(ScrnInfoPtr pScrn)
-{
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-    int			o, c;
-
-    for (o = 0; o < xf86_config->num_output; o++) 
-    {
-	xf86OutputPtr  output = xf86_config->output[o];
-	if (!output->crtc) 
-	    (*output->funcs->dpms)(output, DPMSModeOff);
-    }
-
-    for (c = 0; c < xf86_config->num_crtc; c++) 
-    {
-	xf86CrtcPtr crtc = xf86_config->crtc[c];
-
-	if (!crtc->enabled) 
-	{
-	    crtc->funcs->dpms(crtc, DPMSModeOff);
-	    memset(&crtc->mode, 0, sizeof(crtc->mode));
-	}
-    }
-}
-
-#ifdef RANDR_12_INTERFACE
-
-#define EDID_ATOM_NAME		"EDID_DATA"
-
-/**
- * Set the RandR EDID property
- */
-static void
-xf86OutputSetEDIDProperty (xf86OutputPtr output, void *data, int data_len)
-{
-    Atom edid_atom = MakeAtom(EDID_ATOM_NAME, sizeof(EDID_ATOM_NAME), TRUE);
-
-    /* This may get called before the RandR resources have been created */
-    if (output->randr_output == NULL)
-	return;
-
-    if (data_len != 0) {
-	RRChangeOutputProperty(output->randr_output, edid_atom, XA_INTEGER, 8,
-			       PropModeReplace, data_len, data, FALSE);
-    } else {
-	RRDeleteOutputProperty(output->randr_output, edid_atom);
-    }
-}
-
-#endif
-
-/**
- * Set the EDID information for the specified output
- */
-void
-xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon)
-{
-    ScrnInfoPtr		scrn = output->scrn;
-    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
-    int			i;
-#ifdef RANDR_12_INTERFACE
-    int			size;
-#endif
-    
-    if (output->MonInfo != NULL)
-	xfree(output->MonInfo);
-    
-    output->MonInfo = edid_mon;
-
-    /* Debug info for now, at least */
-    xf86DrvMsg(scrn->scrnIndex, X_INFO, "EDID for output %s\n", output->name);
-    xf86PrintEDID(edid_mon);
-    
-    /* Set the DDC properties for the 'compat' output */
-    if (output == config->output[config->compat_output])
-        xf86SetDDCproperties(scrn, edid_mon);
-
-#ifdef RANDR_12_INTERFACE
-    /* Set the RandR output properties */
-    size = 0;
-    if (edid_mon)
-    {
-	if (edid_mon->ver.version == 1)
-	    size = 128;
-	else if (edid_mon->ver.version == 2)
-	    size = 256;
-    }
-    xf86OutputSetEDIDProperty (output, edid_mon ? edid_mon->rawData : NULL, size);
-#endif
-
-    if (edid_mon)
-    {
-	/* Pull out a phyiscal size from a detailed timing if available. */
-	for (i = 0; i < 4; i++) {
-	    if (edid_mon->det_mon[i].type == DT &&
-		edid_mon->det_mon[i].section.d_timings.h_size != 0 &&
-		edid_mon->det_mon[i].section.d_timings.v_size != 0)
-	    {
-		output->mm_width = edid_mon->det_mon[i].section.d_timings.h_size;
-		output->mm_height = edid_mon->det_mon[i].section.d_timings.v_size;
-		break;
-	    }
-	}
-    
-	/* if no mm size is available from a detailed timing, check the max size field */
-	if ((!output->mm_width || !output->mm_height) &&
-	    (edid_mon->features.hsize && edid_mon->features.vsize))
-	{
-	    output->mm_width = edid_mon->features.hsize * 10;
-	    output->mm_height = edid_mon->features.vsize * 10;
-	}
-    }
-}
-
-/**
- * Return the list of modes supported by the EDID information
- * stored in 'output'
- */
-DisplayModePtr
-xf86OutputGetEDIDModes (xf86OutputPtr output)
-{
-    ScrnInfoPtr	scrn = output->scrn;
-    xf86MonPtr	edid_mon = output->MonInfo;
-
-    if (!edid_mon)
-	return NULL;
-    return xf86DDCGetModes(scrn->scrnIndex, edid_mon);
-}
-
-xf86MonPtr
-xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus)
-{
-    ScrnInfoPtr	scrn = output->scrn;
-
-    return xf86DoEDID_DDC2 (scrn->scrnIndex, pDDCBus);
-}
diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h
deleted file mode 100644
index 53d2cdb..0000000
--- a/src/i830_xf86Crtc.h
+++ /dev/null
@@ -1,553 +0,0 @@
-/*
- * 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 _XF86CRTC_H_
-#define _XF86CRTC_H_
-
-#include <edid.h>
-#include "randrstr.h"
-#include "i830_xf86Rename.h"
-#include "i830_xf86Modes.h"
-#include "xf86Parser.h"
-#include "damage.h"
-
-/* Compat definitions for older X Servers. */
-#ifndef M_T_PREFERRED
-#define M_T_PREFERRED	0x08
-#endif
-#ifndef M_T_DRIVER
-#define M_T_DRIVER	0x40
-#endif
-
-typedef struct _xf86Crtc xf86CrtcRec, *xf86CrtcPtr;
-typedef struct _xf86Output xf86OutputRec, *xf86OutputPtr;
-
-typedef enum _xf86OutputStatus {
-   XF86OutputStatusConnected,
-   XF86OutputStatusDisconnected,
-   XF86OutputStatusUnknown,
-} xf86OutputStatus;
-
-typedef struct _xf86CrtcFuncs {
-   /**
-    * Turns the crtc on/off, or sets intermediate power levels if available.
-    *
-    * Unsupported intermediate modes drop to the lower power setting.  If the
-    * mode is DPMSModeOff, the crtc must be disabled sufficiently for it to
-    * be safe to call mode_set.
-    */
-   void
-    (*dpms)(xf86CrtcPtr		crtc,
-	    int		    	mode);
-
-   /**
-    * Saves the crtc's state for restoration on VT switch.
-    */
-   void
-    (*save)(xf86CrtcPtr		crtc);
-
-   /**
-    * Restore's the crtc's state at VT switch.
-    */
-   void
-    (*restore)(xf86CrtcPtr	crtc);
-
-    /**
-     * Lock CRTC prior to mode setting, mostly for DRI.
-     * Returns whether unlock is needed
-     */
-    Bool
-    (*lock) (xf86CrtcPtr crtc);
-    
-    /**
-     * Unlock CRTC after mode setting, mostly for DRI
-     */
-    void
-    (*unlock) (xf86CrtcPtr crtc);
-    
-    /**
-     * Callback to adjust the mode to be set in the CRTC.
-     *
-     * This allows a CRTC to adjust the clock or even the entire set of
-     * timings, which is used for panels with fixed timings or for
-     * buses with clock limitations.
-     */
-    Bool
-    (*mode_fixup)(xf86CrtcPtr crtc,
-		  DisplayModePtr mode,
-		  DisplayModePtr adjusted_mode);
-
-    /**
-     * Callback for setting up a video mode after fixups have been made.
-     */
-    void
-    (*mode_set)(xf86CrtcPtr crtc,
-		DisplayModePtr mode,
-		DisplayModePtr adjusted_mode,
-		int x, int y);
-
-    /* Set the color ramps for the CRTC to the given values. */
-    void
-    (*gamma_set)(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue,
-		 int size);
-
-    /**
-     * Create shadow pixmap for rotation support
-     */
-    PixmapPtr
-    (*shadow_create) (xf86CrtcPtr crtc, int width, int height);
-    
-    /**
-     * Destroy shadow pixmap
-     */
-    void
-    (*shadow_destroy) (xf86CrtcPtr crtc, PixmapPtr pPixmap);
-
-    /**
-     * Clean up driver-specific bits of the crtc
-     */
-    void
-    (*destroy) (xf86CrtcPtr	crtc);
-} xf86CrtcFuncsRec, *xf86CrtcFuncsPtr;
-
-struct _xf86Crtc {
-    /**
-     * Associated ScrnInfo
-     */
-    ScrnInfoPtr	    scrn;
-    
-    /**
-     * Active state of this CRTC
-     *
-     * Set when this CRTC is driving one or more outputs 
-     */
-    Bool	    enabled;
-    
-    /** 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  mode;
-    Rotation	    rotation;
-    PixmapPtr	    rotatedPixmap;
-    /**
-     * Position on screen
-     *
-     * Locates this CRTC within the frame buffer
-     */
-    int		    x, y;
-    
-    /**
-     * 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;
-    Rotation	    desiredRotation;
-    int		    desiredX, desiredY;
-    
-    /** crtc-specific functions */
-    const 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 _xf86OutputFuncs {
-    /**
-     * Called to allow the output a chance to create properties after the
-     * RandR objects have been created.
-     */
-    void
-    (*create_resources)(xf86OutputPtr output);
-
-    /**
-     * 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)(xf86OutputPtr	output,
-	    int			mode);
-
-    /**
-     * Saves the output's state for restoration on VT switch.
-     */
-    void
-    (*save)(xf86OutputPtr	output);
-
-    /**
-     * Restore's the output's state at VT switch.
-     */
-    void
-    (*restore)(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 output specifically, and not represent generic CRTC limitations.
-     *
-     * \return MODE_OK if the mode is valid, or another MODE_* otherwise.
-     */
-    int
-    (*mode_valid)(xf86OutputPtr	    output,
-		  DisplayModePtr    pMode);
-
-    /**
-     * Callback to adjust the mode to be set in the CRTC.
-     *
-     * This allows an output to adjust the clock or even the entire set of
-     * timings, which is used for panels with fixed timings or for
-     * buses with clock limitations.
-     */
-    Bool
-    (*mode_fixup)(xf86OutputPtr output,
-		  DisplayModePtr mode,
-		  DisplayModePtr adjusted_mode);
-
-    /**
-     * Callback for setting up a video mode after fixups have been made.
-     *
-     * This is only called while the output is disabled.  The dpms callback
-     * must be all that's necessary for the output, to turn the output on
-     * after this function is called.
-     */
-    void
-    (*mode_set)(xf86OutputPtr  output,
-		DisplayModePtr mode,
-		DisplayModePtr adjusted_mode);
-
-    /**
-     * Probe for a connected output, and return detect_status.
-     */
-    xf86OutputStatus
-    (*detect)(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)(xf86OutputPtr	    output);
-
-#ifdef RANDR_12_INTERFACE
-    /**
-     * Callback when an output's property has changed.
-     */
-    Bool
-    (*set_property)(xf86OutputPtr output,
-		    Atom property,
-		    RRPropertyValuePtr value);
-#endif
-    /**
-     * Clean up driver-specific bits of the output
-     */
-    void
-    (*destroy) (xf86OutputPtr	    output);
-} xf86OutputFuncsRec, *xf86OutputFuncsPtr;
-
-struct _xf86Output {
-    /**
-     * Associated ScrnInfo
-     */
-    ScrnInfoPtr		scrn;
-
-    /**
-     * Currently connected crtc (if any)
-     *
-     * If this output is not in use, this field will be NULL.
-     */
-    xf86CrtcPtr		crtc;
-
-    /**
-     * Possible CRTCs for this output as a mask of crtc indices
-     */
-    CARD32		possible_crtcs;
-
-    /**
-     * Possible outputs to share the same CRTC as a mask of output indices
-     */
-    CARD32		possible_clones;
-    
-    /**
-     * Whether this output can support interlaced modes
-     */
-    Bool		interlaceAllowed;
-
-    /**
-     * Whether this output can support double scan modes
-     */
-    Bool		doubleScanAllowed;
-
-    /**
-     * 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;
-
-    /**
-     * Options parsed from the related monitor section
-     */
-    OptionInfoPtr	options;
-    
-    /**
-     * Configured monitor section
-     */
-    XF86ConfMonitorPtr  conf_monitor;
-    
-    /**
-     * Desired initial position
-     */
-    int			initial_x, initial_y;
-
-    /**
-     * Current connection status
-     *
-     * This indicates whether a monitor is known to be connected
-     * to this output or not, or whether there is no way to tell
-     */
-    xf86OutputStatus	status;
-
-    /** EDID monitor information */
-    xf86MonPtr		MonInfo;
-
-    /** subpixel order */
-    int			subpixel_order;
-
-    /** Physical size of the currently attached output device. */
-    int			mm_width, mm_height;
-
-    /** Output name */
-    char		*name;
-
-    /** output-specific functions */
-    const 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
-};
-
-typedef struct _xf86CrtcConfig {
-    int			num_output;
-    xf86OutputPtr	*output;
-    /**
-     * compat_output is used whenever we deal
-     * with legacy code that only understands a single
-     * output. pScrn->modes will be loaded from this output,
-     * adjust frame will whack this output, etc.
-     */
-    int			compat_output;
-
-    int			num_crtc;
-    xf86CrtcPtr		*crtc;
-
-    int			minWidth, minHeight;
-    int			maxWidth, maxHeight;
-    
-    /* For crtc-based rotation */
-    DamagePtr   rotationDamage;
-
-    /* DGA */
-    unsigned int	dga_flags;
-    unsigned long	dga_address;
-    DGAModePtr		dga_modes;
-    int			dga_nmode;
-    int			dga_width, dga_height, dga_stride;
-    DisplayModePtr	dga_save_mode;
-
-} xf86CrtcConfigRec, *xf86CrtcConfigPtr;
-
-extern int xf86CrtcConfigPrivateIndex;
-
-#define XF86_CRTC_CONFIG_PTR(p)	((xf86CrtcConfigPtr) ((p)->privates[xf86CrtcConfigPrivateIndex].ptr))
-
-/*
- * Initialize xf86CrtcConfig structure
- */
-
-void
-xf86CrtcConfigInit (ScrnInfoPtr		scrn);
-
-void
-xf86CrtcSetSizeRange (ScrnInfoPtr scrn,
-		      int minWidth, int minHeight,
-		      int maxWidth, int maxHeight);
-
-/*
- * Crtc functions
- */
-xf86CrtcPtr
-xf86CrtcCreate (ScrnInfoPtr		scrn,
-		const xf86CrtcFuncsRec	*funcs);
-
-void
-xf86CrtcDestroy (xf86CrtcPtr		crtc);
-
-
-/**
- * Allocate a crtc for the specified output
- *
- * Find a currently unused CRTC which is suitable for
- * the specified output
- */
-
-xf86CrtcPtr 
-xf86AllocCrtc (xf86OutputPtr		output);
-
-/**
- * Free a crtc
- *
- * Mark the crtc as unused by any outputs
- */
-
-void
-xf86FreeCrtc (xf86CrtcPtr		crtc);
-
-/**
- * Sets the given video mode on the given crtc
- */
-Bool
-xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
-		 int x, int y);
-
-/*
- * Assign crtc rotation during mode set
- */
-Bool
-xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation);
-
-/**
- * Return whether any output is assigned to the crtc
- */
-Bool
-xf86CrtcInUse (xf86CrtcPtr crtc);
-
-/*
- * Output functions
- */
-xf86OutputPtr
-xf86OutputCreate (ScrnInfoPtr		scrn,
-		      const xf86OutputFuncsRec *funcs,
-		      const char	*name);
-
-Bool
-xf86OutputRename (xf86OutputPtr output, const char *name);
-
-void
-xf86OutputDestroy (xf86OutputPtr	output);
-
-void
-xf86ProbeOutputModes (ScrnInfoPtr pScrn, int maxX, int maxY);
-
-void
-xf86SetScrnInfoModes (ScrnInfoPtr pScrn);
-
-Bool
-xf86InitialConfiguration (ScrnInfoPtr pScrn);
-
-void
-xf86DPMSSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags);
-    
-Bool
-xf86SaveScreen(ScreenPtr pScreen, int mode);
-
-void
-xf86DisableUnusedFunctions(ScrnInfoPtr pScrn);
-
-/**
- * Set the EDID information for the specified output
- */
-void
-xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon);
-
-/**
- * Return the list of modes supported by the EDID information
- * stored in 'output'
- */
-DisplayModePtr
-xf86OutputGetEDIDModes (xf86OutputPtr output);
-
-xf86MonPtr
-xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus);
-
-/**
- * Initialize dga for this screen
- */
-
-Bool
-xf86DiDGAInit (ScreenPtr pScreen, unsigned long dga_address);
-
-/**
- * Re-initialize dga for this screen (as when the set of modes changes)
- */
-
-Bool
-xf86DiDGAReInit (ScreenPtr pScreen);
-
-#endif /* _XF86CRTC_H_ */
diff --git a/src/i830_xf86DiDGA.c b/src/i830_xf86DiDGA.c
deleted file mode 100644
index 24a5297..0000000
--- a/src/i830_xf86DiDGA.c
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "xf86.h"
-#include "xf86DDC.h"
-#include "xf86_OSproc.h"
-#include "dgaproc.h"
-#include "i830_xf86Crtc.h"
-#include "i830_xf86Modes.h"
-#include "gcstruct.h"
-
-static Bool
-xf86_dga_get_modes (ScreenPtr pScreen)
-{
-    ScrnInfoPtr		scrn = xf86Screens[pScreen->myNum];
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
-    DGAModePtr		modes, mode;
-    DisplayModePtr	display_mode;
-    int			bpp = scrn->bitsPerPixel >> 3;
-    int			num;
-
-    num = 0;
-    display_mode = scrn->modes;
-    while (display_mode) 
-    {
-	num++;
-	display_mode = display_mode->next;
-	if (display_mode == scrn->modes)
-	    break;
-    }
-    
-    if (!num)
-	return FALSE;
-    
-    modes = xalloc(num * sizeof(DGAModeRec));
-    if (!modes)
-	return FALSE;
-    
-    num = 0;
-    display_mode = scrn->modes;
-    while (display_mode) 
-    {
-	mode = modes + num++;
-
-	mode->mode = display_mode;
-	mode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
-        mode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT;
-	if (display_mode->Flags & V_DBLSCAN)
-	    mode->flags |= DGA_DOUBLESCAN;
-	if (display_mode->Flags & V_INTERLACE)
-	    mode->flags |= DGA_INTERLACED;
-	mode->byteOrder = scrn->imageByteOrder;
-	mode->depth = scrn->depth;
-	mode->bitsPerPixel = scrn->bitsPerPixel;
-	mode->red_mask = scrn->mask.red;
-	mode->green_mask = scrn->mask.green;
-	mode->blue_mask = scrn->mask.blue;
-	mode->visualClass = (bpp == 1) ? PseudoColor : TrueColor;
-	mode->viewportWidth = display_mode->HDisplay;
-	mode->viewportHeight = display_mode->VDisplay;
-	mode->xViewportStep = (bpp == 3) ? 2 : 1;
-	mode->yViewportStep = 1;
-	mode->viewportFlags = DGA_FLIP_RETRACE;
-	mode->offset = 0;
-	mode->address = (unsigned char *) xf86_config->dga_address;
-	mode->bytesPerScanline = xf86_config->dga_stride;
-	mode->imageWidth = xf86_config->dga_width;
-	mode->imageHeight = xf86_config->dga_height;
-	mode->pixmapWidth = mode->imageWidth;
-	mode->pixmapHeight = mode->imageHeight;
-	mode->maxViewportX = mode->imageWidth -	mode->viewportWidth;
-	mode->maxViewportY = mode->imageHeight - mode->viewportHeight;
-
-	display_mode = display_mode->next;
-	if (display_mode == scrn->modes)
-	    break;
-    }
-    if (xf86_config->dga_modes)
-	xfree (xf86_config->dga_modes);
-    xf86_config->dga_nmode = num;
-    xf86_config->dga_modes = modes;
-    return TRUE;
-}
-
-static Bool
-xf86_dga_set_mode(ScrnInfoPtr scrn, DGAModePtr display_mode)
-{
-    ScreenPtr		pScreen = scrn->pScreen;
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
-
-    if (!display_mode) 
-    {
-	if (xf86_config->dga_save_mode)
-	{
-	    xf86SwitchMode(pScreen, xf86_config->dga_save_mode);
-	    xf86_config->dga_save_mode = NULL;
-	}
-    }
-    else
-    {
-	if (!xf86_config->dga_save_mode)
-	{
-	    xf86_config->dga_save_mode = scrn->currentMode;
-	    xf86SwitchMode(pScreen, display_mode->mode);
-	}
-    }
-    return TRUE;
-}
-
-static int
-xf86_dga_get_viewport(ScrnInfoPtr scrn)
-{
-    return 0;
-}
-
-static void
-xf86_dga_set_viewport(ScrnInfoPtr scrn, int x, int y, int flags)
-{
-   scrn->AdjustFrame(scrn->pScreen->myNum, x, y, flags);
-}
-
-static Bool
-xf86_dga_get_drawable_and_gc (ScrnInfoPtr scrn, DrawablePtr *ppDrawable, GCPtr *ppGC)
-{
-    ScreenPtr		pScreen = scrn->pScreen;
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
-    PixmapPtr		pPixmap;
-    GCPtr		pGC;
-    
-    pPixmap = GetScratchPixmapHeader (pScreen, xf86_config->dga_width, xf86_config->dga_height,
-				      scrn->depth, scrn->bitsPerPixel, xf86_config->dga_stride, 
-				      (char *) scrn->memPhysBase + scrn->fbOffset);
-    if (!pPixmap)
-	return FALSE;
-    pGC  = GetScratchGC (scrn->depth, pScreen);
-    if (!pGC)
-    {
-	FreeScratchPixmapHeader (pPixmap);
-	return FALSE;
-    }
-    *ppDrawable = &pPixmap->drawable;
-    *ppGC = pGC;
-    return TRUE;
-}
-
-static void
-xf86_dga_release_drawable_and_gc (ScrnInfoPtr scrn, DrawablePtr pDrawable, GCPtr pGC)
-{
-    FreeScratchGC (pGC);
-    FreeScratchPixmapHeader ((PixmapPtr) pDrawable);
-}
-
-static void
-xf86_dga_fill_rect(ScrnInfoPtr scrn, int x, int y, int w, int h, unsigned long color)
-{
-    GCPtr		pGC;
-    DrawablePtr		pDrawable;
-    XID			vals[1];
-    xRectangle		r;
-
-    if (!xf86_dga_get_drawable_and_gc (scrn, &pDrawable, &pGC))
-	return;
-    vals[0] = color;
-    ChangeGC (pGC, GCForeground, vals);
-    ValidateGC (pDrawable, pGC);
-    r.x = x;
-    r.y = y;
-    r.width = w;
-    r.height = h;
-    pGC->ops->PolyFillRect (pDrawable, pGC, 1, &r);
-    xf86_dga_release_drawable_and_gc (scrn, pDrawable, pGC);
-}
-
-static void
-xf86_dga_sync(ScrnInfoPtr scrn)
-{
-    ScreenPtr	pScreen = scrn->pScreen;
-    WindowPtr	pRoot = WindowTable [pScreen->myNum];
-    char	buffer[4];
-
-    pScreen->GetImage (&pRoot->drawable, 0, 0, 1, 1, ZPixmap, ~0L, buffer);
-}
-
-static void
-xf86_dga_blit_rect(ScrnInfoPtr scrn, int srcx, int srcy, int w, int h, int dstx, int dsty)
-{
-    DrawablePtr	pDrawable;
-    GCPtr	pGC;
-
-    if (!xf86_dga_get_drawable_and_gc (scrn, &pDrawable, &pGC))
-	return;
-    ValidateGC (pDrawable, pGC);
-    pGC->ops->CopyArea (pDrawable, pDrawable, pGC, srcx, srcy, w, h, dstx, dsty);
-    xf86_dga_release_drawable_and_gc (scrn, pDrawable, pGC);
-}
-
-static Bool
-xf86_dga_open_framebuffer(ScrnInfoPtr scrn,
-			  char **name,
-			  unsigned char **mem, int *size, int *offset, int *flags)
-{
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
-    
-    *size = xf86_config->dga_stride * xf86_config->dga_height;
-    *mem = (unsigned char *) (xf86_config->dga_address);
-    *offset = 0;
-    *flags = DGA_NEED_ROOT;
-
-    return TRUE;
-}
-
-static void
-xf86_dga_close_framebuffer(ScrnInfoPtr scrn)
-{
-}
-
-static DGAFunctionRec xf86_dga_funcs = {
-   xf86_dga_open_framebuffer,
-   xf86_dga_close_framebuffer,
-   xf86_dga_set_mode,
-   xf86_dga_set_viewport,
-   xf86_dga_get_viewport,
-   xf86_dga_sync,
-   xf86_dga_fill_rect,
-   xf86_dga_blit_rect,
-   NULL
-};
-
-Bool
-xf86DiDGAReInit (ScreenPtr pScreen)
-{
-    ScrnInfoPtr		scrn = xf86Screens[pScreen->myNum];
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
-    
-    if (!xf86_dga_get_modes (pScreen))
-	return FALSE;
-    
-    return DGAReInitModes (pScreen, xf86_config->dga_modes, xf86_config->dga_nmode);
-}
-
-Bool
-xf86DiDGAInit (ScreenPtr pScreen, unsigned long dga_address)
-{
-    ScrnInfoPtr		scrn = xf86Screens[pScreen->myNum];
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
-
-    xf86_config->dga_flags = 0;
-    xf86_config->dga_address = dga_address;
-    xf86_config->dga_width = scrn->virtualX;
-    xf86_config->dga_height = scrn->virtualY;
-    xf86_config->dga_stride = scrn->displayWidth * scrn->bitsPerPixel >> 3;
-    
-    if (!xf86_dga_get_modes (pScreen))
-	return FALSE;
-    
-    return DGAInit(pScreen, &xf86_dga_funcs, xf86_config->dga_modes, xf86_config->dga_nmode);
-}
diff --git a/src/i830_xf86EdidModes.c b/src/i830_xf86EdidModes.c
deleted file mode 100644
index 866b9be..0000000
--- a/src/i830_xf86EdidModes.c
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- * Copyright 2006 Luc Verhaegen.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * @file This is a copy of edid_modes.c from the X Server, for compatibility
- * with old X Servers.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "xf86.h"
-#include "xf86DDC.h"
-#include <X11/Xatom.h>
-#include "property.h"
-#include "propertyst.h"
-#include "xf86DDC.h"
-#include "i830.h"
-#include "i830_display.h"
-#include <string.h>
-#include <math.h>
-
-#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0)
-
-/*
- * Quirks to work around broken EDID data from various monitors.
- */
-
-typedef enum {
-    DDC_QUIRK_NONE = 0,
-    /* Force detailed sync polarity to -h +v */
-    DDC_QUIRK_DT_SYNC_HM_VP = 1 << 0,
-    /* First detailed mode is bogus, prefer largest mode at 60hz */
-    DDC_QUIRK_PREFER_LARGE_60 = 1 << 1,
-    /* 135MHz clock is too high, drop a bit */
-    DDC_QUIRK_135_CLOCK_TOO_HIGH = 1 << 2
-} ddc_quirk_t;
-
-static Bool quirk_dt_sync_hm_vp (int scrnIndex, xf86MonPtr DDC)
-{
-    /* Belinea 1924S1W */
-    if (memcmp (DDC->vendor.name, "MAX", 4) == 0 &&
-	DDC->vendor.prod_id == 1932)
-	return TRUE;
-    /* Belinea 10 20 30W */
-    if (memcmp (DDC->vendor.name, "MAX", 4) == 0 &&
-	DDC->vendor.prod_id == 2007)
-	return TRUE;
-    /* ViewSonic VX2025wm (bug #9941) */
-    if (memcmp (DDC->vendor.name, "VSC", 4) == 0 &&
-	DDC->vendor.prod_id == 58653)
-	return TRUE;
-
-    return FALSE;
-}
-
-static Bool quirk_prefer_large_60 (int scrnIndex, xf86MonPtr DDC)
-{
-    /* Belinea 10 15 55 */
-    if (memcmp (DDC->vendor.name, "MAX", 4) == 0 &&
-	DDC->vendor.prod_id == 1516)
-	return TRUE;
-    
-    return FALSE;
-}
-
-static Bool quirk_135_clock_too_high (int scrnIndex, xf86MonPtr DDC)
-{
-    /* Envision Peripherals, Inc. EN-7100e.  See bug #9550. */
-    if (memcmp (DDC->vendor.name, "EPI", 4) == 0 &&
-	DDC->vendor.prod_id == 59264)
-	return TRUE;
-    
-    return FALSE;
-}
-
-typedef struct {
-    Bool	(*detect) (int scrnIndex, xf86MonPtr DDC);
-    ddc_quirk_t	quirk;
-    char	*description;
-} ddc_quirk_map_t;
-
-static const ddc_quirk_map_t ddc_quirks[] = {
-    { 
-	quirk_dt_sync_hm_vp,	DDC_QUIRK_DT_SYNC_HM_VP,
-	"Set detailed timing sync polarity to -h +v"
-    },
-    {
-	quirk_prefer_large_60,   DDC_QUIRK_PREFER_LARGE_60,
-	"Detailed timing is not preferred, use largest mode at 60Hz"
-    },
-    {
-	quirk_135_clock_too_high,   DDC_QUIRK_135_CLOCK_TOO_HIGH,
-	"Recommended 135MHz pixel clock is too high"
-    },
-    { 
-	NULL,		DDC_QUIRK_NONE,
-	"No known quirks"
-    },
-};
-
-/*
- * TODO:
- *  - for those with access to the VESA DMT standard; review please.
- */
-#define MODEPREFIX(name) NULL, NULL, name, 0,M_T_DRIVER
-#define MODESUFFIX   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,FALSE,FALSE,0,NULL,0,0.0,0.0
-
-static DisplayModeRec DDCEstablishedModes[17] = {
-    { MODEPREFIX("800x600"),    40000,  800,  840,  968, 1056, 0,  600,  601,  605,  628, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600 at 60Hz */
-    { MODEPREFIX("800x600"),    36000,  800,  824,  896, 1024, 0,  600,  601,  603,  625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600 at 56Hz */
-    { MODEPREFIX("640x480"),    31500,  640,  656,  720,  840, 0,  480,  481,  484,  500, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480 at 75Hz */
-    { MODEPREFIX("640x480"),    31500,  640,  664,  704,  832, 0,  480,  489,  491,  520, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480 at 72Hz */
-    { MODEPREFIX("640x480"),    30240,  640,  704,  768,  864, 0,  480,  483,  486,  525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480 at 67Hz */
-    { MODEPREFIX("640x480"),    25200,  640,  656,  752,  800, 0,  480,  490,  492,  525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480 at 60Hz */
-    { MODEPREFIX("720x400"),    35500,  720,  738,  846,  900, 0,  400,  421,  423,  449, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 720x400 at 88Hz */
-    { MODEPREFIX("720x400"),    28320,  720,  738,  846,  900, 0,  400,  412,  414,  449, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 720x400 at 70Hz */
-    { MODEPREFIX("1280x1024"), 135000, 1280, 1296, 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x1024 at 75Hz */
-    { MODEPREFIX("1024x768"),   78800, 1024, 1040, 1136, 1312, 0,  768,  769,  772,  800, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1024x768 at 75Hz */
-    { MODEPREFIX("1024x768"),   75000, 1024, 1048, 1184, 1328, 0,  768,  771,  777,  806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768 at 70Hz */
-    { MODEPREFIX("1024x768"),   65000, 1024, 1048, 1184, 1344, 0,  768,  771,  777,  806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768 at 60Hz */
-    { MODEPREFIX("1024x768"),   44900, 1024, 1032, 1208, 1264, 0,  768,  768,  776,  817, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* 1024x768 at 43Hz */
-    { MODEPREFIX("832x624"),    57284,  832,  864,  928, 1152, 0,  624,  625,  628,  667, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 832x624 at 75Hz */
-    { MODEPREFIX("800x600"),    49500,  800,  816,  896, 1056, 0,  600,  601,  604,  625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600 at 75Hz */
-    { MODEPREFIX("800x600"),    50000,  800,  856,  976, 1040, 0,  600,  637,  643,  666, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600 at 72Hz */
-    { MODEPREFIX("1152x864"),  108000, 1152, 1216, 1344, 1600, 0,  864,  865,  868,  900, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1152x864 at 75Hz */
-};
-
-static DisplayModePtr
-DDCModesFromEstablished(int scrnIndex, struct established_timings *timing,
-			ddc_quirk_t quirks)
-{
-    DisplayModePtr Modes = NULL, Mode = NULL;
-    CARD32 bits = (timing->t1) | (timing->t2 << 8) |
-        ((timing->t_manu & 0x80) << 9);
-    int i;
-
-    for (i = 0; i < 17; i++) {
-        if (bits & (0x01 << i)) {
-            Mode = xf86DuplicateMode(&DDCEstablishedModes[i]);
-            Modes = xf86ModesAdd(Modes, Mode);
-        }
-    }
-
-    return Modes;
-}
-
-/*
- *
- */
-static DisplayModePtr
-DDCModesFromStandardTiming(int scrnIndex, struct std_timings *timing,
-			   ddc_quirk_t quirks)
-{
-    DisplayModePtr Modes = NULL, Mode = NULL;
-    int i;
-
-    for (i = 0; i < STD_TIMINGS; i++) {
-        if (timing[i].hsize && timing[i].vsize && timing[i].refresh) {
-            Mode =  xf86CVTMode(timing[i].hsize, timing[i].vsize,
-                                timing[i].refresh, FALSE, FALSE);
-	    Mode->type = M_T_DRIVER;
-            Modes = xf86ModesAdd(Modes, Mode);
-        }
-    }
-
-    return Modes;
-}
-
-/*
- *
- */
-static DisplayModePtr
-DDCModeFromDetailedTiming(int scrnIndex, struct detailed_timings *timing,
-			  int preferred, ddc_quirk_t quirks)
-{
-    DisplayModePtr Mode;
-
-    /* We don't do stereo */
-    if (timing->stereo) {
-        xf86DrvMsg(scrnIndex, X_INFO,
-		   "%s: Ignoring: We don't handle stereo.\n", __func__);
-        return NULL;
-    }
-
-    /* We only do seperate sync currently */
-    if (timing->sync != 0x03) {
-         xf86DrvMsg(scrnIndex, X_INFO,
-		    "%s: %dx%d Warning: We only handle seperate"
-                    " sync.\n", __func__, timing->h_active, timing->v_active);
-    }
-
-    Mode = xnfalloc(sizeof(DisplayModeRec));
-    memset(Mode, 0, sizeof(DisplayModeRec));
-
-    Mode->type = M_T_DRIVER;
-    if (preferred)
-	Mode->type |= M_T_PREFERRED;
-
-    if( ( quirks & DDC_QUIRK_135_CLOCK_TOO_HIGH ) &&
-	timing->clock == 135000000 )
-        Mode->Clock = 108880;
-    else
-        Mode->Clock = timing->clock / 1000.0;
-
-    Mode->HDisplay = timing->h_active;
-    Mode->HSyncStart = timing->h_active + timing->h_sync_off;
-    Mode->HSyncEnd = Mode->HSyncStart + timing->h_sync_width;
-    Mode->HTotal = timing->h_active + timing->h_blanking;
-
-    Mode->VDisplay = timing->v_active;
-    Mode->VSyncStart = timing->v_active + timing->v_sync_off;
-    Mode->VSyncEnd = Mode->VSyncStart + timing->v_sync_width;
-    Mode->VTotal = timing->v_active + timing->v_blanking;
-
-    xf86SetModeDefaultName(Mode);
-
-    /* We ignore h/v_size and h/v_border for now. */
-
-    if (timing->interlaced)
-        Mode->Flags |= V_INTERLACE;
-
-    if (quirks & DDC_QUIRK_DT_SYNC_HM_VP)
-	Mode->Flags |= V_NHSYNC | V_PVSYNC;
-    else
-    {
-	if (timing->misc & 0x02)
-	    Mode->Flags |= V_PHSYNC;
-	else
-	    Mode->Flags |= V_NHSYNC;
-    
-	if (timing->misc & 0x01)
-	    Mode->Flags |= V_PVSYNC;
-	else
-	    Mode->Flags |= V_NVSYNC;
-    }
-
-    return Mode;
-}
-
-DisplayModePtr
-xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC)
-{
-    int preferred, i;
-    DisplayModePtr  Modes = NULL, Mode;
-    ddc_quirk_t	    quirks;
-
-    xf86DrvMsg (scrnIndex, X_INFO, "EDID vendor \"%s\", prod id %d\n",
-		DDC->vendor.name, DDC->vendor.prod_id);
-    quirks = DDC_QUIRK_NONE;
-    for (i = 0; ddc_quirks[i].detect; i++)
-	if (ddc_quirks[i].detect (scrnIndex, DDC))
-	{
-	    xf86DrvMsg (scrnIndex, X_INFO, "    EDID quirk: %s\n",
-			ddc_quirks[i].description);
-	    quirks |= ddc_quirks[i].quirk;
-	}
-    
-    preferred = PREFERRED_TIMING_MODE(DDC->features.msc);
-    if (quirks & DDC_QUIRK_PREFER_LARGE_60)
-	preferred = 0;
-
-    for (i = 0; i < DET_TIMINGS; i++) {
-	struct detailed_monitor_section *det_mon = &DDC->det_mon[i];
-
-        switch (det_mon->type) {
-        case DT:
-            Mode = DDCModeFromDetailedTiming(scrnIndex,
-                                             &det_mon->section.d_timings,
-					     preferred,
-					     quirks);
-	    preferred = 0;
-            Modes = xf86ModesAdd(Modes, Mode);
-            break;
-        case DS_STD_TIMINGS:
-            Mode = DDCModesFromStandardTiming(scrnIndex,
-					      det_mon->section.std_t,
-					      quirks);
-            Modes = xf86ModesAdd(Modes, Mode);
-            break;
-        default:
-            break;
-        }
-    }
-
-    /* Add established timings */
-    Mode = DDCModesFromEstablished(scrnIndex, &DDC->timings1, quirks);
-    Modes = xf86ModesAdd(Modes, Mode);
-
-    /* Add standard timings */
-    Mode = DDCModesFromStandardTiming(scrnIndex, DDC->timings2, quirks);
-    Modes = xf86ModesAdd(Modes, Mode);
-
-    if (quirks & DDC_QUIRK_PREFER_LARGE_60)
-    {
-	DisplayModePtr	best = Modes;
-	for (Mode = Modes; Mode; Mode = Mode->next)
-	{
-	    if (Mode == best) continue;
-	    if (Mode->HDisplay * Mode->VDisplay > best->HDisplay * best->VDisplay)
-	    {
-		best = Mode;
-		continue;
-	    }
-	    if (Mode->HDisplay * Mode->VDisplay == best->HDisplay * best->VDisplay)
-	    {
-		double	mode_refresh = xf86ModeVRefresh (Mode);
-		double	best_refresh = xf86ModeVRefresh (best);
-		double	mode_dist = fabs(mode_refresh - 60.0);
-		double	best_dist = fabs(best_refresh - 60.0);
-		if (mode_dist < best_dist)
-		{
-		    best = Mode;
-		    continue;
-		}
-	    }
-	}
-	if (best)
-	    best->type |= M_T_PREFERRED;
-    }
-    return Modes;
-}
-
-#endif /* XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0) */
diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c
deleted file mode 100644
index f620d4d..0000000
--- a/src/i830_xf86Modes.c
+++ /dev/null
@@ -1,636 +0,0 @@
-/* -*- c-basic-offset: 4 -*- */
-/* $XdotOrg: xserver/xorg/hw/xfree86/common/xf86Mode.c,v 1.10 2006/03/07 16:00:57 libv Exp $ */
-/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Mode.c,v 1.69 2003/10/08 14:58:28 dawes Exp $ */
-/*
- * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name of the copyright holder(s)
- * and author(s) shall not be used in advertising or otherwise to promote
- * the sale, use or other dealings in this Software without prior written
- * authorization from the copyright holder(s) and author(s).
- */
-
-#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 "xf86Priv.h"
-
-extern XF86ConfigPtr xf86configptr;
-
-/**
- * @file this file contains symbols from xf86Mode.c and friends that are static
- * there but we still want to use.  We need to come up with better API here.
- */
-
-#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0)
-/**
- * Calculates the horizontal sync rate of a mode.
- *
- * Exact copy of xf86Mode.c's.
- */
-double
-xf86ModeHSync(DisplayModePtr mode)
-{
-    double hsync = 0.0;
-    
-    if (mode->HSync > 0.0)
-	    hsync = mode->HSync;
-    else if (mode->HTotal > 0)
-	    hsync = (float)mode->Clock / (float)mode->HTotal;
-
-    return hsync;
-}
-
-/**
- * Calculates the vertical refresh rate of a mode.
- *
- * Exact copy of xf86Mode.c's.
- */
-double
-xf86ModeVRefresh(DisplayModePtr mode)
-{
-    double refresh = 0.0;
-
-    if (mode->VRefresh > 0.0)
-	refresh = mode->VRefresh;
-    else if (mode->HTotal > 0 && mode->VTotal > 0) {
-	refresh = mode->Clock * 1000.0 / mode->HTotal / mode->VTotal;
-	if (mode->Flags & V_INTERLACE)
-	    refresh *= 2.0;
-	if (mode->Flags & V_DBLSCAN)
-	    refresh /= 2.0;
-	if (mode->VScan > 1)
-	    refresh /= (float)(mode->VScan);
-    }
-    return refresh;
-}
-
-/** Sets a default mode name of <width>x<height> on a mode. */
-void
-xf86SetModeDefaultName(DisplayModePtr mode)
-{
-    if (mode->name != NULL)
-	xfree(mode->name);
-
-    mode->name = XNFprintf("%dx%d", mode->HDisplay, mode->VDisplay);
-}
-
-/*
- * xf86SetModeCrtc
- *
- * Initialises the Crtc parameters for a mode.  The initialisation includes
- * adjustments for interlaced and double scan modes.
- *
- * Exact copy of xf86Mode.c's.
- */
-void
-xf86SetModeCrtc(DisplayModePtr p, int adjustFlags)
-{
-    if ((p == NULL) || ((p->type & M_T_CRTC_C) == M_T_BUILTIN))
-	return;
-
-    p->CrtcHDisplay             = p->HDisplay;
-    p->CrtcHSyncStart           = p->HSyncStart;
-    p->CrtcHSyncEnd             = p->HSyncEnd;
-    p->CrtcHTotal               = p->HTotal;
-    p->CrtcHSkew                = p->HSkew;
-    p->CrtcVDisplay             = p->VDisplay;
-    p->CrtcVSyncStart           = p->VSyncStart;
-    p->CrtcVSyncEnd             = p->VSyncEnd;
-    p->CrtcVTotal               = p->VTotal;
-    if (p->Flags & V_INTERLACE) {
-	if (adjustFlags & INTERLACE_HALVE_V) {
-	    p->CrtcVDisplay         /= 2;
-	    p->CrtcVSyncStart       /= 2;
-	    p->CrtcVSyncEnd         /= 2;
-	    p->CrtcVTotal           /= 2;
-	}
-	/* Force interlaced modes to have an odd VTotal */
-	/* maybe we should only do this when INTERLACE_HALVE_V is set? */
-	p->CrtcVTotal |= 1;
-    }
-
-    if (p->Flags & V_DBLSCAN) {
-        p->CrtcVDisplay         *= 2;
-        p->CrtcVSyncStart       *= 2;
-        p->CrtcVSyncEnd         *= 2;
-        p->CrtcVTotal           *= 2;
-    }
-    if (p->VScan > 1) {
-        p->CrtcVDisplay         *= p->VScan;
-        p->CrtcVSyncStart       *= p->VScan;
-        p->CrtcVSyncEnd         *= p->VScan;
-        p->CrtcVTotal           *= p->VScan;
-    }
-    p->CrtcVBlankStart = min(p->CrtcVSyncStart, p->CrtcVDisplay);
-    p->CrtcVBlankEnd = max(p->CrtcVSyncEnd, p->CrtcVTotal);
-    p->CrtcHBlankStart = min(p->CrtcHSyncStart, p->CrtcHDisplay);
-    p->CrtcHBlankEnd = max(p->CrtcHSyncEnd, p->CrtcHTotal);
-
-    p->CrtcHAdjusted = FALSE;
-    p->CrtcVAdjusted = FALSE;
-}
-
-/**
- * Allocates and returns a copy of pMode, including pointers within pMode.
- */
-DisplayModePtr
-xf86DuplicateMode(DisplayModePtr pMode)
-{
-    DisplayModePtr pNew;
-
-    pNew = xnfalloc(sizeof(DisplayModeRec));
-    *pNew = *pMode;
-    pNew->next = NULL;
-    pNew->prev = NULL;
-    if (pNew->name == NULL) {
-	xf86SetModeDefaultName(pMode);
-    } else {
-	pNew->name = xnfstrdup(pMode->name);
-    }
-
-    return pNew;
-}
-
-/**
- * Duplicates every mode in the given list and returns a pointer to the first
- * mode.
- *
- * \param modeList doubly-linked mode list
- */
-DisplayModePtr
-xf86DuplicateModes(ScrnInfoPtr pScrn, DisplayModePtr modeList)
-{
-    DisplayModePtr first = NULL, last = NULL;
-    DisplayModePtr mode;
-
-    for (mode = modeList; mode != NULL; mode = mode->next) {
-	DisplayModePtr new;
-
-	new = xf86DuplicateMode(mode);
-
-	/* Insert pNew into modeList */
-	if (last) {
-	    last->next = new;
-	    new->prev = last;
-	} else {
-	    first = new;
-	    new->prev = NULL;
-	}
-	new->next = NULL;
-	last = new;
-    }
-
-    return first;
-}
-
-/**
- * Returns true if the given modes should program to the same timings.
- *
- * This doesn't use Crtc values, as it might be used on ModeRecs without the
- * Crtc values set.  So, it's assumed that the other numbers are enough.
- *
- * This isn't in xf86Modes.c, but it might deserve to be there.
- */
-Bool
-xf86ModesEqual(DisplayModePtr pMode1, DisplayModePtr pMode2)
-{
-     if (pMode1->Clock == pMode2->Clock &&
-	 pMode1->HDisplay == pMode2->HDisplay &&
-	 pMode1->HSyncStart == pMode2->HSyncStart &&
-	 pMode1->HSyncEnd == pMode2->HSyncEnd &&
-	 pMode1->HTotal == pMode2->HTotal &&
-	 pMode1->HSkew == pMode2->HSkew &&
-	 pMode1->VDisplay == pMode2->VDisplay &&
-	 pMode1->VSyncStart == pMode2->VSyncStart &&
-	 pMode1->VSyncEnd == pMode2->VSyncEnd &&
-	 pMode1->VTotal == pMode2->VTotal &&
-	 pMode1->VScan == pMode2->VScan &&
-	 pMode1->Flags == pMode2->Flags)
-     {
-	return TRUE;
-     } else {
-	return FALSE;
-     }
-}
-
-/* exact copy of xf86Mode.c */
-static void
-add(char **p, char *new)
-{
-    *p = xnfrealloc(*p, strlen(*p) + strlen(new) + 2);
-    strcat(*p, " ");
-    strcat(*p, new);
-}
-
-/**
- * Print out a modeline.
- *
- * Convenient VRefresh printing was added, though, compared to xf86Mode.c
- */
-void
-xf86PrintModeline(int scrnIndex,DisplayModePtr mode)
-{
-    char tmp[256];
-    char *flags = xnfcalloc(1, 1);
-
-    if (mode->HSkew) { 
-	snprintf(tmp, 256, "hskew %i", mode->HSkew); 
-	add(&flags, tmp);
-    }
-    if (mode->VScan) { 
-	snprintf(tmp, 256, "vscan %i", mode->VScan); 
-	add(&flags, tmp);
-    }
-    if (mode->Flags & V_INTERLACE) add(&flags, "interlace");
-    if (mode->Flags & V_CSYNC) add(&flags, "composite");
-    if (mode->Flags & V_DBLSCAN) add(&flags, "doublescan");
-    if (mode->Flags & V_BCAST) add(&flags, "bcast");
-    if (mode->Flags & V_PHSYNC) add(&flags, "+hsync");
-    if (mode->Flags & V_NHSYNC) add(&flags, "-hsync");
-    if (mode->Flags & V_PVSYNC) add(&flags, "+vsync");
-    if (mode->Flags & V_NVSYNC) add(&flags, "-vsync");
-    if (mode->Flags & V_PCSYNC) add(&flags, "+csync");
-    if (mode->Flags & V_NCSYNC) add(&flags, "-csync");
-#if 0
-    if (mode->Flags & V_CLKDIV2) add(&flags, "vclk/2");
-#endif
-    xf86DrvMsg(scrnIndex, X_INFO,
-		   "Modeline \"%s\"x%.01f  %6.2f  %i %i %i %i  %i %i %i %i%s "
-		   "(%.01f kHz)\n",
-		   mode->name, mode->VRefresh, mode->Clock/1000., mode->HDisplay,
-		   mode->HSyncStart, mode->HSyncEnd, mode->HTotal,
-		   mode->VDisplay, mode->VSyncStart, mode->VSyncEnd,
-		   mode->VTotal, flags, xf86ModeHSync(mode));
-    xfree(flags);
-}
-#endif /* XORG_VERSION_CURRENT <= 7.2.99.2 */
-
-/**
- * Marks as bad any modes with unsupported flags.
- *
- * \param modeList doubly-linked or circular list of modes.
- * \param flags flags supported by the driver.
- *
- * \bug only V_INTERLACE and V_DBLSCAN are supported.  Is that enough?
- *
- * This is not in xf86Modes.c, but would be part of the proposed new API.
- */
-void
-xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,
-			    int flags)
-{
-    DisplayModePtr mode;
-
-    for (mode = modeList; mode != NULL; mode = mode->next) {
-	if (mode->Flags & V_INTERLACE && !(flags & V_INTERLACE))
-	    mode->status = MODE_NO_INTERLACE;
-	if (mode->Flags & V_DBLSCAN && !(flags & V_DBLSCAN))
-	    mode->status = MODE_NO_DBLESCAN;
-    }
-}
-
-/**
- * Marks as bad any modes extending beyond the given max X, Y, or pitch.
- *
- * \param modeList doubly-linked or circular list of modes.
- *
- * This is not in xf86Modes.c, but would be part of the proposed new API.
- */
-void
-xf86ValidateModesSize(ScrnInfoPtr pScrn, DisplayModePtr modeList,
-			  int maxX, int maxY, int maxPitch)
-{
-    DisplayModePtr mode;
-
-    for (mode = modeList; mode != NULL; mode = mode->next) {
-	if (maxPitch > 0 && mode->HDisplay > maxPitch)
-	    mode->status = MODE_BAD_WIDTH;
-
-	if (maxX > 0 && mode->HDisplay > maxX)
-	    mode->status = MODE_VIRTUAL_X;
-
-	if (maxY > 0 && mode->VDisplay > maxY)
-	    mode->status = MODE_VIRTUAL_Y;
-
-	if (mode->next == modeList)
-	    break;
-    }
-}
-
-/**
- * Marks as bad any modes that aren't supported by the given monitor's
- * hsync and vrefresh ranges.
- *
- * \param modeList doubly-linked or circular list of modes.
- *
- * This is not in xf86Modes.c, but would be part of the proposed new API.
- */
-void
-xf86ValidateModesSync(ScrnInfoPtr pScrn, DisplayModePtr modeList,
-			  MonPtr mon)
-{
-    DisplayModePtr mode;
-
-    for (mode = modeList; mode != NULL; mode = mode->next) {
-	Bool bad;
-	int i;
-
-	bad = TRUE;
-	for (i = 0; i < mon->nHsync; i++) {
-	    if (xf86ModeHSync(mode) >= mon->hsync[i].lo &&
-		xf86ModeHSync(mode) <= mon->hsync[i].hi)
-	    {
-		bad = FALSE;
-	    }
-	}
-	if (bad)
-	    mode->status = MODE_HSYNC;
-
-	bad = TRUE;
-	for (i = 0; i < mon->nVrefresh; i++) {
-	    if (xf86ModeVRefresh(mode) >= mon->vrefresh[i].lo &&
-		xf86ModeVRefresh(mode) <= mon->vrefresh[i].hi)
-	    {
-		bad = FALSE;
-	    }
-	}
-	if (bad)
-	    mode->status = MODE_VSYNC;
-
-	if (mode->next == modeList)
-	    break;
-    }
-}
-
-/**
- * Marks as bad any modes extending beyond outside of the given clock ranges.
- *
- * \param modeList doubly-linked or circular list of modes.
- * \param min pointer to minimums of clock ranges
- * \param max pointer to maximums of clock ranges
- * \param n_ranges number of ranges.
- *
- * This is not in xf86Modes.c, but would be part of the proposed new API.
- */
-void
-xf86ValidateModesClocks(ScrnInfoPtr pScrn, DisplayModePtr modeList,
-			    int *min, int *max, int n_ranges)
-{
-    DisplayModePtr mode;
-    int i;
-
-    for (mode = modeList; mode != NULL; mode = mode->next) {
-	Bool good = FALSE;
-	for (i = 0; i < n_ranges; i++) {
-	    if (mode->Clock >= min[i] && mode->Clock <= max[i]) {
-		good = TRUE;
-		break;
-	    }
-	}
-	if (!good)
-	    mode->status = MODE_CLOCK_RANGE;
-    }
-}
-
-/**
- * If the user has specified a set of mode names to use, mark as bad any modes
- * not listed.
- *
- * The user mode names specified are prefixes to names of modes, so "1024x768"
- * will match modes named "1024x768", "1024x768x75", "1024x768-good", but
- * "1024x768x75" would only match "1024x768x75" from that list.
- *
- * MODE_BAD is used as the rejection flag, for lack of a better flag.
- *
- * \param modeList doubly-linked or circular list of modes.
- *
- * This is not in xf86Modes.c, but would be part of the proposed new API.
- */
-void
-xf86ValidateModesUserConfig(ScrnInfoPtr pScrn, DisplayModePtr modeList)
-{
-    DisplayModePtr mode;
-
-    if (pScrn->display->modes[0] == NULL)
-	return;
-
-    for (mode = modeList; mode != NULL; mode = mode->next) {
-	int i;
-	Bool good = FALSE;
-
-	for (i = 0; pScrn->display->modes[i] != NULL; i++) {
-	    if (strncmp(pScrn->display->modes[i], mode->name,
-			strlen(pScrn->display->modes[i])) == 0) {
-		good = TRUE;
-		break;
-	    }
-	}
-	if (!good)
-	    mode->status = MODE_BAD;
-    }
-}
-
-
-/**
- * Frees any modes from the list with a status other than MODE_OK.
- *
- * \param modeList pointer to a doubly-linked or circular list of modes.
- * \param verbose determines whether the reason for mode invalidation is
- *	  printed.
- *
- * This is not in xf86Modes.c, but would be part of the proposed new API.
- */
-void
-xf86PruneInvalidModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList,
-			  Bool verbose)
-{
-    DisplayModePtr mode;
-
-    for (mode = *modeList; mode != NULL;) {
-	DisplayModePtr next = mode->next, first = *modeList;
-
-	if (mode->status != MODE_OK) {
-	    if (verbose) {
-		char *type = "";
-		if (mode->type & M_T_BUILTIN)
-		    type = "built-in ";
-		else if (mode->type & M_T_DEFAULT)
-		    type = "default ";
-		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-			   "Not using %smode \"%s\" (%s)\n", type, mode->name,
-			   xf86ModeStatusToString(mode->status));
-	    }
-	    xf86DeleteMode(modeList, mode);
-	}
-
-	if (next == first)
-	    break;
-	mode = next;
-    }
-}
-
-/**
- * Adds the new mode into the mode list, and returns the new list
- *
- * \param modes doubly-linked mode list.
- */
-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;
-}
-
-/**
- * Build a mode list from a list of config file modes
- */
-static DisplayModePtr
-xf86GetConfigModes (XF86ConfModeLinePtr conf_mode)
-{
-    DisplayModePtr  head = NULL, prev = NULL, mode;
-    
-    for (; conf_mode; conf_mode = (XF86ConfModeLinePtr) conf_mode->list.next)
-    {
-        mode = xcalloc(1, sizeof(DisplayModeRec));
-	if (!mode)
-	    continue;
-        mode->name       = xstrdup(conf_mode->ml_identifier);
-	if (!mode->name)
-	{
-	    xfree (mode);
-	    continue;
-	}
-	mode->type       = 0;
-        mode->Clock      = conf_mode->ml_clock;
-        mode->HDisplay   = conf_mode->ml_hdisplay;
-        mode->HSyncStart = conf_mode->ml_hsyncstart;
-        mode->HSyncEnd   = conf_mode->ml_hsyncend;
-        mode->HTotal     = conf_mode->ml_htotal;
-        mode->VDisplay   = conf_mode->ml_vdisplay;
-        mode->VSyncStart = conf_mode->ml_vsyncstart;
-        mode->VSyncEnd   = conf_mode->ml_vsyncend;
-        mode->VTotal     = conf_mode->ml_vtotal;
-        mode->Flags      = conf_mode->ml_flags;
-        mode->HSkew      = conf_mode->ml_hskew;
-        mode->VScan      = conf_mode->ml_vscan;
-
-        mode->prev = prev;
-	mode->next = NULL;
-	if (prev)
-	    prev->next = mode;
-	else
-	    head = mode;
-	prev = mode;
-    }
-    return head;
-}
-
-/**
- * Build a mode list from a monitor configuration
- */
-DisplayModePtr
-xf86GetMonitorModes (ScrnInfoPtr pScrn, XF86ConfMonitorPtr conf_monitor)
-{
-    DisplayModePtr	    modes = NULL;
-    XF86ConfModesLinkPtr    modes_link;
-    
-    if (!conf_monitor)
-	return NULL;
-
-    /*
-     * first we collect the mode lines from the UseModes directive
-     */
-    for (modes_link = conf_monitor->mon_modes_sect_lst; 
-	 modes_link; 
-	 modes_link = modes_link->list.next)
-    {
-	/* If this modes link hasn't been resolved, go look it up now */
-	if (!modes_link->ml_modes)
-	    modes_link->ml_modes = xf86findModes (modes_link->ml_modes_str, 
-						  xf86configptr->conf_modes_lst);
-	if (modes_link->ml_modes)
-	    modes = xf86ModesAdd (modes,
-				  xf86GetConfigModes (modes_link->ml_modes->mon_modeline_lst));
-    }
-
-    return xf86ModesAdd (modes,
-			 xf86GetConfigModes (conf_monitor->mon_modeline_lst));
-}
-
-/**
- * Build a mode list containing all of the default modes
- */
-DisplayModePtr
-xf86GetDefaultModes (Bool interlaceAllowed, Bool doubleScanAllowed)
-{
-    DisplayModePtr  head = NULL, prev = NULL, mode;
-    int		    i;
-
-    for (i = 0; xf86DefaultModes[i].name != NULL; i++)
-    {
-	DisplayModePtr	defMode = &xf86DefaultModes[i];
-	
-	if (!interlaceAllowed && (defMode->Flags & V_INTERLACE))
-	    continue;
-	if (!doubleScanAllowed && (defMode->Flags & V_DBLSCAN))
-	    continue;
-
-	mode = xalloc(sizeof(DisplayModeRec));
-	if (!mode)
-	    continue;
-        memcpy(mode,&xf86DefaultModes[i],sizeof(DisplayModeRec));
-        mode->name = xstrdup(xf86DefaultModes[i].name);
-        if (!mode->name)
-	{
-	    xfree (mode);
-	    continue;
-	}
-        mode->prev = prev;
-	mode->next = NULL;
-	if (prev)
-	    prev->next = mode;
-	else
-	    head = mode;
-	prev = mode;
-    }
-    return head;
-}
diff --git a/src/i830_xf86Modes.h b/src/i830_xf86Modes.h
deleted file mode 100644
index d032199..0000000
--- a/src/i830_xf86Modes.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright © 2006 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Authors:
- *    Eric Anholt <eric at anholt.net>
- *
- */
-
-#ifndef _I830_XF86MODES_H_
-#define _I830_XF86MODES_H_
-#include "xorgVersion.h"
-#include "xf86Parser.h"
-#include "i830_xf86Rename.h"
-
-double xf86ModeHSync(DisplayModePtr mode);
-double xf86ModeVRefresh(DisplayModePtr mode);
-DisplayModePtr xf86DuplicateMode(DisplayModePtr pMode);
-DisplayModePtr xf86DuplicateModes(ScrnInfoPtr pScrn,
-				       DisplayModePtr modeList);
-void xf86SetModeDefaultName(DisplayModePtr mode);
-void xf86SetModeCrtc(DisplayModePtr p, int adjustFlags);
-Bool xf86ModesEqual(DisplayModePtr pMode1, DisplayModePtr pMode2);
-void xf86PrintModeline(int scrnIndex,DisplayModePtr mode);
-DisplayModePtr xf86ModesAdd(DisplayModePtr modes, DisplayModePtr new);
-
-DisplayModePtr xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC);
-DisplayModePtr xf86CVTMode(int HDisplay, int VDisplay, float VRefresh,
-			   Bool Reduced, Bool Interlaced);
-
-void
-xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,
-		       int flags);
-
-void
-xf86ValidateModesClocks(ScrnInfoPtr pScrn, DisplayModePtr modeList,
-			int *min, int *max, int n_ranges);
-
-void
-xf86ValidateModesSize(ScrnInfoPtr pScrn, DisplayModePtr modeList,
-		      int maxX, int maxY, int maxPitch);
-
-void
-xf86ValidateModesSync(ScrnInfoPtr pScrn, DisplayModePtr modeList,
-		      MonPtr mon);
-
-void
-xf86PruneInvalidModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList,
-		      Bool verbose);
-
-void
-xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,
-		       int flags);
-
-void
-xf86ValidateModesUserConfig(ScrnInfoPtr pScrn, DisplayModePtr modeList);
-
-DisplayModePtr
-xf86GetMonitorModes (ScrnInfoPtr pScrn, XF86ConfMonitorPtr conf_monitor);
-
-DisplayModePtr
-xf86GetDefaultModes (Bool interlaceAllowed, Bool doubleScanAllowed);
-
-#endif /* _I830_XF86MODES_H_ */
diff --git a/src/i830_xf86RandR12.c b/src/i830_xf86RandR12.c
deleted file mode 100644
index 4ccbdad..0000000
--- a/src/i830_xf86RandR12.c
+++ /dev/null
@@ -1,950 +0,0 @@
-/* $XdotOrg: xc/programs/Xserver/hw/xfree86/common/xf86RandR.c,v 1.3 2004/07/30 21:53:09 eich Exp $ */
-/*
- * $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86RandR.c,v 1.7tsi Exp $
- *
- * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
- *
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "xf86.h"
-#include "os.h"
-#include "mibank.h"
-#include "globals.h"
-#include "xf86.h"
-#include "xf86Priv.h"
-#include "xf86DDC.h"
-#include "mipointer.h"
-#include "windowstr.h"
-#include <randrstr.h>
-#include <X11/extensions/render.h>
-
-#include "i830_xf86Crtc.h"
-#include "i830_xf86RandR12.h"
-
-typedef struct _xf86RandR12Info {
-    int				    virtualX;
-    int				    virtualY;
-    int				    mmWidth;
-    int				    mmHeight;
-    int				    maxX;
-    int				    maxY;
-    Rotation			    rotation; /* current mode */
-    Rotation                        supported_rotations; /* driver supported */
-} XF86RandRInfoRec, *XF86RandRInfoPtr;
-
-#ifdef RANDR_12_INTERFACE
-static Bool xf86RandR12Init12 (ScreenPtr pScreen);
-static Bool xf86RandR12CreateScreenResources12 (ScreenPtr pScreen);
-#endif
-
-static int	    xf86RandR12Index;
-static int	    xf86RandR12Generation;
-
-#define XF86RANDRINFO(p) \
-	((XF86RandRInfoPtr)(p)->devPrivates[xf86RandR12Index].ptr)
-
-static int
-xf86RandR12ModeRefresh (DisplayModePtr mode)
-{
-    if (mode->VRefresh)
-	return (int) (mode->VRefresh + 0.5);
-    else
-	return (int) (mode->Clock * 1000.0 / mode->HTotal / mode->VTotal + 0.5);
-}
-
-static Bool
-xf86RandR12GetInfo (ScreenPtr pScreen, Rotation *rotations)
-{
-    RRScreenSizePtr	    pSize;
-    ScrnInfoPtr		    scrp = XF86SCRNINFO(pScreen);
-    XF86RandRInfoPtr	    randrp = XF86RANDRINFO(pScreen);
-    DisplayModePtr	    mode;
-    int			    refresh0 = 60;
-    int			    maxX = 0, maxY = 0;
-
-    *rotations = randrp->supported_rotations;
-
-    if (randrp->virtualX == -1 || randrp->virtualY == -1)
-    {
-	randrp->virtualX = scrp->virtualX;
-	randrp->virtualY = scrp->virtualY;
-    }
-
-    /* Re-probe the outputs for new monitors or modes */
-    xf86ProbeOutputModes (scrp, 0, 0);
-    xf86SetScrnInfoModes (scrp);
-    xf86DiDGAReInit (pScreen);
-
-    for (mode = scrp->modes; ; mode = mode->next)
-    {
-	int refresh = xf86RandR12ModeRefresh (mode);
-	if (randrp->maxX == 0 || randrp->maxY == 0)
-	{
-		if (maxX < mode->HDisplay)
-			maxX = mode->HDisplay;
-		if (maxY < mode->VDisplay)
-			maxY = mode->VDisplay;
-	}
-	if (mode == scrp->modes)
-	    refresh0 = refresh;
-	pSize = RRRegisterSize (pScreen,
-				mode->HDisplay, mode->VDisplay,
-				randrp->mmWidth, randrp->mmHeight);
-	if (!pSize)
-	    return FALSE;
-	RRRegisterRate (pScreen, pSize, refresh);
-
-	if (xf86ModesEqual(mode, scrp->currentMode) &&
-	    mode->HDisplay == scrp->virtualX &&
-	    mode->VDisplay == scrp->virtualY)
-	{
-	    RRSetCurrentConfig (pScreen, randrp->rotation, refresh, pSize);
-	}
-	if (mode->next == scrp->modes)
-	    break;
-    }
-
-    if (randrp->maxX == 0 || randrp->maxY == 0)
-    {
-	randrp->maxX = maxX;
-	randrp->maxY = maxY;
-    }
-
-    if (scrp->currentMode->HDisplay != randrp->virtualX ||
-	scrp->currentMode->VDisplay != randrp->virtualY)
-    {
-	pSize = RRRegisterSize (pScreen,
-				randrp->virtualX, randrp->virtualY,
-				randrp->mmWidth,
-				randrp->mmHeight);
-	if (!pSize)
-	    return FALSE;
-	RRRegisterRate (pScreen, pSize, refresh0);
-	if (scrp->virtualX == randrp->virtualX &&
-	    scrp->virtualY == randrp->virtualY)
-	{
-	    RRSetCurrentConfig (pScreen, randrp->rotation, refresh0, pSize);
-	}
-    }
-
-    return TRUE;
-}
-
-static Bool
-xf86RandR12SetMode (ScreenPtr	    pScreen,
-		  DisplayModePtr    mode,
-		  Bool		    useVirtual,
-		  int		    mmWidth,
-		  int		    mmHeight)
-{
-    ScrnInfoPtr		scrp = XF86SCRNINFO(pScreen);
-    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
-    int			oldWidth = pScreen->width;
-    int			oldHeight = pScreen->height;
-    int			oldmmWidth = pScreen->mmWidth;
-    int			oldmmHeight = pScreen->mmHeight;
-    WindowPtr		pRoot = WindowTable[pScreen->myNum];
-    DisplayModePtr      currentMode = NULL;
-    Bool 		ret = TRUE;
-    PixmapPtr 		pspix = NULL;
-
-    if (pRoot)
-	(*scrp->EnableDisableFBAccess) (pScreen->myNum, FALSE);
-    if (useVirtual)
-    {
-	scrp->virtualX = randrp->virtualX;
-	scrp->virtualY = randrp->virtualY;
-    }
-    else
-    {
-	scrp->virtualX = mode->HDisplay;
-	scrp->virtualY = mode->VDisplay;
-    }
-
-    if(randrp->rotation & (RR_Rotate_90 | RR_Rotate_270))
-    {
-	/* If the screen is rotated 90 or 270 degrees, swap the sizes. */
-	pScreen->width = scrp->virtualY;
-	pScreen->height = scrp->virtualX;
-	pScreen->mmWidth = mmHeight;
-	pScreen->mmHeight = mmWidth;
-    }
-    else
-    {
-	pScreen->width = scrp->virtualX;
-	pScreen->height = scrp->virtualY;
-	pScreen->mmWidth = mmWidth;
-	pScreen->mmHeight = mmHeight;
-    }
-    if (scrp->currentMode == mode) {
-        /* Save current mode */
-        currentMode = scrp->currentMode;
-        /* Reset, just so we ensure the drivers SwitchMode is called */
-        scrp->currentMode = NULL;
-    }
-    /*
-     * We know that if the driver failed to SwitchMode to the rotated
-     * version, then it should revert back to it's prior mode.
-     */
-    if (!xf86SwitchMode (pScreen, mode))
-    {
-        ret = FALSE;
-	scrp->virtualX = pScreen->width = oldWidth;
-	scrp->virtualY = pScreen->height = oldHeight;
-	pScreen->mmWidth = oldmmWidth;
-	pScreen->mmHeight = oldmmHeight;
-        scrp->currentMode = currentMode;
-    }
-    /*
-     * Get the new Screen pixmap ptr as SwitchMode might have called
-     * ModifyPixmapHeader and xf86EnableDisableFBAccess will put it back...
-     * Unfortunately.
-     */
-    pspix = (*pScreen->GetScreenPixmap) (pScreen);
-    if (pspix->devPrivate.ptr)
-       scrp->pixmapPrivate = pspix->devPrivate;
-
-    /*
-     * Make sure the layout is correct
-     */
-    xf86ReconfigureLayout();
-
-    /*
-     * Make sure the whole screen is visible
-     */
-    xf86SetViewport (pScreen, pScreen->width, pScreen->height);
-    xf86SetViewport (pScreen, 0, 0);
-    if (pRoot)
-	(*scrp->EnableDisableFBAccess) (pScreen->myNum, TRUE);
-    return ret;
-}
-
-Bool
-xf86RandR12SetConfig (ScreenPtr		pScreen,
-		    Rotation		rotation,
-		    int			rate,
-		    RRScreenSizePtr	pSize)
-{
-    ScrnInfoPtr		scrp = XF86SCRNINFO(pScreen);
-    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
-    DisplayModePtr	mode;
-    int			px, py;
-    Bool		useVirtual = FALSE;
-    int			maxX = 0, maxY = 0;
-    Rotation		oldRotation = randrp->rotation;
-
-    randrp->rotation = rotation;
-
-    if (randrp->virtualX == -1 || randrp->virtualY == -1)
-    {
-	randrp->virtualX = scrp->virtualX;
-	randrp->virtualY = scrp->virtualY;
-    }
-
-    miPointerPosition (&px, &py);
-    for (mode = scrp->modes; ; mode = mode->next)
-    {
-	if (randrp->maxX == 0 || randrp->maxY == 0)
-	{
-		if (maxX < mode->HDisplay)
-			maxX = mode->HDisplay;
-		if (maxY < mode->VDisplay)
-			maxY = mode->VDisplay;
-	}
-	if (mode->HDisplay == pSize->width &&
-	    mode->VDisplay == pSize->height &&
-	    (rate == 0 || xf86RandR12ModeRefresh (mode) == rate))
-	    break;
-	if (mode->next == scrp->modes)
-	{
-	    if (pSize->width == randrp->virtualX &&
-		pSize->height == randrp->virtualY)
-	    {
-		mode = scrp->modes;
-		useVirtual = TRUE;
-		break;
-	    }
-    	    if (randrp->maxX == 0 || randrp->maxY == 0)
-    	    {
-		randrp->maxX = maxX;
-		randrp->maxY = maxY;
-    	    }
-	    return FALSE;
-	}
-    }
-
-    if (randrp->maxX == 0 || randrp->maxY == 0)
-    {
-	randrp->maxX = maxX;
-	randrp->maxY = maxY;
-    }
-
-    if (!xf86RandR12SetMode (pScreen, mode, useVirtual, pSize->mmWidth,
-			   pSize->mmHeight)) {
-        randrp->rotation = oldRotation;
-	return FALSE;
-    }
-
-    /*
-     * Move the cursor back where it belongs; SwitchMode repositions it
-     */
-    if (pScreen == miPointerCurrentScreen ())
-    {
-        px = (px >= pScreen->width ? (pScreen->width - 1) : px);
-        py = (py >= pScreen->height ? (pScreen->height - 1) : py);
-
-	xf86SetViewport(pScreen, px, py);
-
-	(*pScreen->SetCursorPosition) (pScreen, px, py, FALSE);
-    }
-
-    return TRUE;
-}
-
-static Bool
-xf86RandR12ScreenSetSize (ScreenPtr	pScreen,
-			CARD16		width,
-			CARD16		height,
-			CARD32		mmWidth,
-			CARD32		mmHeight)
-{
-    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
-    ScrnInfoPtr		pScrn = XF86SCRNINFO(pScreen);
-    WindowPtr		pRoot = WindowTable[pScreen->myNum];
-    Bool 		ret = TRUE;
-
-    if (randrp->virtualX == -1 || randrp->virtualY == -1)
-    {
-	randrp->virtualX = pScrn->virtualX;
-	randrp->virtualY = pScrn->virtualY;
-    }
-    if (pRoot)
-	(*pScrn->EnableDisableFBAccess) (pScreen->myNum, FALSE);
-    pScrn->virtualX = width;
-    pScrn->virtualY = height;
-
-    pScreen->width = pScrn->virtualX;
-    pScreen->height = pScrn->virtualY;
-    pScreen->mmWidth = mmWidth;
-    pScreen->mmHeight = mmHeight;
-
-    xf86SetViewport (pScreen, pScreen->width-1, pScreen->height-1);
-    xf86SetViewport (pScreen, 0, 0);
-    if (pRoot)
-	(*pScrn->EnableDisableFBAccess) (pScreen->myNum, TRUE);
-#if RANDR_12_INTERFACE
-    if (WindowTable[pScreen->myNum])
-	RRScreenSizeNotify (pScreen);
-#endif
-    return ret;
-}
-
-Rotation
-xf86RandR12GetRotation(ScreenPtr pScreen)
-{
-    XF86RandRInfoPtr	    randrp = XF86RANDRINFO(pScreen);
-
-    return randrp->rotation;
-}
-
-Bool
-xf86RandR12CreateScreenResources (ScreenPtr pScreen)
-{
-    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
-    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
-    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
-    int			c;
-    int			width, height;
-    int			mmWidth, mmHeight;
-#ifdef PANORAMIX
-    /* XXX disable RandR when using Xinerama */
-    if (!noPanoramiXExtension)
-	return TRUE;
-#endif
-
-    /*
-     * Compute size of screen
-     */
-    width = 0; height = 0;
-    for (c = 0; c < config->num_crtc; c++)
-    {
-	xf86CrtcPtr crtc = config->crtc[c];
-	int	    crtc_width = crtc->x + crtc->mode.HDisplay;
-	int	    crtc_height = crtc->y + crtc->mode.VDisplay;
-	
-	if (crtc->enabled && crtc_width > width)
-	    width = crtc_width;
-	if (crtc->enabled && crtc_height > height)
-	    height = crtc_height;
-    }
-    
-    if (width && height)
-    {
-	/*
-	 * Compute physical size of screen
-	 */
-	if (monitorResolution) 
-	{
-	    mmWidth = width * 25.4 / monitorResolution;
-	    mmHeight = height * 25.4 / monitorResolution;
-	}
-	else
-	{
-	    mmWidth = pScreen->mmWidth;
-	    mmHeight = pScreen->mmHeight;
-	}
-	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		   "Setting screen physical size to %d x %d\n",
-		   mmWidth, mmHeight);
-	xf86RandR12ScreenSetSize (pScreen,
-				  width,
-				  height,
-				  mmWidth,
-				  mmHeight);
-    }
-
-    if (randrp->virtualX == -1 || randrp->virtualY == -1)
-    {
-	randrp->virtualX = pScrn->virtualX;
-	randrp->virtualY = pScrn->virtualY;
-    }
-#if RANDR_12_INTERFACE
-    if (xf86RandR12CreateScreenResources12 (pScreen))
-	return TRUE;
-#endif
-    return TRUE;
-}
-
-
-Bool
-xf86RandR12Init (ScreenPtr pScreen)
-{
-    rrScrPrivPtr	rp;
-    XF86RandRInfoPtr	randrp;
-
-#ifdef PANORAMIX
-    /* XXX disable RandR when using Xinerama */
-    if (!noPanoramiXExtension)
-	return TRUE;
-#endif
-    if (xf86RandR12Generation != serverGeneration)
-    {
-	xf86RandR12Index = AllocateScreenPrivateIndex();
-	xf86RandR12Generation = serverGeneration;
-    }
-
-    randrp = xalloc (sizeof (XF86RandRInfoRec));
-    if (!randrp)
-	return FALSE;
-
-    if (!RRScreenInit(pScreen))
-    {
-	xfree (randrp);
-	return FALSE;
-    }
-    rp = rrGetScrPriv(pScreen);
-    rp->rrGetInfo = xf86RandR12GetInfo;
-    rp->rrSetConfig = xf86RandR12SetConfig;
-
-    randrp->virtualX = -1;
-    randrp->virtualY = -1;
-    randrp->mmWidth = pScreen->mmWidth;
-    randrp->mmHeight = pScreen->mmHeight;
-
-    randrp->rotation = RR_Rotate_0; /* initial rotated mode */
-
-    randrp->supported_rotations = RR_Rotate_0;
-
-    randrp->maxX = randrp->maxY = 0;
-
-    pScreen->devPrivates[xf86RandR12Index].ptr = randrp;
-
-#if RANDR_12_INTERFACE
-    if (!xf86RandR12Init12 (pScreen))
-	return FALSE;
-#endif
-    return TRUE;
-}
-
-void
-xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotations)
-{
-    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
-    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
-    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
-    int			c;
-
-    randrp->supported_rotations = rotations;
-
-#if RANDR_12_INTERFACE
-    for (c = 0; c < config->num_crtc; c++) {
-	xf86CrtcPtr    crtc = config->crtc[c];
-
-	RRCrtcSetRotations (crtc->randr_crtc, rotations);
-    }
-#endif
-}
-
-void
-xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y)
-{
-    ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
-
-    if (xf86RandR12Generation != serverGeneration ||
-	XF86RANDRINFO(pScreen)->virtualX == -1)
-    {
-	*x = pScrn->virtualX;
-	*y = pScrn->virtualY;
-    } else {
-	XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
-
-	*x = randrp->virtualX;
-	*y = randrp->virtualY;
-    }
-}
-
-#if RANDR_12_INTERFACE
-static Bool
-xf86RandR12CrtcNotify (RRCrtcPtr	randr_crtc)
-{
-    ScreenPtr		pScreen = randr_crtc->pScreen;
-    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
-    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
-    RRModePtr		randr_mode = NULL;
-    int			x;
-    int			y;
-    Rotation		rotation;
-    int			numOutputs;
-    RROutputPtr		*randr_outputs;
-    RROutputPtr		randr_output;
-    xf86CrtcPtr		crtc = randr_crtc->devPrivate;
-    xf86OutputPtr	output;
-    int			i, j;
-    DisplayModePtr	mode = &crtc->mode;
-    Bool		ret;
-
-    randr_outputs = ALLOCATE_LOCAL(config->num_output * sizeof (RROutputPtr));
-    if (!randr_outputs)
-	return FALSE;
-    x = crtc->x;
-    y = crtc->y;
-    rotation = crtc->rotation;
-    numOutputs = 0;
-    randr_mode = NULL;
-    for (i = 0; i < config->num_output; i++)
-    {
-	output = config->output[i];
-	if (output->crtc == crtc)
-	{
-	    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 < randr_output->numModes; j++)
-	    {
-		DisplayModePtr	outMode = randr_output->modes[j]->devPrivate;
-		if (xf86ModesEqual(mode, outMode))
-		{
-		    randr_mode = randr_output->modes[j];
-		    break;
-		}
-	    }
-	}
-    }
-    ret = RRCrtcNotify (randr_crtc, randr_mode, x, y,
-			rotation, numOutputs, randr_outputs);
-    DEALLOCATE_LOCAL(randr_outputs);
-    return ret;
-}
-
-static Bool
-xf86RandR12CrtcSet (ScreenPtr	pScreen,
-		  RRCrtcPtr	randr_crtc,
-		  RRModePtr	randr_mode,
-		  int		x,
-		  int		y,
-		  Rotation	rotation,
-		  int		num_randr_outputs,
-		  RROutputPtr	*randr_outputs)
-{
-    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
-    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
-    xf86CrtcPtr		crtc = randr_crtc->devPrivate;
-    DisplayModePtr	mode = randr_mode ? randr_mode->devPrivate : NULL;
-    Bool		changed = FALSE;
-    int			o, ro;
-    xf86CrtcPtr		*save_crtcs;
-    Bool		save_enabled = crtc->enabled;
-
-    save_crtcs = ALLOCATE_LOCAL(config->num_crtc * sizeof (xf86CrtcPtr));
-    if ((mode != NULL) != crtc->enabled)
-	changed = TRUE;
-    else if (mode && !xf86ModesEqual (&crtc->mode, mode))
-	changed = TRUE;
-    
-    if (rotation != crtc->rotation)
-	changed = TRUE;
-
-    if (x != crtc->x || y != crtc->y)
-	changed = TRUE;
-    for (o = 0; o < config->num_output; o++) 
-    {
-	xf86OutputPtr  output = config->output[o];
-	xf86CrtcPtr    new_crtc;
-
-	save_crtcs[o] = output->crtc;
-	
-	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])
-	    {
-		new_crtc = crtc;
-		break;
-	    }
-	if (new_crtc != output->crtc)
-	{
-	    changed = TRUE;
-	    output->crtc = new_crtc;
-	}
-    }
-    /* XXX need device-independent mode setting code through an API */
-    if (changed)
-    {
-	crtc->enabled = mode != NULL;
-
-	if (mode)
-	{
-	    if (!xf86CrtcSetMode (crtc, mode, rotation, x, y))
-	    {
-		crtc->enabled = save_enabled;
-		for (o = 0; o < config->num_output; o++)
-		{
-		    xf86OutputPtr	output = config->output[o];
-		    output->crtc = save_crtcs[o];
-		}
-		DEALLOCATE_LOCAL(save_crtcs);
-		return FALSE;
-	    }
-	    /*
-	     * Save the last successful setting for EnterVT
-	     */
-	    crtc->desiredMode = *mode;
-	    crtc->desiredRotation = rotation;
-	    crtc->desiredX = x;
-	    crtc->desiredY = y;
-	}
-	xf86DisableUnusedFunctions (pScrn);
-    }
-    DEALLOCATE_LOCAL(save_crtcs);
-    return xf86RandR12CrtcNotify (randr_crtc);
-}
-
-static Bool
-xf86RandR12CrtcSetGamma (ScreenPtr    pScreen,
-			 RRCrtcPtr    randr_crtc)
-{
-    xf86CrtcPtr		crtc = randr_crtc->devPrivate;
-
-    if (crtc->funcs->gamma_set == NULL)
-	return FALSE;
-
-    crtc->funcs->gamma_set(crtc, randr_crtc->gammaRed, randr_crtc->gammaGreen,
-			   randr_crtc->gammaBlue, randr_crtc->gammaSize);
-
-    return TRUE;
-}
-
-static Bool
-xf86RandR12OutputSetProperty (ScreenPtr pScreen,
-			      RROutputPtr randr_output,
-			      Atom property,
-			      RRPropertyValuePtr value)
-{
-    xf86OutputPtr output = randr_output->devPrivate;
-
-    /* If we don't have any property handler, then we don't care what the
-     * user is setting properties to.
-     */
-    if (output->funcs->set_property == NULL)
-	return TRUE;
-
-    return output->funcs->set_property(output, property, value);
-}
-
-/**
- * Given a list of xf86 modes and a RandR Output object, construct
- * RandR modes and assign them to the output
- */
-static Bool
-xf86RROutputSetModes (RROutputPtr randr_output, DisplayModePtr modes)
-{
-    DisplayModePtr  mode;
-    RRModePtr	    *rrmodes = NULL;
-    int		    nmode = 0;
-    int		    npreferred = 0;
-    Bool	    ret = TRUE;
-    int		    pref;
-
-    for (mode = modes; mode; mode = mode->next)
-	nmode++;
-
-    if (nmode) {
-	rrmodes = xalloc (nmode * sizeof (RRModePtr));
-	
-	if (!rrmodes)
-	    return FALSE;
-	nmode = 0;
-
-	for (pref = 1; pref >= 0; pref--) {
-	    for (mode = modes; mode; mode = mode->next) {
-		if ((pref != 0) == ((mode->type & M_T_PREFERRED) != 0)) {
-		    xRRModeInfo		modeInfo;
-		    RRModePtr		rrmode;
-		    
-		    modeInfo.nameLength = strlen (mode->name);
-		    modeInfo.width = mode->HDisplay;
-		    modeInfo.dotClock = mode->Clock * 1000;
-		    modeInfo.hSyncStart = mode->HSyncStart;
-		    modeInfo.hSyncEnd = mode->HSyncEnd;
-		    modeInfo.hTotal = mode->HTotal;
-		    modeInfo.hSkew = mode->HSkew;
-
-		    modeInfo.height = mode->VDisplay;
-		    modeInfo.vSyncStart = mode->VSyncStart;
-		    modeInfo.vSyncEnd = mode->VSyncEnd;
-		    modeInfo.vTotal = mode->VTotal;
-		    modeInfo.modeFlags = mode->Flags;
-
-		    rrmode = RRModeGet (&modeInfo, mode->name);
-		    if (rrmode) {
-			rrmode->devPrivate = mode;
-			rrmodes[nmode++] = rrmode;
-			npreferred += pref;
-		    }
-		}
-	    }
-	}
-    }
-    
-    ret = RROutputSetModes (randr_output, rrmodes, nmode, npreferred);
-    xfree (rrmodes);
-    return ret;
-}
-
-/*
- * Mirror the current mode configuration to RandR
- */
-static Bool
-xf86RandR12SetInfo12 (ScreenPtr pScreen)
-{
-    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
-    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
-    RROutputPtr		*clones;
-    RRCrtcPtr		*crtcs;
-    int			ncrtc;
-    int			o, c, l;
-    RRCrtcPtr		randr_crtc;
-    int			nclone;
-    
-    clones = ALLOCATE_LOCAL(config->num_output * sizeof (RROutputPtr));
-    crtcs = ALLOCATE_LOCAL (config->num_crtc * sizeof (RRCrtcPtr));
-    for (o = 0; o < config->num_output; o++)
-    {
-	xf86OutputPtr	output = config->output[o];
-	
-	ncrtc = 0;
-	for (c = 0; c < config->num_crtc; c++)
-	    if (output->possible_crtcs & (1 << c))
-		crtcs[ncrtc++] = config->crtc[c]->randr_crtc;
-
-	if (output->crtc)
-	    randr_crtc = output->crtc->randr_crtc;
-	else
-	    randr_crtc = NULL;
-
-	if (!RROutputSetCrtcs (output->randr_output, crtcs, ncrtc))
-	{
-	    DEALLOCATE_LOCAL (crtcs);
-	    DEALLOCATE_LOCAL (clones);
-	    return FALSE;
-	}
-
-	RROutputSetCrtc (output->randr_output, randr_crtc);
-	RROutputSetPhysicalSize(output->randr_output, 
-				output->mm_width,
-				output->mm_height);
-	xf86RROutputSetModes (output->randr_output, output->probed_modes);
-
-	switch (output->status) {
-	case XF86OutputStatusConnected:
-	    RROutputSetConnection (output->randr_output, RR_Connected);
-	    break;
-	case XF86OutputStatusDisconnected:
-	    RROutputSetConnection (output->randr_output, RR_Disconnected);
-	    break;
-	case XF86OutputStatusUnknown:
-	    RROutputSetConnection (output->randr_output, RR_UnknownConnection);
-	    break;
-	}
-
-	RROutputSetSubpixelOrder (output->randr_output, output->subpixel_order);
-
-	/*
-	 * Valid clones
-	 */
-	nclone = 0;
-	for (l = 0; l < config->num_output; l++)
-	{
-	    xf86OutputPtr	    clone = config->output[l];
-	    
-	    if (l != o && (output->possible_clones & (1 << l)))
-		clones[nclone++] = clone->randr_output;
-	}
-	if (!RROutputSetClones (output->randr_output, clones, nclone))
-	{
-	    DEALLOCATE_LOCAL (crtcs);
-	    DEALLOCATE_LOCAL (clones);
-	    return FALSE;
-	}
-    }
-    DEALLOCATE_LOCAL (crtcs);
-    DEALLOCATE_LOCAL (clones);
-    return TRUE;
-}
-
-
-
-/*
- * Query the hardware for the current state, then mirror
- * that to RandR
- */
-static Bool
-xf86RandR12GetInfo12 (ScreenPtr pScreen, Rotation *rotations)
-{
-    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
-
-    xf86ProbeOutputModes (pScrn, 0, 0);
-    xf86SetScrnInfoModes (pScrn);
-    xf86DiDGAReInit (pScreen);
-    return xf86RandR12SetInfo12 (pScreen);
-}
-
-static Bool
-xf86RandR12CreateObjects12 (ScreenPtr pScreen)
-{
-    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
-    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
-    int			c;
-    int			o;
-    
-    if (!RRInit ())
-	return FALSE;
-
-    /*
-     * Configure crtcs
-     */
-    for (c = 0; c < config->num_crtc; c++)
-    {
-	xf86CrtcPtr    crtc = config->crtc[c];
-	
-	crtc->randr_crtc = RRCrtcCreate (crtc);
-	RRCrtcAttachScreen (crtc->randr_crtc, pScreen);
-	RRCrtcGammaSetSize (crtc->randr_crtc, 256);
-    }
-    /*
-     * Configure outputs
-     */
-    for (o = 0; o < config->num_output; o++)
-    {
-	xf86OutputPtr	output = config->output[o];
-
-	output->randr_output = RROutputCreate (output->name, 
-					       strlen (output->name),
-					       output);
-	RROutputAttachScreen (output->randr_output, pScreen);
-
-	if (output->funcs->create_resources != NULL)
-	    output->funcs->create_resources(output);
-    }
-    return TRUE;
-}
-
-static Bool
-xf86RandR12CreateScreenResources12 (ScreenPtr pScreen)
-{
-    int			c;
-    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
-    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
-    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
-
-    for (c = 0; c < config->num_crtc; c++)
-	xf86RandR12CrtcNotify (config->crtc[c]->randr_crtc);
-    
-    
-    RRScreenSetSizeRange (pScreen, 320, 240,
-			  randrp->virtualX, randrp->virtualY);
-    return TRUE;
-}
-
-static void
-xf86RandR12PointerMoved (int scrnIndex, int x, int y)
-{
-}
-
-static Bool
-xf86RandR12Init12 (ScreenPtr pScreen)
-{
-    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
-    rrScrPrivPtr	rp = rrGetScrPriv(pScreen);
-
-    rp->rrGetInfo = xf86RandR12GetInfo12;
-    rp->rrScreenSetSize = xf86RandR12ScreenSetSize;
-    rp->rrCrtcSet = xf86RandR12CrtcSet;
-    rp->rrCrtcSetGamma = xf86RandR12CrtcSetGamma;
-    rp->rrOutputSetProperty = xf86RandR12OutputSetProperty;
-    rp->rrSetConfig = NULL;
-    pScrn->PointerMoved = xf86RandR12PointerMoved;
-    if (!xf86RandR12CreateObjects12 (pScreen))
-	return FALSE;
-
-    /*
-     * Configure output modes
-     */
-    if (!xf86RandR12SetInfo12 (pScreen))
-	return FALSE;
-    return TRUE;
-}
-
-#endif
-
-Bool
-xf86RandR12PreInit (ScrnInfoPtr pScrn)
-{
-    return TRUE;
-}
diff --git a/src/i830_xf86RandR12.h b/src/i830_xf86RandR12.h
deleted file mode 100644
index 8a4668b..0000000
--- a/src/i830_xf86RandR12.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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 xf86RandR12CreateScreenResources (ScreenPtr pScreen);
-Bool xf86RandR12Init(ScreenPtr pScreen);
-void xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotation);
-Bool xf86RandR12SetConfig(ScreenPtr pScreen, Rotation rotation, int rate,
-			RRScreenSizePtr pSize);
-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_xf86Rename.h b/src/i830_xf86Rename.h
deleted file mode 100644
index a00253d..0000000
--- a/src/i830_xf86Rename.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * 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 _XF86RENAME_H_
-#define _XF86RENAME_H_
-
-#include "local_xf86Rename.h"
-
-#define xf86CrtcConfigInit XF86NAME(xf86CrtcConfigInit)
-#define xf86CrtcConfigPrivateIndex XF86NAME(xf86CrtcConfigPrivateIndex)
-#define xf86CrtcCreate XF86NAME(xf86CrtcCreate)
-#define xf86CrtcDestroy XF86NAME(xf86CrtcDestroy)
-#define xf86CrtcInUse XF86NAME(xf86CrtcInUse)
-#define xf86CrtcRotate XF86NAME(xf86CrtcRotate)
-#define xf86CrtcSetMode XF86NAME(xf86CrtcSetMode)
-#define xf86CrtcSetSizeRange XF86NAME(xf86CrtcSetSizeRange)
-#define xf86CVTMode XF86NAME(xf86CVTMode)
-#define xf86DisableUnusedFunctions XF86NAME(xf86DisableUnusedFunctions)
-#define xf86DPMSSet XF86NAME(xf86DPMSSet)
-#define xf86DuplicateMode XF86NAME(xf86DuplicateMode)
-#define xf86DuplicateModes XF86NAME(xf86DuplicateModes)
-#define xf86GetDefaultModes XF86NAME(xf86GetDefaultModes)
-#define xf86GetMonitorModes XF86NAME(xf86GetMonitorModes)
-#define xf86InitialConfiguration XF86NAME(xf86InitialConfiguration)
-#define xf86ModeHSync XF86NAME(xf86ModeHSync)
-#define xf86ModesAdd XF86NAME(xf86ModesAdd)
-#define xf86ModesEqual XF86NAME(xf86ModesEqual)
-#define xf86ModeVRefresh XF86NAME(xf86ModeVRefresh)
-#define xf86OutputCreate XF86NAME(xf86OutputCreate)
-#define xf86OutputDestroy XF86NAME(xf86OutputDestroy)
-#define xf86OutputGetEDID XF86NAME(xf86OutputGetEDID)
-#define xf86OutputGetEDIDModes XF86NAME(xf86OutputGetEDIDModes)
-#define xf86OutputRename XF86NAME(xf86OutputRename)
-#define xf86OutputSetEDID XF86NAME(xf86OutputSetEDID)
-#define xf86PrintModeline XF86NAME(xf86PrintModeline)
-#define xf86ProbeOutputModes XF86NAME(xf86ProbeOutputModes)
-#define xf86PruneInvalidModes XF86NAME(xf86PruneInvalidModes)
-#define xf86SetModeCrtc XF86NAME(xf86SetModeCrtc)
-#define xf86SetModeDefaultName XF86NAME(xf86SetModeDefaultName)
-#define xf86SetScrnInfoModes XF86NAME(xf86SetScrnInfoModes)
-#define xf86ValidateModesClocks XF86NAME(xf86ValidateModesClocks)
-#define xf86ValidateModesFlags XF86NAME(xf86ValidateModesFlags)
-#define xf86ValidateModesSize XF86NAME(xf86ValidateModesSize)
-#define xf86ValidateModesSync XF86NAME(xf86ValidateModesSync)
-#define xf86ValidateModesUserConfig XF86NAME(xf86ValidateModesUserConfig)
-#define xf86DiDGAInit XF86NAME(xf86DiDGAInit)
-#define xf86DiDGAReInit XF86NAME(xf86DiDGAReInit)
-#define xf86DDCGetModes XF86NAME(xf86DDCGetModes)
-#define xf86RandR12CreateScreenResources XF86NAME(xf86RandR12CreateScreenResources)
-#define xf86RandR12GetOriginalVirtualSize XF86NAME(xf86RandR12GetOriginalVirtualSize)
-#define xf86RandR12GetRotation XF86NAME(xf86RandR12GetRotation)
-#define xf86RandR12Init XF86NAME(xf86RandR12Init)
-#define xf86RandR12PreInit XF86NAME(xf86RandR12PreInit)
-#define xf86RandR12SetConfig XF86NAME(xf86RandR12SetConfig)
-#define xf86RandR12SetRotations XF86NAME(xf86RandR12SetRotations)
-#define xf86SaveScreen XF86NAME(xf86SaveScreen)
-
-#endif /* _XF86RENAME_H_ */
diff --git a/src/i830_xf86Rotate.c b/src/i830_xf86Rotate.c
deleted file mode 100644
index 8240f67..0000000
--- a/src/i830_xf86Rotate.c
+++ /dev/null
@@ -1,402 +0,0 @@
-/*
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stddef.h>
-#include <string.h>
-#include <stdio.h>
-
-#include "xf86.h"
-#include "xf86DDC.h"
-#include "fb.h"
-#include "windowstr.h"
-#include "i830_xf86Crtc.h"
-#include "i830_xf86Modes.h"
-#include "i830_xf86RandR12.h"
-#include "X11/extensions/render.h"
-#define DPMS_SERVER
-#include "X11/extensions/dpms.h"
-#include "X11/Xatom.h"
-
-static int
-mode_height (DisplayModePtr mode, Rotation rotation)
-{
-    switch (rotation & 0xf) {
-    case RR_Rotate_0:
-    case RR_Rotate_180:
-	return mode->VDisplay;
-    case RR_Rotate_90:
-    case RR_Rotate_270:
-	return mode->HDisplay;
-    default:
-	return 0;
-    }
-}
-
-static int
-mode_width (DisplayModePtr mode, Rotation rotation)
-{
-    switch (rotation & 0xf) {
-    case RR_Rotate_0:
-    case RR_Rotate_180:
-	return mode->HDisplay;
-    case RR_Rotate_90:
-    case RR_Rotate_270:
-	return mode->VDisplay;
-    default:
-	return 0;
-    }
-}
-
-/* borrowed from composite extension, move to Render and publish? */
-
-static VisualPtr
-compGetWindowVisual (WindowPtr pWin)
-{
-    ScreenPtr	    pScreen = pWin->drawable.pScreen;
-    VisualID	    vid = wVisual (pWin);
-    int		    i;
-
-    for (i = 0; i < pScreen->numVisuals; i++)
-	if (pScreen->visuals[i].vid == vid)
-	    return &pScreen->visuals[i];
-    return 0;
-}
-
-static PictFormatPtr
-compWindowFormat (WindowPtr pWin)
-{
-    ScreenPtr	pScreen = pWin->drawable.pScreen;
-    
-    return PictureMatchVisual (pScreen, pWin->drawable.depth,
-			       compGetWindowVisual (pWin));
-}
-
-static void
-xf86RotateBox (BoxPtr dst, BoxPtr src, Rotation rotation,
-	       int dest_width, int dest_height)
-{
-    switch (rotation & 0xf) {
-    default:
-    case RR_Rotate_0:
-	*dst = *src;
-	break;
-    case RR_Rotate_90:
-	dst->x1 = src->y1;
-	dst->y1 = dest_height - src->x2;
-	dst->x2 = src->y2;
-	dst->y2 = dest_height - src->x1;
-	break;
-    case RR_Rotate_180:
-	dst->x1 = dest_width - src->x2;
-	dst->y1 = dest_height - src->y2;
-	dst->x2 = dest_width - src->x1;
-	dst->y2 = dest_height - src->y1;
-	break;
-    case RR_Rotate_270:
-	dst->x1 = dest_width - src->y2;
-	dst->y1 = src->x1;
-	dst->y2 = src->x2;
-	dst->x2 = dest_width - src->y1;
-	break;
-    }
-    if (rotation & RR_Reflect_X) {
-	int x1 = dst->x1;
-	dst->x1 = dest_width - dst->x2;
-	dst->x2 = dest_width - x1;
-    }
-    if (rotation & RR_Reflect_Y) {
-	int y1 = dst->y1;
-	dst->y1 = dest_height - dst->y2;
-	dst->y2 = dest_height - y1;
-    }
-}
-
-static void
-xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region)
-{
-    ScrnInfoPtr		scrn = crtc->scrn;
-    ScreenPtr		screen = scrn->pScreen;
-    WindowPtr		root = WindowTable[screen->myNum];
-    PixmapPtr		dst_pixmap = crtc->rotatedPixmap;
-    PictFormatPtr	format = compWindowFormat (WindowTable[screen->myNum]);
-    int			error;
-    PicturePtr		src, dst;
-    PictTransform	transform;
-    int			n = REGION_NUM_RECTS(region);
-    BoxPtr		b = REGION_RECTS(region);
-    XID			include_inferiors = IncludeInferiors;
-    
-    src = CreatePicture (None,
-			 &root->drawable,
-			 format,
-			 CPSubwindowMode,
-			 &include_inferiors,
-			 serverClient,
-			 &error);
-    if (!src) {
-	ErrorF("couldn't create src pict\n");
-	return;
-    }
-    dst = CreatePicture (None,
-			 &dst_pixmap->drawable,
-			 format,
-			 0L,
-			 NULL,
-			 serverClient,
-			 &error);
-    if (!dst) {
-	ErrorF("couldn't create src pict\n");
-	return;
-    }
-
-    memset (&transform, '\0', sizeof (transform));
-    transform.matrix[2][2] = IntToxFixed(1);
-    transform.matrix[0][2] = IntToxFixed(crtc->x);
-    transform.matrix[1][2] = IntToxFixed(crtc->y);
-    switch (crtc->rotation & 0xf) {
-    default:
-    case RR_Rotate_0:
-	transform.matrix[0][0] = IntToxFixed(1);
-	transform.matrix[1][1] = IntToxFixed(1);
-	break;
-    case RR_Rotate_90:
-	transform.matrix[0][1] = IntToxFixed(-1);
-	transform.matrix[1][0] = IntToxFixed(1);
-	transform.matrix[0][2] += IntToxFixed(crtc->mode.VDisplay);
-	break;
-    case RR_Rotate_180:
-	transform.matrix[0][0] = IntToxFixed(-1);
-	transform.matrix[1][1] = IntToxFixed(-1);
-	transform.matrix[0][2] += IntToxFixed(crtc->mode.HDisplay);
-	transform.matrix[1][2] += IntToxFixed(crtc->mode.VDisplay);
-	break;
-    case RR_Rotate_270:
-	transform.matrix[0][1] = IntToxFixed(1);
-	transform.matrix[1][0] = IntToxFixed(-1);
-	transform.matrix[1][2] += IntToxFixed(crtc->mode.HDisplay);
-	break;
-    }
-
-    /* handle reflection */
-    if (crtc->rotation & RR_Reflect_X)
-    {
-	/* XXX figure this out */
-    }
-    if (crtc->rotation & RR_Reflect_Y)
-    {
-	/* XXX figure this out too */
-    }
-
-    error = SetPictureTransform (src, &transform);
-    if (error) {
-	ErrorF("Couldn't set transform\n");
-	return;
-    }
-
-    while (n--)
-    {
-	BoxRec	dst_box;
-
-	xf86RotateBox (&dst_box, b, crtc->rotation,
-		       crtc->mode.HDisplay, crtc->mode.VDisplay);
-	CompositePicture (PictOpSrc,
-			  src, NULL, dst,
-			  dst_box.x1, dst_box.y1, 0, 0, dst_box.x1, dst_box.y1,
-			  dst_box.x2 - dst_box.x1,
-			  dst_box.y2 - dst_box.y1);
-	b++;
-    }
-    FreePicture (src, None);
-    FreePicture (dst, None);
-}
-
-static void
-xf86RotateRedisplay(ScreenPtr pScreen)
-{
-    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-    DamagePtr		damage = xf86_config->rotationDamage;
-    RegionPtr		region;
-
-    if (!damage)
-	return;
-    region = DamageRegion(damage);
-    if (REGION_NOTEMPTY(pScreen, region)) 
-    {
-	int		    c;
-	
-	for (c = 0; c < xf86_config->num_crtc; c++)
-	{
-	    xf86CrtcPtr	    crtc = xf86_config->crtc[c];
-
-	    if (crtc->rotation != RR_Rotate_0)
-	    {
-		BoxRec	    box;
-		RegionRec   crtc_damage;
-
-		/* compute portion of damage that overlaps crtc */
-		box.x1 = crtc->x;
-		box.x2 = crtc->x + mode_width (&crtc->mode, crtc->rotation);
-		box.y1 = crtc->y;
-		box.y2 = crtc->y + mode_height (&crtc->mode, crtc->rotation);
-		REGION_INIT(pScreen, &crtc_damage, &box, 1);
-		REGION_INTERSECT (pScreen, &crtc_damage, &crtc_damage, region);
-		
-		/* update damaged region */
-		if (REGION_NOTEMPTY(pScreen, &crtc_damage))
-    		    xf86RotateCrtcRedisplay (crtc, &crtc_damage);
-		
-		REGION_UNINIT (pScreen, &crtc_damage);
-	    }
-	}
-	DamageEmpty(damage);
-    }
-}
-
-static void
-xf86RotateBlockHandler(pointer data, OSTimePtr pTimeout, pointer pRead)
-{
-    ScreenPtr pScreen = (ScreenPtr) data;
-
-    xf86RotateRedisplay(pScreen);
-}
-
-static void
-xf86RotateWakeupHandler(pointer data, int i, pointer LastSelectMask)
-{
-}
-
-Bool
-xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
-{
-    ScrnInfoPtr		pScrn = crtc->scrn;
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-    ScreenPtr		pScreen = pScrn->pScreen;
-    
-    if (rotation == RR_Rotate_0)
-    {
-	/* Free memory from rotation */
-	if (crtc->rotatedPixmap)
-	{
-	    crtc->funcs->shadow_destroy (crtc, crtc->rotatedPixmap);
-	    crtc->rotatedPixmap = NULL;
-	}
-
-	if (xf86_config->rotationDamage)
-	{
-	    /* Free damage structure */
-	    DamageUnregister (&(*pScreen->GetScreenPixmap)(pScreen)->drawable,
-			      xf86_config->rotationDamage);
-	    DamageDestroy (xf86_config->rotationDamage);
-	    xf86_config->rotationDamage = NULL;
-	    /* Free block/wakeup handler */
-	    RemoveBlockAndWakeupHandlers (xf86RotateBlockHandler,
-					  xf86RotateWakeupHandler,
-					  (pointer) pScreen);
-	}
-    }
-    else
-    {
-	/* 
-	 * these are the size of the shadow pixmap, which
-	 * matches the mode, not the pre-rotated copy in the
-	 * frame buffer
-	 */
-	int	    width = mode->HDisplay;
-	int	    height = mode->VDisplay;
-	PixmapPtr   shadow = crtc->rotatedPixmap;
-	int	    old_width = shadow ? shadow->drawable.width : 0;
-	int	    old_height = shadow ? shadow->drawable.height : 0;
-	BoxRec	    damage_box;
-	RegionRec   damage_region;
-	
-	/* Allocate memory for rotation */
-	if (old_width != width || old_height != height)
-	{
-	    if (shadow)
-	    {
-		crtc->funcs->shadow_destroy (crtc, shadow);
-		crtc->rotatedPixmap = NULL;
-	    }
-	    shadow = crtc->funcs->shadow_create (crtc, width, height);
-	    if (!shadow)
-		goto bail1;
-	    crtc->rotatedPixmap = shadow;
-	}
-	
-	if (!xf86_config->rotationDamage)
-	{
-	    /* Create damage structure */
-	    xf86_config->rotationDamage = DamageCreate (NULL, NULL,
-						DamageReportNone,
-						TRUE, pScreen, pScreen);
-	    if (!xf86_config->rotationDamage)
-		goto bail2;
-	    
-	    /* Hook damage to screen pixmap */
-	    DamageRegister (&(*pScreen->GetScreenPixmap)(pScreen)->drawable,
-			    xf86_config->rotationDamage);
-	    
-	    /* Assign block/wakeup handler */
-	    if (!RegisterBlockAndWakeupHandlers (xf86RotateBlockHandler,
-						 xf86RotateWakeupHandler,
-						 (pointer) pScreen))
-	    {
-		goto bail3;
-	    }
-	    damage_box.x1 = 0;
-	    damage_box.y1 = 0;
-	    damage_box.x2 = mode_width (mode, rotation);
-	    damage_box.y2 = mode_height (mode, rotation);
-	    REGION_INIT (pScreen, &damage_region, &damage_box, 1);
-	    DamageDamageRegion (&(*pScreen->GetScreenPixmap)(pScreen)->drawable,
-				&damage_region);
-	    REGION_UNINIT (pScreen, &damage_region);
-	}
-	if (0)
-	{
-bail3:
-	    DamageDestroy (xf86_config->rotationDamage);
-	    xf86_config->rotationDamage = NULL;
-	    
-bail2:
-	    if (shadow)
-	    {
-		crtc->funcs->shadow_destroy (crtc, shadow);
-		crtc->rotatedPixmap = NULL;
-	    }
-bail1:
-	    if (old_width && old_height)
-		crtc->rotatedPixmap = crtc->funcs->shadow_create (crtc,
-								  old_width,
-								  old_height);
-	    return FALSE;
-	}
-    }
-    
-    /* All done */
-    return TRUE;
-}
diff --git a/src/i830_xf86cvt.c b/src/i830_xf86cvt.c
deleted file mode 100644
index 1a2b786..0000000
--- a/src/i830_xf86cvt.c
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * Copyright 2005-2006 Luc Verhaegen.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * @file This is a copy of xf86cvt.c from the X Server, for compatibility with
- * old servers (pre-1.2).
- */
-
-/*
- * The reason for having this function in a file of its own is
- * so that ../utils/cvt/cvt can link to it, and that xf86CVTMode
- * code is shared directly.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "xf86.h"
-
-#include "i830.h"
-#include "i830_display.h"
-#include <string.h>
-
-#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0)
-/*
- * Generate a CVT standard mode from HDisplay, VDisplay and VRefresh.
- *
- * These calculations are stolen from the CVT calculation spreadsheet written
- * by Graham Loveridge. He seems to be claiming no copyright and there seems to
- * be no license attached to this. He apparently just wants to see his name
- * mentioned.
- *
- * This file can be found at http://www.vesa.org/Public/CVT/CVTd6r1.xls
- *
- * Comments and structure corresponds to the comments and structure of the xls.
- * This should ease importing of future changes to the standard (not very
- * likely though).
- *
- * About margins; i'm sure that they are to be the bit between HDisplay and
- * HBlankStart, HBlankEnd and HTotal, VDisplay and VBlankStart, VBlankEnd and 
- * VTotal, where the overscan colour is shown. FB seems to call _all_ blanking
- * outside sync "margin" for some reason. Since we prefer seeing proper
- * blanking instead of the overscan colour, and since the Crtc* values will
- * probably get altered after us, we will disable margins altogether. With
- * these calculations, Margins will plainly expand H/VDisplay, and we don't
- * want that. -- libv
- *
- */
-_X_EXPORT DisplayModePtr
-xf86CVTMode(int HDisplay, int VDisplay, float VRefresh, Bool Reduced,
-	    Bool Interlaced)
-{
-    DisplayModeRec  *Mode = xnfalloc(sizeof(DisplayModeRec));
-
-    /* 1) top/bottom margin size (% of height) - default: 1.8 */
-#define CVT_MARGIN_PERCENTAGE 1.8    
-
-    /* 2) character cell horizontal granularity (pixels) - default 8 */
-#define CVT_H_GRANULARITY 8
-
-    /* 4) Minimum vertical porch (lines) - default 3 */
-#define CVT_MIN_V_PORCH 3
-
-    /* 4) Minimum number of vertical back porch lines - default 6 */
-#define CVT_MIN_V_BPORCH 6
-
-    /* Pixel Clock step (kHz) */
-#define CVT_CLOCK_STEP 250
-
-    Bool Margins = FALSE;
-    float  VFieldRate, HPeriod;
-    int  HDisplayRnd, HMargin;
-    int  VDisplayRnd, VMargin, VSync;
-    float  Interlace; /* Please rename this */
-
-    memset(Mode, 0, sizeof(DisplayModeRec));
-
-    /* CVT default is 60.0Hz */
-    if (!VRefresh)
-        VRefresh = 60.0;
-
-    /* 1. Required field rate */
-    if (Interlaced)
-        VFieldRate = VRefresh * 2;
-    else
-        VFieldRate = VRefresh;
-
-    /* 2. Horizontal pixels */
-    HDisplayRnd = HDisplay - (HDisplay % CVT_H_GRANULARITY);
-
-    /* 3. Determine left and right borders */
-    if (Margins) {
-        /* right margin is actually exactly the same as left */
-        HMargin = (((float) HDisplayRnd) * CVT_MARGIN_PERCENTAGE / 100.0);
-        HMargin -= HMargin % CVT_H_GRANULARITY;
-    } else
-        HMargin = 0;
-
-    /* 4. Find total active pixels */
-    Mode->HDisplay = HDisplayRnd + 2*HMargin;
-
-    /* 5. Find number of lines per field */
-    if (Interlaced)
-        VDisplayRnd = VDisplay / 2;
-    else
-        VDisplayRnd = VDisplay;
-
-    /* 6. Find top and bottom margins */
-    /* nope. */
-    if (Margins)
-        /* top and bottom margins are equal again. */
-        VMargin = (((float) VDisplayRnd) * CVT_MARGIN_PERCENTAGE / 100.0);
-    else
-        VMargin = 0;
-
-    Mode->VDisplay = VDisplay + 2*VMargin;
-
-    /* 7. Interlace */
-    if (Interlaced)
-        Interlace = 0.5;
-    else
-        Interlace = 0.0;
-
-    /* Determine VSync Width from aspect ratio */
-    if (!(VDisplay % 3) && ((VDisplay * 4 / 3) == HDisplay))
-        VSync = 4;
-    else if (!(VDisplay % 9) && ((VDisplay * 16 / 9) == HDisplay))
-        VSync = 5;
-    else if (!(VDisplay % 10) && ((VDisplay * 16 / 10) == HDisplay))
-        VSync = 6;
-    else if (!(VDisplay % 4) && ((VDisplay * 5 / 4) == HDisplay))
-        VSync = 7;
-    else if (!(VDisplay % 9) && ((VDisplay * 15 / 9) == HDisplay))
-        VSync = 7;
-    else /* Custom */
-        VSync = 10;
-
-    if (!Reduced) { /* simplified GTF calculation */
-
-        /* 4) Minimum time of vertical sync + back porch interval (µs) 
-         * default 550.0 */
-#define CVT_MIN_VSYNC_BP 550.0
-
-        /* 3) Nominal HSync width (% of line period) - default 8 */
-#define CVT_HSYNC_PERCENTAGE 8
-
-        float  HBlankPercentage;
-        int  VSyncAndBackPorch, VBackPorch;
-        int  HBlank;
-
-        /* 8. Estimated Horizontal period */
-        HPeriod = ((float) (1000000.0 / VFieldRate - CVT_MIN_VSYNC_BP)) / 
-            (VDisplayRnd + 2 * VMargin + CVT_MIN_V_PORCH + Interlace);
-
-        /* 9. Find number of lines in sync + backporch */
-        if (((int)(CVT_MIN_VSYNC_BP / HPeriod) + 1) < (VSync + CVT_MIN_V_PORCH))
-            VSyncAndBackPorch = VSync + CVT_MIN_V_PORCH;
-        else
-            VSyncAndBackPorch = (int)(CVT_MIN_VSYNC_BP / HPeriod) + 1;
-
-        /* 10. Find number of lines in back porch */
-        VBackPorch = VSyncAndBackPorch - VSync;
-
-        /* 11. Find total number of lines in vertical field */
-        Mode->VTotal = VDisplayRnd + 2 * VMargin + VSyncAndBackPorch + Interlace
-            + CVT_MIN_V_PORCH;
-
-        /* 5) Definition of Horizontal blanking time limitation */
-        /* Gradient (%/kHz) - default 600 */
-#define CVT_M_FACTOR 600
-
-        /* Offset (%) - default 40 */
-#define CVT_C_FACTOR 40
-
-        /* Blanking time scaling factor - default 128 */
-#define CVT_K_FACTOR 128
-
-        /* Scaling factor weighting - default 20 */
-#define CVT_J_FACTOR 20
-
-#define CVT_M_PRIME CVT_M_FACTOR * CVT_K_FACTOR / 256
-#define CVT_C_PRIME (CVT_C_FACTOR - CVT_J_FACTOR) * CVT_K_FACTOR / 256 + \
-        CVT_J_FACTOR
-
-        /* 12. Find ideal blanking duty cycle from formula */
-        HBlankPercentage = CVT_C_PRIME - CVT_M_PRIME * HPeriod/1000.0;
-
-        /* 13. Blanking time */
-        if (HBlankPercentage < 20)
-            HBlankPercentage = 20;
-
-        HBlank = Mode->HDisplay * HBlankPercentage/(100.0 - HBlankPercentage);
-        HBlank -= HBlank % (2*CVT_H_GRANULARITY);
-        
-        /* 14. Find total number of pixels in a line. */
-        Mode->HTotal = Mode->HDisplay + HBlank;
-
-        /* Fill in HSync values */
-        Mode->HSyncEnd = Mode->HDisplay + HBlank / 2;
-
-        Mode->HSyncStart = Mode->HSyncEnd - 
-            (Mode->HTotal * CVT_HSYNC_PERCENTAGE) / 100;
-        Mode->HSyncStart += CVT_H_GRANULARITY - 
-            Mode->HSyncStart % CVT_H_GRANULARITY;
-
-        /* Fill in VSync values */
-        Mode->VSyncStart = Mode->VDisplay + CVT_MIN_V_PORCH;
-        Mode->VSyncEnd = Mode->VSyncStart + VSync;
-
-    } else { /* Reduced blanking */
-        /* Minimum vertical blanking interval time (µs) - default 460 */
-#define CVT_RB_MIN_VBLANK 460.0
-
-        /* Fixed number of clocks for horizontal sync */
-#define CVT_RB_H_SYNC 32.0
-
-        /* Fixed number of clocks for horizontal blanking */
-#define CVT_RB_H_BLANK 160.0
-
-        /* Fixed number of lines for vertical front porch - default 3 */
-#define CVT_RB_VFPORCH 3
-
-        int  VBILines;
-
-        /* 8. Estimate Horizontal period. */
-        HPeriod = ((float) (1000000.0 / VFieldRate - CVT_RB_MIN_VBLANK)) / 
-            (VDisplayRnd + 2*VMargin);
-
-        /* 9. Find number of lines in vertical blanking */
-        VBILines = ((float) CVT_RB_MIN_VBLANK) / HPeriod + 1;
-
-        /* 10. Check if vertical blanking is sufficient */
-        if (VBILines < (CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH))
-            VBILines = CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH;
-        
-        /* 11. Find total number of lines in vertical field */
-        Mode->VTotal = VDisplayRnd + 2 * VMargin + Interlace + VBILines;
-
-        /* 12. Find total number of pixels in a line */
-        Mode->HTotal = Mode->HDisplay + CVT_RB_H_BLANK;
-
-        /* Fill in HSync values */
-        Mode->HSyncEnd = Mode->HDisplay + CVT_RB_H_BLANK / 2;
-        Mode->HSyncStart = Mode->HSyncEnd - CVT_RB_H_SYNC;
-
-        /* Fill in VSync values */
-        Mode->VSyncStart = Mode->VDisplay + CVT_RB_VFPORCH;
-        Mode->VSyncEnd = Mode->VSyncStart + VSync;
-    }
-
-    /* 15/13. Find pixel clock frequency (kHz for xf86) */
-    Mode->Clock = Mode->HTotal * 1000.0 / HPeriod;
-    Mode->Clock -= Mode->Clock % CVT_CLOCK_STEP;
-
-    /* 16/14. Find actual Horizontal Frequency (kHz) */
-    Mode->HSync = ((float) Mode->Clock) / ((float) Mode->HTotal);
-
-    /* 17/15. Find actual Field rate */
-    Mode->VRefresh = (1000.0 * ((float) Mode->Clock)) / 
-        ((float) (Mode->HTotal * Mode->VTotal));
-
-    /* 18/16. Find actual vertical frame frequency */
-    /* ignore - just set the mode flag for interlaced */
-    if (Interlaced)
-        Mode->VTotal *= 2;
-
-    {
-        char  Name[256];
-        Name[0] = 0;
-
-        snprintf(Name, 256, "%dx%d", HDisplay, VDisplay);
-
-        Mode->name = xnfalloc(strlen(Name) + 1);
-        memcpy(Mode->name, Name, strlen(Name) + 1);
-    }
-
-    if (Reduced)
-        Mode->Flags |= V_PHSYNC | V_NVSYNC;
-    else
-        Mode->Flags |= V_NHSYNC | V_PVSYNC;
-
-    if (Interlaced)
-        Mode->Flags |= V_INTERLACE;
-
-    return Mode;
-}
-#endif /* XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0) */
diff-tree 20e146a09e3b4907a6800588ebfa787bfc5b0d89 (from 17e38e39a49b2a96e31cca4a0b922631c5f7879e)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Fri Feb 16 00:57:44 2007 -0800

    Change rotation pixmap creation API to permit start-time rotation.
    
    Start time rotation requires that the pixmap be created after the server has
    initialized the screens. Delay the pixmap creation until the first block
    handler invocation.

diff --git a/src/Makefile.am b/src/Makefile.am
index 3f680c7..f656270 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -25,11 +25,9 @@ SUBDIRS = xvmc bios_reader ch7017 ch7xxx
 # -avoid-version prevents gratuitous .0.0.0 version numbers on the end
 # _ladir passes a dummy rpath to libtool so the thing will actually link
 # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
-AM_CFLAGS = @WARN_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@ \
+AM_CFLAGS = @WARN_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@ -Iparser -Imodes \
 	-DI830_XV -DI830_USE_XAA -DI830_USE_EXA -DXF86_MODES_RENAME
 
-AM_INCLUDES=-Iparser -Imodes
-
 intel_drv_la_LTLIBRARIES = intel_drv.la
 intel_drv_la_LDFLAGS = -module -avoid-version
 intel_drv_ladir = @moduledir@/drivers
diff --git a/src/i830.h b/src/i830.h
index 26d16e9..f52f149 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -58,8 +58,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "xf86int10.h"
 #include "vbe.h"
 #include "vgaHW.h"
-#include "i830_xf86Crtc.h"
-#include "i830_xf86RandR12.h"
+#include "xf86Crtc.h"
+#include "xf86RandR12.h"
 
 #ifdef XF86DRI
 #include "xf86drm.h"
diff --git a/src/i830_crt.c b/src/i830_crt.c
index 573e652..7706165 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -31,7 +31,7 @@
 
 #include "xf86.h"
 #include "i830.h"
-#include "i830_xf86Modes.h"
+#include "xf86Modes.h"
 #include "i830_display.h"
 
 static void
diff --git a/src/i830_display.c b/src/i830_display.c
index f44a8bf..e7a5605 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -41,7 +41,7 @@
 #include "i830_bios.h"
 #include "i830_display.h"
 #include "i830_debug.h"
-#include "i830_xf86Modes.h"
+#include "xf86Modes.h"
 
 typedef struct {
     /* given values */    
@@ -342,9 +342,8 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x,
     int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE);
     int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
 
-    if (crtc->rotatedPixmap != NULL) {
-	Start = (char *)crtc->rotatedPixmap->devPrivate.ptr -
-	    (char *)pI830->FbBase;
+    if (crtc->rotatedData != NULL) {
+	Start = (char *)crtc->rotatedData - (char *)pI830->FbBase;
     } else if (I830IsPrimary(pScrn)) {
 	Start = pI830->FrontBuffer.Start;
     } else {
@@ -931,21 +930,18 @@ i830_crtc_gamma_set(xf86CrtcPtr crtc, CA
 }
 
 /**
- * Creates a locked-in-framebuffer pixmap of the given width and height for
- * this CRTC's rotated shadow framebuffer.
- *
- * The current implementation uses fixed buffers allocated at startup at the
- * maximal size.
+ * Allocates memory for a locked-in-framebuffer shadow of the given
+ * width and height for this CRTC's rotated shadow framebuffer.
  */
-static PixmapPtr
-i830_crtc_shadow_create(xf86CrtcPtr crtc, int width, int height)
+ 
+static void *
+i830_crtc_shadow_allocate (xf86CrtcPtr crtc, int width, int height)
 {
     ScrnInfoPtr pScrn = crtc->scrn;
     ScreenPtr pScreen = pScrn->pScreen;
     I830Ptr pI830 = I830PTR(pScrn);
     I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
     unsigned long rotate_pitch;
-    PixmapPtr rotate_pixmap;
     unsigned long rotate_offset;
     int align = KB(4), size;
 
@@ -994,12 +990,32 @@ i830_crtc_shadow_create(xf86CrtcPtr crtc
     }
 #endif /* I830_USE_XAA */
 
+    return pI830->FbBase + rotate_offset;
+}
+    
+/**
+ * Creates a pixmap for this CRTC's rotated shadow framebuffer.
+ */
+static PixmapPtr
+i830_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
+{
+    ScrnInfoPtr pScrn = crtc->scrn;
+    I830Ptr pI830 = I830PTR(pScrn);
+    unsigned long rotate_pitch;
+    PixmapPtr rotate_pixmap;
+
+    if (!data)
+	data = i830_crtc_shadow_allocate (crtc, width, height);
+    
+    rotate_pitch = pI830->displayWidth * pI830->cpp;
+
     rotate_pixmap = GetScratchPixmapHeader(pScrn->pScreen,
 					   width, height,
 					   pScrn->depth,
 					   pScrn->bitsPerPixel,
 					   rotate_pitch,
-					   pI830->FbBase + rotate_offset);
+					   data);
+
     if (rotate_pixmap == NULL) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		   "Couldn't allocate shadow pixmap for rotated CRTC\n");
@@ -1008,25 +1024,30 @@ i830_crtc_shadow_create(xf86CrtcPtr crtc
 }
 
 static void
-i830_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap)
+i830_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
 {
     ScrnInfoPtr pScrn = crtc->scrn;
     I830Ptr pI830 = I830PTR(pScrn);
     I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
 
-    FreeScratchPixmapHeader(rotate_pixmap);
+    if (rotate_pixmap)
+	FreeScratchPixmapHeader(rotate_pixmap);
+    
+    if (data)
+    {
 #ifdef I830_USE_EXA
-    if (pI830->useEXA && intel_crtc->rotate_mem_exa != NULL) {
-	exaOffscreenFree(pScrn->pScreen, intel_crtc->rotate_mem_exa);
-	intel_crtc->rotate_mem_exa = NULL;
-    }
+	if (pI830->useEXA && intel_crtc->rotate_mem_exa != NULL) {
+	    exaOffscreenFree(pScrn->pScreen, intel_crtc->rotate_mem_exa);
+	    intel_crtc->rotate_mem_exa = NULL;
+	}
 #endif /* I830_USE_EXA */
 #ifdef I830_USE_XAA
-    if (!pI830->useEXA) {
-	xf86FreeOffscreenLinear(intel_crtc->rotate_mem_xaa);
-	intel_crtc->rotate_mem_xaa = NULL;
-    }
+	if (!pI830->useEXA) {
+	    xf86FreeOffscreenLinear(intel_crtc->rotate_mem_xaa);
+	    intel_crtc->rotate_mem_xaa = NULL;
+	}
 #endif /* I830_USE_XAA */
+    }
 }
 
 
@@ -1272,6 +1293,7 @@ static const xf86CrtcFuncsRec i830_crtc_
     .mode_set = i830_crtc_mode_set,
     .gamma_set = i830_crtc_gamma_set,
     .shadow_create = i830_crtc_shadow_create,
+    .shadow_allocate = i830_crtc_shadow_allocate,
     .shadow_destroy = i830_crtc_shadow_destroy,
     .destroy = NULL, /* XXX */
 };
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 56903e1..e46c057 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2695,6 +2695,30 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 
    DPRINTF(PFX, "assert( if(!I830EnterVT(scrnIndex, 0)) )\n");
 
+   if (!pI830->useEXA) {
+      if (I830IsPrimary(pScrn)) {
+	 if (!I830InitFBManager(pScreen, &(pI830->FbMemBox))) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Failed to init memory manager\n");
+	 }
+
+	 if (pI830->LinearAlloc &&
+	     xf86InitFBManagerLinear(pScreen,
+				     pI830->LinearMem.Offset / pI830->cpp,
+				     pI830->LinearMem.Size / pI830->cpp))
+	 {
+            xf86DrvMsg(scrnIndex, X_INFO,
+		       "Using %ld bytes of offscreen memory for linear "
+		       "(offset=0x%lx)\n", pI830->LinearMem.Size,
+		       pI830->LinearMem.Offset);
+	 }
+      } else {
+	 if (!I830InitFBManager(pScreen, &(pI8301->FbMemBox2))) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Failed to init memory manager\n");
+	 }
+      }
+   }
    if (!I830EnterVT(scrnIndex, 0))
       return FALSE;
 
@@ -2731,30 +2755,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 
    DPRINTF(PFX,
 	   "assert( if(!I830InitFBManager(pScreen, &(pI830->FbMemBox))) )\n");
-   if (!pI830->useEXA) {
-      if (I830IsPrimary(pScrn)) {
-	 if (!I830InitFBManager(pScreen, &(pI830->FbMemBox))) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		       "Failed to init memory manager\n");
-	 }
-
-	 if (pI830->LinearAlloc &&
-	     xf86InitFBManagerLinear(pScreen,
-				     pI830->LinearMem.Offset / pI830->cpp,
-				     pI830->LinearMem.Size / pI830->cpp))
-	 {
-            xf86DrvMsg(scrnIndex, X_INFO,
-		       "Using %ld bytes of offscreen memory for linear "
-		       "(offset=0x%lx)\n", pI830->LinearMem.Size,
-		       pI830->LinearMem.Offset);
-	 }
-      } else {
-	 if (!I830InitFBManager(pScreen, &(pI8301->FbMemBox2))) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		       "Failed to init memory manager\n");
-	 }
-      }
-   }
 
    if (!pI830->noAccel) {
       if (!I830AccelInit(pScreen)) {
diff --git a/src/i830_modes.c b/src/i830_modes.c
index 405dcc6..06921a5 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -52,7 +52,7 @@
 #include "X11/Xatom.h"
 #include "i830.h"
 #include "i830_display.h"
-#include "i830_xf86Modes.h"
+#include "xf86Modes.h"
 #include <randrstr.h>
 
 DisplayModePtr
diff-tree 17e38e39a49b2a96e31cca4a0b922631c5f7879e (from 8e7bc4b1f95f5d62ff18cd94f14f5e3949ef6a29)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Thu Feb 15 23:09:43 2007 -0800

    Enable mode setting function renames from shared code.

diff --git a/src/Makefile.am b/src/Makefile.am
index e3a0fcc..3f680c7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -26,7 +26,7 @@ SUBDIRS = xvmc bios_reader ch7017 ch7xxx
 # _ladir passes a dummy rpath to libtool so the thing will actually link
 # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
 AM_CFLAGS = @WARN_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@ \
-	-DI830_XV -DI830_USE_XAA -DI830_USE_EXA
+	-DI830_XV -DI830_USE_XAA -DI830_USE_EXA -DXF86_MODES_RENAME
 
 AM_INCLUDES=-Iparser -Imodes
 
diff-tree 8e7bc4b1f95f5d62ff18cd94f14f5e3949ef6a29 (from 6e33c4c44030e05d6d07ca9274cfe4d6df2c0387)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Thu Feb 15 11:17:53 2007 -0800

    Use server sources for crtc/output generic code.
    
    As sources for these have been merged to the server, use them from the
    server source code instead of keeping copies in this driver.

diff --git a/configure.ac b/configure.ac
index d45185a..e0d828e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -70,6 +70,42 @@ AC_ARG_ENABLE(video-debug, AC_HELP_STRIN
               [VIDEO_DEBUG="$enableval"],
               [VIDEO_DEBUG=no])
 
+AC_ARG_WITH(xserver-source,AC_HELP_STRING([--with-xserver-source=XSERVER_SOURCE],
+					  [Path to X server source tree]),
+			   [ XSERVER_SOURCE="$withval" ],
+			   [ XSERVER_SOURCE="" ])
+
+
+PKG_CHECK_MODULES(XORG_XSERVER, xorg-server >= 1.2.99, [XMODES=yes], [XMODES=no])
+
+AM_CONDITIONAL(XMODES, [test "x$XMODES" = xyes])
+
+if test "x$XMODES" = xyes; then
+	AC_DEFINE(XMODES, 1,[X server as built-in mode code])
+else
+	if test "x$XSERVER_SOURCE" = x; then
+		if test -d ../../xserver; then
+			XSERVER_SOURCE="`cd ../../xserver && pwd`"
+		fi
+	fi
+	
+	if test "x$XSERVER_SOURCE" = x; then
+		AC_MSG_ERROR([Must have X server >= 1.3 source tree for mode setting code. Please specify --with-xserver-source])
+	fi
+	
+	if test -f src/modes/xf86Crtc.h; then
+		:
+	else
+		ln -s $XSERVER_SOURCE/hw/xfree86/modes src/modes
+	fi
+	
+	if test -f src/parser/xf86Parser.h; then
+		:
+	else
+		ln -s $XSERVER_SOURCE/hw/xfree86/parser src/parser
+	fi
+
+fi
 
 # Checks for extensions
 XORG_DRIVER_CHECK_EXT(XINERAMA, xineramaproto)
diff --git a/src/Makefile.am b/src/Makefile.am
index 982a959..e3a0fcc 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -28,6 +28,8 @@ SUBDIRS = xvmc bios_reader ch7017 ch7xxx
 AM_CFLAGS = @WARN_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@ \
 	-DI830_XV -DI830_USE_XAA -DI830_USE_EXA
 
+AM_INCLUDES=-Iparser -Imodes
+
 intel_drv_la_LTLIBRARIES = intel_drv.la
 intel_drv_la_LDFLAGS = -module -avoid-version
 intel_drv_ladir = @moduledir@/drivers
@@ -86,20 +88,20 @@ intel_drv_la_SOURCES = \
 	 i830_render.c \
 	 i915_render.c \
 	 i965_render.c \
-	 i830_xf86Rename.h \
 	 local_xf86Rename.h \
-	 xf86Parser.h \
-	 xf86Optrec.h \
-	 i830_xf86Modes.h \
-	 i830_xf86Modes.c \
-	 i830_xf86cvt.c \
-	 i830_xf86Crtc.h \
-	 i830_xf86Crtc.c \
-         i830_xf86EdidModes.c \
-	 i830_xf86RandR12.c \
-	 i830_xf86RandR12.h \
-	 i830_xf86Rotate.c \
-	 i830_xf86DiDGA.c
+	 parser/xf86Rename.h \
+	 parser/xf86Parser.h \
+	 parser/xf86Optrec.h \
+	 modes/xf86Modes.h \
+	 modes/xf86Modes.c \
+	 modes/xf86cvt.c \
+	 modes/xf86Crtc.h \
+	 modes/xf86Crtc.c \
+         modes/xf86EdidModes.c \
+	 modes/xf86RandR12.c \
+	 modes/xf86RandR12.h \
+	 modes/xf86Rotate.c \
+	 modes/xf86DiDGA.c
 
 EXTRA_DIST = \
 	packed_yuv_sf.g4a \
diff-tree 6e33c4c44030e05d6d07ca9274cfe4d6df2c0387 (from 4541150cdce3f2f83b8530d0863aecf28c6610a9)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Feb 15 09:54:43 2007 -0800

    Print the correct meaning of bit 30 of pipeconf for 965 in debug output.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index 2c06056..455c226 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -1690,6 +1690,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define PIPEACONF_ENABLE	(1<<31)
 #define PIPEACONF_DISABLE	0
 #define PIPEACONF_DOUBLE_WIDE	(1<<30)
+#define I965_PIPECONF_ACTIVE	(1<<30)
 #define PIPEACONF_SINGLE_WIDE	0
 #define PIPEACONF_PIPE_UNLOCKED 0
 #define PIPEACONF_PIPE_LOCKED	(1<<25)
diff --git a/src/i830_debug.c b/src/i830_debug.c
index e0be0a4..6716eaa 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -69,8 +69,12 @@ DEBUGSTRING(i830_debug_dspcntr)
 DEBUGSTRING(i830_debug_pipeconf)
 {
     char *enabled = val & PIPEACONF_ENABLE ? "enabled" : "disabled";
-    char *wide = val & PIPEACONF_DOUBLE_WIDE ? "double-wide" : "single-wide";
-    return XNFprintf("%s, %s", enabled, wide);
+    char *bit30;
+    if (IS_I965G(pI830))
+	bit30 = val & I965_PIPECONF_ACTIVE ? "active" : "inactive";
+    else
+	bit30 = val & PIPEACONF_DOUBLE_WIDE ? "double-wide" : "single-wide";
+    return XNFprintf("%s, %s", enabled, bit30);
 }
 
 DEBUGSTRING(i830_debug_hvtotal)
diff-tree 4541150cdce3f2f83b8530d0863aecf28c6610a9 (from d1be0dc4e9d443dcbd218a083cfb21a0b5d634ee)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Feb 15 09:51:04 2007 -0800

    Detect core clock frequencies, to avoid double-wide mode when possible.
    
    Additionally, don't attempt to set double-wide on the 965, where there is
    no such thing any more (not that we'd ever see modes high enough to trigger
    it).

diff --git a/src/i810_reg.h b/src/i810_reg.h
index 68cce93..2c06056 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -1848,6 +1848,19 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define I852_GME				0x2
 #define I852_GM					0x5
 
+#define I915_GCFGC			0xf0
+#define I915_LOW_FREQUENCY_ENABLE		(1 << 7)
+#define I915_DISPLAY_CLOCK_190_200_MHZ		(0 << 4)
+#define I915_DISPLAY_CLOCK_333_MHZ		(4 << 4)
+#define I915_DISPLAY_CLOCK_MASK			(7 << 4)
+
+#define I855_HPLLCC			0xc0
+#define I855_CLOCK_CONTROL_MASK			(3 << 0)
+#define I855_CLOCK_133_200			(0 << 0)
+#define I855_CLOCK_100_200			(1 << 0)
+#define I855_CLOCK_100_133			(2 << 0)
+#define I855_CLOCK_166_250			(3 << 0)
+
 /* BLT commands */
 #define COLOR_BLT_CMD		((2<<29)|(0x40<<22)|(0x3))
 #define COLOR_BLT_WRITE_ALPHA	(1<<21)
diff --git a/src/i830_display.c b/src/i830_display.c
index 345eea9..f44a8bf 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -591,6 +591,59 @@ i830_crtc_mode_fixup(xf86CrtcPtr crtc, D
     return TRUE;
 }
 
+/** Returns the core display clock speed for i830 - i945 */
+static int
+i830_get_core_clock_speed(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    /* Core clock values taken from the published datasheets.
+     * The 830 may go up to 166 Mhz, which we should check.
+     */
+    if (IS_I945G(pI830))
+	return 400000;
+    else if (IS_I915G(pI830))
+	return 333000;
+    else if (IS_I945GM(pI830) || IS_845G(pI830))
+	return 200000;
+    else if (IS_I915GM(pI830)) {
+	CARD16 gcfgc = pciReadWord(pI830->PciTag, I915_GCFGC);
+
+	if (gcfgc & I915_LOW_FREQUENCY_ENABLE)
+	    return 133000;
+	else {
+	    switch (gcfgc & I915_DISPLAY_CLOCK_MASK) {
+	    case I915_DISPLAY_CLOCK_333_MHZ:
+		return 333000;
+	    default:
+	    case I915_DISPLAY_CLOCK_190_200_MHZ:
+		return 190000;
+	    }
+	}
+    } else if (IS_I865G(pI830))
+	return 266000;
+    else if (IS_I855(pI830)) {
+	PCITAG bridge = pciTag(0, 0, 0); /* This is always the host bridge */
+	CARD16 hpllcc = pciReadWord(bridge, I855_HPLLCC);
+
+	/* Assume that the hardware is in the high speed state.  This
+	 * should be the default.
+	 */
+	switch (hpllcc & I855_CLOCK_CONTROL_MASK) {
+	case I855_CLOCK_133_200:
+	case I855_CLOCK_100_200:
+	    return 200000;
+	case I855_CLOCK_166_250:
+	    return 250000;
+	case I855_CLOCK_100_133:
+	    return 133000;
+	}
+    } else /* 852, 830 */
+	return 133000;
+
+    return 0; /* Silence gcc warning */
+}
+
 /**
  * Sets up registers for the given mode/adjusted_mode pair.
  *
@@ -749,23 +802,15 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
 	dspcntr |= DISPPLANE_SEL_PIPE_B;
 
     pipeconf = INREG(pipeconf_reg);
-    if (pipe == 0) 
+    if (pipe == 0 && !IS_I965G(pI830))
     {
-	/*
-	 * The docs say this is needed when the dot clock is > 90% of the
-	 * core speed. Core speeds are indicated by bits in the PCI
-	 * config space, but that's a pain to go read, so we just guess
-	 * based on the hardware age. AGP hardware is assumed to run
-	 * at 133MHz while PCI-E hardware is assumed to run at 200MHz
+	/* Enable pixel doubling when the dot clock is > 90% of the (display)
+	 * core speed.
+	 *
+	 * XXX: No double-wide on 915GM pipe B. Is that the only reason for the
+	 * pipe == 0 check?
 	 */
-	int core_clock;
-	
-	if (IS_I9XX(pI830))
-	    core_clock = 200000;
-	else
-	    core_clock = 133000;
-	
-	if (mode->Clock > core_clock * 9 / 10)
+	if (mode->Clock > i830_get_core_clock_speed(pScrn) * 9 / 10)
 	    pipeconf |= PIPEACONF_DOUBLE_WIDE;
 	else
 	    pipeconf &= ~PIPEACONF_DOUBLE_WIDE;
diff-tree d1be0dc4e9d443dcbd218a083cfb21a0b5d634ee (from c010d28f0a91a9831d366ea490878ef3d958021f)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Thu Feb 15 11:03:12 2007 +0800

    EXA: fix i965 default color (0,0,0,1.0) -> (0,0,0,0)
    
    (0,0,0,1.0) is actually black...

diff --git a/src/i965_render.c b/src/i965_render.c
index 8474c48..5c3f61d 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -698,7 +698,7 @@ i965_prepare_composite(int op, PicturePt
     default_color_state->color[0] = 0.0; /* R */
     default_color_state->color[1] = 0.0; /* G */
     default_color_state->color[2] = 0.0; /* B */
-    default_color_state->color[3] = 1.0; /* A */
+    default_color_state->color[3] = 0.0; /* A */
 
     src_sampler_state->ss0.default_color_mode = 0; /* GL mode */
 
diff-tree c010d28f0a91a9831d366ea490878ef3d958021f (from ec55dd16c4c5f7612d33ae22a6249b3b1c60e2b6)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Thu Feb 15 11:00:06 2007 +0800

    EXA: mask componentAlpha support
    
    we're getting load of multiple sf/wm programs for i965, might
    need to be cleanup in future.

diff --git a/src/exa_wm_maskca.g4a b/src/exa_wm_maskca.g4a
new file mode 100644
index 0000000..fa923f6
--- /dev/null
+++ b/src/exa_wm_maskca.g4a
@@ -0,0 +1,202 @@
+/*
+ * This's for exa composite operation in no mask picture case.
+ * The simplest case is just sending what src picture has to dst picture.
+ * XXX: This is still experimental, and should be fixed to support multiple texture
+ * map, and conditional mul actions. 
+ */
+
+/* I think this should be same as in g4a program for texture video,
+   as we also use 16-pixel dispatch. and SF scale in g3 is useful for us. */
+
+/* The initial payload of the thread is always g0.
+ * WM_URB (incoming URB entries) is g3
+   As mask texture coeffient needs extra setup urb starting from g4, we should
+   shift this location. 
+
+ * X0_R is g4->g6
+ * X1_R is g5->g7
+ * Y0_R is g6->g8
+ * Y1_R is g7->g9
+
+     * X0: {ss0.x, ss0.x+1, ss0.x,   ss0.x+1, ss1.x, ss1.x+1, ss1.x,   ss1.x+y}
+     * Y0: {ss0.y, ss0.y,   ss0.y+1, ss0.y+1, ss1.y, ss1.y,   ss1.y+1, ss1.y+1}
+     * X1: {ss2.x, ss2.x+1, ss2.x,   ss2.x+1, ss3.x, ss3.x+1, ss3.x,   ss3.x+y}
+     * Y1: {ss2.y, ss2.y,   ss2.y+1, ss2.y+1, ss3.y, ss3.y,   ss3.y+1, ss3.y+1}
+ */
+
+/* multitexture program with src and mask texture */
+/* - load src texture */
+/* - load mask texture */
+/* - mul src.X with mask's alpha */
+/* - write out src.X */
+
+    /* Set up ss0.x coordinates*/
+mov (1) g6<1>F g1.8<0,1,0>UW { align1 };
+add (1) g6.4<1>F g1.8<0,1,0>UW 1UB { align1 };
+mov (1) g6.8<1>F g1.8<0,1,0>UW { align1 };
+add (1) g6.12<1>F g1.8<0,1,0>UW 1UB { align1 };
+    /* Set up ss0.y coordinates */
+mov (1) g8<1>F g1.10<0,1,0>UW { align1 };
+mov (1) g8.4<1>F g1.10<0,1,0>UW { align1 };
+add (1) g8.8<1>F g1.10<0,1,0>UW 1UB { align1 };
+add (1) g8.12<1>F g1.10<0,1,0>UW 1UB { align1 };
+    /* set up ss1.x coordinates */
+mov (1) g6.16<1>F g1.12<0,1,0>UW { align1 };
+add (1) g6.20<1>F g1.12<0,1,0>UW 1UB { align1 };
+mov (1) g6.24<1>F g1.12<0,1,0>UW { align1 };
+add (1) g6.28<1>F g1.12<0,1,0>UW 1UB { align1 };
+    /* set up ss1.y coordinates */
+mov (1) g8.16<1>F g1.14<0,1,0>UW { align1 };
+mov (1) g8.20<1>F g1.14<0,1,0>UW { align1 };
+add (1) g8.24<1>F g1.14<0,1,0>UW 1UB { align1 };
+add (1) g8.28<1>F g1.14<0,1,0>UW 1UB { align1 };
+    /* Set up ss2.x coordinates */
+mov (1) g7<1>F g1.16<0,1,0>UW { align1 };
+add (1) g7.4<1>F g1.16<0,1,0>UW 1UB { align1 };
+mov (1) g7.8<1>F g1.16<0,1,0>UW { align1 };
+add (1) g7.12<1>F g1.16<0,1,0>UW 1UB { align1 };
+    /* Set up ss2.y coordinates */
+mov (1) g9<1>F g1.18<0,1,0>UW { align1 };
+mov (1) g9.4<1>F g1.18<0,1,0>UW { align1 };
+add (1) g9.8<1>F g1.18<0,1,0>UW 1UB { align1 };
+add (1) g9.12<1>F g1.18<0,1,0>UW 1UB { align1 };
+    /* Set up ss3.x coordinates */
+mov (1) g7.16<1>F g1.20<0,1,0>UW { align1 };
+add (1) g7.20<1>F g1.20<0,1,0>UW 1UB { align1 };
+mov (1) g7.24<1>F g1.20<0,1,0>UW { align1 };
+add (1) g7.28<1>F g1.20<0,1,0>UW 1UB { align1 };
+    /* Set up ss3.y coordinates */
+mov (1) g9.16<1>F g1.22<0,1,0>UW { align1 };
+mov (1) g9.20<1>F g1.22<0,1,0>UW { align1 };
+add (1) g9.24<1>F g1.22<0,1,0>UW 1UB { align1 };
+add (1) g9.28<1>F g1.22<0,1,0>UW 1UB { align1 };
+
+    /* Now, map these screen space coordinates into texture coordinates. */
+/* This is for src texture */
+/* I don't want to change origin ssX coords, as it will be used later in mask */
+/* so store tex coords in g10, g11, g12, g13 */
+
+    /* subtract screen-space X origin of vertex 0. */
+add (8) g10<1>F g6<8,8,1>F -g1<0,1,0>F { align1 };
+add (8) g11<1>F g7<8,8,1>F -g1<0,1,0>F { align1 };
+    /* scale by texture X increment */
+/* Cx[0] */
+mul (8) g10<1>F g10<8,8,1>F g3<0,1,0>F { align1 };
+mul (8) g11<1>F g11<8,8,1>F g3<0,1,0>F { align1 };
+    /* add in texture X offset */
+/* Co[0] */
+add (8) g10<1>F g10<8,8,1>F g3.12<0,1,0>F { align1 };
+add (8) g11<1>F g11<8,8,1>F g3.12<0,1,0>F { align1 };
+    /* subtract screen-space Y origin of vertex 0. */
+add (8) g12<1>F g8<8,8,1>F -g1.4<0,1,0>F { align1 };
+add (8) g13<1>F g9<8,8,1>F -g1.4<0,1,0>F { align1 };
+    /* scale by texture Y increment */
+/* Cy[0] */
+mul (8) g12<1>F g12<8,8,1>F g3.4<0,1,0>F { align1 };
+mul (8) g13<1>F g13<8,8,1>F g3.4<0,1,0>F { align1 };
+    /* add in texture Y offset */
+/* Co[1] */
+add (8) g12<1>F g12<8,8,1>F g3.28<0,1,0>F { align1 };
+add (8) g13<1>F g13<8,8,1>F g3.28<0,1,0>F { align1 };
+
+/* prepare sampler read back gX register, which would be written back to output */
+
+/* use simd16 sampler, param 0 is u, param 1 is v. */
+/* 'payload' loading, assuming tex coord start from g4 */
+mov (8) m1<1>F g10<8,8,1>F { align1 };
+mov (8) m2<1>F g11<8,8,1>F { align1 }; /* param 0 u in m1, m2 */
+mov (8) m3<1>F g12<8,8,1>F { align1 };
+mov (8) m4<1>F g13<8,8,1>F { align1 }; /* param 1 v in m3, m4 */
+
+/* m0 will be copied with g0, as it contains send desc */
+/* emit sampler 'send' cmd */
+
+/* src texture readback: g14-g21 */
+send (16) 0 		/* msg reg index */
+	g14<1>UW 	/* readback */
+	g0<8,8,1>UW  	/* copy to msg start reg*/
+	sampler (1,0,F)  /* sampler message description, 
+				(binding_table,sampler_index,datatype). 
+			    here(src->dst) we should use src_sampler and 
+			    src_surface */
+	mlen 5 rlen 8 { align1 };   /* required message len 5, readback len 8 */
+
+mov (8) g21<1>UD g21<8,8,1>UD { align1 };  /* wait sampler return */
+
+/* sampler mask texture, use g10, g11, g12, g13 */
+    /* subtract screen-space X origin of vertex 0. */
+add (8) g10<1>F g6<8,8,1>F -g1<0,1,0>F { align1 };
+add (8) g11<1>F g7<8,8,1>F -g1<0,1,0>F { align1 };
+    /* scale by texture X increment */
+/* Cx[2] */
+mul (8) g10<1>F g10<8,8,1>F g4<0,1,0>F { align1 };
+mul (8) g11<1>F g11<8,8,1>F g4<0,1,0>F { align1 };
+    /* add in texture X offset */
+/* Co[2] */
+add (8) g10<1>F g10<8,8,1>F g4.12<0,1,0>F { align1 };
+add (8) g11<1>F g11<8,8,1>F g4.12<0,1,0>F { align1 };
+    /* subtract screen-space Y origin of vertex 0. */
+add (8) g12<1>F g8<8,8,1>F -g1.4<0,1,0>F { align1 };
+add (8) g13<1>F g9<8,8,1>F -g1.4<0,1,0>F { align1 };
+    /* scale by texture Y increment */
+/* Cy[2] */
+mul (8) g12<1>F g12<8,8,1>F g4.4<0,1,0>F { align1 };
+mul (8) g13<1>F g13<8,8,1>F g4.4<0,1,0>F { align1 };
+    /* add in texture Y offset */
+/* Co[3] */
+add (8) g12<1>F g12<8,8,1>F g4.28<0,1,0>F { align1 };
+add (8) g13<1>F g13<8,8,1>F g4.28<0,1,0>F { align1 };
+
+mov (8) m1<1>F g10<8,8,1>F { align1 };
+mov (8) m2<1>F g11<8,8,1>F { align1 }; 
+mov (8) m3<1>F g12<8,8,1>F { align1 };
+mov (8) m4<1>F g13<8,8,1>F { align1 };
+
+/* mask sampler g22-g29 */
+/* binding_table (2), sampler (1) */
+send (16) 0 g22<1>UW g0<8,8,1>UW sampler (2,1,F) mlen 5 rlen 8 { align1 };
+mov (8) g29<1>UD g29<8,8,1>UD { align1 };  /* wait sampler return */
+
+/* mul mask's channel to src, then write out src */
+mul (8) g14<1>F g14<8,8,1>F g22<8,8,1>F { align1 };
+mul (8) g15<1>F g15<8,8,1>F g23<8,8,1>F { align1 };
+mul (8) g16<1>F g16<8,8,1>F g24<8,8,1>F { align1 };
+mul (8) g17<1>F g17<8,8,1>F g25<8,8,1>F { align1 };
+mul (8) g18<1>F g18<8,8,1>F g26<8,8,1>F { align1 };
+mul (8) g19<1>F g19<8,8,1>F g27<8,8,1>F { align1 };
+mul (8) g20<1>F g20<8,8,1>F g28<8,8,1>F { align1 };
+mul (8) g21<1>F g21<8,8,1>F g29<8,8,1>F { align1 };
+
+/* prepare data in m2-m5 for subspan(1,0), m6-m9 for subspan(3,2), then it's ready to write */
+mov (8) m2<1>F g14<8,8,1>F { align1 };
+mov (8) m3<1>F g16<8,8,1>F { align1 };
+mov (8) m4<1>F g18<8,8,1>F { align1 };
+mov (8) m5<1>F g20<8,8,1>F { align1 };
+mov (8) m6<1>F g15<8,8,1>F { align1 };
+mov (8) m7<1>F g17<8,8,1>F { align1 };
+mov (8) m8<1>F g19<8,8,1>F { align1 };
+mov (8) m9<1>F g21<8,8,1>F { align1 };
+
+/* m0, m1 are all direct passed by PS thread payload */
+mov (8) m1<1>UD g1<8,8,1>UD { align1 mask_disable };
+
+/* write */
+send (16) 0 acc0<1>UW g0<8,8,1>UW write (
+	0,  /* binding_table */
+	8,  /* pixel scordboard clear, msg type simd16 single source */
+	4,  /* render target write */
+	0   /* no write commit message */
+	) 
+	mlen 10
+	rlen 0
+	{ align1 EOT };
+
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
diff --git a/src/exa_wm_maskca_prog.h b/src/exa_wm_maskca_prog.h
new file mode 100644
index 0000000..d936412
--- /dev/null
+++ b/src/exa_wm_maskca_prog.h
@@ -0,0 +1,95 @@
+   { 0x00000001, 0x20c0013d, 0x00000028, 0x00000000 },
+   { 0x00000040, 0x20c40d3d, 0x00000028, 0x00000001 },
+   { 0x00000001, 0x20c8013d, 0x00000028, 0x00000000 },
+   { 0x00000040, 0x20cc0d3d, 0x00000028, 0x00000001 },
+   { 0x00000001, 0x2100013d, 0x0000002a, 0x00000000 },
+   { 0x00000001, 0x2104013d, 0x0000002a, 0x00000000 },
+   { 0x00000040, 0x21080d3d, 0x0000002a, 0x00000001 },
+   { 0x00000040, 0x210c0d3d, 0x0000002a, 0x00000001 },
+   { 0x00000001, 0x20d0013d, 0x0000002c, 0x00000000 },
+   { 0x00000040, 0x20d40d3d, 0x0000002c, 0x00000001 },
+   { 0x00000001, 0x20d8013d, 0x0000002c, 0x00000000 },
+   { 0x00000040, 0x20dc0d3d, 0x0000002c, 0x00000001 },
+   { 0x00000001, 0x2110013d, 0x0000002e, 0x00000000 },
+   { 0x00000001, 0x2114013d, 0x0000002e, 0x00000000 },
+   { 0x00000040, 0x21180d3d, 0x0000002e, 0x00000001 },
+   { 0x00000040, 0x211c0d3d, 0x0000002e, 0x00000001 },
+   { 0x00000001, 0x20e0013d, 0x00000030, 0x00000000 },
+   { 0x00000040, 0x20e40d3d, 0x00000030, 0x00000001 },
+   { 0x00000001, 0x20e8013d, 0x00000030, 0x00000000 },
+   { 0x00000040, 0x20ec0d3d, 0x00000030, 0x00000001 },
+   { 0x00000001, 0x2120013d, 0x00000032, 0x00000000 },
+   { 0x00000001, 0x2124013d, 0x00000032, 0x00000000 },
+   { 0x00000040, 0x21280d3d, 0x00000032, 0x00000001 },
+   { 0x00000040, 0x212c0d3d, 0x00000032, 0x00000001 },
+   { 0x00000001, 0x20f0013d, 0x00000034, 0x00000000 },
+   { 0x00000040, 0x20f40d3d, 0x00000034, 0x00000001 },
+   { 0x00000001, 0x20f8013d, 0x00000034, 0x00000000 },
+   { 0x00000040, 0x20fc0d3d, 0x00000034, 0x00000001 },
+   { 0x00000001, 0x2130013d, 0x00000036, 0x00000000 },
+   { 0x00000001, 0x2134013d, 0x00000036, 0x00000000 },
+   { 0x00000040, 0x21380d3d, 0x00000036, 0x00000001 },
+   { 0x00000040, 0x213c0d3d, 0x00000036, 0x00000001 },
+   { 0x00600040, 0x214077bd, 0x008d00c0, 0x00004020 },
+   { 0x00600040, 0x216077bd, 0x008d00e0, 0x00004020 },
+   { 0x00600041, 0x214077bd, 0x008d0140, 0x00000060 },
+   { 0x00600041, 0x216077bd, 0x008d0160, 0x00000060 },
+   { 0x00600040, 0x214077bd, 0x008d0140, 0x0000006c },
+   { 0x00600040, 0x216077bd, 0x008d0160, 0x0000006c },
+   { 0x00600040, 0x218077bd, 0x008d0100, 0x00004024 },
+   { 0x00600040, 0x21a077bd, 0x008d0120, 0x00004024 },
+   { 0x00600041, 0x218077bd, 0x008d0180, 0x00000064 },
+   { 0x00600041, 0x21a077bd, 0x008d01a0, 0x00000064 },
+   { 0x00600040, 0x218077bd, 0x008d0180, 0x0000007c },
+   { 0x00600040, 0x21a077bd, 0x008d01a0, 0x0000007c },
+   { 0x00600001, 0x202003be, 0x008d0140, 0x00000000 },
+   { 0x00600001, 0x204003be, 0x008d0160, 0x00000000 },
+   { 0x00600001, 0x206003be, 0x008d0180, 0x00000000 },
+   { 0x00600001, 0x208003be, 0x008d01a0, 0x00000000 },
+   { 0x00800031, 0x21c01d29, 0x008d0000, 0x02580001 },
+   { 0x00600001, 0x22a00021, 0x008d02a0, 0x00000000 },
+   { 0x00600040, 0x214077bd, 0x008d00c0, 0x00004020 },
+   { 0x00600040, 0x216077bd, 0x008d00e0, 0x00004020 },
+   { 0x00600041, 0x214077bd, 0x008d0140, 0x00000080 },
+   { 0x00600041, 0x216077bd, 0x008d0160, 0x00000080 },
+   { 0x00600040, 0x214077bd, 0x008d0140, 0x0000008c },
+   { 0x00600040, 0x216077bd, 0x008d0160, 0x0000008c },
+   { 0x00600040, 0x218077bd, 0x008d0100, 0x00004024 },
+   { 0x00600040, 0x21a077bd, 0x008d0120, 0x00004024 },
+   { 0x00600041, 0x218077bd, 0x008d0180, 0x00000084 },
+   { 0x00600041, 0x21a077bd, 0x008d01a0, 0x00000084 },
+   { 0x00600040, 0x218077bd, 0x008d0180, 0x0000009c },
+   { 0x00600040, 0x21a077bd, 0x008d01a0, 0x0000009c },
+   { 0x00600001, 0x202003be, 0x008d0140, 0x00000000 },
+   { 0x00600001, 0x204003be, 0x008d0160, 0x00000000 },
+   { 0x00600001, 0x206003be, 0x008d0180, 0x00000000 },
+   { 0x00600001, 0x208003be, 0x008d01a0, 0x00000000 },
+   { 0x00800031, 0x22c01d29, 0x008d0000, 0x02580102 },
+   { 0x00600001, 0x23a00021, 0x008d03a0, 0x00000000 },
+   { 0x00600041, 0x21c077bd, 0x008d01c0, 0x008d02c0 },
+   { 0x00600041, 0x21e077bd, 0x008d01e0, 0x008d02e0 },
+   { 0x00600041, 0x220077bd, 0x008d0200, 0x008d0300 },
+   { 0x00600041, 0x222077bd, 0x008d0220, 0x008d0320 },
+   { 0x00600041, 0x224077bd, 0x008d0240, 0x008d0340 },
+   { 0x00600041, 0x226077bd, 0x008d0260, 0x008d0360 },
+   { 0x00600041, 0x228077bd, 0x008d0280, 0x008d0380 },
+   { 0x00600041, 0x22a077bd, 0x008d02a0, 0x008d03a0 },
+   { 0x00600001, 0x204003be, 0x008d01c0, 0x00000000 },
+   { 0x00600001, 0x206003be, 0x008d0200, 0x00000000 },
+   { 0x00600001, 0x208003be, 0x008d0240, 0x00000000 },
+   { 0x00600001, 0x20a003be, 0x008d0280, 0x00000000 },
+   { 0x00600001, 0x20c003be, 0x008d01e0, 0x00000000 },
+   { 0x00600001, 0x20e003be, 0x008d0220, 0x00000000 },
+   { 0x00600001, 0x210003be, 0x008d0260, 0x00000000 },
+   { 0x00600001, 0x212003be, 0x008d02a0, 0x00000000 },
+   { 0x00600201, 0x20200022, 0x008d0020, 0x00000000 },
+   { 0x00800031, 0x24001d28, 0x008d0000, 0x85a04800 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
diff --git a/src/exa_wm_maskca_srcalpha.g4a b/src/exa_wm_maskca_srcalpha.g4a
new file mode 100644
index 0000000..e233968
--- /dev/null
+++ b/src/exa_wm_maskca_srcalpha.g4a
@@ -0,0 +1,202 @@
+/*
+ * This's for exa composite operation in no mask picture case.
+ * The simplest case is just sending what src picture has to dst picture.
+ * XXX: This is still experimental, and should be fixed to support multiple texture
+ * map, and conditional mul actions. 
+ */
+
+/* I think this should be same as in g4a program for texture video,
+   as we also use 16-pixel dispatch. and SF scale in g3 is useful for us. */
+
+/* The initial payload of the thread is always g0.
+ * WM_URB (incoming URB entries) is g3
+   As mask texture coeffient needs extra setup urb starting from g4, we should
+   shift this location. 
+
+ * X0_R is g4->g6
+ * X1_R is g5->g7
+ * Y0_R is g6->g8
+ * Y1_R is g7->g9
+
+     * X0: {ss0.x, ss0.x+1, ss0.x,   ss0.x+1, ss1.x, ss1.x+1, ss1.x,   ss1.x+y}
+     * Y0: {ss0.y, ss0.y,   ss0.y+1, ss0.y+1, ss1.y, ss1.y,   ss1.y+1, ss1.y+1}
+     * X1: {ss2.x, ss2.x+1, ss2.x,   ss2.x+1, ss3.x, ss3.x+1, ss3.x,   ss3.x+y}
+     * Y1: {ss2.y, ss2.y,   ss2.y+1, ss2.y+1, ss3.y, ss3.y,   ss3.y+1, ss3.y+1}
+ */
+
+/* multitexture program with src and mask texture */
+/* - load src texture */
+/* - load mask texture */
+/* - mul src.X with mask's alpha */
+/* - write out src.X */
+
+    /* Set up ss0.x coordinates*/
+mov (1) g6<1>F g1.8<0,1,0>UW { align1 };
+add (1) g6.4<1>F g1.8<0,1,0>UW 1UB { align1 };
+mov (1) g6.8<1>F g1.8<0,1,0>UW { align1 };
+add (1) g6.12<1>F g1.8<0,1,0>UW 1UB { align1 };
+    /* Set up ss0.y coordinates */
+mov (1) g8<1>F g1.10<0,1,0>UW { align1 };
+mov (1) g8.4<1>F g1.10<0,1,0>UW { align1 };
+add (1) g8.8<1>F g1.10<0,1,0>UW 1UB { align1 };
+add (1) g8.12<1>F g1.10<0,1,0>UW 1UB { align1 };
+    /* set up ss1.x coordinates */
+mov (1) g6.16<1>F g1.12<0,1,0>UW { align1 };
+add (1) g6.20<1>F g1.12<0,1,0>UW 1UB { align1 };
+mov (1) g6.24<1>F g1.12<0,1,0>UW { align1 };
+add (1) g6.28<1>F g1.12<0,1,0>UW 1UB { align1 };
+    /* set up ss1.y coordinates */
+mov (1) g8.16<1>F g1.14<0,1,0>UW { align1 };
+mov (1) g8.20<1>F g1.14<0,1,0>UW { align1 };
+add (1) g8.24<1>F g1.14<0,1,0>UW 1UB { align1 };
+add (1) g8.28<1>F g1.14<0,1,0>UW 1UB { align1 };
+    /* Set up ss2.x coordinates */
+mov (1) g7<1>F g1.16<0,1,0>UW { align1 };
+add (1) g7.4<1>F g1.16<0,1,0>UW 1UB { align1 };
+mov (1) g7.8<1>F g1.16<0,1,0>UW { align1 };
+add (1) g7.12<1>F g1.16<0,1,0>UW 1UB { align1 };
+    /* Set up ss2.y coordinates */
+mov (1) g9<1>F g1.18<0,1,0>UW { align1 };
+mov (1) g9.4<1>F g1.18<0,1,0>UW { align1 };
+add (1) g9.8<1>F g1.18<0,1,0>UW 1UB { align1 };
+add (1) g9.12<1>F g1.18<0,1,0>UW 1UB { align1 };
+    /* Set up ss3.x coordinates */
+mov (1) g7.16<1>F g1.20<0,1,0>UW { align1 };
+add (1) g7.20<1>F g1.20<0,1,0>UW 1UB { align1 };
+mov (1) g7.24<1>F g1.20<0,1,0>UW { align1 };
+add (1) g7.28<1>F g1.20<0,1,0>UW 1UB { align1 };
+    /* Set up ss3.y coordinates */
+mov (1) g9.16<1>F g1.22<0,1,0>UW { align1 };
+mov (1) g9.20<1>F g1.22<0,1,0>UW { align1 };
+add (1) g9.24<1>F g1.22<0,1,0>UW 1UB { align1 };
+add (1) g9.28<1>F g1.22<0,1,0>UW 1UB { align1 };
+
+    /* Now, map these screen space coordinates into texture coordinates. */
+/* This is for src texture */
+/* I don't want to change origin ssX coords, as it will be used later in mask */
+/* so store tex coords in g10, g11, g12, g13 */
+
+    /* subtract screen-space X origin of vertex 0. */
+add (8) g10<1>F g6<8,8,1>F -g1<0,1,0>F { align1 };
+add (8) g11<1>F g7<8,8,1>F -g1<0,1,0>F { align1 };
+    /* scale by texture X increment */
+/* Cx[0] */
+mul (8) g10<1>F g10<8,8,1>F g3<0,1,0>F { align1 };
+mul (8) g11<1>F g11<8,8,1>F g3<0,1,0>F { align1 };
+    /* add in texture X offset */
+/* Co[0] */
+add (8) g10<1>F g10<8,8,1>F g3.12<0,1,0>F { align1 };
+add (8) g11<1>F g11<8,8,1>F g3.12<0,1,0>F { align1 };
+    /* subtract screen-space Y origin of vertex 0. */
+add (8) g12<1>F g8<8,8,1>F -g1.4<0,1,0>F { align1 };
+add (8) g13<1>F g9<8,8,1>F -g1.4<0,1,0>F { align1 };
+    /* scale by texture Y increment */
+/* Cy[0] */
+mul (8) g12<1>F g12<8,8,1>F g3.4<0,1,0>F { align1 };
+mul (8) g13<1>F g13<8,8,1>F g3.4<0,1,0>F { align1 };
+    /* add in texture Y offset */
+/* Co[1] */
+add (8) g12<1>F g12<8,8,1>F g3.28<0,1,0>F { align1 };
+add (8) g13<1>F g13<8,8,1>F g3.28<0,1,0>F { align1 };
+
+/* prepare sampler read back gX register, which would be written back to output */
+
+/* use simd16 sampler, param 0 is u, param 1 is v. */
+/* 'payload' loading, assuming tex coord start from g4 */
+mov (8) m1<1>F g10<8,8,1>F { align1 };
+mov (8) m2<1>F g11<8,8,1>F { align1 }; /* param 0 u in m1, m2 */
+mov (8) m3<1>F g12<8,8,1>F { align1 };
+mov (8) m4<1>F g13<8,8,1>F { align1 }; /* param 1 v in m3, m4 */
+
+/* m0 will be copied with g0, as it contains send desc */
+/* emit sampler 'send' cmd */
+
+/* src texture readback: g14-g21 */
+send (16) 0 		/* msg reg index */
+	g14<1>UW 	/* readback */
+	g0<8,8,1>UW  	/* copy to msg start reg*/
+	sampler (1,0,F)  /* sampler message description, 
+				(binding_table,sampler_index,datatype). 
+			    here(src->dst) we should use src_sampler and 
+			    src_surface */
+	mlen 5 rlen 8 { align1 };   /* required message len 5, readback len 8 */
+
+mov (8) g21<1>UD g21<8,8,1>UD { align1 };  /* wait sampler return */
+
+/* sampler mask texture, use g10, g11, g12, g13 */
+    /* subtract screen-space X origin of vertex 0. */
+add (8) g10<1>F g6<8,8,1>F -g1<0,1,0>F { align1 };
+add (8) g11<1>F g7<8,8,1>F -g1<0,1,0>F { align1 };
+    /* scale by texture X increment */
+/* Cx[2] */
+mul (8) g10<1>F g10<8,8,1>F g4<0,1,0>F { align1 };
+mul (8) g11<1>F g11<8,8,1>F g4<0,1,0>F { align1 };
+    /* add in texture X offset */
+/* Co[2] */
+add (8) g10<1>F g10<8,8,1>F g4.12<0,1,0>F { align1 };
+add (8) g11<1>F g11<8,8,1>F g4.12<0,1,0>F { align1 };
+    /* subtract screen-space Y origin of vertex 0. */
+add (8) g12<1>F g8<8,8,1>F -g1.4<0,1,0>F { align1 };
+add (8) g13<1>F g9<8,8,1>F -g1.4<0,1,0>F { align1 };
+    /* scale by texture Y increment */
+/* Cy[2] */
+mul (8) g12<1>F g12<8,8,1>F g4.4<0,1,0>F { align1 };
+mul (8) g13<1>F g13<8,8,1>F g4.4<0,1,0>F { align1 };
+    /* add in texture Y offset */
+/* Co[3] */
+add (8) g12<1>F g12<8,8,1>F g4.28<0,1,0>F { align1 };
+add (8) g13<1>F g13<8,8,1>F g4.28<0,1,0>F { align1 };
+
+mov (8) m1<1>F g10<8,8,1>F { align1 };
+mov (8) m2<1>F g11<8,8,1>F { align1 }; 
+mov (8) m3<1>F g12<8,8,1>F { align1 };
+mov (8) m4<1>F g13<8,8,1>F { align1 };
+
+/* mask sampler g22-g29 */
+/* binding_table (2), sampler (1) */
+send (16) 0 g22<1>UW g0<8,8,1>UW sampler (2,1,F) mlen 5 rlen 8 { align1 };
+mov (8) g29<1>UD g29<8,8,1>UD { align1 };  /* wait sampler return */
+
+/* src channel has no more use, src.A * mask.C */
+mul (8) g14<1>F g22<8,8,1>F g20<8,8,1>F { align1 };
+mul (8) g15<1>F g23<8,8,1>F g21<8,8,1>F { align1 };
+mul (8) g16<1>F g24<8,8,1>F g20<8,8,1>F { align1 };
+mul (8) g17<1>F g25<8,8,1>F g21<8,8,1>F { align1 };
+mul (8) g18<1>F g26<8,8,1>F g20<8,8,1>F { align1 };
+mul (8) g19<1>F g27<8,8,1>F g21<8,8,1>F { align1 };
+mul (8) g20<1>F g28<8,8,1>F g20<8,8,1>F { align1 };
+mul (8) g21<1>F g29<8,8,1>F g21<8,8,1>F { align1 };
+
+/* prepare data in m2-m5 for subspan(1,0), m6-m9 for subspan(3,2), then it's ready to write */
+mov (8) m2<1>F g14<8,8,1>F { align1 };
+mov (8) m3<1>F g16<8,8,1>F { align1 };
+mov (8) m4<1>F g18<8,8,1>F { align1 };
+mov (8) m5<1>F g20<8,8,1>F { align1 };
+mov (8) m6<1>F g15<8,8,1>F { align1 };
+mov (8) m7<1>F g17<8,8,1>F { align1 };
+mov (8) m8<1>F g19<8,8,1>F { align1 };
+mov (8) m9<1>F g21<8,8,1>F { align1 };
+
+/* m0, m1 are all direct passed by PS thread payload */
+mov (8) m1<1>UD g1<8,8,1>UD { align1 mask_disable };
+
+/* write */
+send (16) 0 acc0<1>UW g0<8,8,1>UW write (
+	0,  /* binding_table */
+	8,  /* pixel scordboard clear, msg type simd16 single source */
+	4,  /* render target write */
+	0   /* no write commit message */
+	) 
+	mlen 10
+	rlen 0
+	{ align1 EOT };
+
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
diff --git a/src/exa_wm_maskca_srcalpha_prog.h b/src/exa_wm_maskca_srcalpha_prog.h
new file mode 100644
index 0000000..d83b119
--- /dev/null
+++ b/src/exa_wm_maskca_srcalpha_prog.h
@@ -0,0 +1,95 @@
+   { 0x00000001, 0x20c0013d, 0x00000028, 0x00000000 },
+   { 0x00000040, 0x20c40d3d, 0x00000028, 0x00000001 },
+   { 0x00000001, 0x20c8013d, 0x00000028, 0x00000000 },
+   { 0x00000040, 0x20cc0d3d, 0x00000028, 0x00000001 },
+   { 0x00000001, 0x2100013d, 0x0000002a, 0x00000000 },
+   { 0x00000001, 0x2104013d, 0x0000002a, 0x00000000 },
+   { 0x00000040, 0x21080d3d, 0x0000002a, 0x00000001 },
+   { 0x00000040, 0x210c0d3d, 0x0000002a, 0x00000001 },
+   { 0x00000001, 0x20d0013d, 0x0000002c, 0x00000000 },
+   { 0x00000040, 0x20d40d3d, 0x0000002c, 0x00000001 },
+   { 0x00000001, 0x20d8013d, 0x0000002c, 0x00000000 },
+   { 0x00000040, 0x20dc0d3d, 0x0000002c, 0x00000001 },
+   { 0x00000001, 0x2110013d, 0x0000002e, 0x00000000 },
+   { 0x00000001, 0x2114013d, 0x0000002e, 0x00000000 },
+   { 0x00000040, 0x21180d3d, 0x0000002e, 0x00000001 },
+   { 0x00000040, 0x211c0d3d, 0x0000002e, 0x00000001 },
+   { 0x00000001, 0x20e0013d, 0x00000030, 0x00000000 },
+   { 0x00000040, 0x20e40d3d, 0x00000030, 0x00000001 },
+   { 0x00000001, 0x20e8013d, 0x00000030, 0x00000000 },
+   { 0x00000040, 0x20ec0d3d, 0x00000030, 0x00000001 },
+   { 0x00000001, 0x2120013d, 0x00000032, 0x00000000 },
+   { 0x00000001, 0x2124013d, 0x00000032, 0x00000000 },
+   { 0x00000040, 0x21280d3d, 0x00000032, 0x00000001 },
+   { 0x00000040, 0x212c0d3d, 0x00000032, 0x00000001 },
+   { 0x00000001, 0x20f0013d, 0x00000034, 0x00000000 },
+   { 0x00000040, 0x20f40d3d, 0x00000034, 0x00000001 },
+   { 0x00000001, 0x20f8013d, 0x00000034, 0x00000000 },
+   { 0x00000040, 0x20fc0d3d, 0x00000034, 0x00000001 },
+   { 0x00000001, 0x2130013d, 0x00000036, 0x00000000 },
+   { 0x00000001, 0x2134013d, 0x00000036, 0x00000000 },
+   { 0x00000040, 0x21380d3d, 0x00000036, 0x00000001 },
+   { 0x00000040, 0x213c0d3d, 0x00000036, 0x00000001 },
+   { 0x00600040, 0x214077bd, 0x008d00c0, 0x00004020 },
+   { 0x00600040, 0x216077bd, 0x008d00e0, 0x00004020 },
+   { 0x00600041, 0x214077bd, 0x008d0140, 0x00000060 },
+   { 0x00600041, 0x216077bd, 0x008d0160, 0x00000060 },
+   { 0x00600040, 0x214077bd, 0x008d0140, 0x0000006c },
+   { 0x00600040, 0x216077bd, 0x008d0160, 0x0000006c },
+   { 0x00600040, 0x218077bd, 0x008d0100, 0x00004024 },
+   { 0x00600040, 0x21a077bd, 0x008d0120, 0x00004024 },
+   { 0x00600041, 0x218077bd, 0x008d0180, 0x00000064 },
+   { 0x00600041, 0x21a077bd, 0x008d01a0, 0x00000064 },
+   { 0x00600040, 0x218077bd, 0x008d0180, 0x0000007c },
+   { 0x00600040, 0x21a077bd, 0x008d01a0, 0x0000007c },
+   { 0x00600001, 0x202003be, 0x008d0140, 0x00000000 },
+   { 0x00600001, 0x204003be, 0x008d0160, 0x00000000 },
+   { 0x00600001, 0x206003be, 0x008d0180, 0x00000000 },
+   { 0x00600001, 0x208003be, 0x008d01a0, 0x00000000 },
+   { 0x00800031, 0x21c01d29, 0x008d0000, 0x02580001 },
+   { 0x00600001, 0x22a00021, 0x008d02a0, 0x00000000 },
+   { 0x00600040, 0x214077bd, 0x008d00c0, 0x00004020 },
+   { 0x00600040, 0x216077bd, 0x008d00e0, 0x00004020 },
+   { 0x00600041, 0x214077bd, 0x008d0140, 0x00000080 },
+   { 0x00600041, 0x216077bd, 0x008d0160, 0x00000080 },
+   { 0x00600040, 0x214077bd, 0x008d0140, 0x0000008c },
+   { 0x00600040, 0x216077bd, 0x008d0160, 0x0000008c },
+   { 0x00600040, 0x218077bd, 0x008d0100, 0x00004024 },
+   { 0x00600040, 0x21a077bd, 0x008d0120, 0x00004024 },
+   { 0x00600041, 0x218077bd, 0x008d0180, 0x00000084 },
+   { 0x00600041, 0x21a077bd, 0x008d01a0, 0x00000084 },
+   { 0x00600040, 0x218077bd, 0x008d0180, 0x0000009c },
+   { 0x00600040, 0x21a077bd, 0x008d01a0, 0x0000009c },
+   { 0x00600001, 0x202003be, 0x008d0140, 0x00000000 },
+   { 0x00600001, 0x204003be, 0x008d0160, 0x00000000 },
+   { 0x00600001, 0x206003be, 0x008d0180, 0x00000000 },
+   { 0x00600001, 0x208003be, 0x008d01a0, 0x00000000 },
+   { 0x00800031, 0x22c01d29, 0x008d0000, 0x02580102 },
+   { 0x00600001, 0x23a00021, 0x008d03a0, 0x00000000 },
+   { 0x00600041, 0x21c077bd, 0x008d02c0, 0x008d0280 },
+   { 0x00600041, 0x21e077bd, 0x008d02e0, 0x008d02a0 },
+   { 0x00600041, 0x220077bd, 0x008d0300, 0x008d0280 },
+   { 0x00600041, 0x222077bd, 0x008d0320, 0x008d02a0 },
+   { 0x00600041, 0x224077bd, 0x008d0340, 0x008d0280 },
+   { 0x00600041, 0x226077bd, 0x008d0360, 0x008d02a0 },
+   { 0x00600041, 0x228077bd, 0x008d0380, 0x008d0280 },
+   { 0x00600041, 0x22a077bd, 0x008d03a0, 0x008d02a0 },
+   { 0x00600001, 0x204003be, 0x008d01c0, 0x00000000 },
+   { 0x00600001, 0x206003be, 0x008d0200, 0x00000000 },
+   { 0x00600001, 0x208003be, 0x008d0240, 0x00000000 },
+   { 0x00600001, 0x20a003be, 0x008d0280, 0x00000000 },
+   { 0x00600001, 0x20c003be, 0x008d01e0, 0x00000000 },
+   { 0x00600001, 0x20e003be, 0x008d0220, 0x00000000 },
+   { 0x00600001, 0x210003be, 0x008d0260, 0x00000000 },
+   { 0x00600001, 0x212003be, 0x008d02a0, 0x00000000 },
+   { 0x00600201, 0x20200022, 0x008d0020, 0x00000000 },
+   { 0x00800031, 0x24001d28, 0x008d0000, 0x85a04800 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
diff --git a/src/i965_render.c b/src/i965_render.c
index a2b21db..8474c48 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -133,7 +133,8 @@ static void i965_get_blend_cntl(int op, 
      * the source blend factor is 0, and the source blend value is the mask
      * channels multiplied by the source picture's alpha.
      */
-    if (pMask && pMask->componentAlpha && i965_blend_op[op].src_alpha) {
+    if (pMask && pMask->componentAlpha && PICT_FORMAT_RGB(pMask->format)
+            && i965_blend_op[op].src_alpha) {
         if (*dblend == BRW_BLENDFACTOR_SRC_ALPHA) {
 	    *dblend = BRW_BLENDFACTOR_SRC_COLOR;
         } else if (*dblend == BRW_BLENDFACTOR_INV_SRC_ALPHA) {
@@ -223,7 +224,8 @@ i965_check_composite(int op, PicturePtr 
     if (op >= sizeof(i965_blend_op) / sizeof(i965_blend_op[0]))
         I830FALLBACK("Unsupported Composite op 0x%x\n", op);
 
-    if (pMaskPicture != NULL && pMaskPicture->componentAlpha) {
+    if (pMaskPicture && pMaskPicture->componentAlpha &&
+            PICT_FORMAT_RGB(pMaskPicture->format)) {
         /* Check if it's component alpha that relies on a source alpha and on
          * the source value.  We can only get one of those into the single
          * source value that we get to blend with.
@@ -234,9 +236,7 @@ i965_check_composite(int op, PicturePtr 
 	    I830FALLBACK("Component alpha not supported with source "
 			 "alpha and source value blending.\n");
 	}
-	/* XXX: fallback now for mask with componentAlpha */
-	I830FALLBACK("mask componentAlpha not ready.\n");
-    }
+    } 
 
     if (!i965_check_composite_texture(pSrcPicture, 0))
         I830FALLBACK("Check Src picture texture\n");
@@ -337,17 +337,19 @@ static const CARD32 sf_kernel_static_mas
 /* ps kernels */
 #define PS_KERNEL_NUM_GRF   32
 #define PS_MAX_THREADS	   32
-/* 1: no mask */
+
 static const CARD32 ps_kernel_static_nomask [][4] = {
 #include "exa_wm_nomask_prog.h"
 };
 
-/* 2: mask with componentAlpha, src * mask color, XXX: later */
 static const CARD32 ps_kernel_static_maskca [][4] = {
-/*#include "i965_composite_wm_maskca.h" */
+#include "exa_wm_maskca_prog.h"
+};
+
+static const CARD32 ps_kernel_static_maskca_srcalpha [][4] = {
+#include "exa_wm_maskca_srcalpha_prog.h"
 };
 
-/* 3: mask without componentAlpha, src * mask alpha */
 static const CARD32 ps_kernel_static_masknoca [][4] = {
 #include "exa_wm_masknoca_prog.h"
 };
@@ -442,13 +444,20 @@ i965_prepare_composite(int op, PicturePt
     else
 	next_offset = sf_kernel_offset + sizeof (sf_kernel_static);
 
-    /* XXX: ps_kernel may be seperated, fix with offset */
     ps_kernel_offset = ALIGN(next_offset, 64);
     if (pMask) {
-	if (pMaskPicture->componentAlpha)
-	    next_offset = ps_kernel_offset + sizeof(ps_kernel_static_maskca);
-	else
-	    next_offset = ps_kernel_offset + sizeof(ps_kernel_static_masknoca);
+	if (pMaskPicture->componentAlpha && 
+                PICT_FORMAT_RGB(pMaskPicture->format)) {
+            if (i965_blend_op[op].src_alpha) {
+                next_offset = ps_kernel_offset + 
+                    sizeof(ps_kernel_static_maskca_srcalpha);
+            } else {
+                next_offset = ps_kernel_offset + 
+                    sizeof(ps_kernel_static_maskca);
+            }
+        } else
+	    next_offset = ps_kernel_offset + 
+                          sizeof(ps_kernel_static_masknoca);
     } else {
    	next_offset = ps_kernel_offset + sizeof (ps_kernel_static_nomask);
     }
@@ -746,7 +755,6 @@ i965_prepare_composite(int op, PicturePt
     vs_state->vs6.vs_enable = 0;
     vs_state->vs6.vert_cache_disable = 1;
 
-    /* XXX: sf_kernel? keep it as now */
     /* Set up the SF kernel to do coord interp: for each attribute,
      * calculate dA/dx and dA/dy.  Hand these interpolation coefficients
      * back to SF which then hands pixels off to WM.
@@ -788,10 +796,15 @@ i965_prepare_composite(int op, PicturePt
 
    /* Set up the PS kernel (dispatched by WM) */
     if (pMask) {
-	if (pMaskPicture->componentAlpha)
-   	    memcpy(ps_kernel, ps_kernel_static_maskca,
-		   sizeof (ps_kernel_static_maskca));
-	else
+	if (pMaskPicture->componentAlpha && 
+                PICT_FORMAT_RGB(pMaskPicture->format)) {
+            if (i965_blend_op[op].src_alpha) 
+                memcpy(ps_kernel, ps_kernel_static_maskca_srcalpha,
+                        sizeof (ps_kernel_static_maskca_srcalpha));
+            else
+                memcpy(ps_kernel, ps_kernel_static_maskca,
+                        sizeof (ps_kernel_static_maskca));
+        } else
    	    memcpy(ps_kernel, ps_kernel_static_masknoca,
 		   sizeof (ps_kernel_static_masknoca));
     } else {
@@ -812,7 +825,6 @@ i965_prepare_composite(int op, PicturePt
     wm_state->thread2.scratch_space_base_pointer = (state_base_offset +
 						    wm_scratch_offset)>>10;
     wm_state->thread2.per_thread_scratch_space = 0;
-    // XXX: urb allocation
     wm_state->thread3.const_urb_entry_read_length = 0;
     wm_state->thread3.const_urb_entry_read_offset = 0;
     /* Each pair of attributes (src/mask coords) is one URB entry */
diff-tree ec55dd16c4c5f7612d33ae22a6249b3b1c60e2b6 (from 22a271555a46267c40448fa926d45692498ef7c6)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Wed Feb 14 14:37:02 2007 -0800

    Global namespace cleanups, filename fixes.
    
    Ensure all xf86 symbols created here are protected with XF86NAME.
    Remove accidentally exported symbols from namespace.
    Make all to-be-DI files prefixed with i830_xf86.

diff --git a/src/Makefile.am b/src/Makefile.am
index a94e14c..982a959 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -63,7 +63,6 @@ intel_drv_la_SOURCES = \
 	 i830_display.h \
          i830_driver.c \
 	 i830_dvo.c \
-         i830_edid_modes.c \
          i830.h \
          i830_i2c.c \
          i830_io.c \
@@ -73,18 +72,10 @@ intel_drv_la_SOURCES = \
          i830_video.c \
          i830_video.h \
 	 i830_reg.h \
-	 i830_randr.c \
 	 i830_sdvo.c \
 	 i830_sdvo.h \
 	 i830_sdvo_regs.h \
 	 i830_tv.c \
-	 i830_xf86Modes.h \
-	 i830_xf86Modes.c \
-	 i830_xf86cvt.c \
-	 i830_xf86Crtc.h \
-	 i830_xf86Crtc.c \
-	 i830_xf86Rotate.c \
-	 i830_xf86DiDGA.c \
 	 i915_3d.c \
 	 i915_3d.h \
 	 i915_reg.h \
@@ -99,7 +90,16 @@ intel_drv_la_SOURCES = \
 	 local_xf86Rename.h \
 	 xf86Parser.h \
 	 xf86Optrec.h \
-	 i830_randr.h
+	 i830_xf86Modes.h \
+	 i830_xf86Modes.c \
+	 i830_xf86cvt.c \
+	 i830_xf86Crtc.h \
+	 i830_xf86Crtc.c \
+         i830_xf86EdidModes.c \
+	 i830_xf86RandR12.c \
+	 i830_xf86RandR12.h \
+	 i830_xf86Rotate.c \
+	 i830_xf86DiDGA.c
 
 EXTRA_DIST = \
 	packed_yuv_sf.g4a \
diff --git a/src/i830.h b/src/i830.h
index 7a442d8..26d16e9 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -59,7 +59,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "vbe.h"
 #include "vgaHW.h"
 #include "i830_xf86Crtc.h"
-#include "i830_randr.h"
+#include "i830_xf86RandR12.h"
 
 #ifdef XF86DRI
 #include "xf86drm.h"
diff --git a/src/i830_edid_modes.c b/src/i830_edid_modes.c
deleted file mode 100644
index 866b9be..0000000
--- a/src/i830_edid_modes.c
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- * Copyright 2006 Luc Verhaegen.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * @file This is a copy of edid_modes.c from the X Server, for compatibility
- * with old X Servers.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "xf86.h"
-#include "xf86DDC.h"
-#include <X11/Xatom.h>
-#include "property.h"
-#include "propertyst.h"
-#include "xf86DDC.h"
-#include "i830.h"
-#include "i830_display.h"
-#include <string.h>
-#include <math.h>
-
-#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0)
-
-/*
- * Quirks to work around broken EDID data from various monitors.
- */
-
-typedef enum {
-    DDC_QUIRK_NONE = 0,
-    /* Force detailed sync polarity to -h +v */
-    DDC_QUIRK_DT_SYNC_HM_VP = 1 << 0,
-    /* First detailed mode is bogus, prefer largest mode at 60hz */
-    DDC_QUIRK_PREFER_LARGE_60 = 1 << 1,
-    /* 135MHz clock is too high, drop a bit */
-    DDC_QUIRK_135_CLOCK_TOO_HIGH = 1 << 2
-} ddc_quirk_t;
-
-static Bool quirk_dt_sync_hm_vp (int scrnIndex, xf86MonPtr DDC)
-{
-    /* Belinea 1924S1W */
-    if (memcmp (DDC->vendor.name, "MAX", 4) == 0 &&
-	DDC->vendor.prod_id == 1932)
-	return TRUE;
-    /* Belinea 10 20 30W */
-    if (memcmp (DDC->vendor.name, "MAX", 4) == 0 &&
-	DDC->vendor.prod_id == 2007)
-	return TRUE;
-    /* ViewSonic VX2025wm (bug #9941) */
-    if (memcmp (DDC->vendor.name, "VSC", 4) == 0 &&
-	DDC->vendor.prod_id == 58653)
-	return TRUE;
-
-    return FALSE;
-}
-
-static Bool quirk_prefer_large_60 (int scrnIndex, xf86MonPtr DDC)
-{
-    /* Belinea 10 15 55 */
-    if (memcmp (DDC->vendor.name, "MAX", 4) == 0 &&
-	DDC->vendor.prod_id == 1516)
-	return TRUE;
-    
-    return FALSE;
-}
-
-static Bool quirk_135_clock_too_high (int scrnIndex, xf86MonPtr DDC)
-{
-    /* Envision Peripherals, Inc. EN-7100e.  See bug #9550. */
-    if (memcmp (DDC->vendor.name, "EPI", 4) == 0 &&
-	DDC->vendor.prod_id == 59264)
-	return TRUE;
-    
-    return FALSE;
-}
-
-typedef struct {
-    Bool	(*detect) (int scrnIndex, xf86MonPtr DDC);
-    ddc_quirk_t	quirk;
-    char	*description;
-} ddc_quirk_map_t;
-
-static const ddc_quirk_map_t ddc_quirks[] = {
-    { 
-	quirk_dt_sync_hm_vp,	DDC_QUIRK_DT_SYNC_HM_VP,
-	"Set detailed timing sync polarity to -h +v"
-    },
-    {
-	quirk_prefer_large_60,   DDC_QUIRK_PREFER_LARGE_60,
-	"Detailed timing is not preferred, use largest mode at 60Hz"
-    },
-    {
-	quirk_135_clock_too_high,   DDC_QUIRK_135_CLOCK_TOO_HIGH,
-	"Recommended 135MHz pixel clock is too high"
-    },
-    { 
-	NULL,		DDC_QUIRK_NONE,
-	"No known quirks"
-    },
-};
-
-/*
- * TODO:
- *  - for those with access to the VESA DMT standard; review please.
- */
-#define MODEPREFIX(name) NULL, NULL, name, 0,M_T_DRIVER
-#define MODESUFFIX   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,FALSE,FALSE,0,NULL,0,0.0,0.0
-
-static DisplayModeRec DDCEstablishedModes[17] = {
-    { MODEPREFIX("800x600"),    40000,  800,  840,  968, 1056, 0,  600,  601,  605,  628, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600 at 60Hz */
-    { MODEPREFIX("800x600"),    36000,  800,  824,  896, 1024, 0,  600,  601,  603,  625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600 at 56Hz */
-    { MODEPREFIX("640x480"),    31500,  640,  656,  720,  840, 0,  480,  481,  484,  500, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480 at 75Hz */
-    { MODEPREFIX("640x480"),    31500,  640,  664,  704,  832, 0,  480,  489,  491,  520, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480 at 72Hz */
-    { MODEPREFIX("640x480"),    30240,  640,  704,  768,  864, 0,  480,  483,  486,  525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480 at 67Hz */
-    { MODEPREFIX("640x480"),    25200,  640,  656,  752,  800, 0,  480,  490,  492,  525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480 at 60Hz */
-    { MODEPREFIX("720x400"),    35500,  720,  738,  846,  900, 0,  400,  421,  423,  449, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 720x400 at 88Hz */
-    { MODEPREFIX("720x400"),    28320,  720,  738,  846,  900, 0,  400,  412,  414,  449, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 720x400 at 70Hz */
-    { MODEPREFIX("1280x1024"), 135000, 1280, 1296, 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x1024 at 75Hz */
-    { MODEPREFIX("1024x768"),   78800, 1024, 1040, 1136, 1312, 0,  768,  769,  772,  800, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1024x768 at 75Hz */
-    { MODEPREFIX("1024x768"),   75000, 1024, 1048, 1184, 1328, 0,  768,  771,  777,  806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768 at 70Hz */
-    { MODEPREFIX("1024x768"),   65000, 1024, 1048, 1184, 1344, 0,  768,  771,  777,  806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768 at 60Hz */
-    { MODEPREFIX("1024x768"),   44900, 1024, 1032, 1208, 1264, 0,  768,  768,  776,  817, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* 1024x768 at 43Hz */
-    { MODEPREFIX("832x624"),    57284,  832,  864,  928, 1152, 0,  624,  625,  628,  667, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 832x624 at 75Hz */
-    { MODEPREFIX("800x600"),    49500,  800,  816,  896, 1056, 0,  600,  601,  604,  625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600 at 75Hz */
-    { MODEPREFIX("800x600"),    50000,  800,  856,  976, 1040, 0,  600,  637,  643,  666, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600 at 72Hz */
-    { MODEPREFIX("1152x864"),  108000, 1152, 1216, 1344, 1600, 0,  864,  865,  868,  900, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1152x864 at 75Hz */
-};
-
-static DisplayModePtr
-DDCModesFromEstablished(int scrnIndex, struct established_timings *timing,
-			ddc_quirk_t quirks)
-{
-    DisplayModePtr Modes = NULL, Mode = NULL;
-    CARD32 bits = (timing->t1) | (timing->t2 << 8) |
-        ((timing->t_manu & 0x80) << 9);
-    int i;
-
-    for (i = 0; i < 17; i++) {
-        if (bits & (0x01 << i)) {
-            Mode = xf86DuplicateMode(&DDCEstablishedModes[i]);
-            Modes = xf86ModesAdd(Modes, Mode);
-        }
-    }
-
-    return Modes;
-}
-
-/*
- *
- */
-static DisplayModePtr
-DDCModesFromStandardTiming(int scrnIndex, struct std_timings *timing,
-			   ddc_quirk_t quirks)
-{
-    DisplayModePtr Modes = NULL, Mode = NULL;
-    int i;
-
-    for (i = 0; i < STD_TIMINGS; i++) {
-        if (timing[i].hsize && timing[i].vsize && timing[i].refresh) {
-            Mode =  xf86CVTMode(timing[i].hsize, timing[i].vsize,
-                                timing[i].refresh, FALSE, FALSE);
-	    Mode->type = M_T_DRIVER;
-            Modes = xf86ModesAdd(Modes, Mode);
-        }
-    }
-
-    return Modes;
-}
-
-/*
- *
- */
-static DisplayModePtr
-DDCModeFromDetailedTiming(int scrnIndex, struct detailed_timings *timing,
-			  int preferred, ddc_quirk_t quirks)
-{
-    DisplayModePtr Mode;
-
-    /* We don't do stereo */
-    if (timing->stereo) {
-        xf86DrvMsg(scrnIndex, X_INFO,
-		   "%s: Ignoring: We don't handle stereo.\n", __func__);
-        return NULL;
-    }
-
-    /* We only do seperate sync currently */
-    if (timing->sync != 0x03) {
-         xf86DrvMsg(scrnIndex, X_INFO,
-		    "%s: %dx%d Warning: We only handle seperate"
-                    " sync.\n", __func__, timing->h_active, timing->v_active);
-    }
-
-    Mode = xnfalloc(sizeof(DisplayModeRec));
-    memset(Mode, 0, sizeof(DisplayModeRec));
-
-    Mode->type = M_T_DRIVER;
-    if (preferred)
-	Mode->type |= M_T_PREFERRED;
-
-    if( ( quirks & DDC_QUIRK_135_CLOCK_TOO_HIGH ) &&
-	timing->clock == 135000000 )
-        Mode->Clock = 108880;
-    else
-        Mode->Clock = timing->clock / 1000.0;
-
-    Mode->HDisplay = timing->h_active;
-    Mode->HSyncStart = timing->h_active + timing->h_sync_off;
-    Mode->HSyncEnd = Mode->HSyncStart + timing->h_sync_width;
-    Mode->HTotal = timing->h_active + timing->h_blanking;
-
-    Mode->VDisplay = timing->v_active;
-    Mode->VSyncStart = timing->v_active + timing->v_sync_off;
-    Mode->VSyncEnd = Mode->VSyncStart + timing->v_sync_width;
-    Mode->VTotal = timing->v_active + timing->v_blanking;
-
-    xf86SetModeDefaultName(Mode);
-
-    /* We ignore h/v_size and h/v_border for now. */
-
-    if (timing->interlaced)
-        Mode->Flags |= V_INTERLACE;
-
-    if (quirks & DDC_QUIRK_DT_SYNC_HM_VP)
-	Mode->Flags |= V_NHSYNC | V_PVSYNC;
-    else
-    {
-	if (timing->misc & 0x02)
-	    Mode->Flags |= V_PHSYNC;
-	else
-	    Mode->Flags |= V_NHSYNC;
-    
-	if (timing->misc & 0x01)
-	    Mode->Flags |= V_PVSYNC;
-	else
-	    Mode->Flags |= V_NVSYNC;
-    }
-
-    return Mode;
-}
-
-DisplayModePtr
-xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC)
-{
-    int preferred, i;
-    DisplayModePtr  Modes = NULL, Mode;
-    ddc_quirk_t	    quirks;
-
-    xf86DrvMsg (scrnIndex, X_INFO, "EDID vendor \"%s\", prod id %d\n",
-		DDC->vendor.name, DDC->vendor.prod_id);
-    quirks = DDC_QUIRK_NONE;
-    for (i = 0; ddc_quirks[i].detect; i++)
-	if (ddc_quirks[i].detect (scrnIndex, DDC))
-	{
-	    xf86DrvMsg (scrnIndex, X_INFO, "    EDID quirk: %s\n",
-			ddc_quirks[i].description);
-	    quirks |= ddc_quirks[i].quirk;
-	}
-    
-    preferred = PREFERRED_TIMING_MODE(DDC->features.msc);
-    if (quirks & DDC_QUIRK_PREFER_LARGE_60)
-	preferred = 0;
-
-    for (i = 0; i < DET_TIMINGS; i++) {
-	struct detailed_monitor_section *det_mon = &DDC->det_mon[i];
-
-        switch (det_mon->type) {
-        case DT:
-            Mode = DDCModeFromDetailedTiming(scrnIndex,
-                                             &det_mon->section.d_timings,
-					     preferred,
-					     quirks);
-	    preferred = 0;
-            Modes = xf86ModesAdd(Modes, Mode);
-            break;
-        case DS_STD_TIMINGS:
-            Mode = DDCModesFromStandardTiming(scrnIndex,
-					      det_mon->section.std_t,
-					      quirks);
-            Modes = xf86ModesAdd(Modes, Mode);
-            break;
-        default:
-            break;
-        }
-    }
-
-    /* Add established timings */
-    Mode = DDCModesFromEstablished(scrnIndex, &DDC->timings1, quirks);
-    Modes = xf86ModesAdd(Modes, Mode);
-
-    /* Add standard timings */
-    Mode = DDCModesFromStandardTiming(scrnIndex, DDC->timings2, quirks);
-    Modes = xf86ModesAdd(Modes, Mode);
-
-    if (quirks & DDC_QUIRK_PREFER_LARGE_60)
-    {
-	DisplayModePtr	best = Modes;
-	for (Mode = Modes; Mode; Mode = Mode->next)
-	{
-	    if (Mode == best) continue;
-	    if (Mode->HDisplay * Mode->VDisplay > best->HDisplay * best->VDisplay)
-	    {
-		best = Mode;
-		continue;
-	    }
-	    if (Mode->HDisplay * Mode->VDisplay == best->HDisplay * best->VDisplay)
-	    {
-		double	mode_refresh = xf86ModeVRefresh (Mode);
-		double	best_refresh = xf86ModeVRefresh (best);
-		double	mode_dist = fabs(mode_refresh - 60.0);
-		double	best_dist = fabs(best_refresh - 60.0);
-		if (mode_dist < best_dist)
-		{
-		    best = Mode;
-		    continue;
-		}
-	    }
-	}
-	if (best)
-	    best->type |= M_T_PREFERRED;
-    }
-    return Modes;
-}
-
-#endif /* XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0) */
diff --git a/src/i830_randr.c b/src/i830_randr.c
deleted file mode 100644
index b9cc9aa..0000000
--- a/src/i830_randr.c
+++ /dev/null
@@ -1,950 +0,0 @@
-/* $XdotOrg: xc/programs/Xserver/hw/xfree86/common/xf86RandR.c,v 1.3 2004/07/30 21:53:09 eich Exp $ */
-/*
- * $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86RandR.c,v 1.7tsi Exp $
- *
- * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
- *
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "xf86.h"
-#include "os.h"
-#include "mibank.h"
-#include "globals.h"
-#include "xf86.h"
-#include "xf86Priv.h"
-#include "xf86DDC.h"
-#include "mipointer.h"
-#include "windowstr.h"
-#include <randrstr.h>
-#include <X11/extensions/render.h>
-
-#include "i830_xf86Crtc.h"
-#include "i830_randr.h"
-
-typedef struct _xf86RandR12Info {
-    int				    virtualX;
-    int				    virtualY;
-    int				    mmWidth;
-    int				    mmHeight;
-    int				    maxX;
-    int				    maxY;
-    Rotation			    rotation; /* current mode */
-    Rotation                        supported_rotations; /* driver supported */
-} XF86RandRInfoRec, *XF86RandRInfoPtr;
-
-#ifdef RANDR_12_INTERFACE
-static Bool xf86RandR12Init12 (ScreenPtr pScreen);
-static Bool xf86RandR12CreateScreenResources12 (ScreenPtr pScreen);
-#endif
-
-static int	    xf86RandR12Index;
-static int	    xf86RandR12Generation;
-
-#define XF86RANDRINFO(p) \
-	((XF86RandRInfoPtr)(p)->devPrivates[xf86RandR12Index].ptr)
-
-static int
-xf86RandR12ModeRefresh (DisplayModePtr mode)
-{
-    if (mode->VRefresh)
-	return (int) (mode->VRefresh + 0.5);
-    else
-	return (int) (mode->Clock * 1000.0 / mode->HTotal / mode->VTotal + 0.5);
-}
-
-static Bool
-xf86RandR12GetInfo (ScreenPtr pScreen, Rotation *rotations)
-{
-    RRScreenSizePtr	    pSize;
-    ScrnInfoPtr		    scrp = XF86SCRNINFO(pScreen);
-    XF86RandRInfoPtr	    randrp = XF86RANDRINFO(pScreen);
-    DisplayModePtr	    mode;
-    int			    refresh0 = 60;
-    int			    maxX = 0, maxY = 0;
-
-    *rotations = randrp->supported_rotations;
-
-    if (randrp->virtualX == -1 || randrp->virtualY == -1)
-    {
-	randrp->virtualX = scrp->virtualX;
-	randrp->virtualY = scrp->virtualY;
-    }
-
-    /* Re-probe the outputs for new monitors or modes */
-    xf86ProbeOutputModes (scrp, 0, 0);
-    xf86SetScrnInfoModes (scrp);
-    xf86DiDGAReInit (pScreen);
-
-    for (mode = scrp->modes; ; mode = mode->next)
-    {
-	int refresh = xf86RandR12ModeRefresh (mode);
-	if (randrp->maxX == 0 || randrp->maxY == 0)
-	{
-		if (maxX < mode->HDisplay)
-			maxX = mode->HDisplay;
-		if (maxY < mode->VDisplay)
-			maxY = mode->VDisplay;
-	}
-	if (mode == scrp->modes)
-	    refresh0 = refresh;
-	pSize = RRRegisterSize (pScreen,
-				mode->HDisplay, mode->VDisplay,
-				randrp->mmWidth, randrp->mmHeight);
-	if (!pSize)
-	    return FALSE;
-	RRRegisterRate (pScreen, pSize, refresh);
-
-	if (xf86ModesEqual(mode, scrp->currentMode) &&
-	    mode->HDisplay == scrp->virtualX &&
-	    mode->VDisplay == scrp->virtualY)
-	{
-	    RRSetCurrentConfig (pScreen, randrp->rotation, refresh, pSize);
-	}
-	if (mode->next == scrp->modes)
-	    break;
-    }
-
-    if (randrp->maxX == 0 || randrp->maxY == 0)
-    {
-	randrp->maxX = maxX;
-	randrp->maxY = maxY;
-    }
-
-    if (scrp->currentMode->HDisplay != randrp->virtualX ||
-	scrp->currentMode->VDisplay != randrp->virtualY)
-    {
-	pSize = RRRegisterSize (pScreen,
-				randrp->virtualX, randrp->virtualY,
-				randrp->mmWidth,
-				randrp->mmHeight);
-	if (!pSize)
-	    return FALSE;
-	RRRegisterRate (pScreen, pSize, refresh0);
-	if (scrp->virtualX == randrp->virtualX &&
-	    scrp->virtualY == randrp->virtualY)
-	{
-	    RRSetCurrentConfig (pScreen, randrp->rotation, refresh0, pSize);
-	}
-    }
-
-    return TRUE;
-}
-
-static Bool
-xf86RandR12SetMode (ScreenPtr	    pScreen,
-		  DisplayModePtr    mode,
-		  Bool		    useVirtual,
-		  int		    mmWidth,
-		  int		    mmHeight)
-{
-    ScrnInfoPtr		scrp = XF86SCRNINFO(pScreen);
-    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
-    int			oldWidth = pScreen->width;
-    int			oldHeight = pScreen->height;
-    int			oldmmWidth = pScreen->mmWidth;
-    int			oldmmHeight = pScreen->mmHeight;
-    WindowPtr		pRoot = WindowTable[pScreen->myNum];
-    DisplayModePtr      currentMode = NULL;
-    Bool 		ret = TRUE;
-    PixmapPtr 		pspix = NULL;
-
-    if (pRoot)
-	(*scrp->EnableDisableFBAccess) (pScreen->myNum, FALSE);
-    if (useVirtual)
-    {
-	scrp->virtualX = randrp->virtualX;
-	scrp->virtualY = randrp->virtualY;
-    }
-    else
-    {
-	scrp->virtualX = mode->HDisplay;
-	scrp->virtualY = mode->VDisplay;
-    }
-
-    if(randrp->rotation & (RR_Rotate_90 | RR_Rotate_270))
-    {
-	/* If the screen is rotated 90 or 270 degrees, swap the sizes. */
-	pScreen->width = scrp->virtualY;
-	pScreen->height = scrp->virtualX;
-	pScreen->mmWidth = mmHeight;
-	pScreen->mmHeight = mmWidth;
-    }
-    else
-    {
-	pScreen->width = scrp->virtualX;
-	pScreen->height = scrp->virtualY;
-	pScreen->mmWidth = mmWidth;
-	pScreen->mmHeight = mmHeight;
-    }
-    if (scrp->currentMode == mode) {
-        /* Save current mode */
-        currentMode = scrp->currentMode;
-        /* Reset, just so we ensure the drivers SwitchMode is called */
-        scrp->currentMode = NULL;
-    }
-    /*
-     * We know that if the driver failed to SwitchMode to the rotated
-     * version, then it should revert back to it's prior mode.
-     */
-    if (!xf86SwitchMode (pScreen, mode))
-    {
-        ret = FALSE;
-	scrp->virtualX = pScreen->width = oldWidth;
-	scrp->virtualY = pScreen->height = oldHeight;
-	pScreen->mmWidth = oldmmWidth;
-	pScreen->mmHeight = oldmmHeight;
-        scrp->currentMode = currentMode;
-    }
-    /*
-     * Get the new Screen pixmap ptr as SwitchMode might have called
-     * ModifyPixmapHeader and xf86EnableDisableFBAccess will put it back...
-     * Unfortunately.
-     */
-    pspix = (*pScreen->GetScreenPixmap) (pScreen);
-    if (pspix->devPrivate.ptr)
-       scrp->pixmapPrivate = pspix->devPrivate;
-
-    /*
-     * Make sure the layout is correct
-     */
-    xf86ReconfigureLayout();
-
-    /*
-     * Make sure the whole screen is visible
-     */
-    xf86SetViewport (pScreen, pScreen->width, pScreen->height);
-    xf86SetViewport (pScreen, 0, 0);
-    if (pRoot)
-	(*scrp->EnableDisableFBAccess) (pScreen->myNum, TRUE);
-    return ret;
-}
-
-Bool
-xf86RandR12SetConfig (ScreenPtr		pScreen,
-		    Rotation		rotation,
-		    int			rate,
-		    RRScreenSizePtr	pSize)
-{
-    ScrnInfoPtr		scrp = XF86SCRNINFO(pScreen);
-    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
-    DisplayModePtr	mode;
-    int			px, py;
-    Bool		useVirtual = FALSE;
-    int			maxX = 0, maxY = 0;
-    Rotation		oldRotation = randrp->rotation;
-
-    randrp->rotation = rotation;
-
-    if (randrp->virtualX == -1 || randrp->virtualY == -1)
-    {
-	randrp->virtualX = scrp->virtualX;
-	randrp->virtualY = scrp->virtualY;
-    }
-
-    miPointerPosition (&px, &py);
-    for (mode = scrp->modes; ; mode = mode->next)
-    {
-	if (randrp->maxX == 0 || randrp->maxY == 0)
-	{
-		if (maxX < mode->HDisplay)
-			maxX = mode->HDisplay;
-		if (maxY < mode->VDisplay)
-			maxY = mode->VDisplay;
-	}
-	if (mode->HDisplay == pSize->width &&
-	    mode->VDisplay == pSize->height &&
-	    (rate == 0 || xf86RandR12ModeRefresh (mode) == rate))
-	    break;
-	if (mode->next == scrp->modes)
-	{
-	    if (pSize->width == randrp->virtualX &&
-		pSize->height == randrp->virtualY)
-	    {
-		mode = scrp->modes;
-		useVirtual = TRUE;
-		break;
-	    }
-    	    if (randrp->maxX == 0 || randrp->maxY == 0)
-    	    {
-		randrp->maxX = maxX;
-		randrp->maxY = maxY;
-    	    }
-	    return FALSE;
-	}
-    }
-
-    if (randrp->maxX == 0 || randrp->maxY == 0)
-    {
-	randrp->maxX = maxX;
-	randrp->maxY = maxY;
-    }
-
-    if (!xf86RandR12SetMode (pScreen, mode, useVirtual, pSize->mmWidth,
-			   pSize->mmHeight)) {
-        randrp->rotation = oldRotation;
-	return FALSE;
-    }
-
-    /*
-     * Move the cursor back where it belongs; SwitchMode repositions it
-     */
-    if (pScreen == miPointerCurrentScreen ())
-    {
-        px = (px >= pScreen->width ? (pScreen->width - 1) : px);
-        py = (py >= pScreen->height ? (pScreen->height - 1) : py);
-
-	xf86SetViewport(pScreen, px, py);
-
-	(*pScreen->SetCursorPosition) (pScreen, px, py, FALSE);
-    }
-
-    return TRUE;
-}
-
-static Bool
-xf86RandR12ScreenSetSize (ScreenPtr	pScreen,
-			CARD16		width,
-			CARD16		height,
-			CARD32		mmWidth,
-			CARD32		mmHeight)
-{
-    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
-    ScrnInfoPtr		pScrn = XF86SCRNINFO(pScreen);
-    WindowPtr		pRoot = WindowTable[pScreen->myNum];
-    Bool 		ret = TRUE;
-
-    if (randrp->virtualX == -1 || randrp->virtualY == -1)
-    {
-	randrp->virtualX = pScrn->virtualX;
-	randrp->virtualY = pScrn->virtualY;
-    }
-    if (pRoot)
-	(*pScrn->EnableDisableFBAccess) (pScreen->myNum, FALSE);
-    pScrn->virtualX = width;
-    pScrn->virtualY = height;
-
-    pScreen->width = pScrn->virtualX;
-    pScreen->height = pScrn->virtualY;
-    pScreen->mmWidth = mmWidth;
-    pScreen->mmHeight = mmHeight;
-
-    xf86SetViewport (pScreen, pScreen->width-1, pScreen->height-1);
-    xf86SetViewport (pScreen, 0, 0);
-    if (pRoot)
-	(*pScrn->EnableDisableFBAccess) (pScreen->myNum, TRUE);
-#if RANDR_12_INTERFACE
-    if (WindowTable[pScreen->myNum])
-	RRScreenSizeNotify (pScreen);
-#endif
-    return ret;
-}
-
-Rotation
-xf86RandR12GetRotation(ScreenPtr pScreen)
-{
-    XF86RandRInfoPtr	    randrp = XF86RANDRINFO(pScreen);
-
-    return randrp->rotation;
-}
-
-Bool
-xf86RandR12CreateScreenResources (ScreenPtr pScreen)
-{
-    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
-    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
-    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
-    int			c;
-    int			width, height;
-    int			mmWidth, mmHeight;
-#ifdef PANORAMIX
-    /* XXX disable RandR when using Xinerama */
-    if (!noPanoramiXExtension)
-	return TRUE;
-#endif
-
-    /*
-     * Compute size of screen
-     */
-    width = 0; height = 0;
-    for (c = 0; c < config->num_crtc; c++)
-    {
-	xf86CrtcPtr crtc = config->crtc[c];
-	int	    crtc_width = crtc->x + crtc->mode.HDisplay;
-	int	    crtc_height = crtc->y + crtc->mode.VDisplay;
-	
-	if (crtc->enabled && crtc_width > width)
-	    width = crtc_width;
-	if (crtc->enabled && crtc_height > height)
-	    height = crtc_height;
-    }
-    
-    if (width && height)
-    {
-	/*
-	 * Compute physical size of screen
-	 */
-	if (monitorResolution) 
-	{
-	    mmWidth = width * 25.4 / monitorResolution;
-	    mmHeight = height * 25.4 / monitorResolution;
-	}
-	else
-	{
-	    mmWidth = pScreen->mmWidth;
-	    mmHeight = pScreen->mmHeight;
-	}
-	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		   "Setting screen physical size to %d x %d\n",
-		   mmWidth, mmHeight);
-	xf86RandR12ScreenSetSize (pScreen,
-				  width,
-				  height,
-				  mmWidth,
-				  mmHeight);
-    }
-
-    if (randrp->virtualX == -1 || randrp->virtualY == -1)
-    {
-	randrp->virtualX = pScrn->virtualX;
-	randrp->virtualY = pScrn->virtualY;
-    }
-#if RANDR_12_INTERFACE
-    if (xf86RandR12CreateScreenResources12 (pScreen))
-	return TRUE;
-#endif
-    return TRUE;
-}
-
-
-Bool
-xf86RandR12Init (ScreenPtr pScreen)
-{
-    rrScrPrivPtr	rp;
-    XF86RandRInfoPtr	randrp;
-
-#ifdef PANORAMIX
-    /* XXX disable RandR when using Xinerama */
-    if (!noPanoramiXExtension)
-	return TRUE;
-#endif
-    if (xf86RandR12Generation != serverGeneration)
-    {
-	xf86RandR12Index = AllocateScreenPrivateIndex();
-	xf86RandR12Generation = serverGeneration;
-    }
-
-    randrp = xalloc (sizeof (XF86RandRInfoRec));
-    if (!randrp)
-	return FALSE;
-
-    if (!RRScreenInit(pScreen))
-    {
-	xfree (randrp);
-	return FALSE;
-    }
-    rp = rrGetScrPriv(pScreen);
-    rp->rrGetInfo = xf86RandR12GetInfo;
-    rp->rrSetConfig = xf86RandR12SetConfig;
-
-    randrp->virtualX = -1;
-    randrp->virtualY = -1;
-    randrp->mmWidth = pScreen->mmWidth;
-    randrp->mmHeight = pScreen->mmHeight;
-
-    randrp->rotation = RR_Rotate_0; /* initial rotated mode */
-
-    randrp->supported_rotations = RR_Rotate_0;
-
-    randrp->maxX = randrp->maxY = 0;
-
-    pScreen->devPrivates[xf86RandR12Index].ptr = randrp;
-
-#if RANDR_12_INTERFACE
-    if (!xf86RandR12Init12 (pScreen))
-	return FALSE;
-#endif
-    return TRUE;
-}
-
-void
-xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotations)
-{
-    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
-    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
-    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
-    int			c;
-
-    randrp->supported_rotations = rotations;
-
-#if RANDR_12_INTERFACE
-    for (c = 0; c < config->num_crtc; c++) {
-	xf86CrtcPtr    crtc = config->crtc[c];
-
-	RRCrtcSetRotations (crtc->randr_crtc, rotations);
-    }
-#endif
-}
-
-void
-xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y)
-{
-    ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
-
-    if (xf86RandR12Generation != serverGeneration ||
-	XF86RANDRINFO(pScreen)->virtualX == -1)
-    {
-	*x = pScrn->virtualX;
-	*y = pScrn->virtualY;
-    } else {
-	XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
-
-	*x = randrp->virtualX;
-	*y = randrp->virtualY;
-    }
-}
-
-#if RANDR_12_INTERFACE
-static Bool
-xf86RandR12CrtcNotify (RRCrtcPtr	randr_crtc)
-{
-    ScreenPtr		pScreen = randr_crtc->pScreen;
-    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
-    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
-    RRModePtr		randr_mode = NULL;
-    int			x;
-    int			y;
-    Rotation		rotation;
-    int			numOutputs;
-    RROutputPtr		*randr_outputs;
-    RROutputPtr		randr_output;
-    xf86CrtcPtr		crtc = randr_crtc->devPrivate;
-    xf86OutputPtr	output;
-    int			i, j;
-    DisplayModePtr	mode = &crtc->mode;
-    Bool		ret;
-
-    randr_outputs = ALLOCATE_LOCAL(config->num_output * sizeof (RROutputPtr));
-    if (!randr_outputs)
-	return FALSE;
-    x = crtc->x;
-    y = crtc->y;
-    rotation = crtc->rotation;
-    numOutputs = 0;
-    randr_mode = NULL;
-    for (i = 0; i < config->num_output; i++)
-    {
-	output = config->output[i];
-	if (output->crtc == crtc)
-	{
-	    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 < randr_output->numModes; j++)
-	    {
-		DisplayModePtr	outMode = randr_output->modes[j]->devPrivate;
-		if (xf86ModesEqual(mode, outMode))
-		{
-		    randr_mode = randr_output->modes[j];
-		    break;
-		}
-	    }
-	}
-    }
-    ret = RRCrtcNotify (randr_crtc, randr_mode, x, y,
-			rotation, numOutputs, randr_outputs);
-    DEALLOCATE_LOCAL(randr_outputs);
-    return ret;
-}
-
-static Bool
-xf86RandR12CrtcSet (ScreenPtr	pScreen,
-		  RRCrtcPtr	randr_crtc,
-		  RRModePtr	randr_mode,
-		  int		x,
-		  int		y,
-		  Rotation	rotation,
-		  int		num_randr_outputs,
-		  RROutputPtr	*randr_outputs)
-{
-    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
-    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
-    xf86CrtcPtr		crtc = randr_crtc->devPrivate;
-    DisplayModePtr	mode = randr_mode ? randr_mode->devPrivate : NULL;
-    Bool		changed = FALSE;
-    int			o, ro;
-    xf86CrtcPtr		*save_crtcs;
-    Bool		save_enabled = crtc->enabled;
-
-    save_crtcs = ALLOCATE_LOCAL(config->num_crtc * sizeof (xf86CrtcPtr));
-    if ((mode != NULL) != crtc->enabled)
-	changed = TRUE;
-    else if (mode && !xf86ModesEqual (&crtc->mode, mode))
-	changed = TRUE;
-    
-    if (rotation != crtc->rotation)
-	changed = TRUE;
-
-    if (x != crtc->x || y != crtc->y)
-	changed = TRUE;
-    for (o = 0; o < config->num_output; o++) 
-    {
-	xf86OutputPtr  output = config->output[o];
-	xf86CrtcPtr    new_crtc;
-
-	save_crtcs[o] = output->crtc;
-	
-	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])
-	    {
-		new_crtc = crtc;
-		break;
-	    }
-	if (new_crtc != output->crtc)
-	{
-	    changed = TRUE;
-	    output->crtc = new_crtc;
-	}
-    }
-    /* XXX need device-independent mode setting code through an API */
-    if (changed)
-    {
-	crtc->enabled = mode != NULL;
-
-	if (mode)
-	{
-	    if (!xf86CrtcSetMode (crtc, mode, rotation, x, y))
-	    {
-		crtc->enabled = save_enabled;
-		for (o = 0; o < config->num_output; o++)
-		{
-		    xf86OutputPtr	output = config->output[o];
-		    output->crtc = save_crtcs[o];
-		}
-		DEALLOCATE_LOCAL(save_crtcs);
-		return FALSE;
-	    }
-	    /*
-	     * Save the last successful setting for EnterVT
-	     */
-	    crtc->desiredMode = *mode;
-	    crtc->desiredRotation = rotation;
-	    crtc->desiredX = x;
-	    crtc->desiredY = y;
-	}
-	xf86DisableUnusedFunctions (pScrn);
-    }
-    DEALLOCATE_LOCAL(save_crtcs);
-    return xf86RandR12CrtcNotify (randr_crtc);
-}
-
-static Bool
-xf86RandR12CrtcSetGamma (ScreenPtr    pScreen,
-			 RRCrtcPtr    randr_crtc)
-{
-    xf86CrtcPtr		crtc = randr_crtc->devPrivate;
-
-    if (crtc->funcs->gamma_set == NULL)
-	return FALSE;
-
-    crtc->funcs->gamma_set(crtc, randr_crtc->gammaRed, randr_crtc->gammaGreen,
-			   randr_crtc->gammaBlue, randr_crtc->gammaSize);
-
-    return TRUE;
-}
-
-static Bool
-xf86RandR12OutputSetProperty (ScreenPtr pScreen,
-			      RROutputPtr randr_output,
-			      Atom property,
-			      RRPropertyValuePtr value)
-{
-    xf86OutputPtr output = randr_output->devPrivate;
-
-    /* If we don't have any property handler, then we don't care what the
-     * user is setting properties to.
-     */
-    if (output->funcs->set_property == NULL)
-	return TRUE;
-
-    return output->funcs->set_property(output, property, value);
-}
-
-/**
- * Given a list of xf86 modes and a RandR Output object, construct
- * RandR modes and assign them to the output
- */
-static Bool
-xf86RROutputSetModes (RROutputPtr randr_output, DisplayModePtr modes)
-{
-    DisplayModePtr  mode;
-    RRModePtr	    *rrmodes = NULL;
-    int		    nmode = 0;
-    int		    npreferred = 0;
-    Bool	    ret = TRUE;
-    int		    pref;
-
-    for (mode = modes; mode; mode = mode->next)
-	nmode++;
-
-    if (nmode) {
-	rrmodes = xalloc (nmode * sizeof (RRModePtr));
-	
-	if (!rrmodes)
-	    return FALSE;
-	nmode = 0;
-
-	for (pref = 1; pref >= 0; pref--) {
-	    for (mode = modes; mode; mode = mode->next) {
-		if ((pref != 0) == ((mode->type & M_T_PREFERRED) != 0)) {
-		    xRRModeInfo		modeInfo;
-		    RRModePtr		rrmode;
-		    
-		    modeInfo.nameLength = strlen (mode->name);
-		    modeInfo.width = mode->HDisplay;
-		    modeInfo.dotClock = mode->Clock * 1000;
-		    modeInfo.hSyncStart = mode->HSyncStart;
-		    modeInfo.hSyncEnd = mode->HSyncEnd;
-		    modeInfo.hTotal = mode->HTotal;
-		    modeInfo.hSkew = mode->HSkew;
-
-		    modeInfo.height = mode->VDisplay;
-		    modeInfo.vSyncStart = mode->VSyncStart;
-		    modeInfo.vSyncEnd = mode->VSyncEnd;
-		    modeInfo.vTotal = mode->VTotal;
-		    modeInfo.modeFlags = mode->Flags;
-
-		    rrmode = RRModeGet (&modeInfo, mode->name);
-		    if (rrmode) {
-			rrmode->devPrivate = mode;
-			rrmodes[nmode++] = rrmode;
-			npreferred += pref;
-		    }
-		}
-	    }
-	}
-    }
-    
-    ret = RROutputSetModes (randr_output, rrmodes, nmode, npreferred);
-    xfree (rrmodes);
-    return ret;
-}
-
-/*
- * Mirror the current mode configuration to RandR
- */
-static Bool
-xf86RandR12SetInfo12 (ScreenPtr pScreen)
-{
-    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
-    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
-    RROutputPtr		*clones;
-    RRCrtcPtr		*crtcs;
-    int			ncrtc;
-    int			o, c, l;
-    RRCrtcPtr		randr_crtc;
-    int			nclone;
-    
-    clones = ALLOCATE_LOCAL(config->num_output * sizeof (RROutputPtr));
-    crtcs = ALLOCATE_LOCAL (config->num_crtc * sizeof (RRCrtcPtr));
-    for (o = 0; o < config->num_output; o++)
-    {
-	xf86OutputPtr	output = config->output[o];
-	
-	ncrtc = 0;
-	for (c = 0; c < config->num_crtc; c++)
-	    if (output->possible_crtcs & (1 << c))
-		crtcs[ncrtc++] = config->crtc[c]->randr_crtc;
-
-	if (output->crtc)
-	    randr_crtc = output->crtc->randr_crtc;
-	else
-	    randr_crtc = NULL;
-
-	if (!RROutputSetCrtcs (output->randr_output, crtcs, ncrtc))
-	{
-	    DEALLOCATE_LOCAL (crtcs);
-	    DEALLOCATE_LOCAL (clones);
-	    return FALSE;
-	}
-
-	RROutputSetCrtc (output->randr_output, randr_crtc);
-	RROutputSetPhysicalSize(output->randr_output, 
-				output->mm_width,
-				output->mm_height);
-	xf86RROutputSetModes (output->randr_output, output->probed_modes);
-
-	switch (output->status) {
-	case XF86OutputStatusConnected:
-	    RROutputSetConnection (output->randr_output, RR_Connected);
-	    break;
-	case XF86OutputStatusDisconnected:
-	    RROutputSetConnection (output->randr_output, RR_Disconnected);
-	    break;
-	case XF86OutputStatusUnknown:
-	    RROutputSetConnection (output->randr_output, RR_UnknownConnection);
-	    break;
-	}
-
-	RROutputSetSubpixelOrder (output->randr_output, output->subpixel_order);
-
-	/*
-	 * Valid clones
-	 */
-	nclone = 0;
-	for (l = 0; l < config->num_output; l++)
-	{
-	    xf86OutputPtr	    clone = config->output[l];
-	    
-	    if (l != o && (output->possible_clones & (1 << l)))
-		clones[nclone++] = clone->randr_output;
-	}
-	if (!RROutputSetClones (output->randr_output, clones, nclone))
-	{
-	    DEALLOCATE_LOCAL (crtcs);
-	    DEALLOCATE_LOCAL (clones);
-	    return FALSE;
-	}
-    }
-    DEALLOCATE_LOCAL (crtcs);
-    DEALLOCATE_LOCAL (clones);
-    return TRUE;
-}
-
-
-
-/*
- * Query the hardware for the current state, then mirror
- * that to RandR
- */
-static Bool
-xf86RandR12GetInfo12 (ScreenPtr pScreen, Rotation *rotations)
-{
-    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
-
-    xf86ProbeOutputModes (pScrn, 0, 0);
-    xf86SetScrnInfoModes (pScrn);
-    xf86DiDGAReInit (pScreen);
-    return xf86RandR12SetInfo12 (pScreen);
-}
-
-static Bool
-xf86RandR12CreateObjects12 (ScreenPtr pScreen)
-{
-    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
-    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
-    int			c;
-    int			o;
-    
-    if (!RRInit ())
-	return FALSE;
-
-    /*
-     * Configure crtcs
-     */
-    for (c = 0; c < config->num_crtc; c++)
-    {
-	xf86CrtcPtr    crtc = config->crtc[c];
-	
-	crtc->randr_crtc = RRCrtcCreate (crtc);
-	RRCrtcAttachScreen (crtc->randr_crtc, pScreen);
-	RRCrtcGammaSetSize (crtc->randr_crtc, 256);
-    }
-    /*
-     * Configure outputs
-     */
-    for (o = 0; o < config->num_output; o++)
-    {
-	xf86OutputPtr	output = config->output[o];
-
-	output->randr_output = RROutputCreate (output->name, 
-					       strlen (output->name),
-					       output);
-	RROutputAttachScreen (output->randr_output, pScreen);
-
-	if (output->funcs->create_resources != NULL)
-	    output->funcs->create_resources(output);
-    }
-    return TRUE;
-}
-
-static Bool
-xf86RandR12CreateScreenResources12 (ScreenPtr pScreen)
-{
-    int			c;
-    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
-    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
-    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
-
-    for (c = 0; c < config->num_crtc; c++)
-	xf86RandR12CrtcNotify (config->crtc[c]->randr_crtc);
-    
-    
-    RRScreenSetSizeRange (pScreen, 320, 240,
-			  randrp->virtualX, randrp->virtualY);
-    return TRUE;
-}
-
-static void
-xf86RandR12PointerMoved (int scrnIndex, int x, int y)
-{
-}
-
-static Bool
-xf86RandR12Init12 (ScreenPtr pScreen)
-{
-    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
-    rrScrPrivPtr	rp = rrGetScrPriv(pScreen);
-
-    rp->rrGetInfo = xf86RandR12GetInfo12;
-    rp->rrScreenSetSize = xf86RandR12ScreenSetSize;
-    rp->rrCrtcSet = xf86RandR12CrtcSet;
-    rp->rrCrtcSetGamma = xf86RandR12CrtcSetGamma;
-    rp->rrOutputSetProperty = xf86RandR12OutputSetProperty;
-    rp->rrSetConfig = NULL;
-    pScrn->PointerMoved = xf86RandR12PointerMoved;
-    if (!xf86RandR12CreateObjects12 (pScreen))
-	return FALSE;
-
-    /*
-     * Configure output modes
-     */
-    if (!xf86RandR12SetInfo12 (pScreen))
-	return FALSE;
-    return TRUE;
-}
-
-#endif
-
-Bool
-xf86RandR12PreInit (ScrnInfoPtr pScrn)
-{
-    return TRUE;
-}
diff --git a/src/i830_randr.h b/src/i830_randr.h
deleted file mode 100644
index 8a4668b..0000000
--- a/src/i830_randr.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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 xf86RandR12CreateScreenResources (ScreenPtr pScreen);
-Bool xf86RandR12Init(ScreenPtr pScreen);
-void xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotation);
-Bool xf86RandR12SetConfig(ScreenPtr pScreen, Rotation rotation, int rate,
-			RRScreenSizePtr pSize);
-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_tv.c b/src/i830_tv.c
index 5ee8866..95612e4 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -1310,7 +1310,7 @@ i830_tv_detect(xf86OutputPtr output)
     }
 }
 
-struct input_res {
+static struct input_res {
     char *name;
     int w, h;	
 } input_res_table[] = 
diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index 0ea0ced..db05aba 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -33,7 +33,7 @@
 /*#include "i830.h" */
 #include "i830_xf86Crtc.h"
 #include "i830_xf86Modes.h"
-#include "i830_randr.h"
+#include "i830_xf86RandR12.h"
 #include "X11/extensions/render.h"
 #define DPMS_SERVER
 #include "X11/extensions/dpms.h"
@@ -886,7 +886,7 @@ xf86PruneDuplicateMonitorModes (MonPtr M
 /** Return - 0 + if a should be earlier, same or later than b in list
  */
 static int
-i830xf86ModeCompare (DisplayModePtr a, DisplayModePtr b)
+xf86ModeCompare (DisplayModePtr a, DisplayModePtr b)
 {
     int	diff;
 
@@ -904,7 +904,7 @@ i830xf86ModeCompare (DisplayModePtr a, D
  * Insertion sort input in-place and return the resulting head
  */
 static DisplayModePtr
-i830xf86SortModes (DisplayModePtr input)
+xf86SortModes (DisplayModePtr input)
 {
     DisplayModePtr  output = NULL, i, o, n, *op, prev;
 
@@ -914,7 +914,7 @@ i830xf86SortModes (DisplayModePtr input)
 	i = input;
 	input = input->next;
 	for (op = &output; (o = *op); op = &o->next)
-	    if (i830xf86ModeCompare (o, i) > 0)
+	    if (xf86ModeCompare (o, i) > 0)
 		break;
 	i->next = *op;
 	*op = i;
@@ -1109,7 +1109,7 @@ xf86ProbeOutputModes (ScrnInfoPtr scrn, 
 	
 	xf86PruneInvalidModes(scrn, &output->probed_modes, TRUE);
 	
-	output->probed_modes = i830xf86SortModes (output->probed_modes);
+	output->probed_modes = xf86SortModes (output->probed_modes);
 	
 	/* Check for a configured preference for a particular mode */
 	preferred_mode = xf86GetOptValString (output->options,
diff --git a/src/i830_xf86EdidModes.c b/src/i830_xf86EdidModes.c
new file mode 100644
index 0000000..866b9be
--- /dev/null
+++ b/src/i830_xf86EdidModes.c
@@ -0,0 +1,344 @@
+/*
+ * Copyright 2006 Luc Verhaegen.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @file This is a copy of edid_modes.c from the X Server, for compatibility
+ * with old X Servers.
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "xf86.h"
+#include "xf86DDC.h"
+#include <X11/Xatom.h>
+#include "property.h"
+#include "propertyst.h"
+#include "xf86DDC.h"
+#include "i830.h"
+#include "i830_display.h"
+#include <string.h>
+#include <math.h>
+
+#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0)
+
+/*
+ * Quirks to work around broken EDID data from various monitors.
+ */
+
+typedef enum {
+    DDC_QUIRK_NONE = 0,
+    /* Force detailed sync polarity to -h +v */
+    DDC_QUIRK_DT_SYNC_HM_VP = 1 << 0,
+    /* First detailed mode is bogus, prefer largest mode at 60hz */
+    DDC_QUIRK_PREFER_LARGE_60 = 1 << 1,
+    /* 135MHz clock is too high, drop a bit */
+    DDC_QUIRK_135_CLOCK_TOO_HIGH = 1 << 2
+} ddc_quirk_t;
+
+static Bool quirk_dt_sync_hm_vp (int scrnIndex, xf86MonPtr DDC)
+{
+    /* Belinea 1924S1W */
+    if (memcmp (DDC->vendor.name, "MAX", 4) == 0 &&
+	DDC->vendor.prod_id == 1932)
+	return TRUE;
+    /* Belinea 10 20 30W */
+    if (memcmp (DDC->vendor.name, "MAX", 4) == 0 &&
+	DDC->vendor.prod_id == 2007)
+	return TRUE;
+    /* ViewSonic VX2025wm (bug #9941) */
+    if (memcmp (DDC->vendor.name, "VSC", 4) == 0 &&
+	DDC->vendor.prod_id == 58653)
+	return TRUE;
+
+    return FALSE;
+}
+
+static Bool quirk_prefer_large_60 (int scrnIndex, xf86MonPtr DDC)
+{
+    /* Belinea 10 15 55 */
+    if (memcmp (DDC->vendor.name, "MAX", 4) == 0 &&
+	DDC->vendor.prod_id == 1516)
+	return TRUE;
+    
+    return FALSE;
+}
+
+static Bool quirk_135_clock_too_high (int scrnIndex, xf86MonPtr DDC)
+{
+    /* Envision Peripherals, Inc. EN-7100e.  See bug #9550. */
+    if (memcmp (DDC->vendor.name, "EPI", 4) == 0 &&
+	DDC->vendor.prod_id == 59264)
+	return TRUE;
+    
+    return FALSE;
+}
+
+typedef struct {
+    Bool	(*detect) (int scrnIndex, xf86MonPtr DDC);
+    ddc_quirk_t	quirk;
+    char	*description;
+} ddc_quirk_map_t;
+
+static const ddc_quirk_map_t ddc_quirks[] = {
+    { 
+	quirk_dt_sync_hm_vp,	DDC_QUIRK_DT_SYNC_HM_VP,
+	"Set detailed timing sync polarity to -h +v"
+    },
+    {
+	quirk_prefer_large_60,   DDC_QUIRK_PREFER_LARGE_60,
+	"Detailed timing is not preferred, use largest mode at 60Hz"
+    },
+    {
+	quirk_135_clock_too_high,   DDC_QUIRK_135_CLOCK_TOO_HIGH,
+	"Recommended 135MHz pixel clock is too high"
+    },
+    { 
+	NULL,		DDC_QUIRK_NONE,
+	"No known quirks"
+    },
+};
+
+/*
+ * TODO:
+ *  - for those with access to the VESA DMT standard; review please.
+ */
+#define MODEPREFIX(name) NULL, NULL, name, 0,M_T_DRIVER
+#define MODESUFFIX   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,FALSE,FALSE,0,NULL,0,0.0,0.0
+
+static DisplayModeRec DDCEstablishedModes[17] = {
+    { MODEPREFIX("800x600"),    40000,  800,  840,  968, 1056, 0,  600,  601,  605,  628, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600 at 60Hz */
+    { MODEPREFIX("800x600"),    36000,  800,  824,  896, 1024, 0,  600,  601,  603,  625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600 at 56Hz */
+    { MODEPREFIX("640x480"),    31500,  640,  656,  720,  840, 0,  480,  481,  484,  500, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480 at 75Hz */
+    { MODEPREFIX("640x480"),    31500,  640,  664,  704,  832, 0,  480,  489,  491,  520, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480 at 72Hz */
+    { MODEPREFIX("640x480"),    30240,  640,  704,  768,  864, 0,  480,  483,  486,  525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480 at 67Hz */
+    { MODEPREFIX("640x480"),    25200,  640,  656,  752,  800, 0,  480,  490,  492,  525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480 at 60Hz */
+    { MODEPREFIX("720x400"),    35500,  720,  738,  846,  900, 0,  400,  421,  423,  449, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 720x400 at 88Hz */
+    { MODEPREFIX("720x400"),    28320,  720,  738,  846,  900, 0,  400,  412,  414,  449, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 720x400 at 70Hz */
+    { MODEPREFIX("1280x1024"), 135000, 1280, 1296, 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x1024 at 75Hz */
+    { MODEPREFIX("1024x768"),   78800, 1024, 1040, 1136, 1312, 0,  768,  769,  772,  800, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1024x768 at 75Hz */
+    { MODEPREFIX("1024x768"),   75000, 1024, 1048, 1184, 1328, 0,  768,  771,  777,  806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768 at 70Hz */
+    { MODEPREFIX("1024x768"),   65000, 1024, 1048, 1184, 1344, 0,  768,  771,  777,  806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768 at 60Hz */
+    { MODEPREFIX("1024x768"),   44900, 1024, 1032, 1208, 1264, 0,  768,  768,  776,  817, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* 1024x768 at 43Hz */
+    { MODEPREFIX("832x624"),    57284,  832,  864,  928, 1152, 0,  624,  625,  628,  667, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 832x624 at 75Hz */
+    { MODEPREFIX("800x600"),    49500,  800,  816,  896, 1056, 0,  600,  601,  604,  625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600 at 75Hz */
+    { MODEPREFIX("800x600"),    50000,  800,  856,  976, 1040, 0,  600,  637,  643,  666, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600 at 72Hz */
+    { MODEPREFIX("1152x864"),  108000, 1152, 1216, 1344, 1600, 0,  864,  865,  868,  900, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1152x864 at 75Hz */
+};
+
+static DisplayModePtr
+DDCModesFromEstablished(int scrnIndex, struct established_timings *timing,
+			ddc_quirk_t quirks)
+{
+    DisplayModePtr Modes = NULL, Mode = NULL;
+    CARD32 bits = (timing->t1) | (timing->t2 << 8) |
+        ((timing->t_manu & 0x80) << 9);
+    int i;
+
+    for (i = 0; i < 17; i++) {
+        if (bits & (0x01 << i)) {
+            Mode = xf86DuplicateMode(&DDCEstablishedModes[i]);
+            Modes = xf86ModesAdd(Modes, Mode);
+        }
+    }
+
+    return Modes;
+}
+
+/*
+ *
+ */
+static DisplayModePtr
+DDCModesFromStandardTiming(int scrnIndex, struct std_timings *timing,
+			   ddc_quirk_t quirks)
+{
+    DisplayModePtr Modes = NULL, Mode = NULL;
+    int i;
+
+    for (i = 0; i < STD_TIMINGS; i++) {
+        if (timing[i].hsize && timing[i].vsize && timing[i].refresh) {
+            Mode =  xf86CVTMode(timing[i].hsize, timing[i].vsize,
+                                timing[i].refresh, FALSE, FALSE);
+	    Mode->type = M_T_DRIVER;
+            Modes = xf86ModesAdd(Modes, Mode);
+        }
+    }
+
+    return Modes;
+}
+
+/*
+ *
+ */
+static DisplayModePtr
+DDCModeFromDetailedTiming(int scrnIndex, struct detailed_timings *timing,
+			  int preferred, ddc_quirk_t quirks)
+{
+    DisplayModePtr Mode;
+
+    /* We don't do stereo */
+    if (timing->stereo) {
+        xf86DrvMsg(scrnIndex, X_INFO,
+		   "%s: Ignoring: We don't handle stereo.\n", __func__);
+        return NULL;
+    }
+
+    /* We only do seperate sync currently */
+    if (timing->sync != 0x03) {
+         xf86DrvMsg(scrnIndex, X_INFO,
+		    "%s: %dx%d Warning: We only handle seperate"
+                    " sync.\n", __func__, timing->h_active, timing->v_active);
+    }
+
+    Mode = xnfalloc(sizeof(DisplayModeRec));
+    memset(Mode, 0, sizeof(DisplayModeRec));
+
+    Mode->type = M_T_DRIVER;
+    if (preferred)
+	Mode->type |= M_T_PREFERRED;
+
+    if( ( quirks & DDC_QUIRK_135_CLOCK_TOO_HIGH ) &&
+	timing->clock == 135000000 )
+        Mode->Clock = 108880;
+    else
+        Mode->Clock = timing->clock / 1000.0;
+
+    Mode->HDisplay = timing->h_active;
+    Mode->HSyncStart = timing->h_active + timing->h_sync_off;
+    Mode->HSyncEnd = Mode->HSyncStart + timing->h_sync_width;
+    Mode->HTotal = timing->h_active + timing->h_blanking;
+
+    Mode->VDisplay = timing->v_active;
+    Mode->VSyncStart = timing->v_active + timing->v_sync_off;
+    Mode->VSyncEnd = Mode->VSyncStart + timing->v_sync_width;
+    Mode->VTotal = timing->v_active + timing->v_blanking;
+
+    xf86SetModeDefaultName(Mode);
+
+    /* We ignore h/v_size and h/v_border for now. */
+
+    if (timing->interlaced)
+        Mode->Flags |= V_INTERLACE;
+
+    if (quirks & DDC_QUIRK_DT_SYNC_HM_VP)
+	Mode->Flags |= V_NHSYNC | V_PVSYNC;
+    else
+    {
+	if (timing->misc & 0x02)
+	    Mode->Flags |= V_PHSYNC;
+	else
+	    Mode->Flags |= V_NHSYNC;
+    
+	if (timing->misc & 0x01)
+	    Mode->Flags |= V_PVSYNC;
+	else
+	    Mode->Flags |= V_NVSYNC;
+    }
+
+    return Mode;
+}
+
+DisplayModePtr
+xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC)
+{
+    int preferred, i;
+    DisplayModePtr  Modes = NULL, Mode;
+    ddc_quirk_t	    quirks;
+
+    xf86DrvMsg (scrnIndex, X_INFO, "EDID vendor \"%s\", prod id %d\n",
+		DDC->vendor.name, DDC->vendor.prod_id);
+    quirks = DDC_QUIRK_NONE;
+    for (i = 0; ddc_quirks[i].detect; i++)
+	if (ddc_quirks[i].detect (scrnIndex, DDC))
+	{
+	    xf86DrvMsg (scrnIndex, X_INFO, "    EDID quirk: %s\n",
+			ddc_quirks[i].description);
+	    quirks |= ddc_quirks[i].quirk;
+	}
+    
+    preferred = PREFERRED_TIMING_MODE(DDC->features.msc);
+    if (quirks & DDC_QUIRK_PREFER_LARGE_60)
+	preferred = 0;
+
+    for (i = 0; i < DET_TIMINGS; i++) {
+	struct detailed_monitor_section *det_mon = &DDC->det_mon[i];
+
+        switch (det_mon->type) {
+        case DT:
+            Mode = DDCModeFromDetailedTiming(scrnIndex,
+                                             &det_mon->section.d_timings,
+					     preferred,
+					     quirks);
+	    preferred = 0;
+            Modes = xf86ModesAdd(Modes, Mode);
+            break;
+        case DS_STD_TIMINGS:
+            Mode = DDCModesFromStandardTiming(scrnIndex,
+					      det_mon->section.std_t,
+					      quirks);
+            Modes = xf86ModesAdd(Modes, Mode);
+            break;
+        default:
+            break;
+        }
+    }
+
+    /* Add established timings */
+    Mode = DDCModesFromEstablished(scrnIndex, &DDC->timings1, quirks);
+    Modes = xf86ModesAdd(Modes, Mode);
+
+    /* Add standard timings */
+    Mode = DDCModesFromStandardTiming(scrnIndex, DDC->timings2, quirks);
+    Modes = xf86ModesAdd(Modes, Mode);
+
+    if (quirks & DDC_QUIRK_PREFER_LARGE_60)
+    {
+	DisplayModePtr	best = Modes;
+	for (Mode = Modes; Mode; Mode = Mode->next)
+	{
+	    if (Mode == best) continue;
+	    if (Mode->HDisplay * Mode->VDisplay > best->HDisplay * best->VDisplay)
+	    {
+		best = Mode;
+		continue;
+	    }
+	    if (Mode->HDisplay * Mode->VDisplay == best->HDisplay * best->VDisplay)
+	    {
+		double	mode_refresh = xf86ModeVRefresh (Mode);
+		double	best_refresh = xf86ModeVRefresh (best);
+		double	mode_dist = fabs(mode_refresh - 60.0);
+		double	best_dist = fabs(best_refresh - 60.0);
+		if (mode_dist < best_dist)
+		{
+		    best = Mode;
+		    continue;
+		}
+	    }
+	}
+	if (best)
+	    best->type |= M_T_PREFERRED;
+    }
+    return Modes;
+}
+
+#endif /* XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0) */
diff --git a/src/i830_xf86RandR12.c b/src/i830_xf86RandR12.c
new file mode 100644
index 0000000..4ccbdad
--- /dev/null
+++ b/src/i830_xf86RandR12.c
@@ -0,0 +1,950 @@
+/* $XdotOrg: xc/programs/Xserver/hw/xfree86/common/xf86RandR.c,v 1.3 2004/07/30 21:53:09 eich Exp $ */
+/*
+ * $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86RandR.c,v 1.7tsi Exp $
+ *
+ * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "os.h"
+#include "mibank.h"
+#include "globals.h"
+#include "xf86.h"
+#include "xf86Priv.h"
+#include "xf86DDC.h"
+#include "mipointer.h"
+#include "windowstr.h"
+#include <randrstr.h>
+#include <X11/extensions/render.h>
+
+#include "i830_xf86Crtc.h"
+#include "i830_xf86RandR12.h"
+
+typedef struct _xf86RandR12Info {
+    int				    virtualX;
+    int				    virtualY;
+    int				    mmWidth;
+    int				    mmHeight;
+    int				    maxX;
+    int				    maxY;
+    Rotation			    rotation; /* current mode */
+    Rotation                        supported_rotations; /* driver supported */
+} XF86RandRInfoRec, *XF86RandRInfoPtr;
+
+#ifdef RANDR_12_INTERFACE
+static Bool xf86RandR12Init12 (ScreenPtr pScreen);
+static Bool xf86RandR12CreateScreenResources12 (ScreenPtr pScreen);
+#endif
+
+static int	    xf86RandR12Index;
+static int	    xf86RandR12Generation;
+
+#define XF86RANDRINFO(p) \
+	((XF86RandRInfoPtr)(p)->devPrivates[xf86RandR12Index].ptr)
+
+static int
+xf86RandR12ModeRefresh (DisplayModePtr mode)
+{
+    if (mode->VRefresh)
+	return (int) (mode->VRefresh + 0.5);
+    else
+	return (int) (mode->Clock * 1000.0 / mode->HTotal / mode->VTotal + 0.5);
+}
+
+static Bool
+xf86RandR12GetInfo (ScreenPtr pScreen, Rotation *rotations)
+{
+    RRScreenSizePtr	    pSize;
+    ScrnInfoPtr		    scrp = XF86SCRNINFO(pScreen);
+    XF86RandRInfoPtr	    randrp = XF86RANDRINFO(pScreen);
+    DisplayModePtr	    mode;
+    int			    refresh0 = 60;
+    int			    maxX = 0, maxY = 0;
+
+    *rotations = randrp->supported_rotations;
+
+    if (randrp->virtualX == -1 || randrp->virtualY == -1)
+    {
+	randrp->virtualX = scrp->virtualX;
+	randrp->virtualY = scrp->virtualY;
+    }
+
+    /* Re-probe the outputs for new monitors or modes */
+    xf86ProbeOutputModes (scrp, 0, 0);
+    xf86SetScrnInfoModes (scrp);
+    xf86DiDGAReInit (pScreen);
+
+    for (mode = scrp->modes; ; mode = mode->next)
+    {
+	int refresh = xf86RandR12ModeRefresh (mode);
+	if (randrp->maxX == 0 || randrp->maxY == 0)
+	{
+		if (maxX < mode->HDisplay)
+			maxX = mode->HDisplay;
+		if (maxY < mode->VDisplay)
+			maxY = mode->VDisplay;
+	}
+	if (mode == scrp->modes)
+	    refresh0 = refresh;
+	pSize = RRRegisterSize (pScreen,
+				mode->HDisplay, mode->VDisplay,
+				randrp->mmWidth, randrp->mmHeight);
+	if (!pSize)
+	    return FALSE;
+	RRRegisterRate (pScreen, pSize, refresh);
+
+	if (xf86ModesEqual(mode, scrp->currentMode) &&
+	    mode->HDisplay == scrp->virtualX &&
+	    mode->VDisplay == scrp->virtualY)
+	{
+	    RRSetCurrentConfig (pScreen, randrp->rotation, refresh, pSize);
+	}
+	if (mode->next == scrp->modes)
+	    break;
+    }
+
+    if (randrp->maxX == 0 || randrp->maxY == 0)
+    {
+	randrp->maxX = maxX;
+	randrp->maxY = maxY;
+    }
+
+    if (scrp->currentMode->HDisplay != randrp->virtualX ||
+	scrp->currentMode->VDisplay != randrp->virtualY)
+    {
+	pSize = RRRegisterSize (pScreen,
+				randrp->virtualX, randrp->virtualY,
+				randrp->mmWidth,
+				randrp->mmHeight);
+	if (!pSize)
+	    return FALSE;
+	RRRegisterRate (pScreen, pSize, refresh0);
+	if (scrp->virtualX == randrp->virtualX &&
+	    scrp->virtualY == randrp->virtualY)
+	{
+	    RRSetCurrentConfig (pScreen, randrp->rotation, refresh0, pSize);
+	}
+    }
+
+    return TRUE;
+}
+
+static Bool
+xf86RandR12SetMode (ScreenPtr	    pScreen,
+		  DisplayModePtr    mode,
+		  Bool		    useVirtual,
+		  int		    mmWidth,
+		  int		    mmHeight)
+{
+    ScrnInfoPtr		scrp = XF86SCRNINFO(pScreen);
+    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
+    int			oldWidth = pScreen->width;
+    int			oldHeight = pScreen->height;
+    int			oldmmWidth = pScreen->mmWidth;
+    int			oldmmHeight = pScreen->mmHeight;
+    WindowPtr		pRoot = WindowTable[pScreen->myNum];
+    DisplayModePtr      currentMode = NULL;
+    Bool 		ret = TRUE;
+    PixmapPtr 		pspix = NULL;
+
+    if (pRoot)
+	(*scrp->EnableDisableFBAccess) (pScreen->myNum, FALSE);
+    if (useVirtual)
+    {
+	scrp->virtualX = randrp->virtualX;
+	scrp->virtualY = randrp->virtualY;
+    }
+    else
+    {
+	scrp->virtualX = mode->HDisplay;
+	scrp->virtualY = mode->VDisplay;
+    }
+
+    if(randrp->rotation & (RR_Rotate_90 | RR_Rotate_270))
+    {
+	/* If the screen is rotated 90 or 270 degrees, swap the sizes. */
+	pScreen->width = scrp->virtualY;
+	pScreen->height = scrp->virtualX;
+	pScreen->mmWidth = mmHeight;
+	pScreen->mmHeight = mmWidth;
+    }
+    else
+    {
+	pScreen->width = scrp->virtualX;
+	pScreen->height = scrp->virtualY;
+	pScreen->mmWidth = mmWidth;
+	pScreen->mmHeight = mmHeight;
+    }
+    if (scrp->currentMode == mode) {
+        /* Save current mode */
+        currentMode = scrp->currentMode;
+        /* Reset, just so we ensure the drivers SwitchMode is called */
+        scrp->currentMode = NULL;
+    }
+    /*
+     * We know that if the driver failed to SwitchMode to the rotated
+     * version, then it should revert back to it's prior mode.
+     */
+    if (!xf86SwitchMode (pScreen, mode))
+    {
+        ret = FALSE;
+	scrp->virtualX = pScreen->width = oldWidth;
+	scrp->virtualY = pScreen->height = oldHeight;
+	pScreen->mmWidth = oldmmWidth;
+	pScreen->mmHeight = oldmmHeight;
+        scrp->currentMode = currentMode;
+    }
+    /*
+     * Get the new Screen pixmap ptr as SwitchMode might have called
+     * ModifyPixmapHeader and xf86EnableDisableFBAccess will put it back...
+     * Unfortunately.
+     */
+    pspix = (*pScreen->GetScreenPixmap) (pScreen);
+    if (pspix->devPrivate.ptr)
+       scrp->pixmapPrivate = pspix->devPrivate;
+
+    /*
+     * Make sure the layout is correct
+     */
+    xf86ReconfigureLayout();
+
+    /*
+     * Make sure the whole screen is visible
+     */
+    xf86SetViewport (pScreen, pScreen->width, pScreen->height);
+    xf86SetViewport (pScreen, 0, 0);
+    if (pRoot)
+	(*scrp->EnableDisableFBAccess) (pScreen->myNum, TRUE);
+    return ret;
+}
+
+Bool
+xf86RandR12SetConfig (ScreenPtr		pScreen,
+		    Rotation		rotation,
+		    int			rate,
+		    RRScreenSizePtr	pSize)
+{
+    ScrnInfoPtr		scrp = XF86SCRNINFO(pScreen);
+    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
+    DisplayModePtr	mode;
+    int			px, py;
+    Bool		useVirtual = FALSE;
+    int			maxX = 0, maxY = 0;
+    Rotation		oldRotation = randrp->rotation;
+
+    randrp->rotation = rotation;
+
+    if (randrp->virtualX == -1 || randrp->virtualY == -1)
+    {
+	randrp->virtualX = scrp->virtualX;
+	randrp->virtualY = scrp->virtualY;
+    }
+
+    miPointerPosition (&px, &py);
+    for (mode = scrp->modes; ; mode = mode->next)
+    {
+	if (randrp->maxX == 0 || randrp->maxY == 0)
+	{
+		if (maxX < mode->HDisplay)
+			maxX = mode->HDisplay;
+		if (maxY < mode->VDisplay)
+			maxY = mode->VDisplay;
+	}
+	if (mode->HDisplay == pSize->width &&
+	    mode->VDisplay == pSize->height &&
+	    (rate == 0 || xf86RandR12ModeRefresh (mode) == rate))
+	    break;
+	if (mode->next == scrp->modes)
+	{
+	    if (pSize->width == randrp->virtualX &&
+		pSize->height == randrp->virtualY)
+	    {
+		mode = scrp->modes;
+		useVirtual = TRUE;
+		break;
+	    }
+    	    if (randrp->maxX == 0 || randrp->maxY == 0)
+    	    {
+		randrp->maxX = maxX;
+		randrp->maxY = maxY;
+    	    }
+	    return FALSE;
+	}
+    }
+
+    if (randrp->maxX == 0 || randrp->maxY == 0)
+    {
+	randrp->maxX = maxX;
+	randrp->maxY = maxY;
+    }
+
+    if (!xf86RandR12SetMode (pScreen, mode, useVirtual, pSize->mmWidth,
+			   pSize->mmHeight)) {
+        randrp->rotation = oldRotation;
+	return FALSE;
+    }
+
+    /*
+     * Move the cursor back where it belongs; SwitchMode repositions it
+     */
+    if (pScreen == miPointerCurrentScreen ())
+    {
+        px = (px >= pScreen->width ? (pScreen->width - 1) : px);
+        py = (py >= pScreen->height ? (pScreen->height - 1) : py);
+
+	xf86SetViewport(pScreen, px, py);
+
+	(*pScreen->SetCursorPosition) (pScreen, px, py, FALSE);
+    }
+
+    return TRUE;
+}
+
+static Bool
+xf86RandR12ScreenSetSize (ScreenPtr	pScreen,
+			CARD16		width,
+			CARD16		height,
+			CARD32		mmWidth,
+			CARD32		mmHeight)
+{
+    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
+    ScrnInfoPtr		pScrn = XF86SCRNINFO(pScreen);
+    WindowPtr		pRoot = WindowTable[pScreen->myNum];
+    Bool 		ret = TRUE;
+
+    if (randrp->virtualX == -1 || randrp->virtualY == -1)
+    {
+	randrp->virtualX = pScrn->virtualX;
+	randrp->virtualY = pScrn->virtualY;
+    }
+    if (pRoot)
+	(*pScrn->EnableDisableFBAccess) (pScreen->myNum, FALSE);
+    pScrn->virtualX = width;
+    pScrn->virtualY = height;
+
+    pScreen->width = pScrn->virtualX;
+    pScreen->height = pScrn->virtualY;
+    pScreen->mmWidth = mmWidth;
+    pScreen->mmHeight = mmHeight;
+
+    xf86SetViewport (pScreen, pScreen->width-1, pScreen->height-1);
+    xf86SetViewport (pScreen, 0, 0);
+    if (pRoot)
+	(*pScrn->EnableDisableFBAccess) (pScreen->myNum, TRUE);
+#if RANDR_12_INTERFACE
+    if (WindowTable[pScreen->myNum])
+	RRScreenSizeNotify (pScreen);
+#endif
+    return ret;
+}
+
+Rotation
+xf86RandR12GetRotation(ScreenPtr pScreen)
+{
+    XF86RandRInfoPtr	    randrp = XF86RANDRINFO(pScreen);
+
+    return randrp->rotation;
+}
+
+Bool
+xf86RandR12CreateScreenResources (ScreenPtr pScreen)
+{
+    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
+    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
+    int			c;
+    int			width, height;
+    int			mmWidth, mmHeight;
+#ifdef PANORAMIX
+    /* XXX disable RandR when using Xinerama */
+    if (!noPanoramiXExtension)
+	return TRUE;
+#endif
+
+    /*
+     * Compute size of screen
+     */
+    width = 0; height = 0;
+    for (c = 0; c < config->num_crtc; c++)
+    {
+	xf86CrtcPtr crtc = config->crtc[c];
+	int	    crtc_width = crtc->x + crtc->mode.HDisplay;
+	int	    crtc_height = crtc->y + crtc->mode.VDisplay;
+	
+	if (crtc->enabled && crtc_width > width)
+	    width = crtc_width;
+	if (crtc->enabled && crtc_height > height)
+	    height = crtc_height;
+    }
+    
+    if (width && height)
+    {
+	/*
+	 * Compute physical size of screen
+	 */
+	if (monitorResolution) 
+	{
+	    mmWidth = width * 25.4 / monitorResolution;
+	    mmHeight = height * 25.4 / monitorResolution;
+	}
+	else
+	{
+	    mmWidth = pScreen->mmWidth;
+	    mmHeight = pScreen->mmHeight;
+	}
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		   "Setting screen physical size to %d x %d\n",
+		   mmWidth, mmHeight);
+	xf86RandR12ScreenSetSize (pScreen,
+				  width,
+				  height,
+				  mmWidth,
+				  mmHeight);
+    }
+
+    if (randrp->virtualX == -1 || randrp->virtualY == -1)
+    {
+	randrp->virtualX = pScrn->virtualX;
+	randrp->virtualY = pScrn->virtualY;
+    }
+#if RANDR_12_INTERFACE
+    if (xf86RandR12CreateScreenResources12 (pScreen))
+	return TRUE;
+#endif
+    return TRUE;
+}
+
+
+Bool
+xf86RandR12Init (ScreenPtr pScreen)
+{
+    rrScrPrivPtr	rp;
+    XF86RandRInfoPtr	randrp;
+
+#ifdef PANORAMIX
+    /* XXX disable RandR when using Xinerama */
+    if (!noPanoramiXExtension)
+	return TRUE;
+#endif
+    if (xf86RandR12Generation != serverGeneration)
+    {
+	xf86RandR12Index = AllocateScreenPrivateIndex();
+	xf86RandR12Generation = serverGeneration;
+    }
+
+    randrp = xalloc (sizeof (XF86RandRInfoRec));
+    if (!randrp)
+	return FALSE;
+
+    if (!RRScreenInit(pScreen))
+    {
+	xfree (randrp);
+	return FALSE;
+    }
+    rp = rrGetScrPriv(pScreen);
+    rp->rrGetInfo = xf86RandR12GetInfo;
+    rp->rrSetConfig = xf86RandR12SetConfig;
+
+    randrp->virtualX = -1;
+    randrp->virtualY = -1;
+    randrp->mmWidth = pScreen->mmWidth;
+    randrp->mmHeight = pScreen->mmHeight;
+
+    randrp->rotation = RR_Rotate_0; /* initial rotated mode */
+
+    randrp->supported_rotations = RR_Rotate_0;
+
+    randrp->maxX = randrp->maxY = 0;
+
+    pScreen->devPrivates[xf86RandR12Index].ptr = randrp;
+
+#if RANDR_12_INTERFACE
+    if (!xf86RandR12Init12 (pScreen))
+	return FALSE;
+#endif
+    return TRUE;
+}
+
+void
+xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotations)
+{
+    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
+    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int			c;
+
+    randrp->supported_rotations = rotations;
+
+#if RANDR_12_INTERFACE
+    for (c = 0; c < config->num_crtc; c++) {
+	xf86CrtcPtr    crtc = config->crtc[c];
+
+	RRCrtcSetRotations (crtc->randr_crtc, rotations);
+    }
+#endif
+}
+
+void
+xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y)
+{
+    ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
+
+    if (xf86RandR12Generation != serverGeneration ||
+	XF86RANDRINFO(pScreen)->virtualX == -1)
+    {
+	*x = pScrn->virtualX;
+	*y = pScrn->virtualY;
+    } else {
+	XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
+
+	*x = randrp->virtualX;
+	*y = randrp->virtualY;
+    }
+}
+
+#if RANDR_12_INTERFACE
+static Bool
+xf86RandR12CrtcNotify (RRCrtcPtr	randr_crtc)
+{
+    ScreenPtr		pScreen = randr_crtc->pScreen;
+    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
+    RRModePtr		randr_mode = NULL;
+    int			x;
+    int			y;
+    Rotation		rotation;
+    int			numOutputs;
+    RROutputPtr		*randr_outputs;
+    RROutputPtr		randr_output;
+    xf86CrtcPtr		crtc = randr_crtc->devPrivate;
+    xf86OutputPtr	output;
+    int			i, j;
+    DisplayModePtr	mode = &crtc->mode;
+    Bool		ret;
+
+    randr_outputs = ALLOCATE_LOCAL(config->num_output * sizeof (RROutputPtr));
+    if (!randr_outputs)
+	return FALSE;
+    x = crtc->x;
+    y = crtc->y;
+    rotation = crtc->rotation;
+    numOutputs = 0;
+    randr_mode = NULL;
+    for (i = 0; i < config->num_output; i++)
+    {
+	output = config->output[i];
+	if (output->crtc == crtc)
+	{
+	    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 < randr_output->numModes; j++)
+	    {
+		DisplayModePtr	outMode = randr_output->modes[j]->devPrivate;
+		if (xf86ModesEqual(mode, outMode))
+		{
+		    randr_mode = randr_output->modes[j];
+		    break;
+		}
+	    }
+	}
+    }
+    ret = RRCrtcNotify (randr_crtc, randr_mode, x, y,
+			rotation, numOutputs, randr_outputs);
+    DEALLOCATE_LOCAL(randr_outputs);
+    return ret;
+}
+
+static Bool
+xf86RandR12CrtcSet (ScreenPtr	pScreen,
+		  RRCrtcPtr	randr_crtc,
+		  RRModePtr	randr_mode,
+		  int		x,
+		  int		y,
+		  Rotation	rotation,
+		  int		num_randr_outputs,
+		  RROutputPtr	*randr_outputs)
+{
+    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
+    xf86CrtcPtr		crtc = randr_crtc->devPrivate;
+    DisplayModePtr	mode = randr_mode ? randr_mode->devPrivate : NULL;
+    Bool		changed = FALSE;
+    int			o, ro;
+    xf86CrtcPtr		*save_crtcs;
+    Bool		save_enabled = crtc->enabled;
+
+    save_crtcs = ALLOCATE_LOCAL(config->num_crtc * sizeof (xf86CrtcPtr));
+    if ((mode != NULL) != crtc->enabled)
+	changed = TRUE;
+    else if (mode && !xf86ModesEqual (&crtc->mode, mode))
+	changed = TRUE;
+    
+    if (rotation != crtc->rotation)
+	changed = TRUE;
+
+    if (x != crtc->x || y != crtc->y)
+	changed = TRUE;
+    for (o = 0; o < config->num_output; o++) 
+    {
+	xf86OutputPtr  output = config->output[o];
+	xf86CrtcPtr    new_crtc;
+
+	save_crtcs[o] = output->crtc;
+	
+	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])
+	    {
+		new_crtc = crtc;
+		break;
+	    }
+	if (new_crtc != output->crtc)
+	{
+	    changed = TRUE;
+	    output->crtc = new_crtc;
+	}
+    }
+    /* XXX need device-independent mode setting code through an API */
+    if (changed)
+    {
+	crtc->enabled = mode != NULL;
+
+	if (mode)
+	{
+	    if (!xf86CrtcSetMode (crtc, mode, rotation, x, y))
+	    {
+		crtc->enabled = save_enabled;
+		for (o = 0; o < config->num_output; o++)
+		{
+		    xf86OutputPtr	output = config->output[o];
+		    output->crtc = save_crtcs[o];
+		}
+		DEALLOCATE_LOCAL(save_crtcs);
+		return FALSE;
+	    }
+	    /*
+	     * Save the last successful setting for EnterVT
+	     */
+	    crtc->desiredMode = *mode;
+	    crtc->desiredRotation = rotation;
+	    crtc->desiredX = x;
+	    crtc->desiredY = y;
+	}
+	xf86DisableUnusedFunctions (pScrn);
+    }
+    DEALLOCATE_LOCAL(save_crtcs);
+    return xf86RandR12CrtcNotify (randr_crtc);
+}
+
+static Bool
+xf86RandR12CrtcSetGamma (ScreenPtr    pScreen,
+			 RRCrtcPtr    randr_crtc)
+{
+    xf86CrtcPtr		crtc = randr_crtc->devPrivate;
+
+    if (crtc->funcs->gamma_set == NULL)
+	return FALSE;
+
+    crtc->funcs->gamma_set(crtc, randr_crtc->gammaRed, randr_crtc->gammaGreen,
+			   randr_crtc->gammaBlue, randr_crtc->gammaSize);
+
+    return TRUE;
+}
+
+static Bool
+xf86RandR12OutputSetProperty (ScreenPtr pScreen,
+			      RROutputPtr randr_output,
+			      Atom property,
+			      RRPropertyValuePtr value)
+{
+    xf86OutputPtr output = randr_output->devPrivate;
+
+    /* If we don't have any property handler, then we don't care what the
+     * user is setting properties to.
+     */
+    if (output->funcs->set_property == NULL)
+	return TRUE;
+
+    return output->funcs->set_property(output, property, value);
+}
+
+/**
+ * Given a list of xf86 modes and a RandR Output object, construct
+ * RandR modes and assign them to the output
+ */
+static Bool
+xf86RROutputSetModes (RROutputPtr randr_output, DisplayModePtr modes)
+{
+    DisplayModePtr  mode;
+    RRModePtr	    *rrmodes = NULL;
+    int		    nmode = 0;
+    int		    npreferred = 0;
+    Bool	    ret = TRUE;
+    int		    pref;
+
+    for (mode = modes; mode; mode = mode->next)
+	nmode++;
+
+    if (nmode) {
+	rrmodes = xalloc (nmode * sizeof (RRModePtr));
+	
+	if (!rrmodes)
+	    return FALSE;
+	nmode = 0;
+
+	for (pref = 1; pref >= 0; pref--) {
+	    for (mode = modes; mode; mode = mode->next) {
+		if ((pref != 0) == ((mode->type & M_T_PREFERRED) != 0)) {
+		    xRRModeInfo		modeInfo;
+		    RRModePtr		rrmode;
+		    
+		    modeInfo.nameLength = strlen (mode->name);
+		    modeInfo.width = mode->HDisplay;
+		    modeInfo.dotClock = mode->Clock * 1000;
+		    modeInfo.hSyncStart = mode->HSyncStart;
+		    modeInfo.hSyncEnd = mode->HSyncEnd;
+		    modeInfo.hTotal = mode->HTotal;
+		    modeInfo.hSkew = mode->HSkew;
+
+		    modeInfo.height = mode->VDisplay;
+		    modeInfo.vSyncStart = mode->VSyncStart;
+		    modeInfo.vSyncEnd = mode->VSyncEnd;
+		    modeInfo.vTotal = mode->VTotal;
+		    modeInfo.modeFlags = mode->Flags;
+
+		    rrmode = RRModeGet (&modeInfo, mode->name);
+		    if (rrmode) {
+			rrmode->devPrivate = mode;
+			rrmodes[nmode++] = rrmode;
+			npreferred += pref;
+		    }
+		}
+	    }
+	}
+    }
+    
+    ret = RROutputSetModes (randr_output, rrmodes, nmode, npreferred);
+    xfree (rrmodes);
+    return ret;
+}
+
+/*
+ * Mirror the current mode configuration to RandR
+ */
+static Bool
+xf86RandR12SetInfo12 (ScreenPtr pScreen)
+{
+    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
+    RROutputPtr		*clones;
+    RRCrtcPtr		*crtcs;
+    int			ncrtc;
+    int			o, c, l;
+    RRCrtcPtr		randr_crtc;
+    int			nclone;
+    
+    clones = ALLOCATE_LOCAL(config->num_output * sizeof (RROutputPtr));
+    crtcs = ALLOCATE_LOCAL (config->num_crtc * sizeof (RRCrtcPtr));
+    for (o = 0; o < config->num_output; o++)
+    {
+	xf86OutputPtr	output = config->output[o];
+	
+	ncrtc = 0;
+	for (c = 0; c < config->num_crtc; c++)
+	    if (output->possible_crtcs & (1 << c))
+		crtcs[ncrtc++] = config->crtc[c]->randr_crtc;
+
+	if (output->crtc)
+	    randr_crtc = output->crtc->randr_crtc;
+	else
+	    randr_crtc = NULL;
+
+	if (!RROutputSetCrtcs (output->randr_output, crtcs, ncrtc))
+	{
+	    DEALLOCATE_LOCAL (crtcs);
+	    DEALLOCATE_LOCAL (clones);
+	    return FALSE;
+	}
+
+	RROutputSetCrtc (output->randr_output, randr_crtc);
+	RROutputSetPhysicalSize(output->randr_output, 
+				output->mm_width,
+				output->mm_height);
+	xf86RROutputSetModes (output->randr_output, output->probed_modes);
+
+	switch (output->status) {
+	case XF86OutputStatusConnected:
+	    RROutputSetConnection (output->randr_output, RR_Connected);
+	    break;
+	case XF86OutputStatusDisconnected:
+	    RROutputSetConnection (output->randr_output, RR_Disconnected);
+	    break;
+	case XF86OutputStatusUnknown:
+	    RROutputSetConnection (output->randr_output, RR_UnknownConnection);
+	    break;
+	}
+
+	RROutputSetSubpixelOrder (output->randr_output, output->subpixel_order);
+
+	/*
+	 * Valid clones
+	 */
+	nclone = 0;
+	for (l = 0; l < config->num_output; l++)
+	{
+	    xf86OutputPtr	    clone = config->output[l];
+	    
+	    if (l != o && (output->possible_clones & (1 << l)))
+		clones[nclone++] = clone->randr_output;
+	}
+	if (!RROutputSetClones (output->randr_output, clones, nclone))
+	{
+	    DEALLOCATE_LOCAL (crtcs);
+	    DEALLOCATE_LOCAL (clones);
+	    return FALSE;
+	}
+    }
+    DEALLOCATE_LOCAL (crtcs);
+    DEALLOCATE_LOCAL (clones);
+    return TRUE;
+}
+
+
+
+/*
+ * Query the hardware for the current state, then mirror
+ * that to RandR
+ */
+static Bool
+xf86RandR12GetInfo12 (ScreenPtr pScreen, Rotation *rotations)
+{
+    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+
+    xf86ProbeOutputModes (pScrn, 0, 0);
+    xf86SetScrnInfoModes (pScrn);
+    xf86DiDGAReInit (pScreen);
+    return xf86RandR12SetInfo12 (pScreen);
+}
+
+static Bool
+xf86RandR12CreateObjects12 (ScreenPtr pScreen)
+{
+    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int			c;
+    int			o;
+    
+    if (!RRInit ())
+	return FALSE;
+
+    /*
+     * Configure crtcs
+     */
+    for (c = 0; c < config->num_crtc; c++)
+    {
+	xf86CrtcPtr    crtc = config->crtc[c];
+	
+	crtc->randr_crtc = RRCrtcCreate (crtc);
+	RRCrtcAttachScreen (crtc->randr_crtc, pScreen);
+	RRCrtcGammaSetSize (crtc->randr_crtc, 256);
+    }
+    /*
+     * Configure outputs
+     */
+    for (o = 0; o < config->num_output; o++)
+    {
+	xf86OutputPtr	output = config->output[o];
+
+	output->randr_output = RROutputCreate (output->name, 
+					       strlen (output->name),
+					       output);
+	RROutputAttachScreen (output->randr_output, pScreen);
+
+	if (output->funcs->create_resources != NULL)
+	    output->funcs->create_resources(output);
+    }
+    return TRUE;
+}
+
+static Bool
+xf86RandR12CreateScreenResources12 (ScreenPtr pScreen)
+{
+    int			c;
+    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
+    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
+
+    for (c = 0; c < config->num_crtc; c++)
+	xf86RandR12CrtcNotify (config->crtc[c]->randr_crtc);
+    
+    
+    RRScreenSetSizeRange (pScreen, 320, 240,
+			  randrp->virtualX, randrp->virtualY);
+    return TRUE;
+}
+
+static void
+xf86RandR12PointerMoved (int scrnIndex, int x, int y)
+{
+}
+
+static Bool
+xf86RandR12Init12 (ScreenPtr pScreen)
+{
+    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+    rrScrPrivPtr	rp = rrGetScrPriv(pScreen);
+
+    rp->rrGetInfo = xf86RandR12GetInfo12;
+    rp->rrScreenSetSize = xf86RandR12ScreenSetSize;
+    rp->rrCrtcSet = xf86RandR12CrtcSet;
+    rp->rrCrtcSetGamma = xf86RandR12CrtcSetGamma;
+    rp->rrOutputSetProperty = xf86RandR12OutputSetProperty;
+    rp->rrSetConfig = NULL;
+    pScrn->PointerMoved = xf86RandR12PointerMoved;
+    if (!xf86RandR12CreateObjects12 (pScreen))
+	return FALSE;
+
+    /*
+     * Configure output modes
+     */
+    if (!xf86RandR12SetInfo12 (pScreen))
+	return FALSE;
+    return TRUE;
+}
+
+#endif
+
+Bool
+xf86RandR12PreInit (ScrnInfoPtr pScrn)
+{
+    return TRUE;
+}
diff --git a/src/i830_xf86RandR12.h b/src/i830_xf86RandR12.h
new file mode 100644
index 0000000..8a4668b
--- /dev/null
+++ b/src/i830_xf86RandR12.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 xf86RandR12CreateScreenResources (ScreenPtr pScreen);
+Bool xf86RandR12Init(ScreenPtr pScreen);
+void xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotation);
+Bool xf86RandR12SetConfig(ScreenPtr pScreen, Rotation rotation, int rate,
+			RRScreenSizePtr pSize);
+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_xf86Rename.h b/src/i830_xf86Rename.h
index de2eb9a..a00253d 100644
--- a/src/i830_xf86Rename.h
+++ b/src/i830_xf86Rename.h
@@ -64,5 +64,14 @@
 #define xf86ValidateModesUserConfig XF86NAME(xf86ValidateModesUserConfig)
 #define xf86DiDGAInit XF86NAME(xf86DiDGAInit)
 #define xf86DiDGAReInit XF86NAME(xf86DiDGAReInit)
+#define xf86DDCGetModes XF86NAME(xf86DDCGetModes)
+#define xf86RandR12CreateScreenResources XF86NAME(xf86RandR12CreateScreenResources)
+#define xf86RandR12GetOriginalVirtualSize XF86NAME(xf86RandR12GetOriginalVirtualSize)
+#define xf86RandR12GetRotation XF86NAME(xf86RandR12GetRotation)
+#define xf86RandR12Init XF86NAME(xf86RandR12Init)
+#define xf86RandR12PreInit XF86NAME(xf86RandR12PreInit)
+#define xf86RandR12SetConfig XF86NAME(xf86RandR12SetConfig)
+#define xf86RandR12SetRotations XF86NAME(xf86RandR12SetRotations)
+#define xf86SaveScreen XF86NAME(xf86SaveScreen)
 
 #endif /* _XF86RENAME_H_ */
diff --git a/src/i830_xf86Rotate.c b/src/i830_xf86Rotate.c
index 2491e7b..8240f67 100644
--- a/src/i830_xf86Rotate.c
+++ b/src/i830_xf86Rotate.c
@@ -34,7 +34,7 @@
 #include "windowstr.h"
 #include "i830_xf86Crtc.h"
 #include "i830_xf86Modes.h"
-#include "i830_randr.h"
+#include "i830_xf86RandR12.h"
 #include "X11/extensions/render.h"
 #define DPMS_SERVER
 #include "X11/extensions/dpms.h"
diff-tree 22a271555a46267c40448fa926d45692498ef7c6 (from a7c64d5e28f608d54c94fa7a5c92bd5b471179c7)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Wed Feb 14 14:17:14 2007 -0800

    Create driver-independent DGA hooks, remove i830 DGA code.
    
    As RandR needs to poke at DGA code, and we want the RandR code to be
    driver-independent, it seemed easier to just make the DGA code
    driver-independent as well.

diff --git a/src/Makefile.am b/src/Makefile.am
index 6c63cc4..a94e14c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -59,7 +59,6 @@ intel_drv_la_SOURCES = \
          i830_cursor.c \
 	 i830_debug.c \
 	 i830_debug.h \
-         i830_dga.c \
 	 i830_display.c \
 	 i830_display.h \
          i830_driver.c \
@@ -85,6 +84,7 @@ intel_drv_la_SOURCES = \
 	 i830_xf86Crtc.h \
 	 i830_xf86Crtc.c \
 	 i830_xf86Rotate.c \
+	 i830_xf86DiDGA.c \
 	 i915_3d.c \
 	 i915_3d.h \
 	 i915_reg.h \
diff --git a/src/i830_dga.c b/src/i830_dga.c
deleted file mode 100644
index 817d96d..0000000
--- a/src/i830_dga.c
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * Copyright 2000 by Alan Hourihane, Sychdyn, North Wales, UK.
- *
- * 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 Alan Hourihane not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission.  Alan Hourihane makes no representations
- * about the suitability of this software for any purpose.  It is provided
- * "as is" without express or implied warranty.
- *
- * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL ALAN HOURIHANE 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.
- *
- * Authors:  Alan Hourihane, <alanh at fairlite.demon.co.uk>
- */
-/*
- * Reformatted with GNU indent (2.2.8), using the following options:
- *
- *    -bad -bap -c41 -cd0 -ncdb -ci6 -cli0 -cp0 -ncs -d0 -di3 -i3 -ip3 -l78
- *    -lp -npcs -psl -sob -ss -br -ce -sc -hnl
- *
- * This provides a good match with the original i810 code and preferred
- * XFree86 formatting conventions.
- *
- * When editing this driver, please follow the existing formatting, and edit
- * with <TAB> characters expanded at 8-column intervals.
- */
-
-/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_dga.c,v 1.2 2002/11/05 02:01:18 dawes Exp $ */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "xf86.h"
-#include "xf86DDC.h"
-#include "xf86_OSproc.h"
-#include "dgaproc.h"
-#include "i830_xf86Crtc.h"
-#include "i830_xf86Modes.h"
-#include "gcstruct.h"
-
-static DGAModePtr
-xf86_dga_get_modes (ScreenPtr pScreen, int *nump)
-{
-    ScrnInfoPtr	    pScrn = xf86Screens[pScreen->myNum];
-    DGAModePtr	    modes, mode;
-    DisplayModePtr  display_mode;
-    int		    bpp = pScrn->bitsPerPixel >> 3;
-    int		    num;
-    PixmapPtr	    pPixmap = pScreen->GetScreenPixmap (pScreen);
-
-    if (!pPixmap)
-	return NULL;
-
-    num = 0;
-    display_mode = pScrn->modes;
-    while (display_mode) 
-    {
-	num++;
-	display_mode = display_mode->next;
-	if (display_mode == pScrn->modes)
-	    break;
-    }
-    
-    if (!num)
-	return NULL;
-    
-    modes = xalloc(num * sizeof(DGAModeRec));
-    if (!modes)
-	return NULL;
-    
-    num = 0;
-    display_mode = pScrn->modes;
-    while (display_mode) 
-    {
-	mode = modes + num++;
-
-	mode->mode = display_mode;
-	mode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
-        mode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT;
-	if (display_mode->Flags & V_DBLSCAN)
-	    mode->flags |= DGA_DOUBLESCAN;
-	if (display_mode->Flags & V_INTERLACE)
-	    mode->flags |= DGA_INTERLACED;
-	mode->byteOrder = pScrn->imageByteOrder;
-	mode->depth = pScrn->depth;
-	mode->bitsPerPixel = pScrn->bitsPerPixel;
-	mode->red_mask = pScrn->mask.red;
-	mode->green_mask = pScrn->mask.green;
-	mode->blue_mask = pScrn->mask.blue;
-	mode->visualClass = (bpp == 1) ? PseudoColor : TrueColor;
-	mode->viewportWidth = display_mode->HDisplay;
-	mode->viewportHeight = display_mode->VDisplay;
-	mode->xViewportStep = (bpp == 3) ? 2 : 1;
-	mode->yViewportStep = 1;
-	mode->viewportFlags = DGA_FLIP_RETRACE;
-	mode->offset = 0;
-	mode->address = pPixmap->devPrivate.ptr;
-	mode->bytesPerScanline = pPixmap->devKind;
-	mode->imageWidth = pPixmap->drawable.width;
-	mode->imageHeight = pPixmap->drawable.height;
-	mode->pixmapWidth = mode->imageWidth;
-	mode->pixmapHeight = mode->imageHeight;
-	mode->maxViewportX = mode->imageWidth -	mode->viewportWidth;
-	mode->maxViewportY = mode->imageHeight - mode->viewportHeight;
-
-	display_mode = display_mode->next;
-	if (display_mode == pScrn->modes)
-	    break;
-    }
-    *nump = num;
-    return modes;
-}
-
-static Bool
-xf86_dga_set_mode(ScrnInfoPtr pScrn, DGAModePtr display_mode)
-{
-    ScreenPtr	pScreen = pScrn->pScreen;
-
-    if (!display_mode) 
-	xf86SwitchMode(pScreen, pScrn->currentMode);
-    else
-	xf86SwitchMode(pScreen, display_mode->mode);
-
-    return TRUE;
-}
-
-static int
-xf86_dga_get_viewport(ScrnInfoPtr pScrn)
-{
-    return 0;
-}
-
-static void
-xf86_dga_set_viewport(ScrnInfoPtr pScrn, int x, int y, int flags)
-{
-   pScrn->AdjustFrame(pScrn->pScreen->myNum, x, y, flags);
-}
-
-static void
-xf86_dga_fill_rect(ScrnInfoPtr pScrn, int x, int y, int w, int h, unsigned long color)
-{
-    ScreenPtr	pScreen = pScrn->pScreen;
-    WindowPtr	pRoot = WindowTable [pScreen->myNum];
-    GCPtr	pGC = GetScratchGC (pRoot->drawable.depth, pScreen);
-    XID		vals[2];
-    xRectangle	r;
-
-    if (!pGC)
-	return;
-    vals[0] = color;
-    vals[1] = IncludeInferiors;
-    ChangeGC (pGC, GCForeground|GCSubwindowMode, vals);
-    ValidateGC (&pRoot->drawable, pGC);
-    r.x = x;
-    r.y = y;
-    r.width = w;
-    r.height = h;
-    pGC->ops->PolyFillRect (&pRoot->drawable, pGC, 1, &r);
-    FreeScratchGC (pGC);
-}
-
-static void
-xf86_dga_sync(ScrnInfoPtr pScrn)
-{
-    ScreenPtr	pScreen = pScrn->pScreen;
-    WindowPtr	pRoot = WindowTable [pScreen->myNum];
-    char	buffer[4];
-
-    pScreen->GetImage (&pRoot->drawable, 0, 0, 1, 1, ZPixmap, ~0L, buffer);
-}
-
-static void
-xf86_dga_blit_rect(ScrnInfoPtr pScrn, int srcx, int srcy, int w, int h, int dstx, int dsty)
-{
-    ScreenPtr	pScreen = pScrn->pScreen;
-    WindowPtr	pRoot = WindowTable [pScreen->myNum];
-    GCPtr	pGC = GetScratchGC (pRoot->drawable.depth, pScreen);
-    XID		vals[1];
-
-    if (!pGC)
-	return;
-    vals[0] = IncludeInferiors;
-    ChangeGC (pGC, GCSubwindowMode, vals);
-    ValidateGC (&pRoot->drawable, pGC);
-    pGC->ops->CopyArea (&pRoot->drawable, &pRoot->drawable, pGC,
-			srcx, srcy, w, h, dstx, dsty);
-    FreeScratchGC (pGC);
-}
-
-static Bool
-xf86_dga_open_framebuffer(ScrnInfoPtr pScrn,
-		     char **name,
-		     unsigned char **mem, int *size, int *offset, int *flags)
-{
-    ScreenPtr	pScreen = pScrn->pScreen;
-    PixmapPtr	pPixmap = pScreen->GetScreenPixmap (pScreen);
-    
-    if (!pPixmap)
-	return FALSE;
-    
-    *size = pPixmap->drawable.height * pPixmap->devKind;
-    *mem = (unsigned char *) (pScrn->memPhysBase + pScrn->fbOffset);
-    *offset = 0;
-    *flags = DGA_NEED_ROOT;
-
-    return TRUE;
-}
-
-static void
-xf86_dga_close_framebuffer(ScrnInfoPtr pScrn)
-{
-}
-
-static DGAFunctionRec xf86_dga_funcs = {
-   xf86_dga_open_framebuffer,
-   xf86_dga_close_framebuffer,
-   xf86_dga_set_mode,
-   xf86_dga_set_viewport,
-   xf86_dga_get_viewport,
-   xf86_dga_sync,
-   xf86_dga_fill_rect,
-   xf86_dga_blit_rect,
-   NULL
-};
-
-static DGAModePtr   xf86_dga_modes[MAXSCREENS];
-
-Bool
-xf86_dga_reinit (ScreenPtr pScreen)
-{
-    int		num;
-    DGAModePtr	modes;
-
-    modes = xf86_dga_get_modes (pScreen, &num);
-    if (!modes)
-	return FALSE;
-
-    if (xf86_dga_modes[pScreen->myNum])
-	xfree (xf86_dga_modes[pScreen->myNum]);
-
-    xf86_dga_modes[pScreen->myNum] = modes;
-    return DGAReInitModes (pScreen, modes, num);
-}
-
-Bool
-xf86_dga_init (ScreenPtr pScreen)
-{
-    int		num;
-    DGAModePtr	modes;
-
-    modes = xf86_dga_get_modes (pScreen, &num);
-    if (!modes)
-	return FALSE;
-
-    if (xf86_dga_modes[pScreen->myNum])
-	xfree (xf86_dga_modes[pScreen->myNum]);
-
-    xf86_dga_modes[pScreen->myNum] = modes;
-    return DGAInit(pScreen, &xf86_dga_funcs, modes, num);
-}
-
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 4b87ec5..56903e1 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2727,7 +2727,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 
    xf86SetBlackWhitePixels(pScreen);
 
-   xf86_dga_init (pScreen);
+   xf86DiDGAInit (pScreen, pI830->LinearAddr + pScrn->fbOffset);
 
    DPRINTF(PFX,
 	   "assert( if(!I830InitFBManager(pScreen, &(pI830->FbMemBox))) )\n");
@@ -3393,7 +3393,7 @@ I830CheckDevicesTimer(OsTimerPtr timer, 
       
       xf86ProbeOutputModes (pScrn, 0, 0);
       xf86SetScrnInfoModes (pScrn);
-      xf86_dga_reinit (pScrn->pScreen);
+      xf86DiDGAReInit (pScrn->pScreen);
       xf86SwitchMode(pScrn->pScreen, pScrn->currentMode);
 
       /* Clear the BIOS's hotkey press flags */
diff --git a/src/i830_randr.c b/src/i830_randr.c
index 03ca504..b9cc9aa 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -94,7 +94,7 @@ xf86RandR12GetInfo (ScreenPtr pScreen, R
     /* Re-probe the outputs for new monitors or modes */
     xf86ProbeOutputModes (scrp, 0, 0);
     xf86SetScrnInfoModes (scrp);
-    xf86_dga_reinit (pScreen);
+    xf86DiDGAReInit (pScreen);
 
     for (mode = scrp->modes; ; mode = mode->next)
     {
@@ -851,7 +851,7 @@ xf86RandR12GetInfo12 (ScreenPtr pScreen,
 
     xf86ProbeOutputModes (pScrn, 0, 0);
     xf86SetScrnInfoModes (pScrn);
-    xf86_dga_reinit (pScreen);
+    xf86DiDGAReInit (pScreen);
     return xf86RandR12SetInfo12 (pScreen);
 }
 
diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h
index 2d77328..53d2cdb 100644
--- a/src/i830_xf86Crtc.h
+++ b/src/i830_xf86Crtc.h
@@ -414,7 +414,12 @@ typedef struct _xf86CrtcConfig {
     DamagePtr   rotationDamage;
 
     /* DGA */
-    unsigned int dga_flags;
+    unsigned int	dga_flags;
+    unsigned long	dga_address;
+    DGAModePtr		dga_modes;
+    int			dga_nmode;
+    int			dga_width, dga_height, dga_stride;
+    DisplayModePtr	dga_save_mode;
 
 } xf86CrtcConfigRec, *xf86CrtcConfigPtr;
 
@@ -536,13 +541,13 @@ xf86OutputGetEDID (xf86OutputPtr output,
  */
 
 Bool
-xf86_dga_init (ScreenPtr pScreen);
+xf86DiDGAInit (ScreenPtr pScreen, unsigned long dga_address);
 
 /**
  * Re-initialize dga for this screen (as when the set of modes changes)
  */
 
 Bool
-xf86_dga_reinit (ScreenPtr pScreen);
+xf86DiDGAReInit (ScreenPtr pScreen);
 
 #endif /* _XF86CRTC_H_ */
diff --git a/src/i830_xf86DiDGA.c b/src/i830_xf86DiDGA.c
new file mode 100644
index 0000000..24a5297
--- /dev/null
+++ b/src/i830_xf86DiDGA.c
@@ -0,0 +1,280 @@
+/*
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "xf86DDC.h"
+#include "xf86_OSproc.h"
+#include "dgaproc.h"
+#include "i830_xf86Crtc.h"
+#include "i830_xf86Modes.h"
+#include "gcstruct.h"
+
+static Bool
+xf86_dga_get_modes (ScreenPtr pScreen)
+{
+    ScrnInfoPtr		scrn = xf86Screens[pScreen->myNum];
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+    DGAModePtr		modes, mode;
+    DisplayModePtr	display_mode;
+    int			bpp = scrn->bitsPerPixel >> 3;
+    int			num;
+
+    num = 0;
+    display_mode = scrn->modes;
+    while (display_mode) 
+    {
+	num++;
+	display_mode = display_mode->next;
+	if (display_mode == scrn->modes)
+	    break;
+    }
+    
+    if (!num)
+	return FALSE;
+    
+    modes = xalloc(num * sizeof(DGAModeRec));
+    if (!modes)
+	return FALSE;
+    
+    num = 0;
+    display_mode = scrn->modes;
+    while (display_mode) 
+    {
+	mode = modes + num++;
+
+	mode->mode = display_mode;
+	mode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
+        mode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT;
+	if (display_mode->Flags & V_DBLSCAN)
+	    mode->flags |= DGA_DOUBLESCAN;
+	if (display_mode->Flags & V_INTERLACE)
+	    mode->flags |= DGA_INTERLACED;
+	mode->byteOrder = scrn->imageByteOrder;
+	mode->depth = scrn->depth;
+	mode->bitsPerPixel = scrn->bitsPerPixel;
+	mode->red_mask = scrn->mask.red;
+	mode->green_mask = scrn->mask.green;
+	mode->blue_mask = scrn->mask.blue;
+	mode->visualClass = (bpp == 1) ? PseudoColor : TrueColor;
+	mode->viewportWidth = display_mode->HDisplay;
+	mode->viewportHeight = display_mode->VDisplay;
+	mode->xViewportStep = (bpp == 3) ? 2 : 1;
+	mode->yViewportStep = 1;
+	mode->viewportFlags = DGA_FLIP_RETRACE;
+	mode->offset = 0;
+	mode->address = (unsigned char *) xf86_config->dga_address;
+	mode->bytesPerScanline = xf86_config->dga_stride;
+	mode->imageWidth = xf86_config->dga_width;
+	mode->imageHeight = xf86_config->dga_height;
+	mode->pixmapWidth = mode->imageWidth;
+	mode->pixmapHeight = mode->imageHeight;
+	mode->maxViewportX = mode->imageWidth -	mode->viewportWidth;
+	mode->maxViewportY = mode->imageHeight - mode->viewportHeight;
+
+	display_mode = display_mode->next;
+	if (display_mode == scrn->modes)
+	    break;
+    }
+    if (xf86_config->dga_modes)
+	xfree (xf86_config->dga_modes);
+    xf86_config->dga_nmode = num;
+    xf86_config->dga_modes = modes;
+    return TRUE;
+}
+
+static Bool
+xf86_dga_set_mode(ScrnInfoPtr scrn, DGAModePtr display_mode)
+{
+    ScreenPtr		pScreen = scrn->pScreen;
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+
+    if (!display_mode) 
+    {
+	if (xf86_config->dga_save_mode)
+	{
+	    xf86SwitchMode(pScreen, xf86_config->dga_save_mode);
+	    xf86_config->dga_save_mode = NULL;
+	}
+    }
+    else
+    {
+	if (!xf86_config->dga_save_mode)
+	{
+	    xf86_config->dga_save_mode = scrn->currentMode;
+	    xf86SwitchMode(pScreen, display_mode->mode);
+	}
+    }
+    return TRUE;
+}
+
+static int
+xf86_dga_get_viewport(ScrnInfoPtr scrn)
+{
+    return 0;
+}
+
+static void
+xf86_dga_set_viewport(ScrnInfoPtr scrn, int x, int y, int flags)
+{
+   scrn->AdjustFrame(scrn->pScreen->myNum, x, y, flags);
+}
+
+static Bool
+xf86_dga_get_drawable_and_gc (ScrnInfoPtr scrn, DrawablePtr *ppDrawable, GCPtr *ppGC)
+{
+    ScreenPtr		pScreen = scrn->pScreen;
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+    PixmapPtr		pPixmap;
+    GCPtr		pGC;
+    
+    pPixmap = GetScratchPixmapHeader (pScreen, xf86_config->dga_width, xf86_config->dga_height,
+				      scrn->depth, scrn->bitsPerPixel, xf86_config->dga_stride, 
+				      (char *) scrn->memPhysBase + scrn->fbOffset);
+    if (!pPixmap)
+	return FALSE;
+    pGC  = GetScratchGC (scrn->depth, pScreen);
+    if (!pGC)
+    {
+	FreeScratchPixmapHeader (pPixmap);
+	return FALSE;
+    }
+    *ppDrawable = &pPixmap->drawable;
+    *ppGC = pGC;
+    return TRUE;
+}
+
+static void
+xf86_dga_release_drawable_and_gc (ScrnInfoPtr scrn, DrawablePtr pDrawable, GCPtr pGC)
+{
+    FreeScratchGC (pGC);
+    FreeScratchPixmapHeader ((PixmapPtr) pDrawable);
+}
+
+static void
+xf86_dga_fill_rect(ScrnInfoPtr scrn, int x, int y, int w, int h, unsigned long color)
+{
+    GCPtr		pGC;
+    DrawablePtr		pDrawable;
+    XID			vals[1];
+    xRectangle		r;
+
+    if (!xf86_dga_get_drawable_and_gc (scrn, &pDrawable, &pGC))
+	return;
+    vals[0] = color;
+    ChangeGC (pGC, GCForeground, vals);
+    ValidateGC (pDrawable, pGC);
+    r.x = x;
+    r.y = y;
+    r.width = w;
+    r.height = h;
+    pGC->ops->PolyFillRect (pDrawable, pGC, 1, &r);
+    xf86_dga_release_drawable_and_gc (scrn, pDrawable, pGC);
+}
+
+static void
+xf86_dga_sync(ScrnInfoPtr scrn)
+{
+    ScreenPtr	pScreen = scrn->pScreen;
+    WindowPtr	pRoot = WindowTable [pScreen->myNum];
+    char	buffer[4];
+
+    pScreen->GetImage (&pRoot->drawable, 0, 0, 1, 1, ZPixmap, ~0L, buffer);
+}
+
+static void
+xf86_dga_blit_rect(ScrnInfoPtr scrn, int srcx, int srcy, int w, int h, int dstx, int dsty)
+{
+    DrawablePtr	pDrawable;
+    GCPtr	pGC;
+
+    if (!xf86_dga_get_drawable_and_gc (scrn, &pDrawable, &pGC))
+	return;
+    ValidateGC (pDrawable, pGC);
+    pGC->ops->CopyArea (pDrawable, pDrawable, pGC, srcx, srcy, w, h, dstx, dsty);
+    xf86_dga_release_drawable_and_gc (scrn, pDrawable, pGC);
+}
+
+static Bool
+xf86_dga_open_framebuffer(ScrnInfoPtr scrn,
+			  char **name,
+			  unsigned char **mem, int *size, int *offset, int *flags)
+{
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+    
+    *size = xf86_config->dga_stride * xf86_config->dga_height;
+    *mem = (unsigned char *) (xf86_config->dga_address);
+    *offset = 0;
+    *flags = DGA_NEED_ROOT;
+
+    return TRUE;
+}
+
+static void
+xf86_dga_close_framebuffer(ScrnInfoPtr scrn)
+{
+}
+
+static DGAFunctionRec xf86_dga_funcs = {
+   xf86_dga_open_framebuffer,
+   xf86_dga_close_framebuffer,
+   xf86_dga_set_mode,
+   xf86_dga_set_viewport,
+   xf86_dga_get_viewport,
+   xf86_dga_sync,
+   xf86_dga_fill_rect,
+   xf86_dga_blit_rect,
+   NULL
+};
+
+Bool
+xf86DiDGAReInit (ScreenPtr pScreen)
+{
+    ScrnInfoPtr		scrn = xf86Screens[pScreen->myNum];
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+    
+    if (!xf86_dga_get_modes (pScreen))
+	return FALSE;
+    
+    return DGAReInitModes (pScreen, xf86_config->dga_modes, xf86_config->dga_nmode);
+}
+
+Bool
+xf86DiDGAInit (ScreenPtr pScreen, unsigned long dga_address)
+{
+    ScrnInfoPtr		scrn = xf86Screens[pScreen->myNum];
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+
+    xf86_config->dga_flags = 0;
+    xf86_config->dga_address = dga_address;
+    xf86_config->dga_width = scrn->virtualX;
+    xf86_config->dga_height = scrn->virtualY;
+    xf86_config->dga_stride = scrn->displayWidth * scrn->bitsPerPixel >> 3;
+    
+    if (!xf86_dga_get_modes (pScreen))
+	return FALSE;
+    
+    return DGAInit(pScreen, &xf86_dga_funcs, xf86_config->dga_modes, xf86_config->dga_nmode);
+}
diff --git a/src/i830_xf86Rename.h b/src/i830_xf86Rename.h
index cf8de62..de2eb9a 100644
--- a/src/i830_xf86Rename.h
+++ b/src/i830_xf86Rename.h
@@ -62,5 +62,7 @@
 #define xf86ValidateModesSize XF86NAME(xf86ValidateModesSize)
 #define xf86ValidateModesSync XF86NAME(xf86ValidateModesSync)
 #define xf86ValidateModesUserConfig XF86NAME(xf86ValidateModesUserConfig)
+#define xf86DiDGAInit XF86NAME(xf86DiDGAInit)
+#define xf86DiDGAReInit XF86NAME(xf86DiDGAReInit)
 
 #endif /* _XF86RENAME_H_ */
diff-tree a7c64d5e28f608d54c94fa7a5c92bd5b471179c7 (from 1623b47c4863f5362587cdac855e3e11c109b007)
Author: root <root at guitar.keithp.com>
Date:   Wed Feb 14 10:20:28 2007 -0800

    WIP DGA generic support.

diff --git a/src/i830.h b/src/i830.h
index 96972eb..7a442d8 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -521,9 +521,6 @@ extern void I830SelectBuffer(ScrnInfoPtr
 extern void I830RefreshRing(ScrnInfoPtr pScrn);
 extern void I830EmitFlush(ScrnInfoPtr pScrn);
 
-extern Bool I830DGAReInit(ScreenPtr pScreen);
-extern Bool I830DGAInit(ScreenPtr pScreen);
-
 #ifdef I830_XV
 extern void I830InitVideo(ScreenPtr pScreen);
 extern void i830_crtc_dpms_video(xf86CrtcPtr crtc, Bool on);
diff --git a/src/i830_dga.c b/src/i830_dga.c
index 6d071ac..817d96d 100644
--- a/src/i830_dga.c
+++ b/src/i830_dga.c
@@ -41,407 +41,231 @@
 #endif
 
 #include "xf86.h"
+#include "xf86DDC.h"
 #include "xf86_OSproc.h"
-#include "xf86Pci.h"
-#include "xf86PciInfo.h"
-#include "xaa.h"
-#include "xaalocal.h"
-#include "i830.h"
-#include "i810_reg.h"
 #include "dgaproc.h"
-#include "vgaHW.h"
-
-static Bool I830_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **,
-				 int *, int *, int *);
-static void I830_CloseFramebuffer(ScrnInfoPtr pScrn);
-static Bool I830_SetMode(ScrnInfoPtr, DGAModePtr);
-static void I830_Sync(ScrnInfoPtr);
-static int I830_GetViewport(ScrnInfoPtr);
-static void I830_SetViewport(ScrnInfoPtr, int, int, int);
-static void I830_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
-static void I830_BlitRect(ScrnInfoPtr, int, int, int, int, int, int);
-
-#if 0
-static void I830_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int,
-			       unsigned long);
-#endif
-
-static
-DGAFunctionRec I830DGAFuncs = {
-   I830_OpenFramebuffer,
-   I830_CloseFramebuffer,
-   I830_SetMode,
-   I830_SetViewport,
-   I830_GetViewport,
-   I830_Sync,
-   I830_FillRect,
-   I830_BlitRect,
-#if 0
-   I830_BlitTransRect
-#else
-   NULL
-#endif
-};
+#include "i830_xf86Crtc.h"
+#include "i830_xf86Modes.h"
+#include "gcstruct.h"
 
 static DGAModePtr
-I830DGAModes (ScreenPtr pScreen, int *nump)
-{
-   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-   I830Ptr pI830 = I830PTR(pScrn);
-   DGAModePtr modes = NULL, newmodes = NULL, currentMode;
-   DisplayModePtr pMode, firstMode;
-   int Bpp = pScrn->bitsPerPixel >> 3;
-   int num = 0;
-
-   pMode = firstMode = pScrn->modes;
-
-   while (pMode) {
-
-      newmodes = xrealloc(modes, (num + 1) * sizeof(DGAModeRec));
-
-      if (!newmodes) {
-	 xfree(modes);
-	 return NULL;
-      }
-      modes = newmodes;
-
-      currentMode = modes + num;
-      num++;
-
-      currentMode->mode = pMode;
-      currentMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
-      if (!pI830->noAccel)
-	 currentMode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT;
-      if (pMode->Flags & V_DBLSCAN)
-	 currentMode->flags |= DGA_DOUBLESCAN;
-      if (pMode->Flags & V_INTERLACE)
-	 currentMode->flags |= DGA_INTERLACED;
-      currentMode->byteOrder = pScrn->imageByteOrder;
-      currentMode->depth = pScrn->depth;
-      currentMode->bitsPerPixel = pScrn->bitsPerPixel;
-      currentMode->red_mask = pScrn->mask.red;
-      currentMode->green_mask = pScrn->mask.green;
-      currentMode->blue_mask = pScrn->mask.blue;
-      currentMode->visualClass = (Bpp == 1) ? PseudoColor : TrueColor;
-      currentMode->viewportWidth = pMode->HDisplay;
-      currentMode->viewportHeight = pMode->VDisplay;
-      currentMode->xViewportStep = (Bpp == 3) ? 2 : 1;
-      currentMode->yViewportStep = 1;
-      currentMode->viewportFlags = DGA_FLIP_RETRACE;
-      currentMode->offset = 0;
-      if (I830IsPrimary(pScrn)) {
-         currentMode->address = pI830->FbBase + pI830->FrontBuffer.Start;
-      } else {
-         I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
-         currentMode->address = pI830->FbBase + pI8301->FrontBuffer2.Start;
-      }
-
-      currentMode->bytesPerScanline = ((pI830->displayWidth * Bpp) + 3) & ~3L;
-      if (I830IsPrimary(pScrn)) {
-         currentMode->imageWidth = pI830->FbMemBox.x2;
-         currentMode->imageHeight = pI830->FbMemBox.y2;
-      } else {
-         I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
-         currentMode->imageWidth = pI8301->FbMemBox2.x2;
-         currentMode->imageHeight = pI8301->FbMemBox2.y2;
-      }
-      currentMode->pixmapWidth = currentMode->imageWidth;
-      currentMode->pixmapHeight = currentMode->imageHeight;
-      currentMode->maxViewportX = currentMode->imageWidth -
-	    currentMode->viewportWidth;
-      /* this might need to get clamped to some maximum */
-      currentMode->maxViewportY = currentMode->imageHeight -
-	    currentMode->viewportHeight;
-
-      pMode = pMode->next;
-      if (pMode == firstMode)
-	 break;
-   }
-   *nump = num;
-   return modes;
-}
-
-Bool
-I830DGAReInit(ScreenPtr pScreen)
-{
-   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-   I830Ptr pI830 = I830PTR(pScrn);
-   int num;
-   DGAModePtr  modes;
-   
-   modes = I830DGAModes (pScreen, &num);
-   if (!modes)
-      return FALSE;
-   
-   if (pI830->DGAModes)
-      xfree (pI830->DGAModes);
-   
-   pI830->numDGAModes = num;
-   pI830->DGAModes = modes;
-   return DGAReInitModes (pScreen, modes, num);
-}
-
-Bool
-I830DGAInit(ScreenPtr pScreen)
+xf86_dga_get_modes (ScreenPtr pScreen, int *nump)
 {
-   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-   I830Ptr pI830 = I830PTR(pScrn);
-   int num;
-   DGAModePtr  modes;
-   
-   modes = I830DGAModes (pScreen, &num);
-   if (!modes)
-      return FALSE;
-   
-   pI830->numDGAModes = num;
-   pI830->DGAModes = modes;
-
-   return DGAInit(pScreen, &I830DGAFuncs, modes, num);
+    ScrnInfoPtr	    pScrn = xf86Screens[pScreen->myNum];
+    DGAModePtr	    modes, mode;
+    DisplayModePtr  display_mode;
+    int		    bpp = pScrn->bitsPerPixel >> 3;
+    int		    num;
+    PixmapPtr	    pPixmap = pScreen->GetScreenPixmap (pScreen);
+
+    if (!pPixmap)
+	return NULL;
+
+    num = 0;
+    display_mode = pScrn->modes;
+    while (display_mode) 
+    {
+	num++;
+	display_mode = display_mode->next;
+	if (display_mode == pScrn->modes)
+	    break;
+    }
+    
+    if (!num)
+	return NULL;
+    
+    modes = xalloc(num * sizeof(DGAModeRec));
+    if (!modes)
+	return NULL;
+    
+    num = 0;
+    display_mode = pScrn->modes;
+    while (display_mode) 
+    {
+	mode = modes + num++;
+
+	mode->mode = display_mode;
+	mode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
+        mode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT;
+	if (display_mode->Flags & V_DBLSCAN)
+	    mode->flags |= DGA_DOUBLESCAN;
+	if (display_mode->Flags & V_INTERLACE)
+	    mode->flags |= DGA_INTERLACED;
+	mode->byteOrder = pScrn->imageByteOrder;
+	mode->depth = pScrn->depth;
+	mode->bitsPerPixel = pScrn->bitsPerPixel;
+	mode->red_mask = pScrn->mask.red;
+	mode->green_mask = pScrn->mask.green;
+	mode->blue_mask = pScrn->mask.blue;
+	mode->visualClass = (bpp == 1) ? PseudoColor : TrueColor;
+	mode->viewportWidth = display_mode->HDisplay;
+	mode->viewportHeight = display_mode->VDisplay;
+	mode->xViewportStep = (bpp == 3) ? 2 : 1;
+	mode->yViewportStep = 1;
+	mode->viewportFlags = DGA_FLIP_RETRACE;
+	mode->offset = 0;
+	mode->address = pPixmap->devPrivate.ptr;
+	mode->bytesPerScanline = pPixmap->devKind;
+	mode->imageWidth = pPixmap->drawable.width;
+	mode->imageHeight = pPixmap->drawable.height;
+	mode->pixmapWidth = mode->imageWidth;
+	mode->pixmapHeight = mode->imageHeight;
+	mode->maxViewportX = mode->imageWidth -	mode->viewportWidth;
+	mode->maxViewportY = mode->imageHeight - mode->viewportHeight;
+
+	display_mode = display_mode->next;
+	if (display_mode == pScrn->modes)
+	    break;
+    }
+    *nump = num;
+    return modes;
 }
 
-static DisplayModePtr I830SavedDGAModes[MAXSCREENS];
-
 static Bool
-I830_SetMode(ScrnInfoPtr pScrn, DGAModePtr pMode)
+xf86_dga_set_mode(ScrnInfoPtr pScrn, DGAModePtr display_mode)
 {
-   int index = pScrn->pScreen->myNum;
-   I830Ptr pI830 = I830PTR(pScrn);
-
-   MARKER();
-
-   if (!pMode) {			/* restore the original mode */
-      DPRINTF(PFX, "Restoring original mode (from DGA mode)\n");
-      if (pI830->DGAactive) {
-         I830_CloseFramebuffer(pScrn);
-	 pScrn->currentMode = I830SavedDGAModes[index];
-	 pScrn->SwitchMode(index, pScrn->currentMode, 0);
-	 pScrn->AdjustFrame(index, 0, 0, 0);
-	 pI830->DGAactive = FALSE;
-      }
-   } else {
-      if (!pI830->DGAactive) {
-	 DPRINTF(PFX, "Setting DGA mode\n");
-	 I830SavedDGAModes[index] = pScrn->currentMode;
-	 pI830->DGAactive = TRUE;
-         if (I830IsPrimary(pScrn)) {
-            pScrn->fbOffset = pI830->FrontBuffer.Start;
-         }
-         else {
-            I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
-            pScrn->fbOffset = pI8301->FrontBuffer2.Start;
-         }
-         pScrn->displayWidth = pI830->displayWidth;
-         I830SelectBuffer(pScrn, I830_SELECT_FRONT);
-      }
+    ScreenPtr	pScreen = pScrn->pScreen;
 
-      pScrn->SwitchMode(index, pMode->mode, 0);
-   }
+    if (!display_mode) 
+	xf86SwitchMode(pScreen, pScrn->currentMode);
+    else
+	xf86SwitchMode(pScreen, display_mode->mode);
 
-   return TRUE;
+    return TRUE;
 }
 
 static int
-I830_GetViewport(ScrnInfoPtr pScrn)
+xf86_dga_get_viewport(ScrnInfoPtr pScrn)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
-
-   MARKER();
-
-   return pI830->DGAViewportStatus;
+    return 0;
 }
 
 static void
-I830_SetViewport(ScrnInfoPtr pScrn, int x, int y, int flags)
+xf86_dga_set_viewport(ScrnInfoPtr pScrn, int x, int y, int flags)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
-   vgaHWPtr hwp = VGAHWPTR(pScrn);
-
-   MARKER();
-
    pScrn->AdjustFrame(pScrn->pScreen->myNum, x, y, flags);
-
-   /* wait for retrace */
-   while ((hwp->readST01(hwp) & 0x08)) ;
-   while (!(hwp->readST01(hwp) & 0x08)) ;
-
-   pI830->DGAViewportStatus = 0;
 }
 
 static void
-I830_FillRect(ScrnInfoPtr pScrn,
-	      int x, int y, int w, int h, unsigned long color)
+xf86_dga_fill_rect(ScrnInfoPtr pScrn, int x, int y, int w, int h, unsigned long color)
 {
-#ifdef I830_USE_XAA
-   I830Ptr pI830 = I830PTR(pScrn);
-
-   MARKER();
-
-   if (pI830->AccelInfoRec) {
-      (*pI830->AccelInfoRec->SetupForSolidFill) (pScrn, color, GXcopy, ~0);
-      (*pI830->AccelInfoRec->SubsequentSolidFillRect) (pScrn, x, y, w, h);
-      SET_SYNC_FLAG(pI830->AccelInfoRec);
-   }
-#endif
+    ScreenPtr	pScreen = pScrn->pScreen;
+    WindowPtr	pRoot = WindowTable [pScreen->myNum];
+    GCPtr	pGC = GetScratchGC (pRoot->drawable.depth, pScreen);
+    XID		vals[2];
+    xRectangle	r;
+
+    if (!pGC)
+	return;
+    vals[0] = color;
+    vals[1] = IncludeInferiors;
+    ChangeGC (pGC, GCForeground|GCSubwindowMode, vals);
+    ValidateGC (&pRoot->drawable, pGC);
+    r.x = x;
+    r.y = y;
+    r.width = w;
+    r.height = h;
+    pGC->ops->PolyFillRect (&pRoot->drawable, pGC, 1, &r);
+    FreeScratchGC (pGC);
 }
 
 static void
-I830_Sync(ScrnInfoPtr pScrn)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   int flags = MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE;
-
-   MARKER();
-
-   if (pI830->noAccel) 
-      return;
-
-   if (IS_I965G(pI830))
-      flags = 0;
-
-   BEGIN_LP_RING(2);
-   OUT_RING(MI_FLUSH | flags);
-   OUT_RING(MI_NOOP);		/* pad to quadword */
-   ADVANCE_LP_RING();
-
-   I830WaitLpRing(pScrn, pI830->LpRing->mem.Size - 8, 0);
-
-   pI830->LpRing->space = pI830->LpRing->mem.Size - 8;
-   pI830->nextColorExpandBuf = 0;
+xf86_dga_sync(ScrnInfoPtr pScrn)
+{
+    ScreenPtr	pScreen = pScrn->pScreen;
+    WindowPtr	pRoot = WindowTable [pScreen->myNum];
+    char	buffer[4];
+
+    pScreen->GetImage (&pRoot->drawable, 0, 0, 1, 1, ZPixmap, ~0L, buffer);
 }
 
 static void
-I830_BlitRect(ScrnInfoPtr pScrn,
-	      int srcx, int srcy, int w, int h, int dstx, int dsty)
-{
-#ifdef I830_USE_XAA
-   I830Ptr pI830 = I830PTR(pScrn);
-
-   MARKER();
+xf86_dga_blit_rect(ScrnInfoPtr pScrn, int srcx, int srcy, int w, int h, int dstx, int dsty)
+{
+    ScreenPtr	pScreen = pScrn->pScreen;
+    WindowPtr	pRoot = WindowTable [pScreen->myNum];
+    GCPtr	pGC = GetScratchGC (pRoot->drawable.depth, pScreen);
+    XID		vals[1];
+
+    if (!pGC)
+	return;
+    vals[0] = IncludeInferiors;
+    ChangeGC (pGC, GCSubwindowMode, vals);
+    ValidateGC (&pRoot->drawable, pGC);
+    pGC->ops->CopyArea (&pRoot->drawable, &pRoot->drawable, pGC,
+			srcx, srcy, w, h, dstx, dsty);
+    FreeScratchGC (pGC);
+}
 
-   if (pI830->AccelInfoRec) {
-      int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
-      int ydir = (srcy < dsty) ? -1 : 1;
-
-      (*pI830->AccelInfoRec->SetupForScreenToScreenCopy) (pScrn, xdir, ydir,
-							  GXcopy, ~0, -1);
-      (*pI830->AccelInfoRec->SubsequentScreenToScreenCopy) (pScrn, srcx, srcy,
-							    dstx, dsty, w, h);
-      SET_SYNC_FLAG(pI830->AccelInfoRec);
-   }
-#endif
+static Bool
+xf86_dga_open_framebuffer(ScrnInfoPtr pScrn,
+		     char **name,
+		     unsigned char **mem, int *size, int *offset, int *flags)
+{
+    ScreenPtr	pScreen = pScrn->pScreen;
+    PixmapPtr	pPixmap = pScreen->GetScreenPixmap (pScreen);
+    
+    if (!pPixmap)
+	return FALSE;
+    
+    *size = pPixmap->drawable.height * pPixmap->devKind;
+    *mem = (unsigned char *) (pScrn->memPhysBase + pScrn->fbOffset);
+    *offset = 0;
+    *flags = DGA_NEED_ROOT;
+
+    return TRUE;
 }
 
-#if 0
 static void
-I830_BlitTransRect(ScrnInfoPtr pScrn,
-		   int srcx, int srcy,
-		   int w, int h, int dstx, int dsty, unsigned long color)
+xf86_dga_close_framebuffer(ScrnInfoPtr pScrn)
 {
+}
 
-   MARKER();
+static DGAFunctionRec xf86_dga_funcs = {
+   xf86_dga_open_framebuffer,
+   xf86_dga_close_framebuffer,
+   xf86_dga_set_mode,
+   xf86_dga_set_viewport,
+   xf86_dga_get_viewport,
+   xf86_dga_sync,
+   xf86_dga_fill_rect,
+   xf86_dga_blit_rect,
+   NULL
+};
 
-   /* this one should be separate since the XAA function would
-    * prohibit usage of ~0 as the key */
-}
-#endif
+static DGAModePtr   xf86_dga_modes[MAXSCREENS];
 
-static Bool
-I830_OpenFramebuffer(ScrnInfoPtr pScrn,
-		     char **name,
-		     unsigned char **mem, int *size, int *offset, int *flags)
+Bool
+xf86_dga_reinit (ScreenPtr pScreen)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
+    int		num;
+    DGAModePtr	modes;
 
-   MARKER();
+    modes = xf86_dga_get_modes (pScreen, &num);
+    if (!modes)
+	return FALSE;
 
-   *name = NULL;			/* no special device */
-   if (I830IsPrimary(pScrn)) {
-      *size = pI830->FrontBuffer.Size;
-      *mem = (unsigned char *)(pI830->LinearAddr + pI830->FrontBuffer.Start);
-      pScrn->fbOffset = pI830->FrontBuffer.Start;
-   }
-   else {
-      I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
-      *size = pI8301->FrontBuffer2.Size;
-      *mem = (unsigned char *)(pI8301->LinearAddr + pI8301->FrontBuffer2.Start);
-      pScrn->fbOffset = pI8301->FrontBuffer2.Start;
-   }
-   pScrn->displayWidth = pI830->displayWidth;
-   I830SelectBuffer(pScrn, I830_SELECT_FRONT);
-   *offset = 0;
-   *flags = DGA_NEED_ROOT;
-
-   DPRINTF(PFX,
-	   " mem == 0x%.8x (pI830->LinearAddr)\n"
-	   "size == %lu (pI830->FbMapSize)\n", *mem, *size);
+    if (xf86_dga_modes[pScreen->myNum])
+	xfree (xf86_dga_modes[pScreen->myNum]);
 
-   return TRUE;
+    xf86_dga_modes[pScreen->myNum] = modes;
+    return DGAReInitModes (pScreen, modes, num);
 }
 
-static void
-I830_CloseFramebuffer(ScrnInfoPtr pScrn)
+Bool
+xf86_dga_init (ScreenPtr pScreen)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
-   int i;
-   /* Good pitches to allow tiling.  Don't care about pitches < 1024. */
-   static const int pitches[] = {
-/*
-	 128 * 2,
-	 128 * 4,
-*/
-	 128 * 8,
-	 128 * 16,
-	 128 * 32,
-	 128 * 64,
-	 0
-   };
-
-   if (I830IsPrimary(pScrn)) {
-     pScrn->fbOffset = pI830->FrontBuffer.Start;
-   } else {
-      I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
-
-      pScrn->fbOffset = pI8301->FrontBuffer2.Start;
-   }
-   I830SelectBuffer(pScrn, I830_SELECT_FRONT);
-
-   switch (pI830->rotation) {
-      case RR_Rotate_0:
-         pScrn->displayWidth = pI830->displayWidth;
-         break;
-      case RR_Rotate_90:
-         pScrn->displayWidth = pScrn->pScreen->width;
-         break;
-      case RR_Rotate_180:
-         pScrn->displayWidth = pI830->displayWidth;
-         break;
-      case RR_Rotate_270:
-         pScrn->displayWidth = pScrn->pScreen->width;
-         break;
-   }
-
-   /* As DRI doesn't run on the secondary head, we know that disableTiling
-    * is always TRUE.
-    */
-   if (I830IsPrimary(pScrn) && !pI830->disableTiling) {
-#if 0
-      int dWidth = pScrn->displayWidth; /* save current displayWidth */
-#endif
+    int		num;
+    DGAModePtr	modes;
+
+    modes = xf86_dga_get_modes (pScreen, &num);
+    if (!modes)
+	return FALSE;
 
-      for (i = 0; pitches[i] != 0; i++) {
-         if (pitches[i] >= pScrn->displayWidth) {
-            pScrn->displayWidth = pitches[i];
-            break;
-         }
-      }
-
-      /*
-       * If the displayWidth is a tilable pitch, test if there's enough
-       * memory available to enable tiling.
-       */
-      if (pScrn->displayWidth == pitches[i]) {
-  	/* TODO */
-      }
-   }
+    if (xf86_dga_modes[pScreen->myNum])
+	xfree (xf86_dga_modes[pScreen->myNum]);
 
+    xf86_dga_modes[pScreen->myNum] = modes;
+    return DGAInit(pScreen, &xf86_dga_funcs, modes, num);
 }
+
diff --git a/src/i830_driver.c b/src/i830_driver.c
index cb3dd87..4b87ec5 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2727,7 +2727,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 
    xf86SetBlackWhitePixels(pScreen);
 
-   I830DGAInit(pScreen);
+   xf86_dga_init (pScreen);
 
    DPRINTF(PFX,
 	   "assert( if(!I830InitFBManager(pScreen, &(pI830->FbMemBox))) )\n");
@@ -3393,7 +3393,7 @@ I830CheckDevicesTimer(OsTimerPtr timer, 
       
       xf86ProbeOutputModes (pScrn, 0, 0);
       xf86SetScrnInfoModes (pScrn);
-      I830DGAReInit (pScrn->pScreen);
+      xf86_dga_reinit (pScrn->pScreen);
       xf86SwitchMode(pScrn->pScreen, pScrn->currentMode);
 
       /* Clear the BIOS's hotkey press flags */
diff --git a/src/i830_randr.c b/src/i830_randr.c
index 811fc50..03ca504 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -41,9 +41,6 @@
 
 #include "i830_xf86Crtc.h"
 #include "i830_randr.h"
-#include "i830_debug.h"
-#include "i830_display.h"
-#include "i830.h"
 
 typedef struct _xf86RandR12Info {
     int				    virtualX;
@@ -97,7 +94,7 @@ xf86RandR12GetInfo (ScreenPtr pScreen, R
     /* Re-probe the outputs for new monitors or modes */
     xf86ProbeOutputModes (scrp, 0, 0);
     xf86SetScrnInfoModes (scrp);
-    I830DGAReInit (pScreen);
+    xf86_dga_reinit (pScreen);
 
     for (mode = scrp->modes; ; mode = mode->next)
     {
@@ -854,7 +851,7 @@ xf86RandR12GetInfo12 (ScreenPtr pScreen,
 
     xf86ProbeOutputModes (pScrn, 0, 0);
     xf86SetScrnInfoModes (pScrn);
-    I830DGAReInit (pScreen);
+    xf86_dga_reinit (pScreen);
     return xf86RandR12SetInfo12 (pScreen);
 }
 
diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h
index 6de2c92..2d77328 100644
--- a/src/i830_xf86Crtc.h
+++ b/src/i830_xf86Crtc.h
@@ -531,4 +531,18 @@ xf86OutputGetEDIDModes (xf86OutputPtr ou
 xf86MonPtr
 xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus);
 
+/**
+ * Initialize dga for this screen
+ */
+
+Bool
+xf86_dga_init (ScreenPtr pScreen);
+
+/**
+ * Re-initialize dga for this screen (as when the set of modes changes)
+ */
+
+Bool
+xf86_dga_reinit (ScreenPtr pScreen);
+
 #endif /* _XF86CRTC_H_ */
diff-tree 1623b47c4863f5362587cdac855e3e11c109b007 (from 4bd4058dfdca84d6ebab82a1dfba99adf3852c9c)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Feb 13 17:37:56 2007 -0800

    Switch the RECTLIST vertex order to (x2, y2), (x1, y2), (x1, y1).
    
    This is the documented correct ordering, and while the previous ordering
    (reversed) worked on some hardware, it failed on others.
    
    Reported by:	Wang Zhenyu <zhenyu.z.wang at intel.com>

diff --git a/src/i830_render.c b/src/i830_render.c
index 96aeb3f..49d8fc1 100644
--- a/src/i830_render.c
+++ b/src/i830_render.c
@@ -557,13 +557,13 @@ i830_composite(PixmapPtr pDst, int srcX,
 
 	OUT_RING(PRIM3D_INLINE | PRIM3D_RECTLIST | (vertex_count-1));
 
-	OUT_RING_F(-0.125 + dstX);
-	OUT_RING_F(-0.125 + dstY);
-	OUT_RING_F(src_x[0] / pI830->scale_units[0][0]);
-	OUT_RING_F(src_y[0] / pI830->scale_units[0][1]);
+	OUT_RING_F(-0.125 + dstX + w);
+	OUT_RING_F(-0.125 + dstY + h);
+	OUT_RING_F(src_x[2] / pI830->scale_units[0][0]);
+	OUT_RING_F(src_y[2] / pI830->scale_units[0][1]);
 	if (has_mask) {
-	    OUT_RING_F(mask_x[0] / pI830->scale_units[1][0]);
-	    OUT_RING_F(mask_y[0] / pI830->scale_units[1][1]);
+	    OUT_RING_F(mask_x[2] / pI830->scale_units[1][0]);
+	    OUT_RING_F(mask_y[2] / pI830->scale_units[1][1]);
 	}
 
 	OUT_RING_F(-0.125 + dstX);
@@ -575,13 +575,13 @@ i830_composite(PixmapPtr pDst, int srcX,
 	    OUT_RING_F(mask_y[1] / pI830->scale_units[1][1]);
 	}
 
-	OUT_RING_F(-0.125 + dstX + w);
-	OUT_RING_F(-0.125 + dstY + h);
-	OUT_RING_F(src_x[2] / pI830->scale_units[0][0]);
-	OUT_RING_F(src_y[2] / pI830->scale_units[0][1]);
+	OUT_RING_F(-0.125 + dstX);
+	OUT_RING_F(-0.125 + dstY);
+	OUT_RING_F(src_x[0] / pI830->scale_units[0][0]);
+	OUT_RING_F(src_y[0] / pI830->scale_units[0][1]);
 	if (has_mask) {
-	    OUT_RING_F(mask_x[2] / pI830->scale_units[1][0]);
-	    OUT_RING_F(mask_y[2] / pI830->scale_units[1][1]);
+	    OUT_RING_F(mask_x[0] / pI830->scale_units[1][0]);
+	    OUT_RING_F(mask_y[0] / pI830->scale_units[1][1]);
 	}
 	ADVANCE_LP_RING();
     }
diff-tree 4bd4058dfdca84d6ebab82a1dfba99adf3852c9c (from 0ec4ffcb4e8e5e707e68bef1b13a324677f19f8f)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Feb 13 14:29:52 2007 -0800

    Bug #9941: ViewSonic VX2025wm sync polarity quirk to fix mode distortion.

diff --git a/src/i830_edid_modes.c b/src/i830_edid_modes.c
index 1bab4cd..866b9be 100644
--- a/src/i830_edid_modes.c
+++ b/src/i830_edid_modes.c
@@ -66,7 +66,11 @@ static Bool quirk_dt_sync_hm_vp (int scr
     if (memcmp (DDC->vendor.name, "MAX", 4) == 0 &&
 	DDC->vendor.prod_id == 2007)
 	return TRUE;
-    
+    /* ViewSonic VX2025wm (bug #9941) */
+    if (memcmp (DDC->vendor.name, "VSC", 4) == 0 &&
+	DDC->vendor.prod_id == 58653)
+	return TRUE;
+
     return FALSE;
 }
 
diff-tree 0ec4ffcb4e8e5e707e68bef1b13a324677f19f8f (from 699fa88d2570de6173e2d866e11b7437f4842d74)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Feb 13 13:18:15 2007 -0800

    Fix double free in the case of LVDS disabled through quirks.

diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index 4c1afb0..642dd8a 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -527,6 +527,5 @@ i830_lvds_init(ScrnInfoPtr pScrn)
 
 disable_exit:
     xf86DestroyI2CBusRec(intel_output->pDDCBus, TRUE, TRUE);
-    xfree(intel_output);
     xf86OutputDestroy(output);
 }
diff-tree 699fa88d2570de6173e2d866e11b7437f4842d74 (from parents)
Merge: 681b91924c364a1c00732f548539f2767929ba0e 6641aec0a1cbc869fba1956c556cdd204631545a
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Feb 13 13:10:08 2007 -0800

    Merge branch 'modesetting-origin' into modesetting

diff-tree 6641aec0a1cbc869fba1956c556cdd204631545a (from 991439d4c78cf5b2a8f6bb8f5b36fffbfcc4e4fc)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Feb 13 10:21:12 2007 -0800

    Attempt to detect panel fixed mode from EDID or current programmed mode.
    
    These two sources are placed in higher priority to the BIOS data when
    available, since the BIOS data has proven unreliable.  The BIOS data is still
    read, and warnings printed if it doesn't match what we probe.  The BIOS data
    remains useful for the situation where we want to turn on LVDS but there is no
    EDID available and no current mode programmed (i.e. booting with VGA or TV
    connected).

diff --git a/src/i830.h b/src/i830.h
index 57d8da1..96972eb 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -590,6 +590,9 @@ extern Bool I830I2CInit(ScrnInfoPtr pScr
 /* return a mask of output indices matching outputs against type_mask */
 int i830_output_clones (ScrnInfoPtr pScrn, int type_mask);
 
+/* i830_bios.c */
+DisplayModePtr i830_bios_get_panel_mode(ScrnInfoPtr pScrn);
+
 /* i830_display.c */
 Bool
 i830PipeHasType (xf86CrtcPtr crtc, int type);
diff --git a/src/i830_bios.c b/src/i830_bios.c
index a9ef474..cb886b5 100644
--- a/src/i830_bios.c
+++ b/src/i830_bios.c
@@ -122,8 +122,16 @@ i830GetBIOS(ScrnInfoPtr pScrn)
     return bios;
 }
 
-Bool
-i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScrn)
+/**
+ * Returns the BIOS's fixed panel mode.
+ *
+ * Note that many BIOSes will have the appropriate tables for a panel even when
+ * a panel is not attached.  Additionally, many BIOSes adjust table sizes or
+ * offsets, such that this parsing fails.  Thus, almost any other method for
+ * detecting the panel mode is preferable.
+ */
+DisplayModePtr
+i830_bios_get_panel_mode(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     struct vbt_header *vbt;
@@ -131,12 +139,11 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScr
     int vbt_off, bdb_off, bdb_block_off, block_size;
     int panel_type = -1;
     unsigned char *bios;
-    Bool found_panel_info = FALSE;
 
     bios = i830GetBIOS(pScrn);
 
     if (bios == NULL)
-	return FALSE;
+	return NULL;
 
     vbt_off = INTEL_BIOS_16(0x1a);
     vbt = (struct vbt_header *)(bios + vbt_off);
@@ -146,7 +153,7 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScr
     if (memcmp(bdb->signature, "BIOS_DATA_BLOCK ", 16) != 0) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Bad BDB signature\n");
 	xfree(bios);
-	return FALSE;
+	return NULL;
     }
 
     for (bdb_block_off = bdb->header_size; bdb_block_off < bdb->bdb_size;
@@ -163,7 +170,6 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScr
 
 	id = INTEL_BIOS_8(start);
 	block_size = INTEL_BIOS_16(start + 1) + 3;
-	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found BDB block type %d\n", id);
 	switch (id) {
 	case 40:
 	    lvds1 = (struct lvds_bdb_1 *)(bios + start);
@@ -227,13 +233,11 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScr
 		       "Found panel mode in BIOS VBT tables:\n");
 	    xf86PrintModeline(pScrn->scrnIndex, fixed_mode);
 
-	    pI830->panel_fixed_mode = fixed_mode;
-
-	    found_panel_info = TRUE;
-	    break;
+	    xfree(bios);
+	    return fixed_mode;
 	}
     }
 
     xfree(bios);
-    return found_panel_info;
+    return NULL;
 }
diff --git a/src/i830_bios.h b/src/i830_bios.h
index 9bd0db8..881d5c8 100644
--- a/src/i830_bios.h
+++ b/src/i830_bios.h
@@ -114,6 +114,3 @@ struct lvds_bdb_2 {
     CARD8 table_size;	/* not sure on this one */
     struct lvds_bdb_2_entry panels[16];
 } __attribute__((packed));
-
-Bool
-i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScrn);
diff --git a/src/i830_display.c b/src/i830_display.c
index 8202985..345eea9 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -1132,6 +1132,91 @@ i830ReleaseLoadDetectPipe(xf86OutputPtr 
     }
 }
 
+/* Returns the clock of the currently programmed mode of the given pipe. */
+static int
+i830_crtc_clock_get(ScrnInfoPtr pScrn, xf86CrtcPtr crtc)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
+    int pipe = intel_crtc->pipe;
+    CARD32 dpll = INREG((pipe == 0) ? DPLL_A : DPLL_B);
+    CARD32 fp;
+    intel_clock_t clock;
+
+    if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
+	fp = INREG((pipe == 0) ? FPA0 : FPB0);
+    else
+	fp = INREG((pipe == 0) ? FPA1 : FPB1);
+
+    clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT;
+    clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT;
+    clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT;
+    clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK) >>
+		   DPLL_FPA01_P1_POST_DIV_SHIFT);
+    switch (dpll & DPLL_MODE_MASK) {
+    case DPLLB_MODE_DAC_SERIAL:
+	clock.p2 = dpll & DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 ? 5 : 10;
+	break;
+    case DPLLB_MODE_LVDS:
+	clock.p2 = dpll & DPLLB_LVDS_P2_CLOCK_DIV_7 ? 7 : 14;
+	break;
+    default:
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		   "Unknown DPLL mode %08x in programmed mode\n",
+		   (int)(dpll & DPLL_MODE_MASK));
+	return 0;
+    }
+    
+    /* XXX: Handle the 100Mhz refclk */
+    if (IS_I9XX(pI830))
+	i9xx_clock(96000, &clock);
+    else
+	i9xx_clock(48000, &clock);
+
+    if (!i830PllIsValid(crtc, &clock)) {
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		   "Bad clock found programmed in pipe %c\n",
+		   pipe == 0 ? 'A' : 'B');
+	i830PrintPll("", &clock);
+    }
+
+    return clock.dot;
+}
+
+/** Returns the currently programmed mode of the given pipe. */
+DisplayModePtr
+i830_crtc_mode_get(ScrnInfoPtr pScrn, xf86CrtcPtr crtc)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
+    int pipe = intel_crtc->pipe;
+    DisplayModePtr mode;
+    int htot = INREG((pipe == 0) ? HTOTAL_A : HTOTAL_B);
+    int hsync = INREG((pipe == 0) ? HSYNC_A : HSYNC_B);
+    int vtot = INREG((pipe == 0) ? VTOTAL_A : VTOTAL_B);
+    int vsync = INREG((pipe == 0) ? VSYNC_A : VSYNC_B);
+
+    mode = xcalloc(1, sizeof(DisplayModeRec));
+    if (mode == NULL)
+	return NULL;
+
+    memset(mode, 0, sizeof(*mode));
+
+    mode->Clock = i830_crtc_clock_get(pScrn, crtc);
+    mode->HDisplay = (htot & 0xffff) + 1;
+    mode->HTotal = ((htot & 0xffff0000) >> 16) + 1;
+    mode->HSyncStart = (hsync & 0xffff) + 1;
+    mode->HSyncEnd = ((hsync & 0xffff0000) >> 16) + 1;
+    mode->VDisplay = (vtot & 0xffff) + 1;
+    mode->VTotal = ((vtot & 0xffff0000) >> 16) + 1;
+    mode->VSyncStart = (vsync & 0xffff) + 1;
+    mode->VSyncEnd = ((vsync & 0xffff0000) >> 16) + 1;
+    xf86SetModeDefaultName(mode);
+    xf86SetModeCrtc(mode, 0);
+
+    return mode;
+}
+
 static const xf86CrtcFuncsRec i830_crtc_funcs = {
     .dpms = i830_crtc_dpms,
     .save = NULL, /* XXX */
diff --git a/src/i830_display.h b/src/i830_display.h
index dc80055..dbd1ea8 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -39,3 +39,4 @@ xf86CrtcPtr i830GetLoadDetectPipe(xf86Ou
 void i830ReleaseLoadDetectPipe(xf86OutputPtr output);
 void i830_crtc_init(ScrnInfoPtr pScrn, int pipe);
 void i830_crtc_load_lut(xf86CrtcPtr crtc);
+DisplayModePtr i830_crtc_mode_get(ScrnInfoPtr pScrn, xf86CrtcPtr crtc);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 0f66311..cb3dd87 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1332,10 +1332,10 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    }
 
    I830PreInitDDC(pScrn);
-   I830SetupOutputs(pScrn);
    for (i = 0; i < num_pipe; i++) {
        i830_crtc_init(pScrn, i);
    }
+   I830SetupOutputs(pScrn);
 
    SaveHWState(pScrn);
    /* Do an initial detection of the outputs while none are configured on yet.
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index 59af13b..4c1afb0 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -32,6 +32,7 @@
 #include "xf86.h"
 #include "i830.h"
 #include "i830_bios.h"
+#include "i830_display.h"
 #include "X11/Xatom.h"
 
 /**
@@ -406,21 +407,99 @@ i830_lvds_init(ScrnInfoPtr pScrn)
     I830Ptr		    pI830 = I830PTR(pScrn);
     xf86OutputPtr	    output;
     I830OutputPrivatePtr    intel_output;
+    DisplayModePtr	    modes, scan, bios_mode;
 
+    output = xf86OutputCreate (pScrn, &i830_lvds_output_funcs, "LVDS");
+    if (!output)
+	return;
+    intel_output = xnfcalloc (sizeof (I830OutputPrivateRec), 1);
+    if (!intel_output)
+    {
+	xf86OutputDestroy (output);
+	return;
+    }
+    intel_output->type = I830_OUTPUT_LVDS;
+    output->driver_private = intel_output;
+    output->subpixel_order = SubPixelHorizontalRGB;
+    output->interlaceAllowed = FALSE;
+    output->doubleScanAllowed = FALSE;
+
+    /* Set up the LVDS DDC channel.  Most panels won't support it, but it can
+     * be useful if available.
+     */
+    I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOC, "LVDSDDC_C");
+
+    /* Attempt to get the fixed panel mode from DDC.  Assume that the preferred
+     * mode is the right one.
+     */
+    modes = i830_ddc_get_modes(output);
+    for (scan = modes; scan != NULL; scan = scan->next) {
+	if (scan->type & M_T_PREFERRED)
+	    break;
+    }
+    if (scan != NULL) {
+	/* Pull our chosen mode out and make it the fixed mode */
+	if (modes == scan)
+	    modes = modes->next;
+	if (scan->prev != NULL)
+	    scan->prev = scan->next;
+	if (scan->next != NULL)
+	    scan->next = scan->prev;
+	pI830->panel_fixed_mode = scan;
+    }
+    /* Delete the mode list */
+    while (modes != NULL)
+	xf86DeleteMode(&modes, modes);
+
+    /* If we didn't get EDID, try checking if the panel is already turned on.
+     * If so, assume that whatever is currently programmed is the correct mode.
+     */
+    if (pI830->panel_fixed_mode == NULL) {
+	CARD32 lvds = INREG(LVDS);
+	int pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
+	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+	xf86CrtcPtr crtc = xf86_config->crtc[pipe];
+
+	if (lvds & LVDS_PORT_EN) {
+	    pI830->panel_fixed_mode = i830_crtc_mode_get(pScrn, crtc);
+	    if (pI830->panel_fixed_mode != NULL)
+		pI830->panel_fixed_mode->type |= M_T_PREFERRED;
+	}
+    }
 
     /* 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
      * for now.
      */
-    if (!i830GetLVDSInfoFromBIOS(pScrn))
-	return;
+    bios_mode = i830_bios_get_panel_mode(pScrn);
+    if (bios_mode != NULL) {
+	if (pI830->panel_fixed_mode != NULL) {
+	    if (!xf86ModesEqual(pI830->panel_fixed_mode, bios_mode)) {
+		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+			   "BIOS panel mode data doesn't match probed data, "
+			   "continuing with probed.\n");
+		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIOS mode:\n");
+		xf86PrintModeline(pScrn->scrnIndex, bios_mode);
+		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "probed mode:\n");
+		xf86PrintModeline(pScrn->scrnIndex, pI830->panel_fixed_mode);
+		xfree(bios_mode->name);
+		xfree(bios_mode);
+	    }
+	}  else {
+	    pI830->panel_fixed_mode = bios_mode;
+	}
+    } else {
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		   "Couldn't detect panel mode.  Disabling panel\n");
+	goto disable_exit;
+    }
 
     /* Blacklist machines with BIOSes that list an LVDS panel without actually
      * having one.
      */
     if (pI830->PciInfo->chipType == PCI_CHIP_I945_GM) {
 	if (pI830->PciInfo->subsysVendor == 0xa0a0)  /* aopen mini pc */
-	    return;
+	    goto disable_exit;
 
 	if ((pI830->PciInfo->subsysVendor == 0x8086) &&
 	    (pI830->PciInfo->subsysCard == 0x7270)) {
@@ -435,31 +514,19 @@ i830_lvds_init(ScrnInfoPtr pScrn)
 
 	    if (pI830->panel_fixed_mode != NULL &&
 		pI830->panel_fixed_mode->HDisplay == 800 &&
-		pI830->panel_fixed_mode->VDisplay == 600) {
+		pI830->panel_fixed_mode->VDisplay == 600)
+	    {
 		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 			   "Suspected Mac Mini, ignoring the LVDS\n");
-		return;
+		goto disable_exit;
 	    }
 	}
-   }
-
-    output = xf86OutputCreate (pScrn, &i830_lvds_output_funcs, "LVDS");
-    if (!output)
-	return;
-    intel_output = xnfcalloc (sizeof (I830OutputPrivateRec), 1);
-    if (!intel_output)
-    {
-	xf86OutputDestroy (output);
-	return;
     }
-    intel_output->type = I830_OUTPUT_LVDS;
-    output->driver_private = intel_output;
-    output->subpixel_order = SubPixelHorizontalRGB;
-    output->interlaceAllowed = FALSE;
-    output->doubleScanAllowed = FALSE;
 
-    /* Set up the LVDS DDC channel.  Most panels won't support it, but it can
-     * be useful if available.
-     */
-    I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOC, "LVDSDDC_C");
+    return;
+
+disable_exit:
+    xf86DestroyI2CBusRec(intel_output->pDDCBus, TRUE, TRUE);
+    xfree(intel_output);
+    xf86OutputDestroy(output);
 }
diff-tree 991439d4c78cf5b2a8f6bb8f5b36fffbfcc4e4fc (from c3aed56d46baba057d83dc6ea12c6b4e705e54ba)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Feb 13 10:07:47 2007 -0800

    Remove dead #if 0-ed structure.

diff --git a/src/i830.h b/src/i830.h
index 42933f9..57d8da1 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -232,21 +232,6 @@ enum last_3d {
     LAST_3D_ROTATION
 };
 
-#if 0
-typedef struct _I830PipeRec {
-   Bool		  enabled;
-   int		  x;
-   int		  y;
-   Bool		  cursorInRange;
-   Bool		  cursorShown;
-   DisplayModeRec curMode;
-   DisplayModeRec desiredMode;
-#ifdef RANDR_12_INTERFACE
-   RRCrtcPtr	  randr_crtc;
-#endif
-} I830PipeRec, *I830PipePtr;
-#endif
-
 typedef struct _I830Rec {
    unsigned char *MMIOBase;
    unsigned char *FbBase;
diff-tree c3aed56d46baba057d83dc6ea12c6b4e705e54ba (from 98318dfcc99264fb7b7ef34568712812aa6300b6)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Feb 9 13:16:37 2007 -0800

    Fix comments on 965 pitch alignment restrictions.

diff --git a/src/i830_exa.c b/src/i830_exa.c
index c3a4c40..42552d4 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -346,7 +346,8 @@ I830EXAInit(ScreenPtr pScreen)
      * i965 limits 3D surface to 4kB-aligned offset if tiled.
      * i965 limits 3D surfaces to w,h of ?,8192.
      * i965 limits 3D surface to pitch of 1B - 128kB.
-     * i965 limits 3D surface pitch alignment to 512B, only if tiled.
+     * i965 limits 3D surface pitch alignment to 1 or 2 times the element size.
+     * i965 limits 3D surface pitch alignment to 512B if tiled.
      * i965 limits 3D destination drawing rect to w,h of 8192,8192.
      *
      * i915 limits 3D textures to 4B-aligned offset if un-tiled.
diff-tree 98318dfcc99264fb7b7ef34568712812aa6300b6 (from fce4390c4f1a76c65423114bb479814787612cd7)
Author: Daniel Stone <daniel at fooishbar.org>
Date:   Fri Feb 9 16:20:57 2007 +0200

    add missing files to fix distcheck
    A bunch of files were missing from _SOURCES, and the build was also broken
    for missing files (from EXTRA_DIST) when building without gen4asm.

diff --git a/src/Makefile.am b/src/Makefile.am
index f824a74..6c63cc4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -94,7 +94,16 @@ intel_drv_la_SOURCES = \
 	 i830_xaa.c \
 	 i830_render.c \
 	 i915_render.c \
-	 i965_render.c
+	 i965_render.c \
+	 i830_xf86Rename.h \
+	 local_xf86Rename.h \
+	 xf86Parser.h \
+	 xf86Optrec.h \
+	 i830_randr.h
+
+EXTRA_DIST = \
+	packed_yuv_sf.g4a \
+	packed_yuv_wm.g4a
 
 if HAVE_GEN4ASM
 sf_prog.h: packed_yuv_sf.g4a
@@ -109,6 +118,14 @@ exa_wm_nomask_prog.h: exa_wm_nomask.g4a
 	intel-gen4asm -o exa_wm_nomask_prog.h exa_wm_nomask.g4a
 exa_wm_masknoca_prog.h: exa_wm_masknoca.g4a
 	intel-gen4asm -o exa_wm_masknoca_prog.h exa_wm_masknoca.g4a
+else
+EXTRA_DIST += \
+	sf_prog.h		\
+	wm_prog.h 		\
+	exa_sf_prog.h 		\
+	exa_sf_mask_prog.h	\
+	exa_wm_nomask_prog.h 	\
+	exa_wm_masknoca_prog.h
 endif
 
 if DRI
@@ -120,10 +137,6 @@ intel_drv_la_SOURCES += \
          i830_dri.h 
 endif
 
-EXTRA_DIST = \
-	packed_yuv_sf.g4a \
-	packed_yuv_wm.g4a
-
 install-data-local: install-intel_drv_laLTLIBRARIES
 	(cd $(DESTDIR)$(intel_drv_ladir) && rm -f i810_drv.so && ln -s intel_drv.so i810_drv.so)
 
diff-tree fce4390c4f1a76c65423114bb479814787612cd7 (from 10712c7a781e50475ee7e8ccd5bfd2d820f863e2)
Author: Zou Nan hai <zhenyu.z.wang at intel.com>
Date:   Fri Feb 9 11:32:22 2007 +0800

     TV Enable

diff --git a/src/i830_tv.c b/src/i830_tv.c
index 79b6ae8..5ee8866 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -37,7 +37,6 @@
 #include "i830.h"
 #include "i830_display.h"
 #include <string.h>
-
 enum tv_type {
     TV_TYPE_NONE,
     TV_TYPE_UNKNOWN,
@@ -94,11 +93,67 @@ typedef struct {
     float   rv, gv, bv, av;
 } color_conversion_t;
 
+static const CARD32 filter_table[] = {
+    0xB1403000, 0x2E203500, 0x35002E20, 0x3000B140,
+    0x35A0B160, 0x2DC02E80, 0xB1403480, 0xB1603000,
+    0x2EA03640, 0x34002D80, 0x3000B120, 0x36E0B160,
+    0x2D202EF0, 0xB1203380, 0xB1603000, 0x2F303780,
+    0x33002CC0, 0x3000B100, 0x3820B160, 0x2C802F50,
+    0xB10032A0, 0xB1603000, 0x2F9038C0, 0x32202C20,
+    0x3000B0E0, 0x3980B160, 0x2BC02FC0, 0xB0E031C0,
+    0xB1603000, 0x2FF03A20, 0x31602B60, 0xB020B0C0,
+    0x3AE0B160, 0x2B001810, 0xB0C03120, 0xB140B020,
+    0x18283BA0, 0x30C02A80, 0xB020B0A0, 0x3C60B140,
+    0x2A201838, 0xB0A03080, 0xB120B020, 0x18383D20,
+    0x304029C0, 0xB040B080, 0x3DE0B100, 0x29601848,
+    0xB0803000, 0xB100B040, 0x18483EC0, 0xB0402900,
+    0xB040B060, 0x3F80B0C0, 0x28801858, 0xB060B080,
+    0xB0A0B060, 0x18602820, 0xB0A02820, 0x0000B060,
+    0xB1403000, 0x2E203500, 0x35002E20, 0x3000B140,
+    0x35A0B160, 0x2DC02E80, 0xB1403480, 0xB1603000,
+    0x2EA03640, 0x34002D80, 0x3000B120, 0x36E0B160,
+    0x2D202EF0, 0xB1203380, 0xB1603000, 0x2F303780,
+    0x33002CC0, 0x3000B100, 0x3820B160, 0x2C802F50,
+    0xB10032A0, 0xB1603000, 0x2F9038C0, 0x32202C20,
+    0x3000B0E0, 0x3980B160, 0x2BC02FC0, 0xB0E031C0,
+    0xB1603000, 0x2FF03A20, 0x31602B60, 0xB020B0C0,
+    0x3AE0B160, 0x2B001810, 0xB0C03120, 0xB140B020,
+    0x18283BA0, 0x30C02A80, 0xB020B0A0, 0x3C60B140,
+    0x2A201838, 0xB0A03080, 0xB120B020, 0x18383D20,
+    0x304029C0, 0xB040B080, 0x3DE0B100, 0x29601848,
+    0xB0803000, 0xB100B040, 0x18483EC0, 0xB0402900,
+    0xB040B060, 0x3F80B0C0, 0x28801858, 0xB060B080,
+    0xB0A0B060, 0x18602820, 0xB0A02820, 0x0000B060,
+    0x36403000, 0x2D002CC0, 0x30003640, 0x2D0036C0,
+    0x35C02CC0, 0x37403000, 0x2C802D40, 0x30003540,
+    0x2D8037C0, 0x34C02C40, 0x38403000, 0x2BC02E00,
+    0x30003440, 0x2E2038C0, 0x34002B80, 0x39803000,
+    0x2B402E40, 0x30003380, 0x2E603A00, 0x33402B00,
+    0x3A803040, 0x2A802EA0, 0x30403300, 0x2EC03B40,
+    0x32802A40, 0x3C003040, 0x2A002EC0, 0x30803240,
+    0x2EC03C80, 0x320029C0, 0x3D403080, 0x29402F00,
+    0x308031C0, 0x2F203DC0, 0x31802900, 0x3E8030C0,
+    0x28802F40, 0x30C03140, 0x2F203F40, 0x31402840,
+    0x28003100, 0x28002F00, 0x00003100, 0x36403000, 
+    0x2D002CC0, 0x30003640, 0x2D0036C0,
+    0x35C02CC0, 0x37403000, 0x2C802D40, 0x30003540,
+    0x2D8037C0, 0x34C02C40, 0x38403000, 0x2BC02E00,
+    0x30003440, 0x2E2038C0, 0x34002B80, 0x39803000,
+    0x2B402E40, 0x30003380, 0x2E603A00, 0x33402B00,
+    0x3A803040, 0x2A802EA0, 0x30403300, 0x2EC03B40,
+    0x32802A40, 0x3C003040, 0x2A002EC0, 0x30803240,
+    0x2EC03C80, 0x320029C0, 0x3D403080, 0x29402F00,
+    0x308031C0, 0x2F203DC0, 0x31802900, 0x3E8030C0,
+    0x28802F40, 0x30C03140, 0x2F203F40, 0x31402840,
+    0x28003100, 0x28002F00, 0x00003100,
+};
+
 typedef struct {
     char *name;
+    int	clock;
     CARD32 oversample;
     int hsync_end, hblank_start, hblank_end, htotal;
-    Bool progressive;
+    Bool progressive, trilevel_sync, component_only;
     int vsync_start_f1, vsync_start_f2, vsync_len;
     Bool veq_ena;
     int veq_start_f1, veq_start_f2, veq_len;
@@ -120,9 +175,10 @@ typedef struct {
      */
     video_levels_t	composite_levels, svideo_levels;
     color_conversion_t	composite_color, svideo_color;
+    const CARD32 *filter_table;
+    int max_srcw;
 } tv_mode_t;
 
-#define TV_PLL_CLOCK	107520
 
 /*
  * Sub carrier DDA
@@ -157,25 +213,26 @@ typedef struct {
 
 const static tv_mode_t tv_modes[] = {
     {
-	.name		= "NTSC 480i",
+	.name		= "NTSC-M",
+	.clock		= 107520,	
 	.oversample	= TV_OVERSAMPLE_8X,
-	
+	.component_only = 0,
 	/* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */
 
 	.hsync_end	= 64,		    .hblank_end		= 124,
 	.hblank_start	= 836,		    .htotal		= 857,
-	
-	.progressive	= FALSE,
-	
+
+	.progressive	= FALSE,	    .trilevel_sync = FALSE,
+
 	.vsync_start_f1	= 6,		    .vsync_start_f2	= 7,
 	.vsync_len	= 6,
-	
+
 	.veq_ena	= TRUE,		    .veq_start_f1    	= 0,
 	.veq_start_f2	= 1,		    .veq_len		= 18,
-	
+
 	.vi_end_f1	= 20,		    .vi_end_f2		= 21,
 	.nbr_end	= 240,
-	
+
 	.burst_ena	= TRUE,
 	.hburst_start	= 72,		    .hburst_len		= 34,
 	.vburst_start_f1 = 9,		    .vburst_end_f1	= 240,
@@ -203,26 +260,78 @@ const static tv_mode_t tv_modes[] = {
 	    .ru =-0.0885, .gu =-0.1738, .bu = 0.2624, .au = 1.0000,
 	    .rv = 0.3693, .gv =-0.3092, .bv =-0.0601, .av = 1.0000,
 	},
+	.filter_table = filter_table,
     },
     {
-	.name		= "NTSC-Japan 480i",
+	.name		= "NTSC-443",
+	.clock		= 107520,	
 	.oversample	= TV_OVERSAMPLE_8X,
-	
-	/* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */
+	.component_only = 0,
+	/* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 4.43MHz */
 	.hsync_end	= 64,		    .hblank_end		= 124,
 	.hblank_start	= 836,		    .htotal		= 857,
-	
-	.progressive	= FALSE,
-	
-	.vsync_start_f1	= 6,		    .vsync_start_f2	= 7,
+
+	.progressive	= FALSE,	    .trilevel_sync = FALSE,
+
+	.vsync_start_f1 = 6,		    .vsync_start_f2	= 7,
 	.vsync_len	= 6,
-	
+
 	.veq_ena	= TRUE,		    .veq_start_f1    	= 0,
 	.veq_start_f2	= 1,		    .veq_len		= 18,
-	
+
+	.vi_end_f1	= 20,		    .vi_end_f2		= 21,
+	.nbr_end	= 240,
+
+	.burst_ena	= 8,
+	.hburst_start	= 72,		    .hburst_len		= 34,
+	.vburst_start_f1 = 9,		    .vburst_end_f1	= 240,
+	.vburst_start_f2 = 10,		    .vburst_end_f2	= 240,
+	.vburst_start_f3 = 9,		    .vburst_end_f3	= 240, 
+	.vburst_start_f4 = 10,		    .vburst_end_f4	= 240,
+
+	/* desired 4.4336180 actual 4.4336180 clock 107.52 */
+	.dda1_inc       =    168,
+	.dda2_inc       =  18557,       .dda2_size      =  20625,
+	.dda3_inc       =      0,       .dda3_size      =      0,
+	.sc_reset   = TV_SC_RESET_EVERY_8,
+	.pal_burst  = TRUE,
+
+	.composite_levels = { .blank = 225, .black = 267, .burst = 113 },
+	.composite_color = {
+	    .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.5082,
+	    .ru =-0.0749, .gu =-0.1471, .bu = 0.2220, .au = 1.0000,
+	    .rv = 0.3125, .gv =-0.2616, .bv =-0.0508, .av = 1.0000,
+	},
+
+	.svideo_levels    = { .blank = 266, .black = 316, .burst = 133 },
+	.svideo_color = {
+	    .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.6006,
+	    .ru =-0.0885, .gu =-0.1738, .bu = 0.2624, .au = 1.0000,
+	    .rv = 0.3693, .gv =-0.3092, .bv =-0.0601, .av = 1.0000,
+	},
+	.filter_table = filter_table,
+    },
+    {
+	.name		= "NTSC-J",
+	.clock		= 107520,	
+	.oversample	= TV_OVERSAMPLE_8X,
+	.component_only = 0,
+
+	/* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */
+	.hsync_end	= 64,		    .hblank_end		= 124,
+	.hblank_start = 836,	    .htotal		= 857,
+
+	.progressive	= FALSE,    .trilevel_sync = FALSE,
+
+	.vsync_start_f1	= 6,	    .vsync_start_f2	= 7,
+	.vsync_len	= 6,
+
+	.veq_ena	= TRUE,		    .veq_start_f1    	= 0,
+	.veq_start_f2 = 1,	    .veq_len		= 18,
+
 	.vi_end_f1	= 20,		    .vi_end_f2		= 21,
 	.nbr_end	= 240,
-	
+
 	.burst_ena	= TRUE,
 	.hburst_start	= 72,		    .hburst_len		= 34,
 	.vburst_start_f1 = 9,		    .vburst_end_f1	= 240,
@@ -250,20 +359,74 @@ const static tv_mode_t tv_modes[] = {
 	    .ru =-0.0957, .gu =-0.1879, .bu = 0.2836, .au = 1.0000,
 	    .rv = 0.3992, .gv =-0.3343, .bv =-0.0649, .av = 1.0000,
 	},
+	.filter_table = filter_table,
+    },
+    {
+	.name		= "PAL-M",
+	.clock		= 107520,	
+	.oversample	= TV_OVERSAMPLE_8X,
+	.component_only = 0,
+
+	/* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */
+	.hsync_end	= 64,		  .hblank_end		= 124,
+	.hblank_start = 836,	  .htotal		= 857,
+
+	.progressive	= FALSE,	    .trilevel_sync = FALSE,
+
+	.vsync_start_f1	= 6,		    .vsync_start_f2	= 7,
+	.vsync_len	= 6,
+
+	.veq_ena	= TRUE,		    .veq_start_f1    	= 0,
+	.veq_start_f2	= 1,		    .veq_len		= 18,
+
+	.vi_end_f1	= 20,		    .vi_end_f2		= 21,
+	.nbr_end	= 240,
+
+	.burst_ena	= TRUE,
+	.hburst_start	= 72,		    .hburst_len		= 34,
+	.vburst_start_f1 = 9,		    .vburst_end_f1	= 240,
+	.vburst_start_f2 = 10,		    .vburst_end_f2	= 240,
+	.vburst_start_f3 = 9,		    .vburst_end_f3	= 240, 
+	.vburst_start_f4 = 10,		    .vburst_end_f4	= 240,
+
+	/* desired 3.5800000 actual 3.5800000 clock 107.52 */
+	.dda1_inc	=    136,
+	.dda2_inc	=    7624,	    .dda2_size		=  20013,
+	.dda3_inc	=      0,	    .dda3_size		=      0,
+	.sc_reset	= TV_SC_RESET_EVERY_4,
+	.pal_burst  = FALSE,
+
+	.composite_levels = { .blank = 225, .black = 267, .burst = 113 },
+	.composite_color = {
+	    .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.5082,
+	    .ru =-0.0749, .gu =-0.1471, .bu = 0.2220, .au = 1.0000,
+	    .rv = 0.3125, .gv =-0.2616, .bv =-0.0508, .av = 1.0000,
+	},
+
+	.svideo_levels    = { .blank = 266, .black = 316, .burst = 133 },
+	.svideo_color = {
+	    .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.6006,
+	    .ru =-0.0885, .gu =-0.1738, .bu = 0.2624, .au = 1.0000,
+	    .rv = 0.3693, .gv =-0.3092, .bv =-0.0601, .av = 1.0000,
+	},
+	.filter_table = filter_table,
     },
     {
 	/* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */
-	.name	    = "PAL 576i",
+	.name	    = "PAL-N",
+	.clock		= 107520,	
 	.oversample	= TV_OVERSAMPLE_8X,
+	.component_only = 0,
 
 	.hsync_end	= 64,		    .hblank_end		= 128,
-	.hblank_start	= 844,		    .htotal		= 863,
-	
-	.progressive	= FALSE,
-	
-	.vsync_start_f1	= 6,		    .vsync_start_f2	= 7,
+	.hblank_start = 844,	    .htotal		= 863,
+
+	.progressive  = FALSE,    .trilevel_sync = FALSE,
+
+
+	.vsync_start_f1	= 6,	   .vsync_start_f2	= 7,
 	.vsync_len	= 6,
-	
+
 	.veq_ena	= TRUE,		    .veq_start_f1    	= 0,
 	.veq_start_f2	= 1,		    .veq_len		= 18,
 
@@ -271,44 +434,70 @@ const static tv_mode_t tv_modes[] = {
 	.nbr_end	= 286,
 
 	.burst_ena	= TRUE,
-	.hburst_start	= 73,		    .hburst_len		= 34,
-	.vburst_start_f1 = 8,		    .vburst_end_f1	= 285,
-	.vburst_start_f2 = 8,		    .vburst_end_f2	= 286,
-	.vburst_start_f3 = 9,		    .vburst_end_f3	= 286, 
-	.vburst_start_f4 = 9,		    .vburst_end_f4	= 285,
+	.hburst_start = 73,	    	    .hburst_len		= 34,
+	.vburst_start_f1 = 8,	    .vburst_end_f1	= 285,
+	.vburst_start_f2 = 8,	    .vburst_end_f2	= 286,
+	.vburst_start_f3 = 9,	    .vburst_end_f3	= 286, 
+	.vburst_start_f4 = 9,	    .vburst_end_f4	= 285,
+
 
 	/* desired 4.4336180 actual 4.4336180 clock 107.52 */
-	.dda1_inc	=    168,
-	.dda2_inc	=  18557,	.dda2_size	=  20625,
-	.dda3_inc	=      0,	.dda3_size	=      0,
+	.dda1_inc       =    168,
+	.dda2_inc       =  18557,       .dda2_size      =  20625,
+	.dda3_inc       =      0,       .dda3_size      =      0,
 	.sc_reset   = TV_SC_RESET_EVERY_8,
 	.pal_burst  = TRUE,
-	
-	.composite_levels = { .blank = 237, .black = 237, .burst = 118 },
+
+	.composite_levels = { .blank = 225, .black = 267, .burst = 118 },
 	.composite_color = {
-	    .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.5379,
-	    .ru =-0.0793, .gu =-0.1557, .bu = 0.2350, .au = 1.0000,
-	    .rv = 0.3307, .gv =-0.2769, .bv =-0.0538, .av = 1.0000,
+	    .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.5082,
+	    .ru =-0.0749, .gu =-0.1471, .bu = 0.2220, .au = 1.0000,
+	    .rv = 0.3125, .gv =-0.2616, .bv =-0.0508, .av = 1.0000,
 	},
 
-	.svideo_levels    = { .blank = 280, .black = 280, .burst = 139 },
+	.svideo_levels    = { .blank = 266, .black = 316, .burst = 139 },
 	.svideo_color = {
-	    .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.6357,
-	    .ru =-0.0937, .gu =-0.1840, .bu = 0.2777, .au = 1.0000,
-	    .rv = 0.3908, .gv =-0.3273, .bv =-0.0636, .av = 1.0000,
+	    .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.6006,
+	    .ru =-0.0885, .gu =-0.1738, .bu = 0.2624, .au = 1.0000,
+	    .rv = 0.3693, .gv =-0.3092, .bv =-0.0601, .av = 1.0000,
 	},
-    }
-#if 0
+	.filter_table = filter_table,
+    },
     {
 	/* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */
 	.name	    = "PAL",
+	.clock		= 107520,	
+	.oversample	= TV_OVERSAMPLE_8X,
+	.component_only = 0,
+
+	.hsync_end	= 64,		    .hblank_end		= 128,
+	.hblank_start	= 844,	    .htotal		= 863,
+
+	.progressive	= FALSE,    .trilevel_sync = FALSE,
+
+	.vsync_start_f1	= 5,	    .vsync_start_f2	= 6,
+	.vsync_len	= 5,
+
+	.veq_ena	= TRUE,		    .veq_start_f1    	= 0,
+	.veq_start_f2	= 1,	    .veq_len		= 15,
+
+	.vi_end_f1	= 24,		    .vi_end_f2		= 25,
+	.nbr_end	= 286,
+
+	.burst_ena	= TRUE,
+	.hburst_start	= 73,		    .hburst_len		= 32,
+	.vburst_start_f1 = 8,		    .vburst_end_f1	= 285,
+	.vburst_start_f2 = 8,		    .vburst_end_f2	= 286,
+	.vburst_start_f3 = 9,		    .vburst_end_f3	= 286, 
+	.vburst_start_f4 = 9,		    .vburst_end_f4	= 285,
+
 	/* desired 4.4336180 actual 4.4336180 clock 107.52 */
-	.dda1_inc	=    168,
-	.dda2_inc	=  18557,	.dda2_size	=  20625,
-	.dda3_inc	=      0,	.dda3_size	=      0,
+	.dda1_inc       =    168,
+	.dda2_inc       =  18557,       .dda2_size      =  20625,
+	.dda3_inc       =      0,       .dda3_size      =      0,
 	.sc_reset   = TV_SC_RESET_EVERY_8,
-	.pal_burst  = TRUE
-	
+	.pal_burst  = TRUE,
+
 	.composite_levels = { .blank = 237, .black = 237, .burst = 118 },
 	.composite_color = {
 	    .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.5379,
@@ -322,84 +511,226 @@ const static tv_mode_t tv_modes[] = {
 	    .ru =-0.0937, .gu =-0.1840, .bu = 0.2777, .au = 1.0000,
 	    .rv = 0.3908, .gv =-0.3273, .bv =-0.0636, .av = 1.0000,
 	},
+	.filter_table = filter_table,
     },
     {
-	/* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.576MHz */
-	.name	    = "PAL M",
-	/* desired 3.5756110 actual 3.5756110 clock 107.52 */
-	.dda1_inc	=    136,
-	.dda2_inc	=   5611,	.dda2_size	=  26250,
-	.dda3_inc	=      0,	.dda3_size	=      0,
-	.sc_reset   = TV_SC_RESET_EVERY_8,
-	.pal_burst  = TRUE
-	
-	.composite_levels = { .blank = 225, .black = 267, .burst = 113 },
-	.composite_color = {
-	    .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.5082,
-	    .ru =-0.0749, .gu =-0.1471, .bu = 0.2220, .au = 1.0000,
-	    .rv = 0.3125, .gv =-0.2616, .bv =-0.0508, .av = 1.0000,
-	},
+	.name       = "480p at 59.94Hz",
+	.clock 	= 107520,	
+	.oversample     = TV_OVERSAMPLE_4X,
+	.component_only = 1,
 
-	.svideo_levels    = { .blank = 266, .black = 316, .burst = 133 },
-	.svideo_color = {
-	    .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.6006,
-	    .ru =-0.0885, .gu =-0.1738, .bu = 0.2624, .au = 1.0000,
-	    .rv = 0.3693, .gv =-0.3092, .bv =-0.0601, .av = 1.0000,
-	},
+	.hsync_end      = 64,               .hblank_end         = 122,
+	.hblank_start   = 842,              .htotal             = 857,
+
+	.progressive    = TRUE,.trilevel_sync = FALSE,
+
+	.vsync_start_f1 = 12,               .vsync_start_f2     = 12,
+	.vsync_len      = 12,
+
+	.veq_ena        = FALSE,
+
+	.vi_end_f1      = 44,               .vi_end_f2          = 44,
+	.nbr_end        = 496,
+
+	.burst_ena      = FALSE,
+
+	.filter_table = filter_table,
     },
     {
-	/* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 3.582MHz */
-	.name	    = "PAL Nc",
-	/* desired 3.5820560 actual 3.5820560 clock 107.52 */
-	.dda1_inc	=    136,
-	.dda2_inc	=  12056,	.dda2_size	=  26250,
-	.dda3_inc	=      0,	.dda3_size	=      0,
-	.sc_reset   = TV_SC_RESET_EVERY_8,
-	.pal_burst  = TRUE
-	
-	.composite_levels = { .blank = 225, .black = 267, .burst = 113 },
-	.composite_color = {
-	    .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.5082,
-	    .ru =-0.0749, .gu =-0.1471, .bu = 0.2220, .au = 1.0000,
-	    .rv = 0.3125, .gv =-0.2616, .bv =-0.0508, .av = 1.0000,
-	},
+	.name       = "480p at 60Hz",
+	.clock 	= 107520,	
+	.oversample     = TV_OVERSAMPLE_4X,
+	.component_only = 1,
 
-	.svideo_levels    = { .blank = 266, .black = 316, .burst = 133 },
-	.svideo_color = {
-	    .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.6006,
-	    .ru =-0.0885, .gu =-0.1738, .bu = 0.2624, .au = 1.0000,
-	    .rv = 0.3693, .gv =-0.3092, .bv =-0.0601, .av = 1.0000,
-	},
+	.hsync_end      = 64,               .hblank_end         = 122,
+	.hblank_start   = 842,              .htotal             = 856,
+
+	.progressive    = TRUE,.trilevel_sync = FALSE,
+
+	.vsync_start_f1 = 12,               .vsync_start_f2     = 12,
+	.vsync_len      = 12,
+
+	.veq_ena        = FALSE,
+
+	.vi_end_f1      = 44,               .vi_end_f2          = 44,
+	.nbr_end        = 496,
+
+	.burst_ena      = FALSE,
+
+	.filter_table = filter_table,
     },
     {
-	/* 525 lines, 60 fields, 15.734KHz line, Sub-Carrier 4.43MHz */
-	.name	    = "NTSC-4.43(nonstandard)",
-	/* desired 4.4336180 actual 4.4336180 clock 107.52 */
-	.dda1_inc	=    168,
-	.dda2_inc	=  18557,	.dda2_size	=  20625,
-	.dda3_inc	=      0,	.dda3_size	=      0,
-	.sc_reset   = TV_SC_RESET_NEVER,
-	.pal_burst  = FALSE
+	.name       = "576p",
+	.clock 	= 107520,	
+	.oversample     = TV_OVERSAMPLE_4X,
+	.component_only = 1,
 
-	.composite_levels = { .blank = 225, .black = 267, .burst = 113 },
-	.composite_color = {
-	    .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.5082,
-	    .ru =-0.0749, .gu =-0.1471, .bu = 0.2220, .au = 1.0000,
-	    .rv = 0.3125, .gv =-0.2616, .bv =-0.0508, .av = 1.0000,
-	},
+	.hsync_end      = 64,               .hblank_end         = 139,
+	.hblank_start   = 859,              .htotal             = 863,
 
-	.svideo_levels    = { .blank = 266, .black = 316, .burst = 133 },
-	.svideo_color = {
-	    .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.6006,
-	    .ru =-0.0885, .gu =-0.1738, .bu = 0.2624, .au = 1.0000,
-	    .rv = 0.3693, .gv =-0.3092, .bv =-0.0601, .av = 1.0000,
-	},
+	.progressive    = TRUE,		.trilevel_sync = FALSE,
+
+	.vsync_start_f1 = 10,               .vsync_start_f2     = 10,
+	.vsync_len      = 10,
+
+	.veq_ena        = FALSE,
+
+	.vi_end_f1      = 48,               .vi_end_f2          = 48,
+	.nbr_end        = 575,
+
+	.burst_ena      = FALSE,
+
+	.filter_table = filter_table,
+    },
+    {
+	.name       = "720p at 60Hz",
+	.clock		= 148800,	
+	.oversample     = TV_OVERSAMPLE_2X,
+	.component_only = 1,
+
+	.hsync_end      = 80,               .hblank_end         = 300,
+	.hblank_start   = 1580,             .htotal             = 1649,
+
+	.progressive    = TRUE, 	    .trilevel_sync = TRUE,
+
+	.vsync_start_f1 = 10,               .vsync_start_f2     = 10,
+	.vsync_len      = 10,
+
+	.veq_ena        = FALSE,
+
+	.vi_end_f1      = 29,               .vi_end_f2          = 29,
+	.nbr_end        = 719,
+
+	.burst_ena      = FALSE,
+
+	.filter_table = filter_table,
+    },
+    {
+	.name       = "720p at 59.94Hz",
+	.clock		= 148800,	
+	.oversample     = TV_OVERSAMPLE_2X,
+	.component_only = 1,
+
+	.hsync_end      = 80,               .hblank_end         = 300,
+	.hblank_start   = 1580,             .htotal             = 1651,
+
+	.progressive    = TRUE, 	    .trilevel_sync = TRUE,
+
+	.vsync_start_f1 = 10,               .vsync_start_f2     = 10,
+	.vsync_len      = 10,
+
+	.veq_ena        = FALSE,
+
+	.vi_end_f1      = 29,               .vi_end_f2          = 29,
+	.nbr_end        = 719,
+
+	.burst_ena      = FALSE,
+
+	.filter_table = filter_table,
+    },
+    {
+	.name       = "720p at 50Hz",
+	.clock		= 148800,	
+	.oversample     = TV_OVERSAMPLE_2X,
+	.component_only = 1,
+
+	.hsync_end      = 80,               .hblank_end         = 300,
+	.hblank_start   = 1580,             .htotal             = 1979,
+
+	.progressive    = TRUE, 	        .trilevel_sync = TRUE,
+
+	.vsync_start_f1 = 10,               .vsync_start_f2     = 10,
+	.vsync_len      = 10,
+
+	.veq_ena        = FALSE,
+
+	.vi_end_f1      = 29,               .vi_end_f2          = 29,
+	.nbr_end        = 719,
+
+	.burst_ena      = FALSE,
+
+	.filter_table = filter_table,
+	.max_srcw = 800
+    },
+    {
+	.name       = "1080i at 50Hz",
+	.clock		= 148800,	
+	.oversample     = TV_OVERSAMPLE_2X,
+	.component_only = 1,
+
+	.hsync_end      = 88,               .hblank_end         = 235,
+	.hblank_start   = 2155,             .htotal             = 2639,
+
+	.progressive    = FALSE, 	    .trilevel_sync = TRUE,
+
+	.vsync_start_f1 = 4,              .vsync_start_f2     = 5,
+	.vsync_len      = 10,
+
+	.veq_ena	= TRUE,		    .veq_start_f1    	= 4,
+	.veq_start_f2   = 4,	    .veq_len		= 10,
+
+
+	.vi_end_f1      = 21,           .vi_end_f2          = 22,
+	.nbr_end        = 539,
+
+	.burst_ena      = FALSE,
+
+	.filter_table = filter_table,
+    },
+    {
+	.name       = "1080i at 60Hz",
+	.clock		= 148800,	
+	.oversample     = TV_OVERSAMPLE_2X,
+	.component_only = 1,
+
+	.hsync_end      = 88,               .hblank_end         = 235,
+	.hblank_start   = 2155,             .htotal             = 2199,
+
+	.progressive    = FALSE, 	    .trilevel_sync = TRUE,
+
+	.vsync_start_f1 = 4,               .vsync_start_f2     = 5,
+	.vsync_len      = 10,
+
+	.veq_ena	= TRUE,		    .veq_start_f1    	= 4,
+	.veq_start_f2	= 4,		    .veq_len		= 10,
+
+
+	.vi_end_f1      = 21,               .vi_end_f2          = 22,
+	.nbr_end        = 539,
+
+	.burst_ena      = FALSE,
+
+	.filter_table = filter_table,
+    },
+    {
+	.name       = "1080i at 59.94Hz",
+	.clock		= 148800,	
+	.oversample     = TV_OVERSAMPLE_2X,
+	.component_only = 1,
+
+	.hsync_end      = 88,               .hblank_end         = 235,
+	.hblank_start   = 2155,             .htotal             = 2200,
+
+	.progressive    = FALSE, 	    .trilevel_sync = TRUE,
+
+	.vsync_start_f1 = 4,            .vsync_start_f2    = 5,
+	.vsync_len      = 10,
+
+	.veq_ena	= TRUE,		    .veq_start_f1	= 4,
+	.veq_start_f2 = 4,	    	    .veq_len = 10,
+
+
+	.vi_end_f1      = 21,           .vi_end_f2         	= 22,
+	.nbr_end        = 539,
+
+	.burst_ena      = FALSE,
+
+	.filter_table = filter_table,
     },
-#endif
 };
 
 static const video_levels_t component_level = {
-    .blank = 279, .black = 279 
+	.blank = 279, .black = 279 
 };
 
 static const color_conversion_t sdtv_component_color = {
@@ -407,13 +738,13 @@ static const color_conversion_t sdtv_com
     .ru =-0.1687, .gu =-0.3313, .bu = 0.5000, .au = 1.0000,
     .rv = 0.5000, .gv =-0.4187, .bv =-0.0813, .av = 1.0000,
 };
-    
+
 static const color_conversion_t hdtv_component_color = {
     .ry = 0.2126, .gy = 0.7152, .by = 0.0722, .ay = 0.6364,
     .ru =-0.1146, .gu =-0.3854, .bu = 0.5000, .au = 1.0000,
     .rv = 0.5000, .gv =-0.4542, .bv =-0.0458, .av = 1.0000,
 };
-    
+
 static void
 i830_tv_dpms(xf86OutputPtr output, int mode)
 {
@@ -421,14 +752,14 @@ i830_tv_dpms(xf86OutputPtr output, int m
     I830Ptr pI830 = I830PTR(pScrn);
 
     switch(mode) {
-    case DPMSModeOn:
-	OUTREG(TV_CTL, INREG(TV_CTL) | TV_ENC_ENABLE);
-	break;
-    case DPMSModeStandby:
-    case DPMSModeSuspend:
-    case DPMSModeOff:
-	OUTREG(TV_CTL, INREG(TV_CTL) & ~TV_ENC_ENABLE);
-	break;
+	case DPMSModeOn:
+	    OUTREG(TV_CTL, INREG(TV_CTL) | TV_ENC_ENABLE);
+	    break;
+	case DPMSModeStandby:
+	case DPMSModeSuspend:
+	case DPMSModeOff:
+	    OUTREG(TV_CTL, INREG(TV_CTL) & ~TV_ENC_ENABLE);
+	    break;
     }
 }
 
@@ -491,6 +822,11 @@ i830_tv_restore(xf86OutputPtr output)
     struct i830_tv_priv	    *dev_priv = intel_output->dev_priv;
     int			    i;
 
+    xf86CrtcPtr	    crtc = output->crtc;
+    I830CrtcPrivatePtr  intel_crtc;
+    if (!crtc)
+	return;
+    intel_crtc = crtc->driver_private;
     OUTREG(TV_H_CTL_1, dev_priv->save_TV_H_CTL_1);
     OUTREG(TV_H_CTL_2, dev_priv->save_TV_H_CTL_2);
     OUTREG(TV_H_CTL_3, dev_priv->save_TV_H_CTL_3);
@@ -513,11 +849,38 @@ i830_tv_restore(xf86OutputPtr output)
     OUTREG(TV_CSC_V2, dev_priv->save_TV_CSC_V2);
     OUTREG(TV_CLR_KNOBS, dev_priv->save_TV_CLR_KNOBS);
     OUTREG(TV_CLR_LEVEL, dev_priv->save_TV_CLR_LEVEL);
-    OUTREG(TV_WIN_POS, dev_priv->save_TV_WIN_POS);
-    OUTREG(TV_WIN_SIZE, dev_priv->save_TV_WIN_SIZE);
-    OUTREG(TV_FILTER_CTL_1, dev_priv->save_TV_FILTER_CTL_1);
-    OUTREG(TV_FILTER_CTL_2, dev_priv->save_TV_FILTER_CTL_2);
-    OUTREG(TV_FILTER_CTL_3, dev_priv->save_TV_FILTER_CTL_3);
+
+    {
+	int pipeconf_reg = (intel_crtc->pipe == 0)?PIPEACONF:PIPEBCONF;
+	int dspcntr_reg = (intel_crtc->pipe == 0)?DSPACNTR : DSPBCNTR;
+	int pipeconf = INREG(pipeconf_reg);
+	int dspcntr = INREG(dspcntr_reg);
+	int dspbase_reg = (intel_crtc->pipe == 0) ? DSPABASE : DSPBBASE;
+	/* Pipe must be off here */
+	OUTREG(dspcntr_reg, dspcntr & ~DISPLAY_PLANE_ENABLE);
+	/* Flush the plane changes */
+	OUTREG(dspbase_reg, INREG(dspbase_reg));
+
+	if (!IS_I9XX(pI830)) {
+	    /* Wait for vblank for the disable to take effect */
+	    i830WaitForVblank(pScrn);
+	}
+
+	OUTREG(pipeconf_reg, pipeconf & ~PIPEACONF_ENABLE);
+	/* Wait for vblank for the disable to take effect. */
+	i830WaitForVblank(pScrn);
+
+	/* Filter ctl must be set before TV_WIN_SIZE */
+	OUTREG(TV_FILTER_CTL_1, dev_priv->save_TV_FILTER_CTL_1);
+	OUTREG(TV_FILTER_CTL_2, dev_priv->save_TV_FILTER_CTL_2);
+	OUTREG(TV_FILTER_CTL_3, dev_priv->save_TV_FILTER_CTL_3);
+	OUTREG(TV_WIN_POS, dev_priv->save_TV_WIN_POS);
+	OUTREG(TV_WIN_SIZE, dev_priv->save_TV_WIN_SIZE);
+	OUTREG(pipeconf_reg, pipeconf);
+	OUTREG(dspcntr_reg, dspcntr);
+	/* Flush the plane changes */
+	OUTREG(dspbase_reg, INREG(dspbase_reg));
+    }
 
     for (i = 0; i < 60; i++)
 	OUTREG(TV_H_LUMA_0 + (i <<2), dev_priv->save_TV_H_LUMA[i]);
@@ -535,95 +898,32 @@ i830_tv_restore(xf86OutputPtr output)
 static int
 i830_tv_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
 {
-    return MODE_OK;
+	return MODE_OK;
 }
 
-static const CARD32 h_luma[60] = {
-    0xB1403000, 0x2E203500, 0x35002E20, 0x3000B140,
-    0x35A0B160, 0x2DC02E80, 0xB1403480, 0xB1603000,
-    0x2EA03640, 0x34002D80, 0x3000B120, 0x36E0B160,
-    0x2D202EF0, 0xB1203380, 0xB1603000, 0x2F303780,
-    0x33002CC0, 0x3000B100, 0x3820B160, 0x2C802F50,
-    0xB10032A0, 0xB1603000, 0x2F9038C0, 0x32202C20,
-    0x3000B0E0, 0x3980B160, 0x2BC02FC0, 0xB0E031C0,
-    0xB1603000, 0x2FF03A20, 0x31602B60, 0xB020B0C0,
-    0x3AE0B160, 0x2B001810, 0xB0C03120, 0xB140B020,
-    0x18283BA0, 0x30C02A80, 0xB020B0A0, 0x3C60B140,
-    0x2A201838, 0xB0A03080, 0xB120B020, 0x18383D20,
-    0x304029C0, 0xB040B080, 0x3DE0B100, 0x29601848,
-    0xB0803000, 0xB100B040, 0x18483EC0, 0xB0402900,
-    0xB040B060, 0x3F80B0C0, 0x28801858, 0xB060B080,
-    0xB0A0B060, 0x18602820, 0xB0A02820, 0x0000B060,
-};
-
-static const CARD32 h_chroma[60] = {
-    0xB1403000, 0x2E203500, 0x35002E20, 0x3000B140,
-    0x35A0B160, 0x2DC02E80, 0xB1403480, 0xB1603000,
-    0x2EA03640, 0x34002D80, 0x3000B120, 0x36E0B160,
-    0x2D202EF0, 0xB1203380, 0xB1603000, 0x2F303780,
-    0x33002CC0, 0x3000B100, 0x3820B160, 0x2C802F50,
-    0xB10032A0, 0xB1603000, 0x2F9038C0, 0x32202C20,
-    0x3000B0E0, 0x3980B160, 0x2BC02FC0, 0xB0E031C0,
-    0xB1603000, 0x2FF03A20, 0x31602B60, 0xB020B0C0,
-    0x3AE0B160, 0x2B001810, 0xB0C03120, 0xB140B020,
-    0x18283BA0, 0x30C02A80, 0xB020B0A0, 0x3C60B140,
-    0x2A201838, 0xB0A03080, 0xB120B020, 0x18383D20,
-    0x304029C0, 0xB040B080, 0x3DE0B100, 0x29601848,
-    0xB0803000, 0xB100B040, 0x18483EC0, 0xB0402900,
-    0xB040B060, 0x3F80B0C0, 0x28801858, 0xB060B080,
-    0xB0A0B060, 0x18602820, 0xB0A02820, 0x0000B060,
-};
-
-static const CARD32 v_luma[43] = {
-    0x36403000, 0x2D002CC0, 0x30003640, 0x2D0036C0,
-    0x35C02CC0, 0x37403000, 0x2C802D40, 0x30003540,
-    0x2D8037C0, 0x34C02C40, 0x38403000, 0x2BC02E00,
-    0x30003440, 0x2E2038C0, 0x34002B80, 0x39803000,
-    0x2B402E40, 0x30003380, 0x2E603A00, 0x33402B00,
-    0x3A803040, 0x2A802EA0, 0x30403300, 0x2EC03B40,
-    0x32802A40, 0x3C003040, 0x2A002EC0, 0x30803240,
-    0x2EC03C80, 0x320029C0, 0x3D403080, 0x29402F00,
-    0x308031C0, 0x2F203DC0, 0x31802900, 0x3E8030C0,
-    0x28802F40, 0x30C03140, 0x2F203F40, 0x31402840,
-    0x28003100, 0x28002F00, 0x00003100,
-};
-
-static const CARD32 v_chroma[43] = {
-    0x36403000, 0x2D002CC0, 0x30003640, 0x2D0036C0,
-    0x35C02CC0, 0x37403000, 0x2C802D40, 0x30003540,
-    0x2D8037C0, 0x34C02C40, 0x38403000, 0x2BC02E00,
-    0x30003440, 0x2E2038C0, 0x34002B80, 0x39803000,
-    0x2B402E40, 0x30003380, 0x2E603A00, 0x33402B00,
-    0x3A803040, 0x2A802EA0, 0x30403300, 0x2EC03B40,
-    0x32802A40, 0x3C003040, 0x2A002EC0, 0x30803240,
-    0x2EC03C80, 0x320029C0, 0x3D403080, 0x29402F00,
-    0x308031C0, 0x2F203DC0, 0x31802900, 0x3E8030C0,
-    0x28802F40, 0x30C03140, 0x2F203F40, 0x31402840,
-    0x28003100, 0x28002F00, 0x00003100,
-};
 
 static Bool
 i830_tv_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
-		 DisplayModePtr adjusted_mode)
+		DisplayModePtr adjusted_mode)
 {
-    ScrnInfoPtr pScrn = output->scrn;
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-    int i;
-
-    for (i = 0; i < xf86_config->num_output; i++) {
-	xf86OutputPtr other_output = xf86_config->output[i];
-
-	if (other_output != output && other_output->crtc == output->crtc) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		       "Can't enable TV and another output on the same "
-		       "pipe\n");
-	    return FALSE;
+	ScrnInfoPtr pScrn = output->scrn;
+	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+	int i;
+
+	for (i = 0; i < xf86_config->num_output; i++) {
+		xf86OutputPtr other_output = xf86_config->output[i];
+
+		if (other_output != output && other_output->crtc == output->crtc) {
+			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+					"Can't enable TV and another output on the same "
+					"pipe\n");
+			return FALSE;
+		}
 	}
-    }
 
-    /* XXX: fill me in */
+	/* XXX: fill me in */
 
-    return TRUE;
+	return TRUE;
 }
 
 static CARD32
@@ -633,10 +933,10 @@ i830_float_to_csc (float fin)
     CARD32  mant;
     CARD32  ret;
     float   f = fin;
-    
+
     /* somehow the color conversion knows the signs of all the values */
     if (f < 0) f = -f;
-    
+
     if (f >= 1)
     {
 	exp = 0x7;
@@ -665,7 +965,7 @@ i830_float_to_luma (float f)
 
 static void
 i830_tv_mode_set(xf86OutputPtr output, DisplayModePtr mode,
-		 DisplayModePtr adjusted_mode)
+		DisplayModePtr adjusted_mode)
 {
     ScrnInfoPtr		    pScrn = output->scrn;
     I830Ptr		    pI830 = I830PTR(pScrn);
@@ -674,53 +974,52 @@ i830_tv_mode_set(xf86OutputPtr output, D
     I830CrtcPrivatePtr	    intel_crtc = crtc->driver_private;
     struct i830_tv_priv	    *dev_priv = intel_output->dev_priv;
     const tv_mode_t	    *tv_mode;
-    CARD32		    tv_ctl, tv_filter_ctl;
+    CARD32		    tv_ctl;
     CARD32		    hctl1, hctl2, hctl3;
     CARD32		    vctl1, vctl2, vctl3, vctl4, vctl5, vctl6, vctl7;
     CARD32		    scctl1, scctl2, scctl3;
-    int			    i;
+    int			    i, j;
     const video_levels_t	*video_levels;
     const color_conversion_t	*color_conversion;
-    Bool		    burst_ena;
-
-    /* Need to actually choose or construct the appropriate
-     * mode.  For now, just set the first one in the list, with
-     * NTSC format.
-     */
-    tv_mode = &tv_modes[0];
-    
+    Bool burst_ena;
+    for (i = 0; i < sizeof(tv_modes) / sizeof (tv_modes[0]); i++) {
+	tv_mode = &tv_modes[i];
+	if (strstr(mode->name, tv_mode->name))
+	    break;	
+    }
     tv_ctl = 0;
 
     switch (dev_priv->type) {
-    default:
-    case TV_TYPE_UNKNOWN:
-    case TV_TYPE_COMPOSITE:
-	tv_ctl |= TV_ENC_OUTPUT_COMPOSITE;
-	video_levels = &tv_mode->composite_levels;
-	color_conversion = &tv_mode->composite_color;
-	burst_ena = tv_mode->burst_ena;
-	break;
-    case TV_TYPE_COMPONENT:
-	tv_ctl |= TV_ENC_OUTPUT_COMPONENT;
-	video_levels = &component_level;
-	if (tv_mode->burst_ena)
-	    color_conversion = &sdtv_component_color;
-	else
-	    color_conversion = &hdtv_component_color;
-	burst_ena = FALSE;
-	break;
-    case TV_TYPE_SVIDEO:
-	tv_ctl |= TV_ENC_OUTPUT_SVIDEO;
-	video_levels = &tv_mode->svideo_levels;
-	color_conversion = &tv_mode->svideo_color;
-	burst_ena = tv_mode->burst_ena;
-	break;
+	default:
+	case TV_TYPE_UNKNOWN:
+	case TV_TYPE_COMPOSITE:
+	    tv_ctl |= TV_ENC_OUTPUT_COMPOSITE;
+	    video_levels = &tv_mode->composite_levels;
+	    color_conversion = &tv_mode->composite_color;
+	    burst_ena = tv_mode->burst_ena;
+	    break;
+	case TV_TYPE_COMPONENT:
+	    tv_ctl |= TV_ENC_OUTPUT_COMPONENT;
+	    video_levels = &component_level;
+	    if (tv_mode->burst_ena)
+		color_conversion = &sdtv_component_color;
+	    else
+		color_conversion = &hdtv_component_color;
+	    burst_ena = FALSE;
+	    break;
+	case TV_TYPE_SVIDEO:
+	    tv_ctl |= TV_ENC_OUTPUT_SVIDEO;
+	    video_levels = &tv_mode->svideo_levels;
+	    color_conversion = &tv_mode->svideo_color;
+	    burst_ena = tv_mode->burst_ena;
+	    break;
     }
     hctl1 = (tv_mode->hsync_end << TV_HSYNC_END_SHIFT) |
 	(tv_mode->htotal << TV_HTOTAL_SHIFT);
 
     hctl2 = (tv_mode->hburst_start << 16) |
 	(tv_mode->hburst_len << TV_HBURST_LEN_SHIFT);
+
     if (burst_ena)
 	hctl2 |= TV_BURST_ENA;
 
@@ -738,6 +1037,7 @@ i830_tv_mode_set(xf86OutputPtr output, D
     vctl3 = (tv_mode->veq_len << TV_VEQ_LEN_SHIFT) |
 	(tv_mode->veq_start_f1 << TV_VEQ_START_F1_SHIFT) |
 	(tv_mode->veq_start_f2 << TV_VEQ_START_F2_SHIFT);
+
     if (tv_mode->veq_ena)
 	vctl3 |= TV_EQUAL_ENA;
 
@@ -755,21 +1055,24 @@ i830_tv_mode_set(xf86OutputPtr output, D
 
     if (intel_crtc->pipe == 1)
 	tv_ctl |= TV_ENC_PIPEB_SELECT;
-
     tv_ctl |= tv_mode->oversample;
+
     if (tv_mode->progressive)
 	tv_ctl |= TV_PROGRESSIVE;
+    if (tv_mode->trilevel_sync)
+	tv_ctl |= TV_TRILEVEL_SYNC;
     if (tv_mode->pal_burst)
 	tv_ctl |= TV_PAL_BURST;
+    scctl1 = 0;
+    if (tv_mode->dda1_inc)
+	scctl1 |= TV_SC_DDA1_EN;
 
-    scctl1 = TV_SC_DDA1_EN;
-    
     if (tv_mode->dda2_inc)
 	scctl1 |= TV_SC_DDA2_EN;
-    
+
     if (tv_mode->dda3_inc)
 	scctl1 |= TV_SC_DDA3_EN;
-    
+
     scctl1 |= tv_mode->sc_reset;
     scctl1 |= video_levels->burst << TV_BURST_LEVEL_SHIFT;
     scctl1 |= tv_mode->dda1_inc << TV_SCDDA1_INC_SHIFT;
@@ -784,10 +1087,6 @@ i830_tv_mode_set(xf86OutputPtr output, D
     if (pI830->PciInfo->chipType < PCI_CHIP_I945_G)
 	tv_ctl |= TV_ENC_C0_FIX | TV_ENC_SDP_FIX;
 
-    tv_filter_ctl = TV_AUTO_SCALE;
-    if (mode->HDisplay > 1024)
-	tv_ctl |= TV_V_FILTER_BYPASS;
-
     OUTREG(TV_H_CTL_1, hctl1);
     OUTREG(TV_H_CTL_2, hctl2);
     OUTREG(TV_H_CTL_3, hctl3);
@@ -801,183 +1100,113 @@ i830_tv_mode_set(xf86OutputPtr output, D
     OUTREG(TV_SC_CTL_1, scctl1);
     OUTREG(TV_SC_CTL_2, scctl2);
     OUTREG(TV_SC_CTL_3, scctl3);
-    
+
     OUTREG(TV_CSC_Y,
-	   (i830_float_to_csc(color_conversion->ry) << 16) |
-	   (i830_float_to_csc(color_conversion->gy)));
+	    (i830_float_to_csc(color_conversion->ry) << 16) |
+	    (i830_float_to_csc(color_conversion->gy)));
     OUTREG(TV_CSC_Y2,
 	    (i830_float_to_csc(color_conversion->by) << 16) |
 	    (i830_float_to_luma(color_conversion->ay)));
-	   
+
     OUTREG(TV_CSC_U,
-	   (i830_float_to_csc(color_conversion->ru) << 16) |
-	   (i830_float_to_csc(color_conversion->gu)));
+	    (i830_float_to_csc(color_conversion->ru) << 16) |
+	    (i830_float_to_csc(color_conversion->gu)));
 
     OUTREG(TV_CSC_U2,
 	    (i830_float_to_csc(color_conversion->bu) << 16) |
 	    (i830_float_to_luma(color_conversion->au)));
-	   
+
     OUTREG(TV_CSC_V,
-	   (i830_float_to_csc(color_conversion->rv) << 16) |
-	   (i830_float_to_csc(color_conversion->gv)));
+	    (i830_float_to_csc(color_conversion->rv) << 16) |
+	    (i830_float_to_csc(color_conversion->gv)));
 
     OUTREG(TV_CSC_V2,
 	    (i830_float_to_csc(color_conversion->bv) << 16) |
 	    (i830_float_to_luma(color_conversion->av)));
-	   
-    OUTREG(TV_CLR_KNOBS, 0x00606000);
+
+    OUTREG(TV_CLR_KNOBS, 0x10606000);
     OUTREG(TV_CLR_LEVEL, ((video_levels->black << TV_BLACK_LEVEL_SHIFT) |
-			  (video_levels->blank << TV_BLANK_LEVEL_SHIFT)));
-    
-    OUTREG(TV_WIN_POS, 0x00360024);
-    OUTREG(TV_WIN_SIZE, 0x02640198);
-    
-    OUTREG(TV_FILTER_CTL_1, 0x8000085E);
-    OUTREG(TV_FILTER_CTL_2, 0x00017878);
-    OUTREG(TV_FILTER_CTL_3, 0x0000BC3C);
+		(video_levels->blank << TV_BLANK_LEVEL_SHIFT)));
+    {
+	int pipeconf_reg = (intel_crtc->pipe == 0)?PIPEACONF:PIPEBCONF;
+	int dspcntr_reg = (intel_crtc->pipe == 0)?DSPACNTR : DSPBCNTR;
+	int pipeconf = INREG(pipeconf_reg);
+	int dspcntr = INREG(dspcntr_reg);
+	int dspbase_reg = (intel_crtc->pipe == 0) ? DSPABASE : DSPBBASE;
+	int xpos = 0x0, ypos = 0x0;
+	unsigned int xsize, ysize;
+	/* Pipe must be off here */
+	OUTREG(dspcntr_reg, dspcntr & ~DISPLAY_PLANE_ENABLE);
+	/* Flush the plane changes */
+	OUTREG(dspbase_reg, INREG(dspbase_reg));
+
+	if (!IS_I9XX(pI830)) {
+	    /* Wait for vblank for the disable to take effect */
+	    i830WaitForVblank(pScrn);
+	}
+
+	OUTREG(pipeconf_reg, pipeconf & ~PIPEACONF_ENABLE);
+	/* Wait for vblank for the disable to take effect. */
+	i830WaitForVblank(pScrn);
+
+	/* Filter ctl must be set before TV_WIN_SIZE */
+	OUTREG(TV_FILTER_CTL_1, TV_AUTO_SCALE); 
+	xsize = tv_mode->hblank_start - tv_mode->hblank_end;
+	if (tv_mode->progressive)
+	    ysize = tv_mode->nbr_end + 1;
+	else
+	    ysize = 2*tv_mode->nbr_end + 1;
+
+	OUTREG(TV_WIN_POS, (xpos<<16)|ypos);
+	OUTREG(TV_WIN_SIZE, (xsize<<16)|ysize);
+
+	OUTREG(pipeconf_reg, pipeconf);
+	OUTREG(dspcntr_reg, dspcntr);
+	/* Flush the plane changes */
+	OUTREG(dspbase_reg, INREG(dspbase_reg));
+    } 	
+
+    j = 0;
     for (i = 0; i < 60; i++)
-	OUTREG(TV_H_LUMA_0 + (i <<2), h_luma[i]);
+	OUTREG(TV_H_LUMA_0 + (i<<2), tv_mode->filter_table[j++]);
     for (i = 0; i < 60; i++)
-	OUTREG(TV_H_CHROMA_0 + (i <<2), h_chroma[i]);
+	OUTREG(TV_H_CHROMA_0 + (i<<2), tv_mode->filter_table[j++]);
     for (i = 0; i < 43; i++)
-	OUTREG(TV_V_LUMA_0 + (i <<2), v_luma[i]);
+	OUTREG(TV_V_LUMA_0 + (i<<2), tv_mode->filter_table[j++]);
     for (i = 0; i < 43; i++)
-	OUTREG(TV_V_CHROMA_0 + (i <<2), v_chroma[i]);
-
+	OUTREG(TV_V_CHROMA_0 + (i<<2), tv_mode->filter_table[j++]);
     OUTREG(TV_DAC, 0);
     OUTREG(TV_CTL, tv_ctl);
 }
 
 static const DisplayModeRec reported_modes[] = {
-	{
-		.name = "NTSC 480i",
-		.Clock = TV_PLL_CLOCK,
-		.HDisplay   = 1280,
-		.HSyncStart = 1368,
-		.HSyncEnd   = 1496,
-		.HTotal     = 1712,
-
-		.VDisplay   = 1024,
-		.VSyncStart = 1027,
-		.VSyncEnd   = 1034,
-		.VTotal     = 1104,
-		.type       = M_T_DRIVER
-	},
-	{
-		.name = "NTSC 480i",
-		.Clock = TV_PLL_CLOCK,
-		.HDisplay   = 1024,
-		.HSyncStart = 1080,
-		.HSyncEnd   = 1184,
-		.HTotal     = 1344,
-
-		.VDisplay   = 768,
-		.VSyncStart = 771,
-		.VSyncEnd   = 777,
-		.VTotal     = 806,
-		.type       = M_T_DRIVER
-	},
-	{
-		.name = "NTSC 480i",
-		.Clock = TV_PLL_CLOCK,
-		.HDisplay   = 800,
-		.HSyncStart = 832,
-		.HSyncEnd   = 912,
-		.HTotal     = 1024,
-
-		.VDisplay   = 600,
-		.VSyncStart = 603,
-		.VSyncEnd   = 607,
-		.VTotal     = 650,
-		.type       = M_T_DRIVER
-	},
-	{
-		.name = "NTSC 480i",
-		.Clock = TV_PLL_CLOCK,
-		.HDisplay   = 640,
-		.HSyncStart = 664,
-		.HSyncEnd   = 720,
-		.HTotal     = 800,
-
-		.VDisplay   = 480,
-		.VSyncStart = 483,
-		.VSyncEnd   = 487,
-		.VTotal     = 552,
-		.type       = M_T_DRIVER
-	},
-	{
-		.name = "PAL 576i",
-		.Clock = TV_PLL_CLOCK,
-		.HDisplay   = 1280,
-		.HSyncStart = 1352,
-		.HSyncEnd   = 1480,
-		.HTotal     = 1680,
-
-		.VDisplay   = 1024,
-		.VSyncStart = 1027,
-		.VSyncEnd   = 1034,
-		.VTotal     = 1092,
-
-		.type       = M_T_DRIVER
-	},
-	{
-		.name = "PAL 576i",
-		.Clock = TV_PLL_CLOCK,
-		.HDisplay   = 1024,
-		.HSyncStart = 1072,
-		.HSyncEnd   = 1168,
-		.HTotal     = 1312,
-		.VDisplay   = 768,
-		.VSyncStart = 771,
-		.VSyncEnd   = 775,
-		.VTotal     = 820,
-		.VRefresh   = 50.0f,
-
-		.type       = M_T_DRIVER
-	},
-	{
-		.name = "PAL 576i",
-		.Clock = TV_PLL_CLOCK,
-		.HDisplay   = 800,
-		.HSyncStart = 832,
-		.HSyncEnd   = 904,
-		.HTotal     = 1008,
-		.VDisplay   = 600,
-		.VSyncStart = 603,
-		.VSyncEnd   = 607,
-		.VTotal     = 642,
-		.VRefresh   = 50.0f,
-
-		.type       = M_T_DRIVER
-	},
-	{
-		.name = "PAL 576i",
-		.Clock = TV_PLL_CLOCK,
-		.HDisplay   = 640,
-		.HSyncStart = 664,
-		.HSyncEnd   = 720,
-		.HTotal     = 800,
-
-		.VDisplay   = 480,
-		.VSyncStart = 483,
-		.VSyncEnd   = 487,
-		.VTotal     = 516,
-		.VRefresh   = 50.0f,
-		.type       = M_T_DRIVER
-	},
+    {
+	.name = "NTSC 480i",
+	.Clock = 107520,
+	.HDisplay   = 1280,
+	.HSyncStart = 1368,
+	.HSyncEnd   = 1496,
+	.HTotal     = 1712,
+
+	.VDisplay   = 1024,
+	.VSyncStart = 1027,
+	.VSyncEnd   = 1034,
+	.VTotal     = 1104,
+	.type       = M_T_DRIVER
+    },
 };
 
 /**
  * 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 void
 i830_tv_detect_type (xf86CrtcPtr    crtc,
-		     xf86OutputPtr  output)
+		xf86OutputPtr  output)
 {
     ScrnInfoPtr		    pScrn = output->scrn;
     I830Ptr		    pI830 = I830PTR(pScrn);
@@ -1002,13 +1231,13 @@ i830_tv_detect_type (xf86CrtcPtr    crtc
 	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 |
-		   DAC_CTL_OVERRIDE |
-		   DAC_A_0_7_V |
-		   DAC_B_0_7_V |
-		   DAC_C_0_7_V);
+		TVDAC_A_SENSE_CTL |
+		TVDAC_B_SENSE_CTL |
+		TVDAC_C_SENSE_CTL |
+		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);
@@ -1024,22 +1253,22 @@ i830_tv_detect_type (xf86CrtcPtr    crtc
      */
     if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) {
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		   "Detected Composite TV connection\n");
+		"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");
+		"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");
+		"Detected Component TV connection\n");
 	type = TV_TYPE_COMPONENT;
     } else {
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		   "No TV connection detected\n");
+		"No TV connection detected\n");
 	type = TV_TYPE_NONE;
     }
-    
+
     dev_priv->type = type;
 }
 
@@ -1060,55 +1289,108 @@ i830_tv_detect(xf86OutputPtr output)
     crtc = i830GetLoadDetectPipe (output);
     if (crtc)
     {
-	if (intel_output->load_detect_temp)
-	{
-	    /* we only need the pixel clock set correctly here */
-	    mode = reported_modes[0];
-	    xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
-	    xf86CrtcSetMode (crtc, &mode, RR_Rotate_0, 0, 0);
-	}
-	i830_tv_detect_type (crtc, output);
-	i830ReleaseLoadDetectPipe (output);
+        if (intel_output->load_detect_temp)
+        {
+            /* we only need the pixel clock set correctly here */
+            mode = reported_modes[0];
+            xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
+	    crtc->funcs->mode_set(crtc, &mode, &mode, 0, 0);
+        }
+        i830_tv_detect_type (crtc, output);
+        i830ReleaseLoadDetectPipe (output);
     }
-    
+
     switch (dev_priv->type) {
     case TV_TYPE_NONE:
-	return XF86OutputStatusDisconnected;
+        return XF86OutputStatusDisconnected;
     case TV_TYPE_UNKNOWN:
-	return XF86OutputStatusUnknown;
+        return XF86OutputStatusUnknown;
     default:
-	return XF86OutputStatusConnected;
+        return XF86OutputStatusConnected;
     }
 }
 
+struct input_res {
+    char *name;
+    int w, h;	
+} input_res_table[] = 
+{
+	{"640x480", 640, 480},
+	{"800x600", 800, 600},
+	{"1024x768", 1024, 768},
+	{"1280x1024", 1280, 1024},
+	{"848x480", 848, 480},
+	{"1280x720", 1280, 720},
+};
+
 /**
  * Stub get_modes function.
  *
  * This should probably return a set of fixed modes, unless we can figure out
  * how to probe modes off of TV connections.
  */
+
 static DisplayModePtr
 i830_tv_get_modes(xf86OutputPtr output)
 {
-    ScrnInfoPtr	    pScrn = output->scrn;
-    I830Ptr	    pI830 = I830PTR(pScrn);
-    DisplayModePtr  new, first = NULL, *tail = &first;
-    int		    i;
-
-    (void) pI830;
-
-    for (i = 0; i < sizeof (reported_modes) / sizeof (reported_modes[0]); i++)
-    {
-	new             = xnfcalloc(1, sizeof (DisplayModeRec));
-
-	*new = reported_modes[i];
-	new->name = xnfalloc(strlen(reported_modes[i].name) + 1);
-	strcpy(new->name, reported_modes[i].name);
-	*tail = new;
-	tail = &new->next;
+    DisplayModePtr  ret = NULL, mode_ptr;
+    int		    i, j;
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    struct i830_tv_priv	    *dev_priv = intel_output->dev_priv;
+
+    for (i = 0; i < sizeof(tv_modes) / sizeof (tv_modes[0]); i++) 
+    {
+	const tv_mode_t *tv_mode = &tv_modes[i];
+	unsigned int hactive = tv_mode->hblank_start - tv_mode->hblank_end;
+	unsigned int vactive = tv_mode->progressive
+	    ?tv_mode->nbr_end + 1: 2*(tv_mode->nbr_end + 1);
+	unsigned int htotal = tv_mode->htotal + 1;
+	unsigned int vtotal = tv_mode->progressive
+	    ?tv_mode->nbr_end + 1 + tv_mode->vi_end_f2:
+	    2*(tv_mode->nbr_end+1) + 2*(tv_mode->vi_end_f2);
+
+	if (dev_priv->type != TV_TYPE_COMPONENT && tv_mode->component_only)
+	    continue;
+
+	for (j = 0; j < sizeof(input_res_table)/sizeof(input_res_table[0]); j++)	{
+	    struct input_res *input = &input_res_table[j];
+	    unsigned int hactive_s = input->w;
+	    unsigned int vactive_s = input->h;
+	    unsigned int htotal_s = htotal*hactive_s/hactive;
+	    unsigned int vtotal_s = vtotal*vactive_s/vactive;
+	    if (tv_mode->max_srcw && input->w > tv_mode->max_srcw)
+		continue;
+	    if (input->w > 1024 && (!tv_mode->progressive 
+			&& !tv_mode->component_only))
+		continue;
+	    mode_ptr = xnfcalloc(1, sizeof(DisplayModeRec));
+	    mode_ptr->name = xnfalloc(strlen(tv_mode->name) + 
+		    strlen(input->name) + 4);
+	    sprintf(mode_ptr->name, "%s %s", tv_mode->name, input->name);
+
+	    mode_ptr->Clock = tv_mode->clock;
+
+	    mode_ptr->HDisplay = hactive_s;
+	    mode_ptr->HSyncStart = hactive_s + 1;
+	    mode_ptr->HSyncEnd = htotal_s - 20;  
+	    if ( mode_ptr->HSyncEnd <= mode_ptr->HSyncStart)
+		mode_ptr->HSyncEnd = mode_ptr->HSyncStart  + 1;
+	    mode_ptr->HTotal = htotal_s;
+
+	    mode_ptr->VDisplay = vactive_s;
+	    mode_ptr->VSyncStart = vactive_s + 1;
+	    mode_ptr->VSyncEnd = vtotal_s - 20;
+	    if ( mode_ptr->VSyncEnd <= mode_ptr->VSyncStart)
+		mode_ptr->VSyncEnd = mode_ptr->VSyncStart  + 1;
+	    mode_ptr->VTotal = vtotal_s;
+
+	    mode_ptr->type = M_T_DRIVER;
+	    mode_ptr->next = ret;
+	    ret = mode_ptr;
+	} 
     }
 
-    return first;
+    return ret;
 }
 
 static void
@@ -1138,7 +1420,7 @@ i830_tv_init(ScrnInfoPtr pScrn)
     I830OutputPrivatePtr    intel_output;
     struct i830_tv_priv	    *dev_priv;
     CARD32		    tv_dac_on, tv_dac_off, save_tv_dac;
- 
+
     if ((INREG(TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED)
 	return;
 
@@ -1147,31 +1429,31 @@ i830_tv_init(ScrnInfoPtr pScrn)
      * DAC register holds a value
      */
     save_tv_dac = INREG(TV_DAC);
-    
+
     OUTREG(TV_DAC, save_tv_dac | TVDAC_STATE_CHG_EN);
     tv_dac_on = INREG(TV_DAC);
-    
+
     OUTREG(TV_DAC, save_tv_dac & ~TVDAC_STATE_CHG_EN);
     tv_dac_off = INREG(TV_DAC);
-    
+
     OUTREG(TV_DAC, save_tv_dac);
-    
+
     /*
      * If the register does not hold the state change enable
      * bit, (either as a 0 or a 1), assume it doesn't really
      * exist
      */
     if ((tv_dac_on & TVDAC_STATE_CHG_EN) == 0 || 
-	(tv_dac_off & TVDAC_STATE_CHG_EN) != 0)
+	    (tv_dac_off & TVDAC_STATE_CHG_EN) != 0)
 	return;
-    
+
     output = xf86OutputCreate (pScrn, &i830_tv_output_funcs, "TV");
-    
+
     if (!output)
 	return;
-    
+
     intel_output = xnfcalloc (sizeof (I830OutputPrivateRec) +
-			      sizeof (struct i830_tv_priv), 1);
+	    sizeof (struct i830_tv_priv), 1);
     if (!intel_output)
     {
 	xf86OutputDestroy (output);
@@ -1181,7 +1463,7 @@ i830_tv_init(ScrnInfoPtr pScrn)
     intel_output->type = I830_OUTPUT_TVOUT;
     intel_output->dev_priv = dev_priv;
     dev_priv->type = TV_TYPE_UNKNOWN;
-    
+
     output->driver_private = intel_output;
     output->interlaceAllowed = FALSE;
     output->doubleScanAllowed = FALSE;
diff-tree 10712c7a781e50475ee7e8ccd5bfd2d820f863e2 (from 44eacf2323454e26b535cc5a4f0789cb0ff0e7fb)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Thu Feb 8 08:56:42 2007 +0800

    EXA: i965 pixmap pitch align
    
    This seems like a typo, which causes screen artifacts.

diff --git a/src/i830_exa.c b/src/i830_exa.c
index 97b4a98..c3a4c40 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -374,7 +374,7 @@ I830EXAInit(ScreenPtr pScreen)
      */
     if (IS_I965G(pI830)) {
 	pI830->EXADriverPtr->pixmapOffsetAlign = 4 * 2;
-	pI830->EXADriverPtr->pixmapPitchAlign = 1;
+	pI830->EXADriverPtr->pixmapPitchAlign = 16;
 	pI830->EXADriverPtr->maxX = 8192;
 	pI830->EXADriverPtr->maxY = 8192;
     } else {
diff-tree 44eacf2323454e26b535cc5a4f0789cb0ff0e7fb (from 785a59ead0e8d1d681b2cb6827ee58ad2c51f8c6)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Feb 7 17:30:51 2007 +0800

    EXA: fix render issue with i965
    
    Fix SF kernel with corrent coeffient work, and correct
    VUE storage in multi texture case.

diff --git a/src/exa_sf_mask.g4a b/src/exa_sf_mask.g4a
index ab519ce..a7e2d32 100644
--- a/src/exa_sf_mask.g4a
+++ b/src/exa_sf_mask.g4a
@@ -22,25 +22,25 @@ mul (1) g7<1>F g7<0,1,0>F g6<0,1,0>F { a
 /* Cy[0] */
 mul (1) g7.4<1>F g7.4<0,1,0>F g6.4<0,1,0>F { align1 };
 /* Cx[2] */
-mul (1) g7.16<1>F g7.16<0,1,0>F g6<0,1,0>F { align1 };
+mul (1) g7.8<1>F g7.8<0,1,0>F g6<0,1,0>F { align1 };
 /* Cy[2] */
-mul (1) g7.20<1>F g7.20<0,1,0>F g6.4<0,1,0>F { align1 };
+mul (1) g7.12<1>F g7.12<0,1,0>F g6.4<0,1,0>F { align1 };
 
 /* src Cx[0], Cx[1] */
 mov (8) m1<1>F g7<0,1,0>F { align1 };
 /* mask Cx[2], Cx[3] */
-mov (1) m1.8<1>F g7.16<0,1,0>F { align1 };
-mov (1) m1.12<1>F g7.16<0,1,0>F { align1 };
+mov (1) m1.8<1>F g7.8<0,1,0>F { align1 };
+mov (1) m1.12<1>F g7.8<0,1,0>F { align1 };
 /* src Cy[0], Cy[1] */
 mov (8) m2<1>F g7.4<0,1,0>F { align1 };
 /* mask Cy[2], Cy[3] */
-mov (1) m2.8<1>F g7.20<0,1,0>F { align1 };
-mov (1) m2.12<1>F g7.20<0,1,0>F { align1 };
+mov (1) m2.8<1>F g7.12<0,1,0>F { align1 };
+mov (1) m2.12<1>F g7.12<0,1,0>F { align1 };
 /* src Co[0], Co[1] */
 mov (8) m3<1>F g3<8,8,1>F { align1 };
 /* mask Co[2], Co[3] */
-mov (1) m3.8<1>F g3.16<0,1,0>F { align1 };
-mov (1) m3.12<1>F g3.20<0,1,0>F { align1 };
+mov (1) m3.8<1>F g3.8<0,1,0>F { align1 };
+mov (1) m3.12<1>F g3.12<0,1,0>F { align1 };
 
 send (8) 0 null g0<8,8,1>F urb 0 transpose used complete mlen 4 rlen 0 { align1 EOT };
 nop;
diff --git a/src/exa_sf_mask_prog.h b/src/exa_sf_mask_prog.h
index cd7f460..4e9114d 100644
--- a/src/exa_sf_mask_prog.h
+++ b/src/exa_sf_mask_prog.h
@@ -3,17 +3,17 @@
    { 0x00600040, 0x20e077bd, 0x008d0080, 0x008d4060 },
    { 0x00000041, 0x20e077bd, 0x000000e0, 0x000000c0 },
    { 0x00000041, 0x20e477bd, 0x000000e4, 0x000000c4 },
-   { 0x00000041, 0x20f077bd, 0x000000f0, 0x000000c0 },
-   { 0x00000041, 0x20f477bd, 0x000000f4, 0x000000c4 },
+   { 0x00000041, 0x20e877bd, 0x000000e8, 0x000000c0 },
+   { 0x00000041, 0x20ec77bd, 0x000000ec, 0x000000c4 },
    { 0x00600001, 0x202003be, 0x000000e0, 0x00000000 },
-   { 0x00000001, 0x202803be, 0x000000f0, 0x00000000 },
-   { 0x00000001, 0x202c03be, 0x000000f0, 0x00000000 },
+   { 0x00000001, 0x202803be, 0x000000e8, 0x00000000 },
+   { 0x00000001, 0x202c03be, 0x000000e8, 0x00000000 },
    { 0x00600001, 0x204003be, 0x000000e4, 0x00000000 },
-   { 0x00000001, 0x204803be, 0x000000f4, 0x00000000 },
-   { 0x00000001, 0x204c03be, 0x000000f4, 0x00000000 },
+   { 0x00000001, 0x204803be, 0x000000ec, 0x00000000 },
+   { 0x00000001, 0x204c03be, 0x000000ec, 0x00000000 },
    { 0x00600001, 0x206003be, 0x008d0060, 0x00000000 },
-   { 0x00000001, 0x206803be, 0x00000070, 0x00000000 },
-   { 0x00000001, 0x206c03be, 0x00000074, 0x00000000 },
+   { 0x00000001, 0x206803be, 0x00000068, 0x00000000 },
+   { 0x00000001, 0x206c03be, 0x0000006c, 0x00000000 },
    { 0x00600031, 0x20001fbc, 0x008d0000, 0x8640c800 },
    { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
    { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
diff --git a/src/i965_render.c b/src/i965_render.c
index 266b461..a2b21db 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -948,44 +948,41 @@ i965_prepare_composite(int op, PicturePt
 	    	 VB0_VERTEXDATA |
 	    	 ((4 * 2 * nelem) << VB0_BUFFER_PITCH_SHIFT));
    	OUT_RING(state_base_offset + vb_offset);
-   	OUT_RING(2); // max index, prim has 4 coords
+        OUT_RING(3);
    	OUT_RING(0); // ignore for VERTEXDATA, but still there
 
 	/* Set up our vertex elements, sourced from the single vertex buffer.
 	 */
    	OUT_RING(BRW_3DSTATE_VERTEX_ELEMENTS | ((2 * nelem) - 1));
-	/* offset 0: X,Y -> {X, Y, 1.0, 1.0} */
    	OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
 	    	 VE0_VALID |
 	    	 (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
 	    	 (0 << VE0_OFFSET_SHIFT));
    	OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
 	    	 (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
-	     	 (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
-	    	 (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
+	     	 (BRW_VFCOMPONENT_NOSTORE << VE1_VFCOMPONENT_2_SHIFT) |
+	    	 (BRW_VFCOMPONENT_NOSTORE << VE1_VFCOMPONENT_3_SHIFT) |
 	    	 (0 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
-	/* offset 8: S0, T0 -> {S0, T0, 1.0, 1.0} */
-   	OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
-	    	 VE0_VALID |
-	    	 (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
-	    	 (8 << VE0_OFFSET_SHIFT));
-   	OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
-	    	 (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
-	    	 (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
-	     	 (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
-	    	 (4 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
-
    	if (pMask) {
 	    OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
 		     VE0_VALID |
 		     (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
-		     (16 << VE0_OFFSET_SHIFT));
+		     (8 << VE0_OFFSET_SHIFT));
 	    OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
 		     (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
-		     (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
-		     (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
-		     (8 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
+		     (BRW_VFCOMPONENT_NOSTORE << VE1_VFCOMPONENT_2_SHIFT) |
+		     (BRW_VFCOMPONENT_NOSTORE << VE1_VFCOMPONENT_3_SHIFT) |
+		     (2 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
    	}
+   	OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
+	    	 VE0_VALID |
+	    	 (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
+	    	 ((pMask?16:8) << VE0_OFFSET_SHIFT)); /* offset vb in bytes */
+   	OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
+	    	 (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
+	    	 (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
+	    	 (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
+	    	 (4 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); /* VUE offset in dwords */
 
    	ADVANCE_LP_RING();
     }
diff-tree 681b91924c364a1c00732f548539f2767929ba0e (from 76a4f2eea826036e2ac16b7e8c61ab946038c120)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Feb 2 17:40:34 2007 -0800

    Add subpixel offsets to fix accelerated rotated rendering on i915.
    
    This fixes the rendercheck "transformed src/mask coords 2" tests. Previously,
    the source pixels chosen would be off by one in some cases.
    
    The particular values were taken from Mesa, which uses .125 offsets (except
    apparently broken for y), but the signs are changed.  I would be happier if
    I had better justification for why this worked.

diff --git a/src/i830_render.c b/src/i830_render.c
index 9933843..96aeb3f 100644
--- a/src/i830_render.c
+++ b/src/i830_render.c
@@ -557,8 +557,8 @@ i830_composite(PixmapPtr pDst, int srcX,
 
 	OUT_RING(PRIM3D_INLINE | PRIM3D_RECTLIST | (vertex_count-1));
 
-	OUT_RING_F(dstX);
-	OUT_RING_F(dstY);
+	OUT_RING_F(-0.125 + dstX);
+	OUT_RING_F(-0.125 + dstY);
 	OUT_RING_F(src_x[0] / pI830->scale_units[0][0]);
 	OUT_RING_F(src_y[0] / pI830->scale_units[0][1]);
 	if (has_mask) {
@@ -566,8 +566,8 @@ i830_composite(PixmapPtr pDst, int srcX,
 	    OUT_RING_F(mask_y[0] / pI830->scale_units[1][1]);
 	}
 
-	OUT_RING_F(dstX);
-	OUT_RING_F(dstY + h);
+	OUT_RING_F(-0.125 + dstX);
+	OUT_RING_F(-0.125 + dstY + h);
 	OUT_RING_F(src_x[1] / pI830->scale_units[0][0]);
 	OUT_RING_F(src_y[1] / pI830->scale_units[0][1]);
 	if (has_mask) {
@@ -575,8 +575,8 @@ i830_composite(PixmapPtr pDst, int srcX,
 	    OUT_RING_F(mask_y[1] / pI830->scale_units[1][1]);
 	}
 
-	OUT_RING_F(dstX + w);
-	OUT_RING_F(dstY + h);
+	OUT_RING_F(-0.125 + dstX + w);
+	OUT_RING_F(-0.125 + dstY + h);
 	OUT_RING_F(src_x[2] / pI830->scale_units[0][0]);
 	OUT_RING_F(src_y[2] / pI830->scale_units[0][1]);
 	if (has_mask) {
diff-tree 76a4f2eea826036e2ac16b7e8c61ab946038c120 (from 1ba45a3fcd40aaf4d373447fb9f252ca053f9105)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Feb 2 17:34:41 2007 -0800

    Fix bad offsets in "right" rotation of the CRTC in cursor and update handling.

diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index 464eb6d..70a8d52 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -510,7 +510,7 @@ I830SetCursorPosition(ScrnInfoPtr pScrn,
 	    hotspoty = I810_CURSOR_Y;
 	    break;
 	case RR_Rotate_270:
-	    thisx = mode->VDisplay - (root_y - crtc->y);
+	    thisx = mode->HDisplay - (root_y - crtc->y);
 	    thisy = (root_x - crtc->x);
 	    hotspotx = I810_CURSOR_Y;
 	    break;
diff --git a/src/i830_xf86Rotate.c b/src/i830_xf86Rotate.c
index bd4d5a6..2491e7b 100644
--- a/src/i830_xf86Rotate.c
+++ b/src/i830_xf86Rotate.c
@@ -196,7 +196,7 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crt
     case RR_Rotate_270:
 	transform.matrix[0][1] = IntToxFixed(1);
 	transform.matrix[1][0] = IntToxFixed(-1);
-	transform.matrix[1][2] += IntToxFixed(crtc->mode.VDisplay);
+	transform.matrix[1][2] += IntToxFixed(crtc->mode.HDisplay);
 	break;
     }
 
diff-tree 785a59ead0e8d1d681b2cb6827ee58ad2c51f8c6 (from 1dde7a15a3a42b881c57ece95feceffadf412cff)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Feb 1 22:48:44 2007 -0800

    Rename driver from i810 to intel. Permit old name for compatibility.
    
    Driver installs as intel_drv.so with symlink to i810_drv.so to ensure
    existing configurations continue to work. Updated manual page to reflect
    name change and add attributions for recent work.

diff --git a/configure.ac b/configure.ac
index 70ae807..d45185a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -21,10 +21,10 @@
 # Process this file with autoconf to produce a configure script
 
 AC_PREREQ(2.57)
-AC_INIT([xf86-video-i810],
+AC_INIT([xf86-video-intel],
         1.7.2,
         [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
-        xf86-video-i810)
+        xf86-video-intel)
 
 AC_DEFINE_UNQUOTED([INTEL_VERSION_MAJOR],
 		   [$(echo $PACKAGE_VERSION | sed -e 's/^\([[0-9]]\)\.[[0-9]]\.[[0-9]]/\1/')],
@@ -139,7 +139,7 @@ AC_SUBST([XORG_CFLAGS])
 AC_SUBST([WARN_CFLAGS])
 AC_SUBST([moduledir])
 
-DRIVER_NAME=i810
+DRIVER_NAME=intel
 AC_SUBST([DRIVER_NAME])
 
 XORG_MANPAGE_SECTIONS
diff --git a/man/i810.man b/man/i810.man
deleted file mode 100644
index 2215c7a..0000000
--- a/man/i810.man
+++ /dev/null
@@ -1,184 +0,0 @@
-.\" $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i810.man,v 1.5 2003/10/18 02:27:07 dawes Exp $ 
-.\" shorthand for double quote that works everywhere.
-.ds q \N'34'
-.TH I810 __drivermansuffix__ __vendorversion__
-.SH NAME
-i810 \- Intel 8xx integrated graphics chipsets
-.SH SYNOPSIS
-.nf
-.B "Section \*qDevice\*q"
-.BI "  Identifier \*q"  devname \*q
-.B  "  Driver \*qi810\*q"
-\ \ ...
-.B EndSection
-.fi
-.SH DESCRIPTION
-.B i810
-is an __xservername__ driver for Intel integrated graphics chipsets.
-The driver supports depths 8, 15, 16 and 24.  All visual types are
-supported in depth 8.  For the i810/i815 other depths support the
-TrueColor and DirectColor visuals.  For the i830M and later, only the
-TrueColor visual is supported for depths greater than 8.  The driver
-supports hardware accelerated 3D via the Direct Rendering Infrastructure
-(DRI), but only in depth 16 for the i810/i815 and depths 16 and 24 for
-the 830M and later.
-.SH SUPPORTED HARDWARE
-.B i810
-supports the i810, i810-DC100, i810e, i815, i830M, 845G, 852GM, 855GM,
-865G, 915G, 915GM, 945G, 945GM, 965G, 965Q and 946GZ chipsets.
-
-.SH CONFIGURATION DETAILS
-Please refer to __xconfigfile__(__filemansuffix__) for general configuration
-details.  This section only covers configuration details specific to this
-driver.
-.PP
-The Intel 8xx and 9xx families of integrated graphics chipsets has a unified
-memory architecture and uses system memory for video ram.  For the i810 and
-i815 family of chipset, operating system support for allocating system
-memory for video use is required in order to use this driver.  For the 830M
-and later, this is required in order for the driver to use more video ram
-than has been pre-allocated at boot time by the BIOS.  This is usually
-achieved with an "agpgart" or "agp" kernel driver.  Linux, and recent
-versions of FreeBSD, OpenBSD and NetBSD have such kernel drivers available.
-.PP
-By default 8 Megabytes
-of system memory are used for graphics.  For the 830M and later, the
-default is 8 Megabytes when DRI is not enabled and 32 Megabytes with
-DRI is enabled.  This amount may be changed with the
-.B VideoRam
-entry in the config file
-.B "Device"
-section.  It may be set to any reasonable value up to 64MB for older
-chipsets or 128MB for newer chipsets.  It is advisable to check the
-__xservername__
-log file to check if any features have been disabled because of insufficient
-video memory.  In particular, DRI support or tiling mode may be disabled
-with insufficient video memory.  Either of these being disabled will
-reduce performance for 3D applications.  Note however, that increasing
-this value too much will reduce the amount of system memory available
-for other applications.
-.PP
-The driver makes use of the video BIOS to program video modes for the 830M
-and later.  This limits the video modes that can be used to those provided
-by the video BIOS, and to those that will fit into the amount of video memory
-that the video BIOS is aware of.
-.PP
-The following driver
-.B Options
-are supported
-.TP
-.BI "Option \*qNoAccel\*q \*q" boolean \*q
-Disable or enable acceleration.  Default: acceleration is enabled.
-.TP
-.BI "Option \*qSWCursor\*q \*q" boolean \*q
-Disable or enable software cursor.  Default: software cursor is disable
-and a hardware cursor is used for configurations where the hardware cursor
-is available.
-.TP
-.BI "Option \*qColorKey\*q \*q" integer \*q
-This sets the default pixel value for the YUV video overlay key.
-Default: undefined.
-.TP
-.BI "Option \*qCacheLines\*q \*q" integer \*q
-This allows the user to change the amount of graphics memory used for
-2D acceleration and video.  Decreasing this amount leaves more for 3D
-textures.  Increasing it can improve 2D performance at the expense of
-3D performance.
-.TP
-This option only takes effect when XAA acceleration is enabled.
-.TP
-Default: depends on the resolution, depth, and available video memory.  The
-driver attempts to allocate space for at 3 screenfuls of pixmaps plus an
-HD-sized XV video.  The default used for a specific configuration can be found
-by examining the __xservername__ log file.
-.TP
-.BI "Option \*qDRI\*q \*q" boolean \*q
-Disable or enable DRI support.
-Default: DRI is enabled for configurations where it is supported.
-
-.PP
-The following driver
-.B Options
-are supported for the i810 and i815 chipsets:
-.TP
-.BI "Option \*qDDC\*q \*q" boolean \*q
-Disable or enable DDC support.
-Default: enabled.
-.TP
-.BI "Option \*qDac6Bit\*q \*q" boolean \*q
-Enable or disable 6-bits per RGB for 8-bit modes.
-Default: 8-bits per RGB for 8-bit modes.
-.TP
-.BI "Option \*qXvMCSurfaces\*q \*q" integer \*q
-This option enables XvMC.  The integer parameter specifies the number of
-surfaces to use.  Valid values are 6 and 7.
-Default: XvMC is disabled.
-
-.PP
-The following driver
-.B Options
-are supported for the 830M and later chipsets:
-.TP
-.BI "Option \*qVideoKey\*q \*q" integer \*q
-This is the same as the
-.B \*qColorKey\*q
-option described above.  It is provided for compatibility with most
-other drivers.
-.TP
-.BI "Option \*qXVideo\*q \*q" boolean \*q
-Disable or enable XVideo support.
-Default: XVideo is enabled for configurations where it is supported.
-.TP
-.BI "Option \*qRotate\*q \*q90\*q"
-Rotate the desktop 90 degrees counterclockwise. Other valid options are
-0, 90, 180 and 270 degrees. The RandR extension is used for rotation 
-functionality. So this option allows the Xserver to start with a rotated
-mode of operation.
-Default: 0 degrees.
-.TP
-.BI "Option \*qLinearAlloc\*q \*q" integer \*q
-Allows more memory for the offscreen allocator. This usually helps in
-situations where HDTV movies are required to play but not enough offscreen
-memory is usually available. Set this to 8160 for upto 1920x1080 HDTV support.
-Default 0KB (off).
-.TP
-.BI "Option \*qLegacy3D\*q \*q" boolean \*q
-Enable support for the legacy i915_dri.so 3D driver.
-This will, among other things, make the 2D driver tell libGL to
-load the 3D driver i915_dri.so instead of the newer i915tex_dri.so.
-This option is only used for chipsets in the range i830-i945. 
-Default for i830-i945 series: Enabled for i915 drm versions < 1.7.0. Otherwise
-disabled. 
-Default for i810: The option is not used.
-Default for i965: The option is always true.
-.TP
-.BI "Option \*qAperTexSize\*q \*q" integer \*q
-Give the size in kiB of the AGP aperture area that is reserved for the
-DRM memory manager present in i915 drm from version 1.7.0 and upwards,
-and that is used with the 3D driver in Mesa from version 6.5.2 and
-upwards. If the size is set too high to make room for pre-allocated
-VideoRam, the driver will try to reduce it automatically. If you use only
-older Mesa or DRM versions, you may set this value to zero, and
-atctivate the legacy texture pool (see 
-.B "Option \*qLegacy3D\*q"
-). If you run 3D programs with large texture memory requirements, you might
-gain some performance by increasing this value.
-Default: 32768.
-.TP
-.BI "Option \*qAccelMethod\*q \*q" string \*q
-Choose acceleration architecture, either "XAA" or "EXA".  XAA is the old
-(but stable) XFree86 based acceleration architecture.  EXA is a newer and
-simpler acceleration architecture designed to better accelerate the X Render
-extension.  Default: "XAA".
-
-.SH "SEE ALSO"
-__xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), xorgconfig(__appmansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__)
-.SH AUTHORS
-Authors include: Keith Whitwell, and also Jonathan Bian, Matthew J Sottek,
-Jeff Hartmann, Mark Vojkovich, Alan Hourihane, H. J. Lu.  830M and 845G
-support reworked for XFree86 4.3 by David Dawes and Keith Whitwell.  852GM,
-855GM, and 865G support added by David Dawes and Keith Whitwell.  915G,
-915GM, 945G, 945GM, 965G, 965Q and 946GZ support added by Alan Hourihane and
-Keith Whitwell.  Dual Head, Clone and lid status support added by Alan
-Hourihane. Textured video support for 915G and later chips added by Keith
-Packard and Eric Anholt.
diff --git a/man/intel.man b/man/intel.man
new file mode 100644
index 0000000..b932632
--- /dev/null
+++ b/man/intel.man
@@ -0,0 +1,179 @@
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH intel  __drivermansuffix__ __vendorversion__
+.SH NAME
+intel \- Intel integrated graphics chipsets
+.SH SYNOPSIS
+.nf
+.B "Section \*qDevice\*q"
+.BI "  Identifier \*q"  devname \*q
+.B  "  Driver \*qintel\*q"
+\ \ ...
+.B EndSection
+.fi
+.SH DESCRIPTION
+.B intel
+is an __xservername__ driver for Intel integrated graphics chipsets.
+The driver supports depths 8, 15, 16 and 24.  All visual types are
+supported in depth 8.  For the i810/i815 other depths support the
+TrueColor and DirectColor visuals.  For the i830M and later, only the
+TrueColor visual is supported for depths greater than 8.  The driver
+supports hardware accelerated 3D via the Direct Rendering Infrastructure
+(DRI), but only in depth 16 for the i810/i815 and depths 16 and 24 for
+the 830M and later.
+.SH SUPPORTED HARDWARE
+.B intel
+supports the i810, i810-DC100, i810e, i815, i830M, 845G, 852GM, 855GM,
+865G, 915G, 915GM, 945G, 945GM, 965G, 965Q and 946GZ chipsets.
+
+.SH CONFIGURATION DETAILS
+Please refer to __xconfigfile__(__filemansuffix__) for general configuration
+details.  This section only covers configuration details specific to this
+driver.
+.PP
+The Intel 8xx and 9xx families of integrated graphics chipsets has a unified
+memory architecture and uses system memory for video ram.  For the i810 and
+i815 family of chipset, operating system support for allocating system
+memory for video use is required in order to use this driver.  For the 830M
+and later, this is required in order for the driver to use more video ram
+than has been pre-allocated at boot time by the BIOS.  This is usually
+achieved with an "agpgart" or "agp" kernel driver.  Linux, and recent
+versions of FreeBSD, OpenBSD and NetBSD have such kernel drivers available.
+.PP
+By default 8 Megabytes
+of system memory are used for graphics.  For the 830M and later, the
+default is 8 Megabytes when DRI is not enabled and 32 Megabytes with
+DRI is enabled.  This amount may be changed with the
+.B VideoRam
+entry in the config file
+.B "Device"
+section.  It may be set to any reasonable value up to 64MB for older
+chipsets or 128MB for newer chipsets.  It is advisable to check the
+__xservername__
+log file to check if any features have been disabled because of insufficient
+video memory.  In particular, DRI support or tiling mode may be disabled
+with insufficient video memory.  Either of these being disabled will
+reduce performance for 3D applications.  Note however, that increasing
+this value too much will reduce the amount of system memory available
+for other applications.
+.PP
+The following driver
+.B Options
+are supported
+.TP
+.BI "Option \*qNoAccel\*q \*q" boolean \*q
+Disable or enable acceleration.  Default: acceleration is enabled.
+.TP
+.BI "Option \*qSWCursor\*q \*q" boolean \*q
+Disable or enable software cursor.  Default: software cursor is disable
+and a hardware cursor is used for configurations where the hardware cursor
+is available.
+.TP
+.BI "Option \*qColorKey\*q \*q" integer \*q
+This sets the default pixel value for the YUV video overlay key.
+Default: undefined.
+.TP
+.BI "Option \*qCacheLines\*q \*q" integer \*q
+This allows the user to change the amount of graphics memory used for
+2D acceleration and video.  Decreasing this amount leaves more for 3D
+textures.  Increasing it can improve 2D performance at the expense of
+3D performance.
+.TP
+This option only takes effect when XAA acceleration is enabled.
+.TP
+Default: depends on the resolution, depth, and available video memory.  The
+driver attempts to allocate space for at 3 screenfuls of pixmaps plus an
+HD-sized XV video.  The default used for a specific configuration can be found
+by examining the __xservername__ log file.
+.TP
+.BI "Option \*qDRI\*q \*q" boolean \*q
+Disable or enable DRI support.
+Default: DRI is enabled for configurations where it is supported.
+
+.PP
+The following driver
+.B Options
+are supported for the i810 and i815 chipsets:
+.TP
+.BI "Option \*qDDC\*q \*q" boolean \*q
+Disable or enable DDC support.
+Default: enabled.
+.TP
+.BI "Option \*qDac6Bit\*q \*q" boolean \*q
+Enable or disable 6-bits per RGB for 8-bit modes.
+Default: 8-bits per RGB for 8-bit modes.
+.TP
+.BI "Option \*qXvMCSurfaces\*q \*q" integer \*q
+This option enables XvMC.  The integer parameter specifies the number of
+surfaces to use.  Valid values are 6 and 7.
+Default: XvMC is disabled.
+
+.PP
+The following driver
+.B Options
+are supported for the 830M and later chipsets:
+.TP
+.BI "Option \*qVideoKey\*q \*q" integer \*q
+This is the same as the
+.B \*qColorKey\*q
+option described above.  It is provided for compatibility with most
+other drivers.
+.TP
+.BI "Option \*qXVideo\*q \*q" boolean \*q
+Disable or enable XVideo support.
+Default: XVideo is enabled for configurations where it is supported.
+.TP
+.BI "Option \*qRotate\*q \*q90\*q"
+Rotate the desktop 90 degrees counterclockwise. Other valid options are
+0, 90, 180 and 270 degrees. The RandR extension is used for rotation 
+functionality. So this option allows the Xserver to start with a rotated
+mode of operation.
+Default: 0 degrees.
+.TP
+.BI "Option \*qLinearAlloc\*q \*q" integer \*q
+Allows more memory for the offscreen allocator. This usually helps in
+situations where HDTV movies are required to play but not enough offscreen
+memory is usually available. Set this to 8160 for upto 1920x1080 HDTV support.
+Default 0KB (off).
+.TP
+.BI "Option \*qLegacy3D\*q \*q" boolean \*q
+Enable support for the legacy i915_dri.so 3D driver.
+This will, among other things, make the 2D driver tell libGL to
+load the 3D driver i915_dri.so instead of the newer i915tex_dri.so.
+This option is only used for chipsets in the range i830-i945. 
+Default for i830-i945 series: Enabled for i915 drm versions < 1.7.0. Otherwise
+disabled. 
+Default for i810: The option is not used.
+Default for i965: The option is always true.
+.TP
+.BI "Option \*qAperTexSize\*q \*q" integer \*q
+Give the size in kiB of the AGP aperture area that is reserved for the
+DRM memory manager present in i915 drm from version 1.7.0 and upwards,
+and that is used with the 3D driver in Mesa from version 6.5.2 and
+upwards. If the size is set too high to make room for pre-allocated
+VideoRam, the driver will try to reduce it automatically. If you use only
+older Mesa or DRM versions, you may set this value to zero, and
+atctivate the legacy texture pool (see 
+.B "Option \*qLegacy3D\*q"
+). If you run 3D programs with large texture memory requirements, you might
+gain some performance by increasing this value.
+Default: 32768.
+.TP
+.BI "Option \*qAccelMethod\*q \*q" string \*q
+Choose acceleration architecture, either "XAA" or "EXA".  XAA is the old
+(but stable) XFree86 based acceleration architecture.  EXA is a newer and
+simpler acceleration architecture designed to better accelerate the X Render
+extension.  Default: "XAA".
+
+.SH "SEE ALSO"
+__xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), xorgconfig(__appmansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__)
+.SH AUTHORS
+Authors include: Keith Whitwell, and also Jonathan Bian, Matthew J Sottek,
+Jeff Hartmann, Mark Vojkovich, Alan Hourihane, H. J. Lu.  830M and 845G
+support reworked for XFree86 4.3 by David Dawes and Keith Whitwell.  852GM,
+855GM, and 865G support added by David Dawes and Keith Whitwell.  915G,
+915GM, 945G, 945GM, 965G, 965Q and 946GZ support added by Alan Hourihane and
+Keith Whitwell. Lid status support added by Alan Hourihane. Textured video
+support for 915G and later chips, RandR 1.2 and hardware modesetting added
+by Eric Anholt and Keith Packard. EXA and Render acceleration added by Wang
+Zhenyu. TV out support added by Zou Nan Hai and Keith Packard.
diff --git a/src/Makefile.am b/src/Makefile.am
index 7656e02..f824a74 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -28,11 +28,11 @@ SUBDIRS = xvmc bios_reader ch7017 ch7xxx
 AM_CFLAGS = @WARN_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@ \
 	-DI830_XV -DI830_USE_XAA -DI830_USE_EXA
 
-i810_drv_la_LTLIBRARIES = i810_drv.la
-i810_drv_la_LDFLAGS = -module -avoid-version
-i810_drv_ladir = @moduledir@/drivers
+intel_drv_la_LTLIBRARIES = intel_drv.la
+intel_drv_la_LDFLAGS = -module -avoid-version
+intel_drv_ladir = @moduledir@/drivers
 
-i810_drv_la_SOURCES = \
+intel_drv_la_SOURCES = \
          brw_defines.h \
          brw_structs.h \
 	 sf_prog.h \
@@ -112,7 +112,7 @@ exa_wm_masknoca_prog.h: exa_wm_masknoca.
 endif
 
 if DRI
-i810_drv_la_SOURCES += \
+intel_drv_la_SOURCES += \
          i810_dri.c \
          i810_dri.h \
          i830_dri.c \
@@ -123,3 +123,10 @@ endif
 EXTRA_DIST = \
 	packed_yuv_sf.g4a \
 	packed_yuv_wm.g4a
+
+install-data-local: install-intel_drv_laLTLIBRARIES
+	(cd $(DESTDIR)$(intel_drv_ladir) && rm -f i810_drv.so && ln -s intel_drv.so i810_drv.so)
+
+uninstall-local:
+	(cd $(DESTDIR)$(intel_drv_ladir) && rm -f i810_drv.so)
+	
diff --git a/src/i810.h b/src/i810.h
index 852a64a..614de52 100644
--- a/src/i810.h
+++ b/src/i810.h
@@ -62,8 +62,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "common.h"
 
 #define I810_VERSION 4000
-#define I810_NAME "I810"
-#define I810_DRIVER_NAME "i810"
+#define I810_NAME "intel"
+#define I810_DRIVER_NAME "intel"
+#define I810_LEGACY_DRIVER_NAME "i810"
 
 /* HWMC Surfaces */
 #define I810_MAX_SURFACES 7
diff --git a/src/i810_driver.c b/src/i810_driver.c
index e7c8507..04166b7 100644
--- a/src/i810_driver.c
+++ b/src/i810_driver.c
@@ -384,6 +384,21 @@ int I830EntityIndex = -1;
 
 static MODULESETUPPROTO(i810Setup);
 
+static XF86ModuleVersionInfo intelVersRec = {
+   "intel",
+   MODULEVENDORSTRING,
+   MODINFOSTRING1,
+   MODINFOSTRING2,
+   XORG_VERSION_CURRENT,
+   INTEL_VERSION_MAJOR, INTEL_VERSION_MINOR, INTEL_VERSION_PATCH,
+   ABI_CLASS_VIDEODRV,
+   ABI_VIDEODRV_VERSION,
+   MOD_CLASS_VIDEODRV,
+   {0, 0, 0, 0}
+};
+
+_X_EXPORT XF86ModuleData intelModuleData = { &intelVersRec, i810Setup, NULL };
+
 static XF86ModuleVersionInfo i810VersRec = {
    "i810",
    MODULEVENDORSTRING,
@@ -521,7 +536,9 @@ I810Probe(DriverPtr drv, int flags)
     * driver, and return if there are none.
     */
    if ((numDevSections =
-	xf86MatchDevice(I810_DRIVER_NAME, &devSections)) <= 0) {
+	xf86MatchDevice(I810_DRIVER_NAME, &devSections)) <= 0 &&
+       (numDevSections =
+	xf86MatchDevice(I810_LEGACY_DRIVER_NAME, &devSections)) <= 0) {
       return FALSE;
    }
 
diff-tree 1dde7a15a3a42b881c57ece95feceffadf412cff (from parents)
Merge: 16f30b2e6c72e228c66946ff9efadd7278379745 1ba45a3fcd40aaf4d373447fb9f252ca053f9105
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Feb 1 21:31:27 2007 -0800

    Merge branch 'modesetting-origin' into modesetting

diff-tree 16f30b2e6c72e228c66946ff9efadd7278379745 (from 9f0acf1eb01ad8320f4da4cc5e498af25c0ecc5e)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Feb 1 21:30:19 2007 -0800

    Add "Ignore" option to per-output monitor, removes output from server.
    
    Setting option "Ignore" "Yes" will cause the server to pretend as if the
    specified output does not exist at all. It will not be listed by the
    RandR1.2 extension, and the server will not attempt to detect monitors at
    startup time.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index ea62ad9..46a35f1 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -1079,8 +1079,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
     char		    *name_prefix;
     char		    *name_suffix;
 
-    output = xf86OutputCreate (pScrn, &i830_sdvo_output_funcs,
-			       "ADD2 PCIE card");
+    output = xf86OutputCreate (pScrn, &i830_sdvo_output_funcs,NULL);
     if (!output)
 	return;
     intel_output = xnfcalloc (sizeof (I830OutputPrivateRec) +
diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index a209914..0ea0ced 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -273,6 +273,7 @@ typedef enum {
     OPTION_DISABLE,
     OPTION_MIN_CLOCK,
     OPTION_MAX_CLOCK,
+    OPTION_IGNORE,
 } OutputOpts;
 
 static OptionInfoRec xf86OutputOptions[] = {
@@ -286,6 +287,7 @@ static OptionInfoRec xf86OutputOptions[]
     {OPTION_DISABLE,	    "Disable",		OPTV_BOOLEAN, {0}, FALSE },
     {OPTION_MIN_CLOCK,	    "MinClock",		OPTV_FREQ,    {0}, FALSE },
     {OPTION_MAX_CLOCK,	    "MaxClock",		OPTV_FREQ,    {0}, FALSE },
+    {OPTION_IGNORE,	    "Ignore",		OPTV_BOOLEAN, {0}, FALSE },
     {-1,		    NULL,		OPTV_NONE,    {0}, FALSE },
 };
 
@@ -296,6 +298,9 @@ xf86OutputSetMonitor (xf86OutputPtr outp
     static const char monitor_prefix[] = "monitor-";
     char    *monitor;
 
+    if (!output->name)
+	return;
+
     if (output->options)
 	xfree (output->options);
 
@@ -332,6 +337,12 @@ xf86OutputEnabled (xf86OutputPtr    outp
     return TRUE;
 }
 
+static Bool
+xf86OutputIgnored (xf86OutputPtr    output)
+{
+    return xf86ReturnOptValBool (output->options, OPTION_IGNORE, FALSE);
+}
+
 xf86OutputPtr
 xf86OutputCreate (ScrnInfoPtr		    scrn,
 		  const xf86OutputFuncsRec *funcs,
@@ -339,20 +350,37 @@ xf86OutputCreate (ScrnInfoPtr		    scrn,
 {
     xf86OutputPtr	output, *outputs;
     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
-    int			len = strlen (name);
+    int			len;
+
+    if (name)
+	len = strlen (name) + 1;
+    else
+	len = 0;
 
-    output = xcalloc (sizeof (xf86OutputRec) + len + 1, 1);
+    output = xcalloc (sizeof (xf86OutputRec) + len, 1);
     if (!output)
 	return NULL;
     output->scrn = scrn;
     output->funcs = funcs;
-    output->name = (char *) (output + 1);
+    if (name)
+    {
+	output->name = (char *) (output + 1);
+	strcpy (output->name, name);
+    }
     output->subpixel_order = SubPixelUnknown;
-    strcpy (output->name, name);
 #ifdef RANDR_12_INTERFACE
     output->randr_output = NULL;
 #endif
-    xf86OutputSetMonitor (output);
+    if (name)
+    {
+	xf86OutputSetMonitor (output);
+	if (xf86OutputIgnored (output))
+	{
+	    xfree (output);
+	    return FALSE;
+	}
+    }
+    
     
     if (xf86_config->output)
 	outputs = xrealloc (xf86_config->output,
@@ -374,17 +402,19 @@ xf86OutputCreate (ScrnInfoPtr		    scrn,
 Bool
 xf86OutputRename (xf86OutputPtr output, const char *name)
 {
-    int	    len = strlen(name);
-    char    *newname = xalloc (len + 1);
+    int	    len = strlen(name) + 1;
+    char    *newname = xalloc (len);
     
     if (!newname)
 	return FALSE;	/* so sorry... */
     
     strcpy (newname, name);
-    if (output->name != (char *) (output + 1))
+    if (output->name && output->name != (char *) (output + 1))
 	xfree (output->name);
     output->name = newname;
     xf86OutputSetMonitor (output);
+    if (xf86OutputIgnored (output))
+	return FALSE;
     return TRUE;
 }
 
@@ -407,7 +437,7 @@ xf86OutputDestroy (xf86OutputPtr output)
 	    xf86_config->num_output--;
 	    break;
 	}
-    if (output->name != (char *) (output + 1))
+    if (output->name && output->name != (char *) (output + 1))
 	xfree (output->name);
     xfree (output);
 }
diff-tree 9f0acf1eb01ad8320f4da4cc5e498af25c0ecc5e (from d6bc03c379c46842676f640b8edb13ea828bf20c)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Feb 1 15:44:18 2007 -0800

    Check for rotation change in xf86RandR12CrtcSet.
    
    xf86RandRCrtcSet was ignoring changes to only rotation, so the screen would
    be left incorrectly rotated.

diff --git a/src/i830_randr.c b/src/i830_randr.c
index 5eccf4b..811fc50 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -608,6 +608,9 @@ xf86RandR12CrtcSet (ScreenPtr	pScreen,
     else if (mode && !xf86ModesEqual (&crtc->mode, mode))
 	changed = TRUE;
     
+    if (rotation != crtc->rotation)
+	changed = TRUE;
+
     if (x != crtc->x || y != crtc->y)
 	changed = TRUE;
     for (o = 0; o < config->num_output; o++) 
diff-tree 1ba45a3fcd40aaf4d373447fb9f252ca053f9105 (from 9bfeadbd5b37acb56cb646009239a94727ec52bc)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Feb 1 13:26:38 2007 -0800

    Improve register debugging output.
    
    This includes not reporting some fields on hardware where those bits are
    reserved, correcting one of the hardware error bit numbers, and reducing
    the severity of the debugging output warnings.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index 33b059d..68cce93 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -401,7 +401,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 # define ERR_VERTEX_MAX				(1 << 5) /* lpt/cst */
 # define ERR_PGTBL_ERROR			(1 << 4)
 # define ERR_DISPLAY_OVERLAY_UNDERRUN		(1 << 3)
-# define ERR_MAIN_MEMORY_REFRESH		(1 << 2)
+# define ERR_MAIN_MEMORY_REFRESH		(1 << 1)
 # define ERR_INSTRUCTION_ERROR			(1 << 0)
 
 
diff --git a/src/i830_debug.c b/src/i830_debug.c
index 897ab92..e0be0a4 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -462,7 +462,7 @@ void i830DumpRegs (ScrnInfoPtr pScrn)
 	    break;
 	default:
 	    p2 = 1;
-	    xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "p2 out of range\n");
+	    xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "p2 out of range\n");
 	    break;
 	}
 	switch ((dpll >> 16) & 0xff) {
@@ -484,33 +484,39 @@ void i830DumpRegs (ScrnInfoPtr pScrn)
 	    p1 = 8; break;
 	default:
 	    p1 = 1;
-	    xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "p1 out of range\n");
+	    xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "p1 out of range\n");
 	    break;
 	}
 	switch ((dpll >> 13) & 0x3) {
 	case 0:
 	    ref = 96000;
 	    break;
+	case 3:
+	    ref = 100000;
+	    break;
 	default:
 	    ref = 0;
-	    xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "ref out of range\n");
+	    xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "ref out of range\n");
 	    break;
 	}
-	phase = (dpll >> 9) & 0xf;
-	switch (phase) {
-	case 6:
-	    break;
-	default:
-	    xf86DrvMsg (pScrn->scrnIndex, X_INFO,
-			"SDVO phase shift %d out of range -- probobly not "
-			"an issue.\n", phase);
-	    break;
+	if (IS_I965G(pI830)) {
+	    phase = (dpll >> 9) & 0xf;
+	    switch (phase) {
+	    case 6:
+		break;
+	    default:
+		xf86DrvMsg (pScrn->scrnIndex, X_INFO,
+			    "SDVO phase shift %d out of range -- probobly not "
+			    "an issue.\n", phase);
+		break;
+	    }
 	}
 	switch ((dpll >> 8) & 1) {
 	case 0:
 	    break;
 	default:
-	    xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "fp select out of range\n");
+	    xf86DrvMsg (pScrn->scrnIndex, X_WARNING,
+			"fp select out of range\n");
 	    break;
 	}
 	n = ((fp >> 16) & 0x3f);
@@ -645,13 +651,18 @@ i830_check_error_state(ScrnInfoPtr pScrn
 
     temp = INREG16(ESR);
     if (temp != 0) {
+	Bool vertex_max = !IS_I965G(pI830) && (temp & ERR_VERTEX_MAX);
+	Bool pgtbl = temp & ERR_PGTBL_ERROR;
+	Bool underrun = !IS_I965G(pI830) &&
+	    (temp & ERR_DISPLAY_OVERLAY_UNDERRUN);
+	Bool instruction = !IS_I965G(pI830) && (temp & ERR_INSTRUCTION_ERROR);
+
 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		   "ESR is 0x%08lx%s%s%s%s\n", temp,
-		   temp & ERR_VERTEX_MAX ? ", max vertices exceeded" : "",
-		   temp & ERR_PGTBL_ERROR ? ", page table error" : "",
-		   temp & ERR_DISPLAY_OVERLAY_UNDERRUN ?
-		   ", display/overlay underrun" : "",
-		   temp & ERR_INSTRUCTION_ERROR ? ", instruction error" : "");
+		   vertex_max ? ", max vertices exceeded" : "",
+		   pgtbl ? ", page table error" : "",
+		   underrun ? ", display/overlay underrun" : "",
+		   instruction ? ", instruction error" : "");
 	errors++;
     }
     /* Check first for page table errors */
@@ -665,7 +676,7 @@ i830_check_error_state(ScrnInfoPtr pScrn
     } else {
 	temp = INREG(PGTBL_ER);
 	if (temp != 0) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		       "PGTBL_ER is 0x%08lx"
 		       "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", temp,
 		       temp & PGTBL_ERR_HOST_GTT_PTE ? ", host gtt pte" : "",
diff --git a/src/i830_driver.c b/src/i830_driver.c
index cbba437..0f66311 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3042,8 +3042,8 @@ I830EnterVT(int scrnIndex, int flags)
          return FALSE;
 
    if (i830_check_error_state(pScrn)) {
-      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		 "Existing errors found in hardware state\n");
+      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		 "Existing errors found in hardware state.\n");
    }
 
    ResetState(pScrn, FALSE);
diff-tree 9bfeadbd5b37acb56cb646009239a94727ec52bc (from d6bc03c379c46842676f640b8edb13ea828bf20c)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Feb 1 12:04:58 2007 -0800

    Remove some more dead options.

diff --git a/man/i810.man b/man/i810.man
index d1ee2da..2215c7a 100644
--- a/man/i810.man
+++ b/man/i810.man
@@ -129,51 +129,6 @@ other drivers.
 Disable or enable XVideo support.
 Default: XVideo is enabled for configurations where it is supported.
 .TP
-.BI "Option \*qMonitorLayout\*q \*q" anystr \*q
-Allow different monitor configurations. e.g. \*qCRT,LFP\*q will 
-configure a CRT on Pipe A and an LFP on Pipe B. Regardless of the 
-primary heads' pipe it is always configured as \*q<PIPEA>,<PIPEB>\*q. 
-Additionally you can add different configurations such as 
-\*qCRT+DFP,LFP\*q which would put a digital flat panel and a CRT 
-on pipe A, and a local flat panel on pipe B.
-For single pipe configurations you can just specify the monitors types
-on Pipe A, such as \*qCRT+DFP\*q which will enable the CRT and DFP
-on Pipe A.
-Valid monitors are CRT, LFP, DFP, TV, CRT2, LFP2, DFP2, TV2 and NONE.
-NOTE: Some configurations of monitor types may fail, this depends on
-the Video BIOS and system configuration.
-Default: Not configured, and will use the current head's pipe and monitor.
-.TP
-.BI "Option \*qClone\*q \*q" boolean \*q
-Enable Clone mode on pipe B. This will setup the second head as a complete
-mirror of the monitor attached to pipe A. 
-NOTE: Video overlay functions will not work on the second head in this mode.
-If you require this, then use the MonitorLayout above and do (as an example)
-\*qCRT+DFP,NONE\*q to configure both a CRT and DFP on Pipe A to achieve
-local mirroring and disable the use of this option.
-Default: Clone mode on pipe B is disabled.
-.TP
-.BI "Option \*qCloneRefresh\*q \*q" integer \*q
-When the Clone option is specified we can drive the second monitor at a
-different refresh rate than the primary. 
-Default: 60Hz.
-.TP
-.BI "Option \*qCheckLid\*q \*q" boolean \*q
-On mobile platforms it's desirable to monitor the lid status and switch
-the outputs accordingly when the lid is opened or closed. By default this
-option is on, but may incur a very minor performance penalty as we need
-to poll a register on the card to check for this activity. It can be
-turned off using this option. This only works with the 830M, 852GM and 855GM
-systems.
-Default: enabled.
-.TP
-.BI "Option \*qFlipPrimary\*q \*q" boolean \*q
-When using a dual pipe system, it may be preferable to switch the primary
-screen to the alternate pipe to display on the other monitor connection.
-NOTE: Using this option may cause text mode to be restored incorrectly,
-and thus should be used with caution.
-Default: disabled.
-.TP
 .BI "Option \*qRotate\*q \*q90\*q"
 Rotate the desktop 90 degrees counterclockwise. Other valid options are
 0, 90, 180 and 270 degrees. The RandR extension is used for rotation 
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 7c365db..cbba437 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -270,12 +270,7 @@ typedef enum {
    OPTION_XVIDEO,
    OPTION_VIDEO_KEY,
    OPTION_COLOR_KEY,
-   OPTION_VBE_RESTORE,
-   OPTION_DISPLAY_INFO,
-   OPTION_DEVICE_PRESENCE,
-   OPTION_MONITOR_LAYOUT,
    OPTION_CHECKDEVICES,
-   OPTION_FIXEDPIPE,
    OPTION_LINEARALLOC,
    OPTION_INTELTEXPOOL,
    OPTION_INTELMMSIZE
@@ -293,9 +288,7 @@ static OptionInfoRec I830Options[] = {
    {OPTION_XVIDEO,	"XVideo",	OPTV_BOOLEAN,	{0},	TRUE},
    {OPTION_COLOR_KEY,	"ColorKey",	OPTV_INTEGER,	{0},	FALSE},
    {OPTION_VIDEO_KEY,	"VideoKey",	OPTV_INTEGER,	{0},	FALSE},
-   {OPTION_MONITOR_LAYOUT, "MonitorLayout", OPTV_ANYSTR,{0},	FALSE},
    {OPTION_CHECKDEVICES, "CheckDevices",OPTV_BOOLEAN,	{0},	FALSE},
-   {OPTION_FIXEDPIPE,   "FixedPipe",    OPTV_ANYSTR, 	{0},	FALSE},
    {OPTION_LINEARALLOC, "LinearAlloc",  OPTV_INTEGER,   {0},    FALSE},
    {OPTION_INTELTEXPOOL,"Legacy3D",     OPTV_BOOLEAN,	{0},	FALSE},
    {OPTION_INTELMMSIZE, "AperTexSize",  OPTV_INTEGER,	{0},	FALSE},
diff-tree d6bc03c379c46842676f640b8edb13ea828bf20c (from 351866b0328b1d7afdc6b414c77d9ab4da4bd085)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Feb 1 11:28:34 2007 -0800

    Bug #9819: Add two headers that are apparently necessary on older X Servers.

diff --git a/src/i830_xf86Rotate.c b/src/i830_xf86Rotate.c
index 3b8be61..bd4d5a6 100644
--- a/src/i830_xf86Rotate.c
+++ b/src/i830_xf86Rotate.c
@@ -30,7 +30,8 @@
 
 #include "xf86.h"
 #include "xf86DDC.h"
-/*#include "i830.h" */
+#include "fb.h"
+#include "windowstr.h"
 #include "i830_xf86Crtc.h"
 #include "i830_xf86Modes.h"
 #include "i830_randr.h"
diff-tree 351866b0328b1d7afdc6b414c77d9ab4da4bd085 (from 96783a458957ca280ebb6275fa692dd415df6931)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Jan 31 15:48:52 2007 -0800

    Sync before overwriting Render acceleration state on the 965.

diff --git a/src/i965_render.c b/src/i965_render.c
index 5ff174d..266b461 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -552,10 +552,10 @@ i965_prepare_composite(int op, PicturePt
     urb_cs_start = urb_sf_start + urb_sf_size;
     urb_cs_size = URB_CS_ENTRIES * URB_CS_ENTRY_SIZE;
 
-    /* We'll be poking the state buffers that could be in use by the 3d
-     * hardware here, but we should have synced the 3D engine already in
-     * I830PutImage. XXX
+    /* Because we only have a single static buffer for our state currently,
+     * we have to sync before updating it every time.
      */
+    i830WaitSync(pScrn);
 
     memset (cc_viewport, 0, sizeof (*cc_viewport));
     cc_viewport->min_depth = -1.e35;
diff-tree 96783a458957ca280ebb6275fa692dd415df6931 (from 5238ff9c80718f9f8baa06123aa1bb6e3193fce6)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Jan 31 15:48:02 2007 -0800

    Fix copy-and-paste-o in the render code cleanup that broke XAA.

diff --git a/src/i830_xaa.c b/src/i830_xaa.c
index dbe1521..5ef5d3c 100644
--- a/src/i830_xaa.c
+++ b/src/i830_xaa.c
@@ -243,22 +243,22 @@ I830XAAInit(ScreenPtr pScreen)
 	if (IS_I865G(pI830) || IS_I855(pI830) ||
 	    IS_845G(pI830) || IS_I830(pI830))
 	{
-	    pI830->EXADriverPtr->CheckComposite = i830_check_composite;
-	    pI830->EXADriverPtr->PrepareComposite = i830_prepare_composite;
-	    pI830->EXADriverPtr->Composite = i830_composite;
-	    pI830->EXADriverPtr->DoneComposite = i830_done_composite;
+	    pI830->xaa_check_composite = i830_check_composite;
+	    pI830->xaa_prepare_composite = i830_prepare_composite;
+	    pI830->xaa_composite = i830_composite;
+	    pI830->xaa_done_composite = i830_done_composite;
 	} else if (IS_I915G(pI830) || IS_I915GM(pI830) ||
 		   IS_I945G(pI830) || IS_I945GM(pI830))
 	{
-	    pI830->EXADriverPtr->CheckComposite = i915_check_composite;
-	    pI830->EXADriverPtr->PrepareComposite = i915_prepare_composite;
-	    pI830->EXADriverPtr->Composite = i830_composite;
-	    pI830->EXADriverPtr->DoneComposite = i830_done_composite;
+	    pI830->xaa_check_composite = i915_check_composite;
+	    pI830->xaa_prepare_composite = i915_prepare_composite;
+	    pI830->xaa_composite = i830_composite;
+	    pI830->xaa_done_composite = i830_done_composite;
 	} else {
-	    pI830->EXADriverPtr->CheckComposite = i965_check_composite;
-	    pI830->EXADriverPtr->PrepareComposite = i965_prepare_composite;
-	    pI830->EXADriverPtr->Composite = i965_composite;
-	    pI830->EXADriverPtr->DoneComposite = i830_done_composite;
+	    pI830->xaa_check_composite = i965_check_composite;
+	    pI830->xaa_prepare_composite = i965_prepare_composite;
+	    pI830->xaa_composite = i965_composite;
+	    pI830->xaa_done_composite = i830_done_composite;
 	}
 
 	pI830->saved_composite = ps->Composite;
diff-tree 5238ff9c80718f9f8baa06123aa1bb6e3193fce6 (from c47210d94ed17ad9e8e489a1e1886732e6dc7220)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Jan 31 14:01:41 2007 -0800

    Naming and formatting cleanup in Render acceleration code.

diff --git a/src/i830.h b/src/i830.h
index 4996cdd..42933f9 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -639,30 +639,29 @@ DisplayModePtr i830_ddc_get_modes(xf86Ou
 /* i830_tv.c */
 void i830_tv_init(ScrnInfoPtr pScrn);
 
-extern Bool I830EXACheckComposite(int, PicturePtr, PicturePtr, PicturePtr);
-extern Bool I830EXAPrepareComposite(int, PicturePtr, PicturePtr, PicturePtr, 
-				PixmapPtr, PixmapPtr, PixmapPtr);
-extern Bool I915EXACheckComposite(int, PicturePtr, PicturePtr, PicturePtr);
-extern Bool I915EXAPrepareComposite(int, PicturePtr, PicturePtr, PicturePtr, 
-				PixmapPtr, PixmapPtr, PixmapPtr);
-
-extern Bool I965EXACheckComposite(int, PicturePtr, PicturePtr, PicturePtr);
-extern Bool I965EXAPrepareComposite(int, PicturePtr, PicturePtr, PicturePtr, 
-				PixmapPtr, PixmapPtr, PixmapPtr);
-extern void I965EXAComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, 
-			int maskY, int dstX, int dstY, int width, int height);
-void IntelEXAComposite(PixmapPtr pDst, int srcX, int srcY,
-		       int maskX, int maskY, int dstX, int dstY, int w, int h);
-void IntelEXADoneComposite(PixmapPtr pDst);
-
-extern Bool
-I830EXACheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
-		      PicturePtr pDstPicture);
-
-extern Bool
-I830EXAPrepareComposite(int op, PicturePtr pSrcPicture,
-			PicturePtr pMaskPicture, PicturePtr pDstPicture,
-			PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst);
+/* i830_render.c */
+Bool i830_check_composite(int op, PicturePtr pSrc, PicturePtr pMask,
+			  PicturePtr pDst);
+Bool i830_prepare_composite(int op, PicturePtr pSrc, PicturePtr pMask,
+			    PicturePtr pDst, PixmapPtr pSrcPixmap,
+			    PixmapPtr pMaskPixmap, PixmapPtr pDstPixmap);
+void i830_composite(PixmapPtr pDst, int srcX, int srcY,
+		    int maskX, int maskY, int dstX, int dstY, int w, int h);
+void i830_done_composite(PixmapPtr pDst);
+/* i915_render.c */
+Bool i915_check_composite(int op, PicturePtr pSrc, PicturePtr pMask,
+			  PicturePtr pDst);
+Bool i915_prepare_composite(int op, PicturePtr pSrc, PicturePtr pMask,
+			    PicturePtr pDst, PixmapPtr pSrcPixmap,
+			    PixmapPtr pMaskPixmap, PixmapPtr pDstPixmap);
+/* i965_render.c */
+Bool i965_check_composite(int op, PicturePtr pSrc, PicturePtr pMask,
+			  PicturePtr pDst);
+Bool i965_prepare_composite(int op, PicturePtr pSrc, PicturePtr pMask,
+			    PicturePtr pDst, PixmapPtr pSrcPixmap,
+			    PixmapPtr pMaskPixmap, PixmapPtr pDstPixmap);
+void i965_composite(PixmapPtr pDst, int srcX, int srcY,
+		    int maskX, int maskY, int dstX, int dstY, int w, int h);
 
 void
 i830_get_transformed_coordinates(int x, int y, PictTransformPtr transform,
diff --git a/src/i830_exa.c b/src/i830_exa.c
index 8a1577a..97b4a98 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -398,23 +398,25 @@ I830EXAInit(ScreenPtr pScreen)
     pI830->EXADriverPtr->DoneCopy = I830EXADoneCopy;
 
     /* Composite */
-    if (IS_I915G(pI830) || IS_I915GM(pI830) || 
-	IS_I945G(pI830) || IS_I945GM(pI830)) {   		
-	pI830->EXADriverPtr->CheckComposite = I915EXACheckComposite;
-   	pI830->EXADriverPtr->PrepareComposite = I915EXAPrepareComposite;
-    	pI830->EXADriverPtr->Composite = IntelEXAComposite;
-    	pI830->EXADriverPtr->DoneComposite = IntelEXADoneComposite;
-    } else if (IS_I865G(pI830) || IS_I855(pI830) || 
-	IS_845G(pI830) || IS_I830(pI830)) { 
-    	pI830->EXADriverPtr->CheckComposite = I830EXACheckComposite;
-    	pI830->EXADriverPtr->PrepareComposite = I830EXAPrepareComposite;
-    	pI830->EXADriverPtr->Composite = IntelEXAComposite;
-    	pI830->EXADriverPtr->DoneComposite = IntelEXADoneComposite;
-    } else if (IS_I965G(pI830)) {
- 	pI830->EXADriverPtr->CheckComposite = I965EXACheckComposite;
- 	pI830->EXADriverPtr->PrepareComposite = I965EXAPrepareComposite;
- 	pI830->EXADriverPtr->Composite = I965EXAComposite;
- 	pI830->EXADriverPtr->DoneComposite = IntelEXADoneComposite;
+    if (IS_I865G(pI830) || IS_I855(pI830) ||
+	       IS_845G(pI830) || IS_I830(pI830))
+    {
+    	pI830->EXADriverPtr->CheckComposite = i830_check_composite;
+    	pI830->EXADriverPtr->PrepareComposite = i830_prepare_composite;
+    	pI830->EXADriverPtr->Composite = i830_composite;
+    	pI830->EXADriverPtr->DoneComposite = i830_done_composite;
+    } else if (IS_I915G(pI830) || IS_I915GM(pI830) ||
+	       IS_I945G(pI830) || IS_I945GM(pI830))
+    {
+	pI830->EXADriverPtr->CheckComposite = i915_check_composite;
+   	pI830->EXADriverPtr->PrepareComposite = i915_prepare_composite;
+    	pI830->EXADriverPtr->Composite = i830_composite;
+    	pI830->EXADriverPtr->DoneComposite = i830_done_composite;
+    } else {
+ 	pI830->EXADriverPtr->CheckComposite = i965_check_composite;
+ 	pI830->EXADriverPtr->PrepareComposite = i965_prepare_composite;
+ 	pI830->EXADriverPtr->Composite = i965_composite;
+ 	pI830->EXADriverPtr->DoneComposite = i830_done_composite;
     }
 
     if(!exaDriverInit(pScreen, pI830->EXADriverPtr)) {
diff --git a/src/i830_render.c b/src/i830_render.c
index c335f6d..9933843 100644
--- a/src/i830_render.c
+++ b/src/i830_render.c
@@ -48,7 +48,7 @@ do {							\
 #define I830FALLBACK(s, arg...) 			\
 do { 							\
 	return FALSE;					\
-} while(0) 
+} while(0)
 #endif
 
 struct blendinfo {
@@ -112,7 +112,7 @@ struct formatinfo {
 #define TB0A_ARG1_SEL_TEXEL2		(8 << 6)
 #define TB0A_ARG1_SEL_TEXEL3		(9 << 6)
 
-static struct blendinfo I830BlendOp[] = { 
+static struct blendinfo i830_blend_op[] = {
     /* Clear */
     {0, 0, BLENDFACTOR_ZERO, 		BLENDFACTOR_ZERO},
     /* Src */
@@ -141,21 +141,20 @@ static struct blendinfo I830BlendOp[] = 
     {0, 0, BLENDFACTOR_ONE, 		BLENDFACTOR_ONE},
 };
 
-
-static struct formatinfo I830TexFormats[] = {
-        {PICT_a8r8g8b8, MT_32BIT_ARGB8888 },
-        {PICT_x8r8g8b8, MT_32BIT_ARGB8888 },
-        {PICT_a8b8g8r8, MT_32BIT_ABGR8888 },
-        {PICT_x8b8g8r8, MT_32BIT_ABGR8888 },
-        {PICT_r5g6b5,   MT_16BIT_RGB565	  },
-        {PICT_a1r5g5b5, MT_16BIT_ARGB1555 },
-        {PICT_x1r5g5b5, MT_16BIT_ARGB1555 },
-        {PICT_a8,       MT_8BIT_I8       },
+static struct formatinfo i830_tex_formats[] = {
+    {PICT_a8r8g8b8, MT_32BIT_ARGB8888 },
+    {PICT_x8r8g8b8, MT_32BIT_ARGB8888 },
+    {PICT_a8b8g8r8, MT_32BIT_ABGR8888 },
+    {PICT_x8b8g8r8, MT_32BIT_ABGR8888 },
+    {PICT_r5g6b5,   MT_16BIT_RGB565	  },
+    {PICT_a1r5g5b5, MT_16BIT_ARGB1555 },
+    {PICT_x1r5g5b5, MT_16BIT_ARGB1555 },
+    {PICT_a8,       MT_8BIT_I8       },
 };
 
-static Bool I830GetDestFormat(PicturePtr pDstPicture, CARD32 *dst_format)
+static Bool i830_get_dest_format(PicturePtr pDstPicture, CARD32 *dst_format)
 {
-	/* XXX: color buffer format for i830 */
+    /* XXX: color buffer format for i830 */
     switch (pDstPicture->format) {
     case PICT_a8r8g8b8:
     case PICT_x8r8g8b8:
@@ -177,35 +176,35 @@ static Bool I830GetDestFormat(PicturePtr
 	break;
     default:
         I830FALLBACK("Unsupported dest format 0x%x\n",
-                        (int)pDstPicture->format);
+		     (int)pDstPicture->format);
     }
 
     return TRUE;
 }
 
 
-static CARD32 I830GetBlendCntl(int op, PicturePtr pMask, CARD32 dst_format)
+static CARD32 i830_get_blend_cntl(int op, PicturePtr pMask, CARD32 dst_format)
 {
     CARD32 sblend, dblend;
 
-    sblend = I830BlendOp[op].src_blend;
-    dblend = I830BlendOp[op].dst_blend;
+    sblend = i830_blend_op[op].src_blend;
+    dblend = i830_blend_op[op].dst_blend;
 
     /* If there's no dst alpha channel, adjust the blend op so that we'll treat
      * it as always 1.
      */
-    if (PICT_FORMAT_A(dst_format) == 0 && I830BlendOp[op].dst_alpha) {
+    if (PICT_FORMAT_A(dst_format) == 0 && i830_blend_op[op].dst_alpha) {
         if (sblend == BLENDFACTOR_DST_ALPHA)
             sblend = BLENDFACTOR_ONE;
         else if (sblend == BLENDFACTOR_INV_DST_ALPHA)
             sblend = BLENDFACTOR_ZERO;
     }
 
-    /* If the source alpha is being used, then we should only be in a case where
-     * the source blend factor is 0, and the source blend value is the mask
-     * channels multiplied by the source picture's alpha.
+    /* If the source alpha is being used, then we should only be in a case
+     * where the source blend factor is 0, and the source blend value is the
+     * mask channels multiplied by the source picture's alpha.
      */
-    if (pMask && pMask->componentAlpha && I830BlendOp[op].src_alpha) {
+    if (pMask && pMask->componentAlpha && i830_blend_op[op].src_alpha) {
         if (dblend == BLENDFACTOR_SRC_ALPHA) {
             dblend = BLENDFACTOR_SRC_COLR;
         } else if (dblend == BLENDFACTOR_INV_SRC_ALPHA) {
@@ -213,27 +212,28 @@ static CARD32 I830GetBlendCntl(int op, P
         }
     }
 
-    return (sblend << S8_SRC_BLEND_FACTOR_SHIFT) | 
-		(dblend << S8_DST_BLEND_FACTOR_SHIFT);
+    return (sblend << S8_SRC_BLEND_FACTOR_SHIFT) |
+	(dblend << S8_DST_BLEND_FACTOR_SHIFT);
 }
 
-static Bool I830CheckCompositeTexture(PicturePtr pPict, int unit)
+static Bool i830_check_composite_texture(PicturePtr pPict, int unit)
 {
     int w = pPict->pDrawable->width;
     int h = pPict->pDrawable->height;
     int i;
-                                                                                                                                                            
+
     if ((w > 0x7ff) || (h > 0x7ff))
         I830FALLBACK("Picture w/h too large (%dx%d)\n", w, h);
 
-    for (i = 0; i < sizeof(I830TexFormats) / sizeof(I830TexFormats[0]); i++)
+    for (i = 0; i < sizeof(i830_tex_formats) / sizeof(i830_tex_formats[0]);
+	 i++)
     {
-        if (I830TexFormats[i].fmt == pPict->format)
+        if (i830_tex_formats[i].fmt == pPict->format)
             break;
     }
-    if (i == sizeof(I830TexFormats) / sizeof(I830TexFormats[0]))
+    if (i == sizeof(i830_tex_formats) / sizeof(i830_tex_formats[0]))
         I830FALLBACK("Unsupported picture format 0x%x\n",
-                         (int)pPict->format);
+		     (int)pPict->format);
 
     /* FIXME: fix repeat support */
     if (pPict->repeat)
@@ -241,20 +241,22 @@ static Bool I830CheckCompositeTexture(Pi
 
     if (pPict->filter != PictFilterNearest &&
         pPict->filter != PictFilterBilinear)
+    {
         I830FALLBACK("Unsupported filter 0x%x\n", pPict->filter);
+    }
 
     return TRUE;
 }
 
 static Bool
-I830TextureSetup(PicturePtr pPict, PixmapPtr pPix, int unit)
+i830_texture_setup(PicturePtr pPict, PixmapPtr pPix, int unit)
 {
 
     ScrnInfoPtr pScrn = xf86Screens[pPict->pDrawable->pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
     CARD32 format, offset, pitch, filter;
     int w, h, i;
-    CARD32 wrap_mode = TEXCOORDMODE_CLAMP; 
+    CARD32 wrap_mode = TEXCOORDMODE_CLAMP;
 
     offset = intel_get_pixmap_offset(pPix);
     pitch = intel_get_pixmap_pitch(pPix);
@@ -263,25 +265,27 @@ I830TextureSetup(PicturePtr pPict, Pixma
     pI830->scale_units[unit][0] = pPix->drawable.width;
     pI830->scale_units[unit][1] = pPix->drawable.height;
 
-    for (i = 0; i < sizeof(I830TexFormats) / sizeof(I830TexFormats[0]); i++) {
-        if (I830TexFormats[i].fmt == pPict->format)
+    for (i = 0; i < sizeof(i830_tex_formats) / sizeof(i830_tex_formats[0]);
+	 i++)
+    {
+        if (i830_tex_formats[i].fmt == pPict->format)
 	    break;
     }
-    if ( i == sizeof(I830TexFormats)/ sizeof(I830TexFormats[0]) )
+    if (i == sizeof(i830_tex_formats)/ sizeof(i830_tex_formats[0]))
 	I830FALLBACK("unknown texture format\n");
-    format = I830TexFormats[i].card_fmt;
+    format = i830_tex_formats[i].card_fmt;
 
-    if (pPict->repeat) 
+    if (pPict->repeat)
 	wrap_mode = TEXCOORDMODE_WRAP; /* XXX: correct ? */
-    
+
     switch (pPict->filter) {
     case PictFilterNearest:
-        filter = ((FILTER_NEAREST<<TM0S3_MAG_FILTER_SHIFT) | 
-			(FILTER_NEAREST<<TM0S3_MIN_FILTER_SHIFT));
+        filter = ((FILTER_NEAREST<<TM0S3_MAG_FILTER_SHIFT) |
+		  (FILTER_NEAREST<<TM0S3_MIN_FILTER_SHIFT));
         break;
     case PictFilterBilinear:
-        filter = ((FILTER_LINEAR<<TM0S3_MAG_FILTER_SHIFT) | 
-			(FILTER_LINEAR<<TM0S3_MIN_FILTER_SHIFT));
+        filter = ((FILTER_LINEAR<<TM0S3_MAG_FILTER_SHIFT) |
+		  (FILTER_LINEAR<<TM0S3_MIN_FILTER_SHIFT));
         break;
     default:
 	filter = 0;
@@ -300,7 +304,7 @@ I830TextureSetup(PicturePtr pPict, Pixma
 	OUT_RING(_3DSTATE_MAP_INFO_CMD);
 	OUT_RING(format | TEXMAP_INDEX(unit) | MAP_FORMAT_2D);
 	OUT_RING(((pPix->drawable.height - 1) << 16) |
-		(pPix->drawable.width - 1)); /* height, width */
+		 (pPix->drawable.width - 1)); /* height, width */
 	OUT_RING(offset); /* map address */
 	OUT_RING(((pitch / 4) - 1) << 2); /* map pitch */
 	OUT_RING(0);
@@ -310,16 +314,19 @@ I830TextureSetup(PicturePtr pPict, Pixma
      {
 	BEGIN_LP_RING(2);
 	/* coord sets */
-	OUT_RING(_3DSTATE_MAP_COORD_SET_CMD | TEXCOORD_SET(unit) | 
-		ENABLE_TEXCOORD_PARAMS | TEXCOORDS_ARE_NORMAL | 
-		TEXCOORDTYPE_CARTESIAN | ENABLE_ADDR_V_CNTL | 
-		TEXCOORD_ADDR_V_MODE(wrap_mode) |
-		ENABLE_ADDR_U_CNTL | TEXCOORD_ADDR_U_MODE(wrap_mode));
+	OUT_RING(_3DSTATE_MAP_COORD_SET_CMD | TEXCOORD_SET(unit) |
+		 ENABLE_TEXCOORD_PARAMS | TEXCOORDS_ARE_NORMAL |
+		 TEXCOORDTYPE_CARTESIAN | ENABLE_ADDR_V_CNTL |
+		 TEXCOORD_ADDR_V_MODE(wrap_mode) |
+		 ENABLE_ADDR_U_CNTL | TEXCOORD_ADDR_U_MODE(wrap_mode));
 	OUT_RING(MI_NOOP);
 
 	/* XXX: filter seems hang engine...*/
 #if 0
-	OUT_RING(I830_STATE3D_MAP_FILTER | FILTER_MAP_INDEX(unit) | ENABLE_KEYS| DISABLE_COLOR_KEY | DISABLE_CHROMA_KEY | DISABLE_KILL_PIXEL |ENABLE_MIP_MODE_FILTER | MIPFILTER_NONE | filter);
+	OUT_RING(I830_STATE3D_MAP_FILTER | FILTER_MAP_INDEX(unit) |
+		 ENABLE_KEYS| DISABLE_COLOR_KEY | DISABLE_CHROMA_KEY |
+		 DISABLE_KILL_PIXEL |ENABLE_MIP_MODE_FILTER |
+		 MIPFILTER_NONE | filter);
 	OUT_RING(0);
 #endif
 
@@ -334,63 +341,63 @@ I830TextureSetup(PicturePtr pPict, Pixma
     ErrorF("try to sync to show any errors...");
     I830Sync(pScrn);
 #endif
-	
+
     return TRUE;
 }
 
 Bool
-I830EXACheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
-		      PicturePtr pDstPicture)
+i830_check_composite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+		     PicturePtr pDstPicture)
 {
     CARD32 tmp1;
-    
+
     /* Check for unsupported compositing operations. */
-    if (op >= sizeof(I830BlendOp) / sizeof(I830BlendOp[0]))
+    if (op >= sizeof(i830_blend_op) / sizeof(i830_blend_op[0]))
         I830FALLBACK("Unsupported Composite op 0x%x\n", op);
-                                                                                                                                                            
+
     if (pMaskPicture != NULL && pMaskPicture->componentAlpha) {
         /* Check if it's component alpha that relies on a source alpha and on
          * the source value.  We can only get one of those into the single
          * source value that we get to blend with.
          */
-        if (I830BlendOp[op].src_alpha &&
-            (I830BlendOp[op].src_blend != BLENDFACTOR_ZERO))
+        if (i830_blend_op[op].src_alpha &&
+            (i830_blend_op[op].src_blend != BLENDFACTOR_ZERO))
             	I830FALLBACK("Component alpha not supported with source "
-                            "alpha and source value blending.\n");
+			     "alpha and source value blending.\n");
     }
 
-    if (!I830CheckCompositeTexture(pSrcPicture, 0))
+    if (!i830_check_composite_texture(pSrcPicture, 0))
         I830FALLBACK("Check Src picture texture\n");
-    if (pMaskPicture != NULL && !I830CheckCompositeTexture(pMaskPicture, 1))
+    if (pMaskPicture != NULL && !i830_check_composite_texture(pMaskPicture, 1))
         I830FALLBACK("Check Mask picture texture\n");
 
-    if (!I830GetDestFormat(pDstPicture, &tmp1)) 
+    if (!i830_get_dest_format(pDstPicture, &tmp1))
 	I830FALLBACK("Get Color buffer format\n");
 
     return TRUE;
 }
 
 Bool
-I830EXAPrepareComposite(int op, PicturePtr pSrcPicture,
-			PicturePtr pMaskPicture, PicturePtr pDstPicture,
-			PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
+i830_prepare_composite(int op, PicturePtr pSrcPicture,
+		       PicturePtr pMaskPicture, PicturePtr pDstPicture,
+		       PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
 {
-/* XXX: setup texture map from pixmap, vertex format, blend cntl */
+    /* XXX: setup texture map from pixmap, vertex format, blend cntl */
     ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
     CARD32 dst_format, dst_offset, dst_pitch;
 
-    I830GetDestFormat(pDstPicture, &dst_format);
+    i830_get_dest_format(pDstPicture, &dst_format);
     dst_offset = intel_get_pixmap_offset(pDst);
     dst_pitch = intel_get_pixmap_pitch(pDst);
 
     pI830->last_3d = LAST_3D_RENDER;
 
-    if (!I830TextureSetup(pSrcPicture, pSrc, 0))
+    if (!i830_texture_setup(pSrcPicture, pSrc, 0))
 	I830FALLBACK("fail to setup src texture\n");
     if (pMask != NULL) {
-	if (!I830TextureSetup(pMaskPicture, pMask, 1))
-		I830FALLBACK("fail to setup mask texture\n");
+	if (!i830_texture_setup(pMaskPicture, pMask, 1))
+	    I830FALLBACK("fail to setup mask texture\n");
     } else {
 	pI830->transform[1] = NULL;
 	pI830->scale_units[1][0] = -1;
@@ -398,17 +405,16 @@ I830EXAPrepareComposite(int op, PictureP
     }
 
     {
-
 	CARD32 cblend, ablend, blendctl, vf2;
 
 	BEGIN_LP_RING(22+6);
-	
-	/*color buffer*/
+
+	/* color buffer */
 	OUT_RING(_3DSTATE_BUF_INFO_CMD);
 	OUT_RING(BUF_3D_ID_COLOR_BACK| BUF_3D_PITCH(dst_pitch));
 	OUT_RING(BUF_3D_ADDR(dst_offset));
 	OUT_RING(MI_NOOP);
-	
+
 	OUT_RING(_3DSTATE_DST_BUF_VARS_CMD);
 	OUT_RING(dst_format);
 
@@ -423,10 +429,10 @@ I830EXAPrepareComposite(int op, PictureP
 
 	OUT_RING(_3DSTATE_DFLT_SPEC_CMD);
 	OUT_RING(0);
-	
+
 	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | 0);
-	OUT_RING((1 << S3_POINT_WIDTH_SHIFT) | (2 << S3_LINE_WIDTH_SHIFT) | 
-		S3_CULLMODE_NONE | S3_VERTEXHAS_XY);  
+	OUT_RING((1 << S3_POINT_WIDTH_SHIFT) | (2 << S3_LINE_WIDTH_SHIFT) |
+		S3_CULLMODE_NONE | S3_VERTEXHAS_XY);
 	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) | 0);
 	if (pMask)
 	    vf2 = 2 << 12; /* 2 texture coord sets */
@@ -437,7 +443,7 @@ I830EXAPrepareComposite(int op, PictureP
 	    vf2 |= (TEXCOORDFMT_2D << 18);
 	else
 	    vf2 |= (TEXCOORDFMT_1D << 18);
-		
+
 	vf2 |= (TEXCOORDFMT_1D << 20);
 	vf2 |= (TEXCOORDFMT_1D << 22);
 	vf2 |= (TEXCOORDFMT_1D << 24);
@@ -452,10 +458,10 @@ I830EXAPrepareComposite(int op, PictureP
 	/* IN operator: Multiply src by mask components or mask alpha.*/
 	/* TEXBLENDOP_MODULE: arg1*arg2 */
 	cblend = TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OP_MODULE |
-		 TB0C_OUTPUT_WRITE_CURRENT;  
-	ablend = TB0A_RESULT_SCALE_1X | TB0A_OP_MODULE | 
+		 TB0C_OUTPUT_WRITE_CURRENT;
+	ablend = TB0A_RESULT_SCALE_1X | TB0A_OP_MODULE |
 		 TB0A_OUTPUT_WRITE_CURRENT;
-	
+
 	cblend |= TB0C_ARG1_SEL_TEXEL0;
 	ablend |= TB0A_ARG1_SEL_TEXEL0;
 	if (pMask) {
@@ -465,11 +471,12 @@ I830EXAPrepareComposite(int op, PictureP
 		cblend |= (TB0C_ARG2_SEL_TEXEL1 | TB0C_ARG2_REPLICATE_ALPHA);
 	    ablend |= TB0A_ARG2_SEL_TEXEL1;
 	} else {
-		cblend |= TB0C_ARG2_SEL_ONE;
-		ablend |= TB0A_ARG2_SEL_ONE;		
+	    cblend |= TB0C_ARG2_SEL_ONE;
+	    ablend |= TB0A_ARG2_SEL_ONE;
 	}
-		
-	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | LOAD_TEXTURE_BLEND_STAGE(0)|1);
+
+	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
+		 LOAD_TEXTURE_BLEND_STAGE(0)|1);
 	OUT_RING(cblend);
 	OUT_RING(ablend);
 	OUT_RING(0);
@@ -477,16 +484,16 @@ I830EXAPrepareComposite(int op, PictureP
       	OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
       	OUT_RING(MI_NOOP);		/* pad to quadword */
 
-	blendctl = I830GetBlendCntl(op, pMaskPicture, pDstPicture->format);
+	blendctl = i830_get_blend_cntl(op, pMaskPicture, pDstPicture->format);
 	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(8) | 0);
 	OUT_RING(S8_ENABLE_COLOR_BLEND | S8_BLENDFUNC_ADD |(blendctl<<4) |
-		S8_ENABLE_COLOR_BUFFER_WRITE);	
+		 S8_ENABLE_COLOR_BUFFER_WRITE);
 	ADVANCE_LP_RING();
     }
 
 #ifdef I830DEBUG
-   Error("try to sync to show any errors...");
-   I830Sync(pScrn);
+    Error("try to sync to show any errors...");
+    I830Sync(pScrn);
 #endif
 
     return TRUE;
@@ -499,8 +506,8 @@ I830EXAPrepareComposite(int op, PictureP
  * This function is shared between i830 and i915 generation code.
  */
 void
-IntelEXAComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
-		 int dstX, int dstY, int w, int h)
+i830_composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
+	       int dstX, int dstY, int w, int h)
 {
     ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
@@ -533,7 +540,7 @@ IntelEXAComposite(PixmapPtr pDst, int sr
     }
 
     {
-	int vertex_count; 
+	int vertex_count;
 
 	if (has_mask)
 		vertex_count = 3*6;
@@ -555,8 +562,8 @@ IntelEXAComposite(PixmapPtr pDst, int sr
 	OUT_RING_F(src_x[0] / pI830->scale_units[0][0]);
 	OUT_RING_F(src_y[0] / pI830->scale_units[0][1]);
 	if (has_mask) {
-		OUT_RING_F(mask_x[0] / pI830->scale_units[1][0]);
-		OUT_RING_F(mask_y[0] / pI830->scale_units[1][1]);
+	    OUT_RING_F(mask_x[0] / pI830->scale_units[1][0]);
+	    OUT_RING_F(mask_y[0] / pI830->scale_units[1][1]);
 	}
 
 	OUT_RING_F(dstX);
@@ -564,8 +571,8 @@ IntelEXAComposite(PixmapPtr pDst, int sr
 	OUT_RING_F(src_x[1] / pI830->scale_units[0][0]);
 	OUT_RING_F(src_y[1] / pI830->scale_units[0][1]);
 	if (has_mask) {
-		OUT_RING_F(mask_x[1] / pI830->scale_units[1][0]);
-		OUT_RING_F(mask_y[1] / pI830->scale_units[1][1]);
+	    OUT_RING_F(mask_x[1] / pI830->scale_units[1][0]);
+	    OUT_RING_F(mask_y[1] / pI830->scale_units[1][1]);
 	}
 
 	OUT_RING_F(dstX + w);
@@ -573,15 +580,20 @@ IntelEXAComposite(PixmapPtr pDst, int sr
 	OUT_RING_F(src_x[2] / pI830->scale_units[0][0]);
 	OUT_RING_F(src_y[2] / pI830->scale_units[0][1]);
 	if (has_mask) {
-		OUT_RING_F(mask_x[2] / pI830->scale_units[1][0]);
-		OUT_RING_F(mask_y[2] / pI830->scale_units[1][1]);
+	    OUT_RING_F(mask_x[2] / pI830->scale_units[1][0]);
+	    OUT_RING_F(mask_y[2] / pI830->scale_units[1][1]);
 	}
 	ADVANCE_LP_RING();
     }
 }
 
+/**
+ * Do any cleanup from the Composite operation.
+ *
+ * This is shared between i830 through i965.
+ */
 void
-IntelEXADoneComposite(PixmapPtr pDst)
+i830_done_composite(PixmapPtr pDst)
 {
 #if ALWAYS_SYNC
     ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
diff --git a/src/i830_xaa.c b/src/i830_xaa.c
index 96b23fa..dbe1521 100644
--- a/src/i830_xaa.c
+++ b/src/i830_xaa.c
@@ -240,26 +240,25 @@ I830XAAInit(ScreenPtr pScreen)
 	return FALSE;
 
     if (ps != NULL) {
-	if (IS_I915G(pI830) || IS_I915GM(pI830) ||
-	    IS_I945G(pI830) || IS_I945GM(pI830))
+	if (IS_I865G(pI830) || IS_I855(pI830) ||
+	    IS_845G(pI830) || IS_I830(pI830))
 	{
-	    pI830->xaa_check_composite = I915EXACheckComposite;
-	    pI830->xaa_prepare_composite = I915EXAPrepareComposite;
-	    pI830->xaa_composite = IntelEXAComposite;
-	    pI830->xaa_done_composite = IntelEXADoneComposite;
-	} else if (IS_I865G(pI830) || IS_I855(pI830) ||
-		   IS_845G(pI830) || IS_I830(pI830)) {
-	    pI830->xaa_check_composite = I830EXACheckComposite;
-	    pI830->xaa_prepare_composite = I830EXAPrepareComposite;
-	    pI830->xaa_composite = IntelEXAComposite;
-	    pI830->xaa_done_composite = IntelEXADoneComposite;
-	} else if (IS_I965G(pI830)) {
-	    pI830->xaa_check_composite = I965EXACheckComposite;
-	    pI830->xaa_prepare_composite = I965EXAPrepareComposite;
-	    pI830->xaa_composite = I965EXAComposite;
-	    pI830->xaa_done_composite = IntelEXADoneComposite;
+	    pI830->EXADriverPtr->CheckComposite = i830_check_composite;
+	    pI830->EXADriverPtr->PrepareComposite = i830_prepare_composite;
+	    pI830->EXADriverPtr->Composite = i830_composite;
+	    pI830->EXADriverPtr->DoneComposite = i830_done_composite;
+	} else if (IS_I915G(pI830) || IS_I915GM(pI830) ||
+		   IS_I945G(pI830) || IS_I945GM(pI830))
+	{
+	    pI830->EXADriverPtr->CheckComposite = i915_check_composite;
+	    pI830->EXADriverPtr->PrepareComposite = i915_prepare_composite;
+	    pI830->EXADriverPtr->Composite = i830_composite;
+	    pI830->EXADriverPtr->DoneComposite = i830_done_composite;
 	} else {
-	    return TRUE;
+	    pI830->EXADriverPtr->CheckComposite = i965_check_composite;
+	    pI830->EXADriverPtr->PrepareComposite = i965_prepare_composite;
+	    pI830->EXADriverPtr->Composite = i965_composite;
+	    pI830->EXADriverPtr->DoneComposite = i830_done_composite;
 	}
 
 	pI830->saved_composite = ps->Composite;
diff --git a/src/i915_render.c b/src/i915_render.c
index 2fb41ad..4d42242 100644
--- a/src/i915_render.c
+++ b/src/i915_render.c
@@ -64,7 +64,7 @@ struct blendinfo {
     CARD32 dst_blend;
 };
 
-static struct blendinfo I915BlendOp[] = {
+static struct blendinfo i915_blend_op[] = {
     /* Clear */
     {0, 0, BLENDFACT_ZERO,          BLENDFACT_ZERO},
     /* Src */
@@ -93,42 +93,42 @@ static struct blendinfo I915BlendOp[] = 
     {0, 0, BLENDFACT_ONE,           BLENDFACT_ONE},
 };
 
-static struct formatinfo I915TexFormats[] = {
-        {PICT_a8r8g8b8, MAPSURF_32BIT | MT_32BIT_ARGB8888 },
-        {PICT_x8r8g8b8, MAPSURF_32BIT | MT_32BIT_XRGB8888 },
-        {PICT_a8b8g8r8, MAPSURF_32BIT | MT_32BIT_ABGR8888 },
-        {PICT_x8b8g8r8, MAPSURF_32BIT | MT_32BIT_XBGR8888 },
-        {PICT_r5g6b5,   MAPSURF_16BIT | MT_16BIT_RGB565   },
-        {PICT_a1r5g5b5, MAPSURF_16BIT | MT_16BIT_ARGB1555 },
-        {PICT_x1r5g5b5, MAPSURF_16BIT | MT_16BIT_ARGB1555 },
-        {PICT_a4r4g4b4, MAPSURF_16BIT | MT_16BIT_ARGB4444 },
-        {PICT_x4r4g4b4, MAPSURF_16BIT | MT_16BIT_ARGB4444 },
-        {PICT_a8,       MAPSURF_8BIT | MT_8BIT_A8 	  },
+static struct formatinfo i915_tex_formats[] = {
+    {PICT_a8r8g8b8, MAPSURF_32BIT | MT_32BIT_ARGB8888 },
+    {PICT_x8r8g8b8, MAPSURF_32BIT | MT_32BIT_XRGB8888 },
+    {PICT_a8b8g8r8, MAPSURF_32BIT | MT_32BIT_ABGR8888 },
+    {PICT_x8b8g8r8, MAPSURF_32BIT | MT_32BIT_XBGR8888 },
+    {PICT_r5g6b5,   MAPSURF_16BIT | MT_16BIT_RGB565   },
+    {PICT_a1r5g5b5, MAPSURF_16BIT | MT_16BIT_ARGB1555 },
+    {PICT_x1r5g5b5, MAPSURF_16BIT | MT_16BIT_ARGB1555 },
+    {PICT_a4r4g4b4, MAPSURF_16BIT | MT_16BIT_ARGB4444 },
+    {PICT_x4r4g4b4, MAPSURF_16BIT | MT_16BIT_ARGB4444 },
+    {PICT_a8,       MAPSURF_8BIT | MT_8BIT_A8 	  },
 };
 
-static CARD32 I915GetBlendCntl(int op, PicturePtr pMask, CARD32 dst_format)
+static CARD32 i915_get_blend_cntl(int op, PicturePtr pMask, CARD32 dst_format)
 {
     CARD32 sblend, dblend;
 
-    sblend = I915BlendOp[op].src_blend;
-    dblend = I915BlendOp[op].dst_blend;
+    sblend = i915_blend_op[op].src_blend;
+    dblend = i915_blend_op[op].dst_blend;
 
     /* If there's no dst alpha channel, adjust the blend op so that we'll treat
      * it as always 1.
      */
-    if (PICT_FORMAT_A(dst_format) == 0 && I915BlendOp[op].dst_alpha) {
+    if (PICT_FORMAT_A(dst_format) == 0 && i915_blend_op[op].dst_alpha) {
         if (sblend == BLENDFACT_DST_ALPHA)
             sblend = BLENDFACT_ONE;
         else if (sblend == BLENDFACT_INV_DST_ALPHA)
             sblend = BLENDFACT_ZERO;
     }
 
-    /* If the source alpha is being used, then we should only be in a case where
-     * the source blend factor is 0, and the source blend value is the mask
-     * channels multiplied by the source picture's alpha.
+    /* If the source alpha is being used, then we should only be in a case
+     * where the source blend factor is 0, and the source blend value is the
+     * mask channels multiplied by the source picture's alpha.
      */
     if (pMask && pMask->componentAlpha && PICT_FORMAT_RGB(pMask->format) &&
-	I915BlendOp[op].src_alpha)
+	i915_blend_op[op].src_alpha)
     {
         if (dblend == BLENDFACT_SRC_ALPHA) {
 	    dblend = BLENDFACT_SRC_COLR;
@@ -141,7 +141,7 @@ static CARD32 I915GetBlendCntl(int op, P
 	(dblend << S6_CBUF_DST_BLEND_FACT_SHIFT);
 }
 
-static Bool I915GetDestFormat(PicturePtr pDstPicture, CARD32 *dst_format)
+static Bool i915_get_dest_format(PicturePtr pDstPicture, CARD32 *dst_format)
 {
     switch (pDstPicture->format) {
     case PICT_a8r8g8b8:
@@ -171,13 +171,13 @@ static Bool I915GetDestFormat(PicturePtr
 	break;
     default:
         I830FALLBACK("Unsupported dest format 0x%x\n",
-                        (int)pDstPicture->format);
+		     (int)pDstPicture->format);
     }
 
     return TRUE;
 }
 
-static Bool I915CheckCompositeTexture(PicturePtr pPict, int unit)
+static Bool i915_check_composite_texture(PicturePtr pPict, int unit)
 {
     int w = pPict->pDrawable->width;
     int h = pPict->pDrawable->height;
@@ -186,14 +186,15 @@ static Bool I915CheckCompositeTexture(Pi
     if ((w > 0x7ff) || (h > 0x7ff))
         I830FALLBACK("Picture w/h too large (%dx%d)\n", w, h);
 
-    for (i = 0; i < sizeof(I915TexFormats) / sizeof(I915TexFormats[0]); i++)
+    for (i = 0; i < sizeof(i915_tex_formats) / sizeof(i915_tex_formats[0]);
+	 i++)
     {
-        if (I915TexFormats[i].fmt == pPict->format)
+        if (i915_tex_formats[i].fmt == pPict->format)
             break;
     }
-    if (i == sizeof(I915TexFormats) / sizeof(I915TexFormats[0]))
+    if (i == sizeof(i915_tex_formats) / sizeof(i915_tex_formats[0]))
         I830FALLBACK("Unsupported picture format 0x%x\n",
-                         (int)pPict->format);
+		     (int)pPict->format);
 
     if (pPict->repeat && pPict->repeatType != RepeatNormal)
 	I830FALLBACK("extended repeat (%d) not supported\n",
@@ -207,13 +208,13 @@ static Bool I915CheckCompositeTexture(Pi
 }
 
 Bool
-I915EXACheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
-		      PicturePtr pDstPicture)
+i915_check_composite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+		     PicturePtr pDstPicture)
 {
     CARD32 tmp1;
 
     /* Check for unsupported compositing operations. */
-    if (op >= sizeof(I915BlendOp) / sizeof(I915BlendOp[0]))
+    if (op >= sizeof(i915_blend_op) / sizeof(i915_blend_op[0]))
         I830FALLBACK("Unsupported Composite op 0x%x\n", op);
     if (pMaskPicture != NULL && pMaskPicture->componentAlpha &&
 	PICT_FORMAT_RGB(pMaskPicture->format))
@@ -222,25 +223,25 @@ I915EXACheckComposite(int op, PicturePtr
          * the source value.  We can only get one of those into the single
          * source value that we get to blend with.
          */
-        if (I915BlendOp[op].src_alpha &&
-            (I915BlendOp[op].src_blend != BLENDFACT_ZERO))
+        if (i915_blend_op[op].src_alpha &&
+            (i915_blend_op[op].src_blend != BLENDFACT_ZERO))
             	I830FALLBACK("Component alpha not supported with source "
-                            "alpha and source value blending.\n");
+			     "alpha and source value blending.\n");
     }
 
-    if (!I915CheckCompositeTexture(pSrcPicture, 0))
+    if (!i915_check_composite_texture(pSrcPicture, 0))
         I830FALLBACK("Check Src picture texture\n");
-    if (pMaskPicture != NULL && !I915CheckCompositeTexture(pMaskPicture, 1))
+    if (pMaskPicture != NULL && !i915_check_composite_texture(pMaskPicture, 1))
         I830FALLBACK("Check Mask picture texture\n");
 
-    if (!I915GetDestFormat(pDstPicture, &tmp1))
+    if (!i915_get_dest_format(pDstPicture, &tmp1))
 	I830FALLBACK("Get Color buffer format\n");
 
     return TRUE;
 }
 
 static Bool
-I915TextureSetup(PicturePtr pPict, PixmapPtr pPix, int unit)
+i915_texture_setup(PicturePtr pPict, PixmapPtr pPix, int unit)
 {
     ScrnInfoPtr pScrn = xf86Screens[pPict->pDrawable->pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
@@ -255,13 +256,15 @@ I915TextureSetup(PicturePtr pPict, Pixma
     pI830->scale_units[unit][0] = pPix->drawable.width;
     pI830->scale_units[unit][1] = pPix->drawable.height;
 
-    for (i = 0; i < sizeof(I915TexFormats) / sizeof(I915TexFormats[0]); i++) {
-        if (I915TexFormats[i].fmt == pPict->format)
+    for (i = 0; i < sizeof(i915_tex_formats) / sizeof(i915_tex_formats[0]);
+	 i++)
+    {
+        if (i915_tex_formats[i].fmt == pPict->format)
 	    break;
     }
-    if (i == sizeof(I915TexFormats)/ sizeof(I915TexFormats[0]))
+    if (i == sizeof(i915_tex_formats)/ sizeof(i915_tex_formats[0]))
 	I830FALLBACK("unknown texture format\n");
-    format = I915TexFormats[i].card_fmt;
+    format = i915_tex_formats[i].card_fmt;
 
     if (pPict->repeat)
 	wrap_mode = TEXCOORDMODE_WRAP;
@@ -269,11 +272,11 @@ I915TextureSetup(PicturePtr pPict, Pixma
     switch (pPict->filter) {
     case PictFilterNearest:
         filter = (FILTER_NEAREST << SS2_MAG_FILTER_SHIFT) |
-			(FILTER_NEAREST << SS2_MIN_FILTER_SHIFT);
+	    (FILTER_NEAREST << SS2_MIN_FILTER_SHIFT);
         break;
     case PictFilterBilinear:
         filter = (FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) |
-			(FILTER_LINEAR << SS2_MIN_FILTER_SHIFT);
+	    (FILTER_LINEAR << SS2_MIN_FILTER_SHIFT);
         break;
     default:
 	filter = 0;
@@ -288,7 +291,8 @@ I915TextureSetup(PicturePtr pPict, Pixma
 	pI830->samplerstate[unit * 3 + 1] |= MS3_USE_FENCE_REGS;
     pI830->mapstate[unit * 3 + 2] = ((pitch / 4) - 1) << MS4_PITCH_SHIFT;
 
-    pI830->samplerstate[unit * 3 + 0] = (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT);
+    pI830->samplerstate[unit * 3 + 0] = (MIPFILTER_NONE <<
+					 SS2_MIP_FILTER_SHIFT);
     pI830->samplerstate[unit * 3 + 0] |= filter;
     pI830->samplerstate[unit * 3 + 1] = SS3_NORMALIZED_COORDS;
     pI830->samplerstate[unit * 3 + 1] |= wrap_mode << SS3_TCX_ADDR_MODE_SHIFT;
@@ -302,9 +306,9 @@ I915TextureSetup(PicturePtr pPict, Pixma
 }
 
 Bool
-I915EXAPrepareComposite(int op, PicturePtr pSrcPicture,
-			PicturePtr pMaskPicture, PicturePtr pDstPicture,
-			PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
+i915_prepare_composite(int op, PicturePtr pSrcPicture,
+		       PicturePtr pMaskPicture, PicturePtr pDstPicture,
+		       PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
 {
     ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
@@ -317,16 +321,16 @@ I915EXAPrepareComposite(int op, PictureP
 
     pI830->last_3d = LAST_3D_RENDER;
 
-    I915GetDestFormat(pDstPicture, &dst_format);
+    i915_get_dest_format(pDstPicture, &dst_format);
     dst_offset = intel_get_pixmap_offset(pDst);
     dst_pitch = intel_get_pixmap_pitch(pDst);
     FS_LOCALS(20);
 
-    if (!I915TextureSetup(pSrcPicture, pSrc, 0))
+    if (!i915_texture_setup(pSrcPicture, pSrc, 0))
 	I830FALLBACK("fail to setup src texture\n");
     if (pMask != NULL) {
-	if (!I915TextureSetup(pMaskPicture, pMask, 1))
-		I830FALLBACK("fail to setup mask texture\n");
+	if (!i915_texture_setup(pMaskPicture, pMask, 1))
+	    I830FALLBACK("fail to setup mask texture\n");
     } else {
 	pI830->transform[1] = NULL;
 	pI830->scale_units[1][0] = -1;
@@ -399,7 +403,7 @@ I915EXAPrepareComposite(int op, PictureP
 	OUT_RING(ss2);
 	OUT_RING((1 << S4_POINT_WIDTH_SHIFT) | S4_LINE_WIDTH_ONE |
 		 S4_CULLMODE_NONE| S4_VFMT_XY);
-	blendctl = I915GetBlendCntl(op, pMaskPicture, pDstPicture->format);
+	blendctl = i915_get_blend_cntl(op, pMaskPicture, pDstPicture->format);
 	OUT_RING(0x00000000); /* Disable stencil buffer */
 	OUT_RING(S6_CBUF_BLEND_ENABLE | S6_COLOR_WRITE_ENABLE |
 		 (BLENDFUNC_ADD << S6_CBUF_BLEND_FUNC_SHIFT) | blendctl);
@@ -459,7 +463,7 @@ I915EXAPrepareComposite(int op, PictureP
 	if (pMaskPicture->componentAlpha &&
 	    PICT_FORMAT_RGB(pMaskPicture->format))
 	{
-	    if (I915BlendOp[op].src_alpha) {
+	    if (i915_blend_op[op].src_alpha) {
 		i915_fs_mul(FS_OC, i915_fs_operand(FS_R0, W, W, W, W),
 			    i915_fs_operand_reg(FS_R1));
 	    } else {
diff --git a/src/i965_render.c b/src/i965_render.c
index 99bd628..5ff174d 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -52,12 +52,9 @@ do {							\
 #define I830FALLBACK(s, arg...) 			\
 do { 							\
 	return FALSE;					\
-} while(0) 
+} while(0)
 #endif
 
-static void I965GetBlendCntl(int op, PicturePtr pMask, CARD32 dst_format, 
-			     CARD32 *sblend, CARD32 *dblend);
-
 struct blendinfo {
     Bool dst_alpha;
     Bool src_alpha;
@@ -73,7 +70,7 @@ struct formatinfo {
 // refer vol2, 3d rasterization 3.8.1
 
 /* defined in brw_defines.h */
-static struct blendinfo I965BlendOp[] = { 
+static struct blendinfo i965_blend_op[] = {
     /* Clear */
     {0, 0, BRW_BLENDFACTOR_ZERO,          BRW_BLENDFACTOR_ZERO},
     /* Src */
@@ -102,28 +99,30 @@ static struct blendinfo I965BlendOp[] = 
     {0, 0, BRW_BLENDFACTOR_ONE,           BRW_BLENDFACTOR_ONE},
 };
 
-/* FIXME: surface format defined in brw_defines.h, shared Sampling engine 1.7.2*/
-static struct formatinfo I965TexFormats[] = {
-        {PICT_a8r8g8b8, BRW_SURFACEFORMAT_B8G8R8A8_UNORM },
-        {PICT_x8r8g8b8, BRW_SURFACEFORMAT_B8G8R8X8_UNORM },
-        {PICT_a8b8g8r8, BRW_SURFACEFORMAT_R8G8B8A8_UNORM },
-        {PICT_x8b8g8r8, BRW_SURFACEFORMAT_R8G8B8X8_UNORM },
-        {PICT_r5g6b5,   BRW_SURFACEFORMAT_B5G6R5_UNORM   },
-        {PICT_a1r5g5b5, BRW_SURFACEFORMAT_B5G5R5A1_UNORM },
-        {PICT_a8,       BRW_SURFACEFORMAT_A8_UNORM	 },
+/* FIXME: surface format defined in brw_defines.h, shared Sampling engine
+ * 1.7.2
+ */
+static struct formatinfo i965_tex_formats[] = {
+    {PICT_a8r8g8b8, BRW_SURFACEFORMAT_B8G8R8A8_UNORM },
+    {PICT_x8r8g8b8, BRW_SURFACEFORMAT_B8G8R8X8_UNORM },
+    {PICT_a8b8g8r8, BRW_SURFACEFORMAT_R8G8B8A8_UNORM },
+    {PICT_x8b8g8r8, BRW_SURFACEFORMAT_R8G8B8X8_UNORM },
+    {PICT_r5g6b5,   BRW_SURFACEFORMAT_B5G6R5_UNORM   },
+    {PICT_a1r5g5b5, BRW_SURFACEFORMAT_B5G5R5A1_UNORM },
+    {PICT_a8,       BRW_SURFACEFORMAT_A8_UNORM	 },
 };
 
-static void I965GetBlendCntl(int op, PicturePtr pMask, CARD32 dst_format, 
-			     CARD32 *sblend, CARD32 *dblend)
+static void i965_get_blend_cntl(int op, PicturePtr pMask, CARD32 dst_format,
+				CARD32 *sblend, CARD32 *dblend)
 {
 
-    *sblend = I965BlendOp[op].src_blend;
-    *dblend = I965BlendOp[op].dst_blend;
+    *sblend = i965_blend_op[op].src_blend;
+    *dblend = i965_blend_op[op].dst_blend;
 
     /* If there's no dst alpha channel, adjust the blend op so that we'll treat
      * it as always 1.
      */
-    if (PICT_FORMAT_A(dst_format) == 0 && I965BlendOp[op].dst_alpha) {
+    if (PICT_FORMAT_A(dst_format) == 0 && i965_blend_op[op].dst_alpha) {
         if (*sblend == BRW_BLENDFACTOR_DST_ALPHA)
             *sblend = BRW_BLENDFACTOR_ONE;
         else if (*sblend == BRW_BLENDFACTOR_INV_DST_ALPHA)
@@ -134,7 +133,7 @@ static void I965GetBlendCntl(int op, Pic
      * the source blend factor is 0, and the source blend value is the mask
      * channels multiplied by the source picture's alpha.
      */
-    if (pMask && pMask->componentAlpha && I965BlendOp[op].src_alpha) {
+    if (pMask && pMask->componentAlpha && i965_blend_op[op].src_alpha) {
         if (*dblend == BRW_BLENDFACTOR_SRC_ALPHA) {
 	    *dblend = BRW_BLENDFACTOR_SRC_COLOR;
         } else if (*dblend == BRW_BLENDFACTOR_INV_SRC_ALPHA) {
@@ -144,7 +143,7 @@ static void I965GetBlendCntl(int op, Pic
 
 }
 
-static Bool I965GetDestFormat(PicturePtr pDstPicture, CARD32 *dst_format)
+static Bool i965_get_dest_format(PicturePtr pDstPicture, CARD32 *dst_format)
 {
     switch (pDstPicture->format) {
     case PICT_a8r8g8b8:
@@ -172,33 +171,34 @@ static Bool I965GetDestFormat(PicturePtr
     */
     case PICT_a4r4g4b4:
     case PICT_x4r4g4b4:
-	*dst_format = BRW_SURFACEFORMAT_B4G4R4A4_UNORM; 
+	*dst_format = BRW_SURFACEFORMAT_B4G4R4A4_UNORM;
 	break;
     default:
         I830FALLBACK("Unsupported dest format 0x%x\n",
-                        (int)pDstPicture->format);
+		     (int)pDstPicture->format);
     }
 
     return TRUE;
 }
 
-static Bool I965CheckCompositeTexture(PicturePtr pPict, int unit)
+static Bool i965_check_composite_texture(PicturePtr pPict, int unit)
 {
     int w = pPict->pDrawable->width;
     int h = pPict->pDrawable->height;
     int i;
-                                                                                                                                                            
+
     if ((w > 0x7ff) || (h > 0x7ff))
         I830FALLBACK("Picture w/h too large (%dx%d)\n", w, h);
 
-    for (i = 0; i < sizeof(I965TexFormats) / sizeof(I965TexFormats[0]); i++)
+    for (i = 0; i < sizeof(i965_tex_formats) / sizeof(i965_tex_formats[0]);
+	 i++)
     {
-        if (I965TexFormats[i].fmt == pPict->format)
+        if (i965_tex_formats[i].fmt == pPict->format)
             break;
     }
-    if (i == sizeof(I965TexFormats) / sizeof(I965TexFormats[0]))
+    if (i == sizeof(i965_tex_formats) / sizeof(i965_tex_formats[0]))
         I830FALLBACK("Unsupported picture format 0x%x\n",
-                         (int)pPict->format);
+		     (int)pPict->format);
 
     if (pPict->repeat && pPict->repeatType != RepeatNormal)
 	I830FALLBACK("extended repeat (%d) not supported\n",
@@ -206,19 +206,21 @@ static Bool I965CheckCompositeTexture(Pi
 
     if (pPict->filter != PictFilterNearest &&
         pPict->filter != PictFilterBilinear)
+    {
         I830FALLBACK("Unsupported filter 0x%x\n", pPict->filter);
+    }
 
     return TRUE;
 }
 
 Bool
-I965EXACheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
-		      PicturePtr pDstPicture)
+i965_check_composite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+		     PicturePtr pDstPicture)
 {
     CARD32 tmp1;
-    
+
     /* Check for unsupported compositing operations. */
-    if (op >= sizeof(I965BlendOp) / sizeof(I965BlendOp[0]))
+    if (op >= sizeof(i965_blend_op) / sizeof(i965_blend_op[0]))
         I830FALLBACK("Unsupported Composite op 0x%x\n", op);
 
     if (pMaskPicture != NULL && pMaskPicture->componentAlpha) {
@@ -226,20 +228,22 @@ I965EXACheckComposite(int op, PicturePtr
          * the source value.  We can only get one of those into the single
          * source value that we get to blend with.
          */
-        if (I965BlendOp[op].src_alpha &&
-            (I965BlendOp[op].src_blend != BRW_BLENDFACTOR_ZERO))
-            	I830FALLBACK("Component alpha not supported with source "
-                            "alpha and source value blending.\n");
+        if (i965_blend_op[op].src_alpha &&
+            (i965_blend_op[op].src_blend != BRW_BLENDFACTOR_ZERO))
+	{
+	    I830FALLBACK("Component alpha not supported with source "
+			 "alpha and source value blending.\n");
+	}
 	/* XXX: fallback now for mask with componentAlpha */
 	I830FALLBACK("mask componentAlpha not ready.\n");
     }
 
-    if (!I965CheckCompositeTexture(pSrcPicture, 0))
+    if (!i965_check_composite_texture(pSrcPicture, 0))
         I830FALLBACK("Check Src picture texture\n");
-    if (pMaskPicture != NULL && !I965CheckCompositeTexture(pMaskPicture, 1))
+    if (pMaskPicture != NULL && !i965_check_composite_texture(pMaskPicture, 1))
         I830FALLBACK("Check Mask picture texture\n");
 
-    if (!I965GetDestFormat(pDstPicture, &tmp1)) 
+    if (!i965_get_dest_format(pDstPicture, &tmp1))
 	I830FALLBACK("Get Color buffer format\n");
 
     return TRUE;
@@ -260,7 +264,7 @@ static struct brw_surface_state *dest_su
 static struct brw_surface_state *src_surf_state;
 static struct brw_surface_state *mask_surf_state;
 static struct brw_sampler_state *src_sampler_state;
-static struct brw_sampler_state *mask_sampler_state;  
+static struct brw_sampler_state *mask_sampler_state;
 static struct brw_sampler_default_color *default_color_state;
 
 static struct brw_vs_unit_state *vs_state;
@@ -274,7 +278,7 @@ static struct brw_instruction *ps_kernel
 static struct brw_instruction *sip_kernel;
 
 static CARD32 *binding_table;
-static int binding_table_entries; 
+static int binding_table_entries;
 
 static int dest_surf_offset, src_surf_offset, mask_surf_offset;
 static int src_sampler_offset, mask_sampler_offset,vs_offset;
@@ -282,12 +286,12 @@ static int sf_offset, wm_offset, cc_offs
 static int sf_kernel_offset, ps_kernel_offset, sip_kernel_offset;
 static int wm_scratch_offset;
 static int binding_table_offset;
-static int default_color_offset; 
+static int default_color_offset;
 static int next_offset, total_state_size;
 static char *state_base;
 static int state_base_offset;
 static float *vb;
-static int vb_size = (4 * 4) * 4 ; /* 4 DWORDS per vertex*/ 
+static int vb_size = (4 * 4) * 4 ; /* 4 DWORDS per vertex*/
 
 static CARD32 src_blend, dst_blend;
 
@@ -348,20 +352,23 @@ static const CARD32 ps_kernel_static_mas
 #include "exa_wm_masknoca_prog.h"
 };
 
-static CARD32 i965_get_card_format(PicturePtr pPict) 
+static CARD32 i965_get_card_format(PicturePtr pPict)
 {
-	int i;
-        for (i = 0; i < sizeof(I965TexFormats) / sizeof(I965TexFormats[0]); i++) {
-            if (I965TexFormats[i].fmt == pPict->format)
-                break;
-        }
-	return I965TexFormats[i].card_fmt;
+    int i;
+
+    for (i = 0; i < sizeof(i965_tex_formats) / sizeof(i965_tex_formats[0]);
+	 i++)
+    {
+	if (i965_tex_formats[i].fmt == pPict->format)
+	    break;
+    }
+    return i965_tex_formats[i].card_fmt;
 }
 
 Bool
-I965EXAPrepareComposite(int op, PicturePtr pSrcPicture,
-			PicturePtr pMaskPicture, PicturePtr pDstPicture,
-			PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
+i965_prepare_composite(int op, PicturePtr pSrcPicture,
+		       PicturePtr pMaskPicture, PicturePtr pDstPicture,
+		       PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
 {
     ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
@@ -402,235 +409,241 @@ I965EXAPrepareComposite(int op, PictureP
 	pI830->scale_units[1][1] = pMask->drawable.height;
     }
 
-	/* setup 3d pipeline state */
+    /* setup 3d pipeline state */
+
+    binding_table_entries = 2; /* default no mask */
+
+    /* Wait for sync before we start setting up our new state */
+    i830WaitSync(pScrn);
+
+    /* Set up our layout of state in framebuffer.  First the general state: */
+    next_offset = 0;
+    vs_offset = ALIGN(next_offset, 64);
+    next_offset = vs_offset + sizeof(*vs_state);
+
+    sf_offset = ALIGN(next_offset, 32);
+    next_offset = sf_offset + sizeof(*sf_state);
+
+    wm_offset = ALIGN(next_offset, 32);
+    next_offset = wm_offset + sizeof(*wm_state);
 
-   binding_table_entries = 2; /* default no mask */
+    wm_scratch_offset = ALIGN(next_offset, 1024);
+    next_offset = wm_scratch_offset + 1024 * PS_MAX_THREADS;
 
-   /* Wait for sync before we start setting up our new state */
-   i830WaitSync(pScrn);
+    cc_offset = ALIGN(next_offset, 32);
+    next_offset = cc_offset + sizeof(*cc_state);
+
+    /* keep current sf_kernel, which will send one setup urb entry to
+     * PS kernel
+     */
+    sf_kernel_offset = ALIGN(next_offset, 64);
+    if (pMask)
+	next_offset = sf_kernel_offset + sizeof (sf_kernel_static_mask);
+    else
+	next_offset = sf_kernel_offset + sizeof (sf_kernel_static);
 
-   /* Set up our layout of state in framebuffer.  First the general state: */
-   next_offset = 0;
-   vs_offset = ALIGN(next_offset, 64);
-   next_offset = vs_offset + sizeof(*vs_state);
-    
-   sf_offset = ALIGN(next_offset, 32);
-   next_offset = sf_offset + sizeof(*sf_state);
-    
-   wm_offset = ALIGN(next_offset, 32);
-   next_offset = wm_offset + sizeof(*wm_state);
-    
-   wm_scratch_offset = ALIGN(next_offset, 1024);
-   next_offset = wm_scratch_offset + 1024 * PS_MAX_THREADS;
-
-   cc_offset = ALIGN(next_offset, 32);
-   next_offset = cc_offset + sizeof(*cc_state);
-
-   /* keep current sf_kernel, which will send one setup urb entry to
-	PS kernel */
-   sf_kernel_offset = ALIGN(next_offset, 64);
-   if (pMask) 
-       next_offset = sf_kernel_offset + sizeof (sf_kernel_static_mask);
-   else
-       next_offset = sf_kernel_offset + sizeof (sf_kernel_static);
-
-   //XXX: ps_kernel may be seperated, fix with offset
-   ps_kernel_offset = ALIGN(next_offset, 64);
-   if (pMask) {
+    /* XXX: ps_kernel may be seperated, fix with offset */
+    ps_kernel_offset = ALIGN(next_offset, 64);
+    if (pMask) {
 	if (pMaskPicture->componentAlpha)
 	    next_offset = ps_kernel_offset + sizeof(ps_kernel_static_maskca);
-	else 
+	else
 	    next_offset = ps_kernel_offset + sizeof(ps_kernel_static_masknoca);
-   } else 
+    } else {
    	next_offset = ps_kernel_offset + sizeof (ps_kernel_static_nomask);
-    
-   sip_kernel_offset = ALIGN(next_offset, 64);
-   next_offset = sip_kernel_offset + sizeof (sip_kernel_static);
-   
-   // needed?
-   cc_viewport_offset = ALIGN(next_offset, 32);
-   next_offset = cc_viewport_offset + sizeof(*cc_viewport);
-
-   // for texture sampler
-   src_sampler_offset = ALIGN(next_offset, 32);
-   next_offset = src_sampler_offset + sizeof(*src_sampler_state);
+    }
+
+    sip_kernel_offset = ALIGN(next_offset, 64);
+    next_offset = sip_kernel_offset + sizeof (sip_kernel_static);
 
-   if (pMask) {
+    /* needed? */
+    cc_viewport_offset = ALIGN(next_offset, 32);
+    next_offset = cc_viewport_offset + sizeof(*cc_viewport);
+
+    /* for texture sampler */
+    src_sampler_offset = ALIGN(next_offset, 32);
+    next_offset = src_sampler_offset + sizeof(*src_sampler_state);
+
+    if (pMask) {
    	mask_sampler_offset = ALIGN(next_offset, 32);
    	next_offset = mask_sampler_offset + sizeof(*mask_sampler_state);
-   }
-   /* Align VB to native size of elements, for safety */
-   vb_offset = ALIGN(next_offset, 8);
-   next_offset = vb_offset + vb_size;
-
-   /* And then the general state: */
-   dest_surf_offset = ALIGN(next_offset, 32);
-   next_offset = dest_surf_offset + sizeof(*dest_surf_state);
+    }
+    /* Align VB to native size of elements, for safety */
+    vb_offset = ALIGN(next_offset, 8);
+    next_offset = vb_offset + vb_size;
+
+    /* And then the general state: */
+    dest_surf_offset = ALIGN(next_offset, 32);
+    next_offset = dest_surf_offset + sizeof(*dest_surf_state);
 
-   src_surf_offset = ALIGN(next_offset, 32);
-   next_offset = src_surf_offset + sizeof(*src_surf_state);
+    src_surf_offset = ALIGN(next_offset, 32);
+    next_offset = src_surf_offset + sizeof(*src_surf_state);
 
-   if (pMask) {
+    if (pMask) {
    	mask_surf_offset = ALIGN(next_offset, 32);
    	next_offset = mask_surf_offset + sizeof(*mask_surf_state);
 	binding_table_entries = 3;
-   }
+    }
 
-   binding_table_offset = ALIGN(next_offset, 32);
-   next_offset = binding_table_offset + (binding_table_entries * 4);
+    binding_table_offset = ALIGN(next_offset, 32);
+    next_offset = binding_table_offset + (binding_table_entries * 4);
 
-   default_color_offset = ALIGN(next_offset, 32);
-   next_offset = default_color_offset + sizeof(*default_color_state);
+    default_color_offset = ALIGN(next_offset, 32);
+    next_offset = default_color_offset + sizeof(*default_color_state);
 
-   total_state_size = next_offset;
-   assert(total_state_size < EXA_LINEAR_EXTRA);
-
-   state_base_offset = pI830->EXAStateMem.Start;
-   state_base_offset = ALIGN(state_base_offset, 64);
-   state_base = (char *)(pI830->FbBase + state_base_offset);
-
-   vs_state = (void *)(state_base + vs_offset);
-   sf_state = (void *)(state_base + sf_offset);
-   wm_state = (void *)(state_base + wm_offset);
-   cc_state = (void *)(state_base + cc_offset);
-   sf_kernel = (void *)(state_base + sf_kernel_offset);
-   ps_kernel = (void *)(state_base + ps_kernel_offset);
-   sip_kernel = (void *)(state_base + sip_kernel_offset);
-   
-   cc_viewport = (void *)(state_base + cc_viewport_offset);
-   
-   dest_surf_state = (void *)(state_base + dest_surf_offset);
-   src_surf_state = (void *)(state_base + src_surf_offset);
-   if (pMask)
+    total_state_size = next_offset;
+    assert(total_state_size < EXA_LINEAR_EXTRA);
+
+    state_base_offset = pI830->EXAStateMem.Start;
+    state_base_offset = ALIGN(state_base_offset, 64);
+    state_base = (char *)(pI830->FbBase + state_base_offset);
+
+    vs_state = (void *)(state_base + vs_offset);
+    sf_state = (void *)(state_base + sf_offset);
+    wm_state = (void *)(state_base + wm_offset);
+    cc_state = (void *)(state_base + cc_offset);
+    sf_kernel = (void *)(state_base + sf_kernel_offset);
+    ps_kernel = (void *)(state_base + ps_kernel_offset);
+    sip_kernel = (void *)(state_base + sip_kernel_offset);
+
+    cc_viewport = (void *)(state_base + cc_viewport_offset);
+
+    dest_surf_state = (void *)(state_base + dest_surf_offset);
+    src_surf_state = (void *)(state_base + src_surf_offset);
+    if (pMask)
 	mask_surf_state = (void *)(state_base + mask_surf_offset);
 
-   src_sampler_state = (void *)(state_base + src_sampler_offset);
-   if (pMask)
+    src_sampler_state = (void *)(state_base + src_sampler_offset);
+    if (pMask)
 	mask_sampler_state = (void *)(state_base + mask_sampler_offset);
 
-   binding_table = (void *)(state_base + binding_table_offset);
+    binding_table = (void *)(state_base + binding_table_offset);
 
-   vb = (void *)(state_base + vb_offset);
+    vb = (void *)(state_base + vb_offset);
 
-   default_color_state = (void*)(state_base + default_color_offset);
+    default_color_state = (void*)(state_base + default_color_offset);
 
-   /* Set up a default static partitioning of the URB, which is supposed to
-    * allow anything we would want to do, at potentially lower performance.
-    */
+    /* Set up a default static partitioning of the URB, which is supposed to
+     * allow anything we would want to do, at potentially lower performance.
+     */
 #define URB_CS_ENTRY_SIZE     0
 #define URB_CS_ENTRIES	      0
-   
+
 #define URB_VS_ENTRY_SIZE     1	  // each 512-bit row
 #define URB_VS_ENTRIES	      8	  // we needs at least 8 entries
-   
+
 #define URB_GS_ENTRY_SIZE     0
 #define URB_GS_ENTRIES	      0
-   
+
 #define URB_CLIP_ENTRY_SIZE   0
 #define URB_CLIP_ENTRIES      0
-   
+
 #define URB_SF_ENTRY_SIZE     2
 #define URB_SF_ENTRIES	      1
 
-   urb_vs_start = 0;
-   urb_vs_size = URB_VS_ENTRIES * URB_VS_ENTRY_SIZE;
-   urb_gs_start = urb_vs_start + urb_vs_size;
-   urb_gs_size = URB_GS_ENTRIES * URB_GS_ENTRY_SIZE;
-   urb_clip_start = urb_gs_start + urb_gs_size;
-   urb_clip_size = URB_CLIP_ENTRIES * URB_CLIP_ENTRY_SIZE;
-   urb_sf_start = urb_clip_start + urb_clip_size;
-   urb_sf_size = URB_SF_ENTRIES * URB_SF_ENTRY_SIZE;
-   urb_cs_start = urb_sf_start + urb_sf_size;
-   urb_cs_size = URB_CS_ENTRIES * URB_CS_ENTRY_SIZE;
-
-   /* We'll be poking the state buffers that could be in use by the 3d hardware
-    * here, but we should have synced the 3D engine already in I830PutImage.
-    */
+    urb_vs_start = 0;
+    urb_vs_size = URB_VS_ENTRIES * URB_VS_ENTRY_SIZE;
+    urb_gs_start = urb_vs_start + urb_vs_size;
+    urb_gs_size = URB_GS_ENTRIES * URB_GS_ENTRY_SIZE;
+    urb_clip_start = urb_gs_start + urb_gs_size;
+    urb_clip_size = URB_CLIP_ENTRIES * URB_CLIP_ENTRY_SIZE;
+    urb_sf_start = urb_clip_start + urb_clip_size;
+    urb_sf_size = URB_SF_ENTRIES * URB_SF_ENTRY_SIZE;
+    urb_cs_start = urb_sf_start + urb_sf_size;
+    urb_cs_size = URB_CS_ENTRIES * URB_CS_ENTRY_SIZE;
+
+    /* We'll be poking the state buffers that could be in use by the 3d
+     * hardware here, but we should have synced the 3D engine already in
+     * I830PutImage. XXX
+     */
 
-   memset (cc_viewport, 0, sizeof (*cc_viewport));
-   cc_viewport->min_depth = -1.e35;
-   cc_viewport->max_depth = 1.e35;
-
-   /* Color calculator state */
-   memset(cc_state, 0, sizeof(*cc_state));
-   cc_state->cc0.stencil_enable = 0;   /* disable stencil */
-   cc_state->cc2.depth_test = 0;       /* disable depth test */
-   cc_state->cc2.logicop_enable = 0;   /* disable logic op */
-   cc_state->cc3.ia_blend_enable = 1;  /* blend alpha just like colors */
-   cc_state->cc3.blend_enable = 1;     /* enable color blend */
-   cc_state->cc3.alpha_test = 0;       /* disable alpha test */
-   cc_state->cc4.cc_viewport_state_offset = (state_base_offset + cc_viewport_offset) >> 5;
-   cc_state->cc5.dither_enable = 0;    /* disable dither */
-   cc_state->cc5.logicop_func = 0xc;   /* COPY */
-   cc_state->cc5.statistics_enable = 1;
-   cc_state->cc5.ia_blend_function = BRW_BLENDFUNCTION_ADD;
-   I965GetBlendCntl(op, pMaskPicture, pDstPicture->format, 
-		    &src_blend, &dst_blend);
-   /* XXX: alpha blend factor should be same as color, but check
-	   for CA case in future */
-   cc_state->cc5.ia_src_blend_factor = src_blend;
-   cc_state->cc5.ia_dest_blend_factor = dst_blend;
-   cc_state->cc6.blend_function = BRW_BLENDFUNCTION_ADD;
-   cc_state->cc6.src_blend_factor = src_blend;
-   cc_state->cc6.dest_blend_factor = dst_blend;
-   cc_state->cc6.clamp_post_alpha_blend = 1; 
-   cc_state->cc6.clamp_pre_alpha_blend = 1; 
-   cc_state->cc6.clamp_range = 0;  /* clamp range [0,1] */
-
-   /* Upload system kernel */
-   memcpy (sip_kernel, sip_kernel_static, sizeof (sip_kernel_static));
-   
-   /* Set up the state buffer for the destination surface */
-   memset(dest_surf_state, 0, sizeof(*dest_surf_state));
-   dest_surf_state->ss0.surface_type = BRW_SURFACE_2D;
-   dest_surf_state->ss0.data_return_format = BRW_SURFACERETURNFORMAT_FLOAT32;
-   I965GetDestFormat(pDstPicture, &dst_format);
-   dest_surf_state->ss0.surface_format = dst_format;
-
-   dest_surf_state->ss0.writedisable_alpha = 0;
-   dest_surf_state->ss0.writedisable_red = 0;
-   dest_surf_state->ss0.writedisable_green = 0;
-   dest_surf_state->ss0.writedisable_blue = 0;
-   dest_surf_state->ss0.color_blend = 1;
-   dest_surf_state->ss0.vert_line_stride = 0;
-   dest_surf_state->ss0.vert_line_stride_ofs = 0;
-   dest_surf_state->ss0.mipmap_layout_mode = 0;
-   dest_surf_state->ss0.render_cache_read_mode = 0;
-   
-   dest_surf_state->ss1.base_addr = dst_offset;
-   dest_surf_state->ss2.height = pDst->drawable.height - 1;
-   dest_surf_state->ss2.width = pDst->drawable.width - 1;
-   dest_surf_state->ss2.mip_count = 0;
-   dest_surf_state->ss2.render_target_rotation = 0;
-   dest_surf_state->ss3.pitch = dst_pitch - 1; 
-
-   /* Set up the source surface state buffer */
-   memset(src_surf_state, 0, sizeof(*src_surf_state));
-   src_surf_state->ss0.surface_type = BRW_SURFACE_2D;
-   src_surf_state->ss0.surface_format = i965_get_card_format(pSrcPicture);
-
-   src_surf_state->ss0.writedisable_alpha = 0;
-   src_surf_state->ss0.writedisable_red = 0;
-   src_surf_state->ss0.writedisable_green = 0;
-   src_surf_state->ss0.writedisable_blue = 0;
-   src_surf_state->ss0.color_blend = 1;
-   src_surf_state->ss0.vert_line_stride = 0;
-   src_surf_state->ss0.vert_line_stride_ofs = 0;
-   src_surf_state->ss0.mipmap_layout_mode = 0;
-   src_surf_state->ss0.render_cache_read_mode = 0;
-   
-   src_surf_state->ss1.base_addr = src_offset;
-   src_surf_state->ss2.width = pSrc->drawable.width - 1;
-   src_surf_state->ss2.height = pSrc->drawable.height - 1;
-   src_surf_state->ss2.mip_count = 0;
-   src_surf_state->ss2.render_target_rotation = 0;
-   src_surf_state->ss3.pitch = src_pitch - 1; 
+    memset (cc_viewport, 0, sizeof (*cc_viewport));
+    cc_viewport->min_depth = -1.e35;
+    cc_viewport->max_depth = 1.e35;
+
+    /* Color calculator state */
+    memset(cc_state, 0, sizeof(*cc_state));
+    cc_state->cc0.stencil_enable = 0;   /* disable stencil */
+    cc_state->cc2.depth_test = 0;       /* disable depth test */
+    cc_state->cc2.logicop_enable = 0;   /* disable logic op */
+    cc_state->cc3.ia_blend_enable = 1;  /* blend alpha just like colors */
+    cc_state->cc3.blend_enable = 1;     /* enable color blend */
+    cc_state->cc3.alpha_test = 0;       /* disable alpha test */
+    cc_state->cc4.cc_viewport_state_offset = (state_base_offset +
+					      cc_viewport_offset) >> 5;
+    cc_state->cc5.dither_enable = 0;    /* disable dither */
+    cc_state->cc5.logicop_func = 0xc;   /* COPY */
+    cc_state->cc5.statistics_enable = 1;
+    cc_state->cc5.ia_blend_function = BRW_BLENDFUNCTION_ADD;
+    i965_get_blend_cntl(op, pMaskPicture, pDstPicture->format,
+			&src_blend, &dst_blend);
+    /* XXX: alpha blend factor should be same as color, but check
+     * for CA case in future
+     */
+    cc_state->cc5.ia_src_blend_factor = src_blend;
+    cc_state->cc5.ia_dest_blend_factor = dst_blend;
+    cc_state->cc6.blend_function = BRW_BLENDFUNCTION_ADD;
+    cc_state->cc6.src_blend_factor = src_blend;
+    cc_state->cc6.dest_blend_factor = dst_blend;
+    cc_state->cc6.clamp_post_alpha_blend = 1;
+    cc_state->cc6.clamp_pre_alpha_blend = 1;
+    cc_state->cc6.clamp_range = 0;  /* clamp range [0,1] */
+
+    /* Upload system kernel */
+    memcpy (sip_kernel, sip_kernel_static, sizeof (sip_kernel_static));
+
+    /* Set up the state buffer for the destination surface */
+    memset(dest_surf_state, 0, sizeof(*dest_surf_state));
+    dest_surf_state->ss0.surface_type = BRW_SURFACE_2D;
+    dest_surf_state->ss0.data_return_format = BRW_SURFACERETURNFORMAT_FLOAT32;
+    i965_get_dest_format(pDstPicture, &dst_format);
+    dest_surf_state->ss0.surface_format = dst_format;
+
+    dest_surf_state->ss0.writedisable_alpha = 0;
+    dest_surf_state->ss0.writedisable_red = 0;
+    dest_surf_state->ss0.writedisable_green = 0;
+    dest_surf_state->ss0.writedisable_blue = 0;
+    dest_surf_state->ss0.color_blend = 1;
+    dest_surf_state->ss0.vert_line_stride = 0;
+    dest_surf_state->ss0.vert_line_stride_ofs = 0;
+    dest_surf_state->ss0.mipmap_layout_mode = 0;
+    dest_surf_state->ss0.render_cache_read_mode = 0;
+
+    dest_surf_state->ss1.base_addr = dst_offset;
+    dest_surf_state->ss2.height = pDst->drawable.height - 1;
+    dest_surf_state->ss2.width = pDst->drawable.width - 1;
+    dest_surf_state->ss2.mip_count = 0;
+    dest_surf_state->ss2.render_target_rotation = 0;
+    dest_surf_state->ss3.pitch = dst_pitch - 1;
+
+    /* Set up the source surface state buffer */
+    memset(src_surf_state, 0, sizeof(*src_surf_state));
+    src_surf_state->ss0.surface_type = BRW_SURFACE_2D;
+    src_surf_state->ss0.surface_format = i965_get_card_format(pSrcPicture);
+
+    src_surf_state->ss0.writedisable_alpha = 0;
+    src_surf_state->ss0.writedisable_red = 0;
+    src_surf_state->ss0.writedisable_green = 0;
+    src_surf_state->ss0.writedisable_blue = 0;
+    src_surf_state->ss0.color_blend = 1;
+    src_surf_state->ss0.vert_line_stride = 0;
+    src_surf_state->ss0.vert_line_stride_ofs = 0;
+    src_surf_state->ss0.mipmap_layout_mode = 0;
+    src_surf_state->ss0.render_cache_read_mode = 0;
+
+    src_surf_state->ss1.base_addr = src_offset;
+    src_surf_state->ss2.width = pSrc->drawable.width - 1;
+    src_surf_state->ss2.height = pSrc->drawable.height - 1;
+    src_surf_state->ss2.mip_count = 0;
+    src_surf_state->ss2.render_target_rotation = 0;
+    src_surf_state->ss3.pitch = src_pitch - 1;
 
-   /* setup mask surface */
-   if (pMask) {
+    /* setup mask surface */
+    if (pMask) {
    	memset(mask_surf_state, 0, sizeof(*mask_surf_state));
 	mask_surf_state->ss0.surface_type = BRW_SURFACE_2D;
-   	mask_surf_state->ss0.surface_format = i965_get_card_format(pMaskPicture);
+   	mask_surf_state->ss0.surface_format =
+	    i965_get_card_format(pMaskPicture);
 
    	mask_surf_state->ss0.writedisable_alpha = 0;
    	mask_surf_state->ss0.writedisable_red = 0;
@@ -641,68 +654,68 @@ I965EXAPrepareComposite(int op, PictureP
    	mask_surf_state->ss0.vert_line_stride_ofs = 0;
    	mask_surf_state->ss0.mipmap_layout_mode = 0;
    	mask_surf_state->ss0.render_cache_read_mode = 0;
-   
+
    	mask_surf_state->ss1.base_addr = mask_offset;
    	mask_surf_state->ss2.width = pMask->drawable.width - 1;
    	mask_surf_state->ss2.height = pMask->drawable.height - 1;
    	mask_surf_state->ss2.mip_count = 0;
    	mask_surf_state->ss2.render_target_rotation = 0;
-   	mask_surf_state->ss3.pitch = mask_pitch - 1; 
-   }
+   	mask_surf_state->ss3.pitch = mask_pitch - 1;
+    }
 
-   /* Set up a binding table for our surfaces.  Only the PS will use it */
-   binding_table[0] = state_base_offset + dest_surf_offset;
-   binding_table[1] = state_base_offset + src_surf_offset;
-   if (pMask)
+    /* Set up a binding table for our surfaces.  Only the PS will use it */
+    binding_table[0] = state_base_offset + dest_surf_offset;
+    binding_table[1] = state_base_offset + src_surf_offset;
+    if (pMask)
    	binding_table[2] = state_base_offset + mask_surf_offset;
 
-   /* PS kernel use this sampler */
-   memset(src_sampler_state, 0, sizeof(*src_sampler_state));
-   src_sampler_state->ss0.lod_preclamp = 1; /* GL mode */
-   switch(pSrcPicture->filter) {
-   case PictFilterNearest:
-   	src_sampler_state->ss0.min_filter = BRW_MAPFILTER_NEAREST; 
+    /* PS kernel use this sampler */
+    memset(src_sampler_state, 0, sizeof(*src_sampler_state));
+    src_sampler_state->ss0.lod_preclamp = 1; /* GL mode */
+    switch(pSrcPicture->filter) {
+    case PictFilterNearest:
+   	src_sampler_state->ss0.min_filter = BRW_MAPFILTER_NEAREST;
    	src_sampler_state->ss0.mag_filter = BRW_MAPFILTER_NEAREST;
 	break;
-   case PictFilterBilinear:
-   	src_sampler_state->ss0.min_filter = BRW_MAPFILTER_LINEAR; 
+    case PictFilterBilinear:
+	src_sampler_state->ss0.min_filter = BRW_MAPFILTER_LINEAR;
    	src_sampler_state->ss0.mag_filter = BRW_MAPFILTER_LINEAR;
 	break;
-   default:
+    default:
 	I830FALLBACK("Bad filter 0x%x\n", pSrcPicture->filter);
-   }
+    }
 
-   memset(default_color_state, 0, sizeof(*default_color_state));
-   default_color_state->color[0] = 0.0; /* R */
-   default_color_state->color[1] = 0.0; /* G */
-   default_color_state->color[2] = 0.0; /* B */
-   default_color_state->color[3] = 1.0; /* A */
+    memset(default_color_state, 0, sizeof(*default_color_state));
+    default_color_state->color[0] = 0.0; /* R */
+    default_color_state->color[1] = 0.0; /* G */
+    default_color_state->color[2] = 0.0; /* B */
+    default_color_state->color[3] = 1.0; /* A */
 
-   src_sampler_state->ss0.default_color_mode = 0; /* GL mode */
+    src_sampler_state->ss0.default_color_mode = 0; /* GL mode */
 
-   if (!pSrcPicture->repeat) {
-   	src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER; 
+    if (!pSrcPicture->repeat) {
+   	src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER;
    	src_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER;
    	src_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER;
-	src_sampler_state->ss2.default_color_pointer = 
-			(state_base_offset + default_color_offset) >> 5;
-   } else {
-   	src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_WRAP; 
+	src_sampler_state->ss2.default_color_pointer =
+	    (state_base_offset + default_color_offset) >> 5;
+    } else {
+   	src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_WRAP;
    	src_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_WRAP;
    	src_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_WRAP;
-   }
-   src_sampler_state->ss3.chroma_key_enable = 0; /* disable chromakey */
+    }
+    src_sampler_state->ss3.chroma_key_enable = 0; /* disable chromakey */
 
-   if (pMask) {
+    if (pMask) {
    	memset(mask_sampler_state, 0, sizeof(*mask_sampler_state));
    	mask_sampler_state->ss0.lod_preclamp = 1; /* GL mode */
    	switch(pMaskPicture->filter) {
    	case PictFilterNearest:
-   	    mask_sampler_state->ss0.min_filter = BRW_MAPFILTER_NEAREST; 
+   	    mask_sampler_state->ss0.min_filter = BRW_MAPFILTER_NEAREST;
    	    mask_sampler_state->ss0.mag_filter = BRW_MAPFILTER_NEAREST;
 	    break;
    	case PictFilterBilinear:
-   	    mask_sampler_state->ss0.min_filter = BRW_MAPFILTER_LINEAR; 
+   	    mask_sampler_state->ss0.min_filter = BRW_MAPFILTER_LINEAR;
    	    mask_sampler_state->ss0.mag_filter = BRW_MAPFILTER_LINEAR;
 	    break;
    	default:
@@ -710,189 +723,203 @@ I965EXAPrepareComposite(int op, PictureP
    	}
 
    	if (!pMaskPicture->repeat) {
-   	    mask_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER; 
-   	    mask_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER;
-   	    mask_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER;
-            mask_sampler_state->ss2.default_color_pointer = 
-				(state_base_offset + default_color_offset)>>5;
+   	    mask_sampler_state->ss1.r_wrap_mode =
+		BRW_TEXCOORDMODE_CLAMP_BORDER;
+   	    mask_sampler_state->ss1.s_wrap_mode =
+		BRW_TEXCOORDMODE_CLAMP_BORDER;
+   	    mask_sampler_state->ss1.t_wrap_mode =
+		BRW_TEXCOORDMODE_CLAMP_BORDER;
+            mask_sampler_state->ss2.default_color_pointer =
+		(state_base_offset + default_color_offset)>>5;
    	} else {
-   	    mask_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_WRAP; 
+   	    mask_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_WRAP;
    	    mask_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_WRAP;
    	    mask_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_WRAP;
     	}
    	mask_sampler_state->ss3.chroma_key_enable = 0; /* disable chromakey */
-   }
+    }
 
-   /* Set up the vertex shader to be disabled (passthrough) */
-   memset(vs_state, 0, sizeof(*vs_state));
-   vs_state->thread4.nr_urb_entries = URB_VS_ENTRIES;
-   vs_state->thread4.urb_entry_allocation_size = URB_VS_ENTRY_SIZE - 1;
-   vs_state->vs6.vs_enable = 0;
-   vs_state->vs6.vert_cache_disable = 1;
-
-   // XXX: sf_kernel? keep it as now
-   /* Set up the SF kernel to do coord interp: for each attribute,
-    * calculate dA/dx and dA/dy.  Hand these interpolation coefficients
-    * back to SF which then hands pixels off to WM.
-    */
-   if (pMask) 
-       memcpy (sf_kernel, sf_kernel_static_mask, sizeof (sf_kernel_static));
-   else
-       memcpy (sf_kernel, sf_kernel_static, sizeof (sf_kernel_static));
-
-   memset(sf_state, 0, sizeof(*sf_state));
-   sf_state->thread0.kernel_start_pointer = 
-	       (state_base_offset + sf_kernel_offset) >> 6;
-   sf_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(SF_KERNEL_NUM_GRF);
-   sf_state->sf1.single_program_flow = 1;
-   sf_state->sf1.binding_table_entry_count = 0;
-   sf_state->sf1.thread_priority = 0;
-   sf_state->sf1.floating_point_mode = 0; /* Mesa does this */
-   sf_state->sf1.illegal_op_exception_enable = 1;
-   sf_state->sf1.mask_stack_exception_enable = 1;
-   sf_state->sf1.sw_exception_enable = 1;
-   sf_state->thread2.per_thread_scratch_space = 0;
-   sf_state->thread2.scratch_space_base_pointer = 0; /* not used in our kernel */
-   sf_state->thread3.const_urb_entry_read_length = 0; /* no const URBs */
-   sf_state->thread3.const_urb_entry_read_offset = 0; /* no const URBs */
-   sf_state->thread3.urb_entry_read_length = 1; /* 1 URB per vertex */
-   sf_state->thread3.urb_entry_read_offset = 0;
-   sf_state->thread3.dispatch_grf_start_reg = 3;
-   sf_state->thread4.max_threads = SF_MAX_THREADS - 1;
-   sf_state->thread4.urb_entry_allocation_size = URB_SF_ENTRY_SIZE - 1;
-   sf_state->thread4.nr_urb_entries = URB_SF_ENTRIES;
-   sf_state->thread4.stats_enable = 1;
-   sf_state->sf5.viewport_transform = FALSE; /* skip viewport */
-   sf_state->sf6.cull_mode = BRW_CULLMODE_NONE;
-   sf_state->sf6.scissor = 0;
-   sf_state->sf7.trifan_pv = 2;
-   sf_state->sf6.dest_org_vbias = 0x8;
-   sf_state->sf6.dest_org_hbias = 0x8;
+    /* Set up the vertex shader to be disabled (passthrough) */
+    memset(vs_state, 0, sizeof(*vs_state));
+    vs_state->thread4.nr_urb_entries = URB_VS_ENTRIES;
+    vs_state->thread4.urb_entry_allocation_size = URB_VS_ENTRY_SIZE - 1;
+    vs_state->vs6.vs_enable = 0;
+    vs_state->vs6.vert_cache_disable = 1;
+
+    /* XXX: sf_kernel? keep it as now */
+    /* Set up the SF kernel to do coord interp: for each attribute,
+     * calculate dA/dx and dA/dy.  Hand these interpolation coefficients
+     * back to SF which then hands pixels off to WM.
+     */
+    if (pMask)
+	memcpy(sf_kernel, sf_kernel_static_mask, sizeof (sf_kernel_static));
+    else
+	memcpy(sf_kernel, sf_kernel_static, sizeof (sf_kernel_static));
+
+    memset(sf_state, 0, sizeof(*sf_state));
+    sf_state->thread0.kernel_start_pointer =
+	(state_base_offset + sf_kernel_offset) >> 6;
+    sf_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(SF_KERNEL_NUM_GRF);
+    sf_state->sf1.single_program_flow = 1;
+    sf_state->sf1.binding_table_entry_count = 0;
+    sf_state->sf1.thread_priority = 0;
+    sf_state->sf1.floating_point_mode = 0; /* Mesa does this */
+    sf_state->sf1.illegal_op_exception_enable = 1;
+    sf_state->sf1.mask_stack_exception_enable = 1;
+    sf_state->sf1.sw_exception_enable = 1;
+    sf_state->thread2.per_thread_scratch_space = 0;
+    /* scratch space is not used in our kernel */
+    sf_state->thread2.scratch_space_base_pointer = 0;
+    sf_state->thread3.const_urb_entry_read_length = 0; /* no const URBs */
+    sf_state->thread3.const_urb_entry_read_offset = 0; /* no const URBs */
+    sf_state->thread3.urb_entry_read_length = 1; /* 1 URB per vertex */
+    sf_state->thread3.urb_entry_read_offset = 0;
+    sf_state->thread3.dispatch_grf_start_reg = 3;
+    sf_state->thread4.max_threads = SF_MAX_THREADS - 1;
+    sf_state->thread4.urb_entry_allocation_size = URB_SF_ENTRY_SIZE - 1;
+    sf_state->thread4.nr_urb_entries = URB_SF_ENTRIES;
+    sf_state->thread4.stats_enable = 1;
+    sf_state->sf5.viewport_transform = FALSE; /* skip viewport */
+    sf_state->sf6.cull_mode = BRW_CULLMODE_NONE;
+    sf_state->sf6.scissor = 0;
+    sf_state->sf7.trifan_pv = 2;
+    sf_state->sf6.dest_org_vbias = 0x8;
+    sf_state->sf6.dest_org_hbias = 0x8;
 
-   /* Set up the PS kernel (dispatched by WM) 
-    */
-    
-   if (pMask) {
+   /* Set up the PS kernel (dispatched by WM) */
+    if (pMask) {
 	if (pMaskPicture->componentAlpha)
-   	    memcpy (ps_kernel, ps_kernel_static_maskca, sizeof (ps_kernel_static_maskca));
+   	    memcpy(ps_kernel, ps_kernel_static_maskca,
+		   sizeof (ps_kernel_static_maskca));
 	else
-   	    memcpy (ps_kernel, ps_kernel_static_masknoca, sizeof (ps_kernel_static_masknoca));
-   } else 
-   	memcpy (ps_kernel, ps_kernel_static_nomask, sizeof (ps_kernel_static_nomask));
-
-   memset (wm_state, 0, sizeof (*wm_state));
-   wm_state->thread0.kernel_start_pointer = 
-	    (state_base_offset + ps_kernel_offset) >> 6;
-   wm_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(PS_KERNEL_NUM_GRF);
-   wm_state->thread1.single_program_flow = 1;
-   if (!pMask)
-       wm_state->thread1.binding_table_entry_count = 2; /* 1 tex and fb */
-   else
-       wm_state->thread1.binding_table_entry_count = 3; /* 2 tex and fb */
-
-   wm_state->thread2.scratch_space_base_pointer = (state_base_offset + 
-						   wm_scratch_offset)>>10;
-   wm_state->thread2.per_thread_scratch_space = 0;
-   // XXX: urb allocation
-   wm_state->thread3.const_urb_entry_read_length = 0;
-   wm_state->thread3.const_urb_entry_read_offset = 0;
-   if (pMask)
-       wm_state->thread3.urb_entry_read_length = 2;  /* two per pair of attrib */
-   else 
-       wm_state->thread3.urb_entry_read_length = 1;  /* one per pair of attrib */
-   wm_state->thread3.urb_entry_read_offset = 0;
-   // wm kernel use urb from 3, see wm_program in compiler module
-   wm_state->thread3.dispatch_grf_start_reg = 3; /* must match kernel */
-
-   wm_state->wm4.stats_enable = 1;  /* statistic */
-   wm_state->wm4.sampler_state_pointer = (state_base_offset + src_sampler_offset) >> 5; 
-   wm_state->wm4.sampler_count = 1; /* 1-4 samplers used */
-   wm_state->wm5.max_threads = PS_MAX_THREADS - 1;
-   wm_state->wm5.thread_dispatch_enable = 1;
-   //just use 16-pixel dispatch (4 subspans), don't need to change kernel start point
-   wm_state->wm5.enable_16_pix = 1;
-   wm_state->wm5.enable_8_pix = 0;
-   wm_state->wm5.early_depth_test = 1;
+   	    memcpy(ps_kernel, ps_kernel_static_masknoca,
+		   sizeof (ps_kernel_static_masknoca));
+    } else {
+   	memcpy(ps_kernel, ps_kernel_static_nomask,
+	       sizeof (ps_kernel_static_nomask));
+    }
 
-   /* Begin the long sequence of commands needed to set up the 3D 
-    * rendering pipe
-    */
-   {
+    memset(wm_state, 0, sizeof (*wm_state));
+    wm_state->thread0.kernel_start_pointer =
+	(state_base_offset + ps_kernel_offset) >> 6;
+    wm_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(PS_KERNEL_NUM_GRF);
+    wm_state->thread1.single_program_flow = 1;
+    if (!pMask)
+	wm_state->thread1.binding_table_entry_count = 2; /* 1 tex and fb */
+    else
+	wm_state->thread1.binding_table_entry_count = 3; /* 2 tex and fb */
+
+    wm_state->thread2.scratch_space_base_pointer = (state_base_offset +
+						    wm_scratch_offset)>>10;
+    wm_state->thread2.per_thread_scratch_space = 0;
+    // XXX: urb allocation
+    wm_state->thread3.const_urb_entry_read_length = 0;
+    wm_state->thread3.const_urb_entry_read_offset = 0;
+    /* Each pair of attributes (src/mask coords) is one URB entry */
+    if (pMask)
+	wm_state->thread3.urb_entry_read_length = 2;
+    else
+	wm_state->thread3.urb_entry_read_length = 1;
+    wm_state->thread3.urb_entry_read_offset = 0;
+    /* wm kernel use urb from 3, see wm_program in compiler module */
+    wm_state->thread3.dispatch_grf_start_reg = 3; /* must match kernel */
+
+    wm_state->wm4.stats_enable = 1;  /* statistic */
+    wm_state->wm4.sampler_state_pointer = (state_base_offset +
+					   src_sampler_offset) >> 5;
+    wm_state->wm4.sampler_count = 1; /* 1-4 samplers used */
+    wm_state->wm5.max_threads = PS_MAX_THREADS - 1;
+    wm_state->wm5.thread_dispatch_enable = 1;
+    /* just use 16-pixel dispatch (4 subspans), don't need to change kernel
+     * start point
+     */
+    wm_state->wm5.enable_16_pix = 1;
+    wm_state->wm5.enable_8_pix = 0;
+    wm_state->wm5.early_depth_test = 1;
+
+    /* Begin the long sequence of commands needed to set up the 3D
+     * rendering pipe
+     */
+    {
 	BEGIN_LP_RING(2);
-   	OUT_RING(MI_FLUSH | 
-	    MI_STATE_INSTRUCTION_CACHE_FLUSH |
-	    BRW_MI_GLOBAL_SNAPSHOT_RESET);
+   	OUT_RING(MI_FLUSH |
+		 MI_STATE_INSTRUCTION_CACHE_FLUSH |
+		 BRW_MI_GLOBAL_SNAPSHOT_RESET);
 	OUT_RING(MI_NOOP);
 	ADVANCE_LP_RING();
-   }
-   {
+    }
+    {
         BEGIN_LP_RING(12);
-   
+
         /* Match Mesa driver setup */
         OUT_RING(BRW_PIPELINE_SELECT | PIPELINE_SELECT_3D);
-   
+
    	OUT_RING(BRW_CS_URB_STATE | 0);
    	OUT_RING((0 << 4) |  /* URB Entry Allocation Size */
-            (0 << 0));  /* Number of URB Entries */
+		 (0 << 0));  /* Number of URB Entries */
 
-   /* Zero out the two base address registers so all offsets are absolute */
+	/* Zero out the two base address registers so all offsets are
+	 * absolute.
+	 */
    	OUT_RING(BRW_STATE_BASE_ADDRESS | 4);
    	OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* Generate state base address */
    	OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* Surface state base address */
    	OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* media base addr, don't care */
-   	OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY);  /* general state max addr, disabled */
-   	OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY);  /* media object state max addr, disabled */
+	/* general state max addr, disabled */
+   	OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY);
+	/* media object state max addr, disabled */
+   	OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY);
 
-   /* Set system instruction pointer */
+	/* Set system instruction pointer */
    	OUT_RING(BRW_STATE_SIP | 0);
-   	OUT_RING(state_base_offset + sip_kernel_offset); /* system instruction pointer */
+   	OUT_RING(state_base_offset + sip_kernel_offset);
 	OUT_RING(MI_NOOP);
 	ADVANCE_LP_RING();
-   }
-   {
+    }
+    {
 	BEGIN_LP_RING(26);
-   /* Pipe control */
+	/* Pipe control */
    	OUT_RING(BRW_PIPE_CONTROL |
-	    BRW_PIPE_CONTROL_NOWRITE |
-	    BRW_PIPE_CONTROL_IS_FLUSH |
-	    2);
+		 BRW_PIPE_CONTROL_NOWRITE |
+		 BRW_PIPE_CONTROL_IS_FLUSH |
+		 2);
    	OUT_RING(0);			       /* Destination address */
    	OUT_RING(0);			       /* Immediate data low DW */
    	OUT_RING(0);			       /* Immediate data high DW */
 
-   /* Binding table pointers */
+	/* Binding table pointers */
    	OUT_RING(BRW_3DSTATE_BINDING_TABLE_POINTERS | 4);
    	OUT_RING(0); /* vs */
    	OUT_RING(0); /* gs */
    	OUT_RING(0); /* clip */
    	OUT_RING(0); /* sf */
-   /* Only the PS uses the binding table */
+	/* Only the PS uses the binding table */
    	OUT_RING(state_base_offset + binding_table_offset); /* ps */
 
-   /* The drawing rectangle clipping is always on.  Set it to values that
-    * shouldn't do any clipping.
-    */
-   	OUT_RING(BRW_3DSTATE_DRAWING_RECTANGLE | 2);	/* XXX 3 for BLC or CTG */
+	/* The drawing rectangle clipping is always on.  Set it to values that
+	 * shouldn't do any clipping.
+	 */
+   	OUT_RING(BRW_3DSTATE_DRAWING_RECTANGLE | 2); /* XXX 3 for BLC or CTG */
    	OUT_RING(0x00000000);	/* ymin, xmin */
    	OUT_RING((pScrn->virtualX - 1) |
  	         (pScrn->virtualY - 1) << 16); /* ymax, xmax */
    	OUT_RING(0x00000000);	/* yorigin, xorigin */
 
-   /* skip the depth buffer */
-   /* skip the polygon stipple */
-   /* skip the polygon stipple offset */
-   /* skip the line stipple */
-   
-   /* Set the pointers to the 3d pipeline state */
+	/* skip the depth buffer */
+	/* skip the polygon stipple */
+	/* skip the polygon stipple offset */
+	/* skip the line stipple */
+
+	/* Set the pointers to the 3d pipeline state */
    	OUT_RING(BRW_3DSTATE_PIPELINED_POINTERS | 5);
    	OUT_RING(state_base_offset + vs_offset);  /* 32 byte aligned */
-   	OUT_RING(BRW_GS_DISABLE);		     /* disable GS, resulting in passthrough */
-   	OUT_RING(BRW_CLIP_DISABLE);		     /* disable CLIP, resulting in passthrough */
+   	OUT_RING(BRW_GS_DISABLE);   /* disable GS, resulting in passthrough */
+   	OUT_RING(BRW_CLIP_DISABLE); /* disable CLIP, resulting in passthrough */
    	OUT_RING(state_base_offset + sf_offset);  /* 32 byte aligned */
    	OUT_RING(state_base_offset + wm_offset);  /* 32 byte aligned */
    	OUT_RING(state_base_offset + cc_offset);  /* 64 byte aligned */
 
-   /* URB fence */
+	/* URB fence */
    	OUT_RING(BRW_URB_FENCE |
         	 UF0_CS_REALLOC |
 	    	 UF0_SF_REALLOC |
@@ -906,27 +933,28 @@ I965EXAPrepareComposite(int op, PictureP
    	OUT_RING(((urb_cs_start + urb_cs_size) << UF2_CS_FENCE_SHIFT) |
 	     	 ((urb_sf_start + urb_sf_size) << UF2_SF_FENCE_SHIFT));
 
-   /* Constant buffer state */
+	/* Constant buffer state */
    	OUT_RING(BRW_CS_URB_STATE | 0);
-   	OUT_RING(((URB_CS_ENTRY_SIZE - 1) << 4) | /* URB Entry Allocation Size */
-	    	 (URB_CS_ENTRIES << 0));	     /* Number of URB Entries */
+   	OUT_RING(((URB_CS_ENTRY_SIZE - 1) << 4) |
+	    	 (URB_CS_ENTRIES << 0));
 	ADVANCE_LP_RING();
-   }
-   {
+    }
+    {
         int nelem = pMask ? 3: 2;
    	BEGIN_LP_RING(pMask?12:10);
-   /* Set up the pointer to our vertex buffer */
-   	OUT_RING(BRW_3DSTATE_VERTEX_BUFFERS | 3); 
+	/* Set up the pointer to our vertex buffer */
+   	OUT_RING(BRW_3DSTATE_VERTEX_BUFFERS | 3);
    	OUT_RING((0 << VB0_BUFFER_INDEX_SHIFT) |
 	    	 VB0_VERTEXDATA |
-	    	 ((4 * 2 * nelem) << VB0_BUFFER_PITCH_SHIFT)); 
+	    	 ((4 * 2 * nelem) << VB0_BUFFER_PITCH_SHIFT));
    	OUT_RING(state_base_offset + vb_offset);
    	OUT_RING(2); // max index, prim has 4 coords
    	OUT_RING(0); // ignore for VERTEXDATA, but still there
 
-   /* Set up our vertex elements, sourced from the single vertex buffer. */
-   	OUT_RING(BRW_3DSTATE_VERTEX_ELEMENTS | ((2 * nelem) - 1));  
-   /* offset 0: X,Y -> {X, Y, 1.0, 1.0} */
+	/* Set up our vertex elements, sourced from the single vertex buffer.
+	 */
+   	OUT_RING(BRW_3DSTATE_VERTEX_ELEMENTS | ((2 * nelem) - 1));
+	/* offset 0: X,Y -> {X, Y, 1.0, 1.0} */
    	OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
 	    	 VE0_VALID |
 	    	 (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
@@ -936,7 +964,7 @@ I965EXAPrepareComposite(int op, PictureP
 	     	 (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
 	    	 (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
 	    	 (0 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
-   /* offset 8: S0, T0 -> {S0, T0, 1.0, 1.0} */
+	/* offset 8: S0, T0 -> {S0, T0, 1.0, 1.0} */
    	OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
 	    	 VE0_VALID |
 	    	 (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
@@ -948,30 +976,30 @@ I965EXAPrepareComposite(int op, PictureP
 	    	 (4 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
 
    	if (pMask) {
-   		OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
-	    		 VE0_VALID |
-	    		 (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
-	    		 (16 << VE0_OFFSET_SHIFT));
-		OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
-	    		 (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
-	    		 (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
-	    		 (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
-	    		 (8 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); 
+	    OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
+		     VE0_VALID |
+		     (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
+		     (16 << VE0_OFFSET_SHIFT));
+	    OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
+		     (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
+		     (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
+		     (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
+		     (8 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
    	}
-   
+
    	ADVANCE_LP_RING();
-   }
+    }
 
 #ifdef I830DEBUG
     ErrorF("try to sync to show any errors...");
     I830Sync(pScrn);
 #endif
     return TRUE;
-}	
+}
 
 void
-I965EXAComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
-		int dstX, int dstY, int w, int h)
+i965_composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
+	       int dstX, int dstY, int w, int h)
 {
     ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
@@ -1039,12 +1067,12 @@ I965EXAComposite(PixmapPtr pDst, int src
     }
     vb[i++] = (float)dstX;
     vb[i++] = (float)dstY;
-   
+
     {
       BEGIN_LP_RING(6);
-      OUT_RING(BRW_3DPRIMITIVE | 
+      OUT_RING(BRW_3DPRIMITIVE |
 	       BRW_3DPRIMITIVE_VERTEX_SEQUENTIAL |
-	       (_3DPRIM_RECTLIST << BRW_3DPRIMITIVE_TOPOLOGY_SHIFT) | 
+	       (_3DPRIM_RECTLIST << BRW_3DPRIMITIVE_TOPOLOGY_SHIFT) |
 	       (0 << 9) |  /* CTG - indirect vertex count */
 	       4);
       OUT_RING(3);  /* vertex count per instance */
diff-tree c47210d94ed17ad9e8e489a1e1886732e6dc7220 (from 72ea0e514dcbebd009833c21f40e9bfb84074628)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Jan 31 12:50:31 2007 -0800

    Move the render code to non-EXA-specific filenames.

diff --git a/src/Makefile.am b/src/Makefile.am
index ba12635..7656e02 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -92,9 +92,9 @@ i810_drv_la_SOURCES = \
 	 i965_video.c \
 	 i830_exa.c \
 	 i830_xaa.c \
-	 i830_exa_render.c \
-	 i915_exa_render.c \
-	 i965_exa_render.c
+	 i830_render.c \
+	 i915_render.c \
+	 i965_render.c
 
 if HAVE_GEN4ASM
 sf_prog.h: packed_yuv_sf.g4a
diff --git a/src/common.h b/src/common.h
index 561dfac..91e31b5 100644
--- a/src/common.h
+++ b/src/common.h
@@ -130,6 +130,17 @@ extern void I830DPRINTF_stub(const char 
    outring &= ringmask;							\
 } while (0)
 
+union intfloat {
+	float f;
+	unsigned int ui;
+};
+
+#define OUT_RING_F(x) do {			\
+	union intfloat tmp;			\
+	tmp.f = (float)(x);			\
+	OUT_RING(tmp.ui);			\
+} while(0)				
+
 #define ADVANCE_LP_RING() do {						\
    if (ringused > needed)          \
       FatalError("%s: ADVANCE_LP_RING: exceeded allocation %d/%d\n ",	\
diff --git a/src/i830_exa.c b/src/i830_exa.c
index 02d2dcf..8a1577a 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -97,18 +97,6 @@ const int I830PatternROP[16] =
     ROP_1
 };
 
-/* move to common.h */
-union intfloat {
-	float f;
-	unsigned int ui;
-};
-
-#define OUT_RING_F(x) do {			\
-	union intfloat tmp;			\
-	tmp.f = (float)(x);			\
-	OUT_RING(tmp.ui);			\
-} while(0)				
-
 /**
  * I830EXASync - wait for a command to finish
  * @pScreen: current screen
@@ -309,103 +297,6 @@ i830_get_transformed_coordinates(int x, 
     }
 }
 
-/**
- * Do a single rectangle composite operation.
- *
- * This function is shared between i830 and i915 generation code.
- */
-void
-IntelEXAComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
-		 int dstX, int dstY, int w, int h)
-{
-    ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
-    I830Ptr pI830 = I830PTR(pScrn);
-    Bool has_mask;
-    float src_x[3], src_y[3], mask_x[3], mask_y[3];
-
-    i830_get_transformed_coordinates(srcX, srcY,
-				     pI830->transform[0],
-				     &src_x[0], &src_y[0]);
-    i830_get_transformed_coordinates(srcX, srcY + h,
-				     pI830->transform[0],
-				     &src_x[1], &src_y[1]);
-    i830_get_transformed_coordinates(srcX + w, srcY + h,
-				     pI830->transform[0],
-				     &src_x[2], &src_y[2]);
-
-    if (pI830->scale_units[1][0] == -1 || pI830->scale_units[1][1] == -1) {
-	has_mask = FALSE;
-    } else {
-	has_mask = TRUE;
-	i830_get_transformed_coordinates(maskX, maskY,
-					 pI830->transform[1],
-					 &mask_x[0], &mask_y[0]);
-	i830_get_transformed_coordinates(maskX, maskY + h,
-					 pI830->transform[1],
-					 &mask_x[1], &mask_y[1]);
-	i830_get_transformed_coordinates(maskX + w, maskY + h,
-					 pI830->transform[1],
-					 &mask_x[2], &mask_y[2]);
-    }
-
-    {
-	int vertex_count; 
-
-	if (has_mask)
-		vertex_count = 3*6;
-	else
-		vertex_count = 3*4;
-
-	BEGIN_LP_RING(6+vertex_count);
-
-	OUT_RING(MI_NOOP);
-	OUT_RING(MI_NOOP);
-	OUT_RING(MI_NOOP);
-	OUT_RING(MI_NOOP);
-	OUT_RING(MI_NOOP);
-
-	OUT_RING(PRIM3D_INLINE | PRIM3D_RECTLIST | (vertex_count-1));
-
-	OUT_RING_F(dstX);
-	OUT_RING_F(dstY);
-	OUT_RING_F(src_x[0] / pI830->scale_units[0][0]);
-	OUT_RING_F(src_y[0] / pI830->scale_units[0][1]);
-	if (has_mask) {
-		OUT_RING_F(mask_x[0] / pI830->scale_units[1][0]);
-		OUT_RING_F(mask_y[0] / pI830->scale_units[1][1]);
-	}
-
-	OUT_RING_F(dstX);
-	OUT_RING_F(dstY + h);
-	OUT_RING_F(src_x[1] / pI830->scale_units[0][0]);
-	OUT_RING_F(src_y[1] / pI830->scale_units[0][1]);
-	if (has_mask) {
-		OUT_RING_F(mask_x[1] / pI830->scale_units[1][0]);
-		OUT_RING_F(mask_y[1] / pI830->scale_units[1][1]);
-	}
-
-	OUT_RING_F(dstX + w);
-	OUT_RING_F(dstY + h);
-	OUT_RING_F(src_x[2] / pI830->scale_units[0][0]);
-	OUT_RING_F(src_y[2] / pI830->scale_units[0][1]);
-	if (has_mask) {
-		OUT_RING_F(mask_x[2] / pI830->scale_units[1][0]);
-		OUT_RING_F(mask_y[2] / pI830->scale_units[1][1]);
-	}
-	ADVANCE_LP_RING();
-    }
-}
-
-void
-IntelEXADoneComposite(PixmapPtr pDst)
-{
-#if ALWAYS_SYNC
-    ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
-
-    I830Sync(pScrn);
-#endif
-}
-
 /*
  * TODO:
  *   - Dual head?
diff --git a/src/i830_exa_render.c b/src/i830_exa_render.c
deleted file mode 100644
index bf521b4..0000000
--- a/src/i830_exa_render.c
+++ /dev/null
@@ -1,494 +0,0 @@
-/*
- * Copyright © 2006 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Authors:
- *    Wang Zhenyu <zhenyu.z.wang at intel.com>
- *    Eric Anholt <eric at anholt.net>
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "xf86.h"
-#include "i830.h"
-#include "i830_reg.h"
-
-#ifdef I830DEBUG
-#define DEBUG_I830FALLBACK 1
-#endif
-
-#ifdef DEBUG_I830FALLBACK
-#define I830FALLBACK(s, arg...)				\
-do {							\
-	DPRINTF(PFX, "EXA fallback: " s "\n", ##arg); 	\
-	return FALSE;					\
-} while(0)
-#else
-#define I830FALLBACK(s, arg...) 			\
-do { 							\
-	return FALSE;					\
-} while(0) 
-#endif
-
-struct blendinfo {
-    Bool dst_alpha;
-    Bool src_alpha;
-    CARD32 src_blend;
-    CARD32 dst_blend;
-};
-
-struct formatinfo {
-    int fmt;
-    CARD32 card_fmt;
-};
-
-#define TB0C_LAST_STAGE	(1 << 31)
-#define TB0C_RESULT_SCALE_1X		(0 << 29)
-#define TB0C_RESULT_SCALE_2X		(1 << 29)
-#define TB0C_RESULT_SCALE_4X		(2 << 29)
-#define TB0C_OP_MODULE			(3 << 25)
-#define TB0C_OUTPUT_WRITE_CURRENT	(0 << 24)
-#define TB0C_OUTPUT_WRITE_ACCUM		(1 << 24)
-#define TB0C_ARG3_REPLICATE_ALPHA 	(1<<23)
-#define TB0C_ARG3_INVERT		(1<<22)
-#define TB0C_ARG3_SEL_XXX
-#define TB0C_ARG2_REPLICATE_ALPHA 	(1<<17)
-#define TB0C_ARG2_INVERT		(1<<16)
-#define TB0C_ARG2_SEL_ONE		(0 << 12)
-#define TB0C_ARG2_SEL_FACTOR		(1 << 12)
-#define TB0C_ARG2_SEL_TEXEL0		(6 << 12)
-#define TB0C_ARG2_SEL_TEXEL1		(7 << 12)
-#define TB0C_ARG2_SEL_TEXEL2		(8 << 12)
-#define TB0C_ARG2_SEL_TEXEL3		(9 << 12)
-#define TB0C_ARG1_REPLICATE_ALPHA 	(1<<11)
-#define TB0C_ARG1_INVERT		(1<<10)
-#define TB0C_ARG1_SEL_TEXEL0		(6 << 6)
-#define TB0C_ARG1_SEL_TEXEL1		(7 << 6)
-#define TB0C_ARG1_SEL_TEXEL2		(8 << 6)
-#define TB0C_ARG1_SEL_TEXEL3		(9 << 6)
-#define TB0C_ARG0_REPLICATE_ALPHA 	(1<<5)
-#define TB0C_ARG0_SEL_XXX
-
-#define TB0A_CTR_STAGE_ENABLE 		(1<<31)
-#define TB0A_RESULT_SCALE_1X		(0 << 29)
-#define TB0A_RESULT_SCALE_2X		(1 << 29)
-#define TB0A_RESULT_SCALE_4X		(2 << 29)
-#define TB0A_OP_MODULE			(3 << 25)
-#define TB0A_OUTPUT_WRITE_CURRENT	(0<<24)
-#define TB0A_OUTPUT_WRITE_ACCUM		(1<<24)
-#define TB0A_CTR_STAGE_SEL_BITS_XXX
-#define TB0A_ARG3_SEL_XXX
-#define TB0A_ARG3_INVERT		(1<<17)
-#define TB0A_ARG2_INVERT		(1<<16)
-#define TB0A_ARG2_SEL_ONE		(0 << 12)
-#define TB0A_ARG2_SEL_TEXEL0		(6 << 12)
-#define TB0A_ARG2_SEL_TEXEL1		(7 << 12)
-#define TB0A_ARG2_SEL_TEXEL2		(8 << 12)
-#define TB0A_ARG2_SEL_TEXEL3		(9 << 12)
-#define TB0A_ARG1_INVERT		(1<<10)
-#define TB0A_ARG1_SEL_TEXEL0		(6 << 6)
-#define TB0A_ARG1_SEL_TEXEL1		(7 << 6)
-#define TB0A_ARG1_SEL_TEXEL2		(8 << 6)
-#define TB0A_ARG1_SEL_TEXEL3		(9 << 6)
-
-static struct blendinfo I830BlendOp[] = { 
-    /* Clear */
-    {0, 0, BLENDFACTOR_ZERO, 		BLENDFACTOR_ZERO},
-    /* Src */
-    {0, 0, BLENDFACTOR_ONE, 		BLENDFACTOR_ZERO},
-    /* Dst */
-    {0, 0, BLENDFACTOR_ZERO,		BLENDFACTOR_ONE},
-    /* Over */
-    {0, 1, BLENDFACTOR_ONE,		BLENDFACTOR_INV_SRC_ALPHA},
-    /* OverReverse */
-    {1, 0, BLENDFACTOR_INV_DST_ALPHA,	BLENDFACTOR_ONE},
-    /* In */
-    {1, 0, BLENDFACTOR_DST_ALPHA,	BLENDFACTOR_ZERO},
-    /* InReverse */
-    {0, 1, BLENDFACTOR_ZERO,		BLENDFACTOR_SRC_ALPHA},
-    /* Out */
-    {1, 0, BLENDFACTOR_INV_DST_ALPHA,	BLENDFACTOR_ZERO},
-    /* OutReverse */
-    {0, 1, BLENDFACTOR_ZERO,		BLENDFACTOR_INV_SRC_ALPHA},
-    /* Atop */
-    {1, 1, BLENDFACTOR_DST_ALPHA,	BLENDFACTOR_INV_SRC_ALPHA},
-    /* AtopReverse */
-    {1, 1, BLENDFACTOR_INV_DST_ALPHA,	BLENDFACTOR_SRC_ALPHA},
-    /* Xor */
-    {1, 1, BLENDFACTOR_INV_DST_ALPHA,	BLENDFACTOR_INV_SRC_ALPHA},
-    /* Add */
-    {0, 0, BLENDFACTOR_ONE, 		BLENDFACTOR_ONE},
-};
-
-
-static struct formatinfo I830TexFormats[] = {
-        {PICT_a8r8g8b8, MT_32BIT_ARGB8888 },
-        {PICT_x8r8g8b8, MT_32BIT_ARGB8888 },
-        {PICT_a8b8g8r8, MT_32BIT_ABGR8888 },
-        {PICT_x8b8g8r8, MT_32BIT_ABGR8888 },
-        {PICT_r5g6b5,   MT_16BIT_RGB565	  },
-        {PICT_a1r5g5b5, MT_16BIT_ARGB1555 },
-        {PICT_x1r5g5b5, MT_16BIT_ARGB1555 },
-        {PICT_a8,       MT_8BIT_I8       },
-};
-
-static Bool I830GetDestFormat(PicturePtr pDstPicture, CARD32 *dst_format)
-{
-	/* XXX: color buffer format for i830 */
-    switch (pDstPicture->format) {
-    case PICT_a8r8g8b8:
-    case PICT_x8r8g8b8:
-        *dst_format = COLR_BUF_ARGB8888;
-        break;
-    case PICT_r5g6b5:
-        *dst_format = COLR_BUF_RGB565;
-        break;
-    case PICT_a1r5g5b5:
-    case PICT_x1r5g5b5:
-        *dst_format = COLR_BUF_ARGB1555;
-        break;
-    case PICT_a8:
-        *dst_format = COLR_BUF_8BIT;
-        break;
-    case PICT_a4r4g4b4:
-    case PICT_x4r4g4b4:
-	*dst_format = COLR_BUF_ARGB4444;
-	break;
-    default:
-        I830FALLBACK("Unsupported dest format 0x%x\n",
-                        (int)pDstPicture->format);
-    }
-
-    return TRUE;
-}
-
-
-static CARD32 I830GetBlendCntl(int op, PicturePtr pMask, CARD32 dst_format)
-{
-    CARD32 sblend, dblend;
-
-    sblend = I830BlendOp[op].src_blend;
-    dblend = I830BlendOp[op].dst_blend;
-
-    /* If there's no dst alpha channel, adjust the blend op so that we'll treat
-     * it as always 1.
-     */
-    if (PICT_FORMAT_A(dst_format) == 0 && I830BlendOp[op].dst_alpha) {
-        if (sblend == BLENDFACTOR_DST_ALPHA)
-            sblend = BLENDFACTOR_ONE;
-        else if (sblend == BLENDFACTOR_INV_DST_ALPHA)
-            sblend = BLENDFACTOR_ZERO;
-    }
-
-    /* If the source alpha is being used, then we should only be in a case where
-     * the source blend factor is 0, and the source blend value is the mask
-     * channels multiplied by the source picture's alpha.
-     */
-    if (pMask && pMask->componentAlpha && I830BlendOp[op].src_alpha) {
-        if (dblend == BLENDFACTOR_SRC_ALPHA) {
-            dblend = BLENDFACTOR_SRC_COLR;
-        } else if (dblend == BLENDFACTOR_INV_SRC_ALPHA) {
-            dblend = BLENDFACTOR_INV_SRC_COLR;
-        }
-    }
-
-    return (sblend << S8_SRC_BLEND_FACTOR_SHIFT) | 
-		(dblend << S8_DST_BLEND_FACTOR_SHIFT);
-}
-
-static Bool I830CheckCompositeTexture(PicturePtr pPict, int unit)
-{
-    int w = pPict->pDrawable->width;
-    int h = pPict->pDrawable->height;
-    int i;
-                                                                                                                                                            
-    if ((w > 0x7ff) || (h > 0x7ff))
-        I830FALLBACK("Picture w/h too large (%dx%d)\n", w, h);
-
-    for (i = 0; i < sizeof(I830TexFormats) / sizeof(I830TexFormats[0]); i++)
-    {
-        if (I830TexFormats[i].fmt == pPict->format)
-            break;
-    }
-    if (i == sizeof(I830TexFormats) / sizeof(I830TexFormats[0]))
-        I830FALLBACK("Unsupported picture format 0x%x\n",
-                         (int)pPict->format);
-
-    /* FIXME: fix repeat support */
-    if (pPict->repeat)
-	I830FALLBACK("repeat unsupport now\n");
-
-    if (pPict->filter != PictFilterNearest &&
-        pPict->filter != PictFilterBilinear)
-        I830FALLBACK("Unsupported filter 0x%x\n", pPict->filter);
-
-    return TRUE;
-}
-
-static Bool
-I830TextureSetup(PicturePtr pPict, PixmapPtr pPix, int unit)
-{
-
-    ScrnInfoPtr pScrn = xf86Screens[pPict->pDrawable->pScreen->myNum];
-    I830Ptr pI830 = I830PTR(pScrn);
-    CARD32 format, offset, pitch, filter;
-    int w, h, i;
-    CARD32 wrap_mode = TEXCOORDMODE_CLAMP; 
-
-    offset = intel_get_pixmap_offset(pPix);
-    pitch = intel_get_pixmap_pitch(pPix);
-    w = pPict->pDrawable->width;
-    h = pPict->pDrawable->height;
-    pI830->scale_units[unit][0] = pPix->drawable.width;
-    pI830->scale_units[unit][1] = pPix->drawable.height;
-
-    for (i = 0; i < sizeof(I830TexFormats) / sizeof(I830TexFormats[0]); i++) {
-        if (I830TexFormats[i].fmt == pPict->format)
-	    break;
-    }
-    if ( i == sizeof(I830TexFormats)/ sizeof(I830TexFormats[0]) )
-	I830FALLBACK("unknown texture format\n");
-    format = I830TexFormats[i].card_fmt;
-
-    if (pPict->repeat) 
-	wrap_mode = TEXCOORDMODE_WRAP; /* XXX: correct ? */
-    
-    switch (pPict->filter) {
-    case PictFilterNearest:
-        filter = ((FILTER_NEAREST<<TM0S3_MAG_FILTER_SHIFT) | 
-			(FILTER_NEAREST<<TM0S3_MIN_FILTER_SHIFT));
-        break;
-    case PictFilterBilinear:
-        filter = ((FILTER_LINEAR<<TM0S3_MAG_FILTER_SHIFT) | 
-			(FILTER_LINEAR<<TM0S3_MIN_FILTER_SHIFT));
-        break;
-    default:
-	filter = 0;
-        I830FALLBACK("Bad filter 0x%x\n", pPict->filter);
-    }
-
-    {
-	if (pPix->drawable.bitsPerPixel == 8)
-		format |= MAP_SURFACE_8BIT;
-	else if (pPix->drawable.bitsPerPixel == 16)
-		format |= MAP_SURFACE_16BIT;
-	else
-		format |= MAP_SURFACE_32BIT;
-
-	BEGIN_LP_RING(6);
-	OUT_RING(_3DSTATE_MAP_INFO_CMD);
-	OUT_RING(format | TEXMAP_INDEX(unit) | MAP_FORMAT_2D);
-	OUT_RING(((pPix->drawable.height - 1) << 16) |
-		(pPix->drawable.width - 1)); /* height, width */
-	OUT_RING(offset); /* map address */
-	OUT_RING(((pitch / 4) - 1) << 2); /* map pitch */
-	OUT_RING(0);
-	ADVANCE_LP_RING();
-     }
-
-     {
-	BEGIN_LP_RING(2);
-	/* coord sets */
-	OUT_RING(_3DSTATE_MAP_COORD_SET_CMD | TEXCOORD_SET(unit) | 
-		ENABLE_TEXCOORD_PARAMS | TEXCOORDS_ARE_NORMAL | 
-		TEXCOORDTYPE_CARTESIAN | ENABLE_ADDR_V_CNTL | 
-		TEXCOORD_ADDR_V_MODE(wrap_mode) |
-		ENABLE_ADDR_U_CNTL | TEXCOORD_ADDR_U_MODE(wrap_mode));
-	OUT_RING(MI_NOOP);
-
-	/* XXX: filter seems hang engine...*/
-#if 0
-	OUT_RING(I830_STATE3D_MAP_FILTER | FILTER_MAP_INDEX(unit) | ENABLE_KEYS| DISABLE_COLOR_KEY | DISABLE_CHROMA_KEY | DISABLE_KILL_PIXEL |ENABLE_MIP_MODE_FILTER | MIPFILTER_NONE | filter);
-	OUT_RING(0);
-#endif
-
-	/* max & min mip level ? or base mip level? */
-
-	ADVANCE_LP_RING();
-    }
-
-    pI830->transform[unit] = pPict->transform;
-
-#ifdef I830DEBUG
-    ErrorF("try to sync to show any errors...");
-    I830Sync(pScrn);
-#endif
-	
-    return TRUE;
-}
-
-Bool
-I830EXACheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
-		      PicturePtr pDstPicture)
-{
-    CARD32 tmp1;
-    
-    /* Check for unsupported compositing operations. */
-    if (op >= sizeof(I830BlendOp) / sizeof(I830BlendOp[0]))
-        I830FALLBACK("Unsupported Composite op 0x%x\n", op);
-                                                                                                                                                            
-    if (pMaskPicture != NULL && pMaskPicture->componentAlpha) {
-        /* Check if it's component alpha that relies on a source alpha and on
-         * the source value.  We can only get one of those into the single
-         * source value that we get to blend with.
-         */
-        if (I830BlendOp[op].src_alpha &&
-            (I830BlendOp[op].src_blend != BLENDFACTOR_ZERO))
-            	I830FALLBACK("Component alpha not supported with source "
-                            "alpha and source value blending.\n");
-    }
-
-    if (!I830CheckCompositeTexture(pSrcPicture, 0))
-        I830FALLBACK("Check Src picture texture\n");
-    if (pMaskPicture != NULL && !I830CheckCompositeTexture(pMaskPicture, 1))
-        I830FALLBACK("Check Mask picture texture\n");
-
-    if (!I830GetDestFormat(pDstPicture, &tmp1)) 
-	I830FALLBACK("Get Color buffer format\n");
-
-    return TRUE;
-}
-
-Bool
-I830EXAPrepareComposite(int op, PicturePtr pSrcPicture,
-			PicturePtr pMaskPicture, PicturePtr pDstPicture,
-			PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
-{
-/* XXX: setup texture map from pixmap, vertex format, blend cntl */
-    ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum];
-    I830Ptr pI830 = I830PTR(pScrn);
-    CARD32 dst_format, dst_offset, dst_pitch;
-
-    I830GetDestFormat(pDstPicture, &dst_format);
-    dst_offset = intel_get_pixmap_offset(pDst);
-    dst_pitch = intel_get_pixmap_pitch(pDst);
-
-    pI830->last_3d = LAST_3D_RENDER;
-
-    if (!I830TextureSetup(pSrcPicture, pSrc, 0))
-	I830FALLBACK("fail to setup src texture\n");
-    if (pMask != NULL) {
-	if (!I830TextureSetup(pMaskPicture, pMask, 1))
-		I830FALLBACK("fail to setup mask texture\n");
-    } else {
-	pI830->transform[1] = NULL;
-	pI830->scale_units[1][0] = -1;
-	pI830->scale_units[1][1] = -1;
-    }
-
-    {
-
-	CARD32 cblend, ablend, blendctl, vf2;
-
-	BEGIN_LP_RING(22+6);
-	
-	/*color buffer*/
-	OUT_RING(_3DSTATE_BUF_INFO_CMD);
-	OUT_RING(BUF_3D_ID_COLOR_BACK| BUF_3D_PITCH(dst_pitch));
-	OUT_RING(BUF_3D_ADDR(dst_offset));
-	OUT_RING(MI_NOOP);
-	
-	OUT_RING(_3DSTATE_DST_BUF_VARS_CMD);
-	OUT_RING(dst_format);
-
-      	OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
-      	OUT_RING(MI_NOOP);		/* pad to quadword */
-	/* defaults */
-	OUT_RING(_3DSTATE_DFLT_Z_CMD);
-	OUT_RING(0);
-
-	OUT_RING(_3DSTATE_DFLT_DIFFUSE_CMD);
-	OUT_RING(0);
-
-	OUT_RING(_3DSTATE_DFLT_SPEC_CMD);
-	OUT_RING(0);
-	
-	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | 0);
-	OUT_RING((1 << S3_POINT_WIDTH_SHIFT) | (2 << S3_LINE_WIDTH_SHIFT) | 
-		S3_CULLMODE_NONE | S3_VERTEXHAS_XY);  
-	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) | 0);
-	if (pMask)
-	    vf2 = 2 << 12; /* 2 texture coord sets */
-	else
-	    vf2 = 1 << 12;
-	vf2 |= (TEXCOORDFMT_2D << 16);
-	if (pMask)
-	    vf2 |= (TEXCOORDFMT_2D << 18);
-	else
-	    vf2 |= (TEXCOORDFMT_1D << 18);
-		
-	vf2 |= (TEXCOORDFMT_1D << 20);
-	vf2 |= (TEXCOORDFMT_1D << 22);
-	vf2 |= (TEXCOORDFMT_1D << 24);
-	vf2 |= (TEXCOORDFMT_1D << 26);
-	vf2 |= (TEXCOORDFMT_1D << 28);
-	vf2 |= (TEXCOORDFMT_1D << 30);
-	OUT_RING(vf2);
-
-      	OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
-      	OUT_RING(MI_NOOP);		/* pad to quadword */
-	/* For (src In mask) operation */
-	/* IN operator: Multiply src by mask components or mask alpha.*/
-	/* TEXBLENDOP_MODULE: arg1*arg2 */
-	cblend = TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OP_MODULE |
-		 TB0C_OUTPUT_WRITE_CURRENT;  
-	ablend = TB0A_RESULT_SCALE_1X | TB0A_OP_MODULE | 
-		 TB0A_OUTPUT_WRITE_CURRENT;
-	
-	cblend |= TB0C_ARG1_SEL_TEXEL0;
-	ablend |= TB0A_ARG1_SEL_TEXEL0;
-	if (pMask) {
-	    if (pMaskPicture->componentAlpha && pDstPicture->format != PICT_a8)
-		cblend |= TB0C_ARG2_SEL_TEXEL1;
-	    else
-		cblend |= (TB0C_ARG2_SEL_TEXEL1 | TB0C_ARG2_REPLICATE_ALPHA);
-	    ablend |= TB0A_ARG2_SEL_TEXEL1;
-	} else {
-		cblend |= TB0C_ARG2_SEL_ONE;
-		ablend |= TB0A_ARG2_SEL_ONE;		
-	}
-		
-	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | LOAD_TEXTURE_BLEND_STAGE(0)|1);
-	OUT_RING(cblend);
-	OUT_RING(ablend);
-	OUT_RING(0);
-
-      	OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
-      	OUT_RING(MI_NOOP);		/* pad to quadword */
-
-	blendctl = I830GetBlendCntl(op, pMaskPicture, pDstPicture->format);
-	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(8) | 0);
-	OUT_RING(S8_ENABLE_COLOR_BLEND | S8_BLENDFUNC_ADD |(blendctl<<4) |
-		S8_ENABLE_COLOR_BUFFER_WRITE);	
-	ADVANCE_LP_RING();
-    }
-
-#ifdef I830DEBUG
-   Error("try to sync to show any errors...");
-   I830Sync(pScrn);
-#endif
-
-    return TRUE;
-}
-
diff --git a/src/i830_render.c b/src/i830_render.c
new file mode 100644
index 0000000..c335f6d
--- /dev/null
+++ b/src/i830_render.c
@@ -0,0 +1,591 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Wang Zhenyu <zhenyu.z.wang at intel.com>
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "i830.h"
+#include "i830_reg.h"
+
+#ifdef I830DEBUG
+#define DEBUG_I830FALLBACK 1
+#endif
+
+#ifdef DEBUG_I830FALLBACK
+#define I830FALLBACK(s, arg...)				\
+do {							\
+	DPRINTF(PFX, "EXA fallback: " s "\n", ##arg); 	\
+	return FALSE;					\
+} while(0)
+#else
+#define I830FALLBACK(s, arg...) 			\
+do { 							\
+	return FALSE;					\
+} while(0) 
+#endif
+
+struct blendinfo {
+    Bool dst_alpha;
+    Bool src_alpha;
+    CARD32 src_blend;
+    CARD32 dst_blend;
+};
+
+struct formatinfo {
+    int fmt;
+    CARD32 card_fmt;
+};
+
+#define TB0C_LAST_STAGE	(1 << 31)
+#define TB0C_RESULT_SCALE_1X		(0 << 29)
+#define TB0C_RESULT_SCALE_2X		(1 << 29)
+#define TB0C_RESULT_SCALE_4X		(2 << 29)
+#define TB0C_OP_MODULE			(3 << 25)
+#define TB0C_OUTPUT_WRITE_CURRENT	(0 << 24)
+#define TB0C_OUTPUT_WRITE_ACCUM		(1 << 24)
+#define TB0C_ARG3_REPLICATE_ALPHA 	(1<<23)
+#define TB0C_ARG3_INVERT		(1<<22)
+#define TB0C_ARG3_SEL_XXX
+#define TB0C_ARG2_REPLICATE_ALPHA 	(1<<17)
+#define TB0C_ARG2_INVERT		(1<<16)
+#define TB0C_ARG2_SEL_ONE		(0 << 12)
+#define TB0C_ARG2_SEL_FACTOR		(1 << 12)
+#define TB0C_ARG2_SEL_TEXEL0		(6 << 12)
+#define TB0C_ARG2_SEL_TEXEL1		(7 << 12)
+#define TB0C_ARG2_SEL_TEXEL2		(8 << 12)
+#define TB0C_ARG2_SEL_TEXEL3		(9 << 12)
+#define TB0C_ARG1_REPLICATE_ALPHA 	(1<<11)
+#define TB0C_ARG1_INVERT		(1<<10)
+#define TB0C_ARG1_SEL_TEXEL0		(6 << 6)
+#define TB0C_ARG1_SEL_TEXEL1		(7 << 6)
+#define TB0C_ARG1_SEL_TEXEL2		(8 << 6)
+#define TB0C_ARG1_SEL_TEXEL3		(9 << 6)
+#define TB0C_ARG0_REPLICATE_ALPHA 	(1<<5)
+#define TB0C_ARG0_SEL_XXX
+
+#define TB0A_CTR_STAGE_ENABLE 		(1<<31)
+#define TB0A_RESULT_SCALE_1X		(0 << 29)
+#define TB0A_RESULT_SCALE_2X		(1 << 29)
+#define TB0A_RESULT_SCALE_4X		(2 << 29)
+#define TB0A_OP_MODULE			(3 << 25)
+#define TB0A_OUTPUT_WRITE_CURRENT	(0<<24)
+#define TB0A_OUTPUT_WRITE_ACCUM		(1<<24)
+#define TB0A_CTR_STAGE_SEL_BITS_XXX
+#define TB0A_ARG3_SEL_XXX
+#define TB0A_ARG3_INVERT		(1<<17)
+#define TB0A_ARG2_INVERT		(1<<16)
+#define TB0A_ARG2_SEL_ONE		(0 << 12)
+#define TB0A_ARG2_SEL_TEXEL0		(6 << 12)
+#define TB0A_ARG2_SEL_TEXEL1		(7 << 12)
+#define TB0A_ARG2_SEL_TEXEL2		(8 << 12)
+#define TB0A_ARG2_SEL_TEXEL3		(9 << 12)
+#define TB0A_ARG1_INVERT		(1<<10)
+#define TB0A_ARG1_SEL_TEXEL0		(6 << 6)
+#define TB0A_ARG1_SEL_TEXEL1		(7 << 6)
+#define TB0A_ARG1_SEL_TEXEL2		(8 << 6)
+#define TB0A_ARG1_SEL_TEXEL3		(9 << 6)
+
+static struct blendinfo I830BlendOp[] = { 
+    /* Clear */
+    {0, 0, BLENDFACTOR_ZERO, 		BLENDFACTOR_ZERO},
+    /* Src */
+    {0, 0, BLENDFACTOR_ONE, 		BLENDFACTOR_ZERO},
+    /* Dst */
+    {0, 0, BLENDFACTOR_ZERO,		BLENDFACTOR_ONE},
+    /* Over */
+    {0, 1, BLENDFACTOR_ONE,		BLENDFACTOR_INV_SRC_ALPHA},
+    /* OverReverse */
+    {1, 0, BLENDFACTOR_INV_DST_ALPHA,	BLENDFACTOR_ONE},
+    /* In */
+    {1, 0, BLENDFACTOR_DST_ALPHA,	BLENDFACTOR_ZERO},
+    /* InReverse */
+    {0, 1, BLENDFACTOR_ZERO,		BLENDFACTOR_SRC_ALPHA},
+    /* Out */
+    {1, 0, BLENDFACTOR_INV_DST_ALPHA,	BLENDFACTOR_ZERO},
+    /* OutReverse */
+    {0, 1, BLENDFACTOR_ZERO,		BLENDFACTOR_INV_SRC_ALPHA},
+    /* Atop */
+    {1, 1, BLENDFACTOR_DST_ALPHA,	BLENDFACTOR_INV_SRC_ALPHA},
+    /* AtopReverse */
+    {1, 1, BLENDFACTOR_INV_DST_ALPHA,	BLENDFACTOR_SRC_ALPHA},
+    /* Xor */
+    {1, 1, BLENDFACTOR_INV_DST_ALPHA,	BLENDFACTOR_INV_SRC_ALPHA},
+    /* Add */
+    {0, 0, BLENDFACTOR_ONE, 		BLENDFACTOR_ONE},
+};
+
+
+static struct formatinfo I830TexFormats[] = {
+        {PICT_a8r8g8b8, MT_32BIT_ARGB8888 },
+        {PICT_x8r8g8b8, MT_32BIT_ARGB8888 },
+        {PICT_a8b8g8r8, MT_32BIT_ABGR8888 },
+        {PICT_x8b8g8r8, MT_32BIT_ABGR8888 },
+        {PICT_r5g6b5,   MT_16BIT_RGB565	  },
+        {PICT_a1r5g5b5, MT_16BIT_ARGB1555 },
+        {PICT_x1r5g5b5, MT_16BIT_ARGB1555 },
+        {PICT_a8,       MT_8BIT_I8       },
+};
+
+static Bool I830GetDestFormat(PicturePtr pDstPicture, CARD32 *dst_format)
+{
+	/* XXX: color buffer format for i830 */
+    switch (pDstPicture->format) {
+    case PICT_a8r8g8b8:
+    case PICT_x8r8g8b8:
+        *dst_format = COLR_BUF_ARGB8888;
+        break;
+    case PICT_r5g6b5:
+        *dst_format = COLR_BUF_RGB565;
+        break;
+    case PICT_a1r5g5b5:
+    case PICT_x1r5g5b5:
+        *dst_format = COLR_BUF_ARGB1555;
+        break;
+    case PICT_a8:
+        *dst_format = COLR_BUF_8BIT;
+        break;
+    case PICT_a4r4g4b4:
+    case PICT_x4r4g4b4:
+	*dst_format = COLR_BUF_ARGB4444;
+	break;
+    default:
+        I830FALLBACK("Unsupported dest format 0x%x\n",
+                        (int)pDstPicture->format);
+    }
+
+    return TRUE;
+}
+
+
+static CARD32 I830GetBlendCntl(int op, PicturePtr pMask, CARD32 dst_format)
+{
+    CARD32 sblend, dblend;
+
+    sblend = I830BlendOp[op].src_blend;
+    dblend = I830BlendOp[op].dst_blend;
+
+    /* If there's no dst alpha channel, adjust the blend op so that we'll treat
+     * it as always 1.
+     */
+    if (PICT_FORMAT_A(dst_format) == 0 && I830BlendOp[op].dst_alpha) {
+        if (sblend == BLENDFACTOR_DST_ALPHA)
+            sblend = BLENDFACTOR_ONE;
+        else if (sblend == BLENDFACTOR_INV_DST_ALPHA)
+            sblend = BLENDFACTOR_ZERO;
+    }
+
+    /* If the source alpha is being used, then we should only be in a case where
+     * the source blend factor is 0, and the source blend value is the mask
+     * channels multiplied by the source picture's alpha.
+     */
+    if (pMask && pMask->componentAlpha && I830BlendOp[op].src_alpha) {
+        if (dblend == BLENDFACTOR_SRC_ALPHA) {
+            dblend = BLENDFACTOR_SRC_COLR;
+        } else if (dblend == BLENDFACTOR_INV_SRC_ALPHA) {
+            dblend = BLENDFACTOR_INV_SRC_COLR;
+        }
+    }
+
+    return (sblend << S8_SRC_BLEND_FACTOR_SHIFT) | 
+		(dblend << S8_DST_BLEND_FACTOR_SHIFT);
+}
+
+static Bool I830CheckCompositeTexture(PicturePtr pPict, int unit)
+{
+    int w = pPict->pDrawable->width;
+    int h = pPict->pDrawable->height;
+    int i;
+                                                                                                                                                            
+    if ((w > 0x7ff) || (h > 0x7ff))
+        I830FALLBACK("Picture w/h too large (%dx%d)\n", w, h);
+
+    for (i = 0; i < sizeof(I830TexFormats) / sizeof(I830TexFormats[0]); i++)
+    {
+        if (I830TexFormats[i].fmt == pPict->format)
+            break;
+    }
+    if (i == sizeof(I830TexFormats) / sizeof(I830TexFormats[0]))
+        I830FALLBACK("Unsupported picture format 0x%x\n",
+                         (int)pPict->format);
+
+    /* FIXME: fix repeat support */
+    if (pPict->repeat)
+	I830FALLBACK("repeat unsupport now\n");
+
+    if (pPict->filter != PictFilterNearest &&
+        pPict->filter != PictFilterBilinear)
+        I830FALLBACK("Unsupported filter 0x%x\n", pPict->filter);
+
+    return TRUE;
+}
+
+static Bool
+I830TextureSetup(PicturePtr pPict, PixmapPtr pPix, int unit)
+{
+
+    ScrnInfoPtr pScrn = xf86Screens[pPict->pDrawable->pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD32 format, offset, pitch, filter;
+    int w, h, i;
+    CARD32 wrap_mode = TEXCOORDMODE_CLAMP; 
+
+    offset = intel_get_pixmap_offset(pPix);
+    pitch = intel_get_pixmap_pitch(pPix);
+    w = pPict->pDrawable->width;
+    h = pPict->pDrawable->height;
+    pI830->scale_units[unit][0] = pPix->drawable.width;
+    pI830->scale_units[unit][1] = pPix->drawable.height;
+
+    for (i = 0; i < sizeof(I830TexFormats) / sizeof(I830TexFormats[0]); i++) {
+        if (I830TexFormats[i].fmt == pPict->format)
+	    break;
+    }
+    if ( i == sizeof(I830TexFormats)/ sizeof(I830TexFormats[0]) )
+	I830FALLBACK("unknown texture format\n");
+    format = I830TexFormats[i].card_fmt;
+
+    if (pPict->repeat) 
+	wrap_mode = TEXCOORDMODE_WRAP; /* XXX: correct ? */
+    
+    switch (pPict->filter) {
+    case PictFilterNearest:
+        filter = ((FILTER_NEAREST<<TM0S3_MAG_FILTER_SHIFT) | 
+			(FILTER_NEAREST<<TM0S3_MIN_FILTER_SHIFT));
+        break;
+    case PictFilterBilinear:
+        filter = ((FILTER_LINEAR<<TM0S3_MAG_FILTER_SHIFT) | 
+			(FILTER_LINEAR<<TM0S3_MIN_FILTER_SHIFT));
+        break;
+    default:
+	filter = 0;
+        I830FALLBACK("Bad filter 0x%x\n", pPict->filter);
+    }
+
+    {
+	if (pPix->drawable.bitsPerPixel == 8)
+		format |= MAP_SURFACE_8BIT;
+	else if (pPix->drawable.bitsPerPixel == 16)
+		format |= MAP_SURFACE_16BIT;
+	else
+		format |= MAP_SURFACE_32BIT;
+
+	BEGIN_LP_RING(6);
+	OUT_RING(_3DSTATE_MAP_INFO_CMD);
+	OUT_RING(format | TEXMAP_INDEX(unit) | MAP_FORMAT_2D);
+	OUT_RING(((pPix->drawable.height - 1) << 16) |
+		(pPix->drawable.width - 1)); /* height, width */
+	OUT_RING(offset); /* map address */
+	OUT_RING(((pitch / 4) - 1) << 2); /* map pitch */
+	OUT_RING(0);
+	ADVANCE_LP_RING();
+     }
+
+     {
+	BEGIN_LP_RING(2);
+	/* coord sets */
+	OUT_RING(_3DSTATE_MAP_COORD_SET_CMD | TEXCOORD_SET(unit) | 
+		ENABLE_TEXCOORD_PARAMS | TEXCOORDS_ARE_NORMAL | 
+		TEXCOORDTYPE_CARTESIAN | ENABLE_ADDR_V_CNTL | 
+		TEXCOORD_ADDR_V_MODE(wrap_mode) |
+		ENABLE_ADDR_U_CNTL | TEXCOORD_ADDR_U_MODE(wrap_mode));
+	OUT_RING(MI_NOOP);
+
+	/* XXX: filter seems hang engine...*/
+#if 0
+	OUT_RING(I830_STATE3D_MAP_FILTER | FILTER_MAP_INDEX(unit) | ENABLE_KEYS| DISABLE_COLOR_KEY | DISABLE_CHROMA_KEY | DISABLE_KILL_PIXEL |ENABLE_MIP_MODE_FILTER | MIPFILTER_NONE | filter);
+	OUT_RING(0);
+#endif
+
+	/* max & min mip level ? or base mip level? */
+
+	ADVANCE_LP_RING();
+    }
+
+    pI830->transform[unit] = pPict->transform;
+
+#ifdef I830DEBUG
+    ErrorF("try to sync to show any errors...");
+    I830Sync(pScrn);
+#endif
+	
+    return TRUE;
+}
+
+Bool
+I830EXACheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+		      PicturePtr pDstPicture)
+{
+    CARD32 tmp1;
+    
+    /* Check for unsupported compositing operations. */
+    if (op >= sizeof(I830BlendOp) / sizeof(I830BlendOp[0]))
+        I830FALLBACK("Unsupported Composite op 0x%x\n", op);
+                                                                                                                                                            
+    if (pMaskPicture != NULL && pMaskPicture->componentAlpha) {
+        /* Check if it's component alpha that relies on a source alpha and on
+         * the source value.  We can only get one of those into the single
+         * source value that we get to blend with.
+         */
+        if (I830BlendOp[op].src_alpha &&
+            (I830BlendOp[op].src_blend != BLENDFACTOR_ZERO))
+            	I830FALLBACK("Component alpha not supported with source "
+                            "alpha and source value blending.\n");
+    }
+
+    if (!I830CheckCompositeTexture(pSrcPicture, 0))
+        I830FALLBACK("Check Src picture texture\n");
+    if (pMaskPicture != NULL && !I830CheckCompositeTexture(pMaskPicture, 1))
+        I830FALLBACK("Check Mask picture texture\n");
+
+    if (!I830GetDestFormat(pDstPicture, &tmp1)) 
+	I830FALLBACK("Get Color buffer format\n");
+
+    return TRUE;
+}
+
+Bool
+I830EXAPrepareComposite(int op, PicturePtr pSrcPicture,
+			PicturePtr pMaskPicture, PicturePtr pDstPicture,
+			PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
+{
+/* XXX: setup texture map from pixmap, vertex format, blend cntl */
+    ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD32 dst_format, dst_offset, dst_pitch;
+
+    I830GetDestFormat(pDstPicture, &dst_format);
+    dst_offset = intel_get_pixmap_offset(pDst);
+    dst_pitch = intel_get_pixmap_pitch(pDst);
+
+    pI830->last_3d = LAST_3D_RENDER;
+
+    if (!I830TextureSetup(pSrcPicture, pSrc, 0))
+	I830FALLBACK("fail to setup src texture\n");
+    if (pMask != NULL) {
+	if (!I830TextureSetup(pMaskPicture, pMask, 1))
+		I830FALLBACK("fail to setup mask texture\n");
+    } else {
+	pI830->transform[1] = NULL;
+	pI830->scale_units[1][0] = -1;
+	pI830->scale_units[1][1] = -1;
+    }
+
+    {
+
+	CARD32 cblend, ablend, blendctl, vf2;
+
+	BEGIN_LP_RING(22+6);
+	
+	/*color buffer*/
+	OUT_RING(_3DSTATE_BUF_INFO_CMD);
+	OUT_RING(BUF_3D_ID_COLOR_BACK| BUF_3D_PITCH(dst_pitch));
+	OUT_RING(BUF_3D_ADDR(dst_offset));
+	OUT_RING(MI_NOOP);
+	
+	OUT_RING(_3DSTATE_DST_BUF_VARS_CMD);
+	OUT_RING(dst_format);
+
+      	OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
+      	OUT_RING(MI_NOOP);		/* pad to quadword */
+	/* defaults */
+	OUT_RING(_3DSTATE_DFLT_Z_CMD);
+	OUT_RING(0);
+
+	OUT_RING(_3DSTATE_DFLT_DIFFUSE_CMD);
+	OUT_RING(0);
+
+	OUT_RING(_3DSTATE_DFLT_SPEC_CMD);
+	OUT_RING(0);
+	
+	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | 0);
+	OUT_RING((1 << S3_POINT_WIDTH_SHIFT) | (2 << S3_LINE_WIDTH_SHIFT) | 
+		S3_CULLMODE_NONE | S3_VERTEXHAS_XY);  
+	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) | 0);
+	if (pMask)
+	    vf2 = 2 << 12; /* 2 texture coord sets */
+	else
+	    vf2 = 1 << 12;
+	vf2 |= (TEXCOORDFMT_2D << 16);
+	if (pMask)
+	    vf2 |= (TEXCOORDFMT_2D << 18);
+	else
+	    vf2 |= (TEXCOORDFMT_1D << 18);
+		
+	vf2 |= (TEXCOORDFMT_1D << 20);
+	vf2 |= (TEXCOORDFMT_1D << 22);
+	vf2 |= (TEXCOORDFMT_1D << 24);
+	vf2 |= (TEXCOORDFMT_1D << 26);
+	vf2 |= (TEXCOORDFMT_1D << 28);
+	vf2 |= (TEXCOORDFMT_1D << 30);
+	OUT_RING(vf2);
+
+      	OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
+      	OUT_RING(MI_NOOP);		/* pad to quadword */
+	/* For (src In mask) operation */
+	/* IN operator: Multiply src by mask components or mask alpha.*/
+	/* TEXBLENDOP_MODULE: arg1*arg2 */
+	cblend = TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OP_MODULE |
+		 TB0C_OUTPUT_WRITE_CURRENT;  
+	ablend = TB0A_RESULT_SCALE_1X | TB0A_OP_MODULE | 
+		 TB0A_OUTPUT_WRITE_CURRENT;
+	
+	cblend |= TB0C_ARG1_SEL_TEXEL0;
+	ablend |= TB0A_ARG1_SEL_TEXEL0;
+	if (pMask) {
+	    if (pMaskPicture->componentAlpha && pDstPicture->format != PICT_a8)
+		cblend |= TB0C_ARG2_SEL_TEXEL1;
+	    else
+		cblend |= (TB0C_ARG2_SEL_TEXEL1 | TB0C_ARG2_REPLICATE_ALPHA);
+	    ablend |= TB0A_ARG2_SEL_TEXEL1;
+	} else {
+		cblend |= TB0C_ARG2_SEL_ONE;
+		ablend |= TB0A_ARG2_SEL_ONE;		
+	}
+		
+	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | LOAD_TEXTURE_BLEND_STAGE(0)|1);
+	OUT_RING(cblend);
+	OUT_RING(ablend);
+	OUT_RING(0);
+
+      	OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
+      	OUT_RING(MI_NOOP);		/* pad to quadword */
+
+	blendctl = I830GetBlendCntl(op, pMaskPicture, pDstPicture->format);
+	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(8) | 0);
+	OUT_RING(S8_ENABLE_COLOR_BLEND | S8_BLENDFUNC_ADD |(blendctl<<4) |
+		S8_ENABLE_COLOR_BUFFER_WRITE);	
+	ADVANCE_LP_RING();
+    }
+
+#ifdef I830DEBUG
+   Error("try to sync to show any errors...");
+   I830Sync(pScrn);
+#endif
+
+    return TRUE;
+}
+
+
+/**
+ * Do a single rectangle composite operation.
+ *
+ * This function is shared between i830 and i915 generation code.
+ */
+void
+IntelEXAComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
+		 int dstX, int dstY, int w, int h)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+    Bool has_mask;
+    float src_x[3], src_y[3], mask_x[3], mask_y[3];
+
+    i830_get_transformed_coordinates(srcX, srcY,
+				     pI830->transform[0],
+				     &src_x[0], &src_y[0]);
+    i830_get_transformed_coordinates(srcX, srcY + h,
+				     pI830->transform[0],
+				     &src_x[1], &src_y[1]);
+    i830_get_transformed_coordinates(srcX + w, srcY + h,
+				     pI830->transform[0],
+				     &src_x[2], &src_y[2]);
+
+    if (pI830->scale_units[1][0] == -1 || pI830->scale_units[1][1] == -1) {
+	has_mask = FALSE;
+    } else {
+	has_mask = TRUE;
+	i830_get_transformed_coordinates(maskX, maskY,
+					 pI830->transform[1],
+					 &mask_x[0], &mask_y[0]);
+	i830_get_transformed_coordinates(maskX, maskY + h,
+					 pI830->transform[1],
+					 &mask_x[1], &mask_y[1]);
+	i830_get_transformed_coordinates(maskX + w, maskY + h,
+					 pI830->transform[1],
+					 &mask_x[2], &mask_y[2]);
+    }
+
+    {
+	int vertex_count; 
+
+	if (has_mask)
+		vertex_count = 3*6;
+	else
+		vertex_count = 3*4;
+
+	BEGIN_LP_RING(6+vertex_count);
+
+	OUT_RING(MI_NOOP);
+	OUT_RING(MI_NOOP);
+	OUT_RING(MI_NOOP);
+	OUT_RING(MI_NOOP);
+	OUT_RING(MI_NOOP);
+
+	OUT_RING(PRIM3D_INLINE | PRIM3D_RECTLIST | (vertex_count-1));
+
+	OUT_RING_F(dstX);
+	OUT_RING_F(dstY);
+	OUT_RING_F(src_x[0] / pI830->scale_units[0][0]);
+	OUT_RING_F(src_y[0] / pI830->scale_units[0][1]);
+	if (has_mask) {
+		OUT_RING_F(mask_x[0] / pI830->scale_units[1][0]);
+		OUT_RING_F(mask_y[0] / pI830->scale_units[1][1]);
+	}
+
+	OUT_RING_F(dstX);
+	OUT_RING_F(dstY + h);
+	OUT_RING_F(src_x[1] / pI830->scale_units[0][0]);
+	OUT_RING_F(src_y[1] / pI830->scale_units[0][1]);
+	if (has_mask) {
+		OUT_RING_F(mask_x[1] / pI830->scale_units[1][0]);
+		OUT_RING_F(mask_y[1] / pI830->scale_units[1][1]);
+	}
+
+	OUT_RING_F(dstX + w);
+	OUT_RING_F(dstY + h);
+	OUT_RING_F(src_x[2] / pI830->scale_units[0][0]);
+	OUT_RING_F(src_y[2] / pI830->scale_units[0][1]);
+	if (has_mask) {
+		OUT_RING_F(mask_x[2] / pI830->scale_units[1][0]);
+		OUT_RING_F(mask_y[2] / pI830->scale_units[1][1]);
+	}
+	ADVANCE_LP_RING();
+    }
+}
+
+void
+IntelEXADoneComposite(PixmapPtr pDst)
+{
+#if ALWAYS_SYNC
+    ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
+
+    I830Sync(pScrn);
+#endif
+}
diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
deleted file mode 100644
index 2fb41ad..0000000
--- a/src/i915_exa_render.c
+++ /dev/null
@@ -1,477 +0,0 @@
-/*
- * Copyright © 2006 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Authors:
- *    Wang Zhenyu <zhenyu.z.wang at intel.com>
- *    Eric Anholt <eric at anholt.net>
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "xf86.h"
-#include "i830.h"
-#include "i915_reg.h"
-#include "i915_3d.h"
-
-#ifdef I830DEBUG
-#define DEBUG_I830FALLBACK 1
-#endif
-
-#ifdef DEBUG_I830FALLBACK
-#define I830FALLBACK(s, arg...)				\
-do {							\
-	DPRINTF(PFX, "EXA fallback: " s "\n", ##arg); 	\
-	return FALSE;					\
-} while(0)
-#else
-#define I830FALLBACK(s, arg...) 			\
-do { 							\
-	return FALSE;					\
-} while(0)
-#endif
-
-struct formatinfo {
-    int fmt;
-    CARD32 card_fmt;
-};
-
-struct blendinfo {
-    Bool dst_alpha;
-    Bool src_alpha;
-    CARD32 src_blend;
-    CARD32 dst_blend;
-};
-
-static struct blendinfo I915BlendOp[] = {
-    /* Clear */
-    {0, 0, BLENDFACT_ZERO,          BLENDFACT_ZERO},
-    /* Src */
-    {0, 0, BLENDFACT_ONE,           BLENDFACT_ZERO},
-    /* Dst */
-    {0, 0, BLENDFACT_ZERO,          BLENDFACT_ONE},
-    /* Over */
-    {0, 1, BLENDFACT_ONE,           BLENDFACT_INV_SRC_ALPHA},
-    /* OverReverse */
-    {1, 0, BLENDFACT_INV_DST_ALPHA, BLENDFACT_ONE},
-    /* In */
-    {1, 0, BLENDFACT_DST_ALPHA,     BLENDFACT_ZERO},
-    /* InReverse */
-    {0, 1, BLENDFACT_ZERO,          BLENDFACT_SRC_ALPHA},
-    /* Out */
-    {1, 0, BLENDFACT_INV_DST_ALPHA, BLENDFACT_ZERO},
-    /* OutReverse */
-    {0, 1, BLENDFACT_ZERO,          BLENDFACT_INV_SRC_ALPHA},
-    /* Atop */
-    {1, 1, BLENDFACT_DST_ALPHA,     BLENDFACT_INV_SRC_ALPHA},
-    /* AtopReverse */
-    {1, 1, BLENDFACT_INV_DST_ALPHA, BLENDFACT_SRC_ALPHA},
-    /* Xor */
-    {1, 1, BLENDFACT_INV_DST_ALPHA, BLENDFACT_INV_SRC_ALPHA},
-    /* Add */
-    {0, 0, BLENDFACT_ONE,           BLENDFACT_ONE},
-};
-
-static struct formatinfo I915TexFormats[] = {
-        {PICT_a8r8g8b8, MAPSURF_32BIT | MT_32BIT_ARGB8888 },
-        {PICT_x8r8g8b8, MAPSURF_32BIT | MT_32BIT_XRGB8888 },
-        {PICT_a8b8g8r8, MAPSURF_32BIT | MT_32BIT_ABGR8888 },
-        {PICT_x8b8g8r8, MAPSURF_32BIT | MT_32BIT_XBGR8888 },
-        {PICT_r5g6b5,   MAPSURF_16BIT | MT_16BIT_RGB565   },
-        {PICT_a1r5g5b5, MAPSURF_16BIT | MT_16BIT_ARGB1555 },
-        {PICT_x1r5g5b5, MAPSURF_16BIT | MT_16BIT_ARGB1555 },
-        {PICT_a4r4g4b4, MAPSURF_16BIT | MT_16BIT_ARGB4444 },
-        {PICT_x4r4g4b4, MAPSURF_16BIT | MT_16BIT_ARGB4444 },
-        {PICT_a8,       MAPSURF_8BIT | MT_8BIT_A8 	  },
-};
-
-static CARD32 I915GetBlendCntl(int op, PicturePtr pMask, CARD32 dst_format)
-{
-    CARD32 sblend, dblend;
-
-    sblend = I915BlendOp[op].src_blend;
-    dblend = I915BlendOp[op].dst_blend;
-
-    /* If there's no dst alpha channel, adjust the blend op so that we'll treat
-     * it as always 1.
-     */
-    if (PICT_FORMAT_A(dst_format) == 0 && I915BlendOp[op].dst_alpha) {
-        if (sblend == BLENDFACT_DST_ALPHA)
-            sblend = BLENDFACT_ONE;
-        else if (sblend == BLENDFACT_INV_DST_ALPHA)
-            sblend = BLENDFACT_ZERO;
-    }
-
-    /* If the source alpha is being used, then we should only be in a case where
-     * the source blend factor is 0, and the source blend value is the mask
-     * channels multiplied by the source picture's alpha.
-     */
-    if (pMask && pMask->componentAlpha && PICT_FORMAT_RGB(pMask->format) &&
-	I915BlendOp[op].src_alpha)
-    {
-        if (dblend == BLENDFACT_SRC_ALPHA) {
-	    dblend = BLENDFACT_SRC_COLR;
-        } else if (dblend == BLENDFACT_INV_SRC_ALPHA) {
-	    dblend = BLENDFACT_INV_SRC_COLR;
-        }
-    }
-
-    return (sblend << S6_CBUF_SRC_BLEND_FACT_SHIFT) |
-	(dblend << S6_CBUF_DST_BLEND_FACT_SHIFT);
-}
-
-static Bool I915GetDestFormat(PicturePtr pDstPicture, CARD32 *dst_format)
-{
-    switch (pDstPicture->format) {
-    case PICT_a8r8g8b8:
-    case PICT_x8r8g8b8:
-        *dst_format = COLR_BUF_ARGB8888;
-        break;
-    case PICT_r5g6b5:
-        *dst_format = COLR_BUF_RGB565;
-        break;
-    case PICT_a1r5g5b5:
-    case PICT_x1r5g5b5:
-        *dst_format = COLR_BUF_ARGB1555;
-        break;
-    /* COLR_BUF_8BIT is special for YUV surfaces.  While we may end up being
-     * able to use it depending on how the hardware implements it, disable it
-     * for now while we don't know what exactly it does (what channel does it
-     * read from?
-     */
-    /*
-    case PICT_a8:
-        *dst_format = COLR_BUF_8BIT;
-        break;
-    */
-    case PICT_a4r4g4b4:
-    case PICT_x4r4g4b4:
-	*dst_format = COLR_BUF_ARGB4444;
-	break;
-    default:
-        I830FALLBACK("Unsupported dest format 0x%x\n",
-                        (int)pDstPicture->format);
-    }
-
-    return TRUE;
-}
-
-static Bool I915CheckCompositeTexture(PicturePtr pPict, int unit)
-{
-    int w = pPict->pDrawable->width;
-    int h = pPict->pDrawable->height;
-    int i;
-
-    if ((w > 0x7ff) || (h > 0x7ff))
-        I830FALLBACK("Picture w/h too large (%dx%d)\n", w, h);
-
-    for (i = 0; i < sizeof(I915TexFormats) / sizeof(I915TexFormats[0]); i++)
-    {
-        if (I915TexFormats[i].fmt == pPict->format)
-            break;
-    }
-    if (i == sizeof(I915TexFormats) / sizeof(I915TexFormats[0]))
-        I830FALLBACK("Unsupported picture format 0x%x\n",
-                         (int)pPict->format);
-
-    if (pPict->repeat && pPict->repeatType != RepeatNormal)
-	I830FALLBACK("extended repeat (%d) not supported\n",
-		     pPict->repeatType);
-
-    if (pPict->filter != PictFilterNearest &&
-        pPict->filter != PictFilterBilinear)
-        I830FALLBACK("Unsupported filter 0x%x\n", pPict->filter);
-
-    return TRUE;
-}
-
-Bool
-I915EXACheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
-		      PicturePtr pDstPicture)
-{
-    CARD32 tmp1;
-
-    /* Check for unsupported compositing operations. */
-    if (op >= sizeof(I915BlendOp) / sizeof(I915BlendOp[0]))
-        I830FALLBACK("Unsupported Composite op 0x%x\n", op);
-    if (pMaskPicture != NULL && pMaskPicture->componentAlpha &&
-	PICT_FORMAT_RGB(pMaskPicture->format))
-    {
-        /* Check if it's component alpha that relies on a source alpha and on
-         * the source value.  We can only get one of those into the single
-         * source value that we get to blend with.
-         */
-        if (I915BlendOp[op].src_alpha &&
-            (I915BlendOp[op].src_blend != BLENDFACT_ZERO))
-            	I830FALLBACK("Component alpha not supported with source "
-                            "alpha and source value blending.\n");
-    }
-
-    if (!I915CheckCompositeTexture(pSrcPicture, 0))
-        I830FALLBACK("Check Src picture texture\n");
-    if (pMaskPicture != NULL && !I915CheckCompositeTexture(pMaskPicture, 1))
-        I830FALLBACK("Check Mask picture texture\n");
-
-    if (!I915GetDestFormat(pDstPicture, &tmp1))
-	I830FALLBACK("Get Color buffer format\n");
-
-    return TRUE;
-}
-
-static Bool
-I915TextureSetup(PicturePtr pPict, PixmapPtr pPix, int unit)
-{
-    ScrnInfoPtr pScrn = xf86Screens[pPict->pDrawable->pScreen->myNum];
-    I830Ptr pI830 = I830PTR(pScrn);
-    CARD32 format, offset, pitch, filter;
-    int w, h, i;
-    CARD32 wrap_mode = TEXCOORDMODE_CLAMP_BORDER;
-
-    offset = intel_get_pixmap_offset(pPix);
-    pitch = intel_get_pixmap_pitch(pPix);
-    w = pPict->pDrawable->width;
-    h = pPict->pDrawable->height;
-    pI830->scale_units[unit][0] = pPix->drawable.width;
-    pI830->scale_units[unit][1] = pPix->drawable.height;
-
-    for (i = 0; i < sizeof(I915TexFormats) / sizeof(I915TexFormats[0]); i++) {
-        if (I915TexFormats[i].fmt == pPict->format)
-	    break;
-    }
-    if (i == sizeof(I915TexFormats)/ sizeof(I915TexFormats[0]))
-	I830FALLBACK("unknown texture format\n");
-    format = I915TexFormats[i].card_fmt;
-
-    if (pPict->repeat)
-	wrap_mode = TEXCOORDMODE_WRAP;
-
-    switch (pPict->filter) {
-    case PictFilterNearest:
-        filter = (FILTER_NEAREST << SS2_MAG_FILTER_SHIFT) |
-			(FILTER_NEAREST << SS2_MIN_FILTER_SHIFT);
-        break;
-    case PictFilterBilinear:
-        filter = (FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) |
-			(FILTER_LINEAR << SS2_MIN_FILTER_SHIFT);
-        break;
-    default:
-	filter = 0;
-        I830FALLBACK("Bad filter 0x%x\n", pPict->filter);
-    }
-
-    pI830->mapstate[unit * 3 + 0] = offset;
-    pI830->mapstate[unit * 3 + 1] = format |
-	((pPix->drawable.height - 1) << MS3_HEIGHT_SHIFT) |
-	((pPix->drawable.width - 1) << MS3_WIDTH_SHIFT);
-    if (!pI830->disableTiling)
-	pI830->samplerstate[unit * 3 + 1] |= MS3_USE_FENCE_REGS;
-    pI830->mapstate[unit * 3 + 2] = ((pitch / 4) - 1) << MS4_PITCH_SHIFT;
-
-    pI830->samplerstate[unit * 3 + 0] = (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT);
-    pI830->samplerstate[unit * 3 + 0] |= filter;
-    pI830->samplerstate[unit * 3 + 1] = SS3_NORMALIZED_COORDS;
-    pI830->samplerstate[unit * 3 + 1] |= wrap_mode << SS3_TCX_ADDR_MODE_SHIFT;
-    pI830->samplerstate[unit * 3 + 1] |= wrap_mode << SS3_TCY_ADDR_MODE_SHIFT;
-    pI830->samplerstate[unit * 3 + 1] |= unit << SS3_TEXTUREMAP_INDEX_SHIFT;
-    pI830->samplerstate[unit * 3 + 2] = 0x00000000; /* border color */
-
-    pI830->transform[unit] = pPict->transform;
-
-    return TRUE;
-}
-
-Bool
-I915EXAPrepareComposite(int op, PicturePtr pSrcPicture,
-			PicturePtr pMaskPicture, PicturePtr pDstPicture,
-			PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
-{
-    ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum];
-    I830Ptr pI830 = I830PTR(pScrn);
-    CARD32 dst_format, dst_offset, dst_pitch;
-    CARD32 blendctl;
-
-#ifdef I830DEBUG
-    ErrorF("Enter i915 prepareComposite\n");
-#endif
-
-    pI830->last_3d = LAST_3D_RENDER;
-
-    I915GetDestFormat(pDstPicture, &dst_format);
-    dst_offset = intel_get_pixmap_offset(pDst);
-    dst_pitch = intel_get_pixmap_pitch(pDst);
-    FS_LOCALS(20);
-
-    if (!I915TextureSetup(pSrcPicture, pSrc, 0))
-	I830FALLBACK("fail to setup src texture\n");
-    if (pMask != NULL) {
-	if (!I915TextureSetup(pMaskPicture, pMask, 1))
-		I830FALLBACK("fail to setup mask texture\n");
-    } else {
-	pI830->transform[1] = NULL;
-	pI830->scale_units[1][0] = -1;
-	pI830->scale_units[1][1] = -1;
-    }
-
-    if (pMask == NULL) {
-	BEGIN_LP_RING(10);
-	OUT_RING(_3DSTATE_MAP_STATE | 3);
-	OUT_RING(0x00000001); /* map 0 */
-	OUT_RING(pI830->mapstate[0]);
-	OUT_RING(pI830->mapstate[1]);
-	OUT_RING(pI830->mapstate[2]);
-
-	OUT_RING(_3DSTATE_SAMPLER_STATE | 3);
-	OUT_RING(0x00000001); /* sampler 0 */
-	OUT_RING(pI830->samplerstate[0]);
-	OUT_RING(pI830->samplerstate[1]);
-	OUT_RING(pI830->samplerstate[2]);
-	ADVANCE_LP_RING();
-    } else {
-	BEGIN_LP_RING(16);
-	OUT_RING(_3DSTATE_MAP_STATE | 6);
-	OUT_RING(0x00000003); /* map 0,1 */
-	OUT_RING(pI830->mapstate[0]);
-	OUT_RING(pI830->mapstate[1]);
-	OUT_RING(pI830->mapstate[2]);
-	OUT_RING(pI830->mapstate[3]);
-	OUT_RING(pI830->mapstate[4]);
-	OUT_RING(pI830->mapstate[5]);
-
-	OUT_RING(_3DSTATE_SAMPLER_STATE | 6);
-	OUT_RING(0x00000003); /* sampler 0,1 */
-	OUT_RING(pI830->samplerstate[0]);
-	OUT_RING(pI830->samplerstate[1]);
-	OUT_RING(pI830->samplerstate[2]);
-	OUT_RING(pI830->samplerstate[3]);
-	OUT_RING(pI830->samplerstate[4]);
-	OUT_RING(pI830->samplerstate[5]);
-	ADVANCE_LP_RING();
-    }
-    {
-	CARD32 ss2;
-
-	BEGIN_LP_RING(18);
-	/* color buffer
-	 * XXX: Need to add USE_FENCE if we ever tile the X Server's pixmaps or
-	 * visible screen.
-	 */
-	OUT_RING(_3DSTATE_BUF_INFO_CMD);
-	OUT_RING(BUF_3D_ID_COLOR_BACK| BUF_3D_PITCH(dst_pitch));
-	OUT_RING(BUF_3D_ADDR(dst_offset));
-
-	OUT_RING(_3DSTATE_DST_BUF_VARS_CMD);
-	OUT_RING(dst_format);
-
-	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) |
-		 I1_LOAD_S(4) | I1_LOAD_S(5) | I1_LOAD_S(6) | 3);
-	ss2 = S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D);
-	if (pMask)
-		ss2 |= S2_TEXCOORD_FMT(1, TEXCOORDFMT_2D);
-	else
-		ss2 |= S2_TEXCOORD_FMT(1, TEXCOORDFMT_NOT_PRESENT);
-	ss2 |= S2_TEXCOORD_FMT(2, TEXCOORDFMT_NOT_PRESENT);
-	ss2 |= S2_TEXCOORD_FMT(3, TEXCOORDFMT_NOT_PRESENT);
-	ss2 |= S2_TEXCOORD_FMT(4, TEXCOORDFMT_NOT_PRESENT);
-	ss2 |= S2_TEXCOORD_FMT(5, TEXCOORDFMT_NOT_PRESENT);
-	ss2 |= S2_TEXCOORD_FMT(6, TEXCOORDFMT_NOT_PRESENT);
-	ss2 |= S2_TEXCOORD_FMT(7, TEXCOORDFMT_NOT_PRESENT);
-	OUT_RING(ss2);
-	OUT_RING((1 << S4_POINT_WIDTH_SHIFT) | S4_LINE_WIDTH_ONE |
-		 S4_CULLMODE_NONE| S4_VFMT_XY);
-	blendctl = I915GetBlendCntl(op, pMaskPicture, pDstPicture->format);
-	OUT_RING(0x00000000); /* Disable stencil buffer */
-	OUT_RING(S6_CBUF_BLEND_ENABLE | S6_COLOR_WRITE_ENABLE |
-		 (BLENDFUNC_ADD << S6_CBUF_BLEND_FUNC_SHIFT) | blendctl);
-
-	/* issue a flush */
-	OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
-	OUT_RING(MI_NOOP);
-
-	/* draw rect is unconditional */
-	OUT_RING(_3DSTATE_DRAW_RECT_CMD);
-	OUT_RING(0x00000000);
-	OUT_RING(0x00000000);  /* ymin, xmin*/
-	OUT_RING(DRAW_YMAX(pDst->drawable.height - 1) |
-		 DRAW_XMAX(pDst->drawable.width - 1));
-	OUT_RING(0x00000000);  /* yorig, xorig (relate to color buffer?)*/
-	OUT_RING(MI_NOOP);
-	ADVANCE_LP_RING();
-    }
-
-    FS_BEGIN();
-
-    /* Declare the registers necessary for our program.  I don't think the
-     * S then T ordering is necessary.
-     */
-    i915_fs_dcl(FS_S0);
-    if (pMask)
-	i915_fs_dcl(FS_S1);
-    i915_fs_dcl(FS_T0);
-    if (pMask)
-	i915_fs_dcl(FS_T1);
-
-    /* Load the pSrcPicture texel */
-    i915_fs_texld(FS_R0, FS_S0, FS_T0);
-    /* If the texture lacks an alpha channel, force the alpha to 1. */
-    if (PICT_FORMAT_A(pSrcPicture->format) == 0)
-	i915_fs_mov_masked(FS_R0, MASK_W, i915_fs_operand_one());
-
-    if (!pMask) {
-	/* No mask, so move to output color */
-	i915_fs_mov(FS_OC, i915_fs_operand_reg(FS_R0));
-    } else {
-	/* Load the pMaskPicture texel */
-	i915_fs_texld(FS_R1, FS_S1, FS_T1);
-	/* If the texture lacks an alpha channel, force the alpha to 1. */
-	if (PICT_FORMAT_A(pMaskPicture->format) == 0)
-	    i915_fs_mov_masked(FS_R1, MASK_W, i915_fs_operand_one());
-
-	/* If component alpha is active in the mask and the blend operation
-	 * uses the source alpha, then we know we don't need the source
-	 * value (otherwise we would have hit a fallback earlier), so we
-	 * provide the source alpha (src.A * mask.X) as output color.
-	 * Conversely, if CA is set and we don't need the source alpha, then
-	 * we produce the source value (src.X * mask.X) and the source alpha
-	 * is unused..  Otherwise, we provide the non-CA source value
-	 * (src.X * mask.A).
-	 */
-	if (pMaskPicture->componentAlpha &&
-	    PICT_FORMAT_RGB(pMaskPicture->format))
-	{
-	    if (I915BlendOp[op].src_alpha) {
-		i915_fs_mul(FS_OC, i915_fs_operand(FS_R0, W, W, W, W),
-			    i915_fs_operand_reg(FS_R1));
-	    } else {
-		i915_fs_mul(FS_OC, i915_fs_operand_reg(FS_R0),
-			    i915_fs_operand_reg(FS_R1));
-	    }
-	} else {
-	    i915_fs_mul(FS_OC, i915_fs_operand_reg(FS_R0),
-			i915_fs_operand(FS_R1, W, W, W, W));
-	}
-    }
-    FS_END();
-
-    return TRUE;
-}
diff --git a/src/i915_render.c b/src/i915_render.c
new file mode 100644
index 0000000..2fb41ad
--- /dev/null
+++ b/src/i915_render.c
@@ -0,0 +1,477 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Wang Zhenyu <zhenyu.z.wang at intel.com>
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "i830.h"
+#include "i915_reg.h"
+#include "i915_3d.h"
+
+#ifdef I830DEBUG
+#define DEBUG_I830FALLBACK 1
+#endif
+
+#ifdef DEBUG_I830FALLBACK
+#define I830FALLBACK(s, arg...)				\
+do {							\
+	DPRINTF(PFX, "EXA fallback: " s "\n", ##arg); 	\
+	return FALSE;					\
+} while(0)
+#else
+#define I830FALLBACK(s, arg...) 			\
+do { 							\
+	return FALSE;					\
+} while(0)
+#endif
+
+struct formatinfo {
+    int fmt;
+    CARD32 card_fmt;
+};
+
+struct blendinfo {
+    Bool dst_alpha;
+    Bool src_alpha;
+    CARD32 src_blend;
+    CARD32 dst_blend;
+};
+
+static struct blendinfo I915BlendOp[] = {
+    /* Clear */
+    {0, 0, BLENDFACT_ZERO,          BLENDFACT_ZERO},
+    /* Src */
+    {0, 0, BLENDFACT_ONE,           BLENDFACT_ZERO},
+    /* Dst */
+    {0, 0, BLENDFACT_ZERO,          BLENDFACT_ONE},
+    /* Over */
+    {0, 1, BLENDFACT_ONE,           BLENDFACT_INV_SRC_ALPHA},
+    /* OverReverse */
+    {1, 0, BLENDFACT_INV_DST_ALPHA, BLENDFACT_ONE},
+    /* In */
+    {1, 0, BLENDFACT_DST_ALPHA,     BLENDFACT_ZERO},
+    /* InReverse */
+    {0, 1, BLENDFACT_ZERO,          BLENDFACT_SRC_ALPHA},
+    /* Out */
+    {1, 0, BLENDFACT_INV_DST_ALPHA, BLENDFACT_ZERO},
+    /* OutReverse */
+    {0, 1, BLENDFACT_ZERO,          BLENDFACT_INV_SRC_ALPHA},
+    /* Atop */
+    {1, 1, BLENDFACT_DST_ALPHA,     BLENDFACT_INV_SRC_ALPHA},
+    /* AtopReverse */
+    {1, 1, BLENDFACT_INV_DST_ALPHA, BLENDFACT_SRC_ALPHA},
+    /* Xor */
+    {1, 1, BLENDFACT_INV_DST_ALPHA, BLENDFACT_INV_SRC_ALPHA},
+    /* Add */
+    {0, 0, BLENDFACT_ONE,           BLENDFACT_ONE},
+};
+
+static struct formatinfo I915TexFormats[] = {
+        {PICT_a8r8g8b8, MAPSURF_32BIT | MT_32BIT_ARGB8888 },
+        {PICT_x8r8g8b8, MAPSURF_32BIT | MT_32BIT_XRGB8888 },
+        {PICT_a8b8g8r8, MAPSURF_32BIT | MT_32BIT_ABGR8888 },
+        {PICT_x8b8g8r8, MAPSURF_32BIT | MT_32BIT_XBGR8888 },
+        {PICT_r5g6b5,   MAPSURF_16BIT | MT_16BIT_RGB565   },
+        {PICT_a1r5g5b5, MAPSURF_16BIT | MT_16BIT_ARGB1555 },
+        {PICT_x1r5g5b5, MAPSURF_16BIT | MT_16BIT_ARGB1555 },
+        {PICT_a4r4g4b4, MAPSURF_16BIT | MT_16BIT_ARGB4444 },
+        {PICT_x4r4g4b4, MAPSURF_16BIT | MT_16BIT_ARGB4444 },
+        {PICT_a8,       MAPSURF_8BIT | MT_8BIT_A8 	  },
+};
+
+static CARD32 I915GetBlendCntl(int op, PicturePtr pMask, CARD32 dst_format)
+{
+    CARD32 sblend, dblend;
+
+    sblend = I915BlendOp[op].src_blend;
+    dblend = I915BlendOp[op].dst_blend;
+
+    /* If there's no dst alpha channel, adjust the blend op so that we'll treat
+     * it as always 1.
+     */
+    if (PICT_FORMAT_A(dst_format) == 0 && I915BlendOp[op].dst_alpha) {
+        if (sblend == BLENDFACT_DST_ALPHA)
+            sblend = BLENDFACT_ONE;
+        else if (sblend == BLENDFACT_INV_DST_ALPHA)
+            sblend = BLENDFACT_ZERO;
+    }
+
+    /* If the source alpha is being used, then we should only be in a case where
+     * the source blend factor is 0, and the source blend value is the mask
+     * channels multiplied by the source picture's alpha.
+     */
+    if (pMask && pMask->componentAlpha && PICT_FORMAT_RGB(pMask->format) &&
+	I915BlendOp[op].src_alpha)
+    {
+        if (dblend == BLENDFACT_SRC_ALPHA) {
+	    dblend = BLENDFACT_SRC_COLR;
+        } else if (dblend == BLENDFACT_INV_SRC_ALPHA) {
+	    dblend = BLENDFACT_INV_SRC_COLR;
+        }
+    }
+
+    return (sblend << S6_CBUF_SRC_BLEND_FACT_SHIFT) |
+	(dblend << S6_CBUF_DST_BLEND_FACT_SHIFT);
+}
+
+static Bool I915GetDestFormat(PicturePtr pDstPicture, CARD32 *dst_format)
+{
+    switch (pDstPicture->format) {
+    case PICT_a8r8g8b8:
+    case PICT_x8r8g8b8:
+        *dst_format = COLR_BUF_ARGB8888;
+        break;
+    case PICT_r5g6b5:
+        *dst_format = COLR_BUF_RGB565;
+        break;
+    case PICT_a1r5g5b5:
+    case PICT_x1r5g5b5:
+        *dst_format = COLR_BUF_ARGB1555;
+        break;
+    /* COLR_BUF_8BIT is special for YUV surfaces.  While we may end up being
+     * able to use it depending on how the hardware implements it, disable it
+     * for now while we don't know what exactly it does (what channel does it
+     * read from?
+     */
+    /*
+    case PICT_a8:
+        *dst_format = COLR_BUF_8BIT;
+        break;
+    */
+    case PICT_a4r4g4b4:
+    case PICT_x4r4g4b4:
+	*dst_format = COLR_BUF_ARGB4444;
+	break;
+    default:
+        I830FALLBACK("Unsupported dest format 0x%x\n",
+                        (int)pDstPicture->format);
+    }
+
+    return TRUE;
+}
+
+static Bool I915CheckCompositeTexture(PicturePtr pPict, int unit)
+{
+    int w = pPict->pDrawable->width;
+    int h = pPict->pDrawable->height;
+    int i;
+
+    if ((w > 0x7ff) || (h > 0x7ff))
+        I830FALLBACK("Picture w/h too large (%dx%d)\n", w, h);
+
+    for (i = 0; i < sizeof(I915TexFormats) / sizeof(I915TexFormats[0]); i++)
+    {
+        if (I915TexFormats[i].fmt == pPict->format)
+            break;
+    }
+    if (i == sizeof(I915TexFormats) / sizeof(I915TexFormats[0]))
+        I830FALLBACK("Unsupported picture format 0x%x\n",
+                         (int)pPict->format);
+
+    if (pPict->repeat && pPict->repeatType != RepeatNormal)
+	I830FALLBACK("extended repeat (%d) not supported\n",
+		     pPict->repeatType);
+
+    if (pPict->filter != PictFilterNearest &&
+        pPict->filter != PictFilterBilinear)
+        I830FALLBACK("Unsupported filter 0x%x\n", pPict->filter);
+
+    return TRUE;
+}
+
+Bool
+I915EXACheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+		      PicturePtr pDstPicture)
+{
+    CARD32 tmp1;
+
+    /* Check for unsupported compositing operations. */
+    if (op >= sizeof(I915BlendOp) / sizeof(I915BlendOp[0]))
+        I830FALLBACK("Unsupported Composite op 0x%x\n", op);
+    if (pMaskPicture != NULL && pMaskPicture->componentAlpha &&
+	PICT_FORMAT_RGB(pMaskPicture->format))
+    {
+        /* Check if it's component alpha that relies on a source alpha and on
+         * the source value.  We can only get one of those into the single
+         * source value that we get to blend with.
+         */
+        if (I915BlendOp[op].src_alpha &&
+            (I915BlendOp[op].src_blend != BLENDFACT_ZERO))
+            	I830FALLBACK("Component alpha not supported with source "
+                            "alpha and source value blending.\n");
+    }
+
+    if (!I915CheckCompositeTexture(pSrcPicture, 0))
+        I830FALLBACK("Check Src picture texture\n");
+    if (pMaskPicture != NULL && !I915CheckCompositeTexture(pMaskPicture, 1))
+        I830FALLBACK("Check Mask picture texture\n");
+
+    if (!I915GetDestFormat(pDstPicture, &tmp1))
+	I830FALLBACK("Get Color buffer format\n");
+
+    return TRUE;
+}
+
+static Bool
+I915TextureSetup(PicturePtr pPict, PixmapPtr pPix, int unit)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pPict->pDrawable->pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD32 format, offset, pitch, filter;
+    int w, h, i;
+    CARD32 wrap_mode = TEXCOORDMODE_CLAMP_BORDER;
+
+    offset = intel_get_pixmap_offset(pPix);
+    pitch = intel_get_pixmap_pitch(pPix);
+    w = pPict->pDrawable->width;
+    h = pPict->pDrawable->height;
+    pI830->scale_units[unit][0] = pPix->drawable.width;
+    pI830->scale_units[unit][1] = pPix->drawable.height;
+
+    for (i = 0; i < sizeof(I915TexFormats) / sizeof(I915TexFormats[0]); i++) {
+        if (I915TexFormats[i].fmt == pPict->format)
+	    break;
+    }
+    if (i == sizeof(I915TexFormats)/ sizeof(I915TexFormats[0]))
+	I830FALLBACK("unknown texture format\n");
+    format = I915TexFormats[i].card_fmt;
+
+    if (pPict->repeat)
+	wrap_mode = TEXCOORDMODE_WRAP;
+
+    switch (pPict->filter) {
+    case PictFilterNearest:
+        filter = (FILTER_NEAREST << SS2_MAG_FILTER_SHIFT) |
+			(FILTER_NEAREST << SS2_MIN_FILTER_SHIFT);
+        break;
+    case PictFilterBilinear:
+        filter = (FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) |
+			(FILTER_LINEAR << SS2_MIN_FILTER_SHIFT);
+        break;
+    default:
+	filter = 0;
+        I830FALLBACK("Bad filter 0x%x\n", pPict->filter);
+    }
+
+    pI830->mapstate[unit * 3 + 0] = offset;
+    pI830->mapstate[unit * 3 + 1] = format |
+	((pPix->drawable.height - 1) << MS3_HEIGHT_SHIFT) |
+	((pPix->drawable.width - 1) << MS3_WIDTH_SHIFT);
+    if (!pI830->disableTiling)
+	pI830->samplerstate[unit * 3 + 1] |= MS3_USE_FENCE_REGS;
+    pI830->mapstate[unit * 3 + 2] = ((pitch / 4) - 1) << MS4_PITCH_SHIFT;
+
+    pI830->samplerstate[unit * 3 + 0] = (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT);
+    pI830->samplerstate[unit * 3 + 0] |= filter;
+    pI830->samplerstate[unit * 3 + 1] = SS3_NORMALIZED_COORDS;
+    pI830->samplerstate[unit * 3 + 1] |= wrap_mode << SS3_TCX_ADDR_MODE_SHIFT;
+    pI830->samplerstate[unit * 3 + 1] |= wrap_mode << SS3_TCY_ADDR_MODE_SHIFT;
+    pI830->samplerstate[unit * 3 + 1] |= unit << SS3_TEXTUREMAP_INDEX_SHIFT;
+    pI830->samplerstate[unit * 3 + 2] = 0x00000000; /* border color */
+
+    pI830->transform[unit] = pPict->transform;
+
+    return TRUE;
+}
+
+Bool
+I915EXAPrepareComposite(int op, PicturePtr pSrcPicture,
+			PicturePtr pMaskPicture, PicturePtr pDstPicture,
+			PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD32 dst_format, dst_offset, dst_pitch;
+    CARD32 blendctl;
+
+#ifdef I830DEBUG
+    ErrorF("Enter i915 prepareComposite\n");
+#endif
+
+    pI830->last_3d = LAST_3D_RENDER;
+
+    I915GetDestFormat(pDstPicture, &dst_format);
+    dst_offset = intel_get_pixmap_offset(pDst);
+    dst_pitch = intel_get_pixmap_pitch(pDst);
+    FS_LOCALS(20);
+
+    if (!I915TextureSetup(pSrcPicture, pSrc, 0))
+	I830FALLBACK("fail to setup src texture\n");
+    if (pMask != NULL) {
+	if (!I915TextureSetup(pMaskPicture, pMask, 1))
+		I830FALLBACK("fail to setup mask texture\n");
+    } else {
+	pI830->transform[1] = NULL;
+	pI830->scale_units[1][0] = -1;
+	pI830->scale_units[1][1] = -1;
+    }
+
+    if (pMask == NULL) {
+	BEGIN_LP_RING(10);
+	OUT_RING(_3DSTATE_MAP_STATE | 3);
+	OUT_RING(0x00000001); /* map 0 */
+	OUT_RING(pI830->mapstate[0]);
+	OUT_RING(pI830->mapstate[1]);
+	OUT_RING(pI830->mapstate[2]);
+
+	OUT_RING(_3DSTATE_SAMPLER_STATE | 3);
+	OUT_RING(0x00000001); /* sampler 0 */
+	OUT_RING(pI830->samplerstate[0]);
+	OUT_RING(pI830->samplerstate[1]);
+	OUT_RING(pI830->samplerstate[2]);
+	ADVANCE_LP_RING();
+    } else {
+	BEGIN_LP_RING(16);
+	OUT_RING(_3DSTATE_MAP_STATE | 6);
+	OUT_RING(0x00000003); /* map 0,1 */
+	OUT_RING(pI830->mapstate[0]);
+	OUT_RING(pI830->mapstate[1]);
+	OUT_RING(pI830->mapstate[2]);
+	OUT_RING(pI830->mapstate[3]);
+	OUT_RING(pI830->mapstate[4]);
+	OUT_RING(pI830->mapstate[5]);
+
+	OUT_RING(_3DSTATE_SAMPLER_STATE | 6);
+	OUT_RING(0x00000003); /* sampler 0,1 */
+	OUT_RING(pI830->samplerstate[0]);
+	OUT_RING(pI830->samplerstate[1]);
+	OUT_RING(pI830->samplerstate[2]);
+	OUT_RING(pI830->samplerstate[3]);
+	OUT_RING(pI830->samplerstate[4]);
+	OUT_RING(pI830->samplerstate[5]);
+	ADVANCE_LP_RING();
+    }
+    {
+	CARD32 ss2;
+
+	BEGIN_LP_RING(18);
+	/* color buffer
+	 * XXX: Need to add USE_FENCE if we ever tile the X Server's pixmaps or
+	 * visible screen.
+	 */
+	OUT_RING(_3DSTATE_BUF_INFO_CMD);
+	OUT_RING(BUF_3D_ID_COLOR_BACK| BUF_3D_PITCH(dst_pitch));
+	OUT_RING(BUF_3D_ADDR(dst_offset));
+
+	OUT_RING(_3DSTATE_DST_BUF_VARS_CMD);
+	OUT_RING(dst_format);
+
+	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) |
+		 I1_LOAD_S(4) | I1_LOAD_S(5) | I1_LOAD_S(6) | 3);
+	ss2 = S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D);
+	if (pMask)
+		ss2 |= S2_TEXCOORD_FMT(1, TEXCOORDFMT_2D);
+	else
+		ss2 |= S2_TEXCOORD_FMT(1, TEXCOORDFMT_NOT_PRESENT);
+	ss2 |= S2_TEXCOORD_FMT(2, TEXCOORDFMT_NOT_PRESENT);
+	ss2 |= S2_TEXCOORD_FMT(3, TEXCOORDFMT_NOT_PRESENT);
+	ss2 |= S2_TEXCOORD_FMT(4, TEXCOORDFMT_NOT_PRESENT);
+	ss2 |= S2_TEXCOORD_FMT(5, TEXCOORDFMT_NOT_PRESENT);
+	ss2 |= S2_TEXCOORD_FMT(6, TEXCOORDFMT_NOT_PRESENT);
+	ss2 |= S2_TEXCOORD_FMT(7, TEXCOORDFMT_NOT_PRESENT);
+	OUT_RING(ss2);
+	OUT_RING((1 << S4_POINT_WIDTH_SHIFT) | S4_LINE_WIDTH_ONE |
+		 S4_CULLMODE_NONE| S4_VFMT_XY);
+	blendctl = I915GetBlendCntl(op, pMaskPicture, pDstPicture->format);
+	OUT_RING(0x00000000); /* Disable stencil buffer */
+	OUT_RING(S6_CBUF_BLEND_ENABLE | S6_COLOR_WRITE_ENABLE |
+		 (BLENDFUNC_ADD << S6_CBUF_BLEND_FUNC_SHIFT) | blendctl);
+
+	/* issue a flush */
+	OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
+	OUT_RING(MI_NOOP);
+
+	/* draw rect is unconditional */
+	OUT_RING(_3DSTATE_DRAW_RECT_CMD);
+	OUT_RING(0x00000000);
+	OUT_RING(0x00000000);  /* ymin, xmin*/
+	OUT_RING(DRAW_YMAX(pDst->drawable.height - 1) |
+		 DRAW_XMAX(pDst->drawable.width - 1));
+	OUT_RING(0x00000000);  /* yorig, xorig (relate to color buffer?)*/
+	OUT_RING(MI_NOOP);
+	ADVANCE_LP_RING();
+    }
+
+    FS_BEGIN();
+
+    /* Declare the registers necessary for our program.  I don't think the
+     * S then T ordering is necessary.
+     */
+    i915_fs_dcl(FS_S0);
+    if (pMask)
+	i915_fs_dcl(FS_S1);
+    i915_fs_dcl(FS_T0);
+    if (pMask)
+	i915_fs_dcl(FS_T1);
+
+    /* Load the pSrcPicture texel */
+    i915_fs_texld(FS_R0, FS_S0, FS_T0);
+    /* If the texture lacks an alpha channel, force the alpha to 1. */
+    if (PICT_FORMAT_A(pSrcPicture->format) == 0)
+	i915_fs_mov_masked(FS_R0, MASK_W, i915_fs_operand_one());
+
+    if (!pMask) {
+	/* No mask, so move to output color */
+	i915_fs_mov(FS_OC, i915_fs_operand_reg(FS_R0));
+    } else {
+	/* Load the pMaskPicture texel */
+	i915_fs_texld(FS_R1, FS_S1, FS_T1);
+	/* If the texture lacks an alpha channel, force the alpha to 1. */
+	if (PICT_FORMAT_A(pMaskPicture->format) == 0)
+	    i915_fs_mov_masked(FS_R1, MASK_W, i915_fs_operand_one());
+
+	/* If component alpha is active in the mask and the blend operation
+	 * uses the source alpha, then we know we don't need the source
+	 * value (otherwise we would have hit a fallback earlier), so we
+	 * provide the source alpha (src.A * mask.X) as output color.
+	 * Conversely, if CA is set and we don't need the source alpha, then
+	 * we produce the source value (src.X * mask.X) and the source alpha
+	 * is unused..  Otherwise, we provide the non-CA source value
+	 * (src.X * mask.A).
+	 */
+	if (pMaskPicture->componentAlpha &&
+	    PICT_FORMAT_RGB(pMaskPicture->format))
+	{
+	    if (I915BlendOp[op].src_alpha) {
+		i915_fs_mul(FS_OC, i915_fs_operand(FS_R0, W, W, W, W),
+			    i915_fs_operand_reg(FS_R1));
+	    } else {
+		i915_fs_mul(FS_OC, i915_fs_operand_reg(FS_R0),
+			    i915_fs_operand_reg(FS_R1));
+	    }
+	} else {
+	    i915_fs_mul(FS_OC, i915_fs_operand_reg(FS_R0),
+			i915_fs_operand(FS_R1, W, W, W, W));
+	}
+    }
+    FS_END();
+
+    return TRUE;
+}
diff --git a/src/i915_video.c b/src/i915_video.c
index 591b6f8..e837097 100644
--- a/src/i915_video.c
+++ b/src/i915_video.c
@@ -39,18 +39,6 @@
 #include "i915_reg.h"
 #include "i915_3d.h"
 
-union intfloat {
-   CARD32 ui;
-   float f;
-};
-
-#define OUT_RING_F(x) do {						\
-   union intfloat _tmp;							\
-   _tmp.f = x;								\
-   OUT_RING(_tmp.ui);							\
-} while (0)
-
-
 void
 I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id,
 			 RegionPtr dstRegion,
diff --git a/src/i965_exa_render.c b/src/i965_exa_render.c
deleted file mode 100644
index 99bd628..0000000
--- a/src/i965_exa_render.c
+++ /dev/null
@@ -1,1081 +0,0 @@
-/*
- * Copyright © 2006 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Authors:
- *    Wang Zhenyu <zhenyu.z.wang at intel.com>
- *    Eric Anholt <eric at anholt.net>
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "xf86.h"
-#include "i830.h"
-#include "i915_reg.h"
-
-/* bring in brw structs */
-#include "brw_defines.h"
-#include "brw_structs.h"
-
-#ifdef I830DEBUG
-#define DEBUG_I830FALLBACK 1
-#endif
-
-#ifdef DEBUG_I830FALLBACK
-#define I830FALLBACK(s, arg...)				\
-do {							\
-	DPRINTF(PFX, "EXA fallback: " s "\n", ##arg); 	\
-	return FALSE;					\
-} while(0)
-#else
-#define I830FALLBACK(s, arg...) 			\
-do { 							\
-	return FALSE;					\
-} while(0) 
-#endif
-
-static void I965GetBlendCntl(int op, PicturePtr pMask, CARD32 dst_format, 
-			     CARD32 *sblend, CARD32 *dblend);
-
-struct blendinfo {
-    Bool dst_alpha;
-    Bool src_alpha;
-    CARD32 src_blend;
-    CARD32 dst_blend;
-};
-
-struct formatinfo {
-    int fmt;
-    CARD32 card_fmt;
-};
-
-// refer vol2, 3d rasterization 3.8.1
-
-/* defined in brw_defines.h */
-static struct blendinfo I965BlendOp[] = { 
-    /* Clear */
-    {0, 0, BRW_BLENDFACTOR_ZERO,          BRW_BLENDFACTOR_ZERO},
-    /* Src */
-    {0, 0, BRW_BLENDFACTOR_ONE,           BRW_BLENDFACTOR_ZERO},
-    /* Dst */
-    {0, 0, BRW_BLENDFACTOR_ZERO,          BRW_BLENDFACTOR_ONE},
-    /* Over */
-    {0, 1, BRW_BLENDFACTOR_ONE,           BRW_BLENDFACTOR_INV_SRC_ALPHA},
-    /* OverReverse */
-    {1, 0, BRW_BLENDFACTOR_INV_DST_ALPHA, BRW_BLENDFACTOR_ONE},
-    /* In */
-    {1, 0, BRW_BLENDFACTOR_DST_ALPHA,     BRW_BLENDFACTOR_ZERO},
-    /* InReverse */
-    {0, 1, BRW_BLENDFACTOR_ZERO,          BRW_BLENDFACTOR_SRC_ALPHA},
-    /* Out */
-    {1, 0, BRW_BLENDFACTOR_INV_DST_ALPHA, BRW_BLENDFACTOR_ZERO},
-    /* OutReverse */
-    {0, 1, BRW_BLENDFACTOR_ZERO,          BRW_BLENDFACTOR_INV_SRC_ALPHA},
-    /* Atop */
-    {1, 1, BRW_BLENDFACTOR_DST_ALPHA,     BRW_BLENDFACTOR_INV_SRC_ALPHA},
-    /* AtopReverse */
-    {1, 1, BRW_BLENDFACTOR_INV_DST_ALPHA, BRW_BLENDFACTOR_SRC_ALPHA},
-    /* Xor */
-    {1, 1, BRW_BLENDFACTOR_INV_DST_ALPHA, BRW_BLENDFACTOR_INV_SRC_ALPHA},
-    /* Add */
-    {0, 0, BRW_BLENDFACTOR_ONE,           BRW_BLENDFACTOR_ONE},
-};
-
-/* FIXME: surface format defined in brw_defines.h, shared Sampling engine 1.7.2*/
-static struct formatinfo I965TexFormats[] = {
-        {PICT_a8r8g8b8, BRW_SURFACEFORMAT_B8G8R8A8_UNORM },
-        {PICT_x8r8g8b8, BRW_SURFACEFORMAT_B8G8R8X8_UNORM },
-        {PICT_a8b8g8r8, BRW_SURFACEFORMAT_R8G8B8A8_UNORM },
-        {PICT_x8b8g8r8, BRW_SURFACEFORMAT_R8G8B8X8_UNORM },
-        {PICT_r5g6b5,   BRW_SURFACEFORMAT_B5G6R5_UNORM   },
-        {PICT_a1r5g5b5, BRW_SURFACEFORMAT_B5G5R5A1_UNORM },
-        {PICT_a8,       BRW_SURFACEFORMAT_A8_UNORM	 },
-};
-
-static void I965GetBlendCntl(int op, PicturePtr pMask, CARD32 dst_format, 
-			     CARD32 *sblend, CARD32 *dblend)
-{
-
-    *sblend = I965BlendOp[op].src_blend;
-    *dblend = I965BlendOp[op].dst_blend;
-
-    /* If there's no dst alpha channel, adjust the blend op so that we'll treat
-     * it as always 1.
-     */
-    if (PICT_FORMAT_A(dst_format) == 0 && I965BlendOp[op].dst_alpha) {
-        if (*sblend == BRW_BLENDFACTOR_DST_ALPHA)
-            *sblend = BRW_BLENDFACTOR_ONE;
-        else if (*sblend == BRW_BLENDFACTOR_INV_DST_ALPHA)
-            *sblend = BRW_BLENDFACTOR_ZERO;
-    }
-
-    /* If the source alpha is being used, then we should only be in a case where
-     * the source blend factor is 0, and the source blend value is the mask
-     * channels multiplied by the source picture's alpha.
-     */
-    if (pMask && pMask->componentAlpha && I965BlendOp[op].src_alpha) {
-        if (*dblend == BRW_BLENDFACTOR_SRC_ALPHA) {
-	    *dblend = BRW_BLENDFACTOR_SRC_COLOR;
-        } else if (*dblend == BRW_BLENDFACTOR_INV_SRC_ALPHA) {
-	    *dblend = BRW_BLENDFACTOR_INV_SRC_COLOR;
-        }
-    }
-
-}
-
-static Bool I965GetDestFormat(PicturePtr pDstPicture, CARD32 *dst_format)
-{
-    switch (pDstPicture->format) {
-    case PICT_a8r8g8b8:
-    case PICT_x8r8g8b8:
-        *dst_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
-        break;
-    case PICT_r5g6b5:
-        *dst_format = BRW_SURFACEFORMAT_B5G6R5_UNORM;
-        break;
-    case PICT_a1r5g5b5:
-    	*dst_format = BRW_SURFACEFORMAT_B5G5R5A1_UNORM;
-	break;
-    case PICT_x1r5g5b5:
-        *dst_format = BRW_SURFACEFORMAT_B5G5R5X1_UNORM;
-        break;
-    /* COLR_BUF_8BIT is special for YUV surfaces.  While we may end up being
-     * able to use it depending on how the hardware implements it, disable it
-     * for now while we don't know what exactly it does (what channel does it
-     * read from?
-     */
-    /*
-    case PICT_a8:
-        *dst_format = COLR_BUF_8BIT;
-        break;
-    */
-    case PICT_a4r4g4b4:
-    case PICT_x4r4g4b4:
-	*dst_format = BRW_SURFACEFORMAT_B4G4R4A4_UNORM; 
-	break;
-    default:
-        I830FALLBACK("Unsupported dest format 0x%x\n",
-                        (int)pDstPicture->format);
-    }
-
-    return TRUE;
-}
-
-static Bool I965CheckCompositeTexture(PicturePtr pPict, int unit)
-{
-    int w = pPict->pDrawable->width;
-    int h = pPict->pDrawable->height;
-    int i;
-                                                                                                                                                            
-    if ((w > 0x7ff) || (h > 0x7ff))
-        I830FALLBACK("Picture w/h too large (%dx%d)\n", w, h);
-
-    for (i = 0; i < sizeof(I965TexFormats) / sizeof(I965TexFormats[0]); i++)
-    {
-        if (I965TexFormats[i].fmt == pPict->format)
-            break;
-    }
-    if (i == sizeof(I965TexFormats) / sizeof(I965TexFormats[0]))
-        I830FALLBACK("Unsupported picture format 0x%x\n",
-                         (int)pPict->format);
-
-    if (pPict->repeat && pPict->repeatType != RepeatNormal)
-	I830FALLBACK("extended repeat (%d) not supported\n",
-		     pPict->repeatType);
-
-    if (pPict->filter != PictFilterNearest &&
-        pPict->filter != PictFilterBilinear)
-        I830FALLBACK("Unsupported filter 0x%x\n", pPict->filter);
-
-    return TRUE;
-}
-
-Bool
-I965EXACheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
-		      PicturePtr pDstPicture)
-{
-    CARD32 tmp1;
-    
-    /* Check for unsupported compositing operations. */
-    if (op >= sizeof(I965BlendOp) / sizeof(I965BlendOp[0]))
-        I830FALLBACK("Unsupported Composite op 0x%x\n", op);
-
-    if (pMaskPicture != NULL && pMaskPicture->componentAlpha) {
-        /* Check if it's component alpha that relies on a source alpha and on
-         * the source value.  We can only get one of those into the single
-         * source value that we get to blend with.
-         */
-        if (I965BlendOp[op].src_alpha &&
-            (I965BlendOp[op].src_blend != BRW_BLENDFACTOR_ZERO))
-            	I830FALLBACK("Component alpha not supported with source "
-                            "alpha and source value blending.\n");
-	/* XXX: fallback now for mask with componentAlpha */
-	I830FALLBACK("mask componentAlpha not ready.\n");
-    }
-
-    if (!I965CheckCompositeTexture(pSrcPicture, 0))
-        I830FALLBACK("Check Src picture texture\n");
-    if (pMaskPicture != NULL && !I965CheckCompositeTexture(pMaskPicture, 1))
-        I830FALLBACK("Check Mask picture texture\n");
-
-    if (!I965GetDestFormat(pDstPicture, &tmp1)) 
-	I830FALLBACK("Get Color buffer format\n");
-
-    return TRUE;
-
-}
-
-#define ALIGN(i,m)    (((i) + (m) - 1) & ~((m) - 1))
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define BRW_GRF_BLOCKS(nreg)    ((nreg + 15) / 16 - 1)
-
-static int urb_vs_start, urb_vs_size;
-static int urb_gs_start, urb_gs_size;
-static int urb_clip_start, urb_clip_size;
-static int urb_sf_start, urb_sf_size;
-static int urb_cs_start, urb_cs_size;
-
-static struct brw_surface_state *dest_surf_state;
-static struct brw_surface_state *src_surf_state;
-static struct brw_surface_state *mask_surf_state;
-static struct brw_sampler_state *src_sampler_state;
-static struct brw_sampler_state *mask_sampler_state;  
-static struct brw_sampler_default_color *default_color_state;
-
-static struct brw_vs_unit_state *vs_state;
-static struct brw_sf_unit_state *sf_state;
-static struct brw_wm_unit_state *wm_state;
-static struct brw_cc_unit_state *cc_state;
-static struct brw_cc_viewport *cc_viewport;
-
-static struct brw_instruction *sf_kernel;
-static struct brw_instruction *ps_kernel;
-static struct brw_instruction *sip_kernel;
-
-static CARD32 *binding_table;
-static int binding_table_entries; 
-
-static int dest_surf_offset, src_surf_offset, mask_surf_offset;
-static int src_sampler_offset, mask_sampler_offset,vs_offset;
-static int sf_offset, wm_offset, cc_offset, vb_offset, cc_viewport_offset;
-static int sf_kernel_offset, ps_kernel_offset, sip_kernel_offset;
-static int wm_scratch_offset;
-static int binding_table_offset;
-static int default_color_offset; 
-static int next_offset, total_state_size;
-static char *state_base;
-static int state_base_offset;
-static float *vb;
-static int vb_size = (4 * 4) * 4 ; /* 4 DWORDS per vertex*/ 
-
-static CARD32 src_blend, dst_blend;
-
-static const CARD32 sip_kernel_static[][4] = {
-/*    wait (1) a0<1>UW a145<0,1,0>UW { align1 +  } */
-    { 0x00000030, 0x20000108, 0x00001220, 0x00000000 },
-/*    nop (4) g0<1>UD { align1 +  } */
-    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
-/*    nop (4) g0<1>UD { align1 +  } */
-    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
-/*    nop (4) g0<1>UD { align1 +  } */
-    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
-/*    nop (4) g0<1>UD { align1 +  } */
-    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
-/*    nop (4) g0<1>UD { align1 +  } */
-    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
-/*    nop (4) g0<1>UD { align1 +  } */
-    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
-/*    nop (4) g0<1>UD { align1 +  } */
-    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
-/*    nop (4) g0<1>UD { align1 +  } */
-    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
-/*    nop (4) g0<1>UD { align1 +  } */
-    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
-};
-
-/*
- * this program computes dA/dx and dA/dy for the texture coordinates along
- * with the base texture coordinate. It was extracted from the Mesa driver
- */
-
-#define SF_KERNEL_NUM_GRF  16
-#define SF_MAX_THREADS	   1
-
-static const CARD32 sf_kernel_static[][4] = {
-#include "exa_sf_prog.h"
-};
-
-static const CARD32 sf_kernel_static_mask[][4] = {
-#include "exa_sf_mask_prog.h"
-};
-
-/* ps kernels */
-#define PS_KERNEL_NUM_GRF   32
-#define PS_MAX_THREADS	   32
-/* 1: no mask */
-static const CARD32 ps_kernel_static_nomask [][4] = {
-#include "exa_wm_nomask_prog.h"
-};
-
-/* 2: mask with componentAlpha, src * mask color, XXX: later */
-static const CARD32 ps_kernel_static_maskca [][4] = {
-/*#include "i965_composite_wm_maskca.h" */
-};
-
-/* 3: mask without componentAlpha, src * mask alpha */
-static const CARD32 ps_kernel_static_masknoca [][4] = {
-#include "exa_wm_masknoca_prog.h"
-};
-
-static CARD32 i965_get_card_format(PicturePtr pPict) 
-{
-	int i;
-        for (i = 0; i < sizeof(I965TexFormats) / sizeof(I965TexFormats[0]); i++) {
-            if (I965TexFormats[i].fmt == pPict->format)
-                break;
-        }
-	return I965TexFormats[i].card_fmt;
-}
-
-Bool
-I965EXAPrepareComposite(int op, PicturePtr pSrcPicture,
-			PicturePtr pMaskPicture, PicturePtr pDstPicture,
-			PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
-{
-    ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum];
-    I830Ptr pI830 = I830PTR(pScrn);
-    CARD32 src_offset, src_pitch;
-    CARD32 mask_offset = 0, mask_pitch = 0;
-    CARD32 dst_format, dst_offset, dst_pitch;
-
-#ifdef XF86DRI
-    if (pI830->directRenderingEnabled) {
-        drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
-
-        pSAREAPriv->ctxOwner = DRIGetContext(pScrn->pScreen);
-    }
-#endif
-
-    pI830->last_3d = LAST_3D_RENDER;
-
-    src_offset = intel_get_pixmap_offset(pSrc);
-    src_pitch = intel_get_pixmap_pitch(pSrc);
-    dst_offset = intel_get_pixmap_offset(pDst);
-    dst_pitch = intel_get_pixmap_pitch(pDst);
-    if (pMask) {
-	mask_offset = intel_get_pixmap_offset(pMask);
-	mask_pitch = intel_get_pixmap_pitch(pMask);
-    }
-    pI830->scale_units[0][0] = pSrc->drawable.width;
-    pI830->scale_units[0][1] = pSrc->drawable.height;
-
-    pI830->transform[0] = pSrcPicture->transform;
-
-    if (!pMask) {
-	pI830->transform[1] = NULL;
-	pI830->scale_units[1][0] = -1;
-	pI830->scale_units[1][1] = -1;
-    } else {
-	pI830->transform[1] = pMaskPicture->transform;
-	pI830->scale_units[1][0] = pMask->drawable.width;
-	pI830->scale_units[1][1] = pMask->drawable.height;
-    }
-
-	/* setup 3d pipeline state */
-
-   binding_table_entries = 2; /* default no mask */
-
-   /* Wait for sync before we start setting up our new state */
-   i830WaitSync(pScrn);
-
-   /* Set up our layout of state in framebuffer.  First the general state: */
-   next_offset = 0;
-   vs_offset = ALIGN(next_offset, 64);
-   next_offset = vs_offset + sizeof(*vs_state);
-    
-   sf_offset = ALIGN(next_offset, 32);
-   next_offset = sf_offset + sizeof(*sf_state);
-    
-   wm_offset = ALIGN(next_offset, 32);
-   next_offset = wm_offset + sizeof(*wm_state);
-    
-   wm_scratch_offset = ALIGN(next_offset, 1024);
-   next_offset = wm_scratch_offset + 1024 * PS_MAX_THREADS;
-
-   cc_offset = ALIGN(next_offset, 32);
-   next_offset = cc_offset + sizeof(*cc_state);
-
-   /* keep current sf_kernel, which will send one setup urb entry to
-	PS kernel */
-   sf_kernel_offset = ALIGN(next_offset, 64);
-   if (pMask) 
-       next_offset = sf_kernel_offset + sizeof (sf_kernel_static_mask);
-   else
-       next_offset = sf_kernel_offset + sizeof (sf_kernel_static);
-
-   //XXX: ps_kernel may be seperated, fix with offset
-   ps_kernel_offset = ALIGN(next_offset, 64);
-   if (pMask) {
-	if (pMaskPicture->componentAlpha)
-	    next_offset = ps_kernel_offset + sizeof(ps_kernel_static_maskca);
-	else 
-	    next_offset = ps_kernel_offset + sizeof(ps_kernel_static_masknoca);
-   } else 
-   	next_offset = ps_kernel_offset + sizeof (ps_kernel_static_nomask);
-    
-   sip_kernel_offset = ALIGN(next_offset, 64);
-   next_offset = sip_kernel_offset + sizeof (sip_kernel_static);
-   
-   // needed?
-   cc_viewport_offset = ALIGN(next_offset, 32);
-   next_offset = cc_viewport_offset + sizeof(*cc_viewport);
-
-   // for texture sampler
-   src_sampler_offset = ALIGN(next_offset, 32);
-   next_offset = src_sampler_offset + sizeof(*src_sampler_state);
-
-   if (pMask) {
-   	mask_sampler_offset = ALIGN(next_offset, 32);
-   	next_offset = mask_sampler_offset + sizeof(*mask_sampler_state);
-   }
-   /* Align VB to native size of elements, for safety */
-   vb_offset = ALIGN(next_offset, 8);
-   next_offset = vb_offset + vb_size;
-
-   /* And then the general state: */
-   dest_surf_offset = ALIGN(next_offset, 32);
-   next_offset = dest_surf_offset + sizeof(*dest_surf_state);
-
-   src_surf_offset = ALIGN(next_offset, 32);
-   next_offset = src_surf_offset + sizeof(*src_surf_state);
-
-   if (pMask) {
-   	mask_surf_offset = ALIGN(next_offset, 32);
-   	next_offset = mask_surf_offset + sizeof(*mask_surf_state);
-	binding_table_entries = 3;
-   }
-
-   binding_table_offset = ALIGN(next_offset, 32);
-   next_offset = binding_table_offset + (binding_table_entries * 4);
-
-   default_color_offset = ALIGN(next_offset, 32);
-   next_offset = default_color_offset + sizeof(*default_color_state);
-
-   total_state_size = next_offset;
-   assert(total_state_size < EXA_LINEAR_EXTRA);
-
-   state_base_offset = pI830->EXAStateMem.Start;
-   state_base_offset = ALIGN(state_base_offset, 64);
-   state_base = (char *)(pI830->FbBase + state_base_offset);
-
-   vs_state = (void *)(state_base + vs_offset);
-   sf_state = (void *)(state_base + sf_offset);
-   wm_state = (void *)(state_base + wm_offset);
-   cc_state = (void *)(state_base + cc_offset);
-   sf_kernel = (void *)(state_base + sf_kernel_offset);
-   ps_kernel = (void *)(state_base + ps_kernel_offset);
-   sip_kernel = (void *)(state_base + sip_kernel_offset);
-   
-   cc_viewport = (void *)(state_base + cc_viewport_offset);
-   
-   dest_surf_state = (void *)(state_base + dest_surf_offset);
-   src_surf_state = (void *)(state_base + src_surf_offset);
-   if (pMask)
-	mask_surf_state = (void *)(state_base + mask_surf_offset);
-
-   src_sampler_state = (void *)(state_base + src_sampler_offset);
-   if (pMask)
-	mask_sampler_state = (void *)(state_base + mask_sampler_offset);
-
-   binding_table = (void *)(state_base + binding_table_offset);
-
-   vb = (void *)(state_base + vb_offset);
-
-   default_color_state = (void*)(state_base + default_color_offset);
-
-   /* Set up a default static partitioning of the URB, which is supposed to
-    * allow anything we would want to do, at potentially lower performance.
-    */
-#define URB_CS_ENTRY_SIZE     0
-#define URB_CS_ENTRIES	      0
-   
-#define URB_VS_ENTRY_SIZE     1	  // each 512-bit row
-#define URB_VS_ENTRIES	      8	  // we needs at least 8 entries
-   
-#define URB_GS_ENTRY_SIZE     0
-#define URB_GS_ENTRIES	      0
-   
-#define URB_CLIP_ENTRY_SIZE   0
-#define URB_CLIP_ENTRIES      0
-   
-#define URB_SF_ENTRY_SIZE     2
-#define URB_SF_ENTRIES	      1
-
-   urb_vs_start = 0;
-   urb_vs_size = URB_VS_ENTRIES * URB_VS_ENTRY_SIZE;
-   urb_gs_start = urb_vs_start + urb_vs_size;
-   urb_gs_size = URB_GS_ENTRIES * URB_GS_ENTRY_SIZE;
-   urb_clip_start = urb_gs_start + urb_gs_size;
-   urb_clip_size = URB_CLIP_ENTRIES * URB_CLIP_ENTRY_SIZE;
-   urb_sf_start = urb_clip_start + urb_clip_size;
-   urb_sf_size = URB_SF_ENTRIES * URB_SF_ENTRY_SIZE;
-   urb_cs_start = urb_sf_start + urb_sf_size;
-   urb_cs_size = URB_CS_ENTRIES * URB_CS_ENTRY_SIZE;
-
-   /* We'll be poking the state buffers that could be in use by the 3d hardware
-    * here, but we should have synced the 3D engine already in I830PutImage.
-    */
-
-   memset (cc_viewport, 0, sizeof (*cc_viewport));
-   cc_viewport->min_depth = -1.e35;
-   cc_viewport->max_depth = 1.e35;
-
-   /* Color calculator state */
-   memset(cc_state, 0, sizeof(*cc_state));
-   cc_state->cc0.stencil_enable = 0;   /* disable stencil */
-   cc_state->cc2.depth_test = 0;       /* disable depth test */
-   cc_state->cc2.logicop_enable = 0;   /* disable logic op */
-   cc_state->cc3.ia_blend_enable = 1;  /* blend alpha just like colors */
-   cc_state->cc3.blend_enable = 1;     /* enable color blend */
-   cc_state->cc3.alpha_test = 0;       /* disable alpha test */
-   cc_state->cc4.cc_viewport_state_offset = (state_base_offset + cc_viewport_offset) >> 5;
-   cc_state->cc5.dither_enable = 0;    /* disable dither */
-   cc_state->cc5.logicop_func = 0xc;   /* COPY */
-   cc_state->cc5.statistics_enable = 1;
-   cc_state->cc5.ia_blend_function = BRW_BLENDFUNCTION_ADD;
-   I965GetBlendCntl(op, pMaskPicture, pDstPicture->format, 
-		    &src_blend, &dst_blend);
-   /* XXX: alpha blend factor should be same as color, but check
-	   for CA case in future */
-   cc_state->cc5.ia_src_blend_factor = src_blend;
-   cc_state->cc5.ia_dest_blend_factor = dst_blend;
-   cc_state->cc6.blend_function = BRW_BLENDFUNCTION_ADD;
-   cc_state->cc6.src_blend_factor = src_blend;
-   cc_state->cc6.dest_blend_factor = dst_blend;
-   cc_state->cc6.clamp_post_alpha_blend = 1; 
-   cc_state->cc6.clamp_pre_alpha_blend = 1; 
-   cc_state->cc6.clamp_range = 0;  /* clamp range [0,1] */
-
-   /* Upload system kernel */
-   memcpy (sip_kernel, sip_kernel_static, sizeof (sip_kernel_static));
-   
-   /* Set up the state buffer for the destination surface */
-   memset(dest_surf_state, 0, sizeof(*dest_surf_state));
-   dest_surf_state->ss0.surface_type = BRW_SURFACE_2D;
-   dest_surf_state->ss0.data_return_format = BRW_SURFACERETURNFORMAT_FLOAT32;
-   I965GetDestFormat(pDstPicture, &dst_format);
-   dest_surf_state->ss0.surface_format = dst_format;
-
-   dest_surf_state->ss0.writedisable_alpha = 0;
-   dest_surf_state->ss0.writedisable_red = 0;
-   dest_surf_state->ss0.writedisable_green = 0;
-   dest_surf_state->ss0.writedisable_blue = 0;
-   dest_surf_state->ss0.color_blend = 1;
-   dest_surf_state->ss0.vert_line_stride = 0;
-   dest_surf_state->ss0.vert_line_stride_ofs = 0;
-   dest_surf_state->ss0.mipmap_layout_mode = 0;
-   dest_surf_state->ss0.render_cache_read_mode = 0;
-   
-   dest_surf_state->ss1.base_addr = dst_offset;
-   dest_surf_state->ss2.height = pDst->drawable.height - 1;
-   dest_surf_state->ss2.width = pDst->drawable.width - 1;
-   dest_surf_state->ss2.mip_count = 0;
-   dest_surf_state->ss2.render_target_rotation = 0;
-   dest_surf_state->ss3.pitch = dst_pitch - 1; 
-
-   /* Set up the source surface state buffer */
-   memset(src_surf_state, 0, sizeof(*src_surf_state));
-   src_surf_state->ss0.surface_type = BRW_SURFACE_2D;
-   src_surf_state->ss0.surface_format = i965_get_card_format(pSrcPicture);
-
-   src_surf_state->ss0.writedisable_alpha = 0;
-   src_surf_state->ss0.writedisable_red = 0;
-   src_surf_state->ss0.writedisable_green = 0;
-   src_surf_state->ss0.writedisable_blue = 0;
-   src_surf_state->ss0.color_blend = 1;
-   src_surf_state->ss0.vert_line_stride = 0;
-   src_surf_state->ss0.vert_line_stride_ofs = 0;
-   src_surf_state->ss0.mipmap_layout_mode = 0;
-   src_surf_state->ss0.render_cache_read_mode = 0;
-   
-   src_surf_state->ss1.base_addr = src_offset;
-   src_surf_state->ss2.width = pSrc->drawable.width - 1;
-   src_surf_state->ss2.height = pSrc->drawable.height - 1;
-   src_surf_state->ss2.mip_count = 0;
-   src_surf_state->ss2.render_target_rotation = 0;
-   src_surf_state->ss3.pitch = src_pitch - 1; 
-
-   /* setup mask surface */
-   if (pMask) {
-   	memset(mask_surf_state, 0, sizeof(*mask_surf_state));
-	mask_surf_state->ss0.surface_type = BRW_SURFACE_2D;
-   	mask_surf_state->ss0.surface_format = i965_get_card_format(pMaskPicture);
-
-   	mask_surf_state->ss0.writedisable_alpha = 0;
-   	mask_surf_state->ss0.writedisable_red = 0;
-   	mask_surf_state->ss0.writedisable_green = 0;
-   	mask_surf_state->ss0.writedisable_blue = 0;
-   	mask_surf_state->ss0.color_blend = 1;
-   	mask_surf_state->ss0.vert_line_stride = 0;
-   	mask_surf_state->ss0.vert_line_stride_ofs = 0;
-   	mask_surf_state->ss0.mipmap_layout_mode = 0;
-   	mask_surf_state->ss0.render_cache_read_mode = 0;
-   
-   	mask_surf_state->ss1.base_addr = mask_offset;
-   	mask_surf_state->ss2.width = pMask->drawable.width - 1;
-   	mask_surf_state->ss2.height = pMask->drawable.height - 1;
-   	mask_surf_state->ss2.mip_count = 0;
-   	mask_surf_state->ss2.render_target_rotation = 0;
-   	mask_surf_state->ss3.pitch = mask_pitch - 1; 
-   }
-
-   /* Set up a binding table for our surfaces.  Only the PS will use it */
-   binding_table[0] = state_base_offset + dest_surf_offset;
-   binding_table[1] = state_base_offset + src_surf_offset;
-   if (pMask)
-   	binding_table[2] = state_base_offset + mask_surf_offset;
-
-   /* PS kernel use this sampler */
-   memset(src_sampler_state, 0, sizeof(*src_sampler_state));
-   src_sampler_state->ss0.lod_preclamp = 1; /* GL mode */
-   switch(pSrcPicture->filter) {
-   case PictFilterNearest:
-   	src_sampler_state->ss0.min_filter = BRW_MAPFILTER_NEAREST; 
-   	src_sampler_state->ss0.mag_filter = BRW_MAPFILTER_NEAREST;
-	break;
-   case PictFilterBilinear:
-   	src_sampler_state->ss0.min_filter = BRW_MAPFILTER_LINEAR; 
-   	src_sampler_state->ss0.mag_filter = BRW_MAPFILTER_LINEAR;
-	break;
-   default:
-	I830FALLBACK("Bad filter 0x%x\n", pSrcPicture->filter);
-   }
-
-   memset(default_color_state, 0, sizeof(*default_color_state));
-   default_color_state->color[0] = 0.0; /* R */
-   default_color_state->color[1] = 0.0; /* G */
-   default_color_state->color[2] = 0.0; /* B */
-   default_color_state->color[3] = 1.0; /* A */
-
-   src_sampler_state->ss0.default_color_mode = 0; /* GL mode */
-
-   if (!pSrcPicture->repeat) {
-   	src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER; 
-   	src_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER;
-   	src_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER;
-	src_sampler_state->ss2.default_color_pointer = 
-			(state_base_offset + default_color_offset) >> 5;
-   } else {
-   	src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_WRAP; 
-   	src_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_WRAP;
-   	src_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_WRAP;
-   }
-   src_sampler_state->ss3.chroma_key_enable = 0; /* disable chromakey */
-
-   if (pMask) {
-   	memset(mask_sampler_state, 0, sizeof(*mask_sampler_state));
-   	mask_sampler_state->ss0.lod_preclamp = 1; /* GL mode */
-   	switch(pMaskPicture->filter) {
-   	case PictFilterNearest:
-   	    mask_sampler_state->ss0.min_filter = BRW_MAPFILTER_NEAREST; 
-   	    mask_sampler_state->ss0.mag_filter = BRW_MAPFILTER_NEAREST;
-	    break;
-   	case PictFilterBilinear:
-   	    mask_sampler_state->ss0.min_filter = BRW_MAPFILTER_LINEAR; 
-   	    mask_sampler_state->ss0.mag_filter = BRW_MAPFILTER_LINEAR;
-	    break;
-   	default:
-	    I830FALLBACK("Bad filter 0x%x\n", pMaskPicture->filter);
-   	}
-
-   	if (!pMaskPicture->repeat) {
-   	    mask_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER; 
-   	    mask_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER;
-   	    mask_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER;
-            mask_sampler_state->ss2.default_color_pointer = 
-				(state_base_offset + default_color_offset)>>5;
-   	} else {
-   	    mask_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_WRAP; 
-   	    mask_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_WRAP;
-   	    mask_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_WRAP;
-    	}
-   	mask_sampler_state->ss3.chroma_key_enable = 0; /* disable chromakey */
-   }
-
-   /* Set up the vertex shader to be disabled (passthrough) */
-   memset(vs_state, 0, sizeof(*vs_state));
-   vs_state->thread4.nr_urb_entries = URB_VS_ENTRIES;
-   vs_state->thread4.urb_entry_allocation_size = URB_VS_ENTRY_SIZE - 1;
-   vs_state->vs6.vs_enable = 0;
-   vs_state->vs6.vert_cache_disable = 1;
-
-   // XXX: sf_kernel? keep it as now
-   /* Set up the SF kernel to do coord interp: for each attribute,
-    * calculate dA/dx and dA/dy.  Hand these interpolation coefficients
-    * back to SF which then hands pixels off to WM.
-    */
-   if (pMask) 
-       memcpy (sf_kernel, sf_kernel_static_mask, sizeof (sf_kernel_static));
-   else
-       memcpy (sf_kernel, sf_kernel_static, sizeof (sf_kernel_static));
-
-   memset(sf_state, 0, sizeof(*sf_state));
-   sf_state->thread0.kernel_start_pointer = 
-	       (state_base_offset + sf_kernel_offset) >> 6;
-   sf_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(SF_KERNEL_NUM_GRF);
-   sf_state->sf1.single_program_flow = 1;
-   sf_state->sf1.binding_table_entry_count = 0;
-   sf_state->sf1.thread_priority = 0;
-   sf_state->sf1.floating_point_mode = 0; /* Mesa does this */
-   sf_state->sf1.illegal_op_exception_enable = 1;
-   sf_state->sf1.mask_stack_exception_enable = 1;
-   sf_state->sf1.sw_exception_enable = 1;
-   sf_state->thread2.per_thread_scratch_space = 0;
-   sf_state->thread2.scratch_space_base_pointer = 0; /* not used in our kernel */
-   sf_state->thread3.const_urb_entry_read_length = 0; /* no const URBs */
-   sf_state->thread3.const_urb_entry_read_offset = 0; /* no const URBs */
-   sf_state->thread3.urb_entry_read_length = 1; /* 1 URB per vertex */
-   sf_state->thread3.urb_entry_read_offset = 0;
-   sf_state->thread3.dispatch_grf_start_reg = 3;
-   sf_state->thread4.max_threads = SF_MAX_THREADS - 1;
-   sf_state->thread4.urb_entry_allocation_size = URB_SF_ENTRY_SIZE - 1;
-   sf_state->thread4.nr_urb_entries = URB_SF_ENTRIES;
-   sf_state->thread4.stats_enable = 1;
-   sf_state->sf5.viewport_transform = FALSE; /* skip viewport */
-   sf_state->sf6.cull_mode = BRW_CULLMODE_NONE;
-   sf_state->sf6.scissor = 0;
-   sf_state->sf7.trifan_pv = 2;
-   sf_state->sf6.dest_org_vbias = 0x8;
-   sf_state->sf6.dest_org_hbias = 0x8;
-
-   /* Set up the PS kernel (dispatched by WM) 
-    */
-    
-   if (pMask) {
-	if (pMaskPicture->componentAlpha)
-   	    memcpy (ps_kernel, ps_kernel_static_maskca, sizeof (ps_kernel_static_maskca));
-	else
-   	    memcpy (ps_kernel, ps_kernel_static_masknoca, sizeof (ps_kernel_static_masknoca));
-   } else 
-   	memcpy (ps_kernel, ps_kernel_static_nomask, sizeof (ps_kernel_static_nomask));
-
-   memset (wm_state, 0, sizeof (*wm_state));
-   wm_state->thread0.kernel_start_pointer = 
-	    (state_base_offset + ps_kernel_offset) >> 6;
-   wm_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(PS_KERNEL_NUM_GRF);
-   wm_state->thread1.single_program_flow = 1;
-   if (!pMask)
-       wm_state->thread1.binding_table_entry_count = 2; /* 1 tex and fb */
-   else
-       wm_state->thread1.binding_table_entry_count = 3; /* 2 tex and fb */
-
-   wm_state->thread2.scratch_space_base_pointer = (state_base_offset + 
-						   wm_scratch_offset)>>10;
-   wm_state->thread2.per_thread_scratch_space = 0;
-   // XXX: urb allocation
-   wm_state->thread3.const_urb_entry_read_length = 0;
-   wm_state->thread3.const_urb_entry_read_offset = 0;
-   if (pMask)
-       wm_state->thread3.urb_entry_read_length = 2;  /* two per pair of attrib */
-   else 
-       wm_state->thread3.urb_entry_read_length = 1;  /* one per pair of attrib */
-   wm_state->thread3.urb_entry_read_offset = 0;
-   // wm kernel use urb from 3, see wm_program in compiler module
-   wm_state->thread3.dispatch_grf_start_reg = 3; /* must match kernel */
-
-   wm_state->wm4.stats_enable = 1;  /* statistic */
-   wm_state->wm4.sampler_state_pointer = (state_base_offset + src_sampler_offset) >> 5; 
-   wm_state->wm4.sampler_count = 1; /* 1-4 samplers used */
-   wm_state->wm5.max_threads = PS_MAX_THREADS - 1;
-   wm_state->wm5.thread_dispatch_enable = 1;
-   //just use 16-pixel dispatch (4 subspans), don't need to change kernel start point
-   wm_state->wm5.enable_16_pix = 1;
-   wm_state->wm5.enable_8_pix = 0;
-   wm_state->wm5.early_depth_test = 1;
-
-   /* Begin the long sequence of commands needed to set up the 3D 
-    * rendering pipe
-    */
-   {
-	BEGIN_LP_RING(2);
-   	OUT_RING(MI_FLUSH | 
-	    MI_STATE_INSTRUCTION_CACHE_FLUSH |
-	    BRW_MI_GLOBAL_SNAPSHOT_RESET);
-	OUT_RING(MI_NOOP);
-	ADVANCE_LP_RING();
-   }
-   {
-        BEGIN_LP_RING(12);
-   
-        /* Match Mesa driver setup */
-        OUT_RING(BRW_PIPELINE_SELECT | PIPELINE_SELECT_3D);
-   
-   	OUT_RING(BRW_CS_URB_STATE | 0);
-   	OUT_RING((0 << 4) |  /* URB Entry Allocation Size */
-            (0 << 0));  /* Number of URB Entries */
-
-   /* Zero out the two base address registers so all offsets are absolute */
-   	OUT_RING(BRW_STATE_BASE_ADDRESS | 4);
-   	OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* Generate state base address */
-   	OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* Surface state base address */
-   	OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* media base addr, don't care */
-   	OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY);  /* general state max addr, disabled */
-   	OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY);  /* media object state max addr, disabled */
-
-   /* Set system instruction pointer */
-   	OUT_RING(BRW_STATE_SIP | 0);
-   	OUT_RING(state_base_offset + sip_kernel_offset); /* system instruction pointer */
-	OUT_RING(MI_NOOP);
-	ADVANCE_LP_RING();
-   }
-   {
-	BEGIN_LP_RING(26);
-   /* Pipe control */
-   	OUT_RING(BRW_PIPE_CONTROL |
-	    BRW_PIPE_CONTROL_NOWRITE |
-	    BRW_PIPE_CONTROL_IS_FLUSH |
-	    2);
-   	OUT_RING(0);			       /* Destination address */
-   	OUT_RING(0);			       /* Immediate data low DW */
-   	OUT_RING(0);			       /* Immediate data high DW */
-
-   /* Binding table pointers */
-   	OUT_RING(BRW_3DSTATE_BINDING_TABLE_POINTERS | 4);
-   	OUT_RING(0); /* vs */
-   	OUT_RING(0); /* gs */
-   	OUT_RING(0); /* clip */
-   	OUT_RING(0); /* sf */
-   /* Only the PS uses the binding table */
-   	OUT_RING(state_base_offset + binding_table_offset); /* ps */
-
-   /* The drawing rectangle clipping is always on.  Set it to values that
-    * shouldn't do any clipping.
-    */
-   	OUT_RING(BRW_3DSTATE_DRAWING_RECTANGLE | 2);	/* XXX 3 for BLC or CTG */
-   	OUT_RING(0x00000000);	/* ymin, xmin */
-   	OUT_RING((pScrn->virtualX - 1) |
- 	         (pScrn->virtualY - 1) << 16); /* ymax, xmax */
-   	OUT_RING(0x00000000);	/* yorigin, xorigin */
-
-   /* skip the depth buffer */
-   /* skip the polygon stipple */
-   /* skip the polygon stipple offset */
-   /* skip the line stipple */
-   
-   /* Set the pointers to the 3d pipeline state */
-   	OUT_RING(BRW_3DSTATE_PIPELINED_POINTERS | 5);
-   	OUT_RING(state_base_offset + vs_offset);  /* 32 byte aligned */
-   	OUT_RING(BRW_GS_DISABLE);		     /* disable GS, resulting in passthrough */
-   	OUT_RING(BRW_CLIP_DISABLE);		     /* disable CLIP, resulting in passthrough */
-   	OUT_RING(state_base_offset + sf_offset);  /* 32 byte aligned */
-   	OUT_RING(state_base_offset + wm_offset);  /* 32 byte aligned */
-   	OUT_RING(state_base_offset + cc_offset);  /* 64 byte aligned */
-
-   /* URB fence */
-   	OUT_RING(BRW_URB_FENCE |
-        	 UF0_CS_REALLOC |
-	    	 UF0_SF_REALLOC |
-	    	 UF0_CLIP_REALLOC |
-	         UF0_GS_REALLOC |
-	         UF0_VS_REALLOC |
-	    	 1);
-   	OUT_RING(((urb_clip_start + urb_clip_size) << UF1_CLIP_FENCE_SHIFT) |
-	    	 ((urb_gs_start + urb_gs_size) << UF1_GS_FENCE_SHIFT) |
-	    	 ((urb_vs_start + urb_vs_size) << UF1_VS_FENCE_SHIFT));
-   	OUT_RING(((urb_cs_start + urb_cs_size) << UF2_CS_FENCE_SHIFT) |
-	     	 ((urb_sf_start + urb_sf_size) << UF2_SF_FENCE_SHIFT));
-
-   /* Constant buffer state */
-   	OUT_RING(BRW_CS_URB_STATE | 0);
-   	OUT_RING(((URB_CS_ENTRY_SIZE - 1) << 4) | /* URB Entry Allocation Size */
-	    	 (URB_CS_ENTRIES << 0));	     /* Number of URB Entries */
-	ADVANCE_LP_RING();
-   }
-   {
-        int nelem = pMask ? 3: 2;
-   	BEGIN_LP_RING(pMask?12:10);
-   /* Set up the pointer to our vertex buffer */
-   	OUT_RING(BRW_3DSTATE_VERTEX_BUFFERS | 3); 
-   	OUT_RING((0 << VB0_BUFFER_INDEX_SHIFT) |
-	    	 VB0_VERTEXDATA |
-	    	 ((4 * 2 * nelem) << VB0_BUFFER_PITCH_SHIFT)); 
-   	OUT_RING(state_base_offset + vb_offset);
-   	OUT_RING(2); // max index, prim has 4 coords
-   	OUT_RING(0); // ignore for VERTEXDATA, but still there
-
-   /* Set up our vertex elements, sourced from the single vertex buffer. */
-   	OUT_RING(BRW_3DSTATE_VERTEX_ELEMENTS | ((2 * nelem) - 1));  
-   /* offset 0: X,Y -> {X, Y, 1.0, 1.0} */
-   	OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
-	    	 VE0_VALID |
-	    	 (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
-	    	 (0 << VE0_OFFSET_SHIFT));
-   	OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
-	    	 (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
-	     	 (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
-	    	 (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
-	    	 (0 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
-   /* offset 8: S0, T0 -> {S0, T0, 1.0, 1.0} */
-   	OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
-	    	 VE0_VALID |
-	    	 (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
-	    	 (8 << VE0_OFFSET_SHIFT));
-   	OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
-	    	 (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
-	    	 (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
-	     	 (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
-	    	 (4 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
-
-   	if (pMask) {
-   		OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
-	    		 VE0_VALID |
-	    		 (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
-	    		 (16 << VE0_OFFSET_SHIFT));
-		OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
-	    		 (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
-	    		 (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
-	    		 (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
-	    		 (8 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); 
-   	}
-   
-   	ADVANCE_LP_RING();
-   }
-
-#ifdef I830DEBUG
-    ErrorF("try to sync to show any errors...");
-    I830Sync(pScrn);
-#endif
-    return TRUE;
-}	
-
-void
-I965EXAComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
-		int dstX, int dstY, int w, int h)
-{
-    ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
-    I830Ptr pI830 = I830PTR(pScrn);
-    Bool has_mask;
-    float src_x[3], src_y[3], mask_x[3], mask_y[3];
-    int i;
-
-    i830_get_transformed_coordinates(srcX, srcY,
-				     pI830->transform[0],
-				     &src_x[0], &src_y[0]);
-    i830_get_transformed_coordinates(srcX, srcY + h,
-				     pI830->transform[0],
-				     &src_x[1], &src_y[1]);
-    i830_get_transformed_coordinates(srcX + w, srcY + h,
-				     pI830->transform[0],
-				     &src_x[2], &src_y[2]);
-
-    if (pI830->scale_units[1][0] == -1 || pI830->scale_units[1][1] == -1) {
-	has_mask = FALSE;
-    } else {
-	has_mask = TRUE;
-	i830_get_transformed_coordinates(maskX, maskY,
-					 pI830->transform[1],
-					 &mask_x[0], &mask_y[0]);
-	i830_get_transformed_coordinates(maskX, maskY + h,
-					 pI830->transform[1],
-					 &mask_x[1], &mask_y[1]);
-	i830_get_transformed_coordinates(maskX + w, maskY + h,
-					 pI830->transform[1],
-					 &mask_x[2], &mask_y[2]);
-    }
-
-    /* Wait for any existing composite rectangles to land before we overwrite
-     * the VB with the next one.
-     */
-    i830WaitSync(pScrn);
-
-    i = 0;
-    /* rect (x2,y2) */
-    vb[i++] = src_x[2] / pI830->scale_units[0][0];
-    vb[i++] = src_y[2] / pI830->scale_units[0][1];
-    if (has_mask) {
-        vb[i++] = mask_x[2] / pI830->scale_units[1][0];
-        vb[i++] = mask_y[2] / pI830->scale_units[1][1];
-    }
-    vb[i++] = (float)(dstX + w);
-    vb[i++] = (float)(dstY + h);
-
-    /* rect (x1,y2) */
-    vb[i++] = src_x[1] / pI830->scale_units[0][0];
-    vb[i++] = src_y[1] / pI830->scale_units[0][1];
-    if (has_mask) {
-        vb[i++] = mask_x[1] / pI830->scale_units[1][0];
-        vb[i++] = mask_y[1] / pI830->scale_units[1][1];
-    }
-    vb[i++] = (float)dstX;
-    vb[i++] = (float)(dstY + h);
-
-    /* rect (x1,y1) */
-    vb[i++] = src_x[0] / pI830->scale_units[0][0];
-    vb[i++] = src_y[0] / pI830->scale_units[0][1];
-    if (has_mask) {
-        vb[i++] = mask_x[0] / pI830->scale_units[1][0];
-        vb[i++] = mask_y[0] / pI830->scale_units[1][1];
-    }
-    vb[i++] = (float)dstX;
-    vb[i++] = (float)dstY;
-   
-    {
-      BEGIN_LP_RING(6);
-      OUT_RING(BRW_3DPRIMITIVE | 
-	       BRW_3DPRIMITIVE_VERTEX_SEQUENTIAL |
-	       (_3DPRIM_RECTLIST << BRW_3DPRIMITIVE_TOPOLOGY_SHIFT) | 
-	       (0 << 9) |  /* CTG - indirect vertex count */
-	       4);
-      OUT_RING(3);  /* vertex count per instance */
-      OUT_RING(0); /* start vertex offset */
-      OUT_RING(1); /* single instance */
-      OUT_RING(0); /* start instance location */
-      OUT_RING(0); /* index buffer offset, ignored */
-      ADVANCE_LP_RING();
-    }
-#ifdef I830DEBUG
-    ErrorF("sync after 3dprimitive");
-    I830Sync(pScrn);
-#endif
-    /* we must be sure that the pipeline is flushed before next exa draw,
-       because that will be new state, binding state and instructions*/
-    {
-	BEGIN_LP_RING(4);
-   	OUT_RING(BRW_PIPE_CONTROL |
-	    BRW_PIPE_CONTROL_NOWRITE |
-	    BRW_PIPE_CONTROL_WC_FLUSH |
-	    BRW_PIPE_CONTROL_IS_FLUSH |
-	    (1 << 10) |  /* XXX texture cache flush for BLC/CTG */
-	    2);
-   	OUT_RING(0); /* Destination address */
-   	OUT_RING(0); /* Immediate data low DW */
-   	OUT_RING(0); /* Immediate data high DW */
-	ADVANCE_LP_RING();
-    }
-
-    /* Mark sync so we can wait for it before setting up the VB on the next
-     * rectangle.
-     */
-    i830MarkSync(pScrn);
-}
diff --git a/src/i965_render.c b/src/i965_render.c
new file mode 100644
index 0000000..99bd628
--- /dev/null
+++ b/src/i965_render.c
@@ -0,0 +1,1081 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Wang Zhenyu <zhenyu.z.wang at intel.com>
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "i830.h"
+#include "i915_reg.h"
+
+/* bring in brw structs */
+#include "brw_defines.h"
+#include "brw_structs.h"
+
+#ifdef I830DEBUG
+#define DEBUG_I830FALLBACK 1
+#endif
+
+#ifdef DEBUG_I830FALLBACK
+#define I830FALLBACK(s, arg...)				\
+do {							\
+	DPRINTF(PFX, "EXA fallback: " s "\n", ##arg); 	\
+	return FALSE;					\
+} while(0)
+#else
+#define I830FALLBACK(s, arg...) 			\
+do { 							\
+	return FALSE;					\
+} while(0) 
+#endif
+
+static void I965GetBlendCntl(int op, PicturePtr pMask, CARD32 dst_format, 
+			     CARD32 *sblend, CARD32 *dblend);
+
+struct blendinfo {
+    Bool dst_alpha;
+    Bool src_alpha;
+    CARD32 src_blend;
+    CARD32 dst_blend;
+};
+
+struct formatinfo {
+    int fmt;
+    CARD32 card_fmt;
+};
+
+// refer vol2, 3d rasterization 3.8.1
+
+/* defined in brw_defines.h */
+static struct blendinfo I965BlendOp[] = { 
+    /* Clear */
+    {0, 0, BRW_BLENDFACTOR_ZERO,          BRW_BLENDFACTOR_ZERO},
+    /* Src */
+    {0, 0, BRW_BLENDFACTOR_ONE,           BRW_BLENDFACTOR_ZERO},
+    /* Dst */
+    {0, 0, BRW_BLENDFACTOR_ZERO,          BRW_BLENDFACTOR_ONE},
+    /* Over */
+    {0, 1, BRW_BLENDFACTOR_ONE,           BRW_BLENDFACTOR_INV_SRC_ALPHA},
+    /* OverReverse */
+    {1, 0, BRW_BLENDFACTOR_INV_DST_ALPHA, BRW_BLENDFACTOR_ONE},
+    /* In */
+    {1, 0, BRW_BLENDFACTOR_DST_ALPHA,     BRW_BLENDFACTOR_ZERO},
+    /* InReverse */
+    {0, 1, BRW_BLENDFACTOR_ZERO,          BRW_BLENDFACTOR_SRC_ALPHA},
+    /* Out */
+    {1, 0, BRW_BLENDFACTOR_INV_DST_ALPHA, BRW_BLENDFACTOR_ZERO},
+    /* OutReverse */
+    {0, 1, BRW_BLENDFACTOR_ZERO,          BRW_BLENDFACTOR_INV_SRC_ALPHA},
+    /* Atop */
+    {1, 1, BRW_BLENDFACTOR_DST_ALPHA,     BRW_BLENDFACTOR_INV_SRC_ALPHA},
+    /* AtopReverse */
+    {1, 1, BRW_BLENDFACTOR_INV_DST_ALPHA, BRW_BLENDFACTOR_SRC_ALPHA},
+    /* Xor */
+    {1, 1, BRW_BLENDFACTOR_INV_DST_ALPHA, BRW_BLENDFACTOR_INV_SRC_ALPHA},
+    /* Add */
+    {0, 0, BRW_BLENDFACTOR_ONE,           BRW_BLENDFACTOR_ONE},
+};
+
+/* FIXME: surface format defined in brw_defines.h, shared Sampling engine 1.7.2*/
+static struct formatinfo I965TexFormats[] = {
+        {PICT_a8r8g8b8, BRW_SURFACEFORMAT_B8G8R8A8_UNORM },
+        {PICT_x8r8g8b8, BRW_SURFACEFORMAT_B8G8R8X8_UNORM },
+        {PICT_a8b8g8r8, BRW_SURFACEFORMAT_R8G8B8A8_UNORM },
+        {PICT_x8b8g8r8, BRW_SURFACEFORMAT_R8G8B8X8_UNORM },
+        {PICT_r5g6b5,   BRW_SURFACEFORMAT_B5G6R5_UNORM   },
+        {PICT_a1r5g5b5, BRW_SURFACEFORMAT_B5G5R5A1_UNORM },
+        {PICT_a8,       BRW_SURFACEFORMAT_A8_UNORM	 },
+};
+
+static void I965GetBlendCntl(int op, PicturePtr pMask, CARD32 dst_format, 
+			     CARD32 *sblend, CARD32 *dblend)
+{
+
+    *sblend = I965BlendOp[op].src_blend;
+    *dblend = I965BlendOp[op].dst_blend;
+
+    /* If there's no dst alpha channel, adjust the blend op so that we'll treat
+     * it as always 1.
+     */
+    if (PICT_FORMAT_A(dst_format) == 0 && I965BlendOp[op].dst_alpha) {
+        if (*sblend == BRW_BLENDFACTOR_DST_ALPHA)
+            *sblend = BRW_BLENDFACTOR_ONE;
+        else if (*sblend == BRW_BLENDFACTOR_INV_DST_ALPHA)
+            *sblend = BRW_BLENDFACTOR_ZERO;
+    }
+
+    /* If the source alpha is being used, then we should only be in a case where
+     * the source blend factor is 0, and the source blend value is the mask
+     * channels multiplied by the source picture's alpha.
+     */
+    if (pMask && pMask->componentAlpha && I965BlendOp[op].src_alpha) {
+        if (*dblend == BRW_BLENDFACTOR_SRC_ALPHA) {
+	    *dblend = BRW_BLENDFACTOR_SRC_COLOR;
+        } else if (*dblend == BRW_BLENDFACTOR_INV_SRC_ALPHA) {
+	    *dblend = BRW_BLENDFACTOR_INV_SRC_COLOR;
+        }
+    }
+
+}
+
+static Bool I965GetDestFormat(PicturePtr pDstPicture, CARD32 *dst_format)
+{
+    switch (pDstPicture->format) {
+    case PICT_a8r8g8b8:
+    case PICT_x8r8g8b8:
+        *dst_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
+        break;
+    case PICT_r5g6b5:
+        *dst_format = BRW_SURFACEFORMAT_B5G6R5_UNORM;
+        break;
+    case PICT_a1r5g5b5:
+    	*dst_format = BRW_SURFACEFORMAT_B5G5R5A1_UNORM;
+	break;
+    case PICT_x1r5g5b5:
+        *dst_format = BRW_SURFACEFORMAT_B5G5R5X1_UNORM;
+        break;
+    /* COLR_BUF_8BIT is special for YUV surfaces.  While we may end up being
+     * able to use it depending on how the hardware implements it, disable it
+     * for now while we don't know what exactly it does (what channel does it
+     * read from?
+     */
+    /*
+    case PICT_a8:
+        *dst_format = COLR_BUF_8BIT;
+        break;
+    */
+    case PICT_a4r4g4b4:
+    case PICT_x4r4g4b4:
+	*dst_format = BRW_SURFACEFORMAT_B4G4R4A4_UNORM; 
+	break;
+    default:
+        I830FALLBACK("Unsupported dest format 0x%x\n",
+                        (int)pDstPicture->format);
+    }
+
+    return TRUE;
+}
+
+static Bool I965CheckCompositeTexture(PicturePtr pPict, int unit)
+{
+    int w = pPict->pDrawable->width;
+    int h = pPict->pDrawable->height;
+    int i;
+                                                                                                                                                            
+    if ((w > 0x7ff) || (h > 0x7ff))
+        I830FALLBACK("Picture w/h too large (%dx%d)\n", w, h);
+
+    for (i = 0; i < sizeof(I965TexFormats) / sizeof(I965TexFormats[0]); i++)
+    {
+        if (I965TexFormats[i].fmt == pPict->format)
+            break;
+    }
+    if (i == sizeof(I965TexFormats) / sizeof(I965TexFormats[0]))
+        I830FALLBACK("Unsupported picture format 0x%x\n",
+                         (int)pPict->format);
+
+    if (pPict->repeat && pPict->repeatType != RepeatNormal)
+	I830FALLBACK("extended repeat (%d) not supported\n",
+		     pPict->repeatType);
+
+    if (pPict->filter != PictFilterNearest &&
+        pPict->filter != PictFilterBilinear)
+        I830FALLBACK("Unsupported filter 0x%x\n", pPict->filter);
+
+    return TRUE;
+}
+
+Bool
+I965EXACheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+		      PicturePtr pDstPicture)
+{
+    CARD32 tmp1;
+    
+    /* Check for unsupported compositing operations. */
+    if (op >= sizeof(I965BlendOp) / sizeof(I965BlendOp[0]))
+        I830FALLBACK("Unsupported Composite op 0x%x\n", op);
+
+    if (pMaskPicture != NULL && pMaskPicture->componentAlpha) {
+        /* Check if it's component alpha that relies on a source alpha and on
+         * the source value.  We can only get one of those into the single
+         * source value that we get to blend with.
+         */
+        if (I965BlendOp[op].src_alpha &&
+            (I965BlendOp[op].src_blend != BRW_BLENDFACTOR_ZERO))
+            	I830FALLBACK("Component alpha not supported with source "
+                            "alpha and source value blending.\n");
+	/* XXX: fallback now for mask with componentAlpha */
+	I830FALLBACK("mask componentAlpha not ready.\n");
+    }
+
+    if (!I965CheckCompositeTexture(pSrcPicture, 0))
+        I830FALLBACK("Check Src picture texture\n");
+    if (pMaskPicture != NULL && !I965CheckCompositeTexture(pMaskPicture, 1))
+        I830FALLBACK("Check Mask picture texture\n");
+
+    if (!I965GetDestFormat(pDstPicture, &tmp1)) 
+	I830FALLBACK("Get Color buffer format\n");
+
+    return TRUE;
+
+}
+
+#define ALIGN(i,m)    (((i) + (m) - 1) & ~((m) - 1))
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define BRW_GRF_BLOCKS(nreg)    ((nreg + 15) / 16 - 1)
+
+static int urb_vs_start, urb_vs_size;
+static int urb_gs_start, urb_gs_size;
+static int urb_clip_start, urb_clip_size;
+static int urb_sf_start, urb_sf_size;
+static int urb_cs_start, urb_cs_size;
+
+static struct brw_surface_state *dest_surf_state;
+static struct brw_surface_state *src_surf_state;
+static struct brw_surface_state *mask_surf_state;
+static struct brw_sampler_state *src_sampler_state;
+static struct brw_sampler_state *mask_sampler_state;  
+static struct brw_sampler_default_color *default_color_state;
+
+static struct brw_vs_unit_state *vs_state;
+static struct brw_sf_unit_state *sf_state;
+static struct brw_wm_unit_state *wm_state;
+static struct brw_cc_unit_state *cc_state;
+static struct brw_cc_viewport *cc_viewport;
+
+static struct brw_instruction *sf_kernel;
+static struct brw_instruction *ps_kernel;
+static struct brw_instruction *sip_kernel;
+
+static CARD32 *binding_table;
+static int binding_table_entries; 
+
+static int dest_surf_offset, src_surf_offset, mask_surf_offset;
+static int src_sampler_offset, mask_sampler_offset,vs_offset;
+static int sf_offset, wm_offset, cc_offset, vb_offset, cc_viewport_offset;
+static int sf_kernel_offset, ps_kernel_offset, sip_kernel_offset;
+static int wm_scratch_offset;
+static int binding_table_offset;
+static int default_color_offset; 
+static int next_offset, total_state_size;
+static char *state_base;
+static int state_base_offset;
+static float *vb;
+static int vb_size = (4 * 4) * 4 ; /* 4 DWORDS per vertex*/ 
+
+static CARD32 src_blend, dst_blend;
+
+static const CARD32 sip_kernel_static[][4] = {
+/*    wait (1) a0<1>UW a145<0,1,0>UW { align1 +  } */
+    { 0x00000030, 0x20000108, 0x00001220, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+};
+
+/*
+ * this program computes dA/dx and dA/dy for the texture coordinates along
+ * with the base texture coordinate. It was extracted from the Mesa driver
+ */
+
+#define SF_KERNEL_NUM_GRF  16
+#define SF_MAX_THREADS	   1
+
+static const CARD32 sf_kernel_static[][4] = {
+#include "exa_sf_prog.h"
+};
+
+static const CARD32 sf_kernel_static_mask[][4] = {
+#include "exa_sf_mask_prog.h"
+};
+
+/* ps kernels */
+#define PS_KERNEL_NUM_GRF   32
+#define PS_MAX_THREADS	   32
+/* 1: no mask */
+static const CARD32 ps_kernel_static_nomask [][4] = {
+#include "exa_wm_nomask_prog.h"
+};
+
+/* 2: mask with componentAlpha, src * mask color, XXX: later */
+static const CARD32 ps_kernel_static_maskca [][4] = {
+/*#include "i965_composite_wm_maskca.h" */
+};
+
+/* 3: mask without componentAlpha, src * mask alpha */
+static const CARD32 ps_kernel_static_masknoca [][4] = {
+#include "exa_wm_masknoca_prog.h"
+};
+
+static CARD32 i965_get_card_format(PicturePtr pPict) 
+{
+	int i;
+        for (i = 0; i < sizeof(I965TexFormats) / sizeof(I965TexFormats[0]); i++) {
+            if (I965TexFormats[i].fmt == pPict->format)
+                break;
+        }
+	return I965TexFormats[i].card_fmt;
+}
+
+Bool
+I965EXAPrepareComposite(int op, PicturePtr pSrcPicture,
+			PicturePtr pMaskPicture, PicturePtr pDstPicture,
+			PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD32 src_offset, src_pitch;
+    CARD32 mask_offset = 0, mask_pitch = 0;
+    CARD32 dst_format, dst_offset, dst_pitch;
+
+#ifdef XF86DRI
+    if (pI830->directRenderingEnabled) {
+        drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
+
+        pSAREAPriv->ctxOwner = DRIGetContext(pScrn->pScreen);
+    }
+#endif
+
+    pI830->last_3d = LAST_3D_RENDER;
+
+    src_offset = intel_get_pixmap_offset(pSrc);
+    src_pitch = intel_get_pixmap_pitch(pSrc);
+    dst_offset = intel_get_pixmap_offset(pDst);
+    dst_pitch = intel_get_pixmap_pitch(pDst);
+    if (pMask) {
+	mask_offset = intel_get_pixmap_offset(pMask);
+	mask_pitch = intel_get_pixmap_pitch(pMask);
+    }
+    pI830->scale_units[0][0] = pSrc->drawable.width;
+    pI830->scale_units[0][1] = pSrc->drawable.height;
+
+    pI830->transform[0] = pSrcPicture->transform;
+
+    if (!pMask) {
+	pI830->transform[1] = NULL;
+	pI830->scale_units[1][0] = -1;
+	pI830->scale_units[1][1] = -1;
+    } else {
+	pI830->transform[1] = pMaskPicture->transform;
+	pI830->scale_units[1][0] = pMask->drawable.width;
+	pI830->scale_units[1][1] = pMask->drawable.height;
+    }
+
+	/* setup 3d pipeline state */
+
+   binding_table_entries = 2; /* default no mask */
+
+   /* Wait for sync before we start setting up our new state */
+   i830WaitSync(pScrn);
+
+   /* Set up our layout of state in framebuffer.  First the general state: */
+   next_offset = 0;
+   vs_offset = ALIGN(next_offset, 64);
+   next_offset = vs_offset + sizeof(*vs_state);
+    
+   sf_offset = ALIGN(next_offset, 32);
+   next_offset = sf_offset + sizeof(*sf_state);
+    
+   wm_offset = ALIGN(next_offset, 32);
+   next_offset = wm_offset + sizeof(*wm_state);
+    
+   wm_scratch_offset = ALIGN(next_offset, 1024);
+   next_offset = wm_scratch_offset + 1024 * PS_MAX_THREADS;
+
+   cc_offset = ALIGN(next_offset, 32);
+   next_offset = cc_offset + sizeof(*cc_state);
+
+   /* keep current sf_kernel, which will send one setup urb entry to
+	PS kernel */
+   sf_kernel_offset = ALIGN(next_offset, 64);
+   if (pMask) 
+       next_offset = sf_kernel_offset + sizeof (sf_kernel_static_mask);
+   else
+       next_offset = sf_kernel_offset + sizeof (sf_kernel_static);
+
+   //XXX: ps_kernel may be seperated, fix with offset
+   ps_kernel_offset = ALIGN(next_offset, 64);
+   if (pMask) {
+	if (pMaskPicture->componentAlpha)
+	    next_offset = ps_kernel_offset + sizeof(ps_kernel_static_maskca);
+	else 
+	    next_offset = ps_kernel_offset + sizeof(ps_kernel_static_masknoca);
+   } else 
+   	next_offset = ps_kernel_offset + sizeof (ps_kernel_static_nomask);
+    
+   sip_kernel_offset = ALIGN(next_offset, 64);
+   next_offset = sip_kernel_offset + sizeof (sip_kernel_static);
+   
+   // needed?
+   cc_viewport_offset = ALIGN(next_offset, 32);
+   next_offset = cc_viewport_offset + sizeof(*cc_viewport);
+
+   // for texture sampler
+   src_sampler_offset = ALIGN(next_offset, 32);
+   next_offset = src_sampler_offset + sizeof(*src_sampler_state);
+
+   if (pMask) {
+   	mask_sampler_offset = ALIGN(next_offset, 32);
+   	next_offset = mask_sampler_offset + sizeof(*mask_sampler_state);
+   }
+   /* Align VB to native size of elements, for safety */
+   vb_offset = ALIGN(next_offset, 8);
+   next_offset = vb_offset + vb_size;
+
+   /* And then the general state: */
+   dest_surf_offset = ALIGN(next_offset, 32);
+   next_offset = dest_surf_offset + sizeof(*dest_surf_state);
+
+   src_surf_offset = ALIGN(next_offset, 32);
+   next_offset = src_surf_offset + sizeof(*src_surf_state);
+
+   if (pMask) {
+   	mask_surf_offset = ALIGN(next_offset, 32);
+   	next_offset = mask_surf_offset + sizeof(*mask_surf_state);
+	binding_table_entries = 3;
+   }
+
+   binding_table_offset = ALIGN(next_offset, 32);
+   next_offset = binding_table_offset + (binding_table_entries * 4);
+
+   default_color_offset = ALIGN(next_offset, 32);
+   next_offset = default_color_offset + sizeof(*default_color_state);
+
+   total_state_size = next_offset;
+   assert(total_state_size < EXA_LINEAR_EXTRA);
+
+   state_base_offset = pI830->EXAStateMem.Start;
+   state_base_offset = ALIGN(state_base_offset, 64);
+   state_base = (char *)(pI830->FbBase + state_base_offset);
+
+   vs_state = (void *)(state_base + vs_offset);
+   sf_state = (void *)(state_base + sf_offset);
+   wm_state = (void *)(state_base + wm_offset);
+   cc_state = (void *)(state_base + cc_offset);
+   sf_kernel = (void *)(state_base + sf_kernel_offset);
+   ps_kernel = (void *)(state_base + ps_kernel_offset);
+   sip_kernel = (void *)(state_base + sip_kernel_offset);
+   
+   cc_viewport = (void *)(state_base + cc_viewport_offset);
+   
+   dest_surf_state = (void *)(state_base + dest_surf_offset);
+   src_surf_state = (void *)(state_base + src_surf_offset);
+   if (pMask)
+	mask_surf_state = (void *)(state_base + mask_surf_offset);
+
+   src_sampler_state = (void *)(state_base + src_sampler_offset);
+   if (pMask)
+	mask_sampler_state = (void *)(state_base + mask_sampler_offset);
+
+   binding_table = (void *)(state_base + binding_table_offset);
+
+   vb = (void *)(state_base + vb_offset);
+
+   default_color_state = (void*)(state_base + default_color_offset);
+
+   /* Set up a default static partitioning of the URB, which is supposed to
+    * allow anything we would want to do, at potentially lower performance.
+    */
+#define URB_CS_ENTRY_SIZE     0
+#define URB_CS_ENTRIES	      0
+   
+#define URB_VS_ENTRY_SIZE     1	  // each 512-bit row
+#define URB_VS_ENTRIES	      8	  // we needs at least 8 entries
+   
+#define URB_GS_ENTRY_SIZE     0
+#define URB_GS_ENTRIES	      0
+   
+#define URB_CLIP_ENTRY_SIZE   0
+#define URB_CLIP_ENTRIES      0
+   
+#define URB_SF_ENTRY_SIZE     2
+#define URB_SF_ENTRIES	      1
+
+   urb_vs_start = 0;
+   urb_vs_size = URB_VS_ENTRIES * URB_VS_ENTRY_SIZE;
+   urb_gs_start = urb_vs_start + urb_vs_size;
+   urb_gs_size = URB_GS_ENTRIES * URB_GS_ENTRY_SIZE;
+   urb_clip_start = urb_gs_start + urb_gs_size;
+   urb_clip_size = URB_CLIP_ENTRIES * URB_CLIP_ENTRY_SIZE;
+   urb_sf_start = urb_clip_start + urb_clip_size;
+   urb_sf_size = URB_SF_ENTRIES * URB_SF_ENTRY_SIZE;
+   urb_cs_start = urb_sf_start + urb_sf_size;
+   urb_cs_size = URB_CS_ENTRIES * URB_CS_ENTRY_SIZE;
+
+   /* We'll be poking the state buffers that could be in use by the 3d hardware
+    * here, but we should have synced the 3D engine already in I830PutImage.
+    */
+
+   memset (cc_viewport, 0, sizeof (*cc_viewport));
+   cc_viewport->min_depth = -1.e35;
+   cc_viewport->max_depth = 1.e35;
+
+   /* Color calculator state */
+   memset(cc_state, 0, sizeof(*cc_state));
+   cc_state->cc0.stencil_enable = 0;   /* disable stencil */
+   cc_state->cc2.depth_test = 0;       /* disable depth test */
+   cc_state->cc2.logicop_enable = 0;   /* disable logic op */
+   cc_state->cc3.ia_blend_enable = 1;  /* blend alpha just like colors */
+   cc_state->cc3.blend_enable = 1;     /* enable color blend */
+   cc_state->cc3.alpha_test = 0;       /* disable alpha test */
+   cc_state->cc4.cc_viewport_state_offset = (state_base_offset + cc_viewport_offset) >> 5;
+   cc_state->cc5.dither_enable = 0;    /* disable dither */
+   cc_state->cc5.logicop_func = 0xc;   /* COPY */
+   cc_state->cc5.statistics_enable = 1;
+   cc_state->cc5.ia_blend_function = BRW_BLENDFUNCTION_ADD;
+   I965GetBlendCntl(op, pMaskPicture, pDstPicture->format, 
+		    &src_blend, &dst_blend);
+   /* XXX: alpha blend factor should be same as color, but check
+	   for CA case in future */
+   cc_state->cc5.ia_src_blend_factor = src_blend;
+   cc_state->cc5.ia_dest_blend_factor = dst_blend;
+   cc_state->cc6.blend_function = BRW_BLENDFUNCTION_ADD;
+   cc_state->cc6.src_blend_factor = src_blend;
+   cc_state->cc6.dest_blend_factor = dst_blend;
+   cc_state->cc6.clamp_post_alpha_blend = 1; 
+   cc_state->cc6.clamp_pre_alpha_blend = 1; 
+   cc_state->cc6.clamp_range = 0;  /* clamp range [0,1] */
+
+   /* Upload system kernel */
+   memcpy (sip_kernel, sip_kernel_static, sizeof (sip_kernel_static));
+   
+   /* Set up the state buffer for the destination surface */
+   memset(dest_surf_state, 0, sizeof(*dest_surf_state));
+   dest_surf_state->ss0.surface_type = BRW_SURFACE_2D;
+   dest_surf_state->ss0.data_return_format = BRW_SURFACERETURNFORMAT_FLOAT32;
+   I965GetDestFormat(pDstPicture, &dst_format);
+   dest_surf_state->ss0.surface_format = dst_format;
+
+   dest_surf_state->ss0.writedisable_alpha = 0;
+   dest_surf_state->ss0.writedisable_red = 0;
+   dest_surf_state->ss0.writedisable_green = 0;
+   dest_surf_state->ss0.writedisable_blue = 0;
+   dest_surf_state->ss0.color_blend = 1;
+   dest_surf_state->ss0.vert_line_stride = 0;
+   dest_surf_state->ss0.vert_line_stride_ofs = 0;
+   dest_surf_state->ss0.mipmap_layout_mode = 0;
+   dest_surf_state->ss0.render_cache_read_mode = 0;
+   
+   dest_surf_state->ss1.base_addr = dst_offset;
+   dest_surf_state->ss2.height = pDst->drawable.height - 1;
+   dest_surf_state->ss2.width = pDst->drawable.width - 1;
+   dest_surf_state->ss2.mip_count = 0;
+   dest_surf_state->ss2.render_target_rotation = 0;
+   dest_surf_state->ss3.pitch = dst_pitch - 1; 
+
+   /* Set up the source surface state buffer */
+   memset(src_surf_state, 0, sizeof(*src_surf_state));
+   src_surf_state->ss0.surface_type = BRW_SURFACE_2D;
+   src_surf_state->ss0.surface_format = i965_get_card_format(pSrcPicture);
+
+   src_surf_state->ss0.writedisable_alpha = 0;
+   src_surf_state->ss0.writedisable_red = 0;
+   src_surf_state->ss0.writedisable_green = 0;
+   src_surf_state->ss0.writedisable_blue = 0;
+   src_surf_state->ss0.color_blend = 1;
+   src_surf_state->ss0.vert_line_stride = 0;
+   src_surf_state->ss0.vert_line_stride_ofs = 0;
+   src_surf_state->ss0.mipmap_layout_mode = 0;
+   src_surf_state->ss0.render_cache_read_mode = 0;
+   
+   src_surf_state->ss1.base_addr = src_offset;
+   src_surf_state->ss2.width = pSrc->drawable.width - 1;
+   src_surf_state->ss2.height = pSrc->drawable.height - 1;
+   src_surf_state->ss2.mip_count = 0;
+   src_surf_state->ss2.render_target_rotation = 0;
+   src_surf_state->ss3.pitch = src_pitch - 1; 
+
+   /* setup mask surface */
+   if (pMask) {
+   	memset(mask_surf_state, 0, sizeof(*mask_surf_state));
+	mask_surf_state->ss0.surface_type = BRW_SURFACE_2D;
+   	mask_surf_state->ss0.surface_format = i965_get_card_format(pMaskPicture);
+
+   	mask_surf_state->ss0.writedisable_alpha = 0;
+   	mask_surf_state->ss0.writedisable_red = 0;
+   	mask_surf_state->ss0.writedisable_green = 0;
+   	mask_surf_state->ss0.writedisable_blue = 0;
+   	mask_surf_state->ss0.color_blend = 1;
+   	mask_surf_state->ss0.vert_line_stride = 0;
+   	mask_surf_state->ss0.vert_line_stride_ofs = 0;
+   	mask_surf_state->ss0.mipmap_layout_mode = 0;
+   	mask_surf_state->ss0.render_cache_read_mode = 0;
+   
+   	mask_surf_state->ss1.base_addr = mask_offset;
+   	mask_surf_state->ss2.width = pMask->drawable.width - 1;
+   	mask_surf_state->ss2.height = pMask->drawable.height - 1;
+   	mask_surf_state->ss2.mip_count = 0;
+   	mask_surf_state->ss2.render_target_rotation = 0;
+   	mask_surf_state->ss3.pitch = mask_pitch - 1; 
+   }
+
+   /* Set up a binding table for our surfaces.  Only the PS will use it */
+   binding_table[0] = state_base_offset + dest_surf_offset;
+   binding_table[1] = state_base_offset + src_surf_offset;
+   if (pMask)
+   	binding_table[2] = state_base_offset + mask_surf_offset;
+
+   /* PS kernel use this sampler */
+   memset(src_sampler_state, 0, sizeof(*src_sampler_state));
+   src_sampler_state->ss0.lod_preclamp = 1; /* GL mode */
+   switch(pSrcPicture->filter) {
+   case PictFilterNearest:
+   	src_sampler_state->ss0.min_filter = BRW_MAPFILTER_NEAREST; 
+   	src_sampler_state->ss0.mag_filter = BRW_MAPFILTER_NEAREST;
+	break;
+   case PictFilterBilinear:
+   	src_sampler_state->ss0.min_filter = BRW_MAPFILTER_LINEAR; 
+   	src_sampler_state->ss0.mag_filter = BRW_MAPFILTER_LINEAR;
+	break;
+   default:
+	I830FALLBACK("Bad filter 0x%x\n", pSrcPicture->filter);
+   }
+
+   memset(default_color_state, 0, sizeof(*default_color_state));
+   default_color_state->color[0] = 0.0; /* R */
+   default_color_state->color[1] = 0.0; /* G */
+   default_color_state->color[2] = 0.0; /* B */
+   default_color_state->color[3] = 1.0; /* A */
+
+   src_sampler_state->ss0.default_color_mode = 0; /* GL mode */
+
+   if (!pSrcPicture->repeat) {
+   	src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER; 
+   	src_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER;
+   	src_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER;
+	src_sampler_state->ss2.default_color_pointer = 
+			(state_base_offset + default_color_offset) >> 5;
+   } else {
+   	src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_WRAP; 
+   	src_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_WRAP;
+   	src_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_WRAP;
+   }
+   src_sampler_state->ss3.chroma_key_enable = 0; /* disable chromakey */
+
+   if (pMask) {
+   	memset(mask_sampler_state, 0, sizeof(*mask_sampler_state));
+   	mask_sampler_state->ss0.lod_preclamp = 1; /* GL mode */
+   	switch(pMaskPicture->filter) {
+   	case PictFilterNearest:
+   	    mask_sampler_state->ss0.min_filter = BRW_MAPFILTER_NEAREST; 
+   	    mask_sampler_state->ss0.mag_filter = BRW_MAPFILTER_NEAREST;
+	    break;
+   	case PictFilterBilinear:
+   	    mask_sampler_state->ss0.min_filter = BRW_MAPFILTER_LINEAR; 
+   	    mask_sampler_state->ss0.mag_filter = BRW_MAPFILTER_LINEAR;
+	    break;
+   	default:
+	    I830FALLBACK("Bad filter 0x%x\n", pMaskPicture->filter);
+   	}
+
+   	if (!pMaskPicture->repeat) {
+   	    mask_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER; 
+   	    mask_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER;
+   	    mask_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER;
+            mask_sampler_state->ss2.default_color_pointer = 
+				(state_base_offset + default_color_offset)>>5;
+   	} else {
+   	    mask_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_WRAP; 
+   	    mask_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_WRAP;
+   	    mask_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_WRAP;
+    	}
+   	mask_sampler_state->ss3.chroma_key_enable = 0; /* disable chromakey */
+   }
+
+   /* Set up the vertex shader to be disabled (passthrough) */
+   memset(vs_state, 0, sizeof(*vs_state));
+   vs_state->thread4.nr_urb_entries = URB_VS_ENTRIES;
+   vs_state->thread4.urb_entry_allocation_size = URB_VS_ENTRY_SIZE - 1;
+   vs_state->vs6.vs_enable = 0;
+   vs_state->vs6.vert_cache_disable = 1;
+
+   // XXX: sf_kernel? keep it as now
+   /* Set up the SF kernel to do coord interp: for each attribute,
+    * calculate dA/dx and dA/dy.  Hand these interpolation coefficients
+    * back to SF which then hands pixels off to WM.
+    */
+   if (pMask) 
+       memcpy (sf_kernel, sf_kernel_static_mask, sizeof (sf_kernel_static));
+   else
+       memcpy (sf_kernel, sf_kernel_static, sizeof (sf_kernel_static));
+
+   memset(sf_state, 0, sizeof(*sf_state));
+   sf_state->thread0.kernel_start_pointer = 
+	       (state_base_offset + sf_kernel_offset) >> 6;
+   sf_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(SF_KERNEL_NUM_GRF);
+   sf_state->sf1.single_program_flow = 1;
+   sf_state->sf1.binding_table_entry_count = 0;
+   sf_state->sf1.thread_priority = 0;
+   sf_state->sf1.floating_point_mode = 0; /* Mesa does this */
+   sf_state->sf1.illegal_op_exception_enable = 1;
+   sf_state->sf1.mask_stack_exception_enable = 1;
+   sf_state->sf1.sw_exception_enable = 1;
+   sf_state->thread2.per_thread_scratch_space = 0;
+   sf_state->thread2.scratch_space_base_pointer = 0; /* not used in our kernel */
+   sf_state->thread3.const_urb_entry_read_length = 0; /* no const URBs */
+   sf_state->thread3.const_urb_entry_read_offset = 0; /* no const URBs */
+   sf_state->thread3.urb_entry_read_length = 1; /* 1 URB per vertex */
+   sf_state->thread3.urb_entry_read_offset = 0;
+   sf_state->thread3.dispatch_grf_start_reg = 3;
+   sf_state->thread4.max_threads = SF_MAX_THREADS - 1;
+   sf_state->thread4.urb_entry_allocation_size = URB_SF_ENTRY_SIZE - 1;
+   sf_state->thread4.nr_urb_entries = URB_SF_ENTRIES;
+   sf_state->thread4.stats_enable = 1;
+   sf_state->sf5.viewport_transform = FALSE; /* skip viewport */
+   sf_state->sf6.cull_mode = BRW_CULLMODE_NONE;
+   sf_state->sf6.scissor = 0;
+   sf_state->sf7.trifan_pv = 2;
+   sf_state->sf6.dest_org_vbias = 0x8;
+   sf_state->sf6.dest_org_hbias = 0x8;
+
+   /* Set up the PS kernel (dispatched by WM) 
+    */
+    
+   if (pMask) {
+	if (pMaskPicture->componentAlpha)
+   	    memcpy (ps_kernel, ps_kernel_static_maskca, sizeof (ps_kernel_static_maskca));
+	else
+   	    memcpy (ps_kernel, ps_kernel_static_masknoca, sizeof (ps_kernel_static_masknoca));
+   } else 
+   	memcpy (ps_kernel, ps_kernel_static_nomask, sizeof (ps_kernel_static_nomask));
+
+   memset (wm_state, 0, sizeof (*wm_state));
+   wm_state->thread0.kernel_start_pointer = 
+	    (state_base_offset + ps_kernel_offset) >> 6;
+   wm_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(PS_KERNEL_NUM_GRF);
+   wm_state->thread1.single_program_flow = 1;
+   if (!pMask)
+       wm_state->thread1.binding_table_entry_count = 2; /* 1 tex and fb */
+   else
+       wm_state->thread1.binding_table_entry_count = 3; /* 2 tex and fb */
+
+   wm_state->thread2.scratch_space_base_pointer = (state_base_offset + 
+						   wm_scratch_offset)>>10;
+   wm_state->thread2.per_thread_scratch_space = 0;
+   // XXX: urb allocation
+   wm_state->thread3.const_urb_entry_read_length = 0;
+   wm_state->thread3.const_urb_entry_read_offset = 0;
+   if (pMask)
+       wm_state->thread3.urb_entry_read_length = 2;  /* two per pair of attrib */
+   else 
+       wm_state->thread3.urb_entry_read_length = 1;  /* one per pair of attrib */
+   wm_state->thread3.urb_entry_read_offset = 0;
+   // wm kernel use urb from 3, see wm_program in compiler module
+   wm_state->thread3.dispatch_grf_start_reg = 3; /* must match kernel */
+
+   wm_state->wm4.stats_enable = 1;  /* statistic */
+   wm_state->wm4.sampler_state_pointer = (state_base_offset + src_sampler_offset) >> 5; 
+   wm_state->wm4.sampler_count = 1; /* 1-4 samplers used */
+   wm_state->wm5.max_threads = PS_MAX_THREADS - 1;
+   wm_state->wm5.thread_dispatch_enable = 1;
+   //just use 16-pixel dispatch (4 subspans), don't need to change kernel start point
+   wm_state->wm5.enable_16_pix = 1;
+   wm_state->wm5.enable_8_pix = 0;
+   wm_state->wm5.early_depth_test = 1;
+
+   /* Begin the long sequence of commands needed to set up the 3D 
+    * rendering pipe
+    */
+   {
+	BEGIN_LP_RING(2);
+   	OUT_RING(MI_FLUSH | 
+	    MI_STATE_INSTRUCTION_CACHE_FLUSH |
+	    BRW_MI_GLOBAL_SNAPSHOT_RESET);
+	OUT_RING(MI_NOOP);
+	ADVANCE_LP_RING();
+   }
+   {
+        BEGIN_LP_RING(12);
+   
+        /* Match Mesa driver setup */
+        OUT_RING(BRW_PIPELINE_SELECT | PIPELINE_SELECT_3D);
+   
+   	OUT_RING(BRW_CS_URB_STATE | 0);
+   	OUT_RING((0 << 4) |  /* URB Entry Allocation Size */
+            (0 << 0));  /* Number of URB Entries */
+
+   /* Zero out the two base address registers so all offsets are absolute */
+   	OUT_RING(BRW_STATE_BASE_ADDRESS | 4);
+   	OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* Generate state base address */
+   	OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* Surface state base address */
+   	OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* media base addr, don't care */
+   	OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY);  /* general state max addr, disabled */
+   	OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY);  /* media object state max addr, disabled */
+
+   /* Set system instruction pointer */
+   	OUT_RING(BRW_STATE_SIP | 0);
+   	OUT_RING(state_base_offset + sip_kernel_offset); /* system instruction pointer */
+	OUT_RING(MI_NOOP);
+	ADVANCE_LP_RING();
+   }
+   {
+	BEGIN_LP_RING(26);
+   /* Pipe control */
+   	OUT_RING(BRW_PIPE_CONTROL |
+	    BRW_PIPE_CONTROL_NOWRITE |
+	    BRW_PIPE_CONTROL_IS_FLUSH |
+	    2);
+   	OUT_RING(0);			       /* Destination address */
+   	OUT_RING(0);			       /* Immediate data low DW */
+   	OUT_RING(0);			       /* Immediate data high DW */
+
+   /* Binding table pointers */
+   	OUT_RING(BRW_3DSTATE_BINDING_TABLE_POINTERS | 4);
+   	OUT_RING(0); /* vs */
+   	OUT_RING(0); /* gs */
+   	OUT_RING(0); /* clip */
+   	OUT_RING(0); /* sf */
+   /* Only the PS uses the binding table */
+   	OUT_RING(state_base_offset + binding_table_offset); /* ps */
+
+   /* The drawing rectangle clipping is always on.  Set it to values that
+    * shouldn't do any clipping.
+    */
+   	OUT_RING(BRW_3DSTATE_DRAWING_RECTANGLE | 2);	/* XXX 3 for BLC or CTG */
+   	OUT_RING(0x00000000);	/* ymin, xmin */
+   	OUT_RING((pScrn->virtualX - 1) |
+ 	         (pScrn->virtualY - 1) << 16); /* ymax, xmax */
+   	OUT_RING(0x00000000);	/* yorigin, xorigin */
+
+   /* skip the depth buffer */
+   /* skip the polygon stipple */
+   /* skip the polygon stipple offset */
+   /* skip the line stipple */
+   
+   /* Set the pointers to the 3d pipeline state */
+   	OUT_RING(BRW_3DSTATE_PIPELINED_POINTERS | 5);
+   	OUT_RING(state_base_offset + vs_offset);  /* 32 byte aligned */
+   	OUT_RING(BRW_GS_DISABLE);		     /* disable GS, resulting in passthrough */
+   	OUT_RING(BRW_CLIP_DISABLE);		     /* disable CLIP, resulting in passthrough */
+   	OUT_RING(state_base_offset + sf_offset);  /* 32 byte aligned */
+   	OUT_RING(state_base_offset + wm_offset);  /* 32 byte aligned */
+   	OUT_RING(state_base_offset + cc_offset);  /* 64 byte aligned */
+
+   /* URB fence */
+   	OUT_RING(BRW_URB_FENCE |
+        	 UF0_CS_REALLOC |
+	    	 UF0_SF_REALLOC |
+	    	 UF0_CLIP_REALLOC |
+	         UF0_GS_REALLOC |
+	         UF0_VS_REALLOC |
+	    	 1);
+   	OUT_RING(((urb_clip_start + urb_clip_size) << UF1_CLIP_FENCE_SHIFT) |
+	    	 ((urb_gs_start + urb_gs_size) << UF1_GS_FENCE_SHIFT) |
+	    	 ((urb_vs_start + urb_vs_size) << UF1_VS_FENCE_SHIFT));
+   	OUT_RING(((urb_cs_start + urb_cs_size) << UF2_CS_FENCE_SHIFT) |
+	     	 ((urb_sf_start + urb_sf_size) << UF2_SF_FENCE_SHIFT));
+
+   /* Constant buffer state */
+   	OUT_RING(BRW_CS_URB_STATE | 0);
+   	OUT_RING(((URB_CS_ENTRY_SIZE - 1) << 4) | /* URB Entry Allocation Size */
+	    	 (URB_CS_ENTRIES << 0));	     /* Number of URB Entries */
+	ADVANCE_LP_RING();
+   }
+   {
+        int nelem = pMask ? 3: 2;
+   	BEGIN_LP_RING(pMask?12:10);
+   /* Set up the pointer to our vertex buffer */
+   	OUT_RING(BRW_3DSTATE_VERTEX_BUFFERS | 3); 
+   	OUT_RING((0 << VB0_BUFFER_INDEX_SHIFT) |
+	    	 VB0_VERTEXDATA |
+	    	 ((4 * 2 * nelem) << VB0_BUFFER_PITCH_SHIFT)); 
+   	OUT_RING(state_base_offset + vb_offset);
+   	OUT_RING(2); // max index, prim has 4 coords
+   	OUT_RING(0); // ignore for VERTEXDATA, but still there
+
+   /* Set up our vertex elements, sourced from the single vertex buffer. */
+   	OUT_RING(BRW_3DSTATE_VERTEX_ELEMENTS | ((2 * nelem) - 1));  
+   /* offset 0: X,Y -> {X, Y, 1.0, 1.0} */
+   	OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
+	    	 VE0_VALID |
+	    	 (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
+	    	 (0 << VE0_OFFSET_SHIFT));
+   	OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
+	    	 (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
+	     	 (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
+	    	 (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
+	    	 (0 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
+   /* offset 8: S0, T0 -> {S0, T0, 1.0, 1.0} */
+   	OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
+	    	 VE0_VALID |
+	    	 (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
+	    	 (8 << VE0_OFFSET_SHIFT));
+   	OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
+	    	 (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
+	    	 (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
+	     	 (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
+	    	 (4 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
+
+   	if (pMask) {
+   		OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
+	    		 VE0_VALID |
+	    		 (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
+	    		 (16 << VE0_OFFSET_SHIFT));
+		OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
+	    		 (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
+	    		 (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
+	    		 (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
+	    		 (8 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); 
+   	}
+   
+   	ADVANCE_LP_RING();
+   }
+
+#ifdef I830DEBUG
+    ErrorF("try to sync to show any errors...");
+    I830Sync(pScrn);
+#endif
+    return TRUE;
+}	
+
+void
+I965EXAComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
+		int dstX, int dstY, int w, int h)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+    Bool has_mask;
+    float src_x[3], src_y[3], mask_x[3], mask_y[3];
+    int i;
+
+    i830_get_transformed_coordinates(srcX, srcY,
+				     pI830->transform[0],
+				     &src_x[0], &src_y[0]);
+    i830_get_transformed_coordinates(srcX, srcY + h,
+				     pI830->transform[0],
+				     &src_x[1], &src_y[1]);
+    i830_get_transformed_coordinates(srcX + w, srcY + h,
+				     pI830->transform[0],
+				     &src_x[2], &src_y[2]);
+
+    if (pI830->scale_units[1][0] == -1 || pI830->scale_units[1][1] == -1) {
+	has_mask = FALSE;
+    } else {
+	has_mask = TRUE;
+	i830_get_transformed_coordinates(maskX, maskY,
+					 pI830->transform[1],
+					 &mask_x[0], &mask_y[0]);
+	i830_get_transformed_coordinates(maskX, maskY + h,
+					 pI830->transform[1],
+					 &mask_x[1], &mask_y[1]);
+	i830_get_transformed_coordinates(maskX + w, maskY + h,
+					 pI830->transform[1],
+					 &mask_x[2], &mask_y[2]);
+    }
+
+    /* Wait for any existing composite rectangles to land before we overwrite
+     * the VB with the next one.
+     */
+    i830WaitSync(pScrn);
+
+    i = 0;
+    /* rect (x2,y2) */
+    vb[i++] = src_x[2] / pI830->scale_units[0][0];
+    vb[i++] = src_y[2] / pI830->scale_units[0][1];
+    if (has_mask) {
+        vb[i++] = mask_x[2] / pI830->scale_units[1][0];
+        vb[i++] = mask_y[2] / pI830->scale_units[1][1];
+    }
+    vb[i++] = (float)(dstX + w);
+    vb[i++] = (float)(dstY + h);
+
+    /* rect (x1,y2) */
+    vb[i++] = src_x[1] / pI830->scale_units[0][0];
+    vb[i++] = src_y[1] / pI830->scale_units[0][1];
+    if (has_mask) {
+        vb[i++] = mask_x[1] / pI830->scale_units[1][0];
+        vb[i++] = mask_y[1] / pI830->scale_units[1][1];
+    }
+    vb[i++] = (float)dstX;
+    vb[i++] = (float)(dstY + h);
+
+    /* rect (x1,y1) */
+    vb[i++] = src_x[0] / pI830->scale_units[0][0];
+    vb[i++] = src_y[0] / pI830->scale_units[0][1];
+    if (has_mask) {
+        vb[i++] = mask_x[0] / pI830->scale_units[1][0];
+        vb[i++] = mask_y[0] / pI830->scale_units[1][1];
+    }
+    vb[i++] = (float)dstX;
+    vb[i++] = (float)dstY;
+   
+    {
+      BEGIN_LP_RING(6);
+      OUT_RING(BRW_3DPRIMITIVE | 
+	       BRW_3DPRIMITIVE_VERTEX_SEQUENTIAL |
+	       (_3DPRIM_RECTLIST << BRW_3DPRIMITIVE_TOPOLOGY_SHIFT) | 
+	       (0 << 9) |  /* CTG - indirect vertex count */
+	       4);
+      OUT_RING(3);  /* vertex count per instance */
+      OUT_RING(0); /* start vertex offset */
+      OUT_RING(1); /* single instance */
+      OUT_RING(0); /* start instance location */
+      OUT_RING(0); /* index buffer offset, ignored */
+      ADVANCE_LP_RING();
+    }
+#ifdef I830DEBUG
+    ErrorF("sync after 3dprimitive");
+    I830Sync(pScrn);
+#endif
+    /* we must be sure that the pipeline is flushed before next exa draw,
+       because that will be new state, binding state and instructions*/
+    {
+	BEGIN_LP_RING(4);
+   	OUT_RING(BRW_PIPE_CONTROL |
+	    BRW_PIPE_CONTROL_NOWRITE |
+	    BRW_PIPE_CONTROL_WC_FLUSH |
+	    BRW_PIPE_CONTROL_IS_FLUSH |
+	    (1 << 10) |  /* XXX texture cache flush for BLC/CTG */
+	    2);
+   	OUT_RING(0); /* Destination address */
+   	OUT_RING(0); /* Immediate data low DW */
+   	OUT_RING(0); /* Immediate data high DW */
+	ADVANCE_LP_RING();
+    }
+
+    /* Mark sync so we can wait for it before setting up the VB on the next
+     * rectangle.
+     */
+    i830MarkSync(pScrn);
+}
diff-tree 72ea0e514dcbebd009833c21f40e9bfb84074628 (from e62751db8b1a631c22ba0f77c932be4ab39ba741)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Jan 31 12:43:38 2007 -0800

    Remove custom accelerated rotation code now that it's all done through Render.

diff --git a/src/Makefile.am b/src/Makefile.am
index 02e8576..ba12635 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -74,7 +74,6 @@ i810_drv_la_SOURCES = \
          i830_video.c \
          i830_video.h \
 	 i830_reg.h \
-         i830_rotate.c \
 	 i830_randr.c \
 	 i830_sdvo.c \
 	 i830_sdvo.h \
diff --git a/src/i810_driver.c b/src/i810_driver.c
index 3d4c7d3..e7c8507 100644
--- a/src/i810_driver.c
+++ b/src/i810_driver.c
@@ -342,11 +342,8 @@ const char *I810driSymbols[] = {
 #endif /* I830_ONLY */
 
 const char *I810shadowSymbols[] = {
-    "shadowInit",
     "shadowSetup",
     "shadowAdd",
-    "shadowRemove",
-    "shadowUpdateRotatePacked",
     NULL
 };
 
diff --git a/src/i830.h b/src/i830.h
index 58e4ec3..4996cdd 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -297,11 +297,7 @@ typedef struct _I830Rec {
 #endif
    unsigned long LinearAlloc;
    XF86ModReqInfo shadowReq; /* to test for later libshadow */
-   I830MemRange RotatedMem;
-   I830MemRange RotatedMem2;
-   I830MemRange RotateStateMem; /* for G965 state buffer */
    Rotation rotation;
-   int InitialRotation;
    int displayWidth;
    void (*PointerMoved)(int, int, int);
    CreateScreenResourcesProcPtr    CreateScreenResources;
@@ -321,8 +317,6 @@ typedef struct _I830Rec {
    unsigned int front_tiled;
    unsigned int back_tiled;
    unsigned int depth_tiled;
-   unsigned int rotated_tiled;
-   unsigned int rotated2_tiled;
 #endif
 
    Bool NeedRingBufferLow;
@@ -550,8 +544,6 @@ extern void I830InitVideo(ScreenPtr pScr
 extern void i830_crtc_dpms_video(xf86CrtcPtr crtc, Bool on);
 #endif
 
-extern Bool I830AllocateRotatedBuffer(ScrnInfoPtr pScrn, const int flags);
-extern Bool I830AllocateRotated2Buffer(ScrnInfoPtr pScrn, const int flags);
 #ifdef XF86DRI
 extern Bool I830Allocate3DMemory(ScrnInfoPtr pScrn, const int flags);
 extern Bool I830AllocateBackBuffer(ScrnInfoPtr pScrn, const int flags);
@@ -606,7 +598,6 @@ extern void I830ReadAllRegisters(I830Ptr
 extern void I830ChangeFrontbuffer(ScrnInfoPtr pScrn,int buffer);
 extern Bool I830IsPrimary(ScrnInfoPtr pScrn);
 
-extern Bool I830Rotate(ScrnInfoPtr pScrn, DisplayModePtr mode);
 extern Bool I830FixOffset(ScrnInfoPtr pScrn, I830MemRange *mem);
 extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg,
 			char *name);
diff --git a/src/i830_dga.c b/src/i830_dga.c
index c312c6d..6d071ac 100644
--- a/src/i830_dga.c
+++ b/src/i830_dga.c
@@ -397,17 +397,11 @@ I830_CloseFramebuffer(ScrnInfoPtr pScrn)
    };
 
    if (I830IsPrimary(pScrn)) {
-      if (pI830->rotation != RR_Rotate_0)
-         pScrn->fbOffset = pI830->RotatedMem.Start;
-      else
-         pScrn->fbOffset = pI830->FrontBuffer.Start;
+     pScrn->fbOffset = pI830->FrontBuffer.Start;
    } else {
       I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
 
-      if (pI830->rotation != RR_Rotate_0)
-         pScrn->fbOffset = pI8301->RotatedMem2.Start;
-      else
-         pScrn->fbOffset = pI8301->FrontBuffer2.Start;
+      pScrn->fbOffset = pI8301->FrontBuffer2.Start;
    }
    I830SelectBuffer(pScrn, I830_SELECT_FRONT);
 
diff --git a/src/i830_dri.c b/src/i830_dri.c
index eeef289..70e7e49 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1446,22 +1446,13 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, 
    sarea->front_tiled = pI830->front_tiled;
    sarea->back_tiled = pI830->back_tiled;
    sarea->depth_tiled = pI830->depth_tiled;
-   sarea->rotated_tiled = pI830->rotated_tiled;
-#if 0
-   sarea->rotated2_tiled = pI830->rotated2_tiled;
-#endif
-
-   if (pI830->rotation == RR_Rotate_0) {
-      sarea->front_offset = pI830->FrontBuffer.Start;
-      /* Don't use FrontBuffer.Size here as it includes the pixmap cache area
-       * Instead, calculate the entire framebuffer.
-       */
-      sarea->front_size = pI830->displayWidth * pScrn->virtualY * pI830->cpp;
-   } else {
-      /* Need to deal with rotated2 once we have dual head DRI */
-      sarea->front_offset = pI830->RotatedMem.Start;
-      sarea->front_size = pI830->RotatedMem.Size;
-   }
+   sarea->rotated_tiled = FALSE;
+
+   sarea->front_offset = pI830->FrontBuffer.Start;
+   /* Don't use FrontBuffer.Size here as it includes the pixmap cache area
+    * Instead, calculate the entire framebuffer.
+    */
+   sarea->front_size = pI830->displayWidth * pScrn->virtualY * pI830->cpp;
 
    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
               "[drm] init sarea width,height = %d x %d (pitch %d)\n",
@@ -1480,32 +1471,12 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, 
    sarea->virtualX = pScrn->virtualX;
    sarea->virtualY = pScrn->virtualY;
 
-   switch (pI830->rotation) {
-      case RR_Rotate_0:
-         sarea->rotation = 0;
-         break;
-      case RR_Rotate_90:
-         sarea->rotation = 90;
-         break;
-      case RR_Rotate_180:
-         sarea->rotation = 180;
-         break;
-      case RR_Rotate_270:
-         sarea->rotation = 270;
-         break;
-      default:
-         sarea->rotation = 0;
-   }
-   if (pI830->rotation == RR_Rotate_0) {
-      sarea->rotated_offset = -1;
-      sarea->rotated_size = 0;
-   }
-   else {
-      sarea->rotated_offset = pI830->FrontBuffer.Start;
-      sarea->rotated_size = pI830->FrontBuffer.Size;
-   }
-
-   /* This is the original pitch */
+   /* The rotation is now handled entirely by the X Server, so just leave the
+    * DRI unaware.
+    */
+   sarea->rotation = 0;
+   sarea->rotated_offset = -1;
+   sarea->rotated_size = 0;
    sarea->rotated_pitch = pI830->displayWidth;
 
    success = I830DRIMapScreenRegions(pScrn, sarea);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index d6d0df0..7c365db 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -276,7 +276,6 @@ typedef enum {
    OPTION_MONITOR_LAYOUT,
    OPTION_CHECKDEVICES,
    OPTION_FIXEDPIPE,
-   OPTION_ROTATE,
    OPTION_LINEARALLOC,
    OPTION_INTELTEXPOOL,
    OPTION_INTELMMSIZE
@@ -297,7 +296,6 @@ static OptionInfoRec I830Options[] = {
    {OPTION_MONITOR_LAYOUT, "MonitorLayout", OPTV_ANYSTR,{0},	FALSE},
    {OPTION_CHECKDEVICES, "CheckDevices",OPTV_BOOLEAN,	{0},	FALSE},
    {OPTION_FIXEDPIPE,   "FixedPipe",    OPTV_ANYSTR, 	{0},	FALSE},
-   {OPTION_ROTATE,      "Rotate",       OPTV_ANYSTR,    {0},    FALSE},
    {OPTION_LINEARALLOC, "LinearAlloc",  OPTV_INTEGER,   {0},    FALSE},
    {OPTION_INTELTEXPOOL,"Legacy3D",     OPTV_BOOLEAN,	{0},	FALSE},
    {OPTION_INTELMMSIZE, "AperTexSize",  OPTV_INTEGER,	{0},	FALSE},
@@ -1368,17 +1366,9 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    RestoreHWState(pScrn);
 
    pScrn->displayWidth = (pScrn->virtualX + 63) & ~63;
-    
+
+   /* XXX This should go away, replaced by xf86Crtc.c support for it */
    pI830->rotation = RR_Rotate_0;
-   if ((s = xf86GetOptValString(pI830->Options, OPTION_ROTATE))) {
-      pI830->InitialRotation = 0;
-      if(!xf86NameCmp(s, "CW") || !xf86NameCmp(s, "270"))
-         pI830->InitialRotation = 270;
-      if(!xf86NameCmp(s, "CCW") || !xf86NameCmp(s, "90"))
-         pI830->InitialRotation = 90;
-      if(!xf86NameCmp(s, "180"))
-         pI830->InitialRotation = 180;
-   }
 
    /*
     * Let's setup the mobile systems to check the lid status
@@ -2495,19 +2485,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 
    pScrn->displayWidth = pI830->displayWidth;
 
-   if (I830IsPrimary(pScrn)) {
-      /* Rotated Buffer */
-      memset(&(pI830->RotatedMem), 0, sizeof(pI830->RotatedMem));
-      pI830->RotatedMem.Key = -1;
-      /* Rotated2 Buffer */
-      memset(&(pI830->RotatedMem2), 0, sizeof(pI830->RotatedMem2));
-      pI830->RotatedMem2.Key = -1;
-      if (IS_I965G(pI830)) {
-          memset(&(pI830->RotateStateMem), 0, sizeof(pI830->RotateStateMem));
-          pI830->RotateStateMem.Key = -1;
-      }
-   }
-
 #ifdef HAS_MTRR_SUPPORT
    {
       int fd;
@@ -2906,29 +2883,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    pI830->closing = FALSE;
    pI830->suspended = FALSE;
 
-   switch (pI830->InitialRotation) {
-      case 0:
-         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Rotating to 0 degrees\n");
-         pI830->rotation = RR_Rotate_0;
-         break;
-      case 90:
-         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Rotating to 90 degrees\n");
-         pI830->rotation = RR_Rotate_90;
-         break;
-      case 180:
-         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Rotating to 180 degrees\n");
-         pI830->rotation = RR_Rotate_180;
-         break;
-      case 270:
-         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Rotating to 270 degrees\n");
-         pI830->rotation = RR_Rotate_270;
-         break;
-      default:
-         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Bad rotation setting - defaulting to 0 degrees\n");
-         pI830->rotation = RR_Rotate_0;
-         break;
-   }
-
 #ifdef XF86DRI_MM
    if (pI830->directRenderingEnabled && (pI830->mmModeFlags & I830_KERNEL_MM)) {
       unsigned long aperEnd = ROUND_DOWN_TO(pI830->FbMapSize, GTT_PAGE_SIZE) 
@@ -3187,7 +3141,7 @@ I830EnterVT(int scrnIndex, int flags)
 
    pI830->currentMode = pScrn->currentMode;
 
-   /* Force invarient state when rotated to be emitted */
+   /* Force invarient 3D state to be emitted */
    *pI830->used3D = 1<<31;
 
    return TRUE;
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 24f0b29..6ceb05b 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -471,156 +471,6 @@ IsTileable(ScrnInfoPtr pScrn, int pitch)
    }
 }
 
-Bool
-I830AllocateRotatedBuffer(ScrnInfoPtr pScrn, int flags)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   unsigned long size, alloced;
-   Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
-   int verbosity = dryrun ? 4 : 1;
-   const char *s = dryrun ? "[dryrun] " : "";
-   int align;
-   Bool tileable;
-   int lines;
-   int height = (pI830->rotation & (RR_Rotate_0 | RR_Rotate_180)) ? pScrn->virtualY : pScrn->virtualX;
-
-   /* Rotated Buffer */
-   memset(&(pI830->RotatedMem), 0, sizeof(I830MemRange));
-   pI830->RotatedMem.Key = -1;
-   tileable = !(flags & ALLOC_NO_TILING) &&
-	      IsTileable(pScrn, pScrn->displayWidth * pI830->cpp);
-   if (tileable) {
-      /* Make the height a multiple of the tile height (16) */
-      lines = (height + 15) / 16 * 16;
-   } else {
-      lines = height;
-   }
-
-   size = ROUND_TO_PAGE(pScrn->displayWidth * lines * pI830->cpp);
-   /*
-    * Try to allocate on the best tile-friendly boundaries.
-    */
-   alloced = 0;
-   if (tileable) {
-      align = GetBestTileAlignment(size);
-      for (align = GetBestTileAlignment(size); align >= (IS_I9XX(pI830) ? MB(1) : KB(512)); align >>= 1) {
-	 alloced = I830AllocVidMem(pScrn, &(pI830->RotatedMem),
-				   &(pI830->StolenPool), size, align,
-				   flags | FROM_ANYWHERE | ALLOCATE_AT_TOP |
-				   ALIGN_BOTH_ENDS);
-	 if (alloced >= size)
-	    break;
-      }
-   }
-   if (alloced < size) {
-      /* Give up on trying to tile */
-      tileable = FALSE;
-      size = ROUND_TO_PAGE(pScrn->displayWidth * height * pI830->cpp);
-      align = GTT_PAGE_SIZE;
-      alloced = I830AllocVidMem(pScrn, &(pI830->RotatedMem),
-				&(pI830->StolenPool), size, align,
-				flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
-   }
-   if (alloced < size) {
-      if (!dryrun) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		    "Failed to allocate rotated buffer space.\n");
-      }
-      return FALSE;
-   }
-   xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-		  "%sAllocated %ld kB for the rotated buffer at 0x%lx.\n", s,
-		  alloced / 1024, pI830->RotatedMem.Start);
-
-#define BRW_LINEAR_EXTRA (32*1024)
-   if (IS_I965G(pI830)) {
-       memset(&(pI830->RotateStateMem), 0, sizeof(I830MemRange));
-       pI830->RotateStateMem.Key = -1;
-       size = ROUND_TO_PAGE(BRW_LINEAR_EXTRA);
-       align = GTT_PAGE_SIZE;
-       alloced = I830AllocVidMem(pScrn, &(pI830->RotateStateMem),
-				&(pI830->StolenPool), size, align,
-				flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
-       if (alloced < size) {
-          if (!dryrun) {
-	     xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		    "G965: Failed to allocate rotate state buffer space.\n");
-          }
-          return FALSE;
-       }
-       xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-		  "%sAllocated %ld kB for the G965 rotate state buffer at 0x%lx - 0x%lx.\n", s, 
-		alloced / 1024, pI830->RotateStateMem.Start, pI830->RotateStateMem.End);
-   }
-  
-   return TRUE;
-}
-
-Bool
-I830AllocateRotated2Buffer(ScrnInfoPtr pScrn, int flags)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   unsigned long size, alloced;
-   Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
-   int verbosity = dryrun ? 4 : 1;
-   const char *s = dryrun ? "[dryrun] " : "";
-   int align;
-   Bool tileable;
-   int lines;
-   I830EntPtr pI830Ent = pI830->entityPrivate;
-   I830Ptr pI8302 = I830PTR(pI830Ent->pScrn_2);
-   int height = (pI8302->rotation & (RR_Rotate_0 | RR_Rotate_180)) ? pI830Ent->pScrn_2->virtualY : pI830Ent->pScrn_2->virtualX;
-
-   /* Rotated Buffer */
-   memset(&(pI830->RotatedMem2), 0, sizeof(I830MemRange));
-   pI830->RotatedMem2.Key = -1;
-   tileable = !(flags & ALLOC_NO_TILING) &&
-	      IsTileable(pScrn, pI830Ent->pScrn_2->displayWidth * pI8302->cpp);
-   if (tileable) {
-      /* Make the height a multiple of the tile height (16) */
-      lines = (height + 15) / 16 * 16;
-   } else {
-      lines = height;
-   }
-
-   size = ROUND_TO_PAGE(pI830Ent->pScrn_2->displayWidth * lines * pI8302->cpp);
-   /*
-    * Try to allocate on the best tile-friendly boundaries.
-    */
-   alloced = 0;
-   if (tileable) {
-      align = GetBestTileAlignment(size);
-      for (align = GetBestTileAlignment(size); align >= (IS_I9XX(pI830) ? MB(1) : KB(512)); align >>= 1) {
-	 alloced = I830AllocVidMem(pScrn, &(pI830->RotatedMem2),
-				   &(pI830->StolenPool), size, align,
-				   flags | FROM_ANYWHERE | ALLOCATE_AT_TOP |
-				   ALIGN_BOTH_ENDS);
-	 if (alloced >= size)
-	    break;
-      }
-   }
-   if (alloced < size) {
-      /* Give up on trying to tile */
-      tileable = FALSE;
-      size = ROUND_TO_PAGE(pI830Ent->pScrn_2->displayWidth * height * pI8302->cpp);
-      align = GTT_PAGE_SIZE;
-      alloced = I830AllocVidMem(pScrn, &(pI830->RotatedMem2),
-				&(pI830->StolenPool), size, align,
-				flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
-   }
-   if (alloced < size) {
-      if (!dryrun) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		    "Failed to allocate rotated2 buffer space.\n");
-      }
-      return FALSE;
-   }
-   xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-		  "%sAllocated %ld kB for the rotated2 buffer at 0x%lx.\n", s,
-		  alloced / 1024, pI830->RotatedMem2.Start);
-   return TRUE;
-}
-
 static unsigned long
 GetFreeSpace(ScrnInfoPtr pScrn)
 {
@@ -1840,8 +1690,6 @@ I830SetupMemoryTiling(ScrnInfoPtr pScrn)
    pI830->front_tiled = FENCE_LINEAR;
    pI830->back_tiled = FENCE_LINEAR;
    pI830->depth_tiled = FENCE_LINEAR;
-   pI830->rotated_tiled = FENCE_LINEAR;
-   pI830->rotated2_tiled = FENCE_LINEAR;
 
    if (pI830->allowPageFlip) {
       if (pI830->allowPageFlip && pI830->FrontBuffer.Alignment >= KB(512)) {
@@ -1888,35 +1736,7 @@ I830SetupMemoryTiling(ScrnInfoPtr pScrn)
 	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		    "MakeTiles failed for the depth buffer.\n");
       }
-   }
-	
-/* XXX tiled rotate mem not ready on G965*/
- 
-  if(!IS_I965G(pI830)) {
-   if (pI830->RotatedMem.Alignment >= KB(512)) {
-      if (MakeTiles(pScrn, &(pI830->RotatedMem), FENCE_XMAJOR)) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		    "Activating tiled memory for the rotated buffer.\n");
-         pI830->rotated_tiled = FENCE_XMAJOR;
-      } else {
-	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		    "MakeTiles failed for the rotated buffer.\n");
-      }
-   }
-  }
-#if 0
-   if (pI830->RotatedMem2.Alignment >= KB(512)) {
-      if (MakeTiles(pScrn, &(pI830->RotatedMem2), FENCE_XMAJOR)) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		    "Activating tiled memory for the rotated2 buffer.\n");
-         pI830->rotated2_tiled = FENCE_XMAJOR;
-      } else {
-	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		    "MakeTiles failed for the rotated buffer.\n");
-      }
-   }
-#endif
-}
+   }}
 #endif /* XF86DRI */
 
 static Bool
@@ -1987,13 +1807,6 @@ I830BindAGPMemory(ScrnInfoPtr pScrn)
 	       return FALSE;
       }
 #endif
-      if (pI830->RotatedMem.Start)
-         if (!BindMemRange(pScrn, &(pI830->RotatedMem)))
-	    return FALSE;
-      if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2 &&
-	  pI830->RotatedMem2.Start)
-         if (!BindMemRange(pScrn, &(pI830->RotatedMem2)))
-	    return FALSE;
 #ifdef XF86DRI
       if (pI830->directRenderingEnabled) {
 	 if (!BindMemRange(pScrn, &(pI830->ContextMem)))
@@ -2088,13 +1901,6 @@ I830UnbindAGPMemory(ScrnInfoPtr pScrn)
    	       return FALSE;
       }
 #endif
-      if (pI830->RotatedMem.Start)
-         if (!UnbindMemRange(pScrn, &(pI830->RotatedMem)))
-	    return FALSE;
-      if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2 &&
-	  pI830->RotatedMem2.Start)
-         if (!UnbindMemRange(pScrn, &(pI830->RotatedMem2)))
-	    return FALSE;
 #ifdef XF86DRI
       if (pI830->directRenderingEnabled) {
 	 if (!UnbindMemRange(pScrn, &(pI830->ContextMem)))
diff --git a/src/i830_rotate.c b/src/i830_rotate.c
deleted file mode 100644
index efa76ed..0000000
--- a/src/i830_rotate.c
+++ /dev/null
@@ -1,1908 +0,0 @@
-/* -*- c-basic-offset: 3 -*- */
-/**************************************************************************
-
-Copyright 2005 Tungsten Graphics, Inc., Cedar Park, Texas.
-
-All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sub license, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice (including the
-next paragraph) shall be included in all copies or substantial portions
-of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
-IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR
-ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-**************************************************************************/
-
-/*
- * Reformatted with GNU indent (2.2.8), using the following options:
- *
- *    -bad -bap -c41 -cd0 -ncdb -ci6 -cli0 -cp0 -ncs -d0 -di3 -i3 -ip3 -l78
- *    -lp -npcs -psl -sob -ss -br -ce -sc -hnl
- *
- * This provides a good match with the original i810 code and preferred
- * XFree86 formatting conventions.
- *
- * When editing this driver, please follow the existing formatting, and edit
- * with <TAB> characters expanded at 8-column intervals.
- */
-
-/*
- * Authors:
- *   Alan Hourihane <alanh at tungstengraphics.com>
- *   Brian Paul <brian.paul at tungstengraphics.com>
- *   Keith Whitwell <keith at tungstengraphics.com>
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-
-#include "xf86.h"
-#include "xf86_OSproc.h"
-#include "servermd.h"
-#include "shadow.h"
-
-#include "i830.h"
-#include "i915_reg.h"
-#include "i915_3d.h"
-#include "brw_defines.h"
-#include "brw_structs.h"
-
-#ifdef XF86DRI
-#include "dri.h"
-#endif
-
-static void *
-I830WindowLinear (ScreenPtr pScreen,
-		 CARD32    row,
-		 CARD32    offset,
-		 int	   mode,
-		 CARD32    *size,
-		 void	   *closure)
-{
-   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-   I830Ptr pI830 = I830PTR(pScrn);
-   CARD8 *ptr;
-
-   *size = (pScrn->bitsPerPixel * pI830->displayWidth >> 3);
-   if (I830IsPrimary(pScrn))
-      ptr = (CARD8 *) (pI830->FbBase + pI830->FrontBuffer.Start) + row * (*size) + offset;
-   else {
-      I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
-      ptr = (CARD8 *) (pI830->FbBase + pI8301->FrontBuffer2.Start) + row * (*size) + offset;
-   }
-   return (void *)ptr;
-}
-
-struct matrix23
-{
-	int m00, m01, m02;
-	int m10, m11, m12;
-};
-
-static void
-matrix23Set(struct matrix23 *m,
-            int m00, int m01, int m02,
-            int m10, int m11, int m12)
-{
-   m->m00 = m00;   m->m01 = m01;   m->m02 = m02;
-   m->m10 = m10;   m->m11 = m11;   m->m12 = m12;
-}
-
-
-/*
- * Transform (x,y) coordinate by the given matrix.
- */
-static void
-matrix23TransformCoordf(const struct matrix23 *m, float *x, float *y)
-{
-   const float x0 = *x;
-   const float y0 = *y;
-
-   *x = m->m00 * x0 + m->m01 * y0 + m->m02;
-   *y = m->m10 * x0 + m->m11 * y0 + m->m12;
-}
-
-/*
- * Make rotation matrix for width X height screen.
- */
-static void
-matrix23Rotate(struct matrix23 *m, int width, int height, int angle)
-{
-   switch (angle) {
-   case 0:
-      matrix23Set(m, 1, 0, 0, 0, 1, 0);
-      break;
-   case 90:
-      matrix23Set(m, 0, 1, 0,  -1, 0, width);
-      break;
-   case 180:
-      matrix23Set(m, -1, 0, width,  0, -1, height);
-      break;
-   case 270:
-      matrix23Set(m, 0, -1, height,  1, 0, 0);
-      break;
-   default:
-      break;
-   }
-}
-
-/* Doesn't matter on the order for our purposes */
-typedef struct {
-   unsigned char red, green, blue, alpha;
-} intel_color_t;
-
-/* Vertex format */
-typedef union {
-   struct {
-      float x, y, z, w;
-      intel_color_t color;
-      intel_color_t specular;
-      float u0, v0;
-      float u1, v1;
-      float u2, v2;
-      float u3, v3;
-   } v;
-   float f[24];
-   unsigned int  ui[24];
-   unsigned char ub4[24][4];
-} intelVertex, *intelVertexPtr;
-
-static void draw_poly(CARD32 *vb,
-                      float verts[][2],
-                      float texcoords[][2])
-{
-   int vertex_size = 8;
-   intelVertex tmp;
-   int i, k;
-
-   /* initial constant vertex fields */
-   tmp.v.z = 1.0;
-   tmp.v.w = 1.0; 
-   tmp.v.color.red = 255;
-   tmp.v.color.green = 255;
-   tmp.v.color.blue = 255;
-   tmp.v.color.alpha = 255;
-   tmp.v.specular.red = 0;
-   tmp.v.specular.green = 0;
-   tmp.v.specular.blue = 0;
-   tmp.v.specular.alpha = 0;
-
-   for (k = 0; k < 4; k++) {
-      tmp.v.x = verts[k][0];
-      tmp.v.y = verts[k][1];
-      tmp.v.u0 = texcoords[k][0];
-      tmp.v.v0 = texcoords[k][1];
-
-      for (i = 0 ; i < vertex_size ; i++)
-         vb[i] = tmp.ui[i];
-
-      vb += vertex_size;
-   }
-}
-
-
-/* Our PS kernel uses less than 32 GRF registers (about 20) */
-#define PS_KERNEL_NUM_GRF   32
-#define PS_MAX_THREADS	   32
-
-#define BRW_GRF_BLOCKS(nreg)	((nreg + 15) / 16 - 1)
-
-static const CARD32 ps_kernel_static0[][4] = {
-#include "rotation_wm_prog0.h"
-};
-
-static const CARD32 ps_kernel_static90[][4] = {
-#include "rotation_wm_prog90.h"
-};
-
-#define ALIGN(i,m)    (((i) + (m) - 1) & ~((m) - 1))
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define BRW_LINEAR_EXTRA (32*1024)
-#define WM_BINDING_TABLE_ENTRIES    2
-
-static const CARD32 sip_kernel_static[][4] = {
-/*    wait (1) a0<1>UW a145<0,1,0>UW { align1 +  } */
-    { 0x00000030, 0x20000108, 0x00001220, 0x00000000 },
-/*    nop (4) g0<1>UD { align1 +  } */
-    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
-/*    nop (4) g0<1>UD { align1 +  } */
-    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
-/*    nop (4) g0<1>UD { align1 +  } */
-    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
-/*    nop (4) g0<1>UD { align1 +  } */
-    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
-/*    nop (4) g0<1>UD { align1 +  } */
-    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
-/*    nop (4) g0<1>UD { align1 +  } */
-    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
-/*    nop (4) g0<1>UD { align1 +  } */
-    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
-/*    nop (4) g0<1>UD { align1 +  } */
-    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
-/*    nop (4) g0<1>UD { align1 +  } */
-    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
-};
-  
-#define SF_KERNEL_NUM_GRF  16
-#define SF_MAX_THREADS	   1
-
-static const CARD32 sf_kernel_static0[][4] = {
-#include "rotation_sf_prog0.h"
-};
-
-
-static const CARD32 sf_kernel_static90[][4] = {
-#include "rotation_sf_prog90.h"
-};
-
-static void
-I965UpdateRotate (ScreenPtr      pScreen,
-                 shadowBufPtr   pBuf)
-{
-   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-   I830Ptr pI830 = I830PTR(pScrn);
-   ScrnInfoPtr pScrn1 = pScrn;
-   I830Ptr pI8301 = NULL;
-   RegionPtr	damage = shadowDamage(pBuf);
-   int		nbox = REGION_NUM_RECTS (damage);
-   BoxPtr	pbox = REGION_RECTS (damage);
-   int		box_x1, box_x2, box_y1, box_y2;
-   float verts[4][2];
-   struct matrix23 rotMatrix;
-   Bool updateInvarient = FALSE;
-#ifdef XF86DRI
-   drmI830Sarea *sarea = NULL;
-   drm_context_t myContext = 0;
-#endif
-   Bool didLock = FALSE;
-
-/* Gen4 states */
-   int urb_vs_start, urb_vs_size;
-   int urb_gs_start, urb_gs_size;
-   int urb_clip_start, urb_clip_size;
-   int urb_sf_start, urb_sf_size;
-   int urb_cs_start, urb_cs_size;
-   struct brw_surface_state *dest_surf_state;
-   struct brw_surface_state *src_surf_state;
-   struct brw_sampler_state *src_sampler_state;
-   struct brw_vs_unit_state *vs_state;
-   struct brw_sf_unit_state *sf_state;
-   struct brw_wm_unit_state *wm_state;
-   struct brw_cc_unit_state *cc_state;
-   struct brw_cc_viewport *cc_viewport;
-   struct brw_instruction *sf_kernel;
-   struct brw_instruction *ps_kernel;
-   struct brw_instruction *sip_kernel;
-   float *vb;  
-   BOOL first_output = TRUE;
-   CARD32 *binding_table;
-   int dest_surf_offset, src_surf_offset, src_sampler_offset, vs_offset;
-   int sf_offset, wm_offset, cc_offset, vb_offset, cc_viewport_offset;
-   int wm_scratch_offset;
-   int sf_kernel_offset, ps_kernel_offset, sip_kernel_offset;
-   int binding_table_offset;
-   int next_offset, total_state_size;
-   int vb_size = (4 * 4) * 4; /* 4 DWORDS per vertex */
-   char *state_base;
-   int state_base_offset;
-
-   DPRINTF(PFX, "I965UpdateRotate: from (%d x %d) -> (%d x %d)\n",	
-		pScrn->virtualX, pScrn->virtualY, pScreen->width, pScreen->height);
-
-   if (I830IsPrimary(pScrn)) {
-      pI8301 = pI830;
-   } else {
-      pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
-      pScrn1 = pI830->entityPrivate->pScrn_1;
-   }
-
-   switch (pI830->rotation) {
-      case RR_Rotate_90:
-         matrix23Rotate(&rotMatrix,
-                     pScreen->width, pScreen->height,
-                     90);
-	 break;
-      case RR_Rotate_180:
-         matrix23Rotate(&rotMatrix,
-                     pScreen->width, pScreen->height,
-                     180);
-	 break;
-      case RR_Rotate_270:
-         matrix23Rotate(&rotMatrix,
-                     pScreen->width, pScreen->height,
-                     270);
-	 break;
-      default:
-	 break;
-   }
-
-#ifdef XF86DRI
-   if (pI8301->directRenderingEnabled) {
-      sarea = DRIGetSAREAPrivate(pScrn1->pScreen);
-      myContext = DRIGetContext(pScrn1->pScreen);
-      didLock = I830DRILock(pScrn1);
-   }
-#endif
-
-   if (pScrn->scrnIndex != *pI830->used3D) 
-      updateInvarient = TRUE;
- 
-#ifdef XF86DRI
-   if (sarea && sarea->ctxOwner != myContext)
-      updateInvarient = TRUE;
-#endif
-
-   /*XXX we'll always update state */
-   *pI830->used3D = pScrn->scrnIndex;
-#ifdef XF86DRI
-   if (sarea)
-      sarea->ctxOwner = myContext;
-#endif
-
-   /* this starts initialize 3D engine for rotation mapping*/
-   next_offset = 0;
-
-   /* Set up our layout of state in framebuffer.  First the general state: */
-   vs_offset = ALIGN(next_offset, 64);
-   next_offset = vs_offset + sizeof(*vs_state);
-   sf_offset = ALIGN(next_offset, 32);
-   next_offset = sf_offset + sizeof(*sf_state);
-   wm_offset = ALIGN(next_offset, 32);
-   next_offset = wm_offset + sizeof(*wm_state);
-   wm_scratch_offset = ALIGN(next_offset, 1024);
-   next_offset = wm_scratch_offset + 1024 * PS_MAX_THREADS;
-   cc_offset = ALIGN(next_offset, 32);
-   next_offset = cc_offset + sizeof(*cc_state);
-
-   sf_kernel_offset = ALIGN(next_offset, 64);
-      
-   switch (pI830->rotation) {
-       case RR_Rotate_90:
-       case RR_Rotate_270:
-      	    next_offset = sf_kernel_offset + sizeof (sf_kernel_static90);
-      	    ps_kernel_offset = ALIGN(next_offset, 64);
-      	    next_offset = ps_kernel_offset + sizeof (ps_kernel_static90);
-	    break;
-       case RR_Rotate_180:
-       default:
-      	    next_offset = sf_kernel_offset + sizeof (sf_kernel_static0);
-      	    ps_kernel_offset = ALIGN(next_offset, 64);
-      	    next_offset = ps_kernel_offset + sizeof (ps_kernel_static0);
-	    break;
-   }
-
-   sip_kernel_offset = ALIGN(next_offset, 64);
-   next_offset = sip_kernel_offset + sizeof (sip_kernel_static);
-   cc_viewport_offset = ALIGN(next_offset, 32);
-   next_offset = cc_viewport_offset + sizeof(*cc_viewport);
-
-   src_sampler_offset = ALIGN(next_offset, 32);
-   next_offset = src_sampler_offset + sizeof(*src_sampler_state);
-
-   /* Align VB to native size of elements, for safety */
-   vb_offset = ALIGN(next_offset, 8);
-   next_offset = vb_offset + vb_size;
-
-   dest_surf_offset = ALIGN(next_offset, 32);
-   next_offset = dest_surf_offset + sizeof(*dest_surf_state);
-   src_surf_offset = ALIGN(next_offset, 32);
-   next_offset = src_surf_offset + sizeof(*src_surf_state);
-   binding_table_offset = ALIGN(next_offset, 32);
-   next_offset = binding_table_offset + (WM_BINDING_TABLE_ENTRIES * 4);
-
-   total_state_size = next_offset;
-   assert (total_state_size < BRW_LINEAR_EXTRA);
-
-   state_base_offset = pI830->RotateStateMem.Start;
-   state_base_offset = ALIGN(state_base_offset, 64);
-   state_base = (char *)(pI830->FbBase + state_base_offset);
-   DPRINTF(PFX, "rotate state buffer start 0x%x, addr 0x%x, base 0x%x\n",
-			pI830->RotateStateMem.Start, state_base, pI830->FbBase);
-
-   vs_state = (void *)(state_base + vs_offset);
-   sf_state = (void *)(state_base + sf_offset);
-   wm_state = (void *)(state_base + wm_offset);
-   cc_state = (void *)(state_base + cc_offset);
-   sf_kernel = (void *)(state_base + sf_kernel_offset);
-   ps_kernel = (void *)(state_base + ps_kernel_offset);
-   sip_kernel = (void *)(state_base + sip_kernel_offset);
-   
-   cc_viewport = (void *)(state_base + cc_viewport_offset);
-   dest_surf_state = (void *)(state_base + dest_surf_offset);
-   src_surf_state = (void *)(state_base + src_surf_offset);
-   src_sampler_state = (void *)(state_base + src_sampler_offset);
-   binding_table = (void *)(state_base + binding_table_offset);
-   vb = (void *)(state_base + vb_offset);
-
-   /* For 3D, the VS must have 8, 12, 16, 24, or 32 VUEs allocated to it.
-    * A VUE consists of a 256-bit vertex header followed by the vertex data,
-    * which in our case is 4 floats (128 bits), thus a single 512-bit URB
-    * entry.
-    */
-#define URB_VS_ENTRIES	      8
-#define URB_VS_ENTRY_SIZE     1
-   
-#define URB_GS_ENTRIES	      0
-#define URB_GS_ENTRY_SIZE     0
-   
-#define URB_CLIP_ENTRIES      0
-#define URB_CLIP_ENTRY_SIZE   0
-   
-   /* The SF kernel we use outputs only 4 256-bit registers, leading to an
-    * entry size of 2 512-bit URBs.  We don't need to have many entries to
-    * output as we're generally working on large rectangles and don't care
-    * about having WM threads running on different rectangles simultaneously.
-    */
-#define URB_SF_ENTRIES	      1
-#define URB_SF_ENTRY_SIZE     2
-
-#define URB_CS_ENTRIES	      0
-#define URB_CS_ENTRY_SIZE     0
-   
-   urb_vs_start = 0;
-   urb_vs_size = URB_VS_ENTRIES * URB_VS_ENTRY_SIZE;
-   urb_gs_start = urb_vs_start + urb_vs_size;
-   urb_gs_size = URB_GS_ENTRIES * URB_GS_ENTRY_SIZE;
-   urb_clip_start = urb_gs_start + urb_gs_size;
-   urb_clip_size = URB_CLIP_ENTRIES * URB_CLIP_ENTRY_SIZE;
-   urb_sf_start = urb_clip_start + urb_clip_size;
-   urb_sf_size = URB_SF_ENTRIES * URB_SF_ENTRY_SIZE;
-   urb_cs_start = urb_sf_start + urb_sf_size;
-   urb_cs_size = URB_CS_ENTRIES * URB_CS_ENTRY_SIZE;
-
-   memset (cc_viewport, 0, sizeof (*cc_viewport));
-   cc_viewport->min_depth = -1.e35;
-   cc_viewport->max_depth = 1.e35;
-
-   memset(cc_state, 0, sizeof(*cc_state));
-   cc_state->cc0.stencil_enable = 0;   /* disable stencil */
-   cc_state->cc2.depth_test = 0;       /* disable depth test */
-   cc_state->cc2.logicop_enable = 1;   /* enable logic op */
-   cc_state->cc3.ia_blend_enable = 1;  /* blend alpha just like colors */
-   cc_state->cc3.blend_enable = 0;     /* disable color blend */
-   cc_state->cc3.alpha_test = 0;       /* disable alpha test */
-   cc_state->cc4.cc_viewport_state_offset = (state_base_offset + cc_viewport_offset) >> 5;
-   cc_state->cc5.dither_enable = 0;    /* disable dither */
-   cc_state->cc5.logicop_func = 0xc;   /* COPY S*/
-   cc_state->cc5.statistics_enable = 1;
-   cc_state->cc5.ia_blend_function = BRW_BLENDFUNCTION_ADD;
-   cc_state->cc5.ia_src_blend_factor = BRW_BLENDFACTOR_ONE;
-   cc_state->cc5.ia_dest_blend_factor = BRW_BLENDFACTOR_ZERO;
-
-   /* Upload system kernel */
-   memcpy (sip_kernel, sip_kernel_static, sizeof (sip_kernel_static));
-   
-   memset(dest_surf_state, 0, sizeof(*dest_surf_state));
-   dest_surf_state->ss0.surface_type = BRW_SURFACE_2D;
-   dest_surf_state->ss0.data_return_format = BRW_SURFACERETURNFORMAT_FLOAT32;
-   if (pI8301->cpp == 2)
-      dest_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B5G6R5_UNORM;
-   else
-      dest_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
-   dest_surf_state->ss0.writedisable_alpha = 0;
-   dest_surf_state->ss0.writedisable_red = 0;
-   dest_surf_state->ss0.writedisable_green = 0;
-   dest_surf_state->ss0.writedisable_blue = 0;
-   dest_surf_state->ss0.color_blend = 0;
-   dest_surf_state->ss0.vert_line_stride = 0;
-   dest_surf_state->ss0.vert_line_stride_ofs = 0;
-   dest_surf_state->ss0.mipmap_layout_mode = 0;
-   dest_surf_state->ss0.render_cache_read_mode = 0;
-   
-   if (I830IsPrimary(pScrn))
-      dest_surf_state->ss1.base_addr = pI830->FrontBuffer.Start;
-   else 
-      dest_surf_state->ss1.base_addr = pI8301->FrontBuffer2.Start;
-   dest_surf_state->ss2.width = pScrn->virtualX - 1;
-   dest_surf_state->ss2.height = pScrn->virtualY - 1; 
-   dest_surf_state->ss2.mip_count = 0;
-   dest_surf_state->ss2.render_target_rotation = 0; /*XXX how to use? */
-   dest_surf_state->ss3.pitch = (pI830->displayWidth * pI830->cpp) - 1;
-   if (pI830->front_tiled) {
-      dest_surf_state->ss3.tiled_surface = 1;
-      dest_surf_state->ss3.tile_walk = 0; /* X major */
-   }
-
-   memset(src_surf_state, 0, sizeof(*src_surf_state));
-   src_surf_state->ss0.surface_type = BRW_SURFACE_2D;
-/* src_surf_state->ss0.data_return_format = BRW_SURFACERETURNFORMAT_FLOAT32;*/
-   if (pI8301->cpp == 2) 
-      src_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B5G6R5_UNORM;
-   else 
-      src_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
-   src_surf_state->ss0.writedisable_alpha = 0;
-   src_surf_state->ss0.writedisable_red = 0;
-   src_surf_state->ss0.writedisable_green = 0;
-   src_surf_state->ss0.writedisable_blue = 0;
-   src_surf_state->ss0.color_blend = 0;
-   src_surf_state->ss0.vert_line_stride = 0;
-   src_surf_state->ss0.vert_line_stride_ofs = 0;
-   src_surf_state->ss0.mipmap_layout_mode = 0;
-   src_surf_state->ss0.render_cache_read_mode = 0;
-  
-   if (I830IsPrimary(pScrn)) 
-      src_surf_state->ss1.base_addr = pI830->RotatedMem.Start;
-   else 
-      src_surf_state->ss1.base_addr = pI8301->RotatedMem2.Start;
-   src_surf_state->ss2.width = pScreen->width - 1;
-   src_surf_state->ss2.height = pScreen->height - 1;
-   src_surf_state->ss2.mip_count = 0;
-   src_surf_state->ss2.render_target_rotation = 0;
-   src_surf_state->ss3.pitch = (pScrn->displayWidth * pI830->cpp) - 1;
-   if (pI830->rotated_tiled) {
-      src_surf_state->ss3.tiled_surface = 1;
-      src_surf_state->ss3.tile_walk = 0; /* X major */
-   }
-
-   binding_table[0] = state_base_offset + dest_surf_offset;
-   binding_table[1] = state_base_offset + src_surf_offset;
-
-   memset(src_sampler_state, 0, sizeof(*src_sampler_state));
-   src_sampler_state->ss0.min_filter = BRW_MAPFILTER_LINEAR;
-   src_sampler_state->ss0.mag_filter = BRW_MAPFILTER_LINEAR;
-   src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
-   src_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
-   src_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
-
-   /* Set up the vertex shader to be disabled (passthrough) */
-   memset(vs_state, 0, sizeof(*vs_state));
-   vs_state->thread4.nr_urb_entries = URB_VS_ENTRIES;
-   vs_state->thread4.urb_entry_allocation_size = URB_VS_ENTRY_SIZE - 1;
-   vs_state->vs6.vs_enable = 0;
-   vs_state->vs6.vert_cache_disable = 1;
-
-   /* Set up the SF kernel to do coord interp: for each attribute,
-    * calculate dA/dx and dA/dy.  Hand these interpolation coefficients
-    * back to SF which then hands pixels off to WM.
-    */
-
-   switch (pI830->rotation) {
-      case RR_Rotate_90:
-      case RR_Rotate_270:
-           memcpy (sf_kernel, sf_kernel_static90, sizeof (sf_kernel_static90));
-           memcpy (ps_kernel, ps_kernel_static90, sizeof (ps_kernel_static90));
-	   break;
-      case RR_Rotate_180:
-      default:
-           memcpy (sf_kernel, sf_kernel_static0, sizeof (sf_kernel_static0));
-           memcpy (ps_kernel, ps_kernel_static0, sizeof (ps_kernel_static0));
-	   break;
-   }
-
-   memset(sf_state, 0, sizeof(*sf_state));
-   sf_state->thread0.kernel_start_pointer = 
-	          (state_base_offset + sf_kernel_offset) >> 6;
-   sf_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(SF_KERNEL_NUM_GRF);
-   sf_state->sf1.single_program_flow = 1; /* XXX */
-   sf_state->sf1.binding_table_entry_count = 0;
-   sf_state->sf1.thread_priority = 0;
-   sf_state->sf1.floating_point_mode = 0; 
-   sf_state->sf1.illegal_op_exception_enable = 1;
-   sf_state->sf1.mask_stack_exception_enable = 1;
-   sf_state->sf1.sw_exception_enable = 1;
-   sf_state->thread2.per_thread_scratch_space = 0;
-   sf_state->thread2.scratch_space_base_pointer = 0; /* not used in our kernel */
-   sf_state->thread3.const_urb_entry_read_length = 0; /* no const URBs */
-   sf_state->thread3.const_urb_entry_read_offset = 0; /* no const URBs */
-   sf_state->thread3.urb_entry_read_length = 1; /* 1 URB per vertex */
-   sf_state->thread3.urb_entry_read_offset = 0;
-   sf_state->thread3.dispatch_grf_start_reg = 3;
-   sf_state->thread4.max_threads = SF_MAX_THREADS - 1;
-   sf_state->thread4.urb_entry_allocation_size = URB_SF_ENTRY_SIZE - 1;
-   sf_state->thread4.nr_urb_entries = URB_SF_ENTRIES;
-   sf_state->thread4.stats_enable = 1;
-   sf_state->sf5.viewport_transform = FALSE; /* skip viewport */
-   sf_state->sf6.cull_mode = BRW_CULLMODE_NONE;
-   sf_state->sf6.scissor = 0;
-   sf_state->sf7.trifan_pv = 2;
-   sf_state->sf6.dest_org_vbias = 0x8;
-   sf_state->sf6.dest_org_hbias = 0x8;
-
-   memset (wm_state, 0, sizeof (*wm_state));
-   wm_state->thread0.kernel_start_pointer = 
-	       (state_base_offset + ps_kernel_offset) >> 6;
-   wm_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(PS_KERNEL_NUM_GRF);
-   wm_state->thread1.single_program_flow = 1; /* XXX */
-   wm_state->thread1.binding_table_entry_count = 2;
-   /* Though we never use the scratch space in our WM kernel, it has to be
-    * set, and the minimum allocation is 1024 bytes.
-    */
-   wm_state->thread2.scratch_space_base_pointer = (state_base_offset +
-						   wm_scratch_offset) >> 10;
-   wm_state->thread2.per_thread_scratch_space = 0; /* 1024 bytes */
-   wm_state->thread3.dispatch_grf_start_reg = 3;
-   wm_state->thread3.const_urb_entry_read_length = 0;
-   wm_state->thread3.const_urb_entry_read_offset = 0;
-   wm_state->thread3.urb_entry_read_length = 1;
-   wm_state->thread3.urb_entry_read_offset = 0;
-   wm_state->wm4.stats_enable = 1;
-   wm_state->wm4.sampler_state_pointer = (state_base_offset + src_sampler_offset) >> 5;
-   wm_state->wm4.sampler_count = 1; /* 1-4 samplers used */
-   wm_state->wm5.max_threads = PS_MAX_THREADS - 1;
-   wm_state->wm5.thread_dispatch_enable = 1;
-   wm_state->wm5.enable_16_pix = 1;
-   wm_state->wm5.enable_8_pix = 0;
-   wm_state->wm5.early_depth_test = 1;
-
-   
-   {
-         BEGIN_LP_RING(2);
-         OUT_RING(MI_FLUSH | 
-	          MI_STATE_INSTRUCTION_CACHE_FLUSH |
-	          BRW_MI_GLOBAL_SNAPSHOT_RESET);
-         OUT_RING(MI_NOOP);
-         ADVANCE_LP_RING();
-    }
-
-    {
-         BEGIN_LP_RING(12);
-         OUT_RING(BRW_PIPELINE_SELECT | PIPELINE_SELECT_3D);
-
-   /* Mesa does this. Who knows... */
-         OUT_RING(BRW_CS_URB_STATE | 0);
-         OUT_RING((0 << 4) |	/* URB Entry Allocation Size */
-	          (0 << 0));	/* Number of URB Entries */
-   
-   /* Zero out the two base address registers so all offsets are absolute */
-         OUT_RING(BRW_STATE_BASE_ADDRESS | 4);
-         OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* Generate state base address */
-         OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* Surface state base address */
-         OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* media base addr, don't care */
-         OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY);  /* general state max addr, disabled */
-         OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY);  /* media object state max addr, disabled */
-
-   /* Set system instruction pointer */
-         OUT_RING(BRW_STATE_SIP | 0);
-         OUT_RING(state_base_offset + sip_kernel_offset); /* system instruction pointer */
-      
-         OUT_RING(MI_NOOP);
-         ADVANCE_LP_RING(); 
-    }
-   
-
-    { 
-         BEGIN_LP_RING(36);
-   /* Enable VF statistics */
-         OUT_RING(BRW_3DSTATE_VF_STATISTICS | 1);
-   
-   /* Pipe control */
-         OUT_RING(BRW_PIPE_CONTROL |
-	          BRW_PIPE_CONTROL_NOWRITE |
-	          BRW_PIPE_CONTROL_IS_FLUSH |
-	          2);
-         OUT_RING(0);			       /* Destination address */
-         OUT_RING(0);			       /* Immediate data low DW */
-         OUT_RING(0);			       /* Immediate data high DW */
-
-   /* Binding table pointers */
-         OUT_RING(BRW_3DSTATE_BINDING_TABLE_POINTERS | 4);
-         OUT_RING(0); /* vs */
-         OUT_RING(0); /* gs */
-         OUT_RING(0); /* clip */
-         OUT_RING(0); /* sf */
-   /* Only the PS uses the binding table */
-         OUT_RING(state_base_offset + binding_table_offset); /* ps */
-   
-   /* XXX: Blend constant color (magenta is fun) */
-         //OUT_RING(BRW_3DSTATE_CONSTANT_COLOR | 3);
-         //OUT_RING(float_to_uint (1.0));
-         //OUT_RING(float_to_uint (0.0));
-         //OUT_RING(float_to_uint (1.0));
-         //OUT_RING(float_to_uint (1.0));
-   
-   /* The drawing rectangle clipping is always on.  Set it to values that
-    * shouldn't do any clipping.
-    */
-         OUT_RING(BRW_3DSTATE_DRAWING_RECTANGLE | 2);	/* XXX 3 for BLC or CTG */
-         OUT_RING(0x00000000);	/* ymin, xmin */
-         OUT_RING((pScrn->virtualX - 1) |
-	          (pScrn->virtualY - 1) << 16); /* ymax, xmax */
-         OUT_RING(0x00000000);	/* yorigin, xorigin */
-
-   /* skip the depth buffer */
-   /* skip the polygon stipple */
-   /* skip the polygon stipple offset */
-   /* skip the line stipple */
-   
-   /* Set the pointers to the 3d pipeline state */
-         OUT_RING(BRW_3DSTATE_PIPELINED_POINTERS | 5);
-         OUT_RING(state_base_offset + vs_offset);  /* 32 byte aligned */
-         OUT_RING(BRW_GS_DISABLE);		     /* disable GS, resulting in passthrough */
-         OUT_RING(BRW_CLIP_DISABLE);		     /* disable CLIP, resulting in passthrough */
-         OUT_RING(state_base_offset + sf_offset);  /* 32 byte aligned */
-         OUT_RING(state_base_offset + wm_offset);  /* 32 byte aligned */
-         OUT_RING(state_base_offset + cc_offset);  /* 64 byte aligned */
-
-   /* URB fence */
-         OUT_RING(BRW_URB_FENCE |
-	          UF0_CS_REALLOC |
-	          UF0_SF_REALLOC |
-	          UF0_CLIP_REALLOC |
-	          UF0_GS_REALLOC |
-	          UF0_VS_REALLOC |
-	    	  1);
-         OUT_RING(((urb_clip_start + urb_clip_size) << UF1_CLIP_FENCE_SHIFT) |
-	          ((urb_gs_start + urb_gs_size) << UF1_GS_FENCE_SHIFT) |
-	          ((urb_vs_start + urb_vs_size) << UF1_VS_FENCE_SHIFT));
-         OUT_RING(((urb_cs_start + urb_cs_size) << UF2_CS_FENCE_SHIFT) |
-	          ((urb_sf_start + urb_sf_size) << UF2_SF_FENCE_SHIFT));
-
-   /* Constant buffer state */
-         OUT_RING(BRW_CS_URB_STATE | 0);
-         OUT_RING(((URB_CS_ENTRY_SIZE - 1) << 4) | /* URB Entry Allocation Size */
-	          (URB_CS_ENTRIES << 0));	     /* Number of URB Entries */
-   
-   /* Set up the pointer to our vertex buffer */
-         OUT_RING(BRW_3DSTATE_VERTEX_BUFFERS | 2);
-         OUT_RING((0 << VB0_BUFFER_INDEX_SHIFT) |
-	          VB0_VERTEXDATA |
-	          ((4 * 4) << VB0_BUFFER_PITCH_SHIFT)); /* four 32-bit floats per vertex */
-         OUT_RING(state_base_offset + vb_offset);
-         OUT_RING(3); /* four corners to our rectangle */
-
-   /* Set up our vertex elements, sourced from the single vertex buffer. */
-         OUT_RING(BRW_3DSTATE_VERTEX_ELEMENTS | 3);
-   /* offset 0: X,Y -> {X, Y, 1.0, 1.0} */
-         OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
-	          VE0_VALID |
-	          (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
-	          (0 << VE0_OFFSET_SHIFT));
-         OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
-	          (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
-	          (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
-	          (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
-	          (0 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
-   /* offset 8: S0, T0 -> {S0, T0, 1.0, 1.0} */
-         OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
-	          VE0_VALID |
-	          (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
-	          (8 << VE0_OFFSET_SHIFT));
-         OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
-	          (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
-	          (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
-	          (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
-	          (4 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
-
-         //OUT_RING(MI_NOOP);			/* pad to quadword */
-         ADVANCE_LP_RING(); 
-   }
-
-   {
-      BEGIN_LP_RING(2);
-      OUT_RING(MI_FLUSH | 
-	       MI_STATE_INSTRUCTION_CACHE_FLUSH |
-	       BRW_MI_GLOBAL_SNAPSHOT_RESET);
-      OUT_RING(MI_NOOP);
-      ADVANCE_LP_RING();
-   }
-
-   while (nbox--)
-   {
-      float src_scale_x, src_scale_y;
-      int i;
-      box_x1 = pbox->x1;
-      box_y1 = pbox->y1;
-      box_x2 = pbox->x2;
-      box_y2 = pbox->y2;
-
-      if (!first_output) {
-	 /* Since we use the same little vertex buffer over and over, sync for
-	  * subsequent rectangles.
-	  */
-	 i830WaitSync(pScrn);
-      }
-
-      pbox++;
-
-      verts[0][0] = box_x1; verts[0][1] = box_y1;
-      verts[1][0] = box_x2; verts[1][1] = box_y1;
-      verts[2][0] = box_x2; verts[2][1] = box_y2;
-      verts[3][0] = box_x1; verts[3][1] = box_y2;
-
-      /* transform coordinates to rotated versions, but leave texcoords unchanged */
-      for (i = 0; i < 4; i++)
-         matrix23TransformCoordf(&rotMatrix, &verts[i][0], &verts[i][1]);
-
-      src_scale_x = (float)1.0 / (float)pScreen->width;
-      src_scale_y = (float)1.0 / (float)pScreen->height;
-      i = 0;
-
-      DPRINTF(PFX, "box size (%d, %d) -> (%d, %d)\n", 
-			box_x1, box_y1, box_x2, box_y2);
-
-      switch (pI830->rotation) {
-         case RR_Rotate_90:
-      	    vb[i++] = (float)box_x1 * src_scale_x;
-      	    vb[i++] = (float)box_y2 * src_scale_y;
-      	    vb[i++] = verts[3][0];
-      	    vb[i++] = verts[3][1];
-
-      	    vb[i++] = (float)box_x1 * src_scale_x;
-      	    vb[i++] = (float)box_y1 * src_scale_y;
-      	    vb[i++] = verts[0][0];
-      	    vb[i++] = verts[0][1];
-
-      	    vb[i++] = (float)box_x2 * src_scale_x;
-      	    vb[i++] = (float)box_y1 * src_scale_y;
-      	    vb[i++] = verts[1][0];
-      	    vb[i++] = verts[1][1];
-	    break;
-         case RR_Rotate_270:
-      	    vb[i++] = (float)box_x2 * src_scale_x;
-      	    vb[i++] = (float)box_y1 * src_scale_y;
-      	    vb[i++] = verts[1][0];
-      	    vb[i++] = verts[1][1];
-
-      	    vb[i++] = (float)box_x2 * src_scale_x;
-      	    vb[i++] = (float)box_y2 * src_scale_y;
-      	    vb[i++] = verts[2][0];
-      	    vb[i++] = verts[2][1];
-
-      	    vb[i++] = (float)box_x1 * src_scale_x;
-      	    vb[i++] = (float)box_y2 * src_scale_y;
-      	    vb[i++] = verts[3][0];
-      	    vb[i++] = verts[3][1];
-	    break;
-	 case RR_Rotate_180:
-       	 default:
-      	    vb[i++] = (float)box_x1 * src_scale_x;
-      	    vb[i++] = (float)box_y1 * src_scale_y;
-      	    vb[i++] = verts[0][0];
-      	    vb[i++] = verts[0][1];
-
-            vb[i++] = (float)box_x2 * src_scale_x;
-      	    vb[i++] = (float)box_y1 * src_scale_y;
-      	    vb[i++] = verts[1][0];
-      	    vb[i++] = verts[1][1];
-
-      	    vb[i++] = (float)box_x2 * src_scale_x;
-      	    vb[i++] = (float)box_y2 * src_scale_y;
-      	    vb[i++] = verts[2][0];
-      	    vb[i++] = verts[2][1];
-	    break;
-      }
-
-      BEGIN_LP_RING(6);
-      OUT_RING(BRW_3DPRIMITIVE | 
-	       BRW_3DPRIMITIVE_VERTEX_SEQUENTIAL |
-	       (_3DPRIM_RECTLIST << BRW_3DPRIMITIVE_TOPOLOGY_SHIFT) | 
-	       (0 << 9) |  /* CTG - indirect vertex count */
-	       4);
-      OUT_RING(3); /* vertex count per instance */
-      OUT_RING(0); /* start vertex offset */
-      OUT_RING(1); /* single instance */
-      OUT_RING(0); /* start instance location */
-      OUT_RING(0); /* index buffer offset, ignored */
-      ADVANCE_LP_RING();
-
-      first_output = FALSE;
-      i830MarkSync(pScrn);
-   }
-
-   i830WaitSync(pScrn);
-#ifdef XF86DRI
-   if (didLock)
-      I830DRIUnlock(pScrn1);
-#endif
-}
-
-
-static void
-I915UpdateRotate (ScreenPtr      pScreen,
-                 shadowBufPtr   pBuf)
-{
-   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-   I830Ptr pI830 = I830PTR(pScrn);
-   ScrnInfoPtr pScrn1 = pScrn;
-   I830Ptr pI8301 = NULL;
-   RegionPtr	damage = shadowDamage(pBuf);
-   int		nbox = REGION_NUM_RECTS (damage);
-   BoxPtr		pbox = REGION_RECTS (damage);
-   int		box_x1, box_x2, box_y1, box_y2;
-   CARD32	vb[32];	/* 32 dword vertex buffer */
-   float verts[4][2], tex[4][2];
-   struct matrix23 rotMatrix;
-   int j;
-   int use_fence;
-   Bool didLock = FALSE;
-
-   if (I830IsPrimary(pScrn)) {
-      pI8301 = pI830;
-   } else {
-      pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
-      pScrn1 = pI830->entityPrivate->pScrn_1;
-   }
-
-   switch (pI830->rotation) {
-      case RR_Rotate_90:
-         matrix23Rotate(&rotMatrix,
-                     pScreen->width, pScreen->height,
-                     90);
-	 break;
-      case RR_Rotate_180:
-         matrix23Rotate(&rotMatrix,
-                     pScreen->width, pScreen->height,
-                     180);
-	 break;
-      case RR_Rotate_270:
-         matrix23Rotate(&rotMatrix,
-                     pScreen->width, pScreen->height,
-                     270);
-	 break;
-      default:
-	 break;
-   }
-
-#ifdef XF86DRI
-   if (pI8301->directRenderingEnabled)
-      didLock = I830DRILock(pScrn1);
-#endif
-
-   /* If another screen was active, we don't know the current state. */
-   if (pScrn->scrnIndex != *pI830->used3D)
-      pI830->last_3d = LAST_3D_OTHER;
-
-   if (pI830->last_3d != LAST_3D_ROTATION) {
-      FS_LOCALS(3);
-      *pI830->used3D = pScrn->scrnIndex;
-
-      BEGIN_LP_RING(34);
-      /* invarient state */
-
-      /* flush map & render cache */
-      OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
-      OUT_RING(0x00000000);
-
-      /* draw rect */
-      OUT_RING(_3DSTATE_DRAW_RECT_CMD);
-      OUT_RING(DRAW_DITHER_OFS_X(0) | DRAW_DITHER_OFS_Y(0));
-      OUT_RING(DRAW_XMIN(0) | DRAW_YMIN(0));
-      OUT_RING(DRAW_XMAX(pScrn->virtualX - 1) |
-	       DRAW_YMAX(pScrn->virtualY - 1));
-      OUT_RING(DRAW_XORG(0) | DRAW_YORG(0));
-
-      OUT_RING(MI_NOOP);
-
-      OUT_RING(0x7c000003); /* XXX: magic numbers */
-      OUT_RING(0x7d070000);
-      OUT_RING(0x00000000);
-      OUT_RING(0x68000002);
-
-      OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
-	       I1_LOAD_S(2) | I1_LOAD_S(4) | I1_LOAD_S(5) | I1_LOAD_S(6) | 3);
-
-      OUT_RING(S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D) |
-	       S2_TEXCOORD_FMT(1, TEXCOORDFMT_NOT_PRESENT) |
-	       S2_TEXCOORD_FMT(2, TEXCOORDFMT_NOT_PRESENT) |
-	       S2_TEXCOORD_FMT(3, TEXCOORDFMT_NOT_PRESENT) |
-	       S2_TEXCOORD_FMT(4, TEXCOORDFMT_NOT_PRESENT) |
-	       S2_TEXCOORD_FMT(5, TEXCOORDFMT_NOT_PRESENT) |
-	       S2_TEXCOORD_FMT(6, TEXCOORDFMT_NOT_PRESENT) |
-	       S2_TEXCOORD_FMT(7, TEXCOORDFMT_NOT_PRESENT));
-      OUT_RING((1 << S4_POINT_WIDTH_SHIFT) | S4_LINE_WIDTH_ONE |
-	       S4_CULLMODE_NONE | S4_VFMT_SPEC_FOG | S4_VFMT_COLOR |
-	       S4_VFMT_XYZW);
-      OUT_RING(0x00000000); /* S5 -- enable bits */
-      OUT_RING((2 << S6_DEPTH_TEST_FUNC_SHIFT) |
-	       (2 << S6_CBUF_SRC_BLEND_FACT_SHIFT) |
-	       (1 << S6_CBUF_DST_BLEND_FACT_SHIFT) | S6_COLOR_WRITE_ENABLE |
-	       (2 << S6_TRISTRIP_PV_SHIFT));
-
-      OUT_RING(_3DSTATE_CONST_BLEND_COLOR_CMD);
-      OUT_RING(0x00000000);
-
-      OUT_RING(_3DSTATE_DST_BUF_VARS_CMD);
-      if (pI830->cpp == 1) {
-	 OUT_RING(LOD_PRECLAMP_OGL | DSTORG_HORT_BIAS(0x8) |
-		  DSTORG_VERT_BIAS(0x8) | COLR_BUF_8BIT);
-      } else if (pI830->cpp == 2) {
-	 OUT_RING(LOD_PRECLAMP_OGL | DSTORG_HORT_BIAS(0x8) |
-		  DSTORG_VERT_BIAS(0x8) | COLR_BUF_RGB565);
-      } else {
-	 OUT_RING(LOD_PRECLAMP_OGL | DSTORG_HORT_BIAS(0x8) |
-		  DSTORG_VERT_BIAS(0x8) | COLR_BUF_ARGB8888 |
-		  DEPTH_FRMT_24_FIXED_8_OTHER);
-      }
-
-      /* texture sampler state */
-      OUT_RING(_3DSTATE_SAMPLER_STATE | 3);
-      OUT_RING(0x00000001);
-      OUT_RING(0x00000000);
-      OUT_RING(0x00000000);
-      OUT_RING(0x00000000);
-
-      /* front buffer, pitch, offset */
-      OUT_RING(_3DSTATE_BUF_INFO_CMD);
-      OUT_RING(BUF_3D_ID_COLOR_BACK | BUF_3D_USE_FENCE |
-	       BUF_3D_PITCH(pI830->displayWidth * pI830->cpp));
-      if (I830IsPrimary(pScrn))
-         OUT_RING(pI830->FrontBuffer.Start);
-      else 
-         OUT_RING(pI8301->FrontBuffer2.Start);
-
-      /* Set the entire frontbuffer up as a texture */
-      OUT_RING(_3DSTATE_MAP_STATE | 3);
-      OUT_RING(0x00000001);
-
-      if (I830IsPrimary(pScrn)) 
-         OUT_RING(pI830->RotatedMem.Start);
-      else 
-	 OUT_RING(pI8301->RotatedMem2.Start);
-
-      if (pI830->disableTiling)
-         use_fence = 0;
-      else
-         use_fence = MS3_USE_FENCE_REGS;
-      
-      if (pI830->cpp == 1)
-	 use_fence |= MAPSURF_8BIT;
-      else
-      if (pI830->cpp == 2)
-	 use_fence |= MAPSURF_16BIT;
-      else
-	 use_fence |= MAPSURF_32BIT;
-      OUT_RING(use_fence | (pScreen->height - 1) << 21 | (pScreen->width - 1) << 10);
-      OUT_RING(((((pScrn->displayWidth * pI830->cpp) / 4) - 1) << 21));
-      ADVANCE_LP_RING();
-
-      /* fragment program - texture blend replace*/
-      FS_BEGIN();
-      i915_fs_dcl(FS_S0);
-      i915_fs_dcl(FS_T0);
-      i915_fs_texld(FS_OC, FS_S0, FS_T0);
-      FS_END();
-   }
-   
-   {
-      BEGIN_LP_RING(2);
-      OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
-      OUT_RING(0x00000000);
-      ADVANCE_LP_RING();
-   }
-
-   while (nbox--)
-   {
-      box_x1 = pbox->x1;
-      box_y1 = pbox->y1;
-      box_x2 = pbox->x2;
-      box_y2 = pbox->y2;
-      pbox++;
-
-      BEGIN_LP_RING(40);
-      OUT_RING(MI_NOOP);
-      OUT_RING(MI_NOOP);
-      OUT_RING(MI_NOOP);
-      OUT_RING(MI_NOOP);
-      OUT_RING(MI_NOOP);
-      OUT_RING(MI_NOOP);
-      OUT_RING(MI_NOOP);
-
-      /* vertex data */
-      OUT_RING(PRIM3D_INLINE | PRIM3D_TRIFAN | (32 - 1));
-      verts[0][0] = box_x1; verts[0][1] = box_y1;
-      verts[1][0] = box_x2; verts[1][1] = box_y1;
-      verts[2][0] = box_x2; verts[2][1] = box_y2;
-      verts[3][0] = box_x1; verts[3][1] = box_y2;
-      tex[0][0] = box_x1; tex[0][1] = box_y1;
-      tex[1][0] = box_x2; tex[1][1] = box_y1;
-      tex[2][0] = box_x2; tex[2][1] = box_y2;
-      tex[3][0] = box_x1; tex[3][1] = box_y2;
-
-      /* transform coordinates to rotated versions, but leave texcoords unchanged */
-      for (j = 0; j < 4; j++)
-         matrix23TransformCoordf(&rotMatrix, &verts[j][0], &verts[j][1]);
-
-      /* emit vertex buffer */
-      draw_poly(vb, verts, tex);
-      for (j = 0; j < 32; j++)
-         OUT_RING(vb[j]);
-
-      ADVANCE_LP_RING();
-   }
-
-#ifdef XF86DRI
-   if (didLock)
-      I830DRIUnlock(pScrn1);
-#endif
-}
-
-static void
-I830UpdateRotate (ScreenPtr      pScreen,
-                 shadowBufPtr   pBuf)
-{
-   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-   I830Ptr pI830 = I830PTR(pScrn);
-   I830Ptr pI8301 = NULL;
-   ScrnInfoPtr pScrn1 = pScrn;
-   RegionPtr	damage = shadowDamage(pBuf);
-   int		nbox = REGION_NUM_RECTS (damage);
-   BoxPtr		pbox = REGION_RECTS (damage);
-   int		box_x1, box_x2, box_y1, box_y2;
-   CARD32	vb[32];	/* 32 dword vertex buffer */
-   float verts[4][2], tex[4][2];
-   struct matrix23 rotMatrix;
-   int use_fence;
-   int j;
-   Bool didLock = FALSE;
-
-   if (I830IsPrimary(pScrn)) {
-      pI8301 = pI830;
-   } else {
-      pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
-      pScrn1 = pI830->entityPrivate->pScrn_1;
-   }
-
-   switch (pI830->rotation) {
-      case RR_Rotate_90:
-         matrix23Rotate(&rotMatrix,
-                     pScreen->width, pScreen->height,
-                     90);
-	 break;
-      case RR_Rotate_180:
-         matrix23Rotate(&rotMatrix,
-                     pScreen->width, pScreen->height,
-                     180);
-	 break;
-      case RR_Rotate_270:
-         matrix23Rotate(&rotMatrix,
-                     pScreen->width, pScreen->height,
-                     270);
-	 break;
-      default:
-	 break;
-   }
-
-#ifdef XF86DRI
-   if (pI8301->directRenderingEnabled)
-      didLock = I830DRILock(pScrn1);
-#endif
-
-   if (pScrn->scrnIndex != *pI830->used3D)
-      pI830->last_3d = LAST_3D_OTHER;
-
-   if (pI830->last_3d != LAST_3D_ROTATION) {
-      *pI830->used3D = pScrn->scrnIndex;
-
-      pI830->last_3d = LAST_3D_ROTATION;
-
-      BEGIN_LP_RING(48);
-      OUT_RING(0x682008a1);
-      OUT_RING(0x6f402100);
-      OUT_RING(0x62120aa9);
-      OUT_RING(0x76b3ffff);
-      OUT_RING(0x6c818a01);
-      OUT_RING(0x6ba008a1);
-      OUT_RING(0x69802100);
-      OUT_RING(0x63a00aaa);
-      OUT_RING(0x6423070e);
-      OUT_RING(0x66014142);
-      OUT_RING(0x75000000);
-      OUT_RING(0x7d880000);
-      OUT_RING(0x00000000);
-      OUT_RING(0x650001c4);
-      OUT_RING(0x6a000000);
-      OUT_RING(0x7d020000);
-      OUT_RING(0x0000ba98);
-
-      /* flush map & render cache */
-      OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
-      OUT_RING(0x00000000);
-      /* draw rect */
-      OUT_RING(_3DSTATE_DRAW_RECT_CMD);
-      OUT_RING(0x00000000);	/* flags */
-      OUT_RING(0x00000000);	/* ymin, xmin */
-      OUT_RING((pScrn->virtualX - 1) | (pScrn->virtualY - 1) << 16); /* ymax, xmax */
-      OUT_RING(0x00000000);	/* yorigin, xorigin */
-      OUT_RING(MI_NOOP);
-
-      /* front buffer */
-      OUT_RING(_3DSTATE_BUF_INFO_CMD);
-      OUT_RING(0x03800000 | (((pI830->displayWidth * pI830->cpp) / 4) << 2));
-      if (I830IsPrimary(pScrn))
-	 OUT_RING(pI830->FrontBuffer.Start);
-      else 
-	 OUT_RING(pI8301->FrontBuffer2.Start);
-      OUT_RING(0x7d850000);
-      if (pI830->cpp == 1)
-	 OUT_RING(0x00880000);
-      else
-	 if (pI830->cpp == 2)
-	    OUT_RING(0x00880200);
-	 else
-	    OUT_RING(0x00880308);
-      /* scissor */
-      OUT_RING(0x7c800002);
-      OUT_RING(0x7d810001);
-      OUT_RING(0x00000000);
-      OUT_RING(0x00000000);
-      /* stipple */
-      OUT_RING(0x7d830000);
-      OUT_RING(0x00000000);
-
-      /* texture blend replace */
-      OUT_RING(0x7c088088);
-      OUT_RING(0x00000000);
-      OUT_RING(0x6d021181);
-      OUT_RING(0x6d060101);
-      OUT_RING(0x6e008046);
-      OUT_RING(0x6e048046);
-
-
-      /* Set the entire frontbuffer up as a texture */
-      OUT_RING(0x7d030804);
-
-      if (pI830->disableTiling)
-         use_fence = 0;
-      else
-         use_fence = 2;
-
-      if (I830IsPrimary(pScrn)) 
-         OUT_RING(pI830->RotatedMem.Start | use_fence);
-      else 
-	 OUT_RING(pI8301->RotatedMem2.Start | use_fence);
-
-      if (pI830->cpp == 1)
-         OUT_RING(0x40 | (pScreen->height - 1) << 21 | (pScreen->width - 1) << 10);
-      else if (pI830->cpp == 2)
-         OUT_RING(0x80 | (pScreen->height - 1) << 21 | (pScreen->width - 1) << 10);
-      else
-         OUT_RING(0xc0 | (pScreen->height - 1) << 21 | (pScreen->width - 1) << 10);
-
-      OUT_RING((((pScrn->displayWidth * pI830->cpp / 4) - 1) << 21));
-      OUT_RING(0x00000000);
-      OUT_RING(0x00000000);
-
-
-      ADVANCE_LP_RING();
-   }
-
-   {
-      BEGIN_LP_RING(2);
-      /* flush map & render cache */
-      OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
-      OUT_RING(0x00000000);
-      ADVANCE_LP_RING();
-   }
-
-   while (nbox--)
-   {
-      box_x1 = pbox->x1;
-      box_y1 = pbox->y1;
-      box_x2 = pbox->x2;
-      box_y2 = pbox->y2;
-      pbox++;
-
-      BEGIN_LP_RING(40);
-
-      OUT_RING(MI_NOOP);
-      OUT_RING(MI_NOOP);
-      OUT_RING(MI_NOOP);
-      OUT_RING(MI_NOOP);
-      OUT_RING(MI_NOOP);
-
-      /* vertex data */
-      OUT_RING(0x7f0c001f);
-      verts[0][0] = box_x1; verts[0][1] = box_y1;
-      verts[1][0] = box_x2; verts[1][1] = box_y1;
-      verts[2][0] = box_x2; verts[2][1] = box_y2;
-      verts[3][0] = box_x1; verts[3][1] = box_y2;
-      tex[0][0] = box_x1; tex[0][1] = box_y1;
-      tex[1][0] = box_x2; tex[1][1] = box_y1;
-      tex[2][0] = box_x2; tex[2][1] = box_y2;
-      tex[3][0] = box_x1; tex[3][1] = box_y2;
-
-      /* transform coordinates to rotated versions, but leave texcoords unchanged */
-      for (j = 0; j < 4; j++)
-         matrix23TransformCoordf(&rotMatrix, &verts[j][0], &verts[j][1]);
-
-      /* emit vertex buffer */
-      draw_poly(vb, verts, tex);
-      for (j = 0; j < 32; j++)
-         OUT_RING(vb[j]);
-
-      OUT_RING(0x05000000);
-      OUT_RING(0x00000000);
-
-      ADVANCE_LP_RING();
-   }
-
-   {
-      BEGIN_LP_RING(2);
-      /* flush map & render cache */
-      OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
-      OUT_RING(0x00000000);
-      ADVANCE_LP_RING();
-   }
-
-#ifdef XF86DRI
-   if (didLock)
-      I830DRIUnlock(pScrn1);
-#endif
-}
-
-Bool
-I830Rotate(ScrnInfoPtr pScrn, DisplayModePtr mode)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   I830Ptr pI8301 = NULL;
-   I830Ptr pI8302 = NULL;
-   ScrnInfoPtr pScrn1 = NULL;
-   ScrnInfoPtr pScrn2 = NULL;
-   int i;
-   ShadowUpdateProc func = NULL;
-   Rotation oldRotation = pI830->rotation; /* save old state */
-   int displayWidth = pScrn->displayWidth; /* save displayWidth */
-   Bool reAllocate = TRUE;
-   Bool didLock = FALSE;
-
-   /* Good pitches to allow tiling.  Don't care about pitches < 1024. */
-   static const int pitches[] = {
-/*
-	 128 * 2,
-	 128 * 4,
-*/
-	 128 * 8,
-	 128 * 16,
-	 128 * 32,
-	 128 * 64,
-	 0
-   };
-
-   if (pI830->noAccel)
-      func = LoaderSymbol("shadowUpdateRotatePacked");
-   else {
-      if (IS_I9XX(pI830)) {
-	 if (IS_I965G(pI830))
-	     func = I965UpdateRotate;
-	 else 
-	     func = I915UpdateRotate;
-      } else
-	 func = I830UpdateRotate;
-   }
-
-   if (I830IsPrimary(pScrn)) {
-      pI8301 = pI830;
-      pScrn1 = pScrn;
-      if (pI830->entityPrivate) {
-         pI8302 = I830PTR(pI830->entityPrivate->pScrn_2);
-         pScrn2 = pI830->entityPrivate->pScrn_2;
-      }
-   } else {
-      pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
-      pScrn1 = pI830->entityPrivate->pScrn_1;
-      pI8302 = pI830;
-      pScrn2 = pScrn;
-   }
-
-   pI830->rotation = xf86RandR12GetRotation(pScrn->pScreen);
-
-   /* Check if we've still got the same orientation, or same mode */
-   if (pI830->rotation == oldRotation && pI830->currentMode == mode)
-#if 0
-	reAllocate = FALSE;
-#else
-	return TRUE;
-#endif
-
-   /* 
-    * We grab the DRI lock when reallocating buffers to avoid DRI clients
-    * getting bogus information.
-    */
-
-#ifdef XF86DRI
-   if (pI8301->directRenderingEnabled && reAllocate) {
-      didLock = I830DRILock(pScrn1);
-      
-      /* Do heap teardown here
-       */
-      if (pI8301->mmModeFlags & I830_KERNEL_TEX) {
-	 drmI830MemDestroyHeap destroy;
-	 destroy.region = I830_MEM_REGION_AGP;
-	 
-	 if (drmCommandWrite(pI8301->drmSubFD, 
-			     DRM_I830_DESTROY_HEAP, 
-			     &destroy, sizeof(destroy))) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		       "[dri] I830 destroy heap failed\n");
-	 }
-      }
-      
-      if (pI8301->mmModeFlags & I830_KERNEL_TEX) {
-	 if (pI8301->TexMem.Key != -1)
-	    xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->TexMem.Key);
-	 I830FreeVidMem(pScrn1, &(pI8301->TexMem));
-      }
-      if (pI8301->StolenPool.Allocated.Key != -1) {
-         xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->StolenPool.Allocated.Key);
-         xf86DeallocateGARTMemory(pScrn1->scrnIndex, pI8301->StolenPool.Allocated.Key);
-      }
-      if (pI8301->DepthBuffer.Key != -1)
-         xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->DepthBuffer.Key);
-      I830FreeVidMem(pScrn1, &(pI8301->DepthBuffer));
-      if (pI8301->BackBuffer.Key != -1)
-         xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->BackBuffer.Key);
-      I830FreeVidMem(pScrn1, &(pI8301->BackBuffer));
-   }
-#endif
-
-   if (reAllocate) {
-      *pI830->used3D |= 1<<31; /* use high bit to denote new rotation occured */
-
-      if (pI8301->RotatedMem.Key != -1)
-         xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->RotatedMem.Key);
- 
-      I830FreeVidMem(pScrn1, &(pI8301->RotatedMem));
-      memset(&(pI8301->RotatedMem), 0, sizeof(pI8301->RotatedMem));
-      pI8301->RotatedMem.Key = -1;
-
-      if (IS_I965G(pI8301)) {
-         if (pI8301->RotateStateMem.Key != -1)
-            xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->RotateStateMem.Key);
- 
-         I830FreeVidMem(pScrn1, &(pI8301->RotateStateMem));
-         memset(&(pI8301->RotateStateMem), 0, sizeof(pI8301->RotateStateMem));
-      	 pI8301->RotateStateMem.Key = -1;
-      }
-
-      if (pI830->entityPrivate) {
-         if (pI8301->RotatedMem2.Key != -1)
-            xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->RotatedMem2.Key);
- 
-         I830FreeVidMem(pScrn1, &(pI8301->RotatedMem2));
-         memset(&(pI8301->RotatedMem2), 0, sizeof(pI8301->RotatedMem2));
-         pI8301->RotatedMem2.Key = -1;
-      }
-   }
-
-   switch (pI830->rotation) {
-      case RR_Rotate_0:
-         if (reAllocate)
-            xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		    "Rotating Screen to 0 degrees\n");
-         pScrn->displayWidth = pI830->displayWidth;
-         break;
-      case RR_Rotate_90:
-         if (reAllocate)
-            xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		    "Rotating Screen to 90 degrees\n");
-         pScrn->displayWidth = pScrn->pScreen->width;
-         break;
-      case RR_Rotate_180:
-         if (reAllocate)
-            xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		    "Rotating Screen to 180 degrees\n");
-         pScrn->displayWidth = pI830->displayWidth;
-         break;
-      case RR_Rotate_270:
-         if (reAllocate)
-            xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		    "Rotating Screen to 270 degrees\n");
-         pScrn->displayWidth = pScrn->pScreen->width;
-         break;
-   }
-
-   /* As DRI doesn't run on the secondary head, we know that disableTiling
-    * is always TRUE.
-    */
-   if (I830IsPrimary(pScrn) && !pI830->disableTiling) {
-#if 0
-      int dWidth = pScrn->displayWidth; /* save current displayWidth */
-#endif
-
-      for (i = 0; pitches[i] != 0; i++) {
-         if (pitches[i] >= pScrn->displayWidth) {
-            pScrn->displayWidth = pitches[i];
-            break;
-         }
-      }
-
-      /*
-       * If the displayWidth is a tilable pitch, test if there's enough
-       * memory available to enable tiling.
-       */
-      if (pScrn->displayWidth == pitches[i]) {
-  	/* TODO */
-      }
-   }
-
-   if (reAllocate) {
-      if (pI830->entityPrivate) {
-         if (pI8302->rotation != RR_Rotate_0) {
-            if (!I830AllocateRotated2Buffer(pScrn1, 
-			      pI8302->disableTiling ? ALLOC_NO_TILING : 0))
-               goto BAIL0;
-
-            I830FixOffset(pScrn1, &(pI8301->RotatedMem2));
-            if (pI8301->RotatedMem2.Key != -1)
-               xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->RotatedMem2.Key, pI8301->RotatedMem2.Offset);
-         }
-      }
-
-      if (pI8301->rotation != RR_Rotate_0) {
-         if (!I830AllocateRotatedBuffer(pScrn1, 
-			      pI8301->disableTiling ? ALLOC_NO_TILING : 0))
-            goto BAIL1;
-
-         I830FixOffset(pScrn1, &(pI8301->RotatedMem));
-         if (pI8301->RotatedMem.Key != -1)
-            xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->RotatedMem.Key, pI8301->RotatedMem.Offset);
-	 if (IS_I965G(pI8301)) {
-            I830FixOffset(pScrn1, &(pI8301->RotateStateMem));
-            if (pI8301->RotateStateMem.Key != -1)
-            	xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->RotateStateMem.Key, 
-				   pI8301->RotateStateMem.Offset);
-	 }
-      }
-   }
-   
-   shadowRemove (pScrn->pScreen, NULL);
-   if (pI830->rotation != RR_Rotate_0)
-      shadowAdd (pScrn->pScreen, 
-		 (*pScrn->pScreen->GetScreenPixmap) (pScrn->pScreen),
-		 func, I830WindowLinear, pI830->rotation, NULL);
-
-   if (I830IsPrimary(pScrn)) {
-      if (pI830->rotation != RR_Rotate_0)
-         pScrn->fbOffset = pI830->RotatedMem.Start;
-      else
-         pScrn->fbOffset = pI830->FrontBuffer.Start;
-      if (pI830->entityPrivate) {
-         if (pI8302->rotation != RR_Rotate_0) 
-            pScrn2->fbOffset = pI8301->RotatedMem2.Start;
-         else
-            pScrn2->fbOffset = pI8301->FrontBuffer2.Start;
-         I830SelectBuffer(pScrn2, I830_SELECT_FRONT);
-      }
-   } else {
-      if (pI830->rotation != RR_Rotate_0)
-         pScrn->fbOffset = pI8301->RotatedMem2.Start;
-      else
-         pScrn->fbOffset = pI8301->FrontBuffer2.Start;
-      if (pI8301->rotation != RR_Rotate_0)
-         pScrn1->fbOffset = pI8301->RotatedMem.Start;
-      else
-         pScrn1->fbOffset = pI8301->FrontBuffer.Start;
-      I830SelectBuffer(pScrn1, I830_SELECT_FRONT);
-   }
-   I830SelectBuffer(pScrn, I830_SELECT_FRONT);
-
-#ifdef XF86DRI
-   if (pI8301->directRenderingEnabled && reAllocate) {
-      if (!I830AllocateBackBuffer(pScrn1,
-			      pI8301->disableTiling ? ALLOC_NO_TILING : 0))
-         goto BAIL2;
-
-      if (!I830AllocateDepthBuffer(pScrn1,
-			      pI8301->disableTiling ? ALLOC_NO_TILING : 0))
-         goto BAIL3;
-
-      if (pI8301->mmModeFlags & I830_KERNEL_TEX) {
-	 if (!I830AllocateTextureMemory(pScrn1,
-					pI8301->disableTiling ? ALLOC_NO_TILING : 0))
-	    goto BAIL4;
-      }
-
-      I830DoPoolAllocation(pScrn1, &(pI8301->StolenPool));
-
-      I830FixOffset(pScrn1, &(pI8301->BackBuffer));
-      I830FixOffset(pScrn1, &(pI8301->DepthBuffer));
-
-      if (pI8301->BackBuffer.Key != -1)
-         xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->BackBuffer.Key, pI8301->BackBuffer.Offset);
-      if (pI8301->DepthBuffer.Key != -1)
-         xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->DepthBuffer.Key, pI8301->DepthBuffer.Offset);
-      if (pI8301->StolenPool.Allocated.Key != -1)
-         xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->StolenPool.Allocated.Key, pI8301->StolenPool.Allocated.Offset);
-      if (pI8301->mmModeFlags & I830_KERNEL_TEX) {
-	 if (pI8301->TexMem.Key != -1)
-	    xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->TexMem.Key, pI8301->TexMem.Offset);
-      }
-      I830SetupMemoryTiling(pScrn1);
-      /* update fence registers */
-      if (IS_I965G(pI830)) {
-         for (i = 0; i < FENCE_NEW_NR; i++) {
-            OUTREG(FENCE_NEW + i * 8, pI830->ModeReg.Fence[i]);
-            OUTREG(FENCE_NEW + 4 + i * 8, pI830->ModeReg.Fence[i+FENCE_NEW_NR]);
-         }
-      } else {
-         for (i = 0; i < 8; i++) 
-            OUTREG(FENCE + i * 4, pI8301->ModeReg.Fence[i]);
-      }
-
-      {
-         drmI830Sarea *sarea = DRIGetSAREAPrivate(pScrn1->pScreen);
-         I830UpdateDRIBuffers(pScrn1, sarea );
-      }
-      
-      if (didLock)
-	 I830DRIUnlock(pScrn1);
-   }
-#endif
-
-#if 0
-   if (I830IsPrimary(pScrn)) {
-      pI830->xoffset = (pI830->FrontBuffer.Start / pI830->cpp) % pI830->displayWidth;
-      pI830->yoffset = (pI830->FrontBuffer.Start / pI830->cpp) / pI830->displayWidth;
-   } else {
-      I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
-      pI830->xoffset = (pI8301->FrontBuffer2.Start / pI830->cpp) % pI830->displayWidth;
-      pI830->yoffset = (pI8301->FrontBuffer2.Start / pI830->cpp) / pI830->displayWidth;
-   }
-#endif
-
-   pScrn->pScreen->ModifyPixmapHeader((*pScrn->pScreen->GetScreenPixmap)(pScrn->pScreen), pScrn->pScreen->width,
-		    pScrn->pScreen->height, pScrn->pScreen->rootDepth, pScrn->bitsPerPixel,
-		    PixmapBytePad(pScrn->displayWidth, pScrn->pScreen->rootDepth), 
-		    (pointer)(pI8301->FbBase + pScrn->fbOffset));
-
-   if (pI830->entityPrivate) {
-      if (I830IsPrimary(pScrn)) {
-         if (!pI830->starting) {
-            pScrn2->pScreen->ModifyPixmapHeader((*pScrn2->pScreen->GetScreenPixmap)(pScrn2->pScreen), pScrn2->pScreen->width,
-		    pScrn2->pScreen->height, pScrn2->pScreen->rootDepth, pScrn2->bitsPerPixel,
-		    PixmapBytePad(pScrn2->displayWidth, pScrn2->pScreen->rootDepth), 
-		    (pointer)(pI8301->FbBase + pScrn2->fbOffset));
-
-            /* Repaint the second head */
-            (*pScrn2->EnableDisableFBAccess) (pScrn2->pScreen->myNum, FALSE);
-            (*pScrn2->EnableDisableFBAccess) (pScrn2->pScreen->myNum, TRUE);
-         }
-      } else {
-         if (!pI830->starting) {
-            pScrn1->pScreen->ModifyPixmapHeader((*pScrn1->pScreen->GetScreenPixmap)(pScrn1->pScreen), pScrn1->pScreen->width,
-		    pScrn1->pScreen->height, pScrn1->pScreen->rootDepth, pScrn1->bitsPerPixel,
-		    PixmapBytePad(pScrn1->displayWidth, pScrn1->pScreen->rootDepth), 
-		    (pointer)(pI8301->FbBase + pScrn1->fbOffset));
-
-            /* Repaint the first head */
-            (*pScrn1->EnableDisableFBAccess) (pScrn1->pScreen->myNum, FALSE);
-            (*pScrn1->EnableDisableFBAccess) (pScrn1->pScreen->myNum, TRUE);
-         }
-      }
-   }
-
-#ifdef I830_USE_XAA
-   if (pI830->AccelInfoRec != NULL) {
-      /* Don't allow pixmap cache or offscreen pixmaps when rotated */
-      /* XAA needs some serious fixing for this to happen */
-      if (pI830->rotation == RR_Rotate_0) {
-	 pI830->AccelInfoRec->Flags = LINEAR_FRAMEBUFFER | OFFSCREEN_PIXMAPS |
-				      PIXMAP_CACHE;
-	 pI830->AccelInfoRec->UsingPixmapCache = TRUE;
-	 /* funny as it seems this will enable XAA's createpixmap */
-	 pI830->AccelInfoRec->maxOffPixWidth = 0;
-	 pI830->AccelInfoRec->maxOffPixHeight = 0;
-      } else {
-	 pI830->AccelInfoRec->Flags = LINEAR_FRAMEBUFFER;
-	 pI830->AccelInfoRec->UsingPixmapCache = FALSE;
-	 /* funny as it seems this will disable XAA's createpixmap */
-	 pI830->AccelInfoRec->maxOffPixWidth = 1;
-	 pI830->AccelInfoRec->maxOffPixHeight = 1;
-      }
-   }
-#endif
-
-   return TRUE;
-
-BAIL4:
-#ifdef XF86DRI
-   if (pI8301->directRenderingEnabled)
-      I830FreeVidMem(pScrn1, &(pI8301->DepthBuffer));
-#endif
-BAIL3:
-#ifdef XF86DRI
-   if (pI8301->directRenderingEnabled)
-      I830FreeVidMem(pScrn1, &(pI8301->BackBuffer));
-#endif
-BAIL2:
-   if (pI8301->rotation != RR_Rotate_0) {
-      if (pI8301->RotatedMem.Key != -1)
-         xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->RotatedMem.Key);
-  
-      I830FreeVidMem(pScrn1, &(pI8301->RotatedMem));
-      memset(&(pI8301->RotatedMem), 0, sizeof(pI8301->RotatedMem));
-      pI8301->RotatedMem.Key = -1;
-   }
-BAIL1:
-   if (pI830->entityPrivate) {
-      if (pI8302->rotation != RR_Rotate_0) {
-         if (pI8301->RotatedMem.Key != -1)
-            xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->RotatedMem.Key);
-
-         I830FreeVidMem(pScrn1, &(pI8301->RotatedMem));
-         memset(&(pI8301->RotatedMem), 0, sizeof(pI8301->RotatedMem));
-         pI8301->RotatedMem.Key = -1;
-      }
-   }
-BAIL0:
-   pScrn->displayWidth = displayWidth;
-
-   /* must flip mmWidth & mmHeight */
-   if ( ((oldRotation & (RR_Rotate_90 | RR_Rotate_270)) &&
-	 (pI830->rotation & (RR_Rotate_0 | RR_Rotate_180))) ||
-        ((oldRotation & (RR_Rotate_0 | RR_Rotate_180)) &&
-	 (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270))) ) {
-      int tmp = pScrn->pScreen->mmWidth;
-      pScrn->pScreen->mmWidth = pScrn->pScreen->mmHeight;
-      pScrn->pScreen->mmHeight = tmp;
-   }
-
-   if (oldRotation & (RR_Rotate_0 | RR_Rotate_180)) {
-      pScrn->pScreen->width = pScrn->virtualX;
-      pScrn->pScreen->height = pScrn->virtualY;
-   } else {
-      pScrn->pScreen->width = pScrn->virtualY;
-      pScrn->pScreen->height = pScrn->virtualX;
-   }
-
-   pI830->rotation = oldRotation;
-
-   if (pI830->entityPrivate) {
-      if (pI8302->rotation != RR_Rotate_0) {
-         if (!I830AllocateRotated2Buffer(pScrn1, 
-			      pI8302->disableTiling ? ALLOC_NO_TILING : 0))
-            xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
-		    "Oh dear, the rotated2 buffer failed - badness\n");
-
-         I830FixOffset(pScrn1, &(pI8301->RotatedMem2));
-         if (pI8301->RotatedMem2.Key != -1)
-            xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->RotatedMem2.Key, pI8301->RotatedMem2.Offset);
-      }
-   }
-
-   if (pI8301->rotation != RR_Rotate_0) {
-      if (!I830AllocateRotatedBuffer(pScrn1, 
-			      pI8301->disableTiling ? ALLOC_NO_TILING : 0))
-         xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
-		    "Oh dear, the rotated buffer failed - badness\n");
-
-      I830FixOffset(pScrn1, &(pI8301->RotatedMem));
-      if (pI8301->RotatedMem.Key != -1)
-         xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->RotatedMem.Key, pI8301->RotatedMem.Offset);
-   }
-
-   shadowRemove (pScrn->pScreen, NULL);
-   if (pI830->rotation != RR_Rotate_0)
-      shadowAdd (pScrn->pScreen, 
-		 (*pScrn->pScreen->GetScreenPixmap) (pScrn->pScreen),
-		 func, I830WindowLinear, pI830->rotation, NULL);
-
-   if (I830IsPrimary(pScrn)) {
-      if (pI830->rotation != RR_Rotate_0)
-         pScrn->fbOffset = pI830->RotatedMem.Start;
-      else
-         pScrn->fbOffset = pI830->FrontBuffer.Start;
-      if (pI830->entityPrivate) {
-         if (pI8302->rotation != RR_Rotate_0) 
-            pScrn2->fbOffset = pI8301->RotatedMem2.Start;
-         else
-            pScrn2->fbOffset = pI8301->FrontBuffer2.Start;
-         I830SelectBuffer(pScrn2, I830_SELECT_FRONT);
-      }
-   } else {
-      if (pI830->rotation != RR_Rotate_0)
-         pScrn->fbOffset = pI8301->RotatedMem2.Start;
-      else
-         pScrn->fbOffset = pI8301->FrontBuffer2.Start;
-      if (pI8301->rotation != RR_Rotate_0)
-         pScrn1->fbOffset = pI8301->RotatedMem.Start;
-      else
-         pScrn1->fbOffset = pI8301->FrontBuffer.Start;
-      I830SelectBuffer(pScrn1, I830_SELECT_FRONT);
-   }
-   I830SelectBuffer(pScrn, I830_SELECT_FRONT);
-
-   xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		    "Reverting to previous configured mode\n");
-
-   switch (oldRotation) {
-      case RR_Rotate_0:
-         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		    "Rotating Screen back to 0 degrees\n");
-         break;
-      case RR_Rotate_90:
-         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		    "Rotating Screen back to 90 degrees\n");
-         break;
-      case RR_Rotate_180:
-         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		    "Rotating Screen back to 180 degrees\n");
-         break;
-      case RR_Rotate_270:
-         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		    "Rotating Screen back to 270 degrees\n");
-         break;
-   }
-
-#ifdef XF86DRI
-   if (pI8301->directRenderingEnabled) {
-      if (!I830AllocateBackBuffer(pScrn1,
-			      pI8301->disableTiling ? ALLOC_NO_TILING : 0))
-         xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 
-		    "Oh dear, the back buffer failed - badness\n");
-
-      if (!I830AllocateDepthBuffer(pScrn1,
-			      pI8301->disableTiling ? ALLOC_NO_TILING : 0))
-         xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 
-		    "Oh dear, the depth buffer failed - badness\n");
-      if (pI8301->mmModeFlags & I830_KERNEL_TEX) {
-	 if (!I830AllocateTextureMemory(pScrn1,
-					pI8301->disableTiling ? ALLOC_NO_TILING : 0))
-	    xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 
-		       "Oh dear, the texture cache failed - badness\n");
-      }
-
-      I830DoPoolAllocation(pScrn1, &(pI8301->StolenPool));
-
-      I830FixOffset(pScrn1, &(pI8301->BackBuffer));
-      I830FixOffset(pScrn1, &(pI8301->DepthBuffer));
-
-      if (pI8301->BackBuffer.Key != -1)
-         xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->BackBuffer.Key, pI8301->BackBuffer.Offset);
-      if (pI8301->DepthBuffer.Key != -1)
-         xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->DepthBuffer.Key, pI8301->DepthBuffer.Offset);
-      if (pI8301->StolenPool.Allocated.Key != -1)
-         xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->StolenPool.Allocated.Key, pI8301->StolenPool.Allocated.Offset);
-      if (pI8301->mmModeFlags & I830_KERNEL_TEX) {
-	 if (pI8301->TexMem.Key != -1)
-	    xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->TexMem.Key, pI8301->TexMem.Offset);
-      }
-      I830SetupMemoryTiling(pScrn1);
-      /* update fence registers */
-      for (i = 0; i < 8; i++) 
-         OUTREG(FENCE + i * 4, pI8301->ModeReg.Fence[i]);
-      { 
-         drmI830Sarea *sarea = DRIGetSAREAPrivate(pScrn1->pScreen);
-         I830UpdateDRIBuffers(pScrn1, sarea );
-      }
-      
-      if (didLock)
-	 I830DRIUnlock(pScrn1);
-   }
-#endif
-
-   pScrn->pScreen->ModifyPixmapHeader((*pScrn->pScreen->GetScreenPixmap)(pScrn->pScreen), pScrn->pScreen->width,
-		    pScrn->pScreen->height, pScrn->pScreen->rootDepth, pScrn->bitsPerPixel,
-		    PixmapBytePad(pScrn->displayWidth, pScrn->pScreen->rootDepth), 
-		    (pointer)(pI8301->FbBase + pScrn->fbOffset));
-
-   if (pI830->entityPrivate) {
-      if (I830IsPrimary(pScrn)) {
-         pScrn2->pScreen->ModifyPixmapHeader((*pScrn2->pScreen->GetScreenPixmap)(pScrn2->pScreen), pScrn2->pScreen->width,
-		    pScrn2->pScreen->height, pScrn2->pScreen->rootDepth, pScrn2->bitsPerPixel,
-		    PixmapBytePad(pScrn2->displayWidth, pScrn2->pScreen->rootDepth), 
-		    (pointer)(pI8301->FbBase + pScrn2->fbOffset));
-
-         /* Repaint the second head */
-         (*pScrn2->EnableDisableFBAccess) (pScrn2->pScreen->myNum, FALSE);
-         (*pScrn2->EnableDisableFBAccess) (pScrn2->pScreen->myNum, TRUE);
-      } else {
-         pScrn1->pScreen->ModifyPixmapHeader((*pScrn1->pScreen->GetScreenPixmap)(pScrn1->pScreen), pScrn1->pScreen->width,
-		    pScrn1->pScreen->height, pScrn1->pScreen->rootDepth, pScrn1->bitsPerPixel,
-		    PixmapBytePad(pScrn1->displayWidth, pScrn1->pScreen->rootDepth), 
-		    (pointer)(pI8301->FbBase + pScrn1->fbOffset));
-
-         /* Repaint the first head */
-         (*pScrn1->EnableDisableFBAccess) (pScrn1->pScreen->myNum, FALSE);
-         (*pScrn1->EnableDisableFBAccess) (pScrn1->pScreen->myNum, TRUE);
-      }
-   }
-
-   return FALSE;
-}
diff --git a/src/i830_xaa.c b/src/i830_xaa.c
index be1fb83..96b23fa 100644
--- a/src/i830_xaa.c
+++ b/src/i830_xaa.c
@@ -280,8 +280,6 @@ CheckTiling(ScrnInfoPtr pScrn)
    if (IS_I965G(pI830)) {
       if (pI830->bufferOffset == pScrn->fbOffset && pI830->front_tiled == FENCE_XMAJOR)
          tiled = 1;
-      if (pI830->bufferOffset == pI830->RotatedMem.Start && pI830->rotated_tiled == FENCE_XMAJOR)
-         tiled = 1;
       if (pI830->bufferOffset == pI830->BackBuffer.Start && pI830->back_tiled == FENCE_XMAJOR)
          tiled = 1;
       /* not really supported as it's always YMajor tiled */
diff --git a/src/rotation_sf0.g4a b/src/rotation_sf0.g4a
deleted file mode 100644
index 8c1398f..0000000
--- a/src/rotation_sf0.g4a
+++ /dev/null
@@ -1,17 +0,0 @@
-send (1) 0 g6<1>F g1.12<0,1,0>F math inv scalar mlen 1 rlen 1 { align1 };
-send (1) 0 g6.4<1>F g1.20<0,1,0>F math inv scalar mlen 1 rlen 1 { align1 };
-add (8) g7<1>F g4<8,8,1>F -g3<8,8,1>F { align1 };
-mul (1) g7<1>F g7<0,1,0>F g6<0,1,0>F { align1 };
-mul (1) g7.4<1>F g7.4<0,1,0>F g6.4<0,1,0>F { align1 };
-mov (8) m1<1>F g7<0,1,0>F { align1 };
-mov (8) m2<1>F g7.4<0,1,0>F { align1 };
-mov (8) m3<1>F g3<8,8,1>F { align1 };
-send (8) 0 null g0<8,8,1>F urb 0 transpose used complete mlen 4 rlen 0 { align1 EOT };
-nop;
-nop;
-nop;
-nop;
-nop;
-nop;
-nop;
-nop;
diff --git a/src/rotation_sf90.g4a b/src/rotation_sf90.g4a
deleted file mode 100644
index 2648dff..0000000
--- a/src/rotation_sf90.g4a
+++ /dev/null
@@ -1,17 +0,0 @@
-send (1) 0 g6<1>F g1.20<0,1,0>F math inv scalar mlen 1 rlen 1 { align1 };
-send (1) 0 g6.4<1>F g1.12<0,1,0>F math inv scalar mlen 1 rlen 1 { align1 };
-add (8) g7<1>F g4<8,8,1>F -g3<8,8,1>F { align1 };
-mul (1) g7<1>F g7<0,1,0>F g6<0,1,0>F { align1 };
-mul (1) g7.4<1>F g7.4<0,1,0>F g6.4<0,1,0>F { align1 };
-mov (8) m1<1>F g7<0,1,0>F { align1 };
-mov (8) m2<1>F g7.4<0,1,0>F { align1 };
-mov (8) m3<1>F g3<8,8,1>F { align1 };
-send (8) 0 null g0<8,8,1>F urb 0 transpose used complete mlen 4 rlen 0 { align1 EOT };
-nop;
-nop;
-nop;
-nop;
-nop;
-nop;
-nop;
-nop;
diff --git a/src/rotation_sf_prog0.h b/src/rotation_sf_prog0.h
deleted file mode 100644
index 830d176..0000000
--- a/src/rotation_sf_prog0.h
+++ /dev/null
@@ -1,17 +0,0 @@
-   { 0x00000031, 0x20c01fbd, 0x0000002c, 0x01110081 },
-   { 0x00000031, 0x20c41fbd, 0x00000034, 0x01110081 },
-   { 0x00600040, 0x20e077bd, 0x008d0080, 0x008d4060 },
-   { 0x00000041, 0x20e077bd, 0x000000e0, 0x000000c0 },
-   { 0x00000041, 0x20e477bd, 0x000000e4, 0x000000c4 },
-   { 0x00600001, 0x202003be, 0x000000e0, 0x00000000 },
-   { 0x00600001, 0x204003be, 0x000000e4, 0x00000000 },
-   { 0x00600001, 0x206003be, 0x008d0060, 0x00000000 },
-   { 0x00600031, 0x20001fbc, 0x008d0000, 0x8640c800 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
diff --git a/src/rotation_sf_prog90.h b/src/rotation_sf_prog90.h
deleted file mode 100644
index 2e94b8f..0000000
--- a/src/rotation_sf_prog90.h
+++ /dev/null
@@ -1,17 +0,0 @@
-   { 0x00000031, 0x20c01fbd, 0x00000034, 0x01110081 },
-   { 0x00000031, 0x20c41fbd, 0x0000002c, 0x01110081 },
-   { 0x00600040, 0x20e077bd, 0x008d0080, 0x008d4060 },
-   { 0x00000041, 0x20e077bd, 0x000000e0, 0x000000c0 },
-   { 0x00000041, 0x20e477bd, 0x000000e4, 0x000000c4 },
-   { 0x00600001, 0x202003be, 0x000000e0, 0x00000000 },
-   { 0x00600001, 0x204003be, 0x000000e4, 0x00000000 },
-   { 0x00600001, 0x206003be, 0x008d0060, 0x00000000 },
-   { 0x00600031, 0x20001fbc, 0x008d0000, 0x8640c800 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
diff --git a/src/rotation_wm0.g4a b/src/rotation_wm0.g4a
deleted file mode 100644
index fe09734..0000000
--- a/src/rotation_wm0.g4a
+++ /dev/null
@@ -1,123 +0,0 @@
-/* The initial payload of the thread is always g0.
- * WM_URB (incoming URB entries) is g3
- * X0_R is g4
- * X1_R is g5
- * Y0_R is g6
- * Y1_R is g7
- */
-
-    /* Set up the X/Y screen coordinates of the pixels in our 4 subspans.  Each
-     * subspan is a 2x2 rectangle, and the screen x/y of the upper left of each
-     * subspan are given in GRF register 1.2 through 1.5 (which, with the word
-     * addressing below, are 1.4 through 1.11).
-     *
-     * The result is WM_X*_R and WM_Y*R being:
-     *
-     * X0: {ss0.x, ss0.x+1, ss0.x,   ss0.x+1, ss1.x, ss1.x+1, ss1.x,   ss1.x+y}
-     * Y0: {ss0.y, ss0.y,   ss0.y+1, ss0.y+1, ss1.y, ss1.y,   ss1.y+1, ss1.y+1}
-     * X1: {ss2.x, ss2.x+1, ss2.x,   ss2.x+1, ss3.x, ss3.x+1, ss3.x,   ss3.x+y}
-     * Y1: {ss2.y, ss2.y,   ss2.y+1, ss2.y+1, ss3.y, ss3.y,   ss3.y+1, ss3.y+1}
-     */
-
-    /* Set up ss0.x coordinates*/
-mov (1) g4<1>F g1.8<0,1,0>UW { align1 };
-add (1) g4.4<1>F g1.8<0,1,0>UW 1UB { align1 };
-mov (1) g4.8<1>F g1.8<0,1,0>UW { align1 };
-add (1) g4.12<1>F g1.8<0,1,0>UW 1UB { align1 };
-    /* Set up ss0.y coordinates */
-mov (1) g6<1>F g1.10<0,1,0>UW { align1 };
-mov (1) g6.4<1>F g1.10<0,1,0>UW { align1 };
-add (1) g6.8<1>F g1.10<0,1,0>UW 1UB { align1 };
-add (1) g6.12<1>F g1.10<0,1,0>UW 1UB { align1 };
-    /* set up ss1.x coordinates */
-mov (1) g4.16<1>F g1.12<0,1,0>UW { align1 };
-add (1) g4.20<1>F g1.12<0,1,0>UW 1UB { align1 };
-mov (1) g4.24<1>F g1.12<0,1,0>UW { align1 };
-add (1) g4.28<1>F g1.12<0,1,0>UW 1UB { align1 };
-    /* set up ss1.y coordinates */
-mov (1) g6.16<1>F g1.14<0,1,0>UW { align1 };
-mov (1) g6.20<1>F g1.14<0,1,0>UW { align1 };
-add (1) g6.24<1>F g1.14<0,1,0>UW 1UB { align1 };
-add (1) g6.28<1>F g1.14<0,1,0>UW 1UB { align1 };
-    /* Set up ss2.x coordinates */
-mov (1) g5<1>F g1.16<0,1,0>UW { align1 };
-add (1) g5.4<1>F g1.16<0,1,0>UW 1UB { align1 };
-mov (1) g5.8<1>F g1.16<0,1,0>UW { align1 };
-add (1) g5.12<1>F g1.16<0,1,0>UW 1UB { align1 };
-    /* Set up ss2.y coordinates */
-mov (1) g7<1>F g1.18<0,1,0>UW { align1 };
-mov (1) g7.4<1>F g1.18<0,1,0>UW { align1 };
-add (1) g7.8<1>F g1.18<0,1,0>UW 1UB { align1 };
-add (1) g7.12<1>F g1.18<0,1,0>UW 1UB { align1 };
-    /* Set up ss3.x coordinates */
-mov (1) g5.16<1>F g1.20<0,1,0>UW { align1 };
-add (1) g5.20<1>F g1.20<0,1,0>UW 1UB { align1 };
-mov (1) g5.24<1>F g1.20<0,1,0>UW { align1 };
-add (1) g5.28<1>F g1.20<0,1,0>UW 1UB { align1 };
-    /* Set up ss3.y coordinates */
-mov (1) g7.16<1>F g1.22<0,1,0>UW { align1 };
-mov (1) g7.20<1>F g1.22<0,1,0>UW { align1 };
-add (1) g7.24<1>F g1.22<0,1,0>UW 1UB { align1 };
-add (1) g7.28<1>F g1.22<0,1,0>UW 1UB { align1 };
-
-    /* Now, map these screen space coordinates into texture coordinates. */
-    /* subtract screen-space X origin of vertex 0. */
-add (8) g4<1>F g4<8,8,1>F -g1<0,1,0>F { align1 };
-add (8) g5<1>F g5<8,8,1>F -g1<0,1,0>F { align1 };
-    /* scale by texture X increment */
-mul (8) g4<1>F g4<8,8,1>F g3<0,1,0>F { align1 };
-mul (8) g5<1>F g5<8,8,1>F g3<0,1,0>F { align1 };
-    /* add in texture X offset */
-add (8) g4<1>F g4<8,8,1>F g3.12<0,1,0>F { align1 };
-add (8) g5<1>F g5<8,8,1>F g3.12<0,1,0>F { align1 };
-    /* subtract screen-space Y origin of vertex 0. */
-add (8) g6<1>F g6<8,8,1>F -g1.4<0,1,0>F { align1 };
-add (8) g7<1>F g7<8,8,1>F -g1.4<0,1,0>F { align1 };
-    /* scale by texture Y increment */
-    /* XXX: double check the fields in Cx,Cy,Co and attributes*/
-mul (8) g6<1>F g6<8,8,1>F g3.20<0,1,0>F { align1 };
-mul (8) g7<1>F g7<8,8,1>F g3.20<0,1,0>F { align1 };
-    /* add in texture Y offset */
-add (8) g6<1>F g6<8,8,1>F g3.28<0,1,0>F { align1 };
-add (8) g7<1>F g7<8,8,1>F g3.28<0,1,0>F { align1 };
-    /* sampler  */
-mov (8) m1<1>F g4<8,8,1>F { align1 };
-mov (8) m2<1>F g5<8,8,1>F { align1 };
-mov (8) m3<1>F g6<8,8,1>F { align1 };
-mov (8) m4<1>F g7<8,8,1>F { align1 };
-
-    /*
-     * g0 holds the PS thread payload, which (oddly) contains
-     * precisely what the sampler wants to see in m0
-     */
-send  (16) 0 g12<1>UW g0<8,8,1>UW sampler (1,0,F) mlen 5 rlen 8 { align1 };
-mov (8) g19<1>UD g19<8,8,1>UD { align1 };
-
-mov (8) m2<1>F g12<8,8,1>F { align1 };
-mov (8) m3<1>F g14<8,8,1>F { align1 };
-mov (8) m4<1>F g16<8,8,1>F { align1 };
-mov (8) m5<1>F g18<8,8,1>F { align1 };
-mov (8) m6<1>F g13<8,8,1>F { align1 };
-mov (8) m7<1>F g15<8,8,1>F { align1 };
-mov (8) m8<1>F g17<8,8,1>F { align1 };
-mov (8) m9<1>F g19<8,8,1>F { align1 };
-
-   /* Pass through control information:
-    */
-mov (8) m1<1>UD g1<8,8,1>UD { align1 mask_disable };
-   /* Send framebuffer write message: XXX: acc0? */
-send (16) 0 acc0<1>UW g0<8,8,1>UW write (
-	0, /* binding table index 0 */
-	8, /* pixel scoreboard clear */
-	4, /* render target write */
-	0 /* no write commit message */
-	) mlen 10 rlen 0 { align1 EOT };
-   /* padding */
-nop;
-nop;
-nop;
-nop;
-nop;
-nop;
-nop;
-nop;
diff --git a/src/rotation_wm90.g4a b/src/rotation_wm90.g4a
deleted file mode 100644
index fd600bf..0000000
--- a/src/rotation_wm90.g4a
+++ /dev/null
@@ -1,127 +0,0 @@
-/* The initial payload of the thread is always g0.
- * WM_URB (incoming URB entries) is g3
- * X0_R is g4
- * X1_R is g5
- * Y0_R is g6
- * Y1_R is g7
- */
-
-    /* Set up the X/Y screen coordinates of the pixels in our 4 subspans.  Each
-     * subspan is a 2x2 rectangle, and the screen x/y of the upper left of each
-     * subspan are given in GRF register 1.2 through 1.5 (which, with the word
-     * addressing below, are 1.4 through 1.11).
-     *
-     * The result is WM_X*_R and WM_Y*R being:
-     *
-     * X0: {ss0.x, ss0.x+1, ss0.x,   ss0.x+1, ss1.x, ss1.x+1, ss1.x,   ss1.x+y}
-     * Y0: {ss0.y, ss0.y,   ss0.y+1, ss0.y+1, ss1.y, ss1.y,   ss1.y+1, ss1.y+1}
-     * X1: {ss2.x, ss2.x+1, ss2.x,   ss2.x+1, ss3.x, ss3.x+1, ss3.x,   ss3.x+y}
-     * Y1: {ss2.y, ss2.y,   ss2.y+1, ss2.y+1, ss3.y, ss3.y,   ss3.y+1, ss3.y+1}
-     */
-
-    /* Set up ss0.x coordinates*/
-mov (1) g4<1>F g1.8<0,1,0>UW { align1 };
-add (1) g4.4<1>F g1.8<0,1,0>UW 1UB { align1 };
-mov (1) g4.8<1>F g1.8<0,1,0>UW { align1 };
-add (1) g4.12<1>F g1.8<0,1,0>UW 1UB { align1 };
-    /* Set up ss0.y coordinates */
-mov (1) g6<1>F g1.10<0,1,0>UW { align1 };
-mov (1) g6.4<1>F g1.10<0,1,0>UW { align1 };
-add (1) g6.8<1>F g1.10<0,1,0>UW 1UB { align1 };
-add (1) g6.12<1>F g1.10<0,1,0>UW 1UB { align1 };
-    /* set up ss1.x coordinates */
-mov (1) g4.16<1>F g1.12<0,1,0>UW { align1 };
-add (1) g4.20<1>F g1.12<0,1,0>UW 1UB { align1 };
-mov (1) g4.24<1>F g1.12<0,1,0>UW { align1 };
-add (1) g4.28<1>F g1.12<0,1,0>UW 1UB { align1 };
-    /* set up ss1.y coordinates */
-mov (1) g6.16<1>F g1.14<0,1,0>UW { align1 };
-mov (1) g6.20<1>F g1.14<0,1,0>UW { align1 };
-add (1) g6.24<1>F g1.14<0,1,0>UW 1UB { align1 };
-add (1) g6.28<1>F g1.14<0,1,0>UW 1UB { align1 };
-    /* Set up ss2.x coordinates */
-mov (1) g5<1>F g1.16<0,1,0>UW { align1 };
-add (1) g5.4<1>F g1.16<0,1,0>UW 1UB { align1 };
-mov (1) g5.8<1>F g1.16<0,1,0>UW { align1 };
-add (1) g5.12<1>F g1.16<0,1,0>UW 1UB { align1 };
-    /* Set up ss2.y coordinates */
-mov (1) g7<1>F g1.18<0,1,0>UW { align1 };
-mov (1) g7.4<1>F g1.18<0,1,0>UW { align1 };
-add (1) g7.8<1>F g1.18<0,1,0>UW 1UB { align1 };
-add (1) g7.12<1>F g1.18<0,1,0>UW 1UB { align1 };
-    /* Set up ss3.x coordinates */
-mov (1) g5.16<1>F g1.20<0,1,0>UW { align1 };
-add (1) g5.20<1>F g1.20<0,1,0>UW 1UB { align1 };
-mov (1) g5.24<1>F g1.20<0,1,0>UW { align1 };
-add (1) g5.28<1>F g1.20<0,1,0>UW 1UB { align1 };
-    /* Set up ss3.y coordinates */
-mov (1) g7.16<1>F g1.22<0,1,0>UW { align1 };
-mov (1) g7.20<1>F g1.22<0,1,0>UW { align1 };
-add (1) g7.24<1>F g1.22<0,1,0>UW 1UB { align1 };
-add (1) g7.28<1>F g1.22<0,1,0>UW 1UB { align1 };
-
-    /* Now, map these screen space coordinates into texture coordinates. */
-/* XXX: convert it to calculate (u,v) in 90 and 270 case */
-    /* subtract screen-space Y origin of vertex 0. */
-add (8) g6<1>F g6<8,8,1>F -g1.4<0,1,0>F { align1 };
-add (8) g7<1>F g7<8,8,1>F -g1.4<0,1,0>F { align1 };
-
-/* (Yp - Ystart) * Cx */
-mul (8) g6<1>F g6<8,8,1>F g3<0,1,0>F { align1 };
-mul (8) g7<1>F g7<8,8,1>F g3<0,1,0>F { align1 };
-
-    /* scale by texture Y increment */
-add (8) g6<1>F g6<8,8,1>F g3.12<0,1,0>F { align1 };
-add (8) g7<1>F g7<8,8,1>F g3.12<0,1,0>F { align1 };
-
-    /* subtract screen-space X origin of vertex 0. */
-add (8) g4<1>F g4<8,8,1>F -g1<0,1,0>F { align1 };
-add (8) g5<1>F g5<8,8,1>F -g1<0,1,0>F { align1 };
-    /* scale by texture X increment */
-mul (8) g4<1>F g4<8,8,1>F g3.20<0,1,0>F { align1 };
-mul (8) g5<1>F g5<8,8,1>F g3.20<0,1,0>F { align1 };
-    /* add in texture X offset */
-add (8) g4<1>F g4<8,8,1>F g3.28<0,1,0>F { align1 };
-add (8) g5<1>F g5<8,8,1>F g3.28<0,1,0>F { align1 };
-
-    /* sampler  */
-mov (8) m1<1>F g6<8,8,1>F { align1 };
-mov (8) m2<1>F g7<8,8,1>F { align1 };
-mov (8) m3<1>F g4<8,8,1>F { align1 };
-mov (8) m4<1>F g5<8,8,1>F { align1 };
-
-    /*
-     * g0 holds the PS thread payload, which (oddly) contains
-     * precisely what the sampler wants to see in m0
-     */
-send  (16) 0 g12<1>UW g0<8,8,1>UW sampler (1,0,F) mlen 5 rlen 8 { align1 };
-mov (8) g19<1>UD g19<8,8,1>UD { align1 };
-
-mov (8) m2<1>F g12<8,8,1>F { align1 };
-mov (8) m3<1>F g14<8,8,1>F { align1 };
-mov (8) m4<1>F g16<8,8,1>F { align1 };
-mov (8) m5<1>F g18<8,8,1>F { align1 };
-mov (8) m6<1>F g13<8,8,1>F { align1 };
-mov (8) m7<1>F g15<8,8,1>F { align1 };
-mov (8) m8<1>F g17<8,8,1>F { align1 };
-mov (8) m9<1>F g19<8,8,1>F { align1 };
-
-   /* Pass through control information:
-    */
-mov (8) m1<1>UD g1<8,8,1>UD { align1 mask_disable };
-   /* Send framebuffer write message: XXX: acc0? */
-send (16) 0 acc0<1>UW g0<8,8,1>UW write (
-	0, /* binding table index 0 */
-	8, /* pixel scoreboard clear */
-	4, /* render target write */
-	0 /* no write commit message */
-	) mlen 10 rlen 0 { align1 EOT };
-   /* padding */
-nop;
-nop;
-nop;
-nop;
-nop;
-nop;
-nop;
-nop;
diff --git a/src/rotation_wm_prog0.h b/src/rotation_wm_prog0.h
deleted file mode 100644
index 08269b7..0000000
--- a/src/rotation_wm_prog0.h
+++ /dev/null
@@ -1,68 +0,0 @@
-   { 0x00000001, 0x2080013d, 0x00000028, 0x00000000 },
-   { 0x00000040, 0x20840d3d, 0x00000028, 0x00000001 },
-   { 0x00000001, 0x2088013d, 0x00000028, 0x00000000 },
-   { 0x00000040, 0x208c0d3d, 0x00000028, 0x00000001 },
-   { 0x00000001, 0x20c0013d, 0x0000002a, 0x00000000 },
-   { 0x00000001, 0x20c4013d, 0x0000002a, 0x00000000 },
-   { 0x00000040, 0x20c80d3d, 0x0000002a, 0x00000001 },
-   { 0x00000040, 0x20cc0d3d, 0x0000002a, 0x00000001 },
-   { 0x00000001, 0x2090013d, 0x0000002c, 0x00000000 },
-   { 0x00000040, 0x20940d3d, 0x0000002c, 0x00000001 },
-   { 0x00000001, 0x2098013d, 0x0000002c, 0x00000000 },
-   { 0x00000040, 0x209c0d3d, 0x0000002c, 0x00000001 },
-   { 0x00000001, 0x20d0013d, 0x0000002e, 0x00000000 },
-   { 0x00000001, 0x20d4013d, 0x0000002e, 0x00000000 },
-   { 0x00000040, 0x20d80d3d, 0x0000002e, 0x00000001 },
-   { 0x00000040, 0x20dc0d3d, 0x0000002e, 0x00000001 },
-   { 0x00000001, 0x20a0013d, 0x00000030, 0x00000000 },
-   { 0x00000040, 0x20a40d3d, 0x00000030, 0x00000001 },
-   { 0x00000001, 0x20a8013d, 0x00000030, 0x00000000 },
-   { 0x00000040, 0x20ac0d3d, 0x00000030, 0x00000001 },
-   { 0x00000001, 0x20e0013d, 0x00000032, 0x00000000 },
-   { 0x00000001, 0x20e4013d, 0x00000032, 0x00000000 },
-   { 0x00000040, 0x20e80d3d, 0x00000032, 0x00000001 },
-   { 0x00000040, 0x20ec0d3d, 0x00000032, 0x00000001 },
-   { 0x00000001, 0x20b0013d, 0x00000034, 0x00000000 },
-   { 0x00000040, 0x20b40d3d, 0x00000034, 0x00000001 },
-   { 0x00000001, 0x20b8013d, 0x00000034, 0x00000000 },
-   { 0x00000040, 0x20bc0d3d, 0x00000034, 0x00000001 },
-   { 0x00000001, 0x20f0013d, 0x00000036, 0x00000000 },
-   { 0x00000001, 0x20f4013d, 0x00000036, 0x00000000 },
-   { 0x00000040, 0x20f80d3d, 0x00000036, 0x00000001 },
-   { 0x00000040, 0x20fc0d3d, 0x00000036, 0x00000001 },
-   { 0x00600040, 0x208077bd, 0x008d0080, 0x00004020 },
-   { 0x00600040, 0x20a077bd, 0x008d00a0, 0x00004020 },
-   { 0x00600041, 0x208077bd, 0x008d0080, 0x00000060 },
-   { 0x00600041, 0x20a077bd, 0x008d00a0, 0x00000060 },
-   { 0x00600040, 0x208077bd, 0x008d0080, 0x0000006c },
-   { 0x00600040, 0x20a077bd, 0x008d00a0, 0x0000006c },
-   { 0x00600040, 0x20c077bd, 0x008d00c0, 0x00004024 },
-   { 0x00600040, 0x20e077bd, 0x008d00e0, 0x00004024 },
-   { 0x00600041, 0x20c077bd, 0x008d00c0, 0x00000074 },
-   { 0x00600041, 0x20e077bd, 0x008d00e0, 0x00000074 },
-   { 0x00600040, 0x20c077bd, 0x008d00c0, 0x0000007c },
-   { 0x00600040, 0x20e077bd, 0x008d00e0, 0x0000007c },
-   { 0x00600001, 0x202003be, 0x008d0080, 0x00000000 },
-   { 0x00600001, 0x204003be, 0x008d00a0, 0x00000000 },
-   { 0x00600001, 0x206003be, 0x008d00c0, 0x00000000 },
-   { 0x00600001, 0x208003be, 0x008d00e0, 0x00000000 },
-   { 0x00800031, 0x21801d29, 0x008d0000, 0x02580001 },
-   { 0x00600001, 0x22600021, 0x008d0260, 0x00000000 },
-   { 0x00600001, 0x204003be, 0x008d0180, 0x00000000 },
-   { 0x00600001, 0x206003be, 0x008d01c0, 0x00000000 },
-   { 0x00600001, 0x208003be, 0x008d0200, 0x00000000 },
-   { 0x00600001, 0x20a003be, 0x008d0240, 0x00000000 },
-   { 0x00600001, 0x20c003be, 0x008d01a0, 0x00000000 },
-   { 0x00600001, 0x20e003be, 0x008d01e0, 0x00000000 },
-   { 0x00600001, 0x210003be, 0x008d0220, 0x00000000 },
-   { 0x00600001, 0x212003be, 0x008d0260, 0x00000000 },
-   { 0x00600201, 0x20200022, 0x008d0020, 0x00000000 },
-   { 0x00800031, 0x24001d28, 0x008d0000, 0x85a04800 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
diff --git a/src/rotation_wm_prog90.h b/src/rotation_wm_prog90.h
deleted file mode 100644
index 9b87750..0000000
--- a/src/rotation_wm_prog90.h
+++ /dev/null
@@ -1,68 +0,0 @@
-   { 0x00000001, 0x2080013d, 0x00000028, 0x00000000 },
-   { 0x00000040, 0x20840d3d, 0x00000028, 0x00000001 },
-   { 0x00000001, 0x2088013d, 0x00000028, 0x00000000 },
-   { 0x00000040, 0x208c0d3d, 0x00000028, 0x00000001 },
-   { 0x00000001, 0x20c0013d, 0x0000002a, 0x00000000 },
-   { 0x00000001, 0x20c4013d, 0x0000002a, 0x00000000 },
-   { 0x00000040, 0x20c80d3d, 0x0000002a, 0x00000001 },
-   { 0x00000040, 0x20cc0d3d, 0x0000002a, 0x00000001 },
-   { 0x00000001, 0x2090013d, 0x0000002c, 0x00000000 },
-   { 0x00000040, 0x20940d3d, 0x0000002c, 0x00000001 },
-   { 0x00000001, 0x2098013d, 0x0000002c, 0x00000000 },
-   { 0x00000040, 0x209c0d3d, 0x0000002c, 0x00000001 },
-   { 0x00000001, 0x20d0013d, 0x0000002e, 0x00000000 },
-   { 0x00000001, 0x20d4013d, 0x0000002e, 0x00000000 },
-   { 0x00000040, 0x20d80d3d, 0x0000002e, 0x00000001 },
-   { 0x00000040, 0x20dc0d3d, 0x0000002e, 0x00000001 },
-   { 0x00000001, 0x20a0013d, 0x00000030, 0x00000000 },
-   { 0x00000040, 0x20a40d3d, 0x00000030, 0x00000001 },
-   { 0x00000001, 0x20a8013d, 0x00000030, 0x00000000 },
-   { 0x00000040, 0x20ac0d3d, 0x00000030, 0x00000001 },
-   { 0x00000001, 0x20e0013d, 0x00000032, 0x00000000 },
-   { 0x00000001, 0x20e4013d, 0x00000032, 0x00000000 },
-   { 0x00000040, 0x20e80d3d, 0x00000032, 0x00000001 },
-   { 0x00000040, 0x20ec0d3d, 0x00000032, 0x00000001 },
-   { 0x00000001, 0x20b0013d, 0x00000034, 0x00000000 },
-   { 0x00000040, 0x20b40d3d, 0x00000034, 0x00000001 },
-   { 0x00000001, 0x20b8013d, 0x00000034, 0x00000000 },
-   { 0x00000040, 0x20bc0d3d, 0x00000034, 0x00000001 },
-   { 0x00000001, 0x20f0013d, 0x00000036, 0x00000000 },
-   { 0x00000001, 0x20f4013d, 0x00000036, 0x00000000 },
-   { 0x00000040, 0x20f80d3d, 0x00000036, 0x00000001 },
-   { 0x00000040, 0x20fc0d3d, 0x00000036, 0x00000001 },
-   { 0x00600040, 0x20c077bd, 0x008d00c0, 0x00004024 },
-   { 0x00600040, 0x20e077bd, 0x008d00e0, 0x00004024 },
-   { 0x00600041, 0x20c077bd, 0x008d00c0, 0x00000060 },
-   { 0x00600041, 0x20e077bd, 0x008d00e0, 0x00000060 },
-   { 0x00600040, 0x20c077bd, 0x008d00c0, 0x0000006c },
-   { 0x00600040, 0x20e077bd, 0x008d00e0, 0x0000006c },
-   { 0x00600040, 0x208077bd, 0x008d0080, 0x00004020 },
-   { 0x00600040, 0x20a077bd, 0x008d00a0, 0x00004020 },
-   { 0x00600041, 0x208077bd, 0x008d0080, 0x00000074 },
-   { 0x00600041, 0x20a077bd, 0x008d00a0, 0x00000074 },
-   { 0x00600040, 0x208077bd, 0x008d0080, 0x0000007c },
-   { 0x00600040, 0x20a077bd, 0x008d00a0, 0x0000007c },
-   { 0x00600001, 0x202003be, 0x008d00c0, 0x00000000 },
-   { 0x00600001, 0x204003be, 0x008d00e0, 0x00000000 },
-   { 0x00600001, 0x206003be, 0x008d0080, 0x00000000 },
-   { 0x00600001, 0x208003be, 0x008d00a0, 0x00000000 },
-   { 0x00800031, 0x21801d29, 0x008d0000, 0x02580001 },
-   { 0x00600001, 0x22600021, 0x008d0260, 0x00000000 },
-   { 0x00600001, 0x204003be, 0x008d0180, 0x00000000 },
-   { 0x00600001, 0x206003be, 0x008d01c0, 0x00000000 },
-   { 0x00600001, 0x208003be, 0x008d0200, 0x00000000 },
-   { 0x00600001, 0x20a003be, 0x008d0240, 0x00000000 },
-   { 0x00600001, 0x20c003be, 0x008d01a0, 0x00000000 },
-   { 0x00600001, 0x20e003be, 0x008d01e0, 0x00000000 },
-   { 0x00600001, 0x210003be, 0x008d0220, 0x00000000 },
-   { 0x00600001, 0x212003be, 0x008d0260, 0x00000000 },
-   { 0x00600201, 0x20200022, 0x008d0020, 0x00000000 },
-   { 0x00800031, 0x24001d28, 0x008d0000, 0x85a04800 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
diff-tree e62751db8b1a631c22ba0f77c932be4ab39ba741 (from 4cd552e8f4851e029e43bf778cd8340f6c2c4881)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Jan 31 12:15:38 2007 -0800

    Add an accelerated path for rotation Render operations in XAA.
    
    The now-generic (kind of) EXA code will be cleaned up and moved to generic
    files in a later commit.

diff --git a/src/i830.h b/src/i830.h
index 66cfba1..58e4ec3 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -365,6 +365,18 @@ typedef struct _I830Rec {
    Bool cursorOn;
 #ifdef I830_USE_XAA
    XAAInfoRecPtr AccelInfoRec;
+
+   /* additional XAA accelerated Composite support */
+   CompositeProcPtr saved_composite;
+   Bool (*xaa_check_composite)(int op, PicturePtr pSrc, PicturePtr pMask,
+			       PicturePtr pDst);
+   Bool (*xaa_prepare_composite)(int op, PicturePtr pSrc, PicturePtr pMask,
+				 PicturePtr pDst, PixmapPtr pSrcPixmap,
+				 PixmapPtr pMaskPixmap, PixmapPtr pDstPixmap);
+   void (*xaa_composite)(PixmapPtr pDst, int xSrc, int ySrc,
+			 int xMask, int yMask, int xDst, int yDst,
+			 int w, int h);
+   void (*xaa_done_composite)(PixmapPtr pDst);
 #endif
    xf86CursorInfoPtr CursorInfoRec;
    CloseScreenProcPtr CloseScreen;
@@ -560,6 +572,8 @@ extern Bool I830DRILock(ScrnInfoPtr pScr
 extern Bool I830DRISetVBlankInterrupt (ScrnInfoPtr pScrn, Bool on);
 #endif
 
+unsigned long intel_get_pixmap_offset(PixmapPtr pPix);
+unsigned long intel_get_pixmap_pitch(PixmapPtr pPix);
 extern Bool I830AccelInit(ScreenPtr pScreen);
 extern void I830SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir,
 					   int ydir, int rop,
@@ -634,7 +648,6 @@ DisplayModePtr i830_ddc_get_modes(xf86Ou
 /* i830_tv.c */
 void i830_tv_init(ScrnInfoPtr pScrn);
 
-#ifdef I830_USE_EXA
 extern Bool I830EXACheckComposite(int, PicturePtr, PicturePtr, PicturePtr);
 extern Bool I830EXAPrepareComposite(int, PicturePtr, PicturePtr, PicturePtr, 
 				PixmapPtr, PixmapPtr, PixmapPtr);
@@ -647,6 +660,9 @@ extern Bool I965EXAPrepareComposite(int,
 				PixmapPtr, PixmapPtr, PixmapPtr);
 extern void I965EXAComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, 
 			int maskY, int dstX, int dstY, int width, int height);
+void IntelEXAComposite(PixmapPtr pDst, int srcX, int srcY,
+		       int maskX, int maskY, int dstX, int dstY, int w, int h);
+void IntelEXADoneComposite(PixmapPtr pDst);
 
 extern Bool
 I830EXACheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
@@ -663,7 +679,7 @@ i830_get_transformed_coordinates(int x, 
 
 extern const int I830PatternROP[16];
 extern const int I830CopyROP[16];
-#endif
+
 /* Flags for memory allocation function */
 #define FROM_ANYWHERE			0x00000000
 #define FROM_POOL_ONLY			0x00000001
diff --git a/src/i830_accel.c b/src/i830_accel.c
index 5fdd101..db3168a 100644
--- a/src/i830_accel.c
+++ b/src/i830_accel.c
@@ -60,6 +60,36 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "i810_reg.h"
 #include "i830_debug.h"
 
+unsigned long
+intel_get_pixmap_offset(PixmapPtr pPix)
+{
+    ScreenPtr pScreen = pPix->drawable.pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+
+#ifdef I830_USE_EXA
+    if (pI830->useEXA)
+	return exaGetPixmapOffset(pPix);
+#endif
+    return (unsigned long)pPix->devPrivate.ptr - (unsigned long)pI830->FbBase;
+}
+
+unsigned long
+intel_get_pixmap_pitch(PixmapPtr pPix)
+{
+    ScreenPtr pScreen = pPix->drawable.pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+
+#ifdef I830_USE_EXA
+    if (pI830->useEXA)
+	return exaGetPixmapPitch(pPix);
+#endif
+#ifdef I830_USE_XAA
+    return (unsigned long)pPix->devKind;
+#endif
+}
+
 int
 I830WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis)
 {
diff --git a/src/i830_exa.c b/src/i830_exa.c
index b0d886b..02d2dcf 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -314,7 +314,7 @@ i830_get_transformed_coordinates(int x, 
  *
  * This function is shared between i830 and i915 generation code.
  */
-static void
+void
 IntelEXAComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
 		 int dstX, int dstY, int w, int h)
 {
@@ -396,7 +396,7 @@ IntelEXAComposite(PixmapPtr pDst, int sr
     }
 }
 
-static void
+void
 IntelEXADoneComposite(PixmapPtr pDst)
 {
 #if ALWAYS_SYNC
diff --git a/src/i830_exa_render.c b/src/i830_exa_render.c
index 98a444f..bf521b4 100644
--- a/src/i830_exa_render.c
+++ b/src/i830_exa_render.c
@@ -256,8 +256,8 @@ I830TextureSetup(PicturePtr pPict, Pixma
     int w, h, i;
     CARD32 wrap_mode = TEXCOORDMODE_CLAMP; 
 
-    offset = exaGetPixmapOffset(pPix);
-    pitch = exaGetPixmapPitch(pPix);
+    offset = intel_get_pixmap_offset(pPix);
+    pitch = intel_get_pixmap_pitch(pPix);
     w = pPict->pDrawable->width;
     h = pPict->pDrawable->height;
     pI830->scale_units[unit][0] = pPix->drawable.width;
@@ -381,8 +381,8 @@ I830EXAPrepareComposite(int op, PictureP
     CARD32 dst_format, dst_offset, dst_pitch;
 
     I830GetDestFormat(pDstPicture, &dst_format);
-    dst_offset = exaGetPixmapOffset(pDst);
-    dst_pitch = exaGetPixmapPitch(pDst);
+    dst_offset = intel_get_pixmap_offset(pDst);
+    dst_pitch = intel_get_pixmap_pitch(pDst);
 
     pI830->last_3d = LAST_3D_RENDER;
 
diff --git a/src/i830_xaa.c b/src/i830_xaa.c
index 13ba743..be1fb83 100644
--- a/src/i830_xaa.c
+++ b/src/i830_xaa.c
@@ -52,6 +52,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "xaarop.h"
 #include "i830.h"
 #include "i810_reg.h"
+#include "mipict.h"
 
 #ifndef DO_SCANLINE_IMAGE_WRITE
 #define DO_SCANLINE_IMAGE_WRITE 0
@@ -91,11 +92,26 @@ static void I830SubsequentImageWriteScan
 #endif
 static void I830RestoreAccelState(ScrnInfoPtr pScrn);
 
+void
+i830_xaa_composite(CARD8	op,
+		   PicturePtr	pSrc,
+		   PicturePtr	pMask,
+		   PicturePtr	pDst,
+		   INT16	xSrc,
+		   INT16	ySrc,
+		   INT16	xMask,
+		   INT16	yMask,
+		   INT16	xDst,
+		   INT16	yDst,
+		   CARD16	width,
+		   CARD16	height);
+
 Bool
 I830XAAInit(ScreenPtr pScreen)
 {
     XAAInfoRecPtr infoPtr;
     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
     I830Ptr pI830 = I830PTR(pScrn);
     int i;
     int width = 0;
@@ -220,7 +236,37 @@ I830XAAInit(ScreenPtr pScreen)
 
     I830SelectBuffer(pScrn, I830_SELECT_FRONT);
 
-    return XAAInit(pScreen, infoPtr);
+    if (!XAAInit(pScreen, infoPtr))
+	return FALSE;
+
+    if (ps != NULL) {
+	if (IS_I915G(pI830) || IS_I915GM(pI830) ||
+	    IS_I945G(pI830) || IS_I945GM(pI830))
+	{
+	    pI830->xaa_check_composite = I915EXACheckComposite;
+	    pI830->xaa_prepare_composite = I915EXAPrepareComposite;
+	    pI830->xaa_composite = IntelEXAComposite;
+	    pI830->xaa_done_composite = IntelEXADoneComposite;
+	} else if (IS_I865G(pI830) || IS_I855(pI830) ||
+		   IS_845G(pI830) || IS_I830(pI830)) {
+	    pI830->xaa_check_composite = I830EXACheckComposite;
+	    pI830->xaa_prepare_composite = I830EXAPrepareComposite;
+	    pI830->xaa_composite = IntelEXAComposite;
+	    pI830->xaa_done_composite = IntelEXADoneComposite;
+	} else if (IS_I965G(pI830)) {
+	    pI830->xaa_check_composite = I965EXACheckComposite;
+	    pI830->xaa_prepare_composite = I965EXAPrepareComposite;
+	    pI830->xaa_composite = I965EXAComposite;
+	    pI830->xaa_done_composite = IntelEXADoneComposite;
+	} else {
+	    return TRUE;
+	}
+
+	pI830->saved_composite = ps->Composite;
+	ps->Composite = i830_xaa_composite;
+    }
+
+    return TRUE;
 }
 
 #ifdef XF86DRI
@@ -694,6 +740,126 @@ I830SubsequentImageWriteScanline(ScrnInf
 #endif /* DO_SCANLINE_IMAGE_WRITE */
 /* Support for multiscreen */
 
+/**
+ * Special case acceleration for Render acceleration of rotation operations
+ * by xf86Rotate.c
+ */
+void
+i830_xaa_composite(CARD8	op,
+		   PicturePtr	pSrc,
+		   PicturePtr	pMask,
+		   PicturePtr	pDst,
+		   INT16	xSrc,
+		   INT16	ySrc,
+		   INT16	xMask,
+		   INT16	yMask,
+		   INT16	xDst,
+		   INT16	yDst,
+		   CARD16	width,
+		   CARD16	height)
+{
+    ScreenPtr pScreen = pDst->pDrawable->pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    PictureScreenPtr ps;
+    PixmapPtr pSrcPixmap, pDstPixmap;
+    RegionRec region;
+    BoxPtr pbox;
+    int nbox;
+    int	i;
+
+    /* Throw out cases that aren't going to be our rotation first */
+    if (pMask != NULL || op != PictOpSrc || pSrc->pDrawable == NULL)
+	goto fallback;
+
+    if (pSrc->pDrawable->type != DRAWABLE_PIXMAP ||
+	pDst->pDrawable->type != DRAWABLE_PIXMAP)
+    {
+	goto fallback;
+    }
+    pSrcPixmap = (PixmapPtr)pSrc->pDrawable;
+    pDstPixmap = (PixmapPtr)pDst->pDrawable;
+
+    /* Check if the dest is one of our shadow pixmaps */
+    for (i = 0; i < xf86_config->num_crtc; i++) {
+	xf86CrtcPtr crtc = xf86_config->crtc[i];
+
+	if (crtc->rotatedPixmap == pDstPixmap)
+	    break;
+    }
+    if (i == xf86_config->num_crtc)
+	goto fallback;
+
+    if (pSrcPixmap != pScreen->GetScreenPixmap(pScreen))
+	goto fallback;
+
+    /* OK, so we've got a Render operation on one of our shadow pixmaps, with
+     * the source being the real framebuffer.  We know that both of these are
+     * in framebuffer, with no x/y offsets, i.e. normal pixmaps like our EXA-
+     * based Render acceleration code expects.
+     */
+    assert(pSrcPixmap->drawable.x == 0);
+    assert(pSrcPixmap->drawable.y == 0);
+    assert(pDstPixmap->drawable.x == 0);
+    assert(pDstPixmap->drawable.y == 0);
+
+    if (!miComputeCompositeRegion (&region, pSrc, NULL, pDst,
+				   xSrc, ySrc, 0, 0, xDst, yDst,
+				   width, height))
+	return;
+
+    if (!pI830->xaa_check_composite(op, pSrc, NULL, pDst)) {
+	REGION_UNINIT(pScreen, &region);
+	goto fallback;
+    }
+
+    if (!pI830->xaa_prepare_composite(op, pSrc, NULL, pDst,
+				      pSrcPixmap, NULL, pDstPixmap))
+    {
+	REGION_UNINIT(pScreen, &region);
+	goto fallback;
+    }
+
+    nbox = REGION_NUM_RECTS(&region);
+    pbox = REGION_RECTS(&region);
+
+    xSrc -= xDst;
+    ySrc -= yDst;
+
+    while (nbox--)
+    {
+	pI830->xaa_composite(pDstPixmap,
+			     pbox->x1 + xSrc,
+			     pbox->y1 + ySrc,
+			     0, 0,
+			     pbox->x1,
+			     pbox->y1,
+			     pbox->x2 - pbox->x1,
+			     pbox->y2 - pbox->y1);
+	pbox++;
+    }
+
+    REGION_UNINIT(pDst->pDrawable->pScreen, &region);
+
+    pI830->xaa_done_composite(pDstPixmap);
+    i830MarkSync(pScrn);
+
+    return;
+
+fallback:
+    /* Fallback path: Call down to the next level (XAA) */
+    ps = GetPictureScreenIfSet(pScreen);
+
+    ps->Composite = pI830->saved_composite;
+
+    ps->Composite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst,
+		  width, height);
+
+    pI830->saved_composite = ps->Composite;
+    ps->Composite = i830_xaa_composite;
+}
+
 static void
 I830RestoreAccelState(ScrnInfoPtr pScrn)
 {
diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
index 8705c6d..2fb41ad 100644
--- a/src/i915_exa_render.c
+++ b/src/i915_exa_render.c
@@ -248,8 +248,8 @@ I915TextureSetup(PicturePtr pPict, Pixma
     int w, h, i;
     CARD32 wrap_mode = TEXCOORDMODE_CLAMP_BORDER;
 
-    offset = exaGetPixmapOffset(pPix);
-    pitch = exaGetPixmapPitch(pPix);
+    offset = intel_get_pixmap_offset(pPix);
+    pitch = intel_get_pixmap_pitch(pPix);
     w = pPict->pDrawable->width;
     h = pPict->pDrawable->height;
     pI830->scale_units[unit][0] = pPix->drawable.width;
@@ -318,8 +318,8 @@ I915EXAPrepareComposite(int op, PictureP
     pI830->last_3d = LAST_3D_RENDER;
 
     I915GetDestFormat(pDstPicture, &dst_format);
-    dst_offset = exaGetPixmapOffset(pDst);
-    dst_pitch = exaGetPixmapPitch(pDst);
+    dst_offset = intel_get_pixmap_offset(pDst);
+    dst_pitch = intel_get_pixmap_pitch(pDst);
     FS_LOCALS(20);
 
     if (!I915TextureSetup(pSrcPicture, pSrc, 0))
diff --git a/src/i965_exa_render.c b/src/i965_exa_render.c
index 1dbccc6..99bd628 100644
--- a/src/i965_exa_render.c
+++ b/src/i965_exa_render.c
@@ -379,13 +379,13 @@ I965EXAPrepareComposite(int op, PictureP
 
     pI830->last_3d = LAST_3D_RENDER;
 
-    src_offset = exaGetPixmapOffset(pSrc);
-    src_pitch = exaGetPixmapPitch(pSrc);
-    dst_offset = exaGetPixmapOffset(pDst);
-    dst_pitch = exaGetPixmapPitch(pDst);
+    src_offset = intel_get_pixmap_offset(pSrc);
+    src_pitch = intel_get_pixmap_pitch(pSrc);
+    dst_offset = intel_get_pixmap_offset(pDst);
+    dst_pitch = intel_get_pixmap_pitch(pDst);
     if (pMask) {
-	mask_offset = exaGetPixmapOffset(pMask);
-	mask_pitch = exaGetPixmapPitch(pMask);
+	mask_offset = intel_get_pixmap_offset(pMask);
+	mask_pitch = intel_get_pixmap_pitch(pMask);
     }
     pI830->scale_units[0][0] = pSrc->drawable.width;
     pI830->scale_units[0][1] = pSrc->drawable.height;
diff-tree 4cd552e8f4851e029e43bf778cd8340f6c2c4881 (from 6a628ae12b0568d656059891c5bca4415d8a735f)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Jan 30 16:34:50 2007 -0800

    Fix accelerated Render transformations.
    
    Previously, we tried to use 2 points instead of 3 to describe the source
    rectangles, which mostly just worked for scaling.

diff --git a/src/i830.h b/src/i830.h
index d9dae5b..66cfba1 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -657,6 +657,10 @@ I830EXAPrepareComposite(int op, PictureP
 			PicturePtr pMaskPicture, PicturePtr pDstPicture,
 			PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst);
 
+void
+i830_get_transformed_coordinates(int x, int y, PictTransformPtr transform,
+				 float *x_out, float *y_out);
+
 extern const int I830PatternROP[16];
 extern const int I830CopyROP[16];
 #endif
diff --git a/src/i830_exa.c b/src/i830_exa.c
index b976f54..b0d886b 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -282,69 +282,76 @@ I830EXADoneCopy(PixmapPtr pDstPixmap)
 #endif
 }
 
+#define xFixedToFloat(val) \
+	((float)xFixedToInt(val) + ((float)xFixedFrac(val) / 65536.0))
+
+/**
+ * Returns the floating-point coordinates transformed by the given transform.
+ *
+ * transform may be null.
+ */
+void
+i830_get_transformed_coordinates(int x, int y, PictTransformPtr transform,
+				 float *x_out, float *y_out)
+{
+    if (transform == NULL) {
+	*x_out = x;
+	*y_out = y;
+    } else {
+	PictVector v;
+
+        v.vector[0] = IntToxFixed(x);
+        v.vector[1] = IntToxFixed(y);
+        v.vector[2] = xFixed1;
+        PictureTransformPoint(transform, &v);
+	*x_out = xFixedToFloat(v.vector[0]);
+	*y_out = xFixedToFloat(v.vector[1]);
+    }
+}
+
+/**
+ * Do a single rectangle composite operation.
+ *
+ * This function is shared between i830 and i915 generation code.
+ */
 static void
 IntelEXAComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
 		 int dstX, int dstY, int w, int h)
 {
     ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
-    int srcXend, srcYend, maskXend, maskYend;
-    PictVector v;
-    int pMask = 1;
-
-    DPRINTF(PFX, "Composite: srcX %d, srcY %d\n\t maskX %d, maskY %d\n\t"
-	    "dstX %d, dstY %d\n\twidth %d, height %d\n\t"
-	    "src_scale_x %f, src_scale_y %f, "
-	    "mask_scale_x %f, mask_scale_y %f\n",
-	    srcX, srcY, maskX, maskY, dstX, dstY, w, h,
-	    pI830->scale_units[0][0], pI830->scale_units[0][1],
-	    pI830->scale_units[1][0], pI830->scale_units[1][1]);
+    Bool has_mask;
+    float src_x[3], src_y[3], mask_x[3], mask_y[3];
+
+    i830_get_transformed_coordinates(srcX, srcY,
+				     pI830->transform[0],
+				     &src_x[0], &src_y[0]);
+    i830_get_transformed_coordinates(srcX, srcY + h,
+				     pI830->transform[0],
+				     &src_x[1], &src_y[1]);
+    i830_get_transformed_coordinates(srcX + w, srcY + h,
+				     pI830->transform[0],
+				     &src_x[2], &src_y[2]);
 
     if (pI830->scale_units[1][0] == -1 || pI830->scale_units[1][1] == -1) {
-	pMask = 0;
+	has_mask = FALSE;
+    } else {
+	has_mask = TRUE;
+	i830_get_transformed_coordinates(maskX, maskY,
+					 pI830->transform[1],
+					 &mask_x[0], &mask_y[0]);
+	i830_get_transformed_coordinates(maskX, maskY + h,
+					 pI830->transform[1],
+					 &mask_x[1], &mask_y[1]);
+	i830_get_transformed_coordinates(maskX + w, maskY + h,
+					 pI830->transform[1],
+					 &mask_x[2], &mask_y[2]);
     }
 
-    srcXend = srcX + w;
-    srcYend = srcY + h;
-    maskXend = maskX + w;
-    maskYend = maskY + h;
-    if (pI830->transform[0] != NULL) {
-        v.vector[0] = IntToxFixed(srcX);
-        v.vector[1] = IntToxFixed(srcY);
-        v.vector[2] = xFixed1;
-        PictureTransformPoint(pI830->transform[0], &v);
-        srcX = xFixedToInt(v.vector[0]);
-        srcY = xFixedToInt(v.vector[1]);
-        v.vector[0] = IntToxFixed(srcXend);
-        v.vector[1] = IntToxFixed(srcYend);
-        v.vector[2] = xFixed1;
-        PictureTransformPoint(pI830->transform[0], &v);
-        srcXend = xFixedToInt(v.vector[0]);
-        srcYend = xFixedToInt(v.vector[1]);
-    }
-    if (pI830->transform[1] != NULL) {
-        v.vector[0] = IntToxFixed(maskX);
-        v.vector[1] = IntToxFixed(maskY);
-        v.vector[2] = xFixed1;
-        PictureTransformPoint(pI830->transform[1], &v);
-        maskX = xFixedToInt(v.vector[0]);
-        maskY = xFixedToInt(v.vector[1]);
-        v.vector[0] = IntToxFixed(maskXend);
-        v.vector[1] = IntToxFixed(maskYend);
-        v.vector[2] = xFixed1;
-        PictureTransformPoint(pI830->transform[1], &v);
-        maskXend = xFixedToInt(v.vector[0]);
-        maskYend = xFixedToInt(v.vector[1]);
-    }
-    DPRINTF(PFX, "After transform: srcX %d, srcY %d,srcXend %d, srcYend %d\n\t"
-		"maskX %d, maskY %d, maskXend %d, maskYend %d\n\t"
-		"dstX %d, dstY %d\n", srcX, srcY, srcXend, srcYend,
-		maskX, maskY, maskXend, maskYend, dstX, dstY);
-
     {
 	int vertex_count; 
 
-	if (pMask)
+	if (has_mask)
 		vertex_count = 3*6;
 	else
 		vertex_count = 3*4;
@@ -361,29 +368,29 @@ IntelEXAComposite(PixmapPtr pDst, int sr
 
 	OUT_RING_F(dstX);
 	OUT_RING_F(dstY);
-	OUT_RING_F(srcX / pI830->scale_units[0][0]);
-	OUT_RING_F(srcY / pI830->scale_units[0][1]);
-	if (pMask) {
-		OUT_RING_F(maskX / pI830->scale_units[1][0]);
-		OUT_RING_F(maskY / pI830->scale_units[1][1]);
+	OUT_RING_F(src_x[0] / pI830->scale_units[0][0]);
+	OUT_RING_F(src_y[0] / pI830->scale_units[0][1]);
+	if (has_mask) {
+		OUT_RING_F(mask_x[0] / pI830->scale_units[1][0]);
+		OUT_RING_F(mask_y[0] / pI830->scale_units[1][1]);
 	}
 
 	OUT_RING_F(dstX);
 	OUT_RING_F(dstY + h);
-	OUT_RING_F(srcX / pI830->scale_units[0][0]);
-	OUT_RING_F(srcYend / pI830->scale_units[0][1]);
-	if (pMask) {
-		OUT_RING_F(maskX / pI830->scale_units[1][0]);
-		OUT_RING_F(maskYend / pI830->scale_units[1][1]);
+	OUT_RING_F(src_x[1] / pI830->scale_units[0][0]);
+	OUT_RING_F(src_y[1] / pI830->scale_units[0][1]);
+	if (has_mask) {
+		OUT_RING_F(mask_x[1] / pI830->scale_units[1][0]);
+		OUT_RING_F(mask_y[1] / pI830->scale_units[1][1]);
 	}
 
 	OUT_RING_F(dstX + w);
 	OUT_RING_F(dstY + h);
-	OUT_RING_F(srcXend / pI830->scale_units[0][0]);
-	OUT_RING_F(srcYend / pI830->scale_units[0][1]);
-	if (pMask) {
-		OUT_RING_F(maskXend / pI830->scale_units[1][0]);
-		OUT_RING_F(maskYend / pI830->scale_units[1][1]);
+	OUT_RING_F(src_x[2] / pI830->scale_units[0][0]);
+	OUT_RING_F(src_y[2] / pI830->scale_units[0][1]);
+	if (has_mask) {
+		OUT_RING_F(mask_x[2] / pI830->scale_units[1][0]);
+		OUT_RING_F(mask_y[2] / pI830->scale_units[1][1]);
 	}
 	ADVANCE_LP_RING();
     }
diff --git a/src/i965_exa_render.c b/src/i965_exa_render.c
index 3e62027..1dbccc6 100644
--- a/src/i965_exa_render.c
+++ b/src/i965_exa_render.c
@@ -975,60 +975,35 @@ I965EXAComposite(PixmapPtr pDst, int src
 {
     ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
-    int srcXend, srcYend, maskXend, maskYend;
-    PictVector v;
-    int pMask = 1, i;
-
-    DPRINTF(PFX, "Composite: srcX %d, srcY %d\n\t maskX %d, maskY %d\n\t"
-	    "dstX %d, dstY %d\n\twidth %d, height %d\n\t"
-	    "src_scale_x %f, src_scale_y %f, "
-	    "mask_scale_x %f, mask_scale_y %f\n",
-	    srcX, srcY, maskX, maskY, dstX, dstY, w, h,
-	    pI830->scale_units[0][0], pI830->scale_units[0][1],
-	    pI830->scale_units[1][0], pI830->scale_units[1][1]);
+    Bool has_mask;
+    float src_x[3], src_y[3], mask_x[3], mask_y[3];
+    int i;
+
+    i830_get_transformed_coordinates(srcX, srcY,
+				     pI830->transform[0],
+				     &src_x[0], &src_y[0]);
+    i830_get_transformed_coordinates(srcX, srcY + h,
+				     pI830->transform[0],
+				     &src_x[1], &src_y[1]);
+    i830_get_transformed_coordinates(srcX + w, srcY + h,
+				     pI830->transform[0],
+				     &src_x[2], &src_y[2]);
 
     if (pI830->scale_units[1][0] == -1 || pI830->scale_units[1][1] == -1) {
-	pMask = 0;
+	has_mask = FALSE;
+    } else {
+	has_mask = TRUE;
+	i830_get_transformed_coordinates(maskX, maskY,
+					 pI830->transform[1],
+					 &mask_x[0], &mask_y[0]);
+	i830_get_transformed_coordinates(maskX, maskY + h,
+					 pI830->transform[1],
+					 &mask_x[1], &mask_y[1]);
+	i830_get_transformed_coordinates(maskX + w, maskY + h,
+					 pI830->transform[1],
+					 &mask_x[2], &mask_y[2]);
     }
 
-    srcXend = srcX + w;
-    srcYend = srcY + h;
-    maskXend = maskX + w;
-    maskYend = maskY + h;
-    if (pI830->transform[0] != NULL) {
-        v.vector[0] = IntToxFixed(srcX);
-        v.vector[1] = IntToxFixed(srcY);
-        v.vector[2] = xFixed1;
-        PictureTransformPoint(pI830->transform[0], &v);
-        srcX = xFixedToInt(v.vector[0]);
-        srcY = xFixedToInt(v.vector[1]);
-        v.vector[0] = IntToxFixed(srcXend);
-        v.vector[1] = IntToxFixed(srcYend);
-        v.vector[2] = xFixed1;
-        PictureTransformPoint(pI830->transform[0], &v);
-        srcXend = xFixedToInt(v.vector[0]);
-        srcYend = xFixedToInt(v.vector[1]);
-    }
-    if (pI830->transform[1] != NULL) {
-        v.vector[0] = IntToxFixed(maskX);
-        v.vector[1] = IntToxFixed(maskY);
-        v.vector[2] = xFixed1;
-        PictureTransformPoint(pI830->transform[1], &v);
-        maskX = xFixedToInt(v.vector[0]);
-        maskY = xFixedToInt(v.vector[1]);
-        v.vector[0] = IntToxFixed(maskXend);
-        v.vector[1] = IntToxFixed(maskYend);
-        v.vector[2] = xFixed1;
-        PictureTransformPoint(pI830->transform[1], &v);
-        maskXend = xFixedToInt(v.vector[0]);
-        maskYend = xFixedToInt(v.vector[1]);
-    }
-
-    DPRINTF(PFX, "After transform: srcX %d, srcY %d,srcXend %d, srcYend %d\n\t"
-		"maskX %d, maskY %d, maskXend %d, maskYend %d\n\t"
-		"dstX %d, dstY %d\n", srcX, srcY, srcXend, srcYend,
-		maskX, maskY, maskXend, maskYend, dstX, dstY);
-
     /* Wait for any existing composite rectangles to land before we overwrite
      * the VB with the next one.
      */
@@ -1036,31 +1011,31 @@ I965EXAComposite(PixmapPtr pDst, int src
 
     i = 0;
     /* rect (x2,y2) */
-    vb[i++] = (float)(srcXend) / pI830->scale_units[0][0];
-    vb[i++] = (float)(srcYend) / pI830->scale_units[0][1];
-    if (pMask) {
-        vb[i++] = (float)maskXend / pI830->scale_units[1][0];
-        vb[i++] = (float)maskYend / pI830->scale_units[1][1];
+    vb[i++] = src_x[2] / pI830->scale_units[0][0];
+    vb[i++] = src_y[2] / pI830->scale_units[0][1];
+    if (has_mask) {
+        vb[i++] = mask_x[2] / pI830->scale_units[1][0];
+        vb[i++] = mask_y[2] / pI830->scale_units[1][1];
     }
     vb[i++] = (float)(dstX + w);
     vb[i++] = (float)(dstY + h);
 
     /* rect (x1,y2) */
-    vb[i++] = (float)(srcX)/ pI830->scale_units[0][0];
-    vb[i++] = (float)(srcYend)/ pI830->scale_units[0][1];
-    if (pMask) {
-        vb[i++] = (float)maskX / pI830->scale_units[1][0];
-        vb[i++] = (float)maskYend / pI830->scale_units[1][1];
+    vb[i++] = src_x[1] / pI830->scale_units[0][0];
+    vb[i++] = src_y[1] / pI830->scale_units[0][1];
+    if (has_mask) {
+        vb[i++] = mask_x[1] / pI830->scale_units[1][0];
+        vb[i++] = mask_y[1] / pI830->scale_units[1][1];
     }
     vb[i++] = (float)dstX;
     vb[i++] = (float)(dstY + h);
 
     /* rect (x1,y1) */
-    vb[i++] = (float)(srcX) / pI830->scale_units[0][0];
-    vb[i++] = (float)(srcY) / pI830->scale_units[0][1];
-    if (pMask) {
-        vb[i++] = (float)maskX / pI830->scale_units[1][0];
-        vb[i++] = (float)maskY / pI830->scale_units[1][1];
+    vb[i++] = src_x[0] / pI830->scale_units[0][0];
+    vb[i++] = src_y[0] / pI830->scale_units[0][1];
+    if (has_mask) {
+        vb[i++] = mask_x[0] / pI830->scale_units[1][0];
+        vb[i++] = mask_y[0] / pI830->scale_units[1][1];
     }
     vb[i++] = (float)dstX;
     vb[i++] = (float)dstY;
diff-tree 6a628ae12b0568d656059891c5bca4415d8a735f (from c8581254cb811f76aa6eae49d74489b543b3eb05)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Jan 30 14:19:05 2007 -0800

    Simplify EXA acceleration transform handling.

diff --git a/src/i830.h b/src/i830.h
index 9ffae94..d9dae5b 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -392,7 +392,7 @@ typedef struct _I830Rec {
 
    /* EXA render state */
    float scale_units[2][2];
-   Bool is_transform[2];
+  /** Transform pointers for src/mask, or NULL if identity */
    PictTransform *transform[2];
    /* i915 EXA render state */
    CARD32 mapstate[6];
diff --git a/src/i830_exa.c b/src/i830_exa.c
index 3fd5e4a..b976f54 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -308,7 +308,7 @@ IntelEXAComposite(PixmapPtr pDst, int sr
     srcYend = srcY + h;
     maskXend = maskX + w;
     maskYend = maskY + h;
-    if (pI830->is_transform[0]) {
+    if (pI830->transform[0] != NULL) {
         v.vector[0] = IntToxFixed(srcX);
         v.vector[1] = IntToxFixed(srcY);
         v.vector[2] = xFixed1;
@@ -322,7 +322,7 @@ IntelEXAComposite(PixmapPtr pDst, int sr
         srcXend = xFixedToInt(v.vector[0]);
         srcYend = xFixedToInt(v.vector[1]);
     }
-    if (pI830->is_transform[1]) {
+    if (pI830->transform[1] != NULL) {
         v.vector[0] = IntToxFixed(maskX);
         v.vector[1] = IntToxFixed(maskY);
         v.vector[2] = xFixed1;
diff --git a/src/i830_exa_render.c b/src/i830_exa_render.c
index ae4f95f..98a444f 100644
--- a/src/i830_exa_render.c
+++ b/src/i830_exa_render.c
@@ -328,13 +328,7 @@ I830TextureSetup(PicturePtr pPict, Pixma
 	ADVANCE_LP_RING();
     }
 
-	/* XXX */
-    if (pPict->transform != 0) {
-        pI830->is_transform[unit] = TRUE;
-        pI830->transform[unit] = pPict->transform;
-    } else {
-        pI830->is_transform[unit] = FALSE;
-    }
+    pI830->transform[unit] = pPict->transform;
 
 #ifdef I830DEBUG
     ErrorF("try to sync to show any errors...");
@@ -398,7 +392,7 @@ I830EXAPrepareComposite(int op, PictureP
 	if (!I830TextureSetup(pMaskPicture, pMask, 1))
 		I830FALLBACK("fail to setup mask texture\n");
     } else {
-	pI830->is_transform[1] = FALSE;
+	pI830->transform[1] = NULL;
 	pI830->scale_units[1][0] = -1;
 	pI830->scale_units[1][1] = -1;
     }
diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
index 46533b3..8705c6d 100644
--- a/src/i915_exa_render.c
+++ b/src/i915_exa_render.c
@@ -296,12 +296,7 @@ I915TextureSetup(PicturePtr pPict, Pixma
     pI830->samplerstate[unit * 3 + 1] |= unit << SS3_TEXTUREMAP_INDEX_SHIFT;
     pI830->samplerstate[unit * 3 + 2] = 0x00000000; /* border color */
 
-    if (pPict->transform != 0) {
-        pI830->is_transform[unit] = TRUE;
-        pI830->transform[unit] = pPict->transform;
-    } else {
-        pI830->is_transform[unit] = FALSE;
-    }
+    pI830->transform[unit] = pPict->transform;
 
     return TRUE;
 }
@@ -333,7 +328,7 @@ I915EXAPrepareComposite(int op, PictureP
 	if (!I915TextureSetup(pMaskPicture, pMask, 1))
 		I830FALLBACK("fail to setup mask texture\n");
     } else {
-	pI830->is_transform[1] = FALSE;
+	pI830->transform[1] = NULL;
 	pI830->scale_units[1][0] = -1;
 	pI830->scale_units[1][1] = -1;
     }
diff --git a/src/i965_exa_render.c b/src/i965_exa_render.c
index 572efd6..3e62027 100644
--- a/src/i965_exa_render.c
+++ b/src/i965_exa_render.c
@@ -390,22 +390,14 @@ I965EXAPrepareComposite(int op, PictureP
     pI830->scale_units[0][0] = pSrc->drawable.width;
     pI830->scale_units[0][1] = pSrc->drawable.height;
 
-    if (pSrcPicture->transform) {
-	pI830->is_transform[0] = TRUE;
-	pI830->transform[0] = pSrcPicture->transform;
-    } else 
-	pI830->is_transform[0] = FALSE;
+    pI830->transform[0] = pSrcPicture->transform;
 
     if (!pMask) {
-	pI830->is_transform[1] = FALSE;
+	pI830->transform[1] = NULL;
 	pI830->scale_units[1][0] = -1;
 	pI830->scale_units[1][1] = -1;
     } else {
-	if (pMaskPicture->transform) {
-	    pI830->is_transform[1] = TRUE;
-	    pI830->transform[1] = pMaskPicture->transform;
-	} else
-	    pI830->is_transform[1] = FALSE;
+	pI830->transform[1] = pMaskPicture->transform;
 	pI830->scale_units[1][0] = pMask->drawable.width;
 	pI830->scale_units[1][1] = pMask->drawable.height;
     }
@@ -1003,7 +995,7 @@ I965EXAComposite(PixmapPtr pDst, int src
     srcYend = srcY + h;
     maskXend = maskX + w;
     maskYend = maskY + h;
-    if (pI830->is_transform[0]) {
+    if (pI830->transform[0] != NULL) {
         v.vector[0] = IntToxFixed(srcX);
         v.vector[1] = IntToxFixed(srcY);
         v.vector[2] = xFixed1;
@@ -1017,7 +1009,7 @@ I965EXAComposite(PixmapPtr pDst, int src
         srcXend = xFixedToInt(v.vector[0]);
         srcYend = xFixedToInt(v.vector[1]);
     }
-    if (pI830->is_transform[1]) {
+    if (pI830->transform[1] != NULL) {
         v.vector[0] = IntToxFixed(maskX);
         v.vector[1] = IntToxFixed(maskY);
         v.vector[2] = xFixed1;
diff-tree c8581254cb811f76aa6eae49d74489b543b3eb05 (from parents)
Merge: 9da1791eeca446cd59e2e7d0803e8a7920dbbea5 d329fa121b2401cadb991c2854e077cfa68e15e8
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Mon Jan 29 21:25:13 2007 -0800

    Merge branch 'modesetting-rotation' into modesetting
    
    This adds reasonably driver-independent rotation support to the common
    layer. The piece required in the driver is to allocate and redirect the crtc
    to a shadow frame buffer. The driver uses Render to perform the actual
    rotation operation (which leaves us free to do fun projective transforms at
    some point in the future :-).

diff --cc src/i830_xf86Crtc.c
index 34fa736,c879d99..a209914
@@@ -1232,14 -1367,11 +1367,14 @@@
   * Otherwise, it will affect CRTCs before outputs.
   */
  void
- xf86DPMSSet(ScrnInfoPtr pScrn, int mode, int flags)
+ xf86DPMSSet(ScrnInfoPtr scrn, int mode, int flags)
  {
-     xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
+     xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
      int			i;
  
-     if (!pScrn->vtSema)
++    if (!scrn->vtSema)
 +	return;
 +
      if (mode == DPMSModeOff) {
  	for (i = 0; i < config->num_output; i++) {
  	    xf86OutputPtr output = config->output[i];
@@@ -1264,24 -1396,34 +1399,52 @@@
  }
  
  /**
 + * Implement the screensaver by just calling down into the driver DPMS hooks.
 + *
 + * Even for monitors with no DPMS support, by the definition of our DPMS hooks,
 + * the outputs will still get disabled (blanked).
 + */
 +Bool
 +xf86SaveScreen(ScreenPtr pScreen, int mode)
 +{
 +    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
 +
 +    if (xf86IsUnblank(mode))
 +	xf86DPMSSet(pScrn, DPMSModeOn, 0);
 +    else
 +	xf86DPMSSet(pScrn, DPMSModeOff, 0);
 +
 +    return TRUE;
 +}
 +
++/**
+  * Disable all inactive crtcs and outputs
+  */
+ void
+ xf86DisableUnusedFunctions(ScrnInfoPtr pScrn)
+ {
+     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+     int			o, c;
+ 
+     for (o = 0; o < xf86_config->num_output; o++) 
+     {
+ 	xf86OutputPtr  output = xf86_config->output[o];
+ 	if (!output->crtc) 
+ 	    (*output->funcs->dpms)(output, DPMSModeOff);
+     }
+ 
+     for (c = 0; c < xf86_config->num_crtc; c++) 
+     {
+ 	xf86CrtcPtr crtc = xf86_config->crtc[c];
+ 
+ 	if (!crtc->enabled) 
+ 	{
+ 	    crtc->funcs->dpms(crtc, DPMSModeOff);
+ 	    memset(&crtc->mode, 0, sizeof(crtc->mode));
+ 	}
+     }
+ }
+ 
 - 
  #ifdef RANDR_12_INTERFACE
  
  #define EDID_ATOM_NAME		"EDID_DATA"
diff --cc src/i830_xf86Crtc.h
index f8b561a,1c07ee8..6de2c92
@@@ -453,9 -508,9 +509,12 @@@
  void
  xf86DPMSSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags);
      
 +Bool
 +xf86SaveScreen(ScreenPtr pScreen, int mode);
 +
+ void
+ xf86DisableUnusedFunctions(ScrnInfoPtr pScrn);
+ 
  /**
   * Set the EDID information for the specified output
   */
diff-tree 9da1791eeca446cd59e2e7d0803e8a7920dbbea5 (from 67c6a490e63f6997f8198bc3ab180a1af097fe86)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Jan 29 17:10:14 2007 -0800

    Restore a few important lines from 89ace3e81fe72075b1709b073c05532f13b7f0d1
    
    Typical results were failure to sync, and a black screen.

diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c
index 7403a4c..a08d5a4 100644
--- a/src/i830_xf86Modes.c
+++ b/src/i830_xf86Modes.c
@@ -148,6 +148,11 @@ xf86SetModeCrtc(DisplayModePtr p, int ad
         p->CrtcVSyncEnd         *= p->VScan;
         p->CrtcVTotal           *= p->VScan;
     }
+    p->CrtcVBlankStart = min(p->CrtcVSyncStart, p->CrtcVDisplay);
+    p->CrtcVBlankEnd = max(p->CrtcVSyncEnd, p->CrtcVTotal);
+    p->CrtcHBlankStart = min(p->CrtcHSyncStart, p->CrtcHDisplay);
+    p->CrtcHBlankEnd = max(p->CrtcHSyncEnd, p->CrtcHTotal);
+
     p->CrtcHAdjusted = FALSE;
     p->CrtcVAdjusted = FALSE;
 }
diff-tree 67c6a490e63f6997f8198bc3ab180a1af097fe86 (from 89ace3e81fe72075b1709b073c05532f13b7f0d1)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Jan 29 09:53:58 2007 -0800

    Remove dead code to undo the damage of xf86SetModeCrtc() blank limiting.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 43f4725..32729c1 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1600,25 +1600,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       PreInitCleanup(pScrn);
       return FALSE;
    }
-
-   /*
-    * Fix up modes to make hblank start at hsync start.
-    * I don't know why the xf86 code mangles this...
-    */
-    {
-	DisplayModePtr	p;
-
-	for (p = pScrn->modes; p;) {
-	    xf86DrvMsg (pScrn->scrnIndex,
-			X_INFO, "move blank start from %d to %d\n",
-			p->CrtcHBlankStart, p->CrtcHDisplay);
-	    p->CrtcHBlankStart = p->CrtcHDisplay;
-	    p = p->next;
-	    if (p == pScrn->modes)
-		break;
-	}
-    }
-   
    pScrn->currentMode = pScrn->modes;
 
    pI830->disableTiling = FALSE;
diff-tree 89ace3e81fe72075b1709b073c05532f13b7f0d1 (from 6eb69e737864d06dc6d4fbb4cd85a027cbb7643a)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Jan 29 09:43:35 2007 -0800

    Bug #9680: Remove bogus blank length limiting in xf86SetModeCrtc().
    
    Our modes typically come from EDID or default modes, and when the monitor
    asks for a specific mode, deciding to tweak it usually results in incorrect
    display.  And if the user is specifying a mode by hand, tweaking it then is
    still pretty rude.
    
    Reviewed by: ajax

diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c
index 482a332..7403a4c 100644
--- a/src/i830_xf86Modes.c
+++ b/src/i830_xf86Modes.c
@@ -150,45 +150,6 @@ xf86SetModeCrtc(DisplayModePtr p, int ad
     }
     p->CrtcHAdjusted = FALSE;
     p->CrtcVAdjusted = FALSE;
-
-    /*
-     * XXX
-     *
-     * The following is taken from VGA, but applies to other cores as well.
-     */
-    p->CrtcVBlankStart = min(p->CrtcVSyncStart, p->CrtcVDisplay);
-    p->CrtcVBlankEnd = max(p->CrtcVSyncEnd, p->CrtcVTotal);
-    if ((p->CrtcVBlankEnd - p->CrtcVBlankStart) >= 127) {
-        /* 
-         * V Blanking size must be < 127.
-         * Moving blank start forward is safer than moving blank end
-         * back, since monitors clamp just AFTER the sync pulse (or in
-         * the sync pulse), but never before.
-         */
-        p->CrtcVBlankStart = p->CrtcVBlankEnd - 127;
-	/*
-	 * If VBlankStart is now > VSyncStart move VBlankStart
-	 * to VSyncStart using the maximum width that fits into
-	 * VTotal.
-	 */
-	if (p->CrtcVBlankStart > p->CrtcVSyncStart) {
-	    p->CrtcVBlankStart = p->CrtcVSyncStart;
-	    p->CrtcVBlankEnd = min(p->CrtcHBlankStart + 127, p->CrtcVTotal);
-	}
-    }
-    p->CrtcHBlankStart = min(p->CrtcHSyncStart, p->CrtcHDisplay);
-    p->CrtcHBlankEnd = max(p->CrtcHSyncEnd, p->CrtcHTotal);
-
-    if ((p->CrtcHBlankEnd - p->CrtcHBlankStart) >= 63 * 8) {
-        /*
-         * H Blanking size must be < 63*8. Same remark as above.
-         */
-        p->CrtcHBlankStart = p->CrtcHBlankEnd - 63 * 8;
-	if (p->CrtcHBlankStart > p->CrtcHSyncStart) {
-	    p->CrtcHBlankStart = p->CrtcHSyncStart;
-	    p->CrtcHBlankEnd = min(p->CrtcHBlankStart + 63 * 8, p->CrtcHTotal);
-	}
-    }
 }
 
 /**
diff-tree 6eb69e737864d06dc6d4fbb4cd85a027cbb7643a (from effe579e691b044e3ce59b41b5c0eaaac4368dda)
Author: Dave Airlie <airlied at linux.ie>
Date:   Sun Jan 28 19:40:12 2007 +1100

    ch7xxx: actually power up the chip around connection detection

diff --git a/src/ch7xxx/ch7xxx.c b/src/ch7xxx/ch7xxx.c
index 9e2a005..161aebf 100644
--- a/src/ch7xxx/ch7xxx.c
+++ b/src/ch7xxx/ch7xxx.c
@@ -183,9 +183,20 @@ static xf86OutputStatus
 ch7xxx_detect(I2CDevPtr d)
 {
     struct ch7xxx_priv *dev_priv = d->DriverPrivate.ptr;
-    CARD8 cdet;
+    CARD8 cdet, gpio, orig_pm, pm;
+
+    ch7xxx_read(dev_priv, CH7xxx_PM, &orig_pm);
+
+    pm = orig_pm;
+    pm &= ~CH7xxx_PM_FPD;
+    pm |= CH7xxx_PM_DVIL | CH7xxx_PM_DVIP;
+
+    ch7xxx_write(dev_priv, CH7xxx_PM, pm);
+
     ch7xxx_read(dev_priv, CH7xxx_CONNECTION_DETECT, &cdet);
 
+    ch7xxx_write(dev_priv, CH7xxx_PM, orig_pm);
+
     if (cdet & CH7xxx_CDET_DVI) 
     	return XF86OutputStatusConnected;
     return XF86OutputStatusDisconnected;
diff --git a/src/ch7xxx/ch7xxx_reg.h b/src/ch7xxx/ch7xxx_reg.h
index 0ec84ea..328b653 100644
--- a/src/ch7xxx/ch7xxx_reg.h
+++ b/src/ch7xxx/ch7xxx_reg.h
@@ -44,6 +44,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define CH7xxx_CM_MCP (1<<2)
 #define CH7xxx_INPUT_CLOCK 0x1D
 #define CH7xxx_GPIO 0x1E
+#define CH7xxx_GPIO_HPIR (1<<3)
 #define CH7xxx_IDF 0x1F
 
 #define CH7xxx_IDF_HSP (1<<3)
diff-tree d329fa121b2401cadb991c2854e077cfa68e15e8 (from 20419d664c77e9a1a2de82987838b45f44774b47)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Sat Jan 27 18:36:15 2007 -0800

    Fetch from root window instead of screen pixmap during rotation.
    
    The XAA Composite wrapper doesn't check for sourcing from the root pixmap
    when deciding whether to sync the hardware drawing. Fix the rotation code to
    reference the root window in IncludeInferiors mode to avoid reading without
    correct synchronization.

diff --git a/src/i830_xf86Rotate.c b/src/i830_xf86Rotate.c
index 7d056e5..3b8be61 100644
--- a/src/i830_xf86Rotate.c
+++ b/src/i830_xf86Rotate.c
@@ -138,7 +138,7 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crt
 {
     ScrnInfoPtr		scrn = crtc->scrn;
     ScreenPtr		screen = scrn->pScreen;
-    PixmapPtr		src_pixmap = (*screen->GetScreenPixmap) (screen);
+    WindowPtr		root = WindowTable[screen->myNum];
     PixmapPtr		dst_pixmap = crtc->rotatedPixmap;
     PictFormatPtr	format = compWindowFormat (WindowTable[screen->myNum]);
     int			error;
@@ -146,12 +146,13 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crt
     PictTransform	transform;
     int			n = REGION_NUM_RECTS(region);
     BoxPtr		b = REGION_RECTS(region);
+    XID			include_inferiors = IncludeInferiors;
     
     src = CreatePicture (None,
-			 &src_pixmap->drawable,
+			 &root->drawable,
 			 format,
-			 0L,
-			 NULL,
+			 CPSubwindowMode,
+			 &include_inferiors,
 			 serverClient,
 			 &error);
     if (!src) {
diff-tree 20419d664c77e9a1a2de82987838b45f44774b47 (from 00decd3b6cea0de22c88b9504dbe26d680e8ab16)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Sat Jan 27 18:34:12 2007 -0800

    Paint ARGB cursor data to ARGB cursor memory space in frame buffer.
    
    When converting from global cursor to per-crtc cursor, the ARGB cursor data
    was accidentally painted to the wrong location, overwriting some critical
    data and causing the hardware to lock up. (along with generating a garbage
    cursor image from uninitialized data).

diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index da220f5..464eb6d 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -389,7 +389,7 @@ static void I830CRTCLoadCursorARGB (xf86
 {
    I830Ptr pI830 = I830PTR(crtc->scrn);
    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
-   CARD32 *dst = (CARD32 *) (pI830->FbBase + intel_crtc->cursor_mem.Start);
+   CARD32 *dst = (CARD32 *) (pI830->FbBase + intel_crtc->cursor_mem_argb.Start);
    CARD32 *image = (CARD32 *)pCurs->bits->argb;
    int x, y, w, h;
 
diff-tree 00decd3b6cea0de22c88b9504dbe26d680e8ab16 (from 7a5f17087bda2833e84fa7e7ff0cb168943b89b6)
Author: Krzysztof Halasa <khc at pm.waw.pl>
Date:   Sat Jan 27 12:29:31 2007 -0800

    Don't zero out mode structure after setting name field.
    
    Instead of using memset to zero the structure (at the wrong time, no less),
    use xcalloc to gather pre-initialized memory.

diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c
index f37eaeb..b5f06d6 100644
--- a/src/i830_xf86Modes.c
+++ b/src/i830_xf86Modes.c
@@ -564,7 +564,7 @@ xf86GetConfigModes (XF86ConfModeLinePtr 
     
     for (; conf_mode; conf_mode = (XF86ConfModeLinePtr) conf_mode->list.next)
     {
-        mode = xalloc(sizeof(DisplayModeRec));
+        mode = xcalloc(1, sizeof(DisplayModeRec));
 	if (!mode)
 	    continue;
         mode->name       = xstrdup(conf_mode->ml_identifier);
@@ -573,8 +573,6 @@ xf86GetConfigModes (XF86ConfModeLinePtr 
 	    xfree (mode);
 	    continue;
 	}
-	
-        memset(mode,'\0',sizeof(DisplayModeRec));
 	mode->type       = 0;
         mode->Clock      = conf_mode->ml_clock;
         mode->HDisplay   = conf_mode->ml_hdisplay;
diff-tree 7a5f17087bda2833e84fa7e7ff0cb168943b89b6 (from 2d95cb6f041653f7e530b1f32cf007929c23ef3b)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Sat Jan 27 00:11:21 2007 -0800

    Mark crtc region as damaged when rotation is set.
    
    When shadow frame buffer is allocated for rotation, it needs to be
    initialized by copying from the frame buffer. Do this by simply marking the
    entire screen as damaged which will force an update.

diff --git a/src/i830_xf86Rotate.c b/src/i830_xf86Rotate.c
index abfaec6..7d056e5 100644
--- a/src/i830_xf86Rotate.c
+++ b/src/i830_xf86Rotate.c
@@ -328,6 +328,8 @@ xf86CrtcRotate (xf86CrtcPtr crtc, Displa
 	PixmapPtr   shadow = crtc->rotatedPixmap;
 	int	    old_width = shadow ? shadow->drawable.width : 0;
 	int	    old_height = shadow ? shadow->drawable.height : 0;
+	BoxRec	    damage_box;
+	RegionRec   damage_region;
 	
 	/* Allocate memory for rotation */
 	if (old_width != width || old_height != height)
@@ -363,6 +365,14 @@ xf86CrtcRotate (xf86CrtcPtr crtc, Displa
 	    {
 		goto bail3;
 	    }
+	    damage_box.x1 = 0;
+	    damage_box.y1 = 0;
+	    damage_box.x2 = mode_width (mode, rotation);
+	    damage_box.y2 = mode_height (mode, rotation);
+	    REGION_INIT (pScreen, &damage_region, &damage_box, 1);
+	    DamageDamageRegion (&(*pScreen->GetScreenPixmap)(pScreen)->drawable,
+				&damage_region);
+	    REGION_UNINIT (pScreen, &damage_region);
 	}
 	if (0)
 	{
diff-tree 2d95cb6f041653f7e530b1f32cf007929c23ef3b (from 5c1e27cdd243dc24dd2bfdeb46d757bbef6ba6af)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Sat Jan 27 00:04:13 2007 -0800

    Make rotated pixmap size of mode, not rotated mode. Update only damage.
    
    Rotated pixmap should match size of displayed mode, not the rotated version
    of that size.
    
    Take damaged region, rotate each box and display them instead of displaying
    the whole screen after each damage update. This exposes a bug where the
    screen is not correctly damaged after rotation.

diff --git a/src/i830_xf86Rotate.c b/src/i830_xf86Rotate.c
index 8da79b6..abfaec6 100644
--- a/src/i830_xf86Rotate.c
+++ b/src/i830_xf86Rotate.c
@@ -94,6 +94,46 @@ compWindowFormat (WindowPtr pWin)
 }
 
 static void
+xf86RotateBox (BoxPtr dst, BoxPtr src, Rotation rotation,
+	       int dest_width, int dest_height)
+{
+    switch (rotation & 0xf) {
+    default:
+    case RR_Rotate_0:
+	*dst = *src;
+	break;
+    case RR_Rotate_90:
+	dst->x1 = src->y1;
+	dst->y1 = dest_height - src->x2;
+	dst->x2 = src->y2;
+	dst->y2 = dest_height - src->x1;
+	break;
+    case RR_Rotate_180:
+	dst->x1 = dest_width - src->x2;
+	dst->y1 = dest_height - src->y2;
+	dst->x2 = dest_width - src->x1;
+	dst->y2 = dest_height - src->y1;
+	break;
+    case RR_Rotate_270:
+	dst->x1 = dest_width - src->y2;
+	dst->y1 = src->x1;
+	dst->y2 = src->x2;
+	dst->x2 = dest_width - src->y1;
+	break;
+    }
+    if (rotation & RR_Reflect_X) {
+	int x1 = dst->x1;
+	dst->x1 = dest_width - dst->x2;
+	dst->x2 = dest_width - x1;
+    }
+    if (rotation & RR_Reflect_Y) {
+	int y1 = dst->y1;
+	dst->y1 = dest_height - dst->y2;
+	dst->y2 = dest_height - y1;
+    }
+}
+
+static void
 xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region)
 {
     ScrnInfoPtr		scrn = crtc->scrn;
@@ -104,6 +144,8 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crt
     int			error;
     PicturePtr		src, dst;
     PictTransform	transform;
+    int			n = REGION_NUM_RECTS(region);
+    BoxPtr		b = REGION_RECTS(region);
     
     src = CreatePicture (None,
 			 &src_pixmap->drawable,
@@ -127,18 +169,13 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crt
 	ErrorF("couldn't create src pict\n");
 	return;
     }
-    /* Unfortunately, we don't do clipping on transformed source pictures.
-     * So we can't use this.  Instead, we'll just repaint the whole screen
-     * for now, and do transform of the source region into a dest region
-     * later.
-     */
-    /* SetPictureClipRegion (src, 0, 0, region); */
 
     memset (&transform, '\0', sizeof (transform));
     transform.matrix[2][2] = IntToxFixed(1);
     transform.matrix[0][2] = IntToxFixed(crtc->x);
     transform.matrix[1][2] = IntToxFixed(crtc->y);
     switch (crtc->rotation & 0xf) {
+    default:
     case RR_Rotate_0:
 	transform.matrix[0][0] = IntToxFixed(1);
 	transform.matrix[1][1] = IntToxFixed(1);
@@ -177,11 +214,19 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crt
 	return;
     }
 
-    CompositePicture (PictOpSrc,
-		      src, NULL, dst,
-		      0, 0, 0, 0, 0, 0,
-		      dst_pixmap->drawable.width,
-		      dst_pixmap->drawable.height);
+    while (n--)
+    {
+	BoxRec	dst_box;
+
+	xf86RotateBox (&dst_box, b, crtc->rotation,
+		       crtc->mode.HDisplay, crtc->mode.VDisplay);
+	CompositePicture (PictOpSrc,
+			  src, NULL, dst,
+			  dst_box.x1, dst_box.y1, 0, 0, dst_box.x1, dst_box.y1,
+			  dst_box.x2 - dst_box.x1,
+			  dst_box.y2 - dst_box.y1);
+	b++;
+    }
     FreePicture (src, None);
     FreePicture (dst, None);
 }
@@ -220,7 +265,7 @@ xf86RotateRedisplay(ScreenPtr pScreen)
 		
 		/* update damaged region */
 		if (REGION_NOTEMPTY(pScreen, &crtc_damage))
-		    xf86RotateCrtcRedisplay (crtc, &crtc_damage);
+    		    xf86RotateCrtcRedisplay (crtc, &crtc_damage);
 		
 		REGION_UNINIT (pScreen, &crtc_damage);
 	    }
@@ -273,8 +318,13 @@ xf86CrtcRotate (xf86CrtcPtr crtc, Displa
     }
     else
     {
-	int	    width = mode_width (mode, rotation);
-	int	    height = mode_height (mode, rotation);
+	/* 
+	 * these are the size of the shadow pixmap, which
+	 * matches the mode, not the pre-rotated copy in the
+	 * frame buffer
+	 */
+	int	    width = mode->HDisplay;
+	int	    height = mode->VDisplay;
 	PixmapPtr   shadow = crtc->rotatedPixmap;
 	int	    old_width = shadow ? shadow->drawable.width : 0;
 	int	    old_height = shadow ? shadow->drawable.height : 0;
diff-tree 5c1e27cdd243dc24dd2bfdeb46d757bbef6ba6af (from 83cc4601b27d871484a2408f31154e9387064b9e)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jan 25 15:31:22 2007 -0800

    Make rotated shadow buffer allocation dynamic.
    
    For EXA, this requires version 2.1 of EXA to do rotation, as the VT switching
    issues were too complicated otherwise.

diff --git a/src/i830.h b/src/i830.h
index a7c889d..9ffae94 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -199,7 +199,13 @@ typedef struct _I830CrtcPrivateRec {
     /* Lookup table values to be set when the CRTC is enabled */
     CARD8 lut_r[256], lut_g[256], lut_b[256];
 
-    I830MemRange rotate_mem;
+#ifdef I830_USE_XAA
+    FBLinearPtr rotate_mem_xaa;
+#endif
+#ifdef I830_USE_EXA
+    ExaOffscreenArea *rotate_mem_exa;
+#endif
+
     I830MemRange cursor_mem;
     I830MemRange cursor_mem_argb;
 } I830CrtcPrivateRec, *I830CrtcPrivatePtr;
@@ -613,6 +619,14 @@ extern void i830WaitSync(ScrnInfoPtr pSc
 /* i830_memory.c */
 Bool I830BindAGPMemory(ScrnInfoPtr pScrn);
 Bool I830UnbindAGPMemory(ScrnInfoPtr pScrn);
+#ifdef I830_USE_XAA
+FBLinearPtr
+i830_xf86AllocateOffscreenLinear(ScreenPtr pScreen, int length,
+				 int granularity,
+				 MoveLinearCallbackProcPtr moveCB,
+				 RemoveLinearCallbackProcPtr removeCB,
+				 pointer privData);
+#endif /* I830_USE_EXA */
 
 /* i830_modes.c */
 DisplayModePtr i830_ddc_get_modes(xf86OutputPtr output);
diff --git a/src/i830_display.c b/src/i830_display.c
index 2313f76..8202985 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -342,8 +342,9 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x,
     int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE);
     int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
 
-    if (crtc->rotation != RR_Rotate_0) {
-	Start = intel_crtc->rotate_mem.Start;
+    if (crtc->rotatedPixmap != NULL) {
+	Start = (char *)crtc->rotatedPixmap->devPrivate.ptr -
+	    (char *)pI830->FbBase;
     } else if (I830IsPrimary(pScrn)) {
 	Start = pI830->FrontBuffer.Start;
     } else {
@@ -895,31 +896,92 @@ static PixmapPtr
 i830_crtc_shadow_create(xf86CrtcPtr crtc, int width, int height)
 {
     ScrnInfoPtr pScrn = crtc->scrn;
+    ScreenPtr pScreen = pScrn->pScreen;
     I830Ptr pI830 = I830PTR(pScrn);
     I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
     unsigned long rotate_pitch;
     PixmapPtr rotate_pixmap;
-    pointer rotate_offset;
-
-    if (intel_crtc->rotate_mem.Start == 0)
-	return NULL;
+    unsigned long rotate_offset;
+    int align = KB(4), size;
 
     rotate_pitch = pI830->displayWidth * pI830->cpp;
-    rotate_offset = pI830->FbBase + intel_crtc->rotate_mem.Start;
+    size = rotate_pitch * height;
+
+#ifdef I830_USE_EXA
+    /* We could get close to what we want here by just creating a pixmap like
+     * normal, but we have to lock it down in framebuffer, and there is no
+     * setter for offscreen area locking in EXA currently.  So, we just
+     * allocate offscreen memory and fake up a pixmap header for it.
+     */
+    if (pI830->useEXA) {
+	assert(intel_crtc->rotate_mem_exa == NULL);
+
+	intel_crtc->rotate_mem_exa = exaOffscreenAlloc(pScreen, size, align,
+						       TRUE, NULL, NULL);
+	if (intel_crtc->rotate_mem_exa == NULL) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Couldn't allocate shadow memory for rotated CRTC\n");
+	    return NULL;
+	}
+	rotate_offset = intel_crtc->rotate_mem_exa->offset;
+    }
+#endif /* I830_USE_EXA */
+#ifdef I830_USE_XAA
+    if (!pI830->useEXA) {
+	/* The XFree86 linear allocator operates in units of screen pixels,
+	 * sadly.
+	 */
+	size = (size + pI830->cpp - 1) / pI830->cpp;
+	align = (align + pI830->cpp - 1) / pI830->cpp;
+
+	assert(intel_crtc->rotate_mem_xaa == NULL);
+
+	intel_crtc->rotate_mem_xaa =
+	    i830_xf86AllocateOffscreenLinear(pScreen, size, align,
+					     NULL, NULL, NULL);
+	if (intel_crtc->rotate_mem_xaa == NULL) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Couldn't allocate shadow memory for rotated CRTC\n");
+	    return NULL;
+	}
+	rotate_offset = pI830->FrontBuffer.Start +
+	    intel_crtc->rotate_mem_xaa->offset * pI830->cpp;
+    }
+#endif /* I830_USE_XAA */
 
     rotate_pixmap = GetScratchPixmapHeader(pScrn->pScreen,
 					   width, height,
 					   pScrn->depth,
 					   pScrn->bitsPerPixel,
 					   rotate_pitch,
-					   rotate_offset);
+					   pI830->FbBase + rotate_offset);
+    if (rotate_pixmap == NULL) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "Couldn't allocate shadow pixmap for rotated CRTC\n");
+    }
     return rotate_pixmap;
 }
 
 static void
 i830_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap)
 {
+    ScrnInfoPtr pScrn = crtc->scrn;
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+
     FreeScratchPixmapHeader(rotate_pixmap);
+#ifdef I830_USE_EXA
+    if (pI830->useEXA && intel_crtc->rotate_mem_exa != NULL) {
+	exaOffscreenFree(pScrn->pScreen, intel_crtc->rotate_mem_exa);
+	intel_crtc->rotate_mem_exa = NULL;
+    }
+#endif /* I830_USE_EXA */
+#ifdef I830_USE_XAA
+    if (!pI830->useEXA) {
+	xf86FreeOffscreenLinear(intel_crtc->rotate_mem_xaa);
+	intel_crtc->rotate_mem_xaa = NULL;
+    }
+#endif /* I830_USE_XAA */
 }
 
 
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 644ea57..19e97b0 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2879,7 +2879,23 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       shadowSetup(pScreen);
       /* support all rotations */
       xf86RandR12Init (pScreen);
-      xf86RandR12SetRotations (pScreen, RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270);
+      if (pI830->useEXA) {
+#ifdef I830_USE_EXA
+	 if (pI830->EXADriverPtr->exa_minor >= 1) {
+	    xf86RandR12SetRotations (pScreen, RR_Rotate_0 | RR_Rotate_90 |
+				     RR_Rotate_180 | RR_Rotate_270);
+	 } else {
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		       "EXA version %d.%d too old to support rotation\n",
+		       pI830->EXADriverPtr->exa_major,
+		       pI830->EXADriverPtr->exa_minor);
+	    xf86RandR12SetRotations (pScreen, RR_Rotate_0);
+	 }
+#endif /* I830_USE_EXA */
+      } else {
+	 xf86RandR12SetRotations (pScreen, RR_Rotate_0 | RR_Rotate_90 |
+				  RR_Rotate_180 | RR_Rotate_270);
+      }
       pI830->PointerMoved = pScrn->PointerMoved;
       pScrn->PointerMoved = I830PointerMoved;
       pI830->CreateScreenResources = pScreen->CreateScreenResources;
diff --git a/src/i830_exa.c b/src/i830_exa.c
index f1cd1e3..3fd5e4a 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -418,7 +418,7 @@ I830EXAInit(ScreenPtr pScreen)
     
     pI830->bufferOffset = 0;
     pI830->EXADriverPtr->exa_major = 2;
-    pI830->EXADriverPtr->exa_minor = 0;
+    pI830->EXADriverPtr->exa_minor = 1;
     pI830->EXADriverPtr->memoryBase = pI830->FbBase;
     pI830->EXADriverPtr->offScreenBase = pI830->Offscreen.Start;
     pI830->EXADriverPtr->memorySize = pI830->Offscreen.End;
@@ -520,9 +520,14 @@ I830EXAInit(ScreenPtr pScreen)
     }
 
     if(!exaDriverInit(pScreen, pI830->EXADriverPtr)) {
-	xfree(pI830->EXADriverPtr);
-	pI830->noAccel = TRUE;
-	return FALSE;
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		   "EXA initialization failed; trying older version\n");
+	pI830->EXADriverPtr->exa_minor = 0;
+	if(!exaDriverInit(pScreen, pI830->EXADriverPtr)) {
+	    xfree(pI830->EXADriverPtr);
+	    pI830->noAccel = TRUE;
+	    return FALSE;
+	}
     }
 
     I830SelectBuffer(pScrn, I830_SELECT_FRONT);
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 14dacc8..24f0b29 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -769,63 +769,6 @@ I830AllocateFramebuffer(ScrnInfoPtr pScr
    return TRUE;
 }
 
-/**
- * Allocates memory for the rotated shadow buffers.
- *
- * This memory would be better allocated normally through the linear allocator,
- * but it gets rotation working for now.
- */
-static Bool
-I830AllocateRotateBuffers(xf86CrtcPtr crtc, const int flags)
-{
-   ScrnInfoPtr pScrn = crtc->scrn;
-   I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
-   I830Ptr pI830 = I830PTR(pScrn);
-   Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
-   unsigned long avail, lineSize;
-   int verbosity = dryrun ? 4 : 1;
-   const char *s = dryrun ? "[dryrun] " : "";
-   int align, alignflags;
-   long size, alloced;
-   int rotate_width, rotate_height;
-
-   memset(&intel_crtc->rotate_mem, 0, sizeof(intel_crtc->rotate_mem));
-
-   rotate_width = pScrn->displayWidth;
-   if (pScrn->virtualX > pScrn->virtualY)
-      rotate_height = pScrn->virtualX;
-   else
-      rotate_height = pScrn->virtualY;
-
-   lineSize = pScrn->displayWidth * pI830->cpp;
-   avail = pScrn->videoRam * 1024;
-
-   align = KB(64);
-   alignflags = 0;
-
-   size = lineSize * rotate_height;
-   size = ROUND_TO_PAGE(size);
-   xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-		  "%sInitial %sshadow framebuffer allocation size: "
-		  "%ld kByte\n",
-		  s, (intel_crtc->pipe == 0) ? "" : "secondary ",
-		  size / 1024);
-   alloced = I830AllocVidMem(pScrn, &intel_crtc->rotate_mem,
-			     &pI830->StolenPool, size, align,
-			     flags | alignflags |
-			     FROM_ANYWHERE | ALLOCATE_AT_BOTTOM);
-   if (alloced < size) {
-      if (!dryrun) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate "
-		    "%sshadow framebuffer. Is your VideoRAM set too low?\n",
-		    (intel_crtc->pipe == 0) ? "" : "secondary ");
-      }
-      return FALSE;
-   }
-
-   return TRUE;
-}
-
 static Bool
 I830AllocateCursorBuffers(xf86CrtcPtr crtc, const int flags)
 {
@@ -981,10 +924,6 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
 	 return FALSE;
       }
 
-      for (i = 0; i < xf86_config->num_crtc; i++) {
-	 I830AllocateRotateBuffers(xf86_config->crtc[i], flags);
-      }
-
 #ifdef I830_USE_EXA
       if (pI830->useEXA) {
 	 /* Default EXA to having 3 screens worth of offscreen memory space
@@ -1619,7 +1558,6 @@ I830FixupOffsets(ScrnInfoPtr pScrn)
    for (i = 0; i < xf86_config->num_crtc; i++) {
       I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private;
 
-      I830FixOffset(pScrn, &intel_crtc->rotate_mem);
       I830FixOffset(pScrn, &intel_crtc->cursor_mem);
       I830FixOffset(pScrn, &intel_crtc->cursor_mem_argb);
    }
@@ -2028,8 +1966,6 @@ I830BindAGPMemory(ScrnInfoPtr pScrn)
       for (i = 0; i < xf86_config->num_crtc; i++) {
 	 I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private;
 
-	 if (!BindMemRange(pScrn, &intel_crtc->rotate_mem))
-	    return FALSE;
 	 if (!BindMemRange(pScrn, &intel_crtc->cursor_mem))
 	    return FALSE;
 	 if (!BindMemRange(pScrn, &intel_crtc->cursor_mem_argb))
@@ -2130,8 +2066,6 @@ I830UnbindAGPMemory(ScrnInfoPtr pScrn)
       for (i = 0; i < xf86_config->num_crtc; i++) {
 	 I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private;
 
-	 if (!UnbindMemRange(pScrn, &intel_crtc->rotate_mem))
-	    return FALSE;
 	 if (!UnbindMemRange(pScrn, &intel_crtc->cursor_mem))
 	    return FALSE;
 	 if (!UnbindMemRange(pScrn, &intel_crtc->cursor_mem_argb))
@@ -2209,3 +2143,41 @@ I830CheckAvailableMemory(ScrnInfoPtr pSc
 
    return maxPages * 4;
 }
+
+#ifdef I830_USE_XAA
+/**
+ * Allocates memory from the XF86 linear allocator, but also purges
+ * memory if possible to cause the allocation to succeed.
+ */
+FBLinearPtr
+i830_xf86AllocateOffscreenLinear(ScreenPtr pScreen, int length,
+				 int granularity,
+				 MoveLinearCallbackProcPtr moveCB,
+				 RemoveLinearCallbackProcPtr removeCB,
+				 pointer privData)
+{
+   FBLinearPtr linear;
+   int max_size;
+
+   linear = xf86AllocateOffscreenLinear(pScreen, length, granularity, moveCB,
+					removeCB, privData);
+   if (linear != NULL)
+      return linear;
+
+   /* The above allocation didn't succeed, so purge unlocked stuff and try
+    * again.
+    */
+   xf86QueryLargestOffscreenLinear(pScreen, &max_size, granularity,
+				   PRIORITY_EXTREME);
+
+   if (max_size < length)
+      return NULL;
+
+   xf86PurgeUnlockedOffscreenAreas(pScreen);
+
+   linear = xf86AllocateOffscreenLinear(pScreen, length, granularity, moveCB,
+					removeCB, privData);
+
+   return linear;
+}
+#endif
diff --git a/src/i830_video.c b/src/i830_video.c
index 79f5a7c..22f5bee 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -2073,8 +2073,6 @@ I830AllocateMemory(ScrnInfoPtr pScrn, st
 #endif /* I830_USE_EXA */
 #ifdef I830_USE_XAA
    if (!pI830->useEXA) {
-      int max_size;
-
       /* Converts an offset from XAA's linear allocator to an offset from the
        * start of fb.
        */
@@ -2100,25 +2098,11 @@ I830AllocateMemory(ScrnInfoPtr pScrn, st
 	 xf86FreeOffscreenLinear(linear->xaa);
       }
 
-      linear->xaa = xf86AllocateOffscreenLinear(pScreen, size, align,
-						NULL, NULL, NULL);
-      if (linear->xaa != NULL) {
-	 linear->offset = XAA_OFFSET_TO_OFFSET(linear->xaa->offset);
+      linear->xaa = i830_xf86AllocateOffscreenLinear(pScreen, size, align,
+						     NULL, NULL, NULL);
+      if (linear->xaa == NULL)
 	 return;
-      }
-
-      xf86QueryLargestOffscreenLinear(pScreen, &max_size, align,
-				      PRIORITY_EXTREME);
-
-      if (max_size < size) {
-	 ErrorF("No memory available\n");
-	 linear->offset = 0;
-	 return;
-      }
 
-      xf86PurgeUnlockedOffscreenAreas(pScreen);
-      linear->xaa = xf86AllocateOffscreenLinear(pScreen, size, align,
-						NULL, NULL, NULL);
       linear->offset = XAA_OFFSET_TO_OFFSET(linear->xaa->offset);
    }
 #endif /* I830_USE_XAA */
diff-tree 83cc4601b27d871484a2408f31154e9387064b9e (from e21332419581eff1d7651741bae0b640c84d0ecd)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Jan 24 16:52:22 2007 +0800

    Fix a possible failure to misalign video allocation in XAA.

diff --git a/src/i830_video.c b/src/i830_video.c
index a330eb5..79f5a7c 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -2117,7 +2117,7 @@ I830AllocateMemory(ScrnInfoPtr pScrn, st
       }
 
       xf86PurgeUnlockedOffscreenAreas(pScreen);
-      linear->xaa = xf86AllocateOffscreenLinear(pScreen, size, 4,
+      linear->xaa = xf86AllocateOffscreenLinear(pScreen, size, align,
 						NULL, NULL, NULL);
       linear->offset = XAA_OFFSET_TO_OFFSET(linear->xaa->offset);
    }
diff-tree e21332419581eff1d7651741bae0b640c84d0ecd (from 74ebff6732b9bfcf8c865b52cbebfd9bf6b73eb2)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Jan 24 12:32:38 2007 +0800

    Warning fix.

diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index bb5bc38..da220f5 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -486,8 +486,8 @@ I830SetCursorPosition(ScrnInfoPtr pScrn,
     {
 	xf86CrtcPtr	    crtc = xf86_config->crtc[pipe];
 	DisplayModePtr	    mode = &crtc->mode;
-	int		    thisx;
-	int		    thisy;
+	int		    thisx = 0;
+	int		    thisy = 0;
 	int hotspotx = 0, hotspoty = 0;
 
 	if (!crtc->enabled)
diff-tree effe579e691b044e3ce59b41b5c0eaaac4368dda (from c68dae2705d6e5b05dba7d40b6da112b98b926b4)
Author: Dave Airlie <airlied at linux.ie>
Date:   Sun Jan 21 20:23:13 2007 +1100

    ch7xxx: fix output detection as per datasheet, have no DVI to test this.

diff --git a/src/ch7xxx/ch7xxx.c b/src/ch7xxx/ch7xxx.c
index 5bfb7c5..9e2a005 100644
--- a/src/ch7xxx/ch7xxx.c
+++ b/src/ch7xxx/ch7xxx.c
@@ -182,7 +182,13 @@ out:
 static xf86OutputStatus
 ch7xxx_detect(I2CDevPtr d)
 {
-    return XF86OutputStatusUnknown;
+    struct ch7xxx_priv *dev_priv = d->DriverPrivate.ptr;
+    CARD8 cdet;
+    ch7xxx_read(dev_priv, CH7xxx_CONNECTION_DETECT, &cdet);
+
+    if (cdet & CH7xxx_CDET_DVI) 
+    	return XF86OutputStatusConnected;
+    return XF86OutputStatusDisconnected;
 }
 
 static ModeStatus
diff --git a/src/ch7xxx/ch7xxx_reg.h b/src/ch7xxx/ch7xxx_reg.h
index c626e1f..0ec84ea 100644
--- a/src/ch7xxx/ch7xxx_reg.h
+++ b/src/ch7xxx/ch7xxx_reg.h
@@ -49,7 +49,9 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define CH7xxx_IDF_HSP (1<<3)
 #define CH7xxx_IDF_VSP (1<<4)
 
-#define CH7301_CONNECTION_DETECT 0x20
+#define CH7xxx_CONNECTION_DETECT 0x20
+#define CH7xxx_CDET_DVI (1<<5)
+
 #define CH7301_DAC_CNTL 0x21
 #define CH7301_HOTPLUG 0x23
 #define CH7xxx_TCTL 0x31
diff-tree c68dae2705d6e5b05dba7d40b6da112b98b926b4 (from 8eb861fb61fda78e6c142ffa66c586357aaa2e44)
Author: Dave Airlie <airlied at linux.ie>
Date:   Sun Jan 21 20:22:39 2007 +1100

    fix building with 7.1 server by hiding stuff inside RANDR_12_INTERFACE

diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index 223c6ab..0092ded 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -354,6 +354,7 @@ i830_lvds_create_resources(xf86OutputPtr
 #endif /* RANDR_12_INTERFACE */
 }
 
+#ifdef RANDR_12_INTERFACE
 static Bool
 i830_lvds_set_property(xf86OutputPtr output, Atom property,
 		       RRPropertyValuePtr value)
@@ -381,6 +382,7 @@ i830_lvds_set_property(xf86OutputPtr out
 
     return TRUE;
 }
+#endif /* RANDR_12_INTERFACE */
 
 static const xf86OutputFuncsRec i830_lvds_output_funcs = {
     .create_resources = i830_lvds_create_resources,
@@ -392,7 +394,9 @@ static const xf86OutputFuncsRec i830_lvd
     .mode_set = i830_lvds_mode_set,
     .detect = i830_lvds_detect,
     .get_modes = i830_lvds_get_modes,
+#ifdef RANDR_12_INTERFACE
     .set_property = i830_lvds_set_property,
+#endif
     .destroy = i830_lvds_destroy
 };
 
diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h
index 04374b7..f8b561a 100644
--- a/src/i830_xf86Crtc.h
+++ b/src/i830_xf86Crtc.h
@@ -252,6 +252,7 @@ typedef struct _xf86OutputFuncs {
     DisplayModePtr
     (*get_modes)(xf86OutputPtr	    output);
 
+#ifdef RANDR_12_INTERFACE
     /**
      * Callback when an output's property has changed.
      */
@@ -259,7 +260,7 @@ typedef struct _xf86OutputFuncs {
     (*set_property)(xf86OutputPtr output,
 		    Atom property,
 		    RRPropertyValuePtr value);
-
+#endif
     /**
      * Clean up driver-specific bits of the output
      */
diff-tree 8eb861fb61fda78e6c142ffa66c586357aaa2e44 (from 7161e824e89a6a69f1277e510f2344ad31721f62)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Jan 22 15:50:14 2007 +0800

    Replace the custom SaveScreen function with a generic function calling DPMS.
    
    With this, additional power saving occurs with the core screensaver, for
    example by turning off LVDS backlight.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 20781aa..43f4725 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -316,7 +316,6 @@ const char *i830_output_type_names[] = {
 
 static void i830AdjustFrame(int scrnIndex, int x, int y, int flags);
 static Bool I830CloseScreen(int scrnIndex, ScreenPtr pScreen);
-static Bool I830SaveScreen(ScreenPtr pScreen, int unblack);
 static Bool I830EnterVT(int scrnIndex, int flags);
 static CARD32 I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg);
 static Bool SaveHWState(ScrnInfoPtr pScrn);
@@ -2891,7 +2890,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering: Not available\n");
 #endif
 
-   pScreen->SaveScreen = I830SaveScreen;
+   pScreen->SaveScreen = xf86SaveScreen;
    pI830->CloseScreen = pScreen->CloseScreen;
    pScreen->CloseScreen = I830CloseScreen;
 
@@ -3263,57 +3262,6 @@ I830SwitchMode(int scrnIndex, DisplayMod
 }
 
 static Bool
-I830SaveScreen(ScreenPtr pScreen, int mode)
-{
-   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-   xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-   I830Ptr pI830 = I830PTR(pScrn);
-   Bool on = xf86IsUnblank(mode);
-   CARD32 temp, ctrl, base, surf;
-   int i;
-
-   DPRINTF(PFX, "I830SaveScreen: %d, on is %s\n", mode, BOOLTOSTRING(on));
-
-   if (pScrn->vtSema) {
-      for (i = 0; i < xf86_config->num_crtc; i++) {
-        if (i == 0) {
-	    ctrl = DSPACNTR;
-	    base = DSPABASE;
-	    surf = DSPASURF;
-        } else {
-	    ctrl = DSPBCNTR;
-	    base = DSPBADDR;
-	    surf = DSPBSURF;
-        }
-        if (xf86_config->crtc[i]->enabled) {
-	   temp = INREG(ctrl);
-	   if (on)
-	      temp |= DISPLAY_PLANE_ENABLE;
-	   else
-	      temp &= ~DISPLAY_PLANE_ENABLE;
-	   OUTREG(ctrl, temp);
-	   /* Flush changes */
-	   temp = INREG(base);
-	   OUTREG(base, temp);
-	   if (IS_I965G(pI830)) {
-	      temp = INREG(surf);
-	      OUTREG(surf, temp);
-	   }
-        }
-      }
-
-      if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn) {
-	 if (on)
-	    pI830->CursorInfoRec->ShowCursor(pScrn);
-	 else
-	    pI830->CursorInfoRec->HideCursor(pScrn);
-	 pI830->cursorOn = TRUE;
-      }
-   }
-   return TRUE;
-}
-
-static Bool
 I830CloseScreen(int scrnIndex, ScreenPtr pScreen)
 {
    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index ceb8f2e..34fa736 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -1237,6 +1237,9 @@ xf86DPMSSet(ScrnInfoPtr pScrn, int mode,
     xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
     int			i;
 
+    if (!pScrn->vtSema)
+	return;
+
     if (mode == DPMSModeOff) {
 	for (i = 0; i < config->num_output; i++) {
 	    xf86OutputPtr output = config->output[i];
@@ -1260,6 +1263,25 @@ xf86DPMSSet(ScrnInfoPtr pScrn, int mode,
     }
 }
 
+/**
+ * Implement the screensaver by just calling down into the driver DPMS hooks.
+ *
+ * Even for monitors with no DPMS support, by the definition of our DPMS hooks,
+ * the outputs will still get disabled (blanked).
+ */
+Bool
+xf86SaveScreen(ScreenPtr pScreen, int mode)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+
+    if (xf86IsUnblank(mode))
+	xf86DPMSSet(pScrn, DPMSModeOn, 0);
+    else
+	xf86DPMSSet(pScrn, DPMSModeOff, 0);
+
+    return TRUE;
+}
+
 #ifdef RANDR_12_INTERFACE
 
 #define EDID_ATOM_NAME		"EDID_DATA"
diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h
index b5f2fc2..04374b7 100644
--- a/src/i830_xf86Crtc.h
+++ b/src/i830_xf86Crtc.h
@@ -452,6 +452,9 @@ xf86InitialConfiguration (ScrnInfoPtr pS
 void
 xf86DPMSSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags);
     
+Bool
+xf86SaveScreen(ScreenPtr pScreen, int mode);
+
 /**
  * Set the EDID information for the specified output
  */
diff-tree 7161e824e89a6a69f1277e510f2344ad31721f62 (from 3094100cdd04560af1b098bbe8024ae5270a10f4)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Fri Jan 19 15:15:19 2007 +0800

    Fix DRI issue when EXA enabled
    
    tell DRI we are smashing the context state.

diff --git a/src/i965_exa_render.c b/src/i965_exa_render.c
index dc3d7bf..572efd6 100644
--- a/src/i965_exa_render.c
+++ b/src/i965_exa_render.c
@@ -369,6 +369,16 @@ I965EXAPrepareComposite(int op, PictureP
     CARD32 mask_offset = 0, mask_pitch = 0;
     CARD32 dst_format, dst_offset, dst_pitch;
 
+#ifdef XF86DRI
+    if (pI830->directRenderingEnabled) {
+        drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
+
+        pSAREAPriv->ctxOwner = DRIGetContext(pScrn->pScreen);
+    }
+#endif
+
+    pI830->last_3d = LAST_3D_RENDER;
+
     src_offset = exaGetPixmapOffset(pSrc);
     src_pitch = exaGetPixmapPitch(pSrc);
     dst_offset = exaGetPixmapOffset(pDst);
diff-tree 74ebff6732b9bfcf8c865b52cbebfd9bf6b73eb2 (from 8759f4d89a141f7d69f1894ec3059ba6bd1cf86b)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jan 18 14:26:21 2007 -0800

    Allocate separate cursor memory per CRTC and rotate cursors appropriately.
    
    Also, add bind/unbind of the shadow rotate buffers, which was missed in a
    previous commit.

diff --git a/src/i830.h b/src/i830.h
index c792073..a7c889d 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -200,6 +200,8 @@ typedef struct _I830CrtcPrivateRec {
     CARD8 lut_r[256], lut_g[256], lut_b[256];
 
     I830MemRange rotate_mem;
+    I830MemRange cursor_mem;
+    I830MemRange cursor_mem_argb;
 } I830CrtcPrivateRec, *I830CrtcPrivatePtr;
 
 #define I830CrtcPrivate(c) ((I830CrtcPrivatePtr) (c)->driver_private)
@@ -276,8 +278,6 @@ typedef struct _I830Rec {
    I830MemRange EXAStateMem;  /* specific exa state for G965 */
 #endif
    /* Regions allocated either from the above pools, or from agpgart. */
-   I830MemRange	*CursorMem;
-   I830MemRange	*CursorMemARGB;
    I830RingBuffer *LpRing;
 
 #if REMAP_RESERVED
diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index 364320e..bb5bc38 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -94,9 +94,9 @@ I830SetPipeCursorBase (xf86CrtcPtr crtc)
 	FatalError("Bad pipe number for cursor base setting\n");
 
     if (pI830->CursorIsARGB)
-	cursor_mem = pI830->CursorMemARGB;
+	cursor_mem = &intel_crtc->cursor_mem_argb;
     else
-	cursor_mem = pI830->CursorMem;
+	cursor_mem = &intel_crtc->cursor_mem;
 
     if (pI830->CursorNeedsPhysical) {
 	OUTREG(cursor_base, cursor_mem->Physical);
@@ -251,21 +251,13 @@ I830CursorInit(ScreenPtr pScreen)
    infoPtr->HideCursor = I830HideCursor;
    infoPtr->ShowCursor = I830ShowCursor;
    infoPtr->UseHWCursor = I830UseHWCursor;
-
-   pI830->pCurs = NULL;
-
 #ifdef ARGB_CURSOR
-   pI830->CursorIsARGB = FALSE;
-
-   if (pI830->CursorMemARGB->Start) {
-      /* Use ARGB if we were able to allocate the 16kb needed */
-      infoPtr->UseHWCursorARGB = I830UseHWCursorARGB;
-      infoPtr->LoadCursorARGB = I830LoadCursorARGB;
-   }
+   infoPtr->UseHWCursorARGB = I830UseHWCursorARGB;
+   infoPtr->LoadCursorARGB = I830LoadCursorARGB;
 #endif
 
-   if (pI830->CursorNeedsPhysical && !pI830->CursorMem->Physical) 
-      return FALSE;
+   pI830->pCurs = NULL;
+
 
    I830HideCursor(pScrn);
 
@@ -280,18 +272,16 @@ I830UseHWCursor(ScreenPtr pScreen, Curso
 
    pI830->pCurs = pCurs;
 
-   DPRINTF(PFX, "I830UseHWCursor\n");
-   if (pI830->CursorNeedsPhysical && !pI830->CursorMem->Physical) 
-      return FALSE;
-
    return TRUE;
 }
 
 static void
-I830LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
+I830CRTCLoadCursorImage(xf86CrtcPtr crtc, unsigned char *src)
 {
+   ScrnInfoPtr pScrn = crtc->scrn;
    I830Ptr pI830 = I830PTR(pScrn);
-   CARD8 *pcurs = (CARD8 *) (pI830->FbBase + pI830->CursorMem->Start);
+   I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+   CARD8 *pcurs = (CARD8 *) (pI830->FbBase + intel_crtc->cursor_mem.Start);
    int x, y;
 
    DPRINTF(PFX, "I830LoadCursorImage\n");
@@ -310,7 +300,7 @@ I830LoadCursorImage(ScrnInfoPtr pScrn, u
     (*(image + (x) / 8 + (y) * (128/8)) |=\
      (int) (1 <<  (7-((x) % 8))))
 
-   switch (pI830->rotation) {
+   switch (crtc->rotation) {
       case RR_Rotate_90:
          for (y = 0; y < 64; y++) {
             for (x = 0; x < 64; x++) {
@@ -353,6 +343,17 @@ I830LoadCursorImage(ScrnInfoPtr pScrn, u
    }
 }
 
+static void
+I830LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
+{
+    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int pipe;
+
+    for (pipe = 0; pipe < xf86_config->num_crtc; pipe++) {
+       I830CRTCLoadCursorImage(xf86_config->crtc[pipe], src);
+    }
+}
+
 #ifdef ARGB_CURSOR
 #include "cursorstr.h"
 
@@ -360,15 +361,22 @@ static Bool I830UseHWCursorARGB (ScreenP
 {
    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
    I830Ptr pI830 = I830PTR(pScrn);
+   xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+   int i;
 
    DPRINTF(PFX, "I830UseHWCursorARGB\n");
 
    pI830->pCurs = pCurs;
 
-   if (pScrn->bitsPerPixel == 8)
-      return FALSE;
+   /* Check that our ARGB allocations succeeded */
+   for (i = 0; i < xf86_config->num_crtc; i++) {
+      I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private;
+
+      if (!intel_crtc->cursor_mem_argb.Start)
+	 return FALSE;
+   }
 
-   if (pI830->CursorNeedsPhysical && !pI830->CursorMemARGB->Physical) 
+   if (pScrn->bitsPerPixel == 8)
       return FALSE;
 
    if (pCurs->bits->height <= 64 && pCurs->bits->width <= 64) 
@@ -377,10 +385,11 @@ static Bool I830UseHWCursorARGB (ScreenP
    return FALSE;
 }
 
-static void I830LoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs)
+static void I830CRTCLoadCursorARGB (xf86CrtcPtr crtc, CursorPtr pCurs)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
-   CARD32 *dst = (CARD32 *) (pI830->FbBase + pI830->CursorMemARGB->Start);
+   I830Ptr pI830 = I830PTR(crtc->scrn);
+   I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+   CARD32 *dst = (CARD32 *) (pI830->FbBase + intel_crtc->cursor_mem.Start);
    CARD32 *image = (CARD32 *)pCurs->bits->argb;
    int x, y, w, h;
 
@@ -394,7 +403,7 @@ static void I830LoadCursorARGB (ScrnInfo
    w = pCurs->bits->width;
    h = pCurs->bits->height;
 
-   switch (pI830->rotation) {
+   switch (crtc->rotation) {
       case RR_Rotate_90:
          for (y = 0; y < h; y++) {
             for (x = 0; x < w; x++)
@@ -447,12 +456,23 @@ static void I830LoadCursorARGB (ScrnInfo
           *dst++ = 0;
    }
 }
+
+static void
+I830LoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs)
+{
+    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int pipe;
+
+    for (pipe = 0; pipe < xf86_config->num_crtc; pipe++) {
+       I830CRTCLoadCursorARGB(xf86_config->crtc[pipe], pCurs);
+    }
+}
 #endif
 
 static void
 I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
 {
-   xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     I830Ptr pI830 = I830PTR(pScrn);
     CARD32 temp;
     Bool inrange;
@@ -473,7 +493,6 @@ I830SetCursorPosition(ScrnInfoPtr pScrn,
 	if (!crtc->enabled)
 	    continue;
 
-	/* XXX: deal with hotspot issues */
 	switch (crtc->rotation) {
 	case RR_Rotate_0:
 	    thisx = (root_x - crtc->x);
@@ -482,18 +501,18 @@ I830SetCursorPosition(ScrnInfoPtr pScrn,
 	case RR_Rotate_90:
 	    thisx = (root_y - crtc->y);
 	    thisy = mode->VDisplay - (root_x - crtc->x);
-	    /*hotspoty = I810_CURSOR_X;*/
+	    hotspoty = I810_CURSOR_X;
 	    break;
 	case RR_Rotate_180:
 	    thisx = mode->HDisplay - (root_x - crtc->x);
 	    thisy = mode->VDisplay - (root_y - crtc->y);
-	    /*hotspotx = I810_CURSOR_X;
-	      hotspoty = I810_CURSOR_Y;*/
+	    hotspotx = I810_CURSOR_X;
+	    hotspoty = I810_CURSOR_Y;
 	    break;
 	case RR_Rotate_270:
 	    thisx = mode->VDisplay - (root_y - crtc->y);
 	    thisy = (root_x - crtc->x);
-	    /*hotspotx = I810_CURSOR_Y;*/
+	    hotspotx = I810_CURSOR_Y;
 	    break;
 	}
 
@@ -542,19 +561,11 @@ I830SetCursorPosition(ScrnInfoPtr pScrn,
 static void
 I830ShowCursor(ScrnInfoPtr pScrn)
 {
-   xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-   I830Ptr pI830 = I830PTR(pScrn);
+    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    I830Ptr pI830 = I830PTR(pScrn);
     int pipe;
 
-   DPRINTF(PFX, "I830ShowCursor\n");
-   DPRINTF(PFX,
-	   "Value of CursorMem->Physical is %x, "
-	   " Value of CursorMem->Start is %x ",
-	   pI830->CursorMem->Physical, pI830->CursorMem->Start);
-   DPRINTF(PFX,
-	   "Value of CursorMemARGB->Physical is %x, "
-	   " Value of CursorMemARGB->Start is %x ",
-	   pI830->CursorMemARGB->Physical, pI830->CursorMemARGB->Start);
+    DPRINTF(PFX, "I830ShowCursor\n");
 
     pI830->cursorOn = TRUE;
     for (pipe = 0; pipe < xf86_config->num_crtc; pipe++)
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 84fd9d8..644ea57 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -765,12 +765,6 @@ PreInitCleanup(ScrnInfoPtr pScrn)
       if (pI830->LpRing)
          xfree(pI830->LpRing);
       pI830->LpRing = NULL;
-      if (pI830->CursorMem)
-         xfree(pI830->CursorMem);
-      pI830->CursorMem = NULL;
-      if (pI830->CursorMemARGB) 
-         xfree(pI830->CursorMemARGB);
-      pI830->CursorMemARGB = NULL;
       if (pI830->OverlayMem)
          xfree(pI830->OverlayMem);
       pI830->OverlayMem = NULL;
@@ -1527,12 +1521,10 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    /* Alloc our pointers for the primary head */
    if (I830IsPrimary(pScrn)) {
       pI830->LpRing = xalloc(sizeof(I830RingBuffer));
-      pI830->CursorMem = xalloc(sizeof(I830MemRange));
-      pI830->CursorMemARGB = xalloc(sizeof(I830MemRange));
       pI830->OverlayMem = xalloc(sizeof(I830MemRange));
       pI830->overlayOn = xalloc(sizeof(Bool));
       pI830->used3D = xalloc(sizeof(int));
-      if (!pI830->LpRing || !pI830->CursorMem || !pI830->CursorMemARGB ||
+      if (!pI830->LpRing ||
           !pI830->OverlayMem || !pI830->overlayOn || !pI830->used3D) {
          xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		 "Could not allocate primary data structures.\n");
@@ -2583,17 +2575,13 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    if (I830IsPrimary(pScrn)) {
       if (!pI830->LpRing)
          pI830->LpRing = xalloc(sizeof(I830RingBuffer));
-      if (!pI830->CursorMem)
-         pI830->CursorMem = xalloc(sizeof(I830MemRange));
-      if (!pI830->CursorMemARGB)
-         pI830->CursorMemARGB = xalloc(sizeof(I830MemRange));
       if (!pI830->OverlayMem)
          pI830->OverlayMem = xalloc(sizeof(I830MemRange));
       if (!pI830->overlayOn)
          pI830->overlayOn = xalloc(sizeof(Bool));
       if (!pI830->used3D)
          pI830->used3D = xalloc(sizeof(int));
-      if (!pI830->LpRing || !pI830->CursorMem || !pI830->CursorMemARGB ||
+      if (!pI830->LpRing ||
           !pI830->OverlayMem || !pI830->overlayOn || !pI830->used3D) {
          xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		 "Could not allocate primary data structures.\n");
@@ -2608,8 +2596,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    if (!I830IsPrimary(pScrn)) {
       pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
       pI830->LpRing = pI8301->LpRing;
-      pI830->CursorMem = pI8301->CursorMem;
-      pI830->CursorMemARGB = pI8301->CursorMemARGB;
       pI830->OverlayMem = pI8301->OverlayMem;
       pI830->overlayOn = pI8301->overlayOn;
       pI830->used3D = pI8301->used3D;
@@ -2658,15 +2644,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       }
    }
 
-   if (!pI830->SWCursor) {
-      if (pI830->CursorMem->Size == 0) {
-	  xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		     "Disabling HW cursor because the cursor memory "
-		      "allocation failed.\n");
-	   pI830->SWCursor = TRUE;
-      }
-   }
-
 #ifdef I830_XV
    if (pI830->XvEnabled) {
       if (pI830->noAccel) {
@@ -3354,10 +3331,6 @@ I830CloseScreen(int scrnIndex, ScreenPtr
 
       xfree(pI830->LpRing);
       pI830->LpRing = NULL;
-      xfree(pI830->CursorMem);
-      pI830->CursorMem = NULL;
-      xfree(pI830->CursorMemARGB);
-      pI830->CursorMemARGB = NULL;
       xfree(pI830->OverlayMem);
       pI830->OverlayMem = NULL;
       xfree(pI830->overlayOn);
diff --git a/src/i830_memory.c b/src/i830_memory.c
index ae14c06..14dacc8 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -826,6 +826,91 @@ I830AllocateRotateBuffers(xf86CrtcPtr cr
    return TRUE;
 }
 
+static Bool
+I830AllocateCursorBuffers(xf86CrtcPtr crtc, const int flags)
+{
+   ScrnInfoPtr pScrn = crtc->scrn;
+   I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+   I830Ptr pI830 = I830PTR(pScrn);
+   Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
+   int verbosity = dryrun ? 4 : 1;
+   const char *s = dryrun ? "[dryrun] " : "";
+   long size, alloced;
+   int cursFlags = 0;
+
+   /* Clear cursor info */
+   memset(&intel_crtc->cursor_mem, 0, sizeof(I830MemRange));
+   intel_crtc->cursor_mem.Key = -1;
+   memset(&intel_crtc->cursor_mem_argb, 0, sizeof(I830MemRange));
+   intel_crtc->cursor_mem_argb.Key = -1;
+
+   if (pI830->SWCursor)
+      return FALSE;
+
+   /*
+    * Mouse cursor -- The i810-i830 need a physical address in system
+    * memory from which to upload the cursor.  We get this from
+    * the agpgart module using a special memory type.
+    */
+
+   size = HWCURSOR_SIZE;
+   cursFlags = FROM_ANYWHERE | ALLOCATE_AT_TOP;
+   if (pI830->CursorNeedsPhysical)
+      cursFlags |= NEED_PHYSICAL_ADDR;
+
+   alloced = I830AllocVidMem(pScrn, &intel_crtc->cursor_mem,
+			     &pI830->StolenPool, size,
+			     GTT_PAGE_SIZE, flags | cursFlags);
+   if (alloced < size ||
+       (pI830->CursorNeedsPhysical && !intel_crtc->cursor_mem.Physical))
+   {
+      if (!dryrun) {
+	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		    "Failed to allocate HW cursor space.\n");
+	 return FALSE;
+      }
+   } else {
+      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		     "%sAllocated %ld kB for HW cursor at 0x%lx", s,
+		     alloced / 1024, intel_crtc->cursor_mem.Start);
+      if (pI830->CursorNeedsPhysical) {
+	 xf86ErrorFVerb(verbosity, " (0x%08lx)",
+			intel_crtc->cursor_mem.Physical);
+      }
+      xf86ErrorFVerb(verbosity, "\n");
+   }
+
+   /* Allocate the ARGB cursor space.  Its success is optional -- we won't set
+    * SWCursor if it fails.
+    */
+   size = HWCURSOR_SIZE_ARGB;
+   cursFlags = FROM_ANYWHERE | ALLOCATE_AT_TOP;
+   if (pI830->CursorNeedsPhysical)
+      cursFlags |= NEED_PHYSICAL_ADDR;
+
+   alloced = I830AllocVidMem(pScrn, &intel_crtc->cursor_mem_argb,
+			     &pI830->StolenPool, size,
+			     GTT_PAGE_SIZE, flags | cursFlags);
+   if (alloced < size ||
+       (pI830->CursorNeedsPhysical && !intel_crtc->cursor_mem_argb.Physical)) {
+      if (!dryrun) {
+	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		    "Failed to allocate HW (ARGB) cursor space.\n");
+      }
+   } else {
+      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		     "%sAllocated %ld kB for HW (ARGB) cursor at 0x%lx", s,
+		     alloced / 1024, intel_crtc->cursor_mem_argb.Start);
+      if (pI830->CursorNeedsPhysical) {
+	 xf86ErrorFVerb(verbosity, " (0x%08lx)",
+			intel_crtc->cursor_mem_argb.Physical);
+      }
+      xf86ErrorFVerb(verbosity, "\n");
+   }
+
+   return FALSE;
+}
+
 /*
  * Allocate memory for 2D operation.  This includes the (front) framebuffer,
  * ring buffer, scratch memory, HW cursor.
@@ -834,6 +919,7 @@ Bool
 I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags)
 {
    I830Ptr pI830 = I830PTR(pScrn);
+   xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
    long size, alloced;
    Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
    int verbosity = dryrun ? 4 : 1;
@@ -871,8 +957,6 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
 	   pI830->StolenPool.Free.Size);
 
    if (flags & ALLOC_INITIAL) {
-      xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-
       if (pI830->NeedRingBufferLow)
 	 AllocateRingBuffer(pScrn, flags | FORCE_LOW);
 
@@ -1041,63 +1125,18 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
    }
 #endif
 
-   /* Clear cursor info */
-   memset(pI830->CursorMem, 0, sizeof(I830MemRange));
-   pI830->CursorMem->Key = -1;
-   memset(pI830->CursorMemARGB, 0, sizeof(I830MemRange));
-   pI830->CursorMemARGB->Key = -1;
-
-   if (!pI830->SWCursor) {
-      int cursFlags = 0;
-      /*
-       * Mouse cursor -- The i810-i830 need a physical address in system
-       * memory from which to upload the cursor.  We get this from
-       * the agpgart module using a special memory type.
-       */
-
-      size = HWCURSOR_SIZE;
-      cursFlags = FROM_ANYWHERE | ALLOCATE_AT_TOP;
-      if (pI830->CursorNeedsPhysical)
-	 cursFlags |= NEED_PHYSICAL_ADDR;
-
-      alloced = I830AllocVidMem(pScrn, pI830->CursorMem,
-				&(pI830->StolenPool), size,
-				GTT_PAGE_SIZE, flags | cursFlags);
-      if (alloced < size) {
-	 if (!dryrun) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		       "Failed to allocate HW cursor space.\n");
-	 }
-      } else {
-	 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-			"%sAllocated %ld kB for HW cursor at 0x%lx", s,
-			alloced / 1024, pI830->CursorMem->Start);
-	 if (pI830->CursorNeedsPhysical)
-	    xf86ErrorFVerb(verbosity, " (0x%08lx)", pI830->CursorMem->Physical);
-	 xf86ErrorFVerb(verbosity, "\n");
-      }
-
-      size = HWCURSOR_SIZE_ARGB;
-      cursFlags = FROM_ANYWHERE | ALLOCATE_AT_TOP;
-      if (pI830->CursorNeedsPhysical)
-	 cursFlags |= NEED_PHYSICAL_ADDR;
-
-      alloced = I830AllocVidMem(pScrn, pI830->CursorMemARGB,
-				&(pI830->StolenPool), size,
-				GTT_PAGE_SIZE, flags | cursFlags);
-      if (alloced < size) {
-	 if (!dryrun) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		       "Failed to allocate HW (ARGB) cursor space.\n");
-	 }
-      } else {
-	 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-			"%sAllocated %ld kB for HW (ARGB) cursor at 0x%lx", s,
-			alloced / 1024, pI830->CursorMemARGB->Start);
-	 if (pI830->CursorNeedsPhysical)
-	    xf86ErrorFVerb(verbosity, " (0x%08lx)", pI830->CursorMemARGB->Physical);
-	 xf86ErrorFVerb(verbosity, "\n");
-      }
+   if (!pI830->SWCursor && !dryrun) {
+       for (i = 0; i < xf86_config->num_crtc; i++) {
+	   if (!I830AllocateCursorBuffers(xf86_config->crtc[i], flags) &&
+	       pI830->SWCursor)
+	   {
+	       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+			  "Disabling HW cursor because the cursor memory "
+			  "allocation failed.\n");
+	       pI830->SWCursor = TRUE;
+	       break;
+	   }
+       }
    }
 
 #ifdef I830_XV
@@ -1567,6 +1606,8 @@ Bool
 I830FixupOffsets(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
+   xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+   int i;
 
    DPRINTF(PFX, "I830FixupOffsets\n");
 
@@ -1574,8 +1615,15 @@ I830FixupOffsets(ScrnInfoPtr pScrn)
    if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2)
       I830FixOffset(pScrn, &(pI830->FrontBuffer2));
    I830FixOffset(pScrn, &(pI830->FrontBuffer));
-   I830FixOffset(pScrn, pI830->CursorMem);
-   I830FixOffset(pScrn, pI830->CursorMemARGB);
+
+   for (i = 0; i < xf86_config->num_crtc; i++) {
+      I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private;
+
+      I830FixOffset(pScrn, &intel_crtc->rotate_mem);
+      I830FixOffset(pScrn, &intel_crtc->cursor_mem);
+      I830FixOffset(pScrn, &intel_crtc->cursor_mem_argb);
+   }
+
    I830FixOffset(pScrn, &(pI830->LpRing->mem));
    I830FixOffset(pScrn, &(pI830->Scratch));
    if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2)
@@ -1958,6 +2006,9 @@ I830BindAGPMemory(ScrnInfoPtr pScrn)
       return TRUE;
 
    if (xf86AgpGARTSupported() && !pI830->GttBound) {
+      xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+      int i;
+
       if (!xf86AcquireGART(pScrn->scrnIndex))
 	 return FALSE;
 
@@ -1973,10 +2024,17 @@ I830BindAGPMemory(ScrnInfoPtr pScrn)
 	    return FALSE;
       if (!BindMemRange(pScrn, &(pI830->FrontBuffer)))
 	 return FALSE;
-      if (!BindMemRange(pScrn, pI830->CursorMem))
-	 return FALSE;
-      if (!BindMemRange(pScrn, pI830->CursorMemARGB))
-	 return FALSE;
+
+      for (i = 0; i < xf86_config->num_crtc; i++) {
+	 I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private;
+
+	 if (!BindMemRange(pScrn, &intel_crtc->rotate_mem))
+	    return FALSE;
+	 if (!BindMemRange(pScrn, &intel_crtc->cursor_mem))
+	    return FALSE;
+	 if (!BindMemRange(pScrn, &intel_crtc->cursor_mem_argb))
+	    return FALSE;
+      }
       if (!BindMemRange(pScrn, &(pI830->LpRing->mem)))
 	 return FALSE;
       if (!BindMemRange(pScrn, &(pI830->Scratch)))
@@ -2053,6 +2111,8 @@ I830UnbindAGPMemory(ScrnInfoPtr pScrn)
       return TRUE;
 
    if (xf86AgpGARTSupported() && pI830->GttBound) {
+      xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+      int i;
 
 #if REMAP_RESERVED
       /* "unbind" the pre-allocated region. */
@@ -2066,10 +2126,18 @@ I830UnbindAGPMemory(ScrnInfoPtr pScrn)
 	    return FALSE;
       if (!UnbindMemRange(pScrn, &(pI830->FrontBuffer)))
 	 return FALSE;
-      if (!UnbindMemRange(pScrn, pI830->CursorMem))
-	 return FALSE;
-      if (!UnbindMemRange(pScrn, pI830->CursorMemARGB))
-	 return FALSE;
+
+      for (i = 0; i < xf86_config->num_crtc; i++) {
+	 I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private;
+
+	 if (!UnbindMemRange(pScrn, &intel_crtc->rotate_mem))
+	    return FALSE;
+	 if (!UnbindMemRange(pScrn, &intel_crtc->cursor_mem))
+	    return FALSE;
+	 if (!UnbindMemRange(pScrn, &intel_crtc->cursor_mem_argb))
+	    return FALSE;
+      }
+
       if (!UnbindMemRange(pScrn, &(pI830->LpRing->mem)))
 	 return FALSE;
       if (!UnbindMemRange(pScrn, &(pI830->Scratch)))
diff-tree 8759f4d89a141f7d69f1894ec3059ba6bd1cf86b (from b296cd9b8f63ab80e8fe46fcfcdba2e9af846468)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jan 18 13:13:25 2007 -0800

    Partially deal with cursor rotation.
    
    The remaining issue is having a cursor image per CRTC so that the cursors can
    be rotated on the independently rotated CRTCs.

diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index 5e7a21a..364320e 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -456,49 +456,50 @@ I830SetCursorPosition(ScrnInfoPtr pScrn,
     I830Ptr pI830 = I830PTR(pScrn);
     CARD32 temp;
     Bool inrange;
-    int oldx = x, oldy = y;
-    int hotspotx = 0, hotspoty = 0;
+    int root_x = x, root_y = y;
     int pipe;
 
-    oldx += pScrn->frameX0; /* undo what xf86HWCurs did */
-    oldy += pScrn->frameY0;
-
-    switch (pI830->rotation) {
-    case RR_Rotate_0:
-	x = oldx;
-	y = oldy;
-	break;
-    case RR_Rotate_90:
-	x = oldy;
-	y = pScrn->pScreen->width - oldx;
-	hotspoty = I810_CURSOR_X;
-	break;
-    case RR_Rotate_180:
-	x = pScrn->pScreen->width - oldx;
-	y = pScrn->pScreen->height - oldy;
-	hotspotx = I810_CURSOR_X;
-	hotspoty = I810_CURSOR_Y;
-	break;
-    case RR_Rotate_270:
-	x = pScrn->pScreen->height - oldy;
-	y = oldx;
-	hotspotx = I810_CURSOR_Y;
-	break;
-    }
-
-    x -= hotspotx;
-    y -= hotspoty;
+    root_x = x + pScrn->frameX0; /* undo what xf86HWCurs did */
+    root_y = y + pScrn->frameY0;
 
     for (pipe = 0; pipe < xf86_config->num_crtc; pipe++)
     {
-	xf86CrtcPtr    crtc = xf86_config->crtc[pipe];
+	xf86CrtcPtr	    crtc = xf86_config->crtc[pipe];
 	DisplayModePtr	    mode = &crtc->mode;
-	int		    thisx = x - crtc->x;
-	int		    thisy = y - crtc->y;
+	int		    thisx;
+	int		    thisy;
+	int hotspotx = 0, hotspoty = 0;
 
 	if (!crtc->enabled)
 	    continue;
 
+	/* XXX: deal with hotspot issues */
+	switch (crtc->rotation) {
+	case RR_Rotate_0:
+	    thisx = (root_x - crtc->x);
+	    thisy = (root_y - crtc->y);
+	    break;
+	case RR_Rotate_90:
+	    thisx = (root_y - crtc->y);
+	    thisy = mode->VDisplay - (root_x - crtc->x);
+	    /*hotspoty = I810_CURSOR_X;*/
+	    break;
+	case RR_Rotate_180:
+	    thisx = mode->HDisplay - (root_x - crtc->x);
+	    thisy = mode->VDisplay - (root_y - crtc->y);
+	    /*hotspotx = I810_CURSOR_X;
+	      hotspoty = I810_CURSOR_Y;*/
+	    break;
+	case RR_Rotate_270:
+	    thisx = mode->VDisplay - (root_y - crtc->y);
+	    thisy = (root_x - crtc->x);
+	    /*hotspotx = I810_CURSOR_Y;*/
+	    break;
+	}
+
+	thisx -= hotspotx;
+	thisy -= hotspoty;
+
 	/*
 	 * There is a screen display problem when the cursor position is set
 	 * wholely outside of the viewport.  We trap that here, turning the
diff-tree b296cd9b8f63ab80e8fe46fcfcdba2e9af846468 (from d2ae2e2ccc3a8e7dc84745c235836cba150754d8)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jan 18 13:02:26 2007 -0800

    Fix transformation matrices for rotation at 90 and 270 degrees.

diff --git a/src/i830_xf86Rotate.c b/src/i830_xf86Rotate.c
index 670ad7a..8da79b6 100644
--- a/src/i830_xf86Rotate.c
+++ b/src/i830_xf86Rotate.c
@@ -144,23 +144,20 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crt
 	transform.matrix[1][1] = IntToxFixed(1);
 	break;
     case RR_Rotate_90:
-	/* XXX probably wrong */
-	transform.matrix[0][1] = IntToxFixed(1);
-	transform.matrix[1][0] = IntToxFixed(-1);
-	transform.matrix[1][2] += IntToxFixed(crtc->mode.HDisplay);
+	transform.matrix[0][1] = IntToxFixed(-1);
+	transform.matrix[1][0] = IntToxFixed(1);
+	transform.matrix[0][2] += IntToxFixed(crtc->mode.VDisplay);
 	break;
     case RR_Rotate_180:
-	/* XXX probably wrong */
 	transform.matrix[0][0] = IntToxFixed(-1);
 	transform.matrix[1][1] = IntToxFixed(-1);
 	transform.matrix[0][2] += IntToxFixed(crtc->mode.HDisplay);
 	transform.matrix[1][2] += IntToxFixed(crtc->mode.VDisplay);
 	break;
     case RR_Rotate_270:
-	/* XXX probably wrong */
-	transform.matrix[0][1] = IntToxFixed(-1);
-	transform.matrix[1][0] = IntToxFixed(1);
-	transform.matrix[0][2] += IntToxFixed(crtc->mode.VDisplay);
+	transform.matrix[0][1] = IntToxFixed(1);
+	transform.matrix[1][0] = IntToxFixed(-1);
+	transform.matrix[1][2] += IntToxFixed(crtc->mode.VDisplay);
 	break;
     }
 
diff-tree d2ae2e2ccc3a8e7dc84745c235836cba150754d8 (from 92b0f3d2013c32d94fe57fe674da1b195288f347)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jan 18 11:37:14 2007 -0800

    Update CRTC values first so they can be used by the driver in mode setting.
    
    With this, the screen now gets rotated, though there are major issues.

diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index a926e9f..c879d99 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -154,6 +154,9 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, Displ
     Bool		ret = FALSE;
     Bool		didLock = FALSE;
     DisplayModePtr	adjusted_mode;
+    DisplayModeRec	saved_mode;
+    int			saved_x, saved_y;
+    Rotation		saved_rotation;
 
     adjusted_mode = xf86DuplicateMode(mode);
 
@@ -167,6 +170,18 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, Displ
 
     didLock = crtc->funcs->lock (crtc);
 
+    saved_mode = crtc->mode;
+    saved_x = crtc->x;
+    saved_y = crtc->y;
+    saved_rotation = crtc->rotation;
+    /* Update crtc values up front so the driver can rely on them for mode
+     * setting.
+     */
+    crtc->mode = *mode;
+    crtc->x = x;
+    crtc->y = y;
+    crtc->rotation = rotation;
+
     /* XXX short-circuit changes to base location only */
     
     /* Pass our mode to the outputs and the CRTC to give them a chance to
@@ -180,18 +195,15 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, Displ
 	    continue;
 
 	if (!output->funcs->mode_fixup(output, mode, adjusted_mode)) {
-	    ret = FALSE;
 	    goto done;
 	}
     }
 
     if (!crtc->funcs->mode_fixup(crtc, mode, adjusted_mode)) {
-	ret = FALSE;
 	goto done;
     }
 
     if (!xf86CrtcRotate (crtc, mode, rotation)) {
-	ret = FALSE;
 	goto done;
     }
 
@@ -228,14 +240,16 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, Displ
 	    output->funcs->dpms(output, DPMSModeOn);
     }
 
-    crtc->mode = *mode;
-    crtc->x = x;
-    crtc->y = y;
-    crtc->rotation = rotation;
-
     /* XXX free adjustedmode */
     ret = TRUE;
 done:
+    if (!ret) {
+	crtc->x = saved_x;
+	crtc->y = saved_y;
+	crtc->rotation = saved_rotation;
+	crtc->mode = saved_mode;
+    }
+
     if (didLock)
 	crtc->funcs->unlock (crtc);
 
diff-tree 92b0f3d2013c32d94fe57fe674da1b195288f347 (from 14d265a02312e9cda7a21614d77525c7140c0ca8)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jan 18 11:23:22 2007 -0800

    Disable the clipping for now, since it won't work.

diff --git a/src/i830_xf86Rotate.c b/src/i830_xf86Rotate.c
index 39733fd..670ad7a 100644
--- a/src/i830_xf86Rotate.c
+++ b/src/i830_xf86Rotate.c
@@ -127,7 +127,13 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crt
 	ErrorF("couldn't create src pict\n");
 	return;
     }
-    SetPictureClipRegion (src, 0, 0, region);
+    /* Unfortunately, we don't do clipping on transformed source pictures.
+     * So we can't use this.  Instead, we'll just repaint the whole screen
+     * for now, and do transform of the source region into a dest region
+     * later.
+     */
+    /* SetPictureClipRegion (src, 0, 0, region); */
+
     memset (&transform, '\0', sizeof (transform));
     transform.matrix[2][2] = IntToxFixed(1);
     transform.matrix[0][2] = IntToxFixed(crtc->x);
diff-tree 14d265a02312e9cda7a21614d77525c7140c0ca8 (from cc09dc3efe7279bf67512babb0f6cdaeba654772)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jan 18 11:21:58 2007 -0800

    Store fixed values, not integers, in the transformation matrix.
    
    Also, add a bit more error checking.

diff --git a/src/i830_xf86Rotate.c b/src/i830_xf86Rotate.c
index 14c0c5d..39733fd 100644
--- a/src/i830_xf86Rotate.c
+++ b/src/i830_xf86Rotate.c
@@ -112,8 +112,10 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crt
 			 NULL,
 			 serverClient,
 			 &error);
-    if (!src)
+    if (!src) {
+	ErrorF("couldn't create src pict\n");
 	return;
+    }
     dst = CreatePicture (None,
 			 &dst_pixmap->drawable,
 			 format,
@@ -121,38 +123,41 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crt
 			 NULL,
 			 serverClient,
 			 &error);
-    if (!dst)
+    if (!dst) {
+	ErrorF("couldn't create src pict\n");
 	return;
+    }
     SetPictureClipRegion (src, 0, 0, region);
     memset (&transform, '\0', sizeof (transform));
-    transform.matrix[2][2] = 1;
-    transform.matrix[0][2] = crtc->x;
-    transform.matrix[1][2] = crtc->y;
+    transform.matrix[2][2] = IntToxFixed(1);
+    transform.matrix[0][2] = IntToxFixed(crtc->x);
+    transform.matrix[1][2] = IntToxFixed(crtc->y);
     switch (crtc->rotation & 0xf) {
     case RR_Rotate_0:
-	transform.matrix[0][0] = 1;
-	transform.matrix[1][1] = 1;
+	transform.matrix[0][0] = IntToxFixed(1);
+	transform.matrix[1][1] = IntToxFixed(1);
 	break;
     case RR_Rotate_90:
 	/* XXX probably wrong */
-	transform.matrix[0][1] = 1;
-	transform.matrix[1][0] = -1;
-	transform.matrix[1][2] += crtc->mode.HDisplay;
+	transform.matrix[0][1] = IntToxFixed(1);
+	transform.matrix[1][0] = IntToxFixed(-1);
+	transform.matrix[1][2] += IntToxFixed(crtc->mode.HDisplay);
 	break;
     case RR_Rotate_180:
 	/* XXX probably wrong */
-	transform.matrix[0][0] = -1;
-	transform.matrix[1][1] = -1;
-	transform.matrix[0][2] += crtc->mode.HDisplay;
-	transform.matrix[1][2] += crtc->mode.VDisplay;
+	transform.matrix[0][0] = IntToxFixed(-1);
+	transform.matrix[1][1] = IntToxFixed(-1);
+	transform.matrix[0][2] += IntToxFixed(crtc->mode.HDisplay);
+	transform.matrix[1][2] += IntToxFixed(crtc->mode.VDisplay);
 	break;
     case RR_Rotate_270:
 	/* XXX probably wrong */
-	transform.matrix[0][1] = -1;
-	transform.matrix[1][0] = 1;
-	transform.matrix[0][2] += crtc->mode.VDisplay;
+	transform.matrix[0][1] = IntToxFixed(-1);
+	transform.matrix[1][0] = IntToxFixed(1);
+	transform.matrix[0][2] += IntToxFixed(crtc->mode.VDisplay);
 	break;
     }
+
     /* handle reflection */
     if (crtc->rotation & RR_Reflect_X)
     {
@@ -162,7 +167,13 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crt
     {
 	/* XXX figure this out too */
     }
-    SetPictureTransform (src, &transform);
+
+    error = SetPictureTransform (src, &transform);
+    if (error) {
+	ErrorF("Couldn't set transform\n");
+	return;
+    }
+
     CompositePicture (PictOpSrc,
 		      src, NULL, dst,
 		      0, 0, 0, 0, 0, 0,
diff-tree cc09dc3efe7279bf67512babb0f6cdaeba654772 (from parents)
Merge: 53e765d1cf5016961c25a798a27f0fe09bd1f237 3094100cdd04560af1b098bbe8024ae5270a10f4
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jan 18 10:20:36 2007 -0800

    Merge branch 'modesetting' into modesetting-rotation

diff-tree 53e765d1cf5016961c25a798a27f0fe09bd1f237 (from f256243fff195f73bc8aa72e8dd2c6f7b33446cf)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Jan 17 16:56:06 2007 -0800

    Fix broken last-minute change in determining whether we're rotated or not.

diff --git a/src/i830_display.c b/src/i830_display.c
index 08842ec..2313f76 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -342,7 +342,7 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x,
     int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE);
     int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
 
-    if (intel_crtc->rotate_mem.Start != 0) {
+    if (crtc->rotation != RR_Rotate_0) {
 	Start = intel_crtc->rotate_mem.Start;
     } else if (I830IsPrimary(pScrn)) {
 	Start = pI830->FrontBuffer.Start;
diff-tree f256243fff195f73bc8aa72e8dd2c6f7b33446cf (from d17c386aee55bd223297adf78cf0fc1db43baf2d)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Jan 17 16:01:18 2007 -0800

    Allocate per-crtc rotation buffers and hook up RandR 1.2 per-CRTC rotation.
    
    It currently displays garbage.

diff --git a/src/i830.h b/src/i830.h
index 66dad9b..c792073 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -195,8 +195,11 @@ extern const char *i830_output_type_name
 
 typedef struct _I830CrtcPrivateRec {
     int			    pipe;
+
     /* Lookup table values to be set when the CRTC is enabled */
     CARD8 lut_r[256], lut_g[256], lut_b[256];
+
+    I830MemRange rotate_mem;
 } I830CrtcPrivateRec, *I830CrtcPrivatePtr;
 
 #define I830CrtcPrivate(c) ((I830CrtcPrivatePtr) (c)->driver_private)
diff --git a/src/i830_display.c b/src/i830_display.c
index de6c722..08842ec 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -342,9 +342,11 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x,
     int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE);
     int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
 
-    if (I830IsPrimary(pScrn))
+    if (intel_crtc->rotate_mem.Start != 0) {
+	Start = intel_crtc->rotate_mem.Start;
+    } else if (I830IsPrimary(pScrn)) {
 	Start = pI830->FrontBuffer.Start;
-    else {
+    } else {
 	I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
 	Start = pI8301->FrontBuffer2.Start;
     }
@@ -883,6 +885,45 @@ i830_crtc_gamma_set(xf86CrtcPtr crtc, CA
 }
 
 /**
+ * Creates a locked-in-framebuffer pixmap of the given width and height for
+ * this CRTC's rotated shadow framebuffer.
+ *
+ * The current implementation uses fixed buffers allocated at startup at the
+ * maximal size.
+ */
+static PixmapPtr
+i830_crtc_shadow_create(xf86CrtcPtr crtc, int width, int height)
+{
+    ScrnInfoPtr pScrn = crtc->scrn;
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+    unsigned long rotate_pitch;
+    PixmapPtr rotate_pixmap;
+    pointer rotate_offset;
+
+    if (intel_crtc->rotate_mem.Start == 0)
+	return NULL;
+
+    rotate_pitch = pI830->displayWidth * pI830->cpp;
+    rotate_offset = pI830->FbBase + intel_crtc->rotate_mem.Start;
+
+    rotate_pixmap = GetScratchPixmapHeader(pScrn->pScreen,
+					   width, height,
+					   pScrn->depth,
+					   pScrn->bitsPerPixel,
+					   rotate_pitch,
+					   rotate_offset);
+    return rotate_pixmap;
+}
+
+static void
+i830_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap)
+{
+    FreeScratchPixmapHeader(rotate_pixmap);
+}
+
+
+/**
  * This function configures the screens in clone mode on
  * all active outputs using a mode similar to the specified mode.
  */
@@ -1038,6 +1079,8 @@ static const xf86CrtcFuncsRec i830_crtc_
     .mode_fixup = i830_crtc_mode_fixup,
     .mode_set = i830_crtc_mode_set,
     .gamma_set = i830_crtc_gamma_set,
+    .shadow_create = i830_crtc_shadow_create,
+    .shadow_destroy = i830_crtc_shadow_destroy,
     .destroy = NULL, /* XXX */
 };
 
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 426242a..ae14c06 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -769,6 +769,63 @@ I830AllocateFramebuffer(ScrnInfoPtr pScr
    return TRUE;
 }
 
+/**
+ * Allocates memory for the rotated shadow buffers.
+ *
+ * This memory would be better allocated normally through the linear allocator,
+ * but it gets rotation working for now.
+ */
+static Bool
+I830AllocateRotateBuffers(xf86CrtcPtr crtc, const int flags)
+{
+   ScrnInfoPtr pScrn = crtc->scrn;
+   I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+   I830Ptr pI830 = I830PTR(pScrn);
+   Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
+   unsigned long avail, lineSize;
+   int verbosity = dryrun ? 4 : 1;
+   const char *s = dryrun ? "[dryrun] " : "";
+   int align, alignflags;
+   long size, alloced;
+   int rotate_width, rotate_height;
+
+   memset(&intel_crtc->rotate_mem, 0, sizeof(intel_crtc->rotate_mem));
+
+   rotate_width = pScrn->displayWidth;
+   if (pScrn->virtualX > pScrn->virtualY)
+      rotate_height = pScrn->virtualX;
+   else
+      rotate_height = pScrn->virtualY;
+
+   lineSize = pScrn->displayWidth * pI830->cpp;
+   avail = pScrn->videoRam * 1024;
+
+   align = KB(64);
+   alignflags = 0;
+
+   size = lineSize * rotate_height;
+   size = ROUND_TO_PAGE(size);
+   xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		  "%sInitial %sshadow framebuffer allocation size: "
+		  "%ld kByte\n",
+		  s, (intel_crtc->pipe == 0) ? "" : "secondary ",
+		  size / 1024);
+   alloced = I830AllocVidMem(pScrn, &intel_crtc->rotate_mem,
+			     &pI830->StolenPool, size, align,
+			     flags | alignflags |
+			     FROM_ANYWHERE | ALLOCATE_AT_BOTTOM);
+   if (alloced < size) {
+      if (!dryrun) {
+	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate "
+		    "%sshadow framebuffer. Is your VideoRAM set too low?\n",
+		    (intel_crtc->pipe == 0) ? "" : "secondary ");
+      }
+      return FALSE;
+   }
+
+   return TRUE;
+}
+
 /*
  * Allocate memory for 2D operation.  This includes the (front) framebuffer,
  * ring buffer, scratch memory, HW cursor.
@@ -782,7 +839,7 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
    int verbosity = dryrun ? 4 : 1;
    const char *s = dryrun ? "[dryrun] " : "";
    Bool tileable;
-   int align, alignflags;
+   int align, alignflags, i;
 
    DPRINTF(PFX, "I830Allocate2DMemory: inital is %s\n",
 	   BOOLTOSTRING(flags & ALLOC_INITIAL));
@@ -814,6 +871,7 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
 	   pI830->StolenPool.Free.Size);
 
    if (flags & ALLOC_INITIAL) {
+      xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
 
       if (pI830->NeedRingBufferLow)
 	 AllocateRingBuffer(pScrn, flags | FORCE_LOW);
@@ -839,6 +897,10 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
 	 return FALSE;
       }
 
+      for (i = 0; i < xf86_config->num_crtc; i++) {
+	 I830AllocateRotateBuffers(xf86_config->crtc[i], flags);
+      }
+
 #ifdef I830_USE_EXA
       if (pI830->useEXA) {
 	 /* Default EXA to having 3 screens worth of offscreen memory space
diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index 504ea0b..a926e9f 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -190,13 +190,10 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, Displ
 	goto done;
     }
 
-#if 0
-    if (!xf86CrtcRotate (crtc, mode, rotation))
-    {
+    if (!xf86CrtcRotate (crtc, mode, rotation)) {
 	ret = FALSE;
 	goto done;
     }
-#endif
 
     /* Disable the outputs and CRTCs before setting the mode. */
     for (i = 0; i < xf86_config->num_output; i++) {
diff-tree d17c386aee55bd223297adf78cf0fc1db43baf2d (from 67a152c43cb7231695b99030c952c52d4edd1e65)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Jan 17 15:49:08 2007 -0800

    Fix some segfaults: crtc->rotatedPixmap not set and dangling damage pointer.

diff --git a/src/i830_xf86Rotate.c b/src/i830_xf86Rotate.c
index 5482a6e..14c0c5d 100644
--- a/src/i830_xf86Rotate.c
+++ b/src/i830_xf86Rotate.c
@@ -247,6 +247,8 @@ xf86CrtcRotate (xf86CrtcPtr crtc, Displa
 	if (xf86_config->rotationDamage)
 	{
 	    /* Free damage structure */
+	    DamageUnregister (&(*pScreen->GetScreenPixmap)(pScreen)->drawable,
+			      xf86_config->rotationDamage);
 	    DamageDestroy (xf86_config->rotationDamage);
 	    xf86_config->rotationDamage = NULL;
 	    /* Free block/wakeup handler */
@@ -274,6 +276,7 @@ xf86CrtcRotate (xf86CrtcPtr crtc, Displa
 	    shadow = crtc->funcs->shadow_create (crtc, width, height);
 	    if (!shadow)
 		goto bail1;
+	    crtc->rotatedPixmap = shadow;
 	}
 	
 	if (!xf86_config->rotationDamage)
diff-tree 67a152c43cb7231695b99030c952c52d4edd1e65 (from a52df90ffcb19e7c0a3b8018db3cd1391a3ec343)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Jan 17 14:35:31 2007 -0800

    Set all CRTCs' allowable rotations when xf86RandR12SetRotations() is called.

diff --git a/src/i830_randr.c b/src/i830_randr.c
index 3aaf88b..c1e9ac0 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -494,8 +494,19 @@ void
 xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotations)
 {
     XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
+    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int			c;
 
     randrp->supported_rotations = rotations;
+
+#if RANDR_12_INTERFACE
+    for (c = 0; c < config->num_crtc; c++) {
+	xf86CrtcPtr    crtc = config->crtc[c];
+
+	RRCrtcSetRotations (crtc->randr_crtc, rotations);
+    }
+#endif
 }
 
 void
diff-tree 3094100cdd04560af1b098bbe8024ae5270a10f4 (from 66c6427cc83e5e381932b0c10743cba4cb9ac883)
Author: Gary Wong <gtw at gnu.org>
Date:   Tue Jan 16 13:25:24 2007 -0800

    Bug #9550: Add a quirk for too-high clock from EDID on the EN-7100e.

diff --git a/src/i830_edid_modes.c b/src/i830_edid_modes.c
index 249f87a..1bab4cd 100644
--- a/src/i830_edid_modes.c
+++ b/src/i830_edid_modes.c
@@ -52,6 +52,8 @@ typedef enum {
     DDC_QUIRK_DT_SYNC_HM_VP = 1 << 0,
     /* First detailed mode is bogus, prefer largest mode at 60hz */
     DDC_QUIRK_PREFER_LARGE_60 = 1 << 1,
+    /* 135MHz clock is too high, drop a bit */
+    DDC_QUIRK_135_CLOCK_TOO_HIGH = 1 << 2
 } ddc_quirk_t;
 
 static Bool quirk_dt_sync_hm_vp (int scrnIndex, xf86MonPtr DDC)
@@ -78,6 +80,16 @@ static Bool quirk_prefer_large_60 (int s
     return FALSE;
 }
 
+static Bool quirk_135_clock_too_high (int scrnIndex, xf86MonPtr DDC)
+{
+    /* Envision Peripherals, Inc. EN-7100e.  See bug #9550. */
+    if (memcmp (DDC->vendor.name, "EPI", 4) == 0 &&
+	DDC->vendor.prod_id == 59264)
+	return TRUE;
+    
+    return FALSE;
+}
+
 typedef struct {
     Bool	(*detect) (int scrnIndex, xf86MonPtr DDC);
     ddc_quirk_t	quirk;
@@ -93,6 +105,10 @@ static const ddc_quirk_map_t ddc_quirks[
 	quirk_prefer_large_60,   DDC_QUIRK_PREFER_LARGE_60,
 	"Detailed timing is not preferred, use largest mode at 60Hz"
     },
+    {
+	quirk_135_clock_too_high,   DDC_QUIRK_135_CLOCK_TOO_HIGH,
+	"Recommended 135MHz pixel clock is too high"
+    },
     { 
 	NULL,		DDC_QUIRK_NONE,
 	"No known quirks"
@@ -197,7 +213,11 @@ DDCModeFromDetailedTiming(int scrnIndex,
     if (preferred)
 	Mode->type |= M_T_PREFERRED;
 
-    Mode->Clock = timing->clock / 1000.0;
+    if( ( quirks & DDC_QUIRK_135_CLOCK_TOO_HIGH ) &&
+	timing->clock == 135000000 )
+        Mode->Clock = 108880;
+    else
+        Mode->Clock = timing->clock / 1000.0;
 
     Mode->HDisplay = timing->h_active;
     Mode->HSyncStart = timing->h_active + timing->h_sync_off;
diff-tree 66c6427cc83e5e381932b0c10743cba4cb9ac883 (from 45696aa29124e2852f94880642e70bb2e0cee827)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Jan 16 12:54:29 2007 -0800

    Add a settable backlight property for LVDS.
    
    This extends the output funcs to have a callback for when it's time to
    configure properties, and another for when the server has changed a property
    whose value isn't pending a mode set. (Pending properties are to be picked up
    by the driver at mode_set time).

diff --git a/src/i810_reg.h b/src/i810_reg.h
index c2eb854..33b059d 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -937,8 +937,21 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 #define BLC_PWM_CTL		0x61254
 #define BACKLIGHT_MODULATION_FREQ_SHIFT		(17)
+/**
+ * This is the most significant 15 bits of the number of backlight cycles in a
+ * complete cycle of the modulated backlight control.
+ *
+ * The actual value is this field multiplied by two.
+ */
 #define BACKLIGHT_MODULATION_FREQ_MASK		(0x7fff << 17)
 #define BLM_LEGACY_MODE				(1 << 16)
+/**
+ * This is the number of cycles out of the backlight modulation cycle for which
+ * the backlight is on.
+ *
+ * This field must be no greater than the number of cycles in the complete
+ * backlight modulation cycle.
+ */
 #define BACKLIGHT_DUTY_CYCLE_SHIFT		(0)
 #define BACKLIGHT_DUTY_CYCLE_MASK		(0xffff)
 
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index 18ac76b..223c6ab 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -32,6 +32,34 @@
 #include "xf86.h"
 #include "i830.h"
 #include "i830_bios.h"
+#include "X11/Xatom.h"
+
+/**
+ * Sets the backlight level.
+ *
+ * \param level backlight level, from 0 to i830_lvds_get_max_backlight().
+ */
+static void
+i830_lvds_set_backlight(ScrnInfoPtr pScrn, int level)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD32 blc_pwm_ctl;
+
+    blc_pwm_ctl = INREG(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
+    OUTREG(BLC_PWM_CTL, blc_pwm_ctl | (level << BACKLIGHT_DUTY_CYCLE_SHIFT));
+}
+
+/**
+ * Returns the maximum level of the backlight duty cycle field.
+ */
+static CARD32
+i830_lvds_get_max_backlight(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    
+    return ((INREG(BLC_PWM_CTL) & BACKLIGHT_MODULATION_FREQ_MASK) >>
+	BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
+}
 
 /**
  * Sets the power state for the panel.
@@ -41,25 +69,16 @@ i830SetLVDSPanelPower(ScrnInfoPtr pScrn,
 {
     I830Ptr pI830 = I830PTR(pScrn);
     CARD32 pp_status;
-    CARD32 blc_pwm_ctl;
-    int backlight_duty_cycle;
-
-    blc_pwm_ctl = INREG (BLC_PWM_CTL);
-    backlight_duty_cycle = blc_pwm_ctl & BACKLIGHT_DUTY_CYCLE_MASK;
-    if (backlight_duty_cycle)
-        pI830->backlight_duty_cycle = backlight_duty_cycle;
 
     if (on) {
 	OUTREG(PP_CONTROL, INREG(PP_CONTROL) | POWER_TARGET_ON);
 	do {
 	    pp_status = INREG(PP_STATUS);
 	} while ((pp_status & PP_ON) == 0);
-	OUTREG(BLC_PWM_CTL,
-	       (blc_pwm_ctl & ~BACKLIGHT_DUTY_CYCLE_MASK) |
-	       pI830->backlight_duty_cycle);
+
+	i830_lvds_set_backlight(pScrn, pI830->backlight_duty_cycle);
     } else {
-	OUTREG(BLC_PWM_CTL,
-	       (blc_pwm_ctl & ~BACKLIGHT_DUTY_CYCLE_MASK));
+	i830_lvds_set_backlight(pScrn, 0);
 
 	OUTREG(PP_CONTROL, INREG(PP_CONTROL) & ~POWER_TARGET_ON);
 	do {
@@ -99,11 +118,8 @@ i830_lvds_save (xf86OutputPtr output)
     /*
      * If the light is off at server startup, just make it full brightness
      */
-    if (pI830->backlight_duty_cycle == 0) {
-	pI830->backlight_duty_cycle =
-	    (pI830->saveBLC_PWM_CTL & BACKLIGHT_MODULATION_FREQ_MASK) >>
-	    BACKLIGHT_MODULATION_FREQ_SHIFT;
-    }
+    if (pI830->backlight_duty_cycle == 0)
+	pI830->backlight_duty_cycle = i830_lvds_get_max_backlight(pScrn);
 }
 
 static void
@@ -294,7 +310,80 @@ i830_lvds_destroy (xf86OutputPtr output)
 	xfree (intel_output);
 }
 
+#ifdef RANDR_12_INTERFACE
+#define BACKLIGHT_NAME	"BACKLIGHT"
+static Atom backlight_atom;
+#endif /* RANDR_12_INTERFACE */
+
+static void
+i830_lvds_create_resources(xf86OutputPtr output)
+{
+#ifdef RANDR_12_INTERFACE
+    ScrnInfoPtr pScrn = output->scrn;
+    I830Ptr pI830 = I830PTR(pScrn);
+    INT32 range[2];
+    int data, err;
+
+    /* Set up the backlight property, which takes effect immediately
+     * and accepts values only within the range.
+     *
+     * XXX: Currently, RandR doesn't verify that properties set are
+     * within the range.
+     */
+    backlight_atom = MakeAtom(BACKLIGHT_NAME, sizeof(BACKLIGHT_NAME) - 1,
+	TRUE);
+
+    range[0] = 0;
+    range[1] = i830_lvds_get_max_backlight(pScrn);
+    err = RRConfigureOutputProperty(output->randr_output, backlight_atom,
+				    FALSE, TRUE, FALSE, 2, range);
+    if (err != 0) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "RRConfigureOutputProperty error, %d\n", err);
+    }
+    /* Set the current value of the backlight property */
+    data = pI830->backlight_duty_cycle;
+    err = RRChangeOutputProperty(output->randr_output, backlight_atom,
+				 XA_INTEGER, 32, PropModeReplace, 4, &data,
+				 FALSE);
+    if (err != 0) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "RRChangeOutputProperty error, %d\n", err);
+    }
+
+#endif /* RANDR_12_INTERFACE */
+}
+
+static Bool
+i830_lvds_set_property(xf86OutputPtr output, Atom property,
+		       RRPropertyValuePtr value)
+{
+    ScrnInfoPtr pScrn = output->scrn;
+    I830Ptr pI830 = I830PTR(pScrn);
+    
+    if (property == backlight_atom) {
+	INT32 val;
+
+	if (value->type != XA_INTEGER || value->format != 32 ||
+	    value->size != 1)
+	{
+	    return FALSE;
+	}
+
+	val = *(INT32 *)value->data;
+	if (val < 0 || val > i830_lvds_get_max_backlight(pScrn))
+	    return FALSE;
+
+	i830_lvds_set_backlight(pScrn, val);
+	pI830->backlight_duty_cycle = val;
+	return TRUE;
+    }
+
+    return TRUE;
+}
+
 static const xf86OutputFuncsRec i830_lvds_output_funcs = {
+    .create_resources = i830_lvds_create_resources,
     .dpms = i830_lvds_dpms,
     .save = i830_lvds_save,
     .restore = i830_lvds_restore,
@@ -303,6 +392,7 @@ static const xf86OutputFuncsRec i830_lvd
     .mode_set = i830_lvds_mode_set,
     .detect = i830_lvds_detect,
     .get_modes = i830_lvds_get_modes,
+    .set_property = i830_lvds_set_property,
     .destroy = i830_lvds_destroy
 };
 
diff --git a/src/i830_randr.c b/src/i830_randr.c
index 18f84c4..6388849 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -672,6 +672,23 @@ xf86RandR12CrtcSetGamma (ScreenPtr    pS
     return TRUE;
 }
 
+static Bool
+xf86RandR12OutputSetProperty (ScreenPtr pScreen,
+			      RROutputPtr randr_output,
+			      Atom property,
+			      RRPropertyValuePtr value)
+{
+    xf86OutputPtr output = randr_output->devPrivate;
+
+    /* If we don't have any property handler, then we don't care what the
+     * user is setting properties to.
+     */
+    if (output->funcs->set_property == NULL)
+	return TRUE;
+
+    return output->funcs->set_property(output, property, value);
+}
+
 /**
  * Given a list of xf86 modes and a RandR Output object, construct
  * RandR modes and assign them to the output
@@ -861,6 +878,9 @@ xf86RandR12CreateObjects12 (ScreenPtr pS
 					       strlen (output->name),
 					       output);
 	RROutputAttachScreen (output->randr_output, pScreen);
+
+	if (output->funcs->create_resources != NULL)
+	    output->funcs->create_resources(output);
     }
     return TRUE;
 }
@@ -897,6 +917,7 @@ xf86RandR12Init12 (ScreenPtr pScreen)
     rp->rrScreenSetSize = xf86RandR12ScreenSetSize;
     rp->rrCrtcSet = xf86RandR12CrtcSet;
     rp->rrCrtcSetGamma = xf86RandR12CrtcSetGamma;
+    rp->rrOutputSetProperty = xf86RandR12OutputSetProperty;
     rp->rrSetConfig = NULL;
     pScrn->PointerMoved = xf86RandR12PointerMoved;
     if (!xf86RandR12CreateObjects12 (pScreen))
diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h
index 8fea162..b5f2fc2 100644
--- a/src/i830_xf86Crtc.h
+++ b/src/i830_xf86Crtc.h
@@ -171,6 +171,13 @@ struct _xf86Crtc {
 
 typedef struct _xf86OutputFuncs {
     /**
+     * Called to allow the output a chance to create properties after the
+     * RandR objects have been created.
+     */
+    void
+    (*create_resources)(xf86OutputPtr output);
+
+    /**
      * Turns the output on/off, or sets intermediate power levels if available.
      *
      * Unsupported intermediate modes drop to the lower power setting.  If the
@@ -246,6 +253,14 @@ typedef struct _xf86OutputFuncs {
     (*get_modes)(xf86OutputPtr	    output);
 
     /**
+     * Callback when an output's property has changed.
+     */
+    Bool
+    (*set_property)(xf86OutputPtr output,
+		    Atom property,
+		    RRPropertyValuePtr value);
+
+    /**
      * Clean up driver-specific bits of the output
      */
     void
diff-tree a52df90ffcb19e7c0a3b8018db3cd1391a3ec343 (from parents)
Merge: 37946c9c8a4afa4a4fc1fe9864a8eec1c4571d2c 45696aa29124e2852f94880642e70bb2e0cee827
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Tue Jan 16 12:20:26 2007 +1100

    Merge branch 'modesetting' into modesetting-rotation
    
    Conflicts:
    
    	src/i830_driver.c
    	src/i830_randr.c
    
    Just a few sync changes.

diff --cc src/i830_driver.c
index 56a599c,20781aa..84fd9d8
@@@ -3016,14 -3015,8 +3015,10 @@@
     if (crtc && crtc->enabled)
     {
        /* Sync the engine before adjust frame */
-       if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
- 	 (*pI830->AccelInfoRec->Sync)(pScrn);
- 	 pI830->AccelInfoRec->NeedToSync = FALSE;
-       }
-       /* XXX should have xf86-based frame adjuster */
+       i830WaitSync(pScrn);
        i830PipeSetBase(crtc, output->initial_x + x, output->initial_y + y);
 +      crtc->x = output->initial_x + x;
 +      crtc->y = output->initial_y + y;
     }
  }
  
diff-tree 37946c9c8a4afa4a4fc1fe9864a8eec1c4571d2c (from bfeda3bfc59d309772398f688d29452ba97f3973)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Tue Jan 16 12:14:55 2007 +1100

    Interim work on rotation support with new xf86 code.
    
    Yes, there are lots of bits tied together here, and we should split this
    patch apart.
    
    Move I830 mode setting to xf86 mode setting.
    
    Make mode setting function also set the base address. This should fix
    problems where the base gets set incorrectly at times.
    
    Add driver-independent rotation support, requires driver-specific hooks for
    shadow pixmap allocation, otherwise it uses Render for painting.

diff --git a/src/i830.h b/src/i830.h
index 95bea2f..66dad9b 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -221,6 +221,7 @@ enum last_3d {
     LAST_3D_ROTATION
 };
 
+#if 0
 typedef struct _I830PipeRec {
    Bool		  enabled;
    int		  x;
@@ -233,6 +234,7 @@ typedef struct _I830PipeRec {
    RRCrtcPtr	  randr_crtc;
 #endif
 } I830PipeRec, *I830PipePtr;
+#endif
 
 typedef struct _I830Rec {
    unsigned char *MMIOBase;
diff --git a/src/i830_crt.c b/src/i830_crt.c
index 00e637a..573e652 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -314,7 +314,7 @@ i830_crt_detect(xf86OutputPtr output)
 	if (intel_output->load_detect_temp)
 	{
 	    xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
-	    xf86CrtcSetMode (crtc, &mode, RR_Rotate_0);
+	    xf86CrtcSetMode (crtc, &mode, RR_Rotate_0, 0, 0);
 	}
 	connected = i830_crt_detect_load (crtc, output);
 
diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index 81cb3bd..5e7a21a 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -492,7 +492,7 @@ I830SetCursorPosition(ScrnInfoPtr pScrn,
     for (pipe = 0; pipe < xf86_config->num_crtc; pipe++)
     {
 	xf86CrtcPtr    crtc = xf86_config->crtc[pipe];
-	DisplayModePtr	    mode = &crtc->curMode;
+	DisplayModePtr	    mode = &crtc->mode;
 	int		    thisx = x - crtc->x;
 	int		    thisy = y - crtc->y;
 
diff --git a/src/i830_display.c b/src/i830_display.c
index d80eb4e..de6c722 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -358,9 +358,6 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x,
 	OUTREG(dspbase, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
 	(void) INREG(dspbase);
     }
-
-    crtc->x = x;
-    crtc->y = y;
 }
 
 /**
@@ -601,7 +598,8 @@ i830_crtc_mode_fixup(xf86CrtcPtr crtc, D
  */
 static void
 i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
-		   DisplayModePtr adjusted_mode)
+		   DisplayModePtr adjusted_mode,
+		   int x, int y)
 {
     ScrnInfoPtr pScrn = crtc->scrn;
     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
@@ -837,7 +835,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
     
     OUTREG(dspcntr_reg, dspcntr);
     /* Flush the plane changes */
-    i830PipeSetBase(crtc, crtc->x, crtc->y);
+    i830PipeSetBase(crtc, x, y);
     
     i830WaitForVblank(pScrn);
 }
@@ -901,7 +899,7 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
     {
 	ok = xf86CrtcSetMode(crtc,
 			     i830PipeFindClosestMode(crtc, pMode),
-			     rotation);
+			     rotation, 0, 0);
 	if (!ok)
 	    goto done;
 	crtc->desiredMode = *pMode;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index daa5a3b..56a599c 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3020,7 +3020,10 @@ i830AdjustFrame(int scrnIndex, int x, in
 	 (*pI830->AccelInfoRec->Sync)(pScrn);
 	 pI830->AccelInfoRec->NeedToSync = FALSE;
       }
+      /* XXX should have xf86-based frame adjuster */
       i830PipeSetBase(crtc, output->initial_x + x, output->initial_y + y);
+      crtc->x = output->initial_x + x;
+      crtc->y = output->initial_y + y;
    }
 }
 
@@ -3138,14 +3141,17 @@ I830EnterVT(int scrnIndex, int flags)
       xf86CrtcPtr	crtc = xf86_config->crtc[i];
 
       /* Mark that we'll need to re-set the mode for sure */
-      memset(&crtc->curMode, 0, sizeof(crtc->curMode));
+      memset(&crtc->mode, 0, sizeof(crtc->mode));
       if (!crtc->desiredMode.CrtcHDisplay)
       {
 	 crtc->desiredMode = *i830PipeFindClosestMode (crtc, pScrn->currentMode);
 	 crtc->desiredRotation = RR_Rotate_0;
+	 crtc->desiredX = 0;
+	 crtc->desiredY = 0;
       }
       
-      if (!xf86CrtcSetMode (crtc, &crtc->desiredMode, crtc->desiredRotation))
+      if (!xf86CrtcSetMode (crtc, &crtc->desiredMode, crtc->desiredRotation,
+			    crtc->desiredX, crtc->desiredY))
 	 return FALSE;
    }
 
diff --git a/src/i830_randr.c b/src/i830_randr.c
index d6df419..3aaf88b 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -393,8 +393,8 @@ xf86RandR12CreateScreenResources (Screen
     for (c = 0; c < config->num_crtc; c++)
     {
 	xf86CrtcPtr crtc = config->crtc[c];
-	int	    crtc_width = crtc->x + crtc->curMode.HDisplay;
-	int	    crtc_height = crtc->y + crtc->curMode.VDisplay;
+	int	    crtc_width = crtc->x + crtc->mode.HDisplay;
+	int	    crtc_height = crtc->y + crtc->mode.VDisplay;
 	
 	if (crtc->enabled && crtc_width > width)
 	    width = crtc_width;
@@ -533,7 +533,7 @@ xf86RandR12CrtcNotify (RRCrtcPtr	randr_c
     xf86CrtcPtr		crtc = randr_crtc->devPrivate;
     xf86OutputPtr	output;
     int			i, j;
-    DisplayModePtr	curMode = &crtc->curMode;
+    DisplayModePtr	mode = &crtc->mode;
     Bool		ret;
 
     randr_outputs = ALLOCATE_LOCAL(config->num_output * sizeof (RROutputPtr));
@@ -541,7 +541,7 @@ xf86RandR12CrtcNotify (RRCrtcPtr	randr_c
 	return FALSE;
     x = crtc->x;
     y = crtc->y;
-    rotation = crtc->curRotation;
+    rotation = crtc->rotation;
     numOutputs = 0;
     randr_mode = NULL;
     for (i = 0; i < config->num_output; i++)
@@ -558,7 +558,7 @@ xf86RandR12CrtcNotify (RRCrtcPtr	randr_c
 	    for (j = 0; j < randr_output->numModes; j++)
 	    {
 		DisplayModePtr	outMode = randr_output->modes[j]->devPrivate;
-		if (xf86ModesEqual(curMode, outMode))
+		if (xf86ModesEqual(mode, outMode))
 		{
 		    randr_mode = randr_output->modes[j];
 		    break;
@@ -587,7 +587,6 @@ xf86RandR12CrtcSet (ScreenPtr	pScreen,
     xf86CrtcPtr		crtc = randr_crtc->devPrivate;
     DisplayModePtr	mode = randr_mode ? randr_mode->devPrivate : NULL;
     Bool		changed = FALSE;
-    Bool		pos_changed;
     int			o, ro;
     xf86CrtcPtr		*save_crtcs;
     Bool		save_enabled = crtc->enabled;
@@ -595,12 +594,11 @@ xf86RandR12CrtcSet (ScreenPtr	pScreen,
     save_crtcs = ALLOCATE_LOCAL(config->num_crtc * sizeof (xf86CrtcPtr));
     if ((mode != NULL) != crtc->enabled)
 	changed = TRUE;
-    else if (mode && !xf86ModesEqual (&crtc->curMode, mode))
+    else if (mode && !xf86ModesEqual (&crtc->mode, mode))
 	changed = TRUE;
     
-    pos_changed = changed;
     if (x != crtc->x || y != crtc->y)
-	pos_changed = TRUE;
+	changed = TRUE;
     for (o = 0; o < config->num_output; o++) 
     {
 	xf86OutputPtr  output = config->output[o];
@@ -627,18 +625,11 @@ xf86RandR12CrtcSet (ScreenPtr	pScreen,
     /* XXX need device-independent mode setting code through an API */
     if (changed)
     {
-	I830Ptr pI830 = I830PTR(pScrn);
 	crtc->enabled = mode != NULL;
 
-	/* Sync the engine before adjust mode */
-	if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
-	    (*pI830->AccelInfoRec->Sync)(pScrn);
-	    pI830->AccelInfoRec->NeedToSync = FALSE;
-	}
-
 	if (mode)
 	{
-	    if (!xf86CrtcSetMode (crtc, mode, rotation))
+	    if (!xf86CrtcSetMode (crtc, mode, rotation, x, y))
 	    {
 		crtc->enabled = save_enabled;
 		for (o = 0; o < config->num_output; o++)
@@ -649,14 +640,16 @@ xf86RandR12CrtcSet (ScreenPtr	pScreen,
 		DEALLOCATE_LOCAL(save_crtcs);
 		return FALSE;
 	    }
+	    /*
+	     * Save the last successful setting for EnterVT
+	     */
 	    crtc->desiredMode = *mode;
+	    crtc->desiredRotation = rotation;
+	    crtc->desiredX = x;
+	    crtc->desiredY = y;
 	}
 	xf86DisableUnusedFunctions (pScrn);
-
-	i830DumpRegs(pScrn);
     }
-    if (pos_changed && mode)
-	i830PipeSetBase(crtc, x, y);
     DEALLOCATE_LOCAL(save_crtcs);
     return xf86RandR12CrtcNotify (randr_crtc);
 }
@@ -817,6 +810,8 @@ xf86RandR12SetInfo12 (ScreenPtr pScreen)
     return TRUE;
 }
 
+
+
 /*
  * Query the hardware for the current state, then mirror
  * that to RandR
diff --git a/src/i830_tv.c b/src/i830_tv.c
index a76cbff..79b6ae8 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -1065,7 +1065,7 @@ i830_tv_detect(xf86OutputPtr output)
 	    /* we only need the pixel clock set correctly here */
 	    mode = reported_modes[0];
 	    xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
-	    xf86CrtcSetMode (crtc, &mode, RR_Rotate_0);
+	    xf86CrtcSetMode (crtc, &mode, RR_Rotate_0, 0, 0);
 	}
 	i830_tv_detect_type (crtc, output);
 	i830ReleaseLoadDetectPipe (output);
diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index 5eb55e9..504ea0b 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -87,7 +87,7 @@ xf86CrtcCreate (ScrnInfoPtr		scrn,
 #ifdef RANDR_12_INTERFACE
     crtc->randr_crtc = NULL;
 #endif
-    crtc->curRotation = RR_Rotate_0;
+    crtc->rotation = RR_Rotate_0;
     crtc->desiredRotation = RR_Rotate_0;
     if (xf86_config->crtc)
 	crtcs = xrealloc (xf86_config->crtc,
@@ -145,7 +145,8 @@ xf86CrtcInUse (xf86CrtcPtr crtc)
  * Sets the given video mode on the given crtc
  */
 Bool
-xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
+xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
+		 int x, int y)
 {
     ScrnInfoPtr		scrn = crtc->scrn;
     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
@@ -166,6 +167,8 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, Displ
 
     didLock = crtc->funcs->lock (crtc);
 
+    /* XXX short-circuit changes to base location only */
+    
     /* Pass our mode to the outputs and the CRTC to give them a chance to
      * adjust it according to limitations or output properties, and also
      * a chance to reject the mode entirely.
@@ -211,7 +214,7 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, Displ
     /* Set up the DPLL and any output state that needs to adjust or depend
      * on the DPLL.
      */
-    crtc->funcs->mode_set(crtc, mode, adjusted_mode);
+    crtc->funcs->mode_set(crtc, mode, adjusted_mode, x, y);
     for (i = 0; i < xf86_config->num_output; i++) 
     {
 	xf86OutputPtr output = xf86_config->output[i];
@@ -228,7 +231,10 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, Displ
 	    output->funcs->dpms(output, DPMSModeOn);
     }
 
-    crtc->curMode = *mode;
+    crtc->mode = *mode;
+    crtc->x = x;
+    crtc->y = y;
+    crtc->rotation = rotation;
 
     /* XXX free adjustedmode */
     ret = TRUE;
@@ -1401,7 +1407,7 @@ xf86DisableUnusedFunctions(ScrnInfoPtr p
 	if (!crtc->enabled) 
 	{
 	    crtc->funcs->dpms(crtc, DPMSModeOff);
-	    memset(&crtc->curMode, 0, sizeof(crtc->curMode));
+	    memset(&crtc->mode, 0, sizeof(crtc->mode));
 	}
     }
 }
diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h
index e72dda6..4b17dce 100644
--- a/src/i830_xf86Crtc.h
+++ b/src/i830_xf86Crtc.h
@@ -70,7 +70,6 @@ typedef struct _xf86CrtcFuncs {
    void
     (*restore)(xf86CrtcPtr	crtc);
 
-
     /**
      * Lock CRTC prior to mode setting, mostly for DRI.
      * Returns whether unlock is needed
@@ -102,7 +101,8 @@ typedef struct _xf86CrtcFuncs {
     void
     (*mode_set)(xf86CrtcPtr crtc,
 		DisplayModePtr mode,
-		DisplayModePtr adjusted_mode);
+		DisplayModePtr adjusted_mode,
+		int x, int y);
 
     /* Set the color ramps for the CRTC to the given values. */
     void
@@ -141,13 +141,6 @@ struct _xf86Crtc {
      */
     Bool	    enabled;
     
-    /**
-     * Position on screen
-     *
-     * Locates this CRTC within the frame buffer
-     */
-    int		    x, y;
-    
     /** Track whether cursor is within CRTC range  */
     Bool	    cursorInRange;
     
@@ -161,9 +154,15 @@ struct _xf86Crtc {
      * It will be cleared when the VT is not active or
      * during server startup
      */
-    DisplayModeRec  curMode;
-    Rotation	    curRotation;
+    DisplayModeRec  mode;
+    Rotation	    rotation;
     PixmapPtr	    rotatedPixmap;
+    /**
+     * Position on screen
+     *
+     * Locates this CRTC within the frame buffer
+     */
+    int		    x, y;
     
     /**
      * Desired mode
@@ -175,6 +174,7 @@ struct _xf86Crtc {
      */
     DisplayModeRec  desiredMode;
     Rotation	    desiredRotation;
+    int		    desiredX, desiredY;
     
     /** crtc-specific functions */
     const xf86CrtcFuncsRec *funcs;
@@ -396,6 +396,10 @@ typedef struct _xf86CrtcConfig {
     
     /* For crtc-based rotation */
     DamagePtr   rotationDamage;
+
+    /* DGA */
+    unsigned int dga_flags;
+
 } xf86CrtcConfigRec, *xf86CrtcConfigPtr;
 
 extern int xf86CrtcConfigPrivateIndex;
@@ -448,7 +452,8 @@ xf86FreeCrtc (xf86CrtcPtr		crtc);
  * Sets the given video mode on the given crtc
  */
 Bool
-xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation);
+xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
+		 int x, int y);
 
 /*
  * Assign crtc rotation during mode set
diff --git a/src/i830_xf86Rotate.c b/src/i830_xf86Rotate.c
index 12b2091..5482a6e 100644
--- a/src/i830_xf86Rotate.c
+++ b/src/i830_xf86Rotate.c
@@ -128,7 +128,7 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crt
     transform.matrix[2][2] = 1;
     transform.matrix[0][2] = crtc->x;
     transform.matrix[1][2] = crtc->y;
-    switch (crtc->curRotation & 0xf) {
+    switch (crtc->rotation & 0xf) {
     case RR_Rotate_0:
 	transform.matrix[0][0] = 1;
 	transform.matrix[1][1] = 1;
@@ -137,28 +137,28 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crt
 	/* XXX probably wrong */
 	transform.matrix[0][1] = 1;
 	transform.matrix[1][0] = -1;
-	transform.matrix[1][2] += crtc->curMode.HDisplay;
+	transform.matrix[1][2] += crtc->mode.HDisplay;
 	break;
     case RR_Rotate_180:
 	/* XXX probably wrong */
 	transform.matrix[0][0] = -1;
 	transform.matrix[1][1] = -1;
-	transform.matrix[0][2] += crtc->curMode.HDisplay;
-	transform.matrix[1][2] += crtc->curMode.VDisplay;
+	transform.matrix[0][2] += crtc->mode.HDisplay;
+	transform.matrix[1][2] += crtc->mode.VDisplay;
 	break;
     case RR_Rotate_270:
 	/* XXX probably wrong */
 	transform.matrix[0][1] = -1;
 	transform.matrix[1][0] = 1;
-	transform.matrix[0][2] += crtc->curMode.VDisplay;
+	transform.matrix[0][2] += crtc->mode.VDisplay;
 	break;
     }
     /* handle reflection */
-    if (crtc->curRotation & RR_Reflect_X)
+    if (crtc->rotation & RR_Reflect_X)
     {
 	/* XXX figure this out */
     }
-    if (crtc->curRotation & RR_Reflect_Y)
+    if (crtc->rotation & RR_Reflect_Y)
     {
 	/* XXX figure this out too */
     }
@@ -191,16 +191,16 @@ xf86RotateRedisplay(ScreenPtr pScreen)
 	{
 	    xf86CrtcPtr	    crtc = xf86_config->crtc[c];
 
-	    if (crtc->curRotation != RR_Rotate_0)
+	    if (crtc->rotation != RR_Rotate_0)
 	    {
 		BoxRec	    box;
 		RegionRec   crtc_damage;
 
 		/* compute portion of damage that overlaps crtc */
 		box.x1 = crtc->x;
-		box.x2 = crtc->x + mode_width (&crtc->curMode, crtc->curRotation);
+		box.x2 = crtc->x + mode_width (&crtc->mode, crtc->rotation);
 		box.y1 = crtc->y;
-		box.y2 = crtc->y + mode_height (&crtc->curMode, crtc->curRotation);
+		box.y2 = crtc->y + mode_height (&crtc->mode, crtc->rotation);
 		REGION_INIT(pScreen, &crtc_damage, &box, 1);
 		REGION_INTERSECT (pScreen, &crtc_damage, &crtc_damage, region);
 		
@@ -319,6 +319,5 @@ bail1:
     }
     
     /* All done */
-    crtc->curRotation = rotation;
     return TRUE;
 }
diff-tree bfeda3bfc59d309772398f688d29452ba97f3973 (from da6a00f787e4d13e6b75768c1976f1c44ae5bf72)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Mon Jan 15 08:05:32 2007 +1100

    Convert I830PipeSetMode to xf86CrtcSetMode. Add rotation structures.
    
    Makes the mode setting logic device independent.
    Magic rename hooks allow multiple drivers to provide the
    generic code without name conflicts.
    Rotation code requires special pixmap creation hook, and uses
    Render to perform the actual rotation.

diff --git a/src/Makefile.am b/src/Makefile.am
index 80cea10..02e8576 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -85,6 +85,7 @@ i810_drv_la_SOURCES = \
 	 i830_xf86cvt.c \
 	 i830_xf86Crtc.h \
 	 i830_xf86Crtc.c \
+	 i830_xf86Rotate.c \
 	 i915_3d.c \
 	 i915_3d.h \
 	 i915_reg.h \
diff --git a/src/i830_crt.c b/src/i830_crt.c
index 4e9e370..00e637a 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -314,7 +314,7 @@ i830_crt_detect(xf86OutputPtr output)
 	if (intel_output->load_detect_temp)
 	{
 	    xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
-	    i830PipeSetMode (crtc, &mode, FALSE);
+	    xf86CrtcSetMode (crtc, &mode, RR_Rotate_0);
 	}
 	connected = i830_crt_detect_load (crtc, output);
 
diff --git a/src/i830_display.c b/src/i830_display.c
index f47a9db..d80eb4e 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -465,23 +465,6 @@ i830PipeFindClosestMode(xf86CrtcPtr crtc
 }
 
 /**
- * Return whether any outputs are connected to the specified pipe
- */
-
-Bool
-i830PipeInUse (xf86CrtcPtr crtc)
-{
-    ScrnInfoPtr pScrn = crtc->scrn;
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-    int	i;
-    
-    for (i = 0; i < xf86_config->num_output; i++)
-	if (xf86_config->output[i]->crtc == crtc)
-	    return TRUE;
-    return FALSE;
-}
-
-/**
  * Sets the power management mode of the pipe and plane.
  *
  * This code should probably grow support for turning the cursor off and back
@@ -581,6 +564,27 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mod
 }
 
 static Bool
+i830_crtc_lock (xf86CrtcPtr crtc)
+{
+   /* Sync the engine before mode switch */
+   i830WaitSync(crtc->scrn);
+
+#ifdef XF86DRI
+    return I830DRILock(crtc->scrn);
+#else
+    return FALSE;
+#endif
+}
+
+static void
+i830_crtc_unlock (xf86CrtcPtr crtc)
+{
+#ifdef XF86DRI
+    I830DRIUnlock (crtc->scrn);
+#endif
+}
+
+static Bool
 i830_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode,
 		     DisplayModePtr adjusted_mode)
 {
@@ -881,165 +885,11 @@ i830_crtc_gamma_set(xf86CrtcPtr crtc, CA
 }
 
 /**
- * Sets the given video mode on the given pipe.
- *
- * Plane A is always output to pipe A, and plane B to pipe B.  The plane
- * will not be enabled if plane_enable is FALSE, which is used for
- * load detection, when something else will be output to the pipe other than
- * display data.
- */
-Bool
-i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode,
-		Bool plane_enable)
-{
-    ScrnInfoPtr pScrn = crtc->scrn;
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-    int i;
-    Bool ret = FALSE;
-#ifdef XF86DRI
-    Bool didLock = FALSE;
-#endif
-    DisplayModePtr adjusted_mode;
-
-    /* XXX: curMode */
-
-    adjusted_mode = xf86DuplicateMode(pMode);
-
-    crtc->enabled = i830PipeInUse (crtc);
-    
-    if (!crtc->enabled)
-    {
-	/* XXX disable crtc? */
-	return TRUE;
-    }
-
-#ifdef XF86DRI
-    didLock = I830DRILock(pScrn);
-#endif
-
-    /* Pass our mode to the outputs and the CRTC to give them a chance to
-     * adjust it according to limitations or output properties, and also
-     * a chance to reject the mode entirely.
-     */
-    for (i = 0; i < xf86_config->num_output; i++) {
-	xf86OutputPtr output = xf86_config->output[i];
-
-	if (output->crtc != crtc)
-	    continue;
-
-	if (!output->funcs->mode_fixup(output, pMode, adjusted_mode)) {
-	    ret = FALSE;
-	    goto done;
-	}
-    }
-
-    if (!crtc->funcs->mode_fixup(crtc, pMode, adjusted_mode)) {
-	ret = FALSE;
-	goto done;
-    }
-
-    /* Disable the outputs and CRTCs before setting the mode. */
-    for (i = 0; i < xf86_config->num_output; i++) {
-	xf86OutputPtr output = xf86_config->output[i];
-
-	if (output->crtc != crtc)
-	    continue;
-
-	/* Disable the output as the first thing we do. */
-	output->funcs->dpms(output, DPMSModeOff);
-    }
-
-    crtc->funcs->dpms(crtc, DPMSModeOff);
-
-    /* Set up the DPLL and any output state that needs to adjust or depend
-     * on the DPLL.
-     */
-    crtc->funcs->mode_set(crtc, pMode, adjusted_mode);
-    for (i = 0; i < xf86_config->num_output; i++) {
-	xf86OutputPtr output = xf86_config->output[i];
-	if (output->crtc == crtc)
-	    output->funcs->mode_set(output, pMode, adjusted_mode);
-    }
-
-    /* Now, enable the clocks, plane, pipe, and outputs that we set up. */
-    crtc->funcs->dpms(crtc, DPMSModeOn);
-    for (i = 0; i < xf86_config->num_output; i++) {
-	xf86OutputPtr output = xf86_config->output[i];
-	if (output->crtc == crtc)
-	    output->funcs->dpms(output, DPMSModeOn);
-    }
-
-#if 0
-    /*
-     * If the display isn't solid, it may be running out
-     * of memory bandwidth. This code will dump out the
-     * pipe status, if bit 31 is on, the fifo underran
-     */
-    for (i = 0; i < 4; i++) {
-	i830WaitForVblank(pScrn);
-    
-	OUTREG(pipestat_reg, INREG(pipestat_reg) | 0x80000000);
-    
-	i830WaitForVblank(pScrn);
-    
-	temp = INREG(pipestat_reg);
-	ErrorF ("pipe status 0x%x\n", temp);
-    }
-#endif
-    
-    crtc->curMode = *pMode;
-
-    /* XXX free adjustedmode */
-    ret = TRUE;
-done:
-#ifdef XF86DRI
-    if (didLock)
-	I830DRIUnlock(pScrn);
-#endif
-    return ret;
-}
-
-void
-i830DisableUnusedFunctions(ScrnInfoPtr pScrn)
-{
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-    int o, pipe;
-
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling unused functions\n");
-
-    for (o = 0; o < xf86_config->num_output; o++) 
-    {
-	xf86OutputPtr  output = xf86_config->output[o];
-	if (!output->crtc) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling output %s\n",
-		       output->name);
-	    (*output->funcs->dpms)(output, DPMSModeOff);
-	}
-    }
-
-    for (pipe = 0; pipe < xf86_config->num_crtc; pipe++) 
-    {
-	xf86CrtcPtr crtc = xf86_config->crtc[pipe];
-	I830CrtcPrivatePtr  intel_crtc = crtc->driver_private;
-	int		    pipe = intel_crtc->pipe;
-	char	    *pipe_name = pipe == 0 ? "A" : "B";
-
-	if (!crtc->enabled) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling CRTC %s\n",
-		       pipe_name);
-	    crtc->funcs->dpms(crtc, DPMSModeOff);
-
-	    memset(&crtc->curMode, 0, sizeof(crtc->curMode));
-	}
-    }
-}
-
-/**
  * This function configures the screens in clone mode on
  * all active outputs using a mode similar to the specified mode.
  */
 Bool
-i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
+i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, Rotation rotation)
 {
     xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
     Bool ok = TRUE;
@@ -1049,9 +899,9 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
 
     if (crtc && crtc->enabled)
     {
-	ok = i830PipeSetMode(crtc,
-			     i830PipeFindClosestMode(crtc, pMode), 
-			     TRUE);
+	ok = xf86CrtcSetMode(crtc,
+			     i830PipeFindClosestMode(crtc, pMode),
+			     rotation);
 	if (!ok)
 	    goto done;
 	crtc->desiredMode = *pMode;
@@ -1061,7 +911,7 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
 	       (int)(pMode->HDisplay * pMode->VDisplay *
 		     pMode->VRefresh / 1000000));
 
-    i830DisableUnusedFunctions(pScrn);
+    xf86DisableUnusedFunctions(pScrn);
 
     i830DescribeOutputConfiguration(pScrn);
 
@@ -1153,7 +1003,7 @@ i830GetLoadDetectPipe(xf86OutputPtr outp
 	return output->crtc;
 
     for (i = 0; i < xf86_config->num_crtc; i++)
-	if (!i830PipeInUse(xf86_config->crtc[i]))
+	if (!xf86CrtcInUse (xf86_config->crtc[i]))
 	    break;
 
     if (i == xf86_config->num_crtc)
@@ -1177,7 +1027,7 @@ i830ReleaseLoadDetectPipe(xf86OutputPtr 
     {
 	output->crtc = NULL;
 	intel_output->load_detect_temp = FALSE;
-	i830DisableUnusedFunctions(pScrn);
+	xf86DisableUnusedFunctions(pScrn);
     }
 }
 
@@ -1185,6 +1035,8 @@ static const xf86CrtcFuncsRec i830_crtc_
     .dpms = i830_crtc_dpms,
     .save = NULL, /* XXX */
     .restore = NULL, /* XXX */
+    .lock = i830_crtc_lock,
+    .unlock = i830_crtc_unlock,
     .mode_fixup = i830_crtc_mode_fixup,
     .mode_set = i830_crtc_mode_set,
     .gamma_set = i830_crtc_gamma_set,
diff --git a/src/i830_display.h b/src/i830_display.h
index 66ab17e..dc80055 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -30,16 +30,12 @@
 /* i830_display.c */
 DisplayModePtr
 i830PipeFindClosestMode(xf86CrtcPtr crtc, DisplayModePtr pMode);
-Bool i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode, 
-		     Bool plane_enable);
-void i830DisableUnusedFunctions(ScrnInfoPtr pScrn);
-Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
+Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, Rotation rotation);
 void i830PipeSetBase(xf86CrtcPtr crtc, int x, int y);
 void i830WaitForVblank(ScrnInfoPtr pScrn);
 void i830DescribeOutputConfiguration(ScrnInfoPtr pScrn);
 
 xf86CrtcPtr i830GetLoadDetectPipe(xf86OutputPtr output);
 void i830ReleaseLoadDetectPipe(xf86OutputPtr output);
-Bool i830PipeInUse(xf86CrtcPtr crtc);
 void i830_crtc_init(ScrnInfoPtr pScrn, int pipe);
 void i830_crtc_load_lut(xf86CrtcPtr crtc);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 2992798..daa5a3b 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3131,7 +3131,7 @@ I830EnterVT(int scrnIndex, int flags)
    ResetState(pScrn, FALSE);
    SetHWOperatingState(pScrn);
 
-   i830DisableUnusedFunctions(pScrn);
+   xf86DisableUnusedFunctions(pScrn);
 
    for (i = 0; i < xf86_config->num_crtc; i++)
    {
@@ -3140,9 +3140,12 @@ I830EnterVT(int scrnIndex, int flags)
       /* Mark that we'll need to re-set the mode for sure */
       memset(&crtc->curMode, 0, sizeof(crtc->curMode));
       if (!crtc->desiredMode.CrtcHDisplay)
+      {
 	 crtc->desiredMode = *i830PipeFindClosestMode (crtc, pScrn->currentMode);
+	 crtc->desiredRotation = RR_Rotate_0;
+      }
       
-      if (!i830PipeSetMode (crtc, &crtc->desiredMode, TRUE))
+      if (!xf86CrtcSetMode (crtc, &crtc->desiredMode, crtc->desiredRotation))
 	 return FALSE;
    }
 
@@ -3223,45 +3226,11 @@ I830SwitchMode(int scrnIndex, DisplayMod
    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
    I830Ptr pI830 = I830PTR(pScrn);
    Bool ret = TRUE;
-   PixmapPtr pspix = (*pScrn->pScreen->GetScreenPixmap) (pScrn->pScreen);
 
    DPRINTF(PFX, "I830SwitchMode: mode == %p\n", mode);
 
-   /* Sync the engine before mode switch */
-   i830WaitSync(pScrn);
-
-   /* Check if our currentmode is about to change. We do this so if we
-    * are rotating, we don't need to call the mode setup again.
-    */
-   if (pI830->currentMode != mode) {
-      if (!i830SetMode(pScrn, mode))
-         ret = FALSE;
-   }
-
-   /* Kludge to detect Rotate or Vidmode switch. Not very elegant, but
-    * workable given the implementation currently. We only need to call
-    * the rotation function when we know that the framebuffer has been
-    * disabled by the EnableDisableFBAccess() function.
-    *
-    * The extra WindowTable check detects a rotation at startup.
-    */
-   if ( (!WindowTable[pScrn->scrnIndex] || pspix->devPrivate.ptr == NULL) &&
-         !pI830->DGAactive && (pScrn->PointerMoved == I830PointerMoved)) {
-      if (!I830Rotate(pScrn, mode))
-         ret = FALSE;
-   }
-
-   /* Either the original setmode or rotation failed, so restore the previous
-    * video mode here, as we'll have already re-instated the original rotation.
-    */
-   if (!ret) {
-      if (!i830SetMode(pScrn, pI830->currentMode)) {
-	 xf86DrvMsg(scrnIndex, X_INFO,
-		    "Failed to restore previous mode (SwitchMode)\n");
-      }
-   } else {
+   if (!i830SetMode(pScrn, mode, pI830->rotation))
       pI830->currentMode = mode;
-   }
 
    return ret;
 }
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index 18ac76b..8abd402 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -254,10 +254,10 @@ i830_lvds_get_modes(xf86OutputPtr output
     xf86MonPtr		    edid_mon;
     DisplayModePtr	    modes;
 
-    edid_mon = i830_xf86OutputGetEDID (output, intel_output->pDDCBus);
-    i830_xf86OutputSetEDID (output, edid_mon);
+    edid_mon = xf86OutputGetEDID (output, intel_output->pDDCBus);
+    xf86OutputSetEDID (output, edid_mon);
     
-    modes = i830_xf86OutputGetEDIDModes (output);
+    modes = xf86OutputGetEDIDModes (output);
     if (modes != NULL)
 	return modes;
 
diff --git a/src/i830_modes.c b/src/i830_modes.c
index b4e22c3..405dcc6 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -62,9 +62,9 @@ i830_ddc_get_modes (xf86OutputPtr output
     xf86MonPtr		    edid_mon;
     DisplayModePtr	    modes;
 
-    edid_mon = i830_xf86OutputGetEDID (output, intel_output->pDDCBus);
-    i830_xf86OutputSetEDID (output, edid_mon);
+    edid_mon = xf86OutputGetEDID (output, intel_output->pDDCBus);
+    xf86OutputSetEDID (output, edid_mon);
     
-    modes = i830_xf86OutputGetEDIDModes (output);
+    modes = xf86OutputGetEDIDModes (output);
     return modes;
 }
diff --git a/src/i830_randr.c b/src/i830_randr.c
index 533322b..d6df419 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -541,7 +541,7 @@ xf86RandR12CrtcNotify (RRCrtcPtr	randr_c
 	return FALSE;
     x = crtc->x;
     y = crtc->y;
-    rotation = RR_Rotate_0;
+    rotation = crtc->curRotation;
     numOutputs = 0;
     randr_mode = NULL;
     for (i = 0; i < config->num_output; i++)
@@ -638,7 +638,7 @@ xf86RandR12CrtcSet (ScreenPtr	pScreen,
 
 	if (mode)
 	{
-	    if (!i830PipeSetMode (crtc, mode, TRUE))
+	    if (!xf86CrtcSetMode (crtc, mode, rotation))
 	    {
 		crtc->enabled = save_enabled;
 		for (o = 0; o < config->num_output; o++)
@@ -651,7 +651,7 @@ xf86RandR12CrtcSet (ScreenPtr	pScreen,
 	    }
 	    crtc->desiredMode = *mode;
 	}
-	i830DisableUnusedFunctions (pScrn);
+	xf86DisableUnusedFunctions (pScrn);
 
 	i830DumpRegs(pScrn);
     }
diff --git a/src/i830_tv.c b/src/i830_tv.c
index 92e417e..a76cbff 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -1065,7 +1065,7 @@ i830_tv_detect(xf86OutputPtr output)
 	    /* we only need the pixel clock set correctly here */
 	    mode = reported_modes[0];
 	    xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
-	    i830PipeSetMode (crtc, &mode, FALSE);
+	    xf86CrtcSetMode (crtc, &mode, RR_Rotate_0);
 	}
 	i830_tv_detect_type (crtc, output);
 	i830ReleaseLoadDetectPipe (output);
diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index ceb8f2e..5eb55e9 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -87,6 +87,8 @@ xf86CrtcCreate (ScrnInfoPtr		scrn,
 #ifdef RANDR_12_INTERFACE
     crtc->randr_crtc = NULL;
 #endif
+    crtc->curRotation = RR_Rotate_0;
+    crtc->desiredRotation = RR_Rotate_0;
     if (xf86_config->crtc)
 	crtcs = xrealloc (xf86_config->crtc,
 			  (xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr));
@@ -121,6 +123,122 @@ xf86CrtcDestroy (xf86CrtcPtr crtc)
     xfree (crtc);
 }
 
+
+/**
+ * Return whether any outputs are connected to the specified pipe
+ */
+
+Bool
+xf86CrtcInUse (xf86CrtcPtr crtc)
+{
+    ScrnInfoPtr		pScrn = crtc->scrn;
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int			o;
+    
+    for (o = 0; o < xf86_config->num_output; o++)
+	if (xf86_config->output[o]->crtc == crtc)
+	    return TRUE;
+    return FALSE;
+}
+
+/**
+ * Sets the given video mode on the given crtc
+ */
+Bool
+xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
+{
+    ScrnInfoPtr		scrn = crtc->scrn;
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+    int			i;
+    Bool		ret = FALSE;
+    Bool		didLock = FALSE;
+    DisplayModePtr	adjusted_mode;
+
+    adjusted_mode = xf86DuplicateMode(mode);
+
+    crtc->enabled = xf86CrtcInUse (crtc);
+    
+    if (!crtc->enabled)
+    {
+	/* XXX disable crtc? */
+	return TRUE;
+    }
+
+    didLock = crtc->funcs->lock (crtc);
+
+    /* Pass our mode to the outputs and the CRTC to give them a chance to
+     * adjust it according to limitations or output properties, and also
+     * a chance to reject the mode entirely.
+     */
+    for (i = 0; i < xf86_config->num_output; i++) {
+	xf86OutputPtr output = xf86_config->output[i];
+
+	if (output->crtc != crtc)
+	    continue;
+
+	if (!output->funcs->mode_fixup(output, mode, adjusted_mode)) {
+	    ret = FALSE;
+	    goto done;
+	}
+    }
+
+    if (!crtc->funcs->mode_fixup(crtc, mode, adjusted_mode)) {
+	ret = FALSE;
+	goto done;
+    }
+
+#if 0
+    if (!xf86CrtcRotate (crtc, mode, rotation))
+    {
+	ret = FALSE;
+	goto done;
+    }
+#endif
+
+    /* Disable the outputs and CRTCs before setting the mode. */
+    for (i = 0; i < xf86_config->num_output; i++) {
+	xf86OutputPtr output = xf86_config->output[i];
+
+	if (output->crtc != crtc)
+	    continue;
+
+	/* Disable the output as the first thing we do. */
+	output->funcs->dpms(output, DPMSModeOff);
+    }
+
+    crtc->funcs->dpms(crtc, DPMSModeOff);
+
+    /* Set up the DPLL and any output state that needs to adjust or depend
+     * on the DPLL.
+     */
+    crtc->funcs->mode_set(crtc, mode, adjusted_mode);
+    for (i = 0; i < xf86_config->num_output; i++) 
+    {
+	xf86OutputPtr output = xf86_config->output[i];
+	if (output->crtc == crtc)
+	    output->funcs->mode_set(output, mode, adjusted_mode);
+    }
+
+    /* Now, enable the clocks, plane, pipe, and outputs that we set up. */
+    crtc->funcs->dpms(crtc, DPMSModeOn);
+    for (i = 0; i < xf86_config->num_output; i++) 
+    {
+	xf86OutputPtr output = xf86_config->output[i];
+	if (output->crtc == crtc)
+	    output->funcs->dpms(output, DPMSModeOn);
+    }
+
+    crtc->curMode = *mode;
+
+    /* XXX free adjustedmode */
+    ret = TRUE;
+done:
+    if (didLock)
+	crtc->funcs->unlock (crtc);
+
+    return ret;
+}
+
 /*
  * Output functions
  */
@@ -362,14 +480,14 @@ xf86OutputHasPreferredMode (xf86OutputPt
 }
 
 static int
-xf86PickCrtcs (ScrnInfoPtr	pScrn,
+xf86PickCrtcs (ScrnInfoPtr	scrn,
 	       xf86CrtcPtr	*best_crtcs,
 	       DisplayModePtr	*modes,
 	       int		n,
 	       int		width,
 	       int		height)
 {
-    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
     int		    c, o, l;
     xf86OutputPtr   output;
     xf86CrtcPtr	    crtc;
@@ -388,7 +506,7 @@ xf86PickCrtcs (ScrnInfoPtr	pScrn,
      */
     best_crtcs[n] = NULL;
     best_crtc = NULL;
-    best_score = xf86PickCrtcs (pScrn, best_crtcs, modes, n+1, width, height);
+    best_score = xf86PickCrtcs (scrn, best_crtcs, modes, n+1, width, height);
     if (modes[n] == NULL)
 	return best_score;
     
@@ -442,7 +560,7 @@ xf86PickCrtcs (ScrnInfoPtr	pScrn,
 	}
 	crtcs[n] = crtc;
 	memcpy (crtcs, best_crtcs, n * sizeof (xf86CrtcPtr));
-	score = my_score + xf86PickCrtcs (pScrn, crtcs, modes, n+1, width, height);
+	score = my_score + xf86PickCrtcs (scrn, crtcs, modes, n+1, width, height);
 	if (score > best_score)
 	{
 	    best_crtc = crtc;
@@ -462,9 +580,9 @@ xf86PickCrtcs (ScrnInfoPtr	pScrn,
  */
 
 static void
-xf86DefaultScreenLimits (ScrnInfoPtr pScrn, int *widthp, int *heightp)
+xf86DefaultScreenLimits (ScrnInfoPtr scrn, int *widthp, int *heightp)
 {
-    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
     int	    width = 0, height = 0;
     int	    o;
     int	    c;
@@ -513,9 +631,9 @@ xf86DefaultScreenLimits (ScrnInfoPtr pSc
 #define POSITION_UNSET	-100000
 
 static Bool
-xf86InitialOutputPositions (ScrnInfoPtr pScrn, DisplayModePtr *modes)
+xf86InitialOutputPositions (ScrnInfoPtr scrn, DisplayModePtr *modes)
 {
-    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
     int			o;
     int			min_x, min_y;
     
@@ -563,7 +681,7 @@ xf86InitialOutputPositions (ScrnInfoPtr 
 		}
 		else
 		{
-		    xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
+		    xf86DrvMsg (scrn->scrnIndex, X_ERROR,
 				"Output %s position not of form \"x y\"\n",
 				output->name);
 		    output->initial_x = output->initial_y = 0;
@@ -606,7 +724,7 @@ xf86InitialOutputPositions (ScrnInfoPtr 
 		}
 		if (!relative)
 		{
-		    xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
+		    xf86DrvMsg (scrn->scrnIndex, X_ERROR,
 				"Cannot position output %s relative to unknown output %s\n",
 				output->name, relative_name);
 		    output->initial_x = 0;
@@ -655,7 +773,7 @@ xf86InitialOutputPositions (ScrnInfoPtr 
 		xf86OutputPtr   output = config->output[o];
 		if (output->initial_x == POSITION_UNSET)
 		{
-		    xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
+		    xf86DrvMsg (scrn->scrnIndex, X_ERROR,
 				"Output position loop. Moving %s to 0,0\n",
 				output->name);
 		    output->initial_x = output->initial_y = 0;
@@ -778,16 +896,16 @@ i830xf86SortModes (DisplayModePtr input)
 #define DEBUG_REPROBE 1
 
 void
-xf86ProbeOutputModes (ScrnInfoPtr pScrn, int maxX, int maxY)
+xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY)
 {
-    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
     int			o;
 
     if (maxX == 0 || maxY == 0)
-	xf86RandR12GetOriginalVirtualSize (pScrn, &maxX, &maxY);
+	xf86RandR12GetOriginalVirtualSize (scrn, &maxX, &maxY);
 
     /* Elide duplicate modes before defaulting code uses them */
-    xf86PruneDuplicateMonitorModes (pScrn->monitor);
+    xf86PruneDuplicateMonitorModes (scrn->monitor);
     
     /* Probe the list of modes for each output. */
     for (o = 0; o < config->num_output; o++) 
@@ -837,7 +955,7 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn,
 		mon_rec.nVrefresh++;
 		sync_source = sync_config;
 	    }
-	    config_modes = i830xf86GetMonitorModes (pScrn, conf_monitor);
+	    config_modes = xf86GetMonitorModes (scrn, conf_monitor);
 	}
 	
 	output_modes = (*output->funcs->get_modes) (output);
@@ -901,27 +1019,27 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn,
 	    mon_rec.vrefresh[0].hi = 62.0;
 	    mon_rec.nVrefresh = 1;
 	}
-	default_modes = i830xf86GetDefaultModes (output->interlaceAllowed,
-						 output->doubleScanAllowed);
+	default_modes = xf86GetDefaultModes (output->interlaceAllowed,
+					     output->doubleScanAllowed);
 	
 	if (sync_source == sync_config)
 	{
 	    /* 
 	     * Check output and config modes against sync range from config file
 	     */
-	    i830xf86ValidateModesSync (pScrn, output_modes, &mon_rec);
-	    i830xf86ValidateModesSync (pScrn, config_modes, &mon_rec);
+	    xf86ValidateModesSync (scrn, output_modes, &mon_rec);
+	    xf86ValidateModesSync (scrn, config_modes, &mon_rec);
 	}
 	/*
 	 * Check default modes against sync range
 	 */
-        i830xf86ValidateModesSync (pScrn, default_modes, &mon_rec);
+        xf86ValidateModesSync (scrn, default_modes, &mon_rec);
 	/*
 	 * Check default modes against monitor max clock
 	 */
 	if (max_clock)
-	    i830xf86ValidateModesClocks(pScrn, default_modes,
-					&min_clock, &max_clock, 1);
+	    xf86ValidateModesClocks(scrn, default_modes,
+				    &min_clock, &max_clock, 1);
 	
 	output->probed_modes = NULL;
 	output->probed_modes = xf86ModesAdd (output->probed_modes, config_modes);
@@ -932,7 +1050,7 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn,
 	 * Check all modes against max size
 	 */
 	if (maxX && maxY)
-	    i830xf86ValidateModesSize (pScrn, output->probed_modes,
+	    xf86ValidateModesSize (scrn, output->probed_modes,
 				       maxX, maxY, 0);
 	 
 	/*
@@ -942,7 +1060,7 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn,
 	    if (mode->status == MODE_OK)
 		mode->status = (*output->funcs->mode_valid)(output, mode);
 	
-	i830xf86PruneInvalidModes(pScrn, &output->probed_modes, TRUE);
+	xf86PruneInvalidModes(scrn, &output->probed_modes, TRUE);
 	
 	output->probed_modes = i830xf86SortModes (output->probed_modes);
 	
@@ -975,11 +1093,11 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn,
 	
 #ifdef DEBUG_REPROBE
 	if (output->probed_modes != NULL) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+	    xf86DrvMsg(scrn->scrnIndex, X_INFO,
 		       "Printing probed modes for output %s\n",
 		       output->name);
 	} else {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+	    xf86DrvMsg(scrn->scrnIndex, X_INFO,
 		       "No remaining probed modes for output %s\n",
 		       output->name);
 	}
@@ -993,7 +1111,7 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn,
 	    xf86SetModeCrtc(mode, INTERLACE_HALVE_V);
 
 #ifdef DEBUG_REPROBE
-	    xf86PrintModeline(pScrn->scrnIndex, mode);
+	    xf86PrintModeline(scrn->scrnIndex, mode);
 #endif
 	}
     }
@@ -1006,12 +1124,12 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn,
 
 /* XXX where does this function belong? Here? */
 void
-xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y);
+xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr scrn, int *x, int *y);
 
 void
-xf86SetScrnInfoModes (ScrnInfoPtr pScrn)
+xf86SetScrnInfoModes (ScrnInfoPtr scrn)
 {
-    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
     xf86OutputPtr	output;
     xf86CrtcPtr		crtc;
     DisplayModePtr	last, mode;
@@ -1035,31 +1153,31 @@ xf86SetScrnInfoModes (ScrnInfoPtr pScrn)
     }
     crtc = output->crtc;
 
-    /* Clear any existing modes from pScrn->modes */
-    while (pScrn->modes != NULL)
-	xf86DeleteMode(&pScrn->modes, pScrn->modes);
+    /* Clear any existing modes from scrn->modes */
+    while (scrn->modes != NULL)
+	xf86DeleteMode(&scrn->modes, scrn->modes);
 
-    /* Set pScrn->modes to the mode list for the 'compat' output */
-    pScrn->modes = xf86DuplicateModes(pScrn, output->probed_modes);
+    /* Set scrn->modes to the mode list for the 'compat' output */
+    scrn->modes = xf86DuplicateModes(scrn, output->probed_modes);
 
-    for (mode = pScrn->modes; mode; mode = mode->next)
+    for (mode = scrn->modes; mode; mode = mode->next)
 	if (xf86ModesEqual (mode, &crtc->desiredMode))
 	    break;
 
-    if (pScrn->modes != NULL) {
-	/* For some reason, pScrn->modes is circular, unlike the other mode
+    if (scrn->modes != NULL) {
+	/* For some reason, scrn->modes is circular, unlike the other mode
 	 * lists.  How great is that?
 	 */
-	for (last = pScrn->modes; last && last->next; last = last->next)
+	for (last = scrn->modes; last && last->next; last = last->next)
 	    ;
-	last->next = pScrn->modes;
-	pScrn->modes->prev = last;
+	last->next = scrn->modes;
+	scrn->modes->prev = last;
 	if (mode) {
-	    while (pScrn->modes != mode)
-		pScrn->modes = pScrn->modes->next;
+	    while (scrn->modes != mode)
+		scrn->modes = scrn->modes->next;
 	}
     }
-    pScrn->currentMode = pScrn->modes;
+    scrn->currentMode = scrn->modes;
 }
 
 /**
@@ -1070,9 +1188,9 @@ xf86SetScrnInfoModes (ScrnInfoPtr pScrn)
  */
 
 Bool
-xf86InitialConfiguration (ScrnInfoPtr	    pScrn)
+xf86InitialConfiguration (ScrnInfoPtr	    scrn)
 {
-    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
     int			o, c;
     DisplayModePtr	target_mode = NULL;
     xf86CrtcPtr		*crtcs;
@@ -1081,16 +1199,16 @@ xf86InitialConfiguration (ScrnInfoPtr	  
     int			width;
     int			height;
 
-    if (pScrn->display->virtualX)
-	width = pScrn->display->virtualX;
+    if (scrn->display->virtualX)
+	width = scrn->display->virtualX;
     else
 	width = config->maxWidth;
-    if (pScrn->display->virtualY)
-	height = pScrn->display->virtualY;
+    if (scrn->display->virtualY)
+	height = scrn->display->virtualY;
     else
 	height = config->maxHeight;
 
-    xf86ProbeOutputModes (pScrn, width, height);
+    xf86ProbeOutputModes (scrn, width, height);
 
     crtcs = xnfcalloc (config->num_output, sizeof (xf86CrtcPtr));
     modes = xnfcalloc (config->num_output, sizeof (DisplayModePtr));
@@ -1152,7 +1270,7 @@ xf86InitialConfiguration (ScrnInfoPtr	  
     /*
      * Set the position of each output
      */
-    if (!xf86InitialOutputPositions (pScrn, modes))
+    if (!xf86InitialOutputPositions (scrn, modes))
     {
 	xfree (crtcs);
 	xfree (modes);
@@ -1162,7 +1280,7 @@ xf86InitialConfiguration (ScrnInfoPtr	  
     /*
      * Assign CRTCs to fit output configuration
      */
-    if (!xf86PickCrtcs (pScrn, crtcs, modes, 0, width, height))
+    if (!xf86PickCrtcs (scrn, crtcs, modes, 0, width, height))
     {
 	xfree (crtcs);
 	xfree (modes);
@@ -1171,8 +1289,8 @@ xf86InitialConfiguration (ScrnInfoPtr	  
     
     /* XXX override xf86 common frame computation code */
     
-    pScrn->display->frameX0 = 0;
-    pScrn->display->frameY0 = 0;
+    scrn->display->frameX0 = 0;
+    scrn->display->frameY0 = 0;
     
     for (c = 0; c < config->num_crtc; c++)
     {
@@ -1201,24 +1319,24 @@ xf86InitialConfiguration (ScrnInfoPtr	  
 	}
     }
     
-    if (pScrn->display->virtualX == 0)
+    if (scrn->display->virtualX == 0)
     {
 	/*
 	 * Expand virtual size to cover potential mode switches
 	 */
-	xf86DefaultScreenLimits (pScrn, &width, &height);
+	xf86DefaultScreenLimits (scrn, &width, &height);
     
-	pScrn->display->virtualX = width;
-	pScrn->display->virtualY = height;
+	scrn->display->virtualX = width;
+	scrn->display->virtualY = height;
     }
 
-    if (width > pScrn->virtualX)
-	pScrn->virtualX = width;
-    if (height > pScrn->virtualY)
-	pScrn->virtualY = height;
+    if (width > scrn->virtualX)
+	scrn->virtualX = width;
+    if (height > scrn->virtualY)
+	scrn->virtualY = height;
     
-    /* Mirror output modes to pScrn mode list */
-    xf86SetScrnInfoModes (pScrn);
+    /* Mirror output modes to scrn mode list */
+    xf86SetScrnInfoModes (scrn);
     
     xfree (crtcs);
     xfree (modes);
@@ -1232,9 +1350,9 @@ xf86InitialConfiguration (ScrnInfoPtr	  
  * Otherwise, it will affect CRTCs before outputs.
  */
 void
-xf86DPMSSet(ScrnInfoPtr pScrn, int mode, int flags)
+xf86DPMSSet(ScrnInfoPtr scrn, int mode, int flags)
 {
-    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
     int			i;
 
     if (mode == DPMSModeOff) {
@@ -1260,6 +1378,35 @@ xf86DPMSSet(ScrnInfoPtr pScrn, int mode,
     }
 }
 
+/**
+ * Disable all inactive crtcs and outputs
+ */
+void
+xf86DisableUnusedFunctions(ScrnInfoPtr pScrn)
+{
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int			o, c;
+
+    for (o = 0; o < xf86_config->num_output; o++) 
+    {
+	xf86OutputPtr  output = xf86_config->output[o];
+	if (!output->crtc) 
+	    (*output->funcs->dpms)(output, DPMSModeOff);
+    }
+
+    for (c = 0; c < xf86_config->num_crtc; c++) 
+    {
+	xf86CrtcPtr crtc = xf86_config->crtc[c];
+
+	if (!crtc->enabled) 
+	{
+	    crtc->funcs->dpms(crtc, DPMSModeOff);
+	    memset(&crtc->curMode, 0, sizeof(crtc->curMode));
+	}
+    }
+}
+
+ 
 #ifdef RANDR_12_INTERFACE
 
 #define EDID_ATOM_NAME		"EDID_DATA"
@@ -1290,10 +1437,10 @@ xf86OutputSetEDIDProperty (xf86OutputPtr
  * Set the EDID information for the specified output
  */
 void
-i830_xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon)
+xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon)
 {
-    ScrnInfoPtr		pScrn = output->scrn;
-    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
+    ScrnInfoPtr		scrn = output->scrn;
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
     int			i;
 #ifdef RANDR_12_INTERFACE
     int			size;
@@ -1305,12 +1452,12 @@ i830_xf86OutputSetEDID (xf86OutputPtr ou
     output->MonInfo = edid_mon;
 
     /* Debug info for now, at least */
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID for output %s\n", output->name);
+    xf86DrvMsg(scrn->scrnIndex, X_INFO, "EDID for output %s\n", output->name);
     xf86PrintEDID(edid_mon);
     
     /* Set the DDC properties for the 'compat' output */
     if (output == config->output[config->compat_output])
-        xf86SetDDCproperties(pScrn, edid_mon);
+        xf86SetDDCproperties(scrn, edid_mon);
 
 #ifdef RANDR_12_INTERFACE
     /* Set the RandR output properties */
@@ -1354,20 +1501,20 @@ i830_xf86OutputSetEDID (xf86OutputPtr ou
  * stored in 'output'
  */
 DisplayModePtr
-i830_xf86OutputGetEDIDModes (xf86OutputPtr output)
+xf86OutputGetEDIDModes (xf86OutputPtr output)
 {
-    ScrnInfoPtr	pScrn = output->scrn;
+    ScrnInfoPtr	scrn = output->scrn;
     xf86MonPtr	edid_mon = output->MonInfo;
 
     if (!edid_mon)
 	return NULL;
-    return xf86DDCGetModes(pScrn->scrnIndex, edid_mon);
+    return xf86DDCGetModes(scrn->scrnIndex, edid_mon);
 }
 
 xf86MonPtr
-i830_xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus)
+xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus)
 {
-    ScrnInfoPtr	pScrn = output->scrn;
+    ScrnInfoPtr	scrn = output->scrn;
 
-    return xf86DoEDID_DDC2 (pScrn->scrnIndex, pDDCBus);
+    return xf86DoEDID_DDC2 (scrn->scrnIndex, pDDCBus);
 }
diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h
index 8fea162..e72dda6 100644
--- a/src/i830_xf86Crtc.h
+++ b/src/i830_xf86Crtc.h
@@ -24,8 +24,10 @@
 
 #include <edid.h>
 #include "randrstr.h"
+#include "i830_xf86Rename.h"
 #include "i830_xf86Modes.h"
 #include "xf86Parser.h"
+#include "damage.h"
 
 /* Compat definitions for older X Servers. */
 #ifndef M_T_PREFERRED
@@ -70,6 +72,19 @@ typedef struct _xf86CrtcFuncs {
 
 
     /**
+     * Lock CRTC prior to mode setting, mostly for DRI.
+     * Returns whether unlock is needed
+     */
+    Bool
+    (*lock) (xf86CrtcPtr crtc);
+    
+    /**
+     * Unlock CRTC after mode setting, mostly for DRI
+     */
+    void
+    (*unlock) (xf86CrtcPtr crtc);
+    
+    /**
      * Callback to adjust the mode to be set in the CRTC.
      *
      * This allows a CRTC to adjust the clock or even the entire set of
@@ -95,6 +110,18 @@ typedef struct _xf86CrtcFuncs {
 		 int size);
 
     /**
+     * Create shadow pixmap for rotation support
+     */
+    PixmapPtr
+    (*shadow_create) (xf86CrtcPtr crtc, int width, int height);
+    
+    /**
+     * Destroy shadow pixmap
+     */
+    void
+    (*shadow_destroy) (xf86CrtcPtr crtc, PixmapPtr pPixmap);
+
+    /**
      * Clean up driver-specific bits of the crtc
      */
     void
@@ -135,6 +162,8 @@ struct _xf86Crtc {
      * during server startup
      */
     DisplayModeRec  curMode;
+    Rotation	    curRotation;
+    PixmapPtr	    rotatedPixmap;
     
     /**
      * Desired mode
@@ -145,6 +174,7 @@ struct _xf86Crtc {
      * on VT switch.
      */
     DisplayModeRec  desiredMode;
+    Rotation	    desiredRotation;
     
     /** crtc-specific functions */
     const xf86CrtcFuncsRec *funcs;
@@ -363,6 +393,9 @@ typedef struct _xf86CrtcConfig {
 
     int			minWidth, minHeight;
     int			maxWidth, maxHeight;
+    
+    /* For crtc-based rotation */
+    DamagePtr   rotationDamage;
 } xf86CrtcConfigRec, *xf86CrtcConfigPtr;
 
 extern int xf86CrtcConfigPrivateIndex;
@@ -411,6 +444,24 @@ xf86AllocCrtc (xf86OutputPtr		output);
 void
 xf86FreeCrtc (xf86CrtcPtr		crtc);
 
+/**
+ * Sets the given video mode on the given crtc
+ */
+Bool
+xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation);
+
+/*
+ * Assign crtc rotation during mode set
+ */
+Bool
+xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation);
+
+/**
+ * Return whether any output is assigned to the crtc
+ */
+Bool
+xf86CrtcInUse (xf86CrtcPtr crtc);
+
 /*
  * Output functions
  */
@@ -437,20 +488,23 @@ xf86InitialConfiguration (ScrnInfoPtr pS
 void
 xf86DPMSSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags);
     
+void
+xf86DisableUnusedFunctions(ScrnInfoPtr pScrn);
+
 /**
  * Set the EDID information for the specified output
  */
 void
-i830_xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon);
+xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon);
 
 /**
  * Return the list of modes supported by the EDID information
  * stored in 'output'
  */
 DisplayModePtr
-i830_xf86OutputGetEDIDModes (xf86OutputPtr output);
+xf86OutputGetEDIDModes (xf86OutputPtr output);
 
 xf86MonPtr
-i830_xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus);
+xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus);
 
 #endif /* _XF86CRTC_H_ */
diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c
index 482a332..f37eaeb 100644
--- a/src/i830_xf86Modes.c
+++ b/src/i830_xf86Modes.c
@@ -337,7 +337,7 @@ xf86PrintModeline(int scrnIndex,DisplayM
  * This is not in xf86Modes.c, but would be part of the proposed new API.
  */
 void
-i830xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,
 			    int flags)
 {
     DisplayModePtr mode;
@@ -358,7 +358,7 @@ i830xf86ValidateModesFlags(ScrnInfoPtr p
  * This is not in xf86Modes.c, but would be part of the proposed new API.
  */
 void
-i830xf86ValidateModesSize(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+xf86ValidateModesSize(ScrnInfoPtr pScrn, DisplayModePtr modeList,
 			  int maxX, int maxY, int maxPitch)
 {
     DisplayModePtr mode;
@@ -387,7 +387,7 @@ i830xf86ValidateModesSize(ScrnInfoPtr pS
  * This is not in xf86Modes.c, but would be part of the proposed new API.
  */
 void
-i830xf86ValidateModesSync(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+xf86ValidateModesSync(ScrnInfoPtr pScrn, DisplayModePtr modeList,
 			  MonPtr mon)
 {
     DisplayModePtr mode;
@@ -434,7 +434,7 @@ i830xf86ValidateModesSync(ScrnInfoPtr pS
  * This is not in xf86Modes.c, but would be part of the proposed new API.
  */
 void
-i830xf86ValidateModesClocks(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+xf86ValidateModesClocks(ScrnInfoPtr pScrn, DisplayModePtr modeList,
 			    int *min, int *max, int n_ranges)
 {
     DisplayModePtr mode;
@@ -468,7 +468,7 @@ i830xf86ValidateModesClocks(ScrnInfoPtr 
  * This is not in xf86Modes.c, but would be part of the proposed new API.
  */
 void
-i830xf86ValidateModesUserConfig(ScrnInfoPtr pScrn, DisplayModePtr modeList)
+xf86ValidateModesUserConfig(ScrnInfoPtr pScrn, DisplayModePtr modeList)
 {
     DisplayModePtr mode;
 
@@ -502,7 +502,7 @@ i830xf86ValidateModesUserConfig(ScrnInfo
  * This is not in xf86Modes.c, but would be part of the proposed new API.
  */
 void
-i830xf86PruneInvalidModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList,
+xf86PruneInvalidModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList,
 			  Bool verbose)
 {
     DisplayModePtr mode;
@@ -558,7 +558,7 @@ xf86ModesAdd(DisplayModePtr modes, Displ
  * Build a mode list from a list of config file modes
  */
 static DisplayModePtr
-i830xf86GetConfigModes (XF86ConfModeLinePtr conf_mode)
+xf86GetConfigModes (XF86ConfModeLinePtr conf_mode)
 {
     DisplayModePtr  head = NULL, prev = NULL, mode;
     
@@ -604,7 +604,7 @@ i830xf86GetConfigModes (XF86ConfModeLine
  * Build a mode list from a monitor configuration
  */
 DisplayModePtr
-i830xf86GetMonitorModes (ScrnInfoPtr pScrn, XF86ConfMonitorPtr conf_monitor)
+xf86GetMonitorModes (ScrnInfoPtr pScrn, XF86ConfMonitorPtr conf_monitor)
 {
     DisplayModePtr	    modes = NULL;
     XF86ConfModesLinkPtr    modes_link;
@@ -625,18 +625,18 @@ i830xf86GetMonitorModes (ScrnInfoPtr pSc
 						  xf86configptr->conf_modes_lst);
 	if (modes_link->ml_modes)
 	    modes = xf86ModesAdd (modes,
-				  i830xf86GetConfigModes (modes_link->ml_modes->mon_modeline_lst));
+				  xf86GetConfigModes (modes_link->ml_modes->mon_modeline_lst));
     }
 
     return xf86ModesAdd (modes,
-			 i830xf86GetConfigModes (conf_monitor->mon_modeline_lst));
+			 xf86GetConfigModes (conf_monitor->mon_modeline_lst));
 }
 
 /**
  * Build a mode list containing all of the default modes
  */
 DisplayModePtr
-i830xf86GetDefaultModes (Bool interlaceAllowed, Bool doubleScanAllowed)
+xf86GetDefaultModes (Bool interlaceAllowed, Bool doubleScanAllowed)
 {
     DisplayModePtr  head = NULL, prev = NULL, mode;
     int		    i;
diff --git a/src/i830_xf86Modes.h b/src/i830_xf86Modes.h
index a7d0839..d032199 100644
--- a/src/i830_xf86Modes.h
+++ b/src/i830_xf86Modes.h
@@ -29,67 +29,54 @@
 #define _I830_XF86MODES_H_
 #include "xorgVersion.h"
 #include "xf86Parser.h"
+#include "i830_xf86Rename.h"
 
-#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0)
-double i830_xf86ModeHSync(DisplayModePtr mode);
-double i830_xf86ModeVRefresh(DisplayModePtr mode);
-DisplayModePtr i830_xf86DuplicateMode(DisplayModePtr pMode);
-DisplayModePtr i830_xf86DuplicateModes(ScrnInfoPtr pScrn,
+double xf86ModeHSync(DisplayModePtr mode);
+double xf86ModeVRefresh(DisplayModePtr mode);
+DisplayModePtr xf86DuplicateMode(DisplayModePtr pMode);
+DisplayModePtr 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);
+void xf86SetModeDefaultName(DisplayModePtr mode);
+void xf86SetModeCrtc(DisplayModePtr p, int adjustFlags);
+Bool xf86ModesEqual(DisplayModePtr pMode1, DisplayModePtr pMode2);
+void xf86PrintModeline(int scrnIndex,DisplayModePtr mode);
+DisplayModePtr xf86ModesAdd(DisplayModePtr modes, DisplayModePtr new);
 
-DisplayModePtr i830_xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC);
-DisplayModePtr i830_xf86CVTMode(int HDisplay, int VDisplay, float VRefresh,
-				Bool Reduced, Bool Interlaced);
-
-#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
-#define xf86DDCGetModes i830_xf86DDCGetModes
-#define xf86CVTMode i830_xf86CVTMode
-#endif /* XORG_VERSION_CURRENT <= 7.2.99.2 */
+DisplayModePtr xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC);
+DisplayModePtr xf86CVTMode(int HDisplay, int VDisplay, float VRefresh,
+			   Bool Reduced, Bool Interlaced);
 
 void
-i830xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,
-			    int flags);
+xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+		       int flags);
 
 void
-i830xf86ValidateModesClocks(ScrnInfoPtr pScrn, DisplayModePtr modeList,
-			    int *min, int *max, int n_ranges);
+xf86ValidateModesClocks(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+			int *min, int *max, int n_ranges);
 
 void
-i830xf86ValidateModesSize(ScrnInfoPtr pScrn, DisplayModePtr modeList,
-			  int maxX, int maxY, int maxPitch);
+xf86ValidateModesSize(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+		      int maxX, int maxY, int maxPitch);
 
 void
-i830xf86ValidateModesSync(ScrnInfoPtr pScrn, DisplayModePtr modeList,
-			  MonPtr mon);
+xf86ValidateModesSync(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+		      MonPtr mon);
 
 void
-i830xf86PruneInvalidModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList,
-			  Bool verbose);
+xf86PruneInvalidModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList,
+		      Bool verbose);
 
 void
-i830xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,
-			    int flags);
+xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+		       int flags);
 
 void
-i830xf86ValidateModesUserConfig(ScrnInfoPtr pScrn, DisplayModePtr modeList);
+xf86ValidateModesUserConfig(ScrnInfoPtr pScrn, DisplayModePtr modeList);
 
 DisplayModePtr
-i830xf86GetMonitorModes (ScrnInfoPtr pScrn, XF86ConfMonitorPtr conf_monitor);
+xf86GetMonitorModes (ScrnInfoPtr pScrn, XF86ConfMonitorPtr conf_monitor);
 
 DisplayModePtr
-i830xf86GetDefaultModes (Bool interlaceAllowed, Bool doubleScanAllowed);
+xf86GetDefaultModes (Bool interlaceAllowed, Bool doubleScanAllowed);
 
 #endif /* _I830_XF86MODES_H_ */
diff --git a/src/i830_xf86Rename.h b/src/i830_xf86Rename.h
new file mode 100644
index 0000000..cf8de62
--- /dev/null
+++ b/src/i830_xf86Rename.h
@@ -0,0 +1,66 @@
+/*
+ * 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 _XF86RENAME_H_
+#define _XF86RENAME_H_
+
+#include "local_xf86Rename.h"
+
+#define xf86CrtcConfigInit XF86NAME(xf86CrtcConfigInit)
+#define xf86CrtcConfigPrivateIndex XF86NAME(xf86CrtcConfigPrivateIndex)
+#define xf86CrtcCreate XF86NAME(xf86CrtcCreate)
+#define xf86CrtcDestroy XF86NAME(xf86CrtcDestroy)
+#define xf86CrtcInUse XF86NAME(xf86CrtcInUse)
+#define xf86CrtcRotate XF86NAME(xf86CrtcRotate)
+#define xf86CrtcSetMode XF86NAME(xf86CrtcSetMode)
+#define xf86CrtcSetSizeRange XF86NAME(xf86CrtcSetSizeRange)
+#define xf86CVTMode XF86NAME(xf86CVTMode)
+#define xf86DisableUnusedFunctions XF86NAME(xf86DisableUnusedFunctions)
+#define xf86DPMSSet XF86NAME(xf86DPMSSet)
+#define xf86DuplicateMode XF86NAME(xf86DuplicateMode)
+#define xf86DuplicateModes XF86NAME(xf86DuplicateModes)
+#define xf86GetDefaultModes XF86NAME(xf86GetDefaultModes)
+#define xf86GetMonitorModes XF86NAME(xf86GetMonitorModes)
+#define xf86InitialConfiguration XF86NAME(xf86InitialConfiguration)
+#define xf86ModeHSync XF86NAME(xf86ModeHSync)
+#define xf86ModesAdd XF86NAME(xf86ModesAdd)
+#define xf86ModesEqual XF86NAME(xf86ModesEqual)
+#define xf86ModeVRefresh XF86NAME(xf86ModeVRefresh)
+#define xf86OutputCreate XF86NAME(xf86OutputCreate)
+#define xf86OutputDestroy XF86NAME(xf86OutputDestroy)
+#define xf86OutputGetEDID XF86NAME(xf86OutputGetEDID)
+#define xf86OutputGetEDIDModes XF86NAME(xf86OutputGetEDIDModes)
+#define xf86OutputRename XF86NAME(xf86OutputRename)
+#define xf86OutputSetEDID XF86NAME(xf86OutputSetEDID)
+#define xf86PrintModeline XF86NAME(xf86PrintModeline)
+#define xf86ProbeOutputModes XF86NAME(xf86ProbeOutputModes)
+#define xf86PruneInvalidModes XF86NAME(xf86PruneInvalidModes)
+#define xf86SetModeCrtc XF86NAME(xf86SetModeCrtc)
+#define xf86SetModeDefaultName XF86NAME(xf86SetModeDefaultName)
+#define xf86SetScrnInfoModes XF86NAME(xf86SetScrnInfoModes)
+#define xf86ValidateModesClocks XF86NAME(xf86ValidateModesClocks)
+#define xf86ValidateModesFlags XF86NAME(xf86ValidateModesFlags)
+#define xf86ValidateModesSize XF86NAME(xf86ValidateModesSize)
+#define xf86ValidateModesSync XF86NAME(xf86ValidateModesSync)
+#define xf86ValidateModesUserConfig XF86NAME(xf86ValidateModesUserConfig)
+
+#endif /* _XF86RENAME_H_ */
diff --git a/src/i830_xf86Rotate.c b/src/i830_xf86Rotate.c
new file mode 100644
index 0000000..12b2091
--- /dev/null
+++ b/src/i830_xf86Rotate.c
@@ -0,0 +1,324 @@
+/*
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stddef.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "xf86.h"
+#include "xf86DDC.h"
+/*#include "i830.h" */
+#include "i830_xf86Crtc.h"
+#include "i830_xf86Modes.h"
+#include "i830_randr.h"
+#include "X11/extensions/render.h"
+#define DPMS_SERVER
+#include "X11/extensions/dpms.h"
+#include "X11/Xatom.h"
+
+static int
+mode_height (DisplayModePtr mode, Rotation rotation)
+{
+    switch (rotation & 0xf) {
+    case RR_Rotate_0:
+    case RR_Rotate_180:
+	return mode->VDisplay;
+    case RR_Rotate_90:
+    case RR_Rotate_270:
+	return mode->HDisplay;
+    default:
+	return 0;
+    }
+}
+
+static int
+mode_width (DisplayModePtr mode, Rotation rotation)
+{
+    switch (rotation & 0xf) {
+    case RR_Rotate_0:
+    case RR_Rotate_180:
+	return mode->HDisplay;
+    case RR_Rotate_90:
+    case RR_Rotate_270:
+	return mode->VDisplay;
+    default:
+	return 0;
+    }
+}
+
+/* borrowed from composite extension, move to Render and publish? */
+
+static VisualPtr
+compGetWindowVisual (WindowPtr pWin)
+{
+    ScreenPtr	    pScreen = pWin->drawable.pScreen;
+    VisualID	    vid = wVisual (pWin);
+    int		    i;
+
+    for (i = 0; i < pScreen->numVisuals; i++)
+	if (pScreen->visuals[i].vid == vid)
+	    return &pScreen->visuals[i];
+    return 0;
+}
+
+static PictFormatPtr
+compWindowFormat (WindowPtr pWin)
+{
+    ScreenPtr	pScreen = pWin->drawable.pScreen;
+    
+    return PictureMatchVisual (pScreen, pWin->drawable.depth,
+			       compGetWindowVisual (pWin));
+}
+
+static void
+xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region)
+{
+    ScrnInfoPtr		scrn = crtc->scrn;
+    ScreenPtr		screen = scrn->pScreen;
+    PixmapPtr		src_pixmap = (*screen->GetScreenPixmap) (screen);
+    PixmapPtr		dst_pixmap = crtc->rotatedPixmap;
+    PictFormatPtr	format = compWindowFormat (WindowTable[screen->myNum]);
+    int			error;
+    PicturePtr		src, dst;
+    PictTransform	transform;
+    
+    src = CreatePicture (None,
+			 &src_pixmap->drawable,
+			 format,
+			 0L,
+			 NULL,
+			 serverClient,
+			 &error);
+    if (!src)
+	return;
+    dst = CreatePicture (None,
+			 &dst_pixmap->drawable,
+			 format,
+			 0L,
+			 NULL,
+			 serverClient,
+			 &error);
+    if (!dst)
+	return;
+    SetPictureClipRegion (src, 0, 0, region);
+    memset (&transform, '\0', sizeof (transform));
+    transform.matrix[2][2] = 1;
+    transform.matrix[0][2] = crtc->x;
+    transform.matrix[1][2] = crtc->y;
+    switch (crtc->curRotation & 0xf) {
+    case RR_Rotate_0:
+	transform.matrix[0][0] = 1;
+	transform.matrix[1][1] = 1;
+	break;
+    case RR_Rotate_90:
+	/* XXX probably wrong */
+	transform.matrix[0][1] = 1;
+	transform.matrix[1][0] = -1;
+	transform.matrix[1][2] += crtc->curMode.HDisplay;
+	break;
+    case RR_Rotate_180:
+	/* XXX probably wrong */
+	transform.matrix[0][0] = -1;
+	transform.matrix[1][1] = -1;
+	transform.matrix[0][2] += crtc->curMode.HDisplay;
+	transform.matrix[1][2] += crtc->curMode.VDisplay;
+	break;
+    case RR_Rotate_270:
+	/* XXX probably wrong */
+	transform.matrix[0][1] = -1;
+	transform.matrix[1][0] = 1;
+	transform.matrix[0][2] += crtc->curMode.VDisplay;
+	break;
+    }
+    /* handle reflection */
+    if (crtc->curRotation & RR_Reflect_X)
+    {
+	/* XXX figure this out */
+    }
+    if (crtc->curRotation & RR_Reflect_Y)
+    {
+	/* XXX figure this out too */
+    }
+    SetPictureTransform (src, &transform);
+    CompositePicture (PictOpSrc,
+		      src, NULL, dst,
+		      0, 0, 0, 0, 0, 0,
+		      dst_pixmap->drawable.width,
+		      dst_pixmap->drawable.height);
+    FreePicture (src, None);
+    FreePicture (dst, None);
+}
+
+static void
+xf86RotateRedisplay(ScreenPtr pScreen)
+{
+    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    DamagePtr		damage = xf86_config->rotationDamage;
+    RegionPtr		region;
+
+    if (!damage)
+	return;
+    region = DamageRegion(damage);
+    if (REGION_NOTEMPTY(pScreen, region)) 
+    {
+	int		    c;
+	
+	for (c = 0; c < xf86_config->num_crtc; c++)
+	{
+	    xf86CrtcPtr	    crtc = xf86_config->crtc[c];
+
+	    if (crtc->curRotation != RR_Rotate_0)
+	    {
+		BoxRec	    box;
+		RegionRec   crtc_damage;
+
+		/* compute portion of damage that overlaps crtc */
+		box.x1 = crtc->x;
+		box.x2 = crtc->x + mode_width (&crtc->curMode, crtc->curRotation);
+		box.y1 = crtc->y;
+		box.y2 = crtc->y + mode_height (&crtc->curMode, crtc->curRotation);
+		REGION_INIT(pScreen, &crtc_damage, &box, 1);
+		REGION_INTERSECT (pScreen, &crtc_damage, &crtc_damage, region);
+		
+		/* update damaged region */
+		if (REGION_NOTEMPTY(pScreen, &crtc_damage))
+		    xf86RotateCrtcRedisplay (crtc, &crtc_damage);
+		
+		REGION_UNINIT (pScreen, &crtc_damage);
+	    }
+	}
+	DamageEmpty(damage);
+    }
+}
+
+static void
+xf86RotateBlockHandler(pointer data, OSTimePtr pTimeout, pointer pRead)
+{
+    ScreenPtr pScreen = (ScreenPtr) data;
+
+    xf86RotateRedisplay(pScreen);
+}
+
+static void
+xf86RotateWakeupHandler(pointer data, int i, pointer LastSelectMask)
+{
+}
+
+Bool
+xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
+{
+    ScrnInfoPtr		pScrn = crtc->scrn;
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    ScreenPtr		pScreen = pScrn->pScreen;
+    
+    if (rotation == RR_Rotate_0)
+    {
+	/* Free memory from rotation */
+	if (crtc->rotatedPixmap)
+	{
+	    crtc->funcs->shadow_destroy (crtc, crtc->rotatedPixmap);
+	    crtc->rotatedPixmap = NULL;
+	}
+
+	if (xf86_config->rotationDamage)
+	{
+	    /* Free damage structure */
+	    DamageDestroy (xf86_config->rotationDamage);
+	    xf86_config->rotationDamage = NULL;
+	    /* Free block/wakeup handler */
+	    RemoveBlockAndWakeupHandlers (xf86RotateBlockHandler,
+					  xf86RotateWakeupHandler,
+					  (pointer) pScreen);
+	}
+    }
+    else
+    {
+	int	    width = mode_width (mode, rotation);
+	int	    height = mode_height (mode, rotation);
+	PixmapPtr   shadow = crtc->rotatedPixmap;
+	int	    old_width = shadow ? shadow->drawable.width : 0;
+	int	    old_height = shadow ? shadow->drawable.height : 0;
+	
+	/* Allocate memory for rotation */
+	if (old_width != width || old_height != height)
+	{
+	    if (shadow)
+	    {
+		crtc->funcs->shadow_destroy (crtc, shadow);
+		crtc->rotatedPixmap = NULL;
+	    }
+	    shadow = crtc->funcs->shadow_create (crtc, width, height);
+	    if (!shadow)
+		goto bail1;
+	}
+	
+	if (!xf86_config->rotationDamage)
+	{
+	    /* Create damage structure */
+	    xf86_config->rotationDamage = DamageCreate (NULL, NULL,
+						DamageReportNone,
+						TRUE, pScreen, pScreen);
+	    if (!xf86_config->rotationDamage)
+		goto bail2;
+	    
+	    /* Hook damage to screen pixmap */
+	    DamageRegister (&(*pScreen->GetScreenPixmap)(pScreen)->drawable,
+			    xf86_config->rotationDamage);
+	    
+	    /* Assign block/wakeup handler */
+	    if (!RegisterBlockAndWakeupHandlers (xf86RotateBlockHandler,
+						 xf86RotateWakeupHandler,
+						 (pointer) pScreen))
+	    {
+		goto bail3;
+	    }
+	}
+	if (0)
+	{
+bail3:
+	    DamageDestroy (xf86_config->rotationDamage);
+	    xf86_config->rotationDamage = NULL;
+	    
+bail2:
+	    if (shadow)
+	    {
+		crtc->funcs->shadow_destroy (crtc, shadow);
+		crtc->rotatedPixmap = NULL;
+	    }
+bail1:
+	    if (old_width && old_height)
+		crtc->rotatedPixmap = crtc->funcs->shadow_create (crtc,
+								  old_width,
+								  old_height);
+	    return FALSE;
+	}
+    }
+    
+    /* All done */
+    crtc->curRotation = rotation;
+    return TRUE;
+}
diff --git a/src/local_xf86Rename.h b/src/local_xf86Rename.h
new file mode 100644
index 0000000..e1e788f
--- /dev/null
+++ b/src/local_xf86Rename.h
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+#define XF86NAME(x) intel_##x
diff-tree 45696aa29124e2852f94880642e70bb2e0cee827 (from 6874a6f25ac87783d3770f77b9192e2d36d083a3)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jan 4 12:34:47 2007 -0800

    EXA: Use PRIM3D_RECTLIST instead of TRIFAN so we don't get diagonal tearing.
    
    A side effect is the reduction in vertex dispatch, which is nice.

diff --git a/src/i830_exa.c b/src/i830_exa.c
index f11424f..f1cd1e3 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -345,9 +345,9 @@ IntelEXAComposite(PixmapPtr pDst, int sr
 	int vertex_count; 
 
 	if (pMask)
-		vertex_count = 4*6;
+		vertex_count = 3*6;
 	else
-		vertex_count = 4*4;
+		vertex_count = 3*4;
 
 	BEGIN_LP_RING(6+vertex_count);
 
@@ -357,7 +357,7 @@ IntelEXAComposite(PixmapPtr pDst, int sr
 	OUT_RING(MI_NOOP);
 	OUT_RING(MI_NOOP);
 
-	OUT_RING(PRIM3D_INLINE | PRIM3D_TRIFAN | (vertex_count-1));
+	OUT_RING(PRIM3D_INLINE | PRIM3D_RECTLIST | (vertex_count-1));
 
 	OUT_RING_F(dstX);
 	OUT_RING_F(dstY);
@@ -385,15 +385,6 @@ IntelEXAComposite(PixmapPtr pDst, int sr
 		OUT_RING_F(maskXend / pI830->scale_units[1][0]);
 		OUT_RING_F(maskYend / pI830->scale_units[1][1]);
 	}
-
-	OUT_RING_F(dstX + w);
-	OUT_RING_F(dstY);
-	OUT_RING_F(srcXend / pI830->scale_units[0][0]);
-	OUT_RING_F(srcY / pI830->scale_units[0][1]);
-	if (pMask) {
-		OUT_RING_F(maskXend / pI830->scale_units[1][0]);
-		OUT_RING_F(maskY / pI830->scale_units[1][1]);
-	}
 	ADVANCE_LP_RING();
     }
 }
diff-tree 6874a6f25ac87783d3770f77b9192e2d36d083a3 (from c288aea40775a9cf561fda9912187c3cb5baa419)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jan 11 12:34:38 2007 -0800

    Restore legacy overlay size limits, due to card hangs at larger sizes.

diff --git a/src/i830_video.c b/src/i830_video.c
index 816289e..a330eb5 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -128,12 +128,14 @@ I830FreeMemory(ScrnInfoPtr pScrn, struct
 static Atom xvBrightness, xvContrast, xvSaturation, xvColorKey, xvPipe, xvDoubleBuffer;
 static Atom xvGamma0, xvGamma1, xvGamma2, xvGamma3, xvGamma4, xvGamma5;
 
-/* Limits for the overlay/textured video source sizes.  The actual hardware
+/* Limits for the overlay/textured video source sizes.  The documented hardware
  * limits are 2048x2048 or better for overlay and both of our textured video
  * implementations.  However, we run into the bigrequests limit of (currently)
  * 4MB, which even the planar format's 2048*2048*1.5 bytes is larger than.
  * Conveniently, the HD resolution, even in packed format, takes
- * (1920*1088*2) bytes, which is just shy of 4MB.
+ * (1920*1088*2) bytes, which is just shy of 4MB.  Additionally, on the 830
+ * and 845, larger sizes resulted in the card hanging, so we keep the limits
+ * lower there.
  *
  * While the HD resolution is actually 1920x1080, we increase our advertised
  * size to 1088 because some software wants to send an image aligned to
@@ -141,6 +143,8 @@ static Atom xvGamma0, xvGamma1, xvGamma2
  */
 #define IMAGE_MAX_WIDTH		1920
 #define IMAGE_MAX_HEIGHT	1088
+#define IMAGE_MAX_WIDTH_LEGACY	1024
+#define IMAGE_MAX_HEIGHT_LEGACY	1088
 
 /* overlay debugging printf function */
 #if 0
@@ -678,6 +682,11 @@ I830SetupImageVideoOverlay(ScreenPtr pSc
    adapt->name = "Intel(R) Video Overlay";
    adapt->nEncodings = 1;
    adapt->pEncodings = DummyEncoding;
+   /* update the DummyEncoding for these two chipsets */
+   if (IS_845G(pI830) || IS_I830(pI830)) {
+      adapt->pEncodings->width = IMAGE_MAX_WIDTH_LEGACY;
+      adapt->pEncodings->height = IMAGE_MAX_HEIGHT_LEGACY;
+   }
    adapt->nFormats = NUM_FORMATS;
    adapt->pFormats = Formats;
    adapt->nPorts = 1;
@@ -2434,16 +2443,24 @@ I830QueryImageAttributes(ScrnInfoPtr pSc
 			 unsigned short *w, unsigned short *h,
 			 int *pitches, int *offsets, Bool textured)
 {
+   I830Ptr pI830 = I830PTR(pScrn);
    int size, tmp;
 
 #if 0
    ErrorF("I830QueryImageAttributes: w is %d, h is %d\n", *w, *h);
 #endif
 
-   if (*w > IMAGE_MAX_WIDTH)
-       *w = IMAGE_MAX_WIDTH;
-   if (*h > IMAGE_MAX_HEIGHT)
-       *h = IMAGE_MAX_HEIGHT;
+   if (IS_845G(pI830) || IS_I830(pI830)) {
+      if (*w > IMAGE_MAX_WIDTH_LEGACY)
+	 *w = IMAGE_MAX_WIDTH_LEGACY;
+      if (*h > IMAGE_MAX_HEIGHT_LEGACY)
+	 *h = IMAGE_MAX_HEIGHT_LEGACY;
+   } else {
+      if (*w > IMAGE_MAX_WIDTH)
+	 *w = IMAGE_MAX_WIDTH;
+      if (*h > IMAGE_MAX_HEIGHT)
+	 *h = IMAGE_MAX_HEIGHT;
+   }
 
    *w = (*w + 1) & ~1;
    if (offsets)
@@ -2581,8 +2598,13 @@ I830AllocateSurface(ScrnInfoPtr pScrn,
 
    OVERLAY_DEBUG("I830AllocateSurface\n");
 
-   if ((w > IMAGE_MAX_WIDTH) || (h > IMAGE_MAX_HEIGHT))
-       return BadAlloc;
+   if (IS_845G(pI830) || IS_I830(pI830)) {
+      if ((w > IMAGE_MAX_WIDTH_LEGACY) || (h > IMAGE_MAX_HEIGHT_LEGACY))
+         return BadAlloc;
+   } else {
+      if ((w > IMAGE_MAX_WIDTH) || (h > IMAGE_MAX_HEIGHT))
+         return BadAlloc;
+   }
 
    /* What to do when rotated ?? */
    if (pI830->rotation != RR_Rotate_0)
@@ -2784,6 +2806,8 @@ static void
 I830InitOffscreenImages(ScreenPtr pScreen)
 {
    XF86OffscreenImagePtr offscreenImages;
+   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+   I830Ptr pI830 = I830PTR(pScrn);
 
    /* need to free this someplace */
    if (!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec)))) {
@@ -2798,8 +2822,13 @@ I830InitOffscreenImages(ScreenPtr pScree
    offscreenImages[0].stop = I830StopSurface;
    offscreenImages[0].setAttribute = I830SetSurfaceAttribute;
    offscreenImages[0].getAttribute = I830GetSurfaceAttribute;
-   offscreenImages[0].max_width = IMAGE_MAX_WIDTH;
-   offscreenImages[0].max_height = IMAGE_MAX_HEIGHT;
+   if (IS_845G(pI830) || IS_I830(pI830)) {
+      offscreenImages[0].max_width = IMAGE_MAX_WIDTH_LEGACY;
+      offscreenImages[0].max_height = IMAGE_MAX_HEIGHT_LEGACY;
+   } else {
+      offscreenImages[0].max_width = IMAGE_MAX_WIDTH;
+      offscreenImages[0].max_height = IMAGE_MAX_HEIGHT; 
+   }
    offscreenImages[0].num_attributes = 1;
    offscreenImages[0].attributes = Attributes;
 
diff-tree c288aea40775a9cf561fda9912187c3cb5baa419 (from f5d528f8ea27de31054e7f1843e34d8379f811ea)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jan 11 10:39:00 2007 -0800

    Bug #8845: Unify all our XV ports to 1920x1088 maximum size.
    
    This increases the "legacy" size, but that was checked against the 845
    documentation which claims support for 2048x2048 as well.  It decreases the
    textured video size, which was running into the limits of the bigrequests
    extension.  The new limits should fit within bigrequests while still supporting
    HD videos.

diff --git a/src/i830_video.c b/src/i830_video.c
index 652e73d..816289e 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -128,10 +128,19 @@ I830FreeMemory(ScrnInfoPtr pScrn, struct
 static Atom xvBrightness, xvContrast, xvSaturation, xvColorKey, xvPipe, xvDoubleBuffer;
 static Atom xvGamma0, xvGamma1, xvGamma2, xvGamma3, xvGamma4, xvGamma5;
 
+/* Limits for the overlay/textured video source sizes.  The actual hardware
+ * limits are 2048x2048 or better for overlay and both of our textured video
+ * implementations.  However, we run into the bigrequests limit of (currently)
+ * 4MB, which even the planar format's 2048*2048*1.5 bytes is larger than.
+ * Conveniently, the HD resolution, even in packed format, takes
+ * (1920*1088*2) bytes, which is just shy of 4MB.
+ *
+ * While the HD resolution is actually 1920x1080, we increase our advertised
+ * size to 1088 because some software wants to send an image aligned to
+ * 16-pixel boundaries.
+ */
 #define IMAGE_MAX_WIDTH		1920
 #define IMAGE_MAX_HEIGHT	1088
-#define IMAGE_MAX_WIDTH_LEGACY	1024
-#define IMAGE_MAX_HEIGHT_LEGACY	1088
 
 /* overlay debugging printf function */
 #if 0
@@ -669,11 +678,6 @@ I830SetupImageVideoOverlay(ScreenPtr pSc
    adapt->name = "Intel(R) Video Overlay";
    adapt->nEncodings = 1;
    adapt->pEncodings = DummyEncoding;
-   /* update the DummyEncoding for these two chipsets */
-   if (IS_845G(pI830) || IS_I830(pI830)) {
-      adapt->pEncodings->width = IMAGE_MAX_WIDTH_LEGACY;
-      adapt->pEncodings->height = IMAGE_MAX_HEIGHT_LEGACY;
-   }
    adapt->nFormats = NUM_FORMATS;
    adapt->pFormats = Formats;
    adapt->nPorts = 1;
@@ -777,7 +781,6 @@ static XF86VideoAdaptorPtr
 I830SetupImageVideoTextured(ScreenPtr pScreen)
 {
    XF86VideoAdaptorPtr adapt;
-   XF86VideoEncodingPtr encoding;
    XF86AttributePtr attrs;
    I830PortPrivPtr portPrivs;
    DevUnion *devUnions;
@@ -791,15 +794,13 @@ I830SetupImageVideoTextured(ScreenPtr pS
    adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec));
    portPrivs = xcalloc(nports, sizeof(I830PortPrivRec));
    devUnions = xcalloc(nports, sizeof(DevUnion));
-   encoding = xcalloc(1, sizeof(XF86VideoEncodingRec));
    attrs = xcalloc(nAttributes, sizeof(XF86AttributeRec));
    if (adapt == NULL || portPrivs == NULL || devUnions == NULL ||
-       encoding == NULL || attrs == NULL)
+       attrs == NULL)
    {
       xfree(adapt);
       xfree(portPrivs);
       xfree(devUnions);
-      xfree(encoding);
       xfree(attrs);
       return NULL;
    }
@@ -808,13 +809,7 @@ I830SetupImageVideoTextured(ScreenPtr pS
    adapt->flags = 0;
    adapt->name = "Intel(R) Textured Video";
    adapt->nEncodings = 1;
-   adapt->pEncodings = encoding;
-   adapt->pEncodings[0].id = 0;
-   adapt->pEncodings[0].name = "XV_IMAGE";
-   adapt->pEncodings[0].width = 2048;
-   adapt->pEncodings[0].height = 2048;
-   adapt->pEncodings[0].rate.numerator = 1;
-   adapt->pEncodings[0].rate.denominator = 1;
+   adapt->pEncodings = DummyEncoding;
    adapt->nFormats = NUM_FORMATS;
    adapt->pFormats = Formats;
    adapt->nPorts = nports;
@@ -2439,26 +2434,16 @@ I830QueryImageAttributes(ScrnInfoPtr pSc
 			 unsigned short *w, unsigned short *h,
 			 int *pitches, int *offsets, Bool textured)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
    int size, tmp;
 
 #if 0
    ErrorF("I830QueryImageAttributes: w is %d, h is %d\n", *w, *h);
 #endif
 
-   if (!textured) {
-      if (IS_845G(pI830) || IS_I830(pI830)) {
-	 if (*w > IMAGE_MAX_WIDTH_LEGACY)
-	    *w = IMAGE_MAX_WIDTH_LEGACY;
-	 if (*h > IMAGE_MAX_HEIGHT_LEGACY)
-	    *h = IMAGE_MAX_HEIGHT_LEGACY;
-      } else {
-	 if (*w > IMAGE_MAX_WIDTH)
-	    *w = IMAGE_MAX_WIDTH;
-	 if (*h > IMAGE_MAX_HEIGHT)
-	    *h = IMAGE_MAX_HEIGHT;
-      }
-   }
+   if (*w > IMAGE_MAX_WIDTH)
+       *w = IMAGE_MAX_WIDTH;
+   if (*h > IMAGE_MAX_HEIGHT)
+       *h = IMAGE_MAX_HEIGHT;
 
    *w = (*w + 1) & ~1;
    if (offsets)
@@ -2596,13 +2581,8 @@ I830AllocateSurface(ScrnInfoPtr pScrn,
 
    OVERLAY_DEBUG("I830AllocateSurface\n");
 
-   if (IS_845G(pI830) || IS_I830(pI830)) {
-      if ((w > IMAGE_MAX_WIDTH_LEGACY) || (h > IMAGE_MAX_HEIGHT_LEGACY))
-         return BadAlloc;
-   } else {
-      if ((w > IMAGE_MAX_WIDTH) || (h > IMAGE_MAX_HEIGHT))
-         return BadAlloc;
-   }
+   if ((w > IMAGE_MAX_WIDTH) || (h > IMAGE_MAX_HEIGHT))
+       return BadAlloc;
 
    /* What to do when rotated ?? */
    if (pI830->rotation != RR_Rotate_0)
@@ -2804,8 +2784,6 @@ static void
 I830InitOffscreenImages(ScreenPtr pScreen)
 {
    XF86OffscreenImagePtr offscreenImages;
-   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-   I830Ptr pI830 = I830PTR(pScrn);
 
    /* need to free this someplace */
    if (!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec)))) {
@@ -2820,13 +2798,8 @@ I830InitOffscreenImages(ScreenPtr pScree
    offscreenImages[0].stop = I830StopSurface;
    offscreenImages[0].setAttribute = I830SetSurfaceAttribute;
    offscreenImages[0].getAttribute = I830GetSurfaceAttribute;
-   if (IS_845G(pI830) || IS_I830(pI830)) {
-      offscreenImages[0].max_width = IMAGE_MAX_WIDTH_LEGACY;
-      offscreenImages[0].max_height = IMAGE_MAX_HEIGHT_LEGACY;
-   } else {
-      offscreenImages[0].max_width = IMAGE_MAX_WIDTH;
-      offscreenImages[0].max_height = IMAGE_MAX_HEIGHT; 
-   }
+   offscreenImages[0].max_width = IMAGE_MAX_WIDTH;
+   offscreenImages[0].max_height = IMAGE_MAX_HEIGHT;
    offscreenImages[0].num_attributes = 1;
    offscreenImages[0].attributes = Attributes;
 
diff-tree f5d528f8ea27de31054e7f1843e34d8379f811ea (from d13bc016c0723f1df633ddaf5610ad73003b7c96)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jan 11 10:36:33 2007 -0800

    Don't limit cachelines to a vertical of 2048, and increase default allocation.
    
    The cachelines are used for two things: XAA pixmap cache and XV memory.
    Only XAA pixmap cache is referred to using an offset pointing at the
    beginning of the front buffer in rendering, and XAA only uses the 2d BLT
    engine, which actually has a vertical limit of 65536.  So, pixmap cache is now
    limited to that much vertical.
    
    Additionally, the previous cachelines allocation was too small for our
    advertised XV limits, so video at the limits would fail with BadAlloc.  Now,
    XAA allocates the same approximate amount of offscreen memory as EXA:
    3 times the screen size, plus one packed HD video.

diff --git a/man/i810.man b/man/i810.man
index ff45809..d1ee2da 100644
--- a/man/i810.man
+++ b/man/i810.man
@@ -84,9 +84,12 @@ This allows the user to change the amoun
 2D acceleration and video.  Decreasing this amount leaves more for 3D
 textures.  Increasing it can improve 2D performance at the expense of
 3D performance.
+.TP
+This option only takes effect when XAA acceleration is enabled.
+.TP
 Default: depends on the resolution, depth, and available video memory.  The
-driver attempts to allocate at least enough to hold two DVD-sized YUV buffers
-by default.  The default used for a specific configuration can be found
+driver attempts to allocate space for at 3 screenfuls of pixmaps plus an
+HD-sized XV video.  The default used for a specific configuration can be found
 by examining the __xservername__ log file.
 .TP
 .BI "Option \*qDRI\*q \*q" boolean \*q
diff --git a/src/common.h b/src/common.h
index 2035862..561dfac 100644
--- a/src/common.h
+++ b/src/common.h
@@ -339,10 +339,6 @@ extern int I810_DEBUG;
 #define I810_CURSOR_X			64
 #define I810_CURSOR_Y			I810_CURSOR_X
 
-/* XXX Need to check if these are reasonable. */
-#define MAX_DISPLAY_PITCH		2048
-#define MAX_DISPLAY_HEIGHT		2048
-
 #define PIPE_NAME(n)			('A' + (n))
 
 #endif /* _INTEL_COMMON_H_ */
diff --git a/src/i830_memory.c b/src/i830_memory.c
index af86688..426242a 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -637,6 +637,13 @@ GetFreeSpace(ScrnInfoPtr pScrn)
    return extra;
 }
 
+/* This is the 2D rendering vertical coordinate limit.  We can ignore
+ * the 3D rendering limits in our 2d pixmap cache allocation, because XAA
+ * doesn't do any 3D rendering to/from the cache lines when using an offset
+ * at the start of framebuffer.
+ */
+#define MAX_2D_HEIGHT		65536
+
 /**
  * Allocates a framebuffer for a screen.
  *
@@ -698,25 +705,19 @@ I830AllocateFramebuffer(ScrnInfoPtr pScr
 		    "maxCacheLines < 0 in I830Allocate2DMemory()\n");
 	 maxCacheLines = 0;
       }
-      if (maxCacheLines > (MAX_DISPLAY_HEIGHT - pScrn->virtualY))
-	 maxCacheLines = MAX_DISPLAY_HEIGHT - pScrn->virtualY;
+      if (maxCacheLines > (MAX_2D_HEIGHT - pScrn->virtualY))
+	 maxCacheLines = MAX_2D_HEIGHT - pScrn->virtualY;
 
       if (pI830->CacheLines >= 0) {
 	 cacheLines = pI830->CacheLines;
       } else {
-#if 1
-	 /* Make sure there is enough for two DVD sized YUV buffers */
-	 cacheLines = (pScrn->depth == 24) ? 256 : 384;
-	 if (pScrn->displayWidth <= 1024)
-	    cacheLines *= 2;
-#else
-	 /*
-	  * Make sure there is enough for two DVD sized YUV buffers.
-	  * Make that 1.5MB, which is around what was allocated with
-	  * the old algorithm
-	  */
-	 cacheLines = (MB(1) + KB(512)) / pI830->cpp / pScrn->displayWidth;
-#endif
+	 int size;
+
+	 size = 3 * lineSize * pScrn->virtualY;
+	 size += 1920 * 1088 * 2 * 2;
+	 size = ROUND_TO_PAGE(size);
+
+	 cacheLines = (size + lineSize - 1) / lineSize;
       }
       if (cacheLines > maxCacheLines)
 	 cacheLines = maxCacheLines;
@@ -902,8 +903,8 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
       maxFb = pI830->FrontBuffer.Size + extra;
       lineSize = pScrn->displayWidth * pI830->cpp;
       maxFb = ROUND_DOWN_TO(maxFb, lineSize);
-      if (maxFb > lineSize * MAX_DISPLAY_HEIGHT)
-	 maxFb = lineSize * MAX_DISPLAY_HEIGHT;
+      if (maxFb > lineSize * MAX_2D_HEIGHT)
+	 maxFb = lineSize * MAX_2D_HEIGHT;
       if (0/*maxFb > pI830->FrontBuffer.Size*/) {
 	 unsigned long oldsize;
 	 /*
diff-tree d13bc016c0723f1df633ddaf5610ad73003b7c96 (from fa383289ac8a6dd1cb359e6f1991cc42beb6ff02)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Jan 10 15:06:56 2007 -0800

    Correct x/y/pitch limitations in several cases, and detail them in i830_exa.c.
    
    This reduces max framebuffer width and increases max framebuffer height on
    965, reduces max X/Y on pre-965 EXA (could have caused mis-rendering), and
    increases max X/Y on 965 EXA (would have prevented acceleration).

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 9bc74b5..20781aa 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1139,14 +1139,13 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    /* Allocate an xf86CrtcConfig */
    xf86CrtcConfigInit (pScrn);
    xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-   
-   if (IS_I965G(pI830))
-   {
-      max_width = 16384;
-      max_height = 4096;
-   }
-   else
-   {
+
+   /* See i830_exa.c comments for why we limit the framebuffer size like this.
+    */
+   if (IS_I965G(pI830)) {
+      max_width = 8192;
+      max_height = 8192;
+   } else {
       max_width = 2048;
       max_height = 2048;
    }
diff --git a/src/i830_exa.c b/src/i830_exa.c
index 4944e40..f11424f 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -447,13 +447,53 @@ I830EXAInit(ScreenPtr pScreen)
 	/* disable Xv here... */
     }
 
-    /* i915 3D requires 16 byte alignment (4k if tiled) */
-    pI830->EXADriverPtr->pixmapOffsetAlign = 256;
-    pI830->EXADriverPtr->pixmapPitchAlign = 64;
-
-    /* i845 and i945 2D limits rendering to 65536 lines and pitch of 32768. */
-    pI830->EXADriverPtr->maxX = 4095;
-    pI830->EXADriverPtr->maxY = 4095;
+    /* Limits are described in the BLT engine chapter under Graphics Data Size
+     * Limitations, and the descriptions of SURFACE_STATE, 3DSTATE_BUFFER_INFO,
+     * 3DSTATE_DRAWING_RECTANGLE, 3DSTATE_MAP_INFO, and 3DSTATE_MAP_INFO.
+     *
+     * i845 through i965 limits 2D rendering to 65536 lines and pitch of 32768.
+     *
+     * i965 limits 3D surface to (2*element size)-aligned offset if un-tiled.
+     * i965 limits 3D surface to 4kB-aligned offset if tiled.
+     * i965 limits 3D surfaces to w,h of ?,8192.
+     * i965 limits 3D surface to pitch of 1B - 128kB.
+     * i965 limits 3D surface pitch alignment to 512B, only if tiled.
+     * i965 limits 3D destination drawing rect to w,h of 8192,8192.
+     *
+     * i915 limits 3D textures to 4B-aligned offset if un-tiled.
+     * i915 limits 3D textures to ~4kB-aligned offset if tiled.
+     * i915 limits 3D textures to width,height of 2048,2048.
+     * i915 limits 3D textures to pitch of 16B - 8kB, in dwords.
+     * i915 limits 3D destination to ~4kB-aligned offset if tiled.
+     * i915 limits 3D destination to pitch of 16B - 8kB, in dwords, if un-tiled.
+     * i915 limits 3D destination to pitch of 512B - 8kB, in tiles, if tiled.
+     * i915 limits 3D destination to POT aligned pitch if tiled.
+     * i915 limits 3D destination drawing rect to w,h of 2048,2048.
+     *
+     * i845 limits 3D textures to 4B-aligned offset if un-tiled.
+     * i845 limits 3D textures to ~4kB-aligned offset if tiled.
+     * i845 limits 3D textures to width,height of 2048,2048.
+     * i845 limits 3D textures to pitch of 4B - 8kB, in dwords.
+     * i845 limits 3D destination to 4B-aligned offset if un-tiled.
+     * i845 limits 3D destination to ~4kB-aligned offset if tiled.
+     * i845 limits 3D destination to pitch of 8B - 8kB, in dwords.
+     * i845 limits 3D destination drawing rect to w,h of 2048,2048.
+     *
+     * For the tiled issues, the only tiled buffer we draw to should be
+     * the front, which will have an appropriate pitch/offset already set up,
+     * so EXA doesn't need to worry.
+     */
+    if (IS_I965G(pI830)) {
+	pI830->EXADriverPtr->pixmapOffsetAlign = 4 * 2;
+	pI830->EXADriverPtr->pixmapPitchAlign = 1;
+	pI830->EXADriverPtr->maxX = 8192;
+	pI830->EXADriverPtr->maxY = 8192;
+    } else {
+	pI830->EXADriverPtr->pixmapOffsetAlign = 4;
+	pI830->EXADriverPtr->pixmapPitchAlign = 16;
+	pI830->EXADriverPtr->maxX = 2048;
+	pI830->EXADriverPtr->maxY = 2048;
+    }
 
     /* Sync */
     pI830->EXADriverPtr->WaitMarker = I830EXASync;
diff-tree fa383289ac8a6dd1cb359e6f1991cc42beb6ff02 (from 5857b4a1693085b8b42dd9560a7c4f5c3c82f862)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jan 4 14:12:45 2007 -0800

    EXA: Wait for sync before we set up new state in our static state buffers.

diff --git a/src/i965_exa_render.c b/src/i965_exa_render.c
index 68293cd..dc3d7bf 100644
--- a/src/i965_exa_render.c
+++ b/src/i965_exa_render.c
@@ -404,6 +404,9 @@ I965EXAPrepareComposite(int op, PictureP
 
    binding_table_entries = 2; /* default no mask */
 
+   /* Wait for sync before we start setting up our new state */
+   i830WaitSync(pScrn);
+
    /* Set up our layout of state in framebuffer.  First the general state: */
    next_offset = 0;
    vs_offset = ALIGN(next_offset, 64);
@@ -1024,6 +1027,11 @@ I965EXAComposite(PixmapPtr pDst, int src
 		"dstX %d, dstY %d\n", srcX, srcY, srcXend, srcYend,
 		maskX, maskY, maskXend, maskYend, dstX, dstY);
 
+    /* Wait for any existing composite rectangles to land before we overwrite
+     * the VB with the next one.
+     */
+    i830WaitSync(pScrn);
+
     i = 0;
     /* rect (x2,y2) */
     vb[i++] = (float)(srcXend) / pI830->scale_units[0][0];
@@ -1088,4 +1096,9 @@ I965EXAComposite(PixmapPtr pDst, int src
    	OUT_RING(0); /* Immediate data high DW */
 	ADVANCE_LP_RING();
     }
+
+    /* Mark sync so we can wait for it before setting up the VB on the next
+     * rectangle.
+     */
+    i830MarkSync(pScrn);
 }
diff-tree 5857b4a1693085b8b42dd9560a7c4f5c3c82f862 (from ee52c0ec4e95fa6e5f35c9cd75005a0c0003fd97)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Jan 10 15:09:47 2007 +0800

    Formalize sync interface
    
    We should just call i830MarkSync/i830WaitSync in places we need,
    which care for both XAA and EXA.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 2992798..9bc74b5 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3016,10 +3016,7 @@ i830AdjustFrame(int scrnIndex, int x, in
    if (crtc && crtc->enabled)
    {
       /* Sync the engine before adjust frame */
-      if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
-	 (*pI830->AccelInfoRec->Sync)(pScrn);
-	 pI830->AccelInfoRec->NeedToSync = FALSE;
-      }
+      i830WaitSync(pScrn);
       i830PipeSetBase(crtc, output->initial_x + x, output->initial_y + y);
    }
 }
diff --git a/src/i830_randr.c b/src/i830_randr.c
index 533322b..18f84c4 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -627,14 +627,10 @@ xf86RandR12CrtcSet (ScreenPtr	pScreen,
     /* XXX need device-independent mode setting code through an API */
     if (changed)
     {
-	I830Ptr pI830 = I830PTR(pScrn);
 	crtc->enabled = mode != NULL;
 
 	/* Sync the engine before adjust mode */
-	if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
-	    (*pI830->AccelInfoRec->Sync)(pScrn);
-	    pI830->AccelInfoRec->NeedToSync = FALSE;
-	}
+        i830WaitSync(pScrn);
 
 	if (mode)
 	{
diff --git a/src/i830_rotate.c b/src/i830_rotate.c
index 029f439..efa76ed 100644
--- a/src/i830_rotate.c
+++ b/src/i830_rotate.c
@@ -805,10 +805,7 @@ I965UpdateRotate (ScreenPtr      pScreen
 	 /* Since we use the same little vertex buffer over and over, sync for
 	  * subsequent rectangles.
 	  */
-	 if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
-	    (*pI830->AccelInfoRec->Sync)(pScrn);
-	    pI830->AccelInfoRec->NeedToSync = FALSE;
-	 }
+	 i830WaitSync(pScrn);
       }
 
       pbox++;
@@ -895,12 +892,10 @@ I965UpdateRotate (ScreenPtr      pScreen
       ADVANCE_LP_RING();
 
       first_output = FALSE;
-      if (pI830->AccelInfoRec)
-	 pI830->AccelInfoRec->NeedToSync = TRUE;
+      i830MarkSync(pScrn);
    }
 
-   if (pI830->AccelInfoRec)
-      (*pI830->AccelInfoRec->Sync)(pScrn);
+   i830WaitSync(pScrn);
 #ifdef XF86DRI
    if (didLock)
       I830DRIUnlock(pScrn1);
diff --git a/src/i830_video.c b/src/i830_video.c
index 6b76faa..652e73d 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -2358,10 +2358,7 @@ I830PutImage(ScrnInfoPtr pScrn,
        * acceleration to finish before writing the new video data into
        * framebuffer.
        */
-      if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
-	 (*pI830->AccelInfoRec->Sync)(pScrn);
-	 pI830->AccelInfoRec->NeedToSync = FALSE;
-      }
+      i830WaitSync(pScrn);
    }
 
    switch (id) {
diff --git a/src/i915_video.c b/src/i915_video.c
index 52fe1a5..591b6f8 100644
--- a/src/i915_video.c
+++ b/src/i915_video.c
@@ -433,7 +433,6 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
       ADVANCE_LP_RING();
    }
 
-   if (pI830->AccelInfoRec)
-      pI830->AccelInfoRec->NeedToSync = TRUE;
+   i830MarkSync(pScrn);
 }
 
diff-tree ee52c0ec4e95fa6e5f35c9cd75005a0c0003fd97 (from da6a00f787e4d13e6b75768c1976f1c44ae5bf72)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Jan 8 16:53:07 2007 -0800

    Correct typo resulting in a crash with ivch.  = != ==.

diff --git a/src/ivch/ivch.c b/src/ivch/ivch.c
index 6c5db6c..085b542 100644
--- a/src/ivch/ivch.c
+++ b/src/ivch/ivch.c
@@ -92,7 +92,7 @@ ivch_init(I2CBusPtr b, I2CSlaveAddr addr
     xf86DrvMsg(b->scrnIndex, X_INFO, "detecting ivch\n");
 
     priv = xcalloc(1, sizeof(struct ivch_priv));
-    if (priv = NULL)
+    if (priv == NULL)
 	return NULL;
 
     priv->d.DevName = "i82807aa \"ivch\" LVDS/CMOS panel controller";
diff-tree da6a00f787e4d13e6b75768c1976f1c44ae5bf72 (from 66546d8a8006e1c828e18ccab850214fd8d56b63)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Mon Jan 8 12:36:54 2007 -0800

    Move EXA function declarations from source to header.
    
    Several new global functions were not put into the header file leading to
    potential mismatches between declaration and definition.

diff --git a/src/i830.h b/src/i830.h
index dc0d768..95bea2f 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -503,11 +503,6 @@ typedef struct _I830Rec {
 #define I830_SELECT_BACK	1
 #define I830_SELECT_DEPTH	2
 
-#ifdef I830_USE_EXA
-extern const int I830PatternROP[16];
-extern const int I830CopyROP[16];
-#endif
-
 /* I830 specific functions */
 extern int I830WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis);
 extern void I830SetPIOAccess(I830Ptr pI830);
@@ -620,6 +615,32 @@ DisplayModePtr i830_ddc_get_modes(xf86Ou
 /* i830_tv.c */
 void i830_tv_init(ScrnInfoPtr pScrn);
 
+#ifdef I830_USE_EXA
+extern Bool I830EXACheckComposite(int, PicturePtr, PicturePtr, PicturePtr);
+extern Bool I830EXAPrepareComposite(int, PicturePtr, PicturePtr, PicturePtr, 
+				PixmapPtr, PixmapPtr, PixmapPtr);
+extern Bool I915EXACheckComposite(int, PicturePtr, PicturePtr, PicturePtr);
+extern Bool I915EXAPrepareComposite(int, PicturePtr, PicturePtr, PicturePtr, 
+				PixmapPtr, PixmapPtr, PixmapPtr);
+
+extern Bool I965EXACheckComposite(int, PicturePtr, PicturePtr, PicturePtr);
+extern Bool I965EXAPrepareComposite(int, PicturePtr, PicturePtr, PicturePtr, 
+				PixmapPtr, PixmapPtr, PixmapPtr);
+extern void I965EXAComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, 
+			int maskY, int dstX, int dstY, int width, int height);
+
+extern Bool
+I830EXACheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+		      PicturePtr pDstPicture);
+
+extern Bool
+I830EXAPrepareComposite(int op, PicturePtr pSrcPicture,
+			PicturePtr pMaskPicture, PicturePtr pDstPicture,
+			PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst);
+
+extern const int I830PatternROP[16];
+extern const int I830CopyROP[16];
+#endif
 /* Flags for memory allocation function */
 #define FROM_ANYWHERE			0x00000000
 #define FROM_POOL_ONLY			0x00000001
diff --git a/src/i830_exa.c b/src/i830_exa.c
index 02ac903..4944e40 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -109,18 +109,6 @@ union intfloat {
 	OUT_RING(tmp.ui);			\
 } while(0)				
 
-extern Bool I830EXACheckComposite(int, PicturePtr, PicturePtr, PicturePtr);
-extern Bool I830EXAPrepareComposite(int, PicturePtr, PicturePtr, PicturePtr, 
-				PixmapPtr, PixmapPtr, PixmapPtr);
-extern Bool I915EXACheckComposite(int, PicturePtr, PicturePtr, PicturePtr);
-extern Bool I915EXAPrepareComposite(int, PicturePtr, PicturePtr, PicturePtr, 
-				PixmapPtr, PixmapPtr, PixmapPtr);
-
-extern Bool I965EXACheckComposite(int, PicturePtr, PicturePtr, PicturePtr);
-extern Bool I965EXAPrepareComposite(int, PicturePtr, PicturePtr, PicturePtr, 
-				PixmapPtr, PixmapPtr, PixmapPtr);
-extern void I965EXAComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, 
-			int maskY, int dstX, int dstY, int width, int height);
 /**
  * I830EXASync - wait for a command to finish
  * @pScreen: current screen
diff --git a/src/i830_exa_render.c b/src/i830_exa_render.c
index 5e202c8..ae4f95f 100644
--- a/src/i830_exa_render.c
+++ b/src/i830_exa_render.c
@@ -63,16 +63,6 @@ struct formatinfo {
     CARD32 card_fmt;
 };
 
-extern Bool
-I830EXACheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
-		      PicturePtr pDstPicture);
-
-extern Bool
-I830EXAPrepareComposite(int op, PicturePtr pSrcPicture,
-			PicturePtr pMaskPicture, PicturePtr pDstPicture,
-			PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst);
-
-
 #define TB0C_LAST_STAGE	(1 << 31)
 #define TB0C_RESULT_SCALE_1X		(0 << 29)
 #define TB0C_RESULT_SCALE_2X		(1 << 29)
diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
index 640ebd9..46533b3 100644
--- a/src/i915_exa_render.c
+++ b/src/i915_exa_render.c
@@ -64,15 +64,6 @@ struct blendinfo {
     CARD32 dst_blend;
 };
 
-extern Bool
-I915EXACheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
-		      PicturePtr pDstPicture);
-
-extern Bool
-I915EXAPrepareComposite(int op, PicturePtr pSrcPicture,
-			PicturePtr pMaskPicture, PicturePtr pDstPicture,
-			PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst);
-
 static struct blendinfo I915BlendOp[] = {
     /* Clear */
     {0, 0, BLENDFACT_ZERO,          BLENDFACT_ZERO},
diff --git a/src/i965_exa_render.c b/src/i965_exa_render.c
index 89581e9..68293cd 100644
--- a/src/i965_exa_render.c
+++ b/src/i965_exa_render.c
@@ -55,19 +55,6 @@ do { 							\
 } while(0) 
 #endif
 
-extern Bool
-I965EXACheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
-		      PicturePtr pDstPicture);
-
-extern Bool
-I965EXAPrepareComposite(int op, PicturePtr pSrcPicture,
-			PicturePtr pMaskPicture, PicturePtr pDstPicture,
-			PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst);
-
-extern void
-I965EXAComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
-		int dstX, int dstY, int width, int height);
-
 static void I965GetBlendCntl(int op, PicturePtr pMask, CARD32 dst_format, 
 			     CARD32 *sblend, CARD32 *dblend);
 
diff-tree 66546d8a8006e1c828e18ccab850214fd8d56b63 (from parents)
Merge: 0fd2752f199928f846fe03c9087f7b6d48cc28d9 40af0ee6ba4ab7596fbc7fcc3ad04d109746ca6f
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Mon Jan 8 10:14:24 2007 -0800

    Merge branch 'modesetting-origin' into modesetting

diff-tree 0fd2752f199928f846fe03c9087f7b6d48cc28d9 (from 736d82a6b43f174cb95b425faacd4b0b889916fa)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Thu Jan 4 14:35:55 2007 +0800

    minor fix on last exa mem binding commit

diff --git a/src/i830_memory.c b/src/i830_memory.c
index 3a3836c..af86688 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -2044,10 +2044,12 @@ I830UnbindAGPMemory(ScrnInfoPtr pScrn)
       }
 #endif
 #ifdef I830_USE_EXA
-     if (!UnbindMemRange(pScrn, &(pI830->Offscreen)))
-	return FALSE;
-     if (IS_I965G(pI830) && !UnbindMemRange(pScrn, &(pI830->EXAStateMem)))
-	return FALSE;
+     if (pI830->useEXA) {
+         if (!UnbindMemRange(pScrn, &(pI830->Offscreen)))
+	    return FALSE;
+         if (IS_I965G(pI830) && !UnbindMemRange(pScrn, &(pI830->EXAStateMem)))
+	    return FALSE;
+     }
 #endif
       if (!xf86ReleaseGART(pScrn->scrnIndex))
 	 return FALSE;
diff-tree 40af0ee6ba4ab7596fbc7fcc3ad04d109746ca6f (from 736d82a6b43f174cb95b425faacd4b0b889916fa)
Author: Keith Packard <keithp at mandolin.keithp.com>
Date:   Sat Jan 6 18:19:34 2007 -0800

    Numerous symbol scope issues.
    
    I830EntityIndex is shared between 810 and newer driver.
    Move most EXA rendering state into I830 structure.
    Declare shared variables in shared header files rather than .c.

diff --git a/src/brw_structs.h b/src/brw_structs.h
index d2f9be0..28d8e12 100644
--- a/src/brw_structs.h
+++ b/src/brw_structs.h
@@ -34,7 +34,7 @@ struct header 
 {
    unsigned int length:16; 
    unsigned int opcode:16; 
-} bits;
+};
 
 
 union header_union
diff --git a/src/common.h b/src/common.h
index 540983b..2035862 100644
--- a/src/common.h
+++ b/src/common.h
@@ -77,6 +77,7 @@ extern const OptionInfoRec *I830Availabl
 extern void I830InitpScrn(ScrnInfoPtr pScrn);
 
 /* Symbol lists shared by the i810 and i830 parts. */
+extern int I830EntityIndex;
 extern const char *I810vgahwSymbols[];
 extern const char *I810ramdacSymbols[];
 extern const char *I810int10Symbols[];
diff --git a/src/i810_driver.c b/src/i810_driver.c
index 7574fb5..3d4c7d3 100644
--- a/src/i810_driver.c
+++ b/src/i810_driver.c
@@ -381,7 +381,7 @@ static int i810_pitches[] = {
 #endif
 #endif
 
-static int I830EntityIndex = -1;
+int I830EntityIndex = -1;
 
 #ifdef XFree86LOADER
 
diff --git a/src/i810_wmark.c b/src/i810_wmark.c
index 85d55ef..d21f6aa 100644
--- a/src/i810_wmark.c
+++ b/src/i810_wmark.c
@@ -149,11 +149,14 @@ static struct wm_info i810_wm_24_100[] =
    {202.5, 0x44419000}
 };
 
+#if 0
+/* not used */
 static struct wm_info i810_wm_32_100[] = {
    {0, 0x2210b000},
    {60, 0x22415000},			/* 0x314000 works too */
    {80, 0x22419000}			/* 0x518000 works too */
 };
+#endif
 
 static struct wm_info i810_wm_8_133[] = {
    {0, 0x22003000},
diff --git a/src/i830.h b/src/i830.h
index f89d022..dc0d768 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -379,6 +379,14 @@ typedef struct _I830Rec {
    Bool *overlayOn;
 #endif
 
+   /* EXA render state */
+   float scale_units[2][2];
+   Bool is_transform[2];
+   PictTransform *transform[2];
+   /* i915 EXA render state */
+   CARD32 mapstate[6];
+   CARD32 samplerstate[6];
+
    Bool directRenderingDisabled;	/* DRI disabled in PreInit. */
    Bool directRenderingEnabled;		/* DRI enabled this generation. */
 
@@ -495,6 +503,11 @@ typedef struct _I830Rec {
 #define I830_SELECT_BACK	1
 #define I830_SELECT_DEPTH	2
 
+#ifdef I830_USE_EXA
+extern const int I830PatternROP[16];
+extern const int I830CopyROP[16];
+#endif
+
 /* I830 specific functions */
 extern int I830WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis);
 extern void I830SetPIOAccess(I830Ptr pI830);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index ffa391f..2992798 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -322,9 +322,6 @@ static CARD32 I830CheckDevicesTimer(OsTi
 static Bool SaveHWState(ScrnInfoPtr pScrn);
 static Bool RestoreHWState(ScrnInfoPtr pScrn);
 
-
-extern int I830EntityIndex;
-
 /* temporary */
 extern void xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y);
 
diff --git a/src/i830_edid_modes.c b/src/i830_edid_modes.c
index 31ce100..249f87a 100644
--- a/src/i830_edid_modes.c
+++ b/src/i830_edid_modes.c
@@ -106,7 +106,7 @@ static const ddc_quirk_map_t ddc_quirks[
 #define MODEPREFIX(name) NULL, NULL, name, 0,M_T_DRIVER
 #define MODESUFFIX   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,FALSE,FALSE,0,NULL,0,0.0,0.0
 
-DisplayModeRec DDCEstablishedModes[17] = {
+static DisplayModeRec DDCEstablishedModes[17] = {
     { MODEPREFIX("800x600"),    40000,  800,  840,  968, 1056, 0,  600,  601,  605,  628, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600 at 60Hz */
     { MODEPREFIX("800x600"),    36000,  800,  824,  896, 1024, 0,  600,  601,  603,  625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600 at 56Hz */
     { MODEPREFIX("640x480"),    31500,  640,  656,  720,  840, 0,  480,  481,  484,  500, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480 at 75Hz */
diff --git a/src/i830_exa.c b/src/i830_exa.c
index f23816f..02ac903 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -57,9 +57,7 @@ do { 							\
 } while(0) 
 #endif
 
-static float scale_units[2][2];
-
-const static int I830CopyROP[16] =
+const int I830CopyROP[16] =
 {
    ROP_0,               /* GXclear */
    ROP_DSa,             /* GXand */
@@ -79,7 +77,7 @@ const static int I830CopyROP[16] =
    ROP_1                /* GXset */
 };
 
-const static int I830PatternROP[16] =
+const int I830PatternROP[16] =
 {
     ROP_0,
     ROP_DPa,
@@ -111,9 +109,6 @@ union intfloat {
 	OUT_RING(tmp.ui);			\
 } while(0)				
 
-static Bool is_transform[2];
-static PictTransform *transform[2];
-
 extern Bool I830EXACheckComposite(int, PicturePtr, PicturePtr, PicturePtr);
 extern Bool I830EXAPrepareComposite(int, PicturePtr, PicturePtr, PicturePtr, 
 				PixmapPtr, PixmapPtr, PixmapPtr);
@@ -314,10 +309,10 @@ IntelEXAComposite(PixmapPtr pDst, int sr
 	    "src_scale_x %f, src_scale_y %f, "
 	    "mask_scale_x %f, mask_scale_y %f\n",
 	    srcX, srcY, maskX, maskY, dstX, dstY, w, h,
-	    scale_units[0][0], scale_units[0][1],
-	    scale_units[1][0], scale_units[1][1]);
+	    pI830->scale_units[0][0], pI830->scale_units[0][1],
+	    pI830->scale_units[1][0], pI830->scale_units[1][1]);
 
-    if (scale_units[1][0] == -1 || scale_units[1][1] == -1) {
+    if (pI830->scale_units[1][0] == -1 || pI830->scale_units[1][1] == -1) {
 	pMask = 0;
     }
 
@@ -325,31 +320,31 @@ IntelEXAComposite(PixmapPtr pDst, int sr
     srcYend = srcY + h;
     maskXend = maskX + w;
     maskYend = maskY + h;
-    if (is_transform[0]) {
+    if (pI830->is_transform[0]) {
         v.vector[0] = IntToxFixed(srcX);
         v.vector[1] = IntToxFixed(srcY);
         v.vector[2] = xFixed1;
-        PictureTransformPoint(transform[0], &v);
+        PictureTransformPoint(pI830->transform[0], &v);
         srcX = xFixedToInt(v.vector[0]);
         srcY = xFixedToInt(v.vector[1]);
         v.vector[0] = IntToxFixed(srcXend);
         v.vector[1] = IntToxFixed(srcYend);
         v.vector[2] = xFixed1;
-        PictureTransformPoint(transform[0], &v);
+        PictureTransformPoint(pI830->transform[0], &v);
         srcXend = xFixedToInt(v.vector[0]);
         srcYend = xFixedToInt(v.vector[1]);
     }
-    if (is_transform[1]) {
+    if (pI830->is_transform[1]) {
         v.vector[0] = IntToxFixed(maskX);
         v.vector[1] = IntToxFixed(maskY);
         v.vector[2] = xFixed1;
-        PictureTransformPoint(transform[1], &v);
+        PictureTransformPoint(pI830->transform[1], &v);
         maskX = xFixedToInt(v.vector[0]);
         maskY = xFixedToInt(v.vector[1]);
         v.vector[0] = IntToxFixed(maskXend);
         v.vector[1] = IntToxFixed(maskYend);
         v.vector[2] = xFixed1;
-        PictureTransformPoint(transform[1], &v);
+        PictureTransformPoint(pI830->transform[1], &v);
         maskXend = xFixedToInt(v.vector[0]);
         maskYend = xFixedToInt(v.vector[1]);
     }
@@ -378,38 +373,38 @@ IntelEXAComposite(PixmapPtr pDst, int sr
 
 	OUT_RING_F(dstX);
 	OUT_RING_F(dstY);
-	OUT_RING_F(srcX / scale_units[0][0]);
-	OUT_RING_F(srcY / scale_units[0][1]);
+	OUT_RING_F(srcX / pI830->scale_units[0][0]);
+	OUT_RING_F(srcY / pI830->scale_units[0][1]);
 	if (pMask) {
-		OUT_RING_F(maskX / scale_units[1][0]);
-		OUT_RING_F(maskY / scale_units[1][1]);
+		OUT_RING_F(maskX / pI830->scale_units[1][0]);
+		OUT_RING_F(maskY / pI830->scale_units[1][1]);
 	}
 
 	OUT_RING_F(dstX);
 	OUT_RING_F(dstY + h);
-	OUT_RING_F(srcX / scale_units[0][0]);
-	OUT_RING_F(srcYend / scale_units[0][1]);
+	OUT_RING_F(srcX / pI830->scale_units[0][0]);
+	OUT_RING_F(srcYend / pI830->scale_units[0][1]);
 	if (pMask) {
-		OUT_RING_F(maskX / scale_units[1][0]);
-		OUT_RING_F(maskYend / scale_units[1][1]);
+		OUT_RING_F(maskX / pI830->scale_units[1][0]);
+		OUT_RING_F(maskYend / pI830->scale_units[1][1]);
 	}
 
 	OUT_RING_F(dstX + w);
 	OUT_RING_F(dstY + h);
-	OUT_RING_F(srcXend / scale_units[0][0]);
-	OUT_RING_F(srcYend / scale_units[0][1]);
+	OUT_RING_F(srcXend / pI830->scale_units[0][0]);
+	OUT_RING_F(srcYend / pI830->scale_units[0][1]);
 	if (pMask) {
-		OUT_RING_F(maskXend / scale_units[1][0]);
-		OUT_RING_F(maskYend / scale_units[1][1]);
+		OUT_RING_F(maskXend / pI830->scale_units[1][0]);
+		OUT_RING_F(maskYend / pI830->scale_units[1][1]);
 	}
 
 	OUT_RING_F(dstX + w);
 	OUT_RING_F(dstY);
-	OUT_RING_F(srcXend / scale_units[0][0]);
-	OUT_RING_F(srcY / scale_units[0][1]);
+	OUT_RING_F(srcXend / pI830->scale_units[0][0]);
+	OUT_RING_F(srcY / pI830->scale_units[0][1]);
 	if (pMask) {
-		OUT_RING_F(maskXend / scale_units[1][0]);
-		OUT_RING_F(maskY / scale_units[1][1]);
+		OUT_RING_F(maskXend / pI830->scale_units[1][0]);
+		OUT_RING_F(maskY / pI830->scale_units[1][1]);
 	}
 	ADVANCE_LP_RING();
     }
diff --git a/src/i830_exa_render.c b/src/i830_exa_render.c
index f63313f..5e202c8 100644
--- a/src/i830_exa_render.c
+++ b/src/i830_exa_render.c
@@ -51,10 +51,6 @@ do { 							\
 } while(0) 
 #endif
 
-extern float scale_units[2][2];
-extern Bool is_transform[2];
-extern PictTransform *transform[2];
-
 struct blendinfo {
     Bool dst_alpha;
     Bool src_alpha;
@@ -274,8 +270,8 @@ I830TextureSetup(PicturePtr pPict, Pixma
     pitch = exaGetPixmapPitch(pPix);
     w = pPict->pDrawable->width;
     h = pPict->pDrawable->height;
-    scale_units[unit][0] = pPix->drawable.width;
-    scale_units[unit][1] = pPix->drawable.height;
+    pI830->scale_units[unit][0] = pPix->drawable.width;
+    pI830->scale_units[unit][1] = pPix->drawable.height;
 
     for (i = 0; i < sizeof(I830TexFormats) / sizeof(I830TexFormats[0]); i++) {
         if (I830TexFormats[i].fmt == pPict->format)
@@ -344,10 +340,10 @@ I830TextureSetup(PicturePtr pPict, Pixma
 
 	/* XXX */
     if (pPict->transform != 0) {
-        is_transform[unit] = TRUE;
-        transform[unit] = pPict->transform;
+        pI830->is_transform[unit] = TRUE;
+        pI830->transform[unit] = pPict->transform;
     } else {
-        is_transform[unit] = FALSE;
+        pI830->is_transform[unit] = FALSE;
     }
 
 #ifdef I830DEBUG
@@ -412,9 +408,9 @@ I830EXAPrepareComposite(int op, PictureP
 	if (!I830TextureSetup(pMaskPicture, pMask, 1))
 		I830FALLBACK("fail to setup mask texture\n");
     } else {
-	is_transform[1] = FALSE;
-	scale_units[1][0] = -1;
-	scale_units[1][1] = -1;
+	pI830->is_transform[1] = FALSE;
+	pI830->scale_units[1][0] = -1;
+	pI830->scale_units[1][1] = -1;
     }
 
     {
diff --git a/src/i830_xaa.c b/src/i830_xaa.c
index cad9c71..13ba743 100644
--- a/src/i830_xaa.c
+++ b/src/i830_xaa.c
@@ -91,11 +91,6 @@ static void I830SubsequentImageWriteScan
 #endif
 static void I830RestoreAccelState(ScrnInfoPtr pScrn);
 
-#ifdef I830_USE_EXA
-extern const int I830PatternROP[16];
-extern const int I830CopyROP[16];
-#endif
-
 Bool
 I830XAAInit(ScreenPtr pScreen)
 {
diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
index cefa15c..640ebd9 100644
--- a/src/i915_exa_render.c
+++ b/src/i915_exa_render.c
@@ -52,12 +52,6 @@ do { 							\
 } while(0)
 #endif
 
-extern float scale_units[2][2];
-extern Bool is_transform[2];
-extern PictTransform *transform[2];
-static CARD32 mapstate[6];
-static CARD32 samplerstate[6];
-
 struct formatinfo {
     int fmt;
     CARD32 card_fmt;
@@ -267,8 +261,8 @@ I915TextureSetup(PicturePtr pPict, Pixma
     pitch = exaGetPixmapPitch(pPix);
     w = pPict->pDrawable->width;
     h = pPict->pDrawable->height;
-    scale_units[unit][0] = pPix->drawable.width;
-    scale_units[unit][1] = pPix->drawable.height;
+    pI830->scale_units[unit][0] = pPix->drawable.width;
+    pI830->scale_units[unit][1] = pPix->drawable.height;
 
     for (i = 0; i < sizeof(I915TexFormats) / sizeof(I915TexFormats[0]); i++) {
         if (I915TexFormats[i].fmt == pPict->format)
@@ -295,27 +289,27 @@ I915TextureSetup(PicturePtr pPict, Pixma
         I830FALLBACK("Bad filter 0x%x\n", pPict->filter);
     }
 
-    mapstate[unit * 3 + 0] = offset;
-    mapstate[unit * 3 + 1] = format |
+    pI830->mapstate[unit * 3 + 0] = offset;
+    pI830->mapstate[unit * 3 + 1] = format |
 	((pPix->drawable.height - 1) << MS3_HEIGHT_SHIFT) |
 	((pPix->drawable.width - 1) << MS3_WIDTH_SHIFT);
     if (!pI830->disableTiling)
-	samplerstate[unit * 3 + 1] |= MS3_USE_FENCE_REGS;
-    mapstate[unit * 3 + 2] = ((pitch / 4) - 1) << MS4_PITCH_SHIFT;
+	pI830->samplerstate[unit * 3 + 1] |= MS3_USE_FENCE_REGS;
+    pI830->mapstate[unit * 3 + 2] = ((pitch / 4) - 1) << MS4_PITCH_SHIFT;
 
-    samplerstate[unit * 3 + 0] = (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT);
-    samplerstate[unit * 3 + 0] |= filter;
-    samplerstate[unit * 3 + 1] = SS3_NORMALIZED_COORDS;
-    samplerstate[unit * 3 + 1] |= wrap_mode << SS3_TCX_ADDR_MODE_SHIFT;
-    samplerstate[unit * 3 + 1] |= wrap_mode << SS3_TCY_ADDR_MODE_SHIFT;
-    samplerstate[unit * 3 + 1] |= unit << SS3_TEXTUREMAP_INDEX_SHIFT;
-    samplerstate[unit * 3 + 2] = 0x00000000; /* border color */
+    pI830->samplerstate[unit * 3 + 0] = (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT);
+    pI830->samplerstate[unit * 3 + 0] |= filter;
+    pI830->samplerstate[unit * 3 + 1] = SS3_NORMALIZED_COORDS;
+    pI830->samplerstate[unit * 3 + 1] |= wrap_mode << SS3_TCX_ADDR_MODE_SHIFT;
+    pI830->samplerstate[unit * 3 + 1] |= wrap_mode << SS3_TCY_ADDR_MODE_SHIFT;
+    pI830->samplerstate[unit * 3 + 1] |= unit << SS3_TEXTUREMAP_INDEX_SHIFT;
+    pI830->samplerstate[unit * 3 + 2] = 0x00000000; /* border color */
 
     if (pPict->transform != 0) {
-        is_transform[unit] = TRUE;
-        transform[unit] = pPict->transform;
+        pI830->is_transform[unit] = TRUE;
+        pI830->transform[unit] = pPict->transform;
     } else {
-        is_transform[unit] = FALSE;
+        pI830->is_transform[unit] = FALSE;
     }
 
     return TRUE;
@@ -348,44 +342,44 @@ I915EXAPrepareComposite(int op, PictureP
 	if (!I915TextureSetup(pMaskPicture, pMask, 1))
 		I830FALLBACK("fail to setup mask texture\n");
     } else {
-	is_transform[1] = FALSE;
-	scale_units[1][0] = -1;
-	scale_units[1][1] = -1;
+	pI830->is_transform[1] = FALSE;
+	pI830->scale_units[1][0] = -1;
+	pI830->scale_units[1][1] = -1;
     }
 
     if (pMask == NULL) {
 	BEGIN_LP_RING(10);
 	OUT_RING(_3DSTATE_MAP_STATE | 3);
 	OUT_RING(0x00000001); /* map 0 */
-	OUT_RING(mapstate[0]);
-	OUT_RING(mapstate[1]);
-	OUT_RING(mapstate[2]);
+	OUT_RING(pI830->mapstate[0]);
+	OUT_RING(pI830->mapstate[1]);
+	OUT_RING(pI830->mapstate[2]);
 
 	OUT_RING(_3DSTATE_SAMPLER_STATE | 3);
 	OUT_RING(0x00000001); /* sampler 0 */
-	OUT_RING(samplerstate[0]);
-	OUT_RING(samplerstate[1]);
-	OUT_RING(samplerstate[2]);
+	OUT_RING(pI830->samplerstate[0]);
+	OUT_RING(pI830->samplerstate[1]);
+	OUT_RING(pI830->samplerstate[2]);
 	ADVANCE_LP_RING();
     } else {
 	BEGIN_LP_RING(16);
 	OUT_RING(_3DSTATE_MAP_STATE | 6);
 	OUT_RING(0x00000003); /* map 0,1 */
-	OUT_RING(mapstate[0]);
-	OUT_RING(mapstate[1]);
-	OUT_RING(mapstate[2]);
-	OUT_RING(mapstate[3]);
-	OUT_RING(mapstate[4]);
-	OUT_RING(mapstate[5]);
+	OUT_RING(pI830->mapstate[0]);
+	OUT_RING(pI830->mapstate[1]);
+	OUT_RING(pI830->mapstate[2]);
+	OUT_RING(pI830->mapstate[3]);
+	OUT_RING(pI830->mapstate[4]);
+	OUT_RING(pI830->mapstate[5]);
 
 	OUT_RING(_3DSTATE_SAMPLER_STATE | 6);
 	OUT_RING(0x00000003); /* sampler 0,1 */
-	OUT_RING(samplerstate[0]);
-	OUT_RING(samplerstate[1]);
-	OUT_RING(samplerstate[2]);
-	OUT_RING(samplerstate[3]);
-	OUT_RING(samplerstate[4]);
-	OUT_RING(samplerstate[5]);
+	OUT_RING(pI830->samplerstate[0]);
+	OUT_RING(pI830->samplerstate[1]);
+	OUT_RING(pI830->samplerstate[2]);
+	OUT_RING(pI830->samplerstate[3]);
+	OUT_RING(pI830->samplerstate[4]);
+	OUT_RING(pI830->samplerstate[5]);
 	ADVANCE_LP_RING();
     }
     {
diff --git a/src/i965_exa_render.c b/src/i965_exa_render.c
index 583bc26..89581e9 100644
--- a/src/i965_exa_render.c
+++ b/src/i965_exa_render.c
@@ -71,10 +71,6 @@ I965EXAComposite(PixmapPtr pDst, int src
 static void I965GetBlendCntl(int op, PicturePtr pMask, CARD32 dst_format, 
 			     CARD32 *sblend, CARD32 *dblend);
 
-extern float scale_units[2][2];
-extern Bool is_transform[2];
-extern PictTransform *transform[2];
-
 struct blendinfo {
     Bool dst_alpha;
     Bool src_alpha;
@@ -267,46 +263,46 @@ I965EXACheckComposite(int op, PicturePtr
 #define MIN(a,b) ((a) < (b) ? (a) : (b))
 #define BRW_GRF_BLOCKS(nreg)    ((nreg + 15) / 16 - 1)
 
-int urb_vs_start, urb_vs_size;
-int urb_gs_start, urb_gs_size;
-int urb_clip_start, urb_clip_size;
-int urb_sf_start, urb_sf_size;
-int urb_cs_start, urb_cs_size;
-
-struct brw_surface_state *dest_surf_state;
-struct brw_surface_state *src_surf_state;
-struct brw_surface_state *mask_surf_state;
-struct brw_sampler_state *src_sampler_state;
-struct brw_sampler_state *mask_sampler_state;  
-struct brw_sampler_default_color *default_color_state;
-
-struct brw_vs_unit_state *vs_state;
-struct brw_sf_unit_state *sf_state;
-struct brw_wm_unit_state *wm_state;
-struct brw_cc_unit_state *cc_state;
-struct brw_cc_viewport *cc_viewport;
-
-struct brw_instruction *sf_kernel;
-struct brw_instruction *ps_kernel;
-struct brw_instruction *sip_kernel;
-
-CARD32 *binding_table;
-int binding_table_entries; 
-
-int dest_surf_offset, src_surf_offset, mask_surf_offset;
-int src_sampler_offset, mask_sampler_offset,vs_offset;
-int sf_offset, wm_offset, cc_offset, vb_offset, cc_viewport_offset;
-int sf_kernel_offset, ps_kernel_offset, sip_kernel_offset;
-int wm_scratch_offset;
-int binding_table_offset;
-int default_color_offset; 
-int next_offset, total_state_size;
-char *state_base;
-int state_base_offset;
-float *vb;
-int vb_size = (4 * 4) * 4 ; /* 4 DWORDS per vertex*/ 
+static int urb_vs_start, urb_vs_size;
+static int urb_gs_start, urb_gs_size;
+static int urb_clip_start, urb_clip_size;
+static int urb_sf_start, urb_sf_size;
+static int urb_cs_start, urb_cs_size;
+
+static struct brw_surface_state *dest_surf_state;
+static struct brw_surface_state *src_surf_state;
+static struct brw_surface_state *mask_surf_state;
+static struct brw_sampler_state *src_sampler_state;
+static struct brw_sampler_state *mask_sampler_state;  
+static struct brw_sampler_default_color *default_color_state;
+
+static struct brw_vs_unit_state *vs_state;
+static struct brw_sf_unit_state *sf_state;
+static struct brw_wm_unit_state *wm_state;
+static struct brw_cc_unit_state *cc_state;
+static struct brw_cc_viewport *cc_viewport;
+
+static struct brw_instruction *sf_kernel;
+static struct brw_instruction *ps_kernel;
+static struct brw_instruction *sip_kernel;
+
+static CARD32 *binding_table;
+static int binding_table_entries; 
+
+static int dest_surf_offset, src_surf_offset, mask_surf_offset;
+static int src_sampler_offset, mask_sampler_offset,vs_offset;
+static int sf_offset, wm_offset, cc_offset, vb_offset, cc_viewport_offset;
+static int sf_kernel_offset, ps_kernel_offset, sip_kernel_offset;
+static int wm_scratch_offset;
+static int binding_table_offset;
+static int default_color_offset; 
+static int next_offset, total_state_size;
+static char *state_base;
+static int state_base_offset;
+static float *vb;
+static int vb_size = (4 * 4) * 4 ; /* 4 DWORDS per vertex*/ 
 
-CARD32 src_blend, dst_blend;
+static CARD32 src_blend, dst_blend;
 
 static const CARD32 sip_kernel_static[][4] = {
 /*    wait (1) a0<1>UW a145<0,1,0>UW { align1 +  } */
@@ -394,27 +390,27 @@ I965EXAPrepareComposite(int op, PictureP
 	mask_offset = exaGetPixmapOffset(pMask);
 	mask_pitch = exaGetPixmapPitch(pMask);
     }
-    scale_units[0][0] = pSrc->drawable.width;
-    scale_units[0][1] = pSrc->drawable.height;
+    pI830->scale_units[0][0] = pSrc->drawable.width;
+    pI830->scale_units[0][1] = pSrc->drawable.height;
 
     if (pSrcPicture->transform) {
-	is_transform[0] = TRUE;
-	transform[0] = pSrcPicture->transform;
+	pI830->is_transform[0] = TRUE;
+	pI830->transform[0] = pSrcPicture->transform;
     } else 
-	is_transform[0] = FALSE;
+	pI830->is_transform[0] = FALSE;
 
     if (!pMask) {
-	is_transform[1] = FALSE;
-	scale_units[1][0] = -1;
-	scale_units[1][1] = -1;
+	pI830->is_transform[1] = FALSE;
+	pI830->scale_units[1][0] = -1;
+	pI830->scale_units[1][1] = -1;
     } else {
 	if (pMaskPicture->transform) {
-	    is_transform[1] = TRUE;
-	    transform[1] = pMaskPicture->transform;
+	    pI830->is_transform[1] = TRUE;
+	    pI830->transform[1] = pMaskPicture->transform;
 	} else
-	    is_transform[1] = FALSE;
-	scale_units[1][0] = pMask->drawable.width;
-	scale_units[1][1] = pMask->drawable.height;
+	    pI830->is_transform[1] = FALSE;
+	pI830->scale_units[1][0] = pMask->drawable.width;
+	pI830->scale_units[1][1] = pMask->drawable.height;
     }
 
 	/* setup 3d pipeline state */
@@ -996,10 +992,10 @@ I965EXAComposite(PixmapPtr pDst, int src
 	    "src_scale_x %f, src_scale_y %f, "
 	    "mask_scale_x %f, mask_scale_y %f\n",
 	    srcX, srcY, maskX, maskY, dstX, dstY, w, h,
-	    scale_units[0][0], scale_units[0][1],
-	    scale_units[1][0], scale_units[1][1]);
+	    pI830->scale_units[0][0], pI830->scale_units[0][1],
+	    pI830->scale_units[1][0], pI830->scale_units[1][1]);
 
-    if (scale_units[1][0] == -1 || scale_units[1][1] == -1) {
+    if (pI830->scale_units[1][0] == -1 || pI830->scale_units[1][1] == -1) {
 	pMask = 0;
     }
 
@@ -1007,31 +1003,31 @@ I965EXAComposite(PixmapPtr pDst, int src
     srcYend = srcY + h;
     maskXend = maskX + w;
     maskYend = maskY + h;
-    if (is_transform[0]) {
+    if (pI830->is_transform[0]) {
         v.vector[0] = IntToxFixed(srcX);
         v.vector[1] = IntToxFixed(srcY);
         v.vector[2] = xFixed1;
-        PictureTransformPoint(transform[0], &v);
+        PictureTransformPoint(pI830->transform[0], &v);
         srcX = xFixedToInt(v.vector[0]);
         srcY = xFixedToInt(v.vector[1]);
         v.vector[0] = IntToxFixed(srcXend);
         v.vector[1] = IntToxFixed(srcYend);
         v.vector[2] = xFixed1;
-        PictureTransformPoint(transform[0], &v);
+        PictureTransformPoint(pI830->transform[0], &v);
         srcXend = xFixedToInt(v.vector[0]);
         srcYend = xFixedToInt(v.vector[1]);
     }
-    if (is_transform[1]) {
+    if (pI830->is_transform[1]) {
         v.vector[0] = IntToxFixed(maskX);
         v.vector[1] = IntToxFixed(maskY);
         v.vector[2] = xFixed1;
-        PictureTransformPoint(transform[1], &v);
+        PictureTransformPoint(pI830->transform[1], &v);
         maskX = xFixedToInt(v.vector[0]);
         maskY = xFixedToInt(v.vector[1]);
         v.vector[0] = IntToxFixed(maskXend);
         v.vector[1] = IntToxFixed(maskYend);
         v.vector[2] = xFixed1;
-        PictureTransformPoint(transform[1], &v);
+        PictureTransformPoint(pI830->transform[1], &v);
         maskXend = xFixedToInt(v.vector[0]);
         maskYend = xFixedToInt(v.vector[1]);
     }
@@ -1043,31 +1039,31 @@ I965EXAComposite(PixmapPtr pDst, int src
 
     i = 0;
     /* rect (x2,y2) */
-    vb[i++] = (float)(srcXend) / scale_units[0][0];
-    vb[i++] = (float)(srcYend) / scale_units[0][1];
+    vb[i++] = (float)(srcXend) / pI830->scale_units[0][0];
+    vb[i++] = (float)(srcYend) / pI830->scale_units[0][1];
     if (pMask) {
-        vb[i++] = (float)maskXend / scale_units[1][0];
-        vb[i++] = (float)maskYend / scale_units[1][1];
+        vb[i++] = (float)maskXend / pI830->scale_units[1][0];
+        vb[i++] = (float)maskYend / pI830->scale_units[1][1];
     }
     vb[i++] = (float)(dstX + w);
     vb[i++] = (float)(dstY + h);
 
     /* rect (x1,y2) */
-    vb[i++] = (float)(srcX)/ scale_units[0][0];
-    vb[i++] = (float)(srcYend)/ scale_units[0][1];
+    vb[i++] = (float)(srcX)/ pI830->scale_units[0][0];
+    vb[i++] = (float)(srcYend)/ pI830->scale_units[0][1];
     if (pMask) {
-        vb[i++] = (float)maskX / scale_units[1][0];
-        vb[i++] = (float)maskYend / scale_units[1][1];
+        vb[i++] = (float)maskX / pI830->scale_units[1][0];
+        vb[i++] = (float)maskYend / pI830->scale_units[1][1];
     }
     vb[i++] = (float)dstX;
     vb[i++] = (float)(dstY + h);
 
     /* rect (x1,y1) */
-    vb[i++] = (float)(srcX) / scale_units[0][0];
-    vb[i++] = (float)(srcY) / scale_units[0][1];
+    vb[i++] = (float)(srcX) / pI830->scale_units[0][0];
+    vb[i++] = (float)(srcY) / pI830->scale_units[0][1];
     if (pMask) {
-        vb[i++] = (float)maskX / scale_units[1][0];
-        vb[i++] = (float)maskY / scale_units[1][1];
+        vb[i++] = (float)maskX / pI830->scale_units[1][0];
+        vb[i++] = (float)maskY / pI830->scale_units[1][1];
     }
     vb[i++] = (float)dstX;
     vb[i++] = (float)dstY;
diff-tree 736d82a6b43f174cb95b425faacd4b0b889916fa (from parents)
Merge: 53b42f5bc7a58d02106436486e5bb56e56dbbfa1 4c790f614ecba1f6468e51779cfaf0e36b6b17ad
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Mon Dec 4 15:48:04 2006 +0800

    Merge branch 'modesetting-origin' into modesetting

diff-tree 53b42f5bc7a58d02106436486e5bb56e56dbbfa1 (from 71946bcdc3c68c220996afac944698eea1974a36)
Author: Zou Nan hai <nanhai.zou at intel.com>
Date:   Sat Jan 6 14:59:14 2007 -0800

    support NTSC 480i M-J, PAL 576i for 640x480-1280x1024 sizes
    
    I still have problem with non-interlace mode and Hi Res mode.
    also I don't know how to pickup those mode in xorg.conf

diff --git a/src/i830_tv.c b/src/i830_tv.c
index 5cf36a5..4a79d2e 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -250,6 +250,53 @@ const tv_mode_t tv_modes[] = {
 	    .ru =-0.0957, .gu =-0.1879, .bu = 0.2836, .au = 1.0000,
 	    .rv = 0.3992, .gv =-0.3343, .bv =-0.0649, .av = 1.0000,
 	},
+    },
+    {
+	/* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */
+	.name	    = "PAL 576i",
+	.oversample	= TV_OVERSAMPLE_8X,
+
+	.hsync_end	= 64,		    .hblank_end		= 128,
+	.hblank_start	= 844,		    .htotal		= 863,
+	
+	.progressive	= FALSE,
+	
+	.vsync_start_f1	= 6,		    .vsync_start_f2	= 7,
+	.vsync_len	= 6,
+	
+	.veq_ena	= TRUE,		    .veq_start_f1    	= 0,
+	.veq_start_f2	= 1,		    .veq_len		= 18,
+
+	.vi_end_f1	= 24,		    .vi_end_f2		= 25,
+	.nbr_end	= 286,
+
+	.burst_ena	= TRUE,
+	.hburst_start	= 73,		    .hburst_len		= 34,
+	.vburst_start_f1 = 8,		    .vburst_end_f1	= 285,
+	.vburst_start_f2 = 8,		    .vburst_end_f2	= 286,
+	.vburst_start_f3 = 9,		    .vburst_end_f3	= 286, 
+	.vburst_start_f4 = 9,		    .vburst_end_f4	= 285,
+
+	/* desired 4.4336180 actual 4.4336180 clock 107.52 */
+	.dda1_inc	=    168,
+	.dda2_inc	=  18557,	.dda2_size	=  20625,
+	.dda3_inc	=      0,	.dda3_size	=      0,
+	.sc_reset   = TV_SC_RESET_EVERY_8,
+	.pal_burst  = TRUE,
+	
+	.composite_levels = { .blank = 237, .black = 237, .burst = 118 },
+	.composite_color = {
+	    .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.5379,
+	    .ru =-0.0793, .gu =-0.1557, .bu = 0.2350, .au = 1.0000,
+	    .rv = 0.3307, .gv =-0.2769, .bv =-0.0538, .av = 1.0000,
+	},
+
+	.svideo_levels    = { .blank = 280, .black = 280, .burst = 139 },
+	.svideo_color = {
+	    .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.6357,
+	    .ru =-0.0937, .gu =-0.1840, .bu = 0.2777, .au = 1.0000,
+	    .rv = 0.3908, .gv =-0.3273, .bv =-0.0636, .av = 1.0000,
+	},
     }
 #if 0
     {
@@ -802,22 +849,122 @@ i830_tv_mode_set(xf86OutputPtr output, D
 }
 
 static const DisplayModeRec reported_modes[] = {
-    {
-	.name = "NTSC 480i",
-	.Clock = TV_PLL_CLOCK,
-	
-	.HDisplay   = 1024,
-	.HSyncStart = 1048,
-	.HSyncEnd   = 1184,
-	.HTotal     = 1344,
-
-	.VDisplay   = 768,
-	.VSyncStart = 771,
-	.VSyncEnd   = 777,
-	.VTotal     = 806,
+	{
+		.name = "NTSC 480i",
+		.Clock = TV_PLL_CLOCK,
+		.HDisplay   = 1280,
+		.HSyncStart = 1368,
+		.HSyncEnd   = 1496,
+		.HTotal     = 1712,
+
+		.VDisplay   = 1024,
+		.VSyncStart = 1027,
+		.VSyncEnd   = 1034,
+		.VTotal     = 1104,
+		.type       = M_T_DRIVER
+	},
+	{
+		.name = "NTSC 480i",
+		.Clock = TV_PLL_CLOCK,
+		.HDisplay   = 1024,
+		.HSyncStart = 1080,
+		.HSyncEnd   = 1184,
+		.HTotal     = 1344,
+
+		.VDisplay   = 768,
+		.VSyncStart = 771,
+		.VSyncEnd   = 777,
+		.VTotal     = 806,
+		.type       = M_T_DRIVER
+	},
+	{
+		.name = "NTSC 480i",
+		.Clock = TV_PLL_CLOCK,
+		.HDisplay   = 800,
+		.HSyncStart = 832,
+		.HSyncEnd   = 912,
+		.HTotal     = 1024,
+
+		.VDisplay   = 600,
+		.VSyncStart = 603,
+		.VSyncEnd   = 607,
+		.VTotal     = 650,
+		.type       = M_T_DRIVER
+	},
+	{
+		.name = "NTSC 480i",
+		.Clock = TV_PLL_CLOCK,
+		.HDisplay   = 640,
+		.HSyncStart = 664,
+		.HSyncEnd   = 720,
+		.HTotal     = 800,
+
+		.VDisplay   = 480,
+		.VSyncStart = 483,
+		.VSyncEnd   = 487,
+		.VTotal     = 552,
+		.type       = M_T_DRIVER
+	},
+	{
+		.name = "PAL 576i",
+		.Clock = TV_PLL_CLOCK,
+		.HDisplay   = 1280,
+		.HSyncStart = 1352,
+		.HSyncEnd   = 1480,
+		.HTotal     = 1680,
+
+		.VDisplay   = 1024,
+		.VSyncStart = 1027,
+		.VSyncEnd   = 1034,
+		.VTotal     = 1092,
 
-	.type       = M_T_DRIVER
-    }
+		.type       = M_T_DRIVER
+	},
+	{
+		.name = "PAL 576i",
+		.Clock = TV_PLL_CLOCK,
+		.HDisplay   = 1024,
+		.HSyncStart = 1072,
+		.HSyncEnd   = 1168,
+		.HTotal     = 1312,
+		.VDisplay   = 768,
+		.VSyncStart = 771,
+		.VSyncEnd   = 775,
+		.VTotal     = 820,
+		.VRefresh   = 50.0f,
+
+		.type       = M_T_DRIVER
+	},
+	{
+		.name = "PAL 576i",
+		.Clock = TV_PLL_CLOCK,
+		.HDisplay   = 800,
+		.HSyncStart = 832,
+		.HSyncEnd   = 904,
+		.HTotal     = 1008,
+		.VDisplay   = 600,
+		.VSyncStart = 603,
+		.VSyncEnd   = 607,
+		.VTotal     = 642,
+		.VRefresh   = 50.0f,
+
+		.type       = M_T_DRIVER
+	},
+	{
+		.name = "PAL 576i",
+		.Clock = TV_PLL_CLOCK,
+		.HDisplay   = 640,
+		.HSyncStart = 664,
+		.HSyncEnd   = 720,
+		.HTotal     = 800,
+
+		.VDisplay   = 480,
+		.VSyncStart = 483,
+		.VSyncEnd   = 487,
+		.VTotal     = 516,
+		.VRefresh   = 50.0f,
+		.type       = M_T_DRIVER
+	},
 };
 
 /**
diff-tree 71946bcdc3c68c220996afac944698eea1974a36 (from 35cebed70827999812f8343ac97ad0dffda20786)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Jan 3 22:37:32 2007 -0800

    [PATCH] Add rotation support for 965.

diff --git a/src/i830.h b/src/i830.h
index 3b7301e..f89d022 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -288,6 +288,7 @@ typedef struct _I830Rec {
    XF86ModReqInfo shadowReq; /* to test for later libshadow */
    I830MemRange RotatedMem;
    I830MemRange RotatedMem2;
+   I830MemRange RotateStateMem; /* for G965 state buffer */
    Rotation rotation;
    int InitialRotation;
    int displayWidth;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 6b76d12..ffa391f 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2534,6 +2534,10 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       /* Rotated2 Buffer */
       memset(&(pI830->RotatedMem2), 0, sizeof(pI830->RotatedMem2));
       pI830->RotatedMem2.Key = -1;
+      if (IS_I965G(pI830)) {
+          memset(&(pI830->RotateStateMem), 0, sizeof(pI830->RotateStateMem));
+          pI830->RotateStateMem.Key = -1;
+      }
    }
 
 #ifdef HAS_MTRR_SUPPORT
@@ -2902,11 +2906,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       shadowSetup(pScreen);
       /* support all rotations */
       xf86RandR12Init (pScreen);
-      if (IS_I965G(pI830)) {
-	 xf86RandR12SetRotations (pScreen, RR_Rotate_0); /* only 0 degrees for I965G */
-      } else {
-	 xf86RandR12SetRotations (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;
       pI830->CreateScreenResources = pScreen->CreateScreenResources;
@@ -3249,8 +3249,7 @@ I830SwitchMode(int scrnIndex, DisplayMod
     * The extra WindowTable check detects a rotation at startup.
     */
    if ( (!WindowTable[pScrn->scrnIndex] || pspix->devPrivate.ptr == NULL) &&
-         !pI830->DGAactive && (pScrn->PointerMoved == I830PointerMoved) &&
-	 !IS_I965G(pI830)) {
+         !pI830->DGAactive && (pScrn->PointerMoved == I830PointerMoved)) {
       if (!I830Rotate(pScrn, mode))
          ret = FALSE;
    }
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 60257b9..3a3836c 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -531,6 +531,28 @@ I830AllocateRotatedBuffer(ScrnInfoPtr pS
    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
 		  "%sAllocated %ld kB for the rotated buffer at 0x%lx.\n", s,
 		  alloced / 1024, pI830->RotatedMem.Start);
+
+#define BRW_LINEAR_EXTRA (32*1024)
+   if (IS_I965G(pI830)) {
+       memset(&(pI830->RotateStateMem), 0, sizeof(I830MemRange));
+       pI830->RotateStateMem.Key = -1;
+       size = ROUND_TO_PAGE(BRW_LINEAR_EXTRA);
+       align = GTT_PAGE_SIZE;
+       alloced = I830AllocVidMem(pScrn, &(pI830->RotateStateMem),
+				&(pI830->StolenPool), size, align,
+				flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
+       if (alloced < size) {
+          if (!dryrun) {
+	     xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		    "G965: Failed to allocate rotate state buffer space.\n");
+          }
+          return FALSE;
+       }
+       xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		  "%sAllocated %ld kB for the G965 rotate state buffer at 0x%lx - 0x%lx.\n", s, 
+		alloced / 1024, pI830->RotateStateMem.Start, pI830->RotateStateMem.End);
+   }
+  
    return TRUE;
 }
 
@@ -1743,8 +1765,13 @@ I830SetupMemoryTiling(ScrnInfoPtr pScrn)
    int i;
 
    /* Clear out */
-   for (i = 0; i < 8; i++)
-      pI830->ModeReg.Fence[i] = 0;
+   if (IS_I965G(pI830)) {
+      for (i = 0; i < FENCE_NEW_NR*2; i++)
+	 pI830->ModeReg.Fence[i] = 0;
+   } else {
+      for (i = 0; i < 8; i++)
+         pI830->ModeReg.Fence[i] = 0;
+   }
 
    nextTile = 0;
    tileGeneration = -1;
@@ -1814,6 +1841,9 @@ I830SetupMemoryTiling(ScrnInfoPtr pScrn)
       }
    }
 	
+/* XXX tiled rotate mem not ready on G965*/
+ 
+  if(!IS_I965G(pI830)) {
    if (pI830->RotatedMem.Alignment >= KB(512)) {
       if (MakeTiles(pScrn, &(pI830->RotatedMem), FENCE_XMAJOR)) {
 	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
@@ -1824,7 +1854,7 @@ I830SetupMemoryTiling(ScrnInfoPtr pScrn)
 		    "MakeTiles failed for the rotated buffer.\n");
       }
    }
-
+  }
 #if 0
    if (pI830->RotatedMem2.Alignment >= KB(512)) {
       if (MakeTiles(pScrn, &(pI830->RotatedMem2), FENCE_XMAJOR)) {
diff --git a/src/i830_rotate.c b/src/i830_rotate.c
index 9fa3290..b2587b2 100644
--- a/src/i830_rotate.c
+++ b/src/i830_rotate.c
@@ -60,6 +60,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "i830.h"
 #include "i915_reg.h"
 #include "i915_3d.h"
+#include "brw_defines.h"
+#include "brw_structs.h"
 
 #ifdef XF86DRI
 #include "dri.h"
@@ -194,6 +196,718 @@ static void draw_poly(CARD32 *vb,
    }
 }
 
+
+/* Our PS kernel uses less than 32 GRF registers (about 20) */
+#define PS_KERNEL_NUM_GRF   32
+#define PS_MAX_THREADS	   32
+
+#define BRW_GRF_BLOCKS(nreg)	((nreg + 15) / 16 - 1)
+
+static const CARD32 ps_kernel_static0[][4] = {
+#include "rotation_wm_prog0.h"
+};
+
+static const CARD32 ps_kernel_static90[][4] = {
+#include "rotation_wm_prog90.h"
+};
+
+#define ALIGN(i,m)    (((i) + (m) - 1) & ~((m) - 1))
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define BRW_LINEAR_EXTRA (32*1024)
+#define WM_BINDING_TABLE_ENTRIES    2
+
+static const CARD32 sip_kernel_static[][4] = {
+/*    wait (1) a0<1>UW a145<0,1,0>UW { align1 +  } */
+    { 0x00000030, 0x20000108, 0x00001220, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+};
+  
+#define SF_KERNEL_NUM_GRF  16
+#define SF_MAX_THREADS	   1
+
+static const CARD32 sf_kernel_static0[][4] = {
+#include "rotation_sf_prog0.h"
+};
+
+
+static const CARD32 sf_kernel_static90[][4] = {
+#include "rotation_sf_prog90.h"
+};
+
+static void
+I965UpdateRotate (ScreenPtr      pScreen,
+                 shadowBufPtr   pBuf)
+{
+   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+   I830Ptr pI830 = I830PTR(pScrn);
+   ScrnInfoPtr pScrn1 = pScrn;
+   I830Ptr pI8301 = NULL;
+   RegionPtr	damage = shadowDamage(pBuf);
+   int		nbox = REGION_NUM_RECTS (damage);
+   BoxPtr	pbox = REGION_RECTS (damage);
+   int		box_x1, box_x2, box_y1, box_y2;
+   float verts[4][2];
+   struct matrix23 rotMatrix;
+   Bool updateInvarient = FALSE;
+#ifdef XF86DRI
+   drmI830Sarea *sarea = NULL;
+   drm_context_t myContext = 0;
+#endif
+   Bool didLock = FALSE;
+
+/* Gen4 states */
+   int urb_vs_start, urb_vs_size;
+   int urb_gs_start, urb_gs_size;
+   int urb_clip_start, urb_clip_size;
+   int urb_sf_start, urb_sf_size;
+   int urb_cs_start, urb_cs_size;
+   struct brw_surface_state *dest_surf_state;
+   struct brw_surface_state *src_surf_state;
+   struct brw_sampler_state *src_sampler_state;
+   struct brw_vs_unit_state *vs_state;
+   struct brw_sf_unit_state *sf_state;
+   struct brw_wm_unit_state *wm_state;
+   struct brw_cc_unit_state *cc_state;
+   struct brw_cc_viewport *cc_viewport;
+   struct brw_instruction *sf_kernel;
+   struct brw_instruction *ps_kernel;
+   struct brw_instruction *sip_kernel;
+   float *vb;  
+   BOOL first_output = TRUE;
+   CARD32 *binding_table;
+   int dest_surf_offset, src_surf_offset, src_sampler_offset, vs_offset;
+   int sf_offset, wm_offset, cc_offset, vb_offset, cc_viewport_offset;
+   int wm_scratch_offset;
+   int sf_kernel_offset, ps_kernel_offset, sip_kernel_offset;
+   int binding_table_offset;
+   int next_offset, total_state_size;
+   int vb_size = (4 * 4) * 4; /* 4 DWORDS per vertex */
+   char *state_base;
+   int state_base_offset;
+
+   DPRINTF(PFX, "I965UpdateRotate: from (%d x %d) -> (%d x %d)\n",	
+		pScrn->virtualX, pScrn->virtualY, pScreen->width, pScreen->height);
+
+   if (I830IsPrimary(pScrn)) {
+      pI8301 = pI830;
+   } else {
+      pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
+      pScrn1 = pI830->entityPrivate->pScrn_1;
+   }
+
+   switch (pI830->rotation) {
+      case RR_Rotate_90:
+         matrix23Rotate(&rotMatrix,
+                     pScreen->width, pScreen->height,
+                     90);
+	 break;
+      case RR_Rotate_180:
+         matrix23Rotate(&rotMatrix,
+                     pScreen->width, pScreen->height,
+                     180);
+	 break;
+      case RR_Rotate_270:
+         matrix23Rotate(&rotMatrix,
+                     pScreen->width, pScreen->height,
+                     270);
+	 break;
+      default:
+	 break;
+   }
+
+#ifdef XF86DRI
+   if (pI8301->directRenderingEnabled) {
+      sarea = DRIGetSAREAPrivate(pScrn1->pScreen);
+      myContext = DRIGetContext(pScrn1->pScreen);
+      didLock = I830DRILock(pScrn1);
+   }
+#endif
+
+   if (pScrn->scrnIndex != *pI830->used3D) 
+      updateInvarient = TRUE;
+ 
+#ifdef XF86DRI
+   if (sarea && sarea->ctxOwner != myContext)
+      updateInvarient = TRUE;
+#endif
+
+   /*XXX we'll always update state */
+   *pI830->used3D = pScrn->scrnIndex;
+#ifdef XF86DRI
+   if (sarea)
+      sarea->ctxOwner = myContext;
+#endif
+
+   /* this starts initialize 3D engine for rotation mapping*/
+   next_offset = 0;
+
+   /* Set up our layout of state in framebuffer.  First the general state: */
+   vs_offset = ALIGN(next_offset, 64);
+   next_offset = vs_offset + sizeof(*vs_state);
+   sf_offset = ALIGN(next_offset, 32);
+   next_offset = sf_offset + sizeof(*sf_state);
+   wm_offset = ALIGN(next_offset, 32);
+   next_offset = wm_offset + sizeof(*wm_state);
+   wm_scratch_offset = ALIGN(next_offset, 1024);
+   next_offset = wm_scratch_offset + 1024 * PS_MAX_THREADS;
+   cc_offset = ALIGN(next_offset, 32);
+   next_offset = cc_offset + sizeof(*cc_state);
+
+   sf_kernel_offset = ALIGN(next_offset, 64);
+      
+   switch (pI830->rotation) {
+       case RR_Rotate_90:
+       case RR_Rotate_270:
+      	    next_offset = sf_kernel_offset + sizeof (sf_kernel_static90);
+      	    ps_kernel_offset = ALIGN(next_offset, 64);
+      	    next_offset = ps_kernel_offset + sizeof (ps_kernel_static90);
+	    break;
+       case RR_Rotate_180:
+       default:
+      	    next_offset = sf_kernel_offset + sizeof (sf_kernel_static0);
+      	    ps_kernel_offset = ALIGN(next_offset, 64);
+      	    next_offset = ps_kernel_offset + sizeof (ps_kernel_static0);
+	    break;
+   }
+
+   sip_kernel_offset = ALIGN(next_offset, 64);
+   next_offset = sip_kernel_offset + sizeof (sip_kernel_static);
+   cc_viewport_offset = ALIGN(next_offset, 32);
+   next_offset = cc_viewport_offset + sizeof(*cc_viewport);
+
+   src_sampler_offset = ALIGN(next_offset, 32);
+   next_offset = src_sampler_offset + sizeof(*src_sampler_state);
+
+   /* Align VB to native size of elements, for safety */
+   vb_offset = ALIGN(next_offset, 8);
+   next_offset = vb_offset + vb_size;
+
+   dest_surf_offset = ALIGN(next_offset, 32);
+   next_offset = dest_surf_offset + sizeof(*dest_surf_state);
+   src_surf_offset = ALIGN(next_offset, 32);
+   next_offset = src_surf_offset + sizeof(*src_surf_state);
+   binding_table_offset = ALIGN(next_offset, 32);
+   next_offset = binding_table_offset + (WM_BINDING_TABLE_ENTRIES * 4);
+
+   total_state_size = next_offset;
+   assert (total_state_size < BRW_LINEAR_EXTRA);
+
+   state_base_offset = pI830->RotateStateMem.Start;
+   state_base_offset = ALIGN(state_base_offset, 64);
+   state_base = (char *)(pI830->FbBase + state_base_offset);
+   DPRINTF(PFX, "rotate state buffer start 0x%x, addr 0x%x, base 0x%x\n",
+			pI830->RotateStateMem.Start, state_base, pI830->FbBase);
+
+   vs_state = (void *)(state_base + vs_offset);
+   sf_state = (void *)(state_base + sf_offset);
+   wm_state = (void *)(state_base + wm_offset);
+   cc_state = (void *)(state_base + cc_offset);
+   sf_kernel = (void *)(state_base + sf_kernel_offset);
+   ps_kernel = (void *)(state_base + ps_kernel_offset);
+   sip_kernel = (void *)(state_base + sip_kernel_offset);
+   
+   cc_viewport = (void *)(state_base + cc_viewport_offset);
+   dest_surf_state = (void *)(state_base + dest_surf_offset);
+   src_surf_state = (void *)(state_base + src_surf_offset);
+   src_sampler_state = (void *)(state_base + src_sampler_offset);
+   binding_table = (void *)(state_base + binding_table_offset);
+   vb = (void *)(state_base + vb_offset);
+
+   /* For 3D, the VS must have 8, 12, 16, 24, or 32 VUEs allocated to it.
+    * A VUE consists of a 256-bit vertex header followed by the vertex data,
+    * which in our case is 4 floats (128 bits), thus a single 512-bit URB
+    * entry.
+    */
+#define URB_VS_ENTRIES	      8
+#define URB_VS_ENTRY_SIZE     1
+   
+#define URB_GS_ENTRIES	      0
+#define URB_GS_ENTRY_SIZE     0
+   
+#define URB_CLIP_ENTRIES      0
+#define URB_CLIP_ENTRY_SIZE   0
+   
+   /* The SF kernel we use outputs only 4 256-bit registers, leading to an
+    * entry size of 2 512-bit URBs.  We don't need to have many entries to
+    * output as we're generally working on large rectangles and don't care
+    * about having WM threads running on different rectangles simultaneously.
+    */
+#define URB_SF_ENTRIES	      1
+#define URB_SF_ENTRY_SIZE     2
+
+#define URB_CS_ENTRIES	      0
+#define URB_CS_ENTRY_SIZE     0
+   
+   urb_vs_start = 0;
+   urb_vs_size = URB_VS_ENTRIES * URB_VS_ENTRY_SIZE;
+   urb_gs_start = urb_vs_start + urb_vs_size;
+   urb_gs_size = URB_GS_ENTRIES * URB_GS_ENTRY_SIZE;
+   urb_clip_start = urb_gs_start + urb_gs_size;
+   urb_clip_size = URB_CLIP_ENTRIES * URB_CLIP_ENTRY_SIZE;
+   urb_sf_start = urb_clip_start + urb_clip_size;
+   urb_sf_size = URB_SF_ENTRIES * URB_SF_ENTRY_SIZE;
+   urb_cs_start = urb_sf_start + urb_sf_size;
+   urb_cs_size = URB_CS_ENTRIES * URB_CS_ENTRY_SIZE;
+
+   memset (cc_viewport, 0, sizeof (*cc_viewport));
+   cc_viewport->min_depth = -1.e35;
+   cc_viewport->max_depth = 1.e35;
+
+   memset(cc_state, 0, sizeof(*cc_state));
+   cc_state->cc0.stencil_enable = 0;   /* disable stencil */
+   cc_state->cc2.depth_test = 0;       /* disable depth test */
+   cc_state->cc2.logicop_enable = 1;   /* enable logic op */
+   cc_state->cc3.ia_blend_enable = 1;  /* blend alpha just like colors */
+   cc_state->cc3.blend_enable = 0;     /* disable color blend */
+   cc_state->cc3.alpha_test = 0;       /* disable alpha test */
+   cc_state->cc4.cc_viewport_state_offset = (state_base_offset + cc_viewport_offset) >> 5;
+   cc_state->cc5.dither_enable = 0;    /* disable dither */
+   cc_state->cc5.logicop_func = 0xc;   /* COPY S*/
+   cc_state->cc5.statistics_enable = 1;
+   cc_state->cc5.ia_blend_function = BRW_BLENDFUNCTION_ADD;
+   cc_state->cc5.ia_src_blend_factor = BRW_BLENDFACTOR_ONE;
+   cc_state->cc5.ia_dest_blend_factor = BRW_BLENDFACTOR_ZERO;
+
+   /* Upload system kernel */
+   memcpy (sip_kernel, sip_kernel_static, sizeof (sip_kernel_static));
+   
+   memset(dest_surf_state, 0, sizeof(*dest_surf_state));
+   dest_surf_state->ss0.surface_type = BRW_SURFACE_2D;
+   dest_surf_state->ss0.data_return_format = BRW_SURFACERETURNFORMAT_FLOAT32;
+   if (pI8301->cpp == 2)
+      dest_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B5G6R5_UNORM;
+   else
+      dest_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
+   dest_surf_state->ss0.writedisable_alpha = 0;
+   dest_surf_state->ss0.writedisable_red = 0;
+   dest_surf_state->ss0.writedisable_green = 0;
+   dest_surf_state->ss0.writedisable_blue = 0;
+   dest_surf_state->ss0.color_blend = 0;
+   dest_surf_state->ss0.vert_line_stride = 0;
+   dest_surf_state->ss0.vert_line_stride_ofs = 0;
+   dest_surf_state->ss0.mipmap_layout_mode = 0;
+   dest_surf_state->ss0.render_cache_read_mode = 0;
+   
+   if (I830IsPrimary(pScrn))
+      dest_surf_state->ss1.base_addr = pI830->FrontBuffer.Start;
+   else 
+      dest_surf_state->ss1.base_addr = pI8301->FrontBuffer2.Start;
+   dest_surf_state->ss2.width = pScrn->virtualX - 1;
+   dest_surf_state->ss2.height = pScrn->virtualY - 1; 
+   dest_surf_state->ss2.mip_count = 0;
+   dest_surf_state->ss2.render_target_rotation = 0; /*XXX how to use? */
+   dest_surf_state->ss3.pitch = (pI830->displayWidth * pI830->cpp) - 1;
+   if (pI830->front_tiled) {
+      dest_surf_state->ss3.tiled_surface = 1;
+      dest_surf_state->ss3.tile_walk = 0; /* X major */
+   }
+
+   memset(src_surf_state, 0, sizeof(*src_surf_state));
+   src_surf_state->ss0.surface_type = BRW_SURFACE_2D;
+/* src_surf_state->ss0.data_return_format = BRW_SURFACERETURNFORMAT_FLOAT32;*/
+   if (pI8301->cpp == 2) 
+      src_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B5G6R5_UNORM;
+   else 
+      src_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
+   src_surf_state->ss0.writedisable_alpha = 0;
+   src_surf_state->ss0.writedisable_red = 0;
+   src_surf_state->ss0.writedisable_green = 0;
+   src_surf_state->ss0.writedisable_blue = 0;
+   src_surf_state->ss0.color_blend = 0;
+   src_surf_state->ss0.vert_line_stride = 0;
+   src_surf_state->ss0.vert_line_stride_ofs = 0;
+   src_surf_state->ss0.mipmap_layout_mode = 0;
+   src_surf_state->ss0.render_cache_read_mode = 0;
+  
+   if (I830IsPrimary(pScrn)) 
+      src_surf_state->ss1.base_addr = pI830->RotatedMem.Start;
+   else 
+      src_surf_state->ss1.base_addr = pI8301->RotatedMem2.Start;
+   src_surf_state->ss2.width = pScreen->width - 1;
+   src_surf_state->ss2.height = pScreen->height - 1;
+   src_surf_state->ss2.mip_count = 0;
+   src_surf_state->ss2.render_target_rotation = 0;
+   src_surf_state->ss3.pitch = (pScrn->displayWidth * pI830->cpp) - 1;
+   if (pI830->rotated_tiled) {
+      src_surf_state->ss3.tiled_surface = 1;
+      src_surf_state->ss3.tile_walk = 0; /* X major */
+   }
+
+   binding_table[0] = state_base_offset + dest_surf_offset;
+   binding_table[1] = state_base_offset + src_surf_offset;
+
+   memset(src_sampler_state, 0, sizeof(*src_sampler_state));
+   src_sampler_state->ss0.min_filter = BRW_MAPFILTER_LINEAR;
+   src_sampler_state->ss0.mag_filter = BRW_MAPFILTER_LINEAR;
+   src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
+   src_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
+   src_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
+
+   /* Set up the vertex shader to be disabled (passthrough) */
+   memset(vs_state, 0, sizeof(*vs_state));
+   vs_state->thread4.nr_urb_entries = URB_VS_ENTRIES;
+   vs_state->thread4.urb_entry_allocation_size = URB_VS_ENTRY_SIZE - 1;
+   vs_state->vs6.vs_enable = 0;
+   vs_state->vs6.vert_cache_disable = 1;
+
+   /* Set up the SF kernel to do coord interp: for each attribute,
+    * calculate dA/dx and dA/dy.  Hand these interpolation coefficients
+    * back to SF which then hands pixels off to WM.
+    */
+
+   switch (pI830->rotation) {
+      case RR_Rotate_90:
+      case RR_Rotate_270:
+           memcpy (sf_kernel, sf_kernel_static90, sizeof (sf_kernel_static90));
+           memcpy (ps_kernel, ps_kernel_static90, sizeof (ps_kernel_static90));
+	   break;
+      case RR_Rotate_180:
+      default:
+           memcpy (sf_kernel, sf_kernel_static0, sizeof (sf_kernel_static0));
+           memcpy (ps_kernel, ps_kernel_static0, sizeof (ps_kernel_static0));
+	   break;
+   }
+
+   memset(sf_state, 0, sizeof(*sf_state));
+   sf_state->thread0.kernel_start_pointer = 
+	          (state_base_offset + sf_kernel_offset) >> 6;
+   sf_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(SF_KERNEL_NUM_GRF);
+   sf_state->sf1.single_program_flow = 1; /* XXX */
+   sf_state->sf1.binding_table_entry_count = 0;
+   sf_state->sf1.thread_priority = 0;
+   sf_state->sf1.floating_point_mode = 0; 
+   sf_state->sf1.illegal_op_exception_enable = 1;
+   sf_state->sf1.mask_stack_exception_enable = 1;
+   sf_state->sf1.sw_exception_enable = 1;
+   sf_state->thread2.per_thread_scratch_space = 0;
+   sf_state->thread2.scratch_space_base_pointer = 0; /* not used in our kernel */
+   sf_state->thread3.const_urb_entry_read_length = 0; /* no const URBs */
+   sf_state->thread3.const_urb_entry_read_offset = 0; /* no const URBs */
+   sf_state->thread3.urb_entry_read_length = 1; /* 1 URB per vertex */
+   sf_state->thread3.urb_entry_read_offset = 0;
+   sf_state->thread3.dispatch_grf_start_reg = 3;
+   sf_state->thread4.max_threads = SF_MAX_THREADS - 1;
+   sf_state->thread4.urb_entry_allocation_size = URB_SF_ENTRY_SIZE - 1;
+   sf_state->thread4.nr_urb_entries = URB_SF_ENTRIES;
+   sf_state->thread4.stats_enable = 1;
+   sf_state->sf5.viewport_transform = FALSE; /* skip viewport */
+   sf_state->sf6.cull_mode = BRW_CULLMODE_NONE;
+   sf_state->sf6.scissor = 0;
+   sf_state->sf7.trifan_pv = 2;
+   sf_state->sf6.dest_org_vbias = 0x8;
+   sf_state->sf6.dest_org_hbias = 0x8;
+
+   memset (wm_state, 0, sizeof (*wm_state));
+   wm_state->thread0.kernel_start_pointer = 
+	       (state_base_offset + ps_kernel_offset) >> 6;
+   wm_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(PS_KERNEL_NUM_GRF);
+   wm_state->thread1.single_program_flow = 1; /* XXX */
+   wm_state->thread1.binding_table_entry_count = 2;
+   /* Though we never use the scratch space in our WM kernel, it has to be
+    * set, and the minimum allocation is 1024 bytes.
+    */
+   wm_state->thread2.scratch_space_base_pointer = (state_base_offset +
+						   wm_scratch_offset) >> 10;
+   wm_state->thread2.per_thread_scratch_space = 0; /* 1024 bytes */
+   wm_state->thread3.dispatch_grf_start_reg = 3;
+   wm_state->thread3.const_urb_entry_read_length = 0;
+   wm_state->thread3.const_urb_entry_read_offset = 0;
+   wm_state->thread3.urb_entry_read_length = 1;
+   wm_state->thread3.urb_entry_read_offset = 0;
+   wm_state->wm4.stats_enable = 1;
+   wm_state->wm4.sampler_state_pointer = (state_base_offset + src_sampler_offset) >> 5;
+   wm_state->wm4.sampler_count = 1; /* 1-4 samplers used */
+   wm_state->wm5.max_threads = PS_MAX_THREADS - 1;
+   wm_state->wm5.thread_dispatch_enable = 1;
+   wm_state->wm5.enable_16_pix = 1;
+   wm_state->wm5.enable_8_pix = 0;
+   wm_state->wm5.early_depth_test = 1;
+
+   
+   {
+         BEGIN_LP_RING(2);
+         OUT_RING(MI_FLUSH | 
+	          MI_STATE_INSTRUCTION_CACHE_FLUSH |
+	          BRW_MI_GLOBAL_SNAPSHOT_RESET);
+         OUT_RING(MI_NOOP);
+         ADVANCE_LP_RING();
+    }
+
+    {
+         BEGIN_LP_RING(12);
+         OUT_RING(BRW_PIPELINE_SELECT | PIPELINE_SELECT_3D);
+
+   /* Mesa does this. Who knows... */
+         OUT_RING(BRW_CS_URB_STATE | 0);
+         OUT_RING((0 << 4) |	/* URB Entry Allocation Size */
+	          (0 << 0));	/* Number of URB Entries */
+   
+   /* Zero out the two base address registers so all offsets are absolute */
+         OUT_RING(BRW_STATE_BASE_ADDRESS | 4);
+         OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* Generate state base address */
+         OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* Surface state base address */
+         OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* media base addr, don't care */
+         OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY);  /* general state max addr, disabled */
+         OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY);  /* media object state max addr, disabled */
+
+   /* Set system instruction pointer */
+         OUT_RING(BRW_STATE_SIP | 0);
+         OUT_RING(state_base_offset + sip_kernel_offset); /* system instruction pointer */
+      
+         OUT_RING(MI_NOOP);
+         ADVANCE_LP_RING(); 
+    }
+   
+
+    { 
+         BEGIN_LP_RING(36);
+   /* Enable VF statistics */
+         OUT_RING(BRW_3DSTATE_VF_STATISTICS | 1);
+   
+   /* Pipe control */
+         OUT_RING(BRW_PIPE_CONTROL |
+	          BRW_PIPE_CONTROL_NOWRITE |
+	          BRW_PIPE_CONTROL_IS_FLUSH |
+	          2);
+         OUT_RING(0);			       /* Destination address */
+         OUT_RING(0);			       /* Immediate data low DW */
+         OUT_RING(0);			       /* Immediate data high DW */
+
+   /* Binding table pointers */
+         OUT_RING(BRW_3DSTATE_BINDING_TABLE_POINTERS | 4);
+         OUT_RING(0); /* vs */
+         OUT_RING(0); /* gs */
+         OUT_RING(0); /* clip */
+         OUT_RING(0); /* sf */
+   /* Only the PS uses the binding table */
+         OUT_RING(state_base_offset + binding_table_offset); /* ps */
+   
+   /* XXX: Blend constant color (magenta is fun) */
+         //OUT_RING(BRW_3DSTATE_CONSTANT_COLOR | 3);
+         //OUT_RING(float_to_uint (1.0));
+         //OUT_RING(float_to_uint (0.0));
+         //OUT_RING(float_to_uint (1.0));
+         //OUT_RING(float_to_uint (1.0));
+   
+   /* The drawing rectangle clipping is always on.  Set it to values that
+    * shouldn't do any clipping.
+    */
+         OUT_RING(BRW_3DSTATE_DRAWING_RECTANGLE | 2);	/* XXX 3 for BLC or CTG */
+         OUT_RING(0x00000000);	/* ymin, xmin */
+         OUT_RING((pScrn->virtualX - 1) |
+	          (pScrn->virtualY - 1) << 16); /* ymax, xmax */
+         OUT_RING(0x00000000);	/* yorigin, xorigin */
+
+   /* skip the depth buffer */
+   /* skip the polygon stipple */
+   /* skip the polygon stipple offset */
+   /* skip the line stipple */
+   
+   /* Set the pointers to the 3d pipeline state */
+         OUT_RING(BRW_3DSTATE_PIPELINED_POINTERS | 5);
+         OUT_RING(state_base_offset + vs_offset);  /* 32 byte aligned */
+         OUT_RING(BRW_GS_DISABLE);		     /* disable GS, resulting in passthrough */
+         OUT_RING(BRW_CLIP_DISABLE);		     /* disable CLIP, resulting in passthrough */
+         OUT_RING(state_base_offset + sf_offset);  /* 32 byte aligned */
+         OUT_RING(state_base_offset + wm_offset);  /* 32 byte aligned */
+         OUT_RING(state_base_offset + cc_offset);  /* 64 byte aligned */
+
+   /* URB fence */
+         OUT_RING(BRW_URB_FENCE |
+	          UF0_CS_REALLOC |
+	          UF0_SF_REALLOC |
+	          UF0_CLIP_REALLOC |
+	          UF0_GS_REALLOC |
+	          UF0_VS_REALLOC |
+	    	  1);
+         OUT_RING(((urb_clip_start + urb_clip_size) << UF1_CLIP_FENCE_SHIFT) |
+	          ((urb_gs_start + urb_gs_size) << UF1_GS_FENCE_SHIFT) |
+	          ((urb_vs_start + urb_vs_size) << UF1_VS_FENCE_SHIFT));
+         OUT_RING(((urb_cs_start + urb_cs_size) << UF2_CS_FENCE_SHIFT) |
+	          ((urb_sf_start + urb_sf_size) << UF2_SF_FENCE_SHIFT));
+
+   /* Constant buffer state */
+         OUT_RING(BRW_CS_URB_STATE | 0);
+         OUT_RING(((URB_CS_ENTRY_SIZE - 1) << 4) | /* URB Entry Allocation Size */
+	          (URB_CS_ENTRIES << 0));	     /* Number of URB Entries */
+   
+   /* Set up the pointer to our vertex buffer */
+         OUT_RING(BRW_3DSTATE_VERTEX_BUFFERS | 2);
+         OUT_RING((0 << VB0_BUFFER_INDEX_SHIFT) |
+	          VB0_VERTEXDATA |
+	          ((4 * 4) << VB0_BUFFER_PITCH_SHIFT)); /* four 32-bit floats per vertex */
+         OUT_RING(state_base_offset + vb_offset);
+         OUT_RING(3); /* four corners to our rectangle */
+
+   /* Set up our vertex elements, sourced from the single vertex buffer. */
+         OUT_RING(BRW_3DSTATE_VERTEX_ELEMENTS | 3);
+   /* offset 0: X,Y -> {X, Y, 1.0, 1.0} */
+         OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
+	          VE0_VALID |
+	          (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
+	          (0 << VE0_OFFSET_SHIFT));
+         OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
+	          (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
+	          (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
+	          (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
+	          (0 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
+   /* offset 8: S0, T0 -> {S0, T0, 1.0, 1.0} */
+         OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
+	          VE0_VALID |
+	          (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
+	          (8 << VE0_OFFSET_SHIFT));
+         OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
+	          (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
+	          (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
+	          (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
+	          (4 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
+
+         //OUT_RING(MI_NOOP);			/* pad to quadword */
+         ADVANCE_LP_RING(); 
+   }
+
+   {
+      BEGIN_LP_RING(2);
+      OUT_RING(MI_FLUSH | 
+	       MI_STATE_INSTRUCTION_CACHE_FLUSH |
+	       BRW_MI_GLOBAL_SNAPSHOT_RESET);
+      OUT_RING(MI_NOOP);
+      ADVANCE_LP_RING();
+   }
+
+   while (nbox--)
+   {
+      float src_scale_x, src_scale_y;
+      int i;
+      box_x1 = pbox->x1;
+      box_y1 = pbox->y1;
+      box_x2 = pbox->x2;
+      box_y2 = pbox->y2;
+
+      if (!first_output) {
+	 /* Since we use the same little vertex buffer over and over, sync for
+	  * subsequent rectangles.
+	  */
+	 if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
+	    (*pI830->AccelInfoRec->Sync)(pScrn);
+	    pI830->AccelInfoRec->NeedToSync = FALSE;
+	 }
+      }
+
+      pbox++;
+
+      verts[0][0] = box_x1; verts[0][1] = box_y1;
+      verts[1][0] = box_x2; verts[1][1] = box_y1;
+      verts[2][0] = box_x2; verts[2][1] = box_y2;
+      verts[3][0] = box_x1; verts[3][1] = box_y2;
+
+      /* transform coordinates to rotated versions, but leave texcoords unchanged */
+      for (i = 0; i < 4; i++)
+         matrix23TransformCoordf(&rotMatrix, &verts[i][0], &verts[i][1]);
+
+      src_scale_x = (float)1.0 / (float)pScreen->width;
+      src_scale_y = (float)1.0 / (float)pScreen->height;
+      i = 0;
+
+      DPRINTF(PFX, "box size (%d, %d) -> (%d, %d)\n", 
+			box_x1, box_y1, box_x2, box_y2);
+
+      switch (pI830->rotation) {
+         case RR_Rotate_90:
+      	    vb[i++] = (float)box_x1 * src_scale_x;
+      	    vb[i++] = (float)box_y2 * src_scale_y;
+      	    vb[i++] = verts[3][0];
+      	    vb[i++] = verts[3][1];
+
+      	    vb[i++] = (float)box_x1 * src_scale_x;
+      	    vb[i++] = (float)box_y1 * src_scale_y;
+      	    vb[i++] = verts[0][0];
+      	    vb[i++] = verts[0][1];
+
+      	    vb[i++] = (float)box_x2 * src_scale_x;
+      	    vb[i++] = (float)box_y1 * src_scale_y;
+      	    vb[i++] = verts[1][0];
+      	    vb[i++] = verts[1][1];
+	    break;
+         case RR_Rotate_270:
+      	    vb[i++] = (float)box_x2 * src_scale_x;
+      	    vb[i++] = (float)box_y1 * src_scale_y;
+      	    vb[i++] = verts[1][0];
+      	    vb[i++] = verts[1][1];
+
+      	    vb[i++] = (float)box_x2 * src_scale_x;
+      	    vb[i++] = (float)box_y2 * src_scale_y;
+      	    vb[i++] = verts[2][0];
+      	    vb[i++] = verts[2][1];
+
+      	    vb[i++] = (float)box_x1 * src_scale_x;
+      	    vb[i++] = (float)box_y2 * src_scale_y;
+      	    vb[i++] = verts[3][0];
+      	    vb[i++] = verts[3][1];
+	    break;
+	 case RR_Rotate_180:
+       	 default:
+      	    vb[i++] = (float)box_x1 * src_scale_x;
+      	    vb[i++] = (float)box_y1 * src_scale_y;
+      	    vb[i++] = verts[0][0];
+      	    vb[i++] = verts[0][1];
+
+            vb[i++] = (float)box_x2 * src_scale_x;
+      	    vb[i++] = (float)box_y1 * src_scale_y;
+      	    vb[i++] = verts[1][0];
+      	    vb[i++] = verts[1][1];
+
+      	    vb[i++] = (float)box_x2 * src_scale_x;
+      	    vb[i++] = (float)box_y2 * src_scale_y;
+      	    vb[i++] = verts[2][0];
+      	    vb[i++] = verts[2][1];
+	    break;
+      }
+
+      BEGIN_LP_RING(6);
+      OUT_RING(BRW_3DPRIMITIVE | 
+	       BRW_3DPRIMITIVE_VERTEX_SEQUENTIAL |
+	       (_3DPRIM_RECTLIST << BRW_3DPRIMITIVE_TOPOLOGY_SHIFT) | 
+	       (0 << 9) |  /* CTG - indirect vertex count */
+	       4);
+      OUT_RING(3); /* vertex count per instance */
+      OUT_RING(0); /* start vertex offset */
+      OUT_RING(1); /* single instance */
+      OUT_RING(0); /* start instance location */
+      OUT_RING(0); /* index buffer offset, ignored */
+      ADVANCE_LP_RING();
+
+      first_output = FALSE;
+      if (pI830->AccelInfoRec)
+	 pI830->AccelInfoRec->NeedToSync = TRUE;
+   }
+
+   if (pI830->AccelInfoRec)
+      (*pI830->AccelInfoRec->Sync)(pScrn);
+#ifdef XF86DRI
+   if (didLock)
+      I830DRIUnlock(pScrn1);
+#endif
+}
+
+
 static void
 I915UpdateRotate (ScreenPtr      pScreen,
                  shadowBufPtr   pBuf)
@@ -657,11 +1371,15 @@ I830Rotate(ScrnInfoPtr pScrn, DisplayMod
 
    if (pI830->noAccel)
       func = LoaderSymbol("shadowUpdateRotatePacked");
-   else
-      if (IS_I9XX(pI830))
-	 func = I915UpdateRotate;
-      else
+   else {
+      if (IS_I9XX(pI830)) {
+	 if (IS_I965G(pI830))
+	     func = I965UpdateRotate;
+	 else 
+	     func = I915UpdateRotate;
+      } else
 	 func = I830UpdateRotate;
+   }
 
    if (I830IsPrimary(pScrn)) {
       pI8301 = pI830;
@@ -738,6 +1456,15 @@ I830Rotate(ScrnInfoPtr pScrn, DisplayMod
       memset(&(pI8301->RotatedMem), 0, sizeof(pI8301->RotatedMem));
       pI8301->RotatedMem.Key = -1;
 
+      if (IS_I965G(pI8301)) {
+         if (pI8301->RotateStateMem.Key != -1)
+            xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->RotateStateMem.Key);
+ 
+         I830FreeVidMem(pScrn1, &(pI8301->RotateStateMem));
+         memset(&(pI8301->RotateStateMem), 0, sizeof(pI8301->RotateStateMem));
+      	 pI8301->RotateStateMem.Key = -1;
+      }
+
       if (pI830->entityPrivate) {
          if (pI8301->RotatedMem2.Key != -1)
             xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->RotatedMem2.Key);
@@ -820,6 +1547,12 @@ I830Rotate(ScrnInfoPtr pScrn, DisplayMod
          I830FixOffset(pScrn1, &(pI8301->RotatedMem));
          if (pI8301->RotatedMem.Key != -1)
             xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->RotatedMem.Key, pI8301->RotatedMem.Offset);
+	 if (IS_I965G(pI8301)) {
+            I830FixOffset(pScrn1, &(pI8301->RotateStateMem));
+            if (pI8301->RotateStateMem.Key != -1)
+            	xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->RotateStateMem.Key, 
+				   pI8301->RotateStateMem.Offset);
+	 }
       }
    }
    
@@ -887,8 +1620,16 @@ I830Rotate(ScrnInfoPtr pScrn, DisplayMod
       }
       I830SetupMemoryTiling(pScrn1);
       /* update fence registers */
-      for (i = 0; i < 8; i++) 
-         OUTREG(FENCE + i * 4, pI8301->ModeReg.Fence[i]);
+      if (IS_I965G(pI830)) {
+         for (i = 0; i < FENCE_NEW_NR; i++) {
+            OUTREG(FENCE_NEW + i * 8, pI830->ModeReg.Fence[i]);
+            OUTREG(FENCE_NEW + 4 + i * 8, pI830->ModeReg.Fence[i+FENCE_NEW_NR]);
+         }
+      } else {
+         for (i = 0; i < 8; i++) 
+            OUTREG(FENCE + i * 4, pI8301->ModeReg.Fence[i]);
+      }
+
       {
          drmI830Sarea *sarea = DRIGetSAREAPrivate(pScrn1->pScreen);
          I830UpdateDRIBuffers(pScrn1, sarea );
diff --git a/src/rotation_sf0.g4a b/src/rotation_sf0.g4a
new file mode 100644
index 0000000..8c1398f
--- /dev/null
+++ b/src/rotation_sf0.g4a
@@ -0,0 +1,17 @@
+send (1) 0 g6<1>F g1.12<0,1,0>F math inv scalar mlen 1 rlen 1 { align1 };
+send (1) 0 g6.4<1>F g1.20<0,1,0>F math inv scalar mlen 1 rlen 1 { align1 };
+add (8) g7<1>F g4<8,8,1>F -g3<8,8,1>F { align1 };
+mul (1) g7<1>F g7<0,1,0>F g6<0,1,0>F { align1 };
+mul (1) g7.4<1>F g7.4<0,1,0>F g6.4<0,1,0>F { align1 };
+mov (8) m1<1>F g7<0,1,0>F { align1 };
+mov (8) m2<1>F g7.4<0,1,0>F { align1 };
+mov (8) m3<1>F g3<8,8,1>F { align1 };
+send (8) 0 null g0<8,8,1>F urb 0 transpose used complete mlen 4 rlen 0 { align1 EOT };
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
diff --git a/src/rotation_sf90.g4a b/src/rotation_sf90.g4a
new file mode 100644
index 0000000..2648dff
--- /dev/null
+++ b/src/rotation_sf90.g4a
@@ -0,0 +1,17 @@
+send (1) 0 g6<1>F g1.20<0,1,0>F math inv scalar mlen 1 rlen 1 { align1 };
+send (1) 0 g6.4<1>F g1.12<0,1,0>F math inv scalar mlen 1 rlen 1 { align1 };
+add (8) g7<1>F g4<8,8,1>F -g3<8,8,1>F { align1 };
+mul (1) g7<1>F g7<0,1,0>F g6<0,1,0>F { align1 };
+mul (1) g7.4<1>F g7.4<0,1,0>F g6.4<0,1,0>F { align1 };
+mov (8) m1<1>F g7<0,1,0>F { align1 };
+mov (8) m2<1>F g7.4<0,1,0>F { align1 };
+mov (8) m3<1>F g3<8,8,1>F { align1 };
+send (8) 0 null g0<8,8,1>F urb 0 transpose used complete mlen 4 rlen 0 { align1 EOT };
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
diff --git a/src/rotation_sf_prog0.h b/src/rotation_sf_prog0.h
new file mode 100644
index 0000000..830d176
--- /dev/null
+++ b/src/rotation_sf_prog0.h
@@ -0,0 +1,17 @@
+   { 0x00000031, 0x20c01fbd, 0x0000002c, 0x01110081 },
+   { 0x00000031, 0x20c41fbd, 0x00000034, 0x01110081 },
+   { 0x00600040, 0x20e077bd, 0x008d0080, 0x008d4060 },
+   { 0x00000041, 0x20e077bd, 0x000000e0, 0x000000c0 },
+   { 0x00000041, 0x20e477bd, 0x000000e4, 0x000000c4 },
+   { 0x00600001, 0x202003be, 0x000000e0, 0x00000000 },
+   { 0x00600001, 0x204003be, 0x000000e4, 0x00000000 },
+   { 0x00600001, 0x206003be, 0x008d0060, 0x00000000 },
+   { 0x00600031, 0x20001fbc, 0x008d0000, 0x8640c800 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
diff --git a/src/rotation_sf_prog90.h b/src/rotation_sf_prog90.h
new file mode 100644
index 0000000..2e94b8f
--- /dev/null
+++ b/src/rotation_sf_prog90.h
@@ -0,0 +1,17 @@
+   { 0x00000031, 0x20c01fbd, 0x00000034, 0x01110081 },
+   { 0x00000031, 0x20c41fbd, 0x0000002c, 0x01110081 },
+   { 0x00600040, 0x20e077bd, 0x008d0080, 0x008d4060 },
+   { 0x00000041, 0x20e077bd, 0x000000e0, 0x000000c0 },
+   { 0x00000041, 0x20e477bd, 0x000000e4, 0x000000c4 },
+   { 0x00600001, 0x202003be, 0x000000e0, 0x00000000 },
+   { 0x00600001, 0x204003be, 0x000000e4, 0x00000000 },
+   { 0x00600001, 0x206003be, 0x008d0060, 0x00000000 },
+   { 0x00600031, 0x20001fbc, 0x008d0000, 0x8640c800 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
diff --git a/src/rotation_wm0.g4a b/src/rotation_wm0.g4a
new file mode 100644
index 0000000..fe09734
--- /dev/null
+++ b/src/rotation_wm0.g4a
@@ -0,0 +1,123 @@
+/* The initial payload of the thread is always g0.
+ * WM_URB (incoming URB entries) is g3
+ * X0_R is g4
+ * X1_R is g5
+ * Y0_R is g6
+ * Y1_R is g7
+ */
+
+    /* Set up the X/Y screen coordinates of the pixels in our 4 subspans.  Each
+     * subspan is a 2x2 rectangle, and the screen x/y of the upper left of each
+     * subspan are given in GRF register 1.2 through 1.5 (which, with the word
+     * addressing below, are 1.4 through 1.11).
+     *
+     * The result is WM_X*_R and WM_Y*R being:
+     *
+     * X0: {ss0.x, ss0.x+1, ss0.x,   ss0.x+1, ss1.x, ss1.x+1, ss1.x,   ss1.x+y}
+     * Y0: {ss0.y, ss0.y,   ss0.y+1, ss0.y+1, ss1.y, ss1.y,   ss1.y+1, ss1.y+1}
+     * X1: {ss2.x, ss2.x+1, ss2.x,   ss2.x+1, ss3.x, ss3.x+1, ss3.x,   ss3.x+y}
+     * Y1: {ss2.y, ss2.y,   ss2.y+1, ss2.y+1, ss3.y, ss3.y,   ss3.y+1, ss3.y+1}
+     */
+
+    /* Set up ss0.x coordinates*/
+mov (1) g4<1>F g1.8<0,1,0>UW { align1 };
+add (1) g4.4<1>F g1.8<0,1,0>UW 1UB { align1 };
+mov (1) g4.8<1>F g1.8<0,1,0>UW { align1 };
+add (1) g4.12<1>F g1.8<0,1,0>UW 1UB { align1 };
+    /* Set up ss0.y coordinates */
+mov (1) g6<1>F g1.10<0,1,0>UW { align1 };
+mov (1) g6.4<1>F g1.10<0,1,0>UW { align1 };
+add (1) g6.8<1>F g1.10<0,1,0>UW 1UB { align1 };
+add (1) g6.12<1>F g1.10<0,1,0>UW 1UB { align1 };
+    /* set up ss1.x coordinates */
+mov (1) g4.16<1>F g1.12<0,1,0>UW { align1 };
+add (1) g4.20<1>F g1.12<0,1,0>UW 1UB { align1 };
+mov (1) g4.24<1>F g1.12<0,1,0>UW { align1 };
+add (1) g4.28<1>F g1.12<0,1,0>UW 1UB { align1 };
+    /* set up ss1.y coordinates */
+mov (1) g6.16<1>F g1.14<0,1,0>UW { align1 };
+mov (1) g6.20<1>F g1.14<0,1,0>UW { align1 };
+add (1) g6.24<1>F g1.14<0,1,0>UW 1UB { align1 };
+add (1) g6.28<1>F g1.14<0,1,0>UW 1UB { align1 };
+    /* Set up ss2.x coordinates */
+mov (1) g5<1>F g1.16<0,1,0>UW { align1 };
+add (1) g5.4<1>F g1.16<0,1,0>UW 1UB { align1 };
+mov (1) g5.8<1>F g1.16<0,1,0>UW { align1 };
+add (1) g5.12<1>F g1.16<0,1,0>UW 1UB { align1 };
+    /* Set up ss2.y coordinates */
+mov (1) g7<1>F g1.18<0,1,0>UW { align1 };
+mov (1) g7.4<1>F g1.18<0,1,0>UW { align1 };
+add (1) g7.8<1>F g1.18<0,1,0>UW 1UB { align1 };
+add (1) g7.12<1>F g1.18<0,1,0>UW 1UB { align1 };
+    /* Set up ss3.x coordinates */
+mov (1) g5.16<1>F g1.20<0,1,0>UW { align1 };
+add (1) g5.20<1>F g1.20<0,1,0>UW 1UB { align1 };
+mov (1) g5.24<1>F g1.20<0,1,0>UW { align1 };
+add (1) g5.28<1>F g1.20<0,1,0>UW 1UB { align1 };
+    /* Set up ss3.y coordinates */
+mov (1) g7.16<1>F g1.22<0,1,0>UW { align1 };
+mov (1) g7.20<1>F g1.22<0,1,0>UW { align1 };
+add (1) g7.24<1>F g1.22<0,1,0>UW 1UB { align1 };
+add (1) g7.28<1>F g1.22<0,1,0>UW 1UB { align1 };
+
+    /* Now, map these screen space coordinates into texture coordinates. */
+    /* subtract screen-space X origin of vertex 0. */
+add (8) g4<1>F g4<8,8,1>F -g1<0,1,0>F { align1 };
+add (8) g5<1>F g5<8,8,1>F -g1<0,1,0>F { align1 };
+    /* scale by texture X increment */
+mul (8) g4<1>F g4<8,8,1>F g3<0,1,0>F { align1 };
+mul (8) g5<1>F g5<8,8,1>F g3<0,1,0>F { align1 };
+    /* add in texture X offset */
+add (8) g4<1>F g4<8,8,1>F g3.12<0,1,0>F { align1 };
+add (8) g5<1>F g5<8,8,1>F g3.12<0,1,0>F { align1 };
+    /* subtract screen-space Y origin of vertex 0. */
+add (8) g6<1>F g6<8,8,1>F -g1.4<0,1,0>F { align1 };
+add (8) g7<1>F g7<8,8,1>F -g1.4<0,1,0>F { align1 };
+    /* scale by texture Y increment */
+    /* XXX: double check the fields in Cx,Cy,Co and attributes*/
+mul (8) g6<1>F g6<8,8,1>F g3.20<0,1,0>F { align1 };
+mul (8) g7<1>F g7<8,8,1>F g3.20<0,1,0>F { align1 };
+    /* add in texture Y offset */
+add (8) g6<1>F g6<8,8,1>F g3.28<0,1,0>F { align1 };
+add (8) g7<1>F g7<8,8,1>F g3.28<0,1,0>F { align1 };
+    /* sampler  */
+mov (8) m1<1>F g4<8,8,1>F { align1 };
+mov (8) m2<1>F g5<8,8,1>F { align1 };
+mov (8) m3<1>F g6<8,8,1>F { align1 };
+mov (8) m4<1>F g7<8,8,1>F { align1 };
+
+    /*
+     * g0 holds the PS thread payload, which (oddly) contains
+     * precisely what the sampler wants to see in m0
+     */
+send  (16) 0 g12<1>UW g0<8,8,1>UW sampler (1,0,F) mlen 5 rlen 8 { align1 };
+mov (8) g19<1>UD g19<8,8,1>UD { align1 };
+
+mov (8) m2<1>F g12<8,8,1>F { align1 };
+mov (8) m3<1>F g14<8,8,1>F { align1 };
+mov (8) m4<1>F g16<8,8,1>F { align1 };
+mov (8) m5<1>F g18<8,8,1>F { align1 };
+mov (8) m6<1>F g13<8,8,1>F { align1 };
+mov (8) m7<1>F g15<8,8,1>F { align1 };
+mov (8) m8<1>F g17<8,8,1>F { align1 };
+mov (8) m9<1>F g19<8,8,1>F { align1 };
+
+   /* Pass through control information:
+    */
+mov (8) m1<1>UD g1<8,8,1>UD { align1 mask_disable };
+   /* Send framebuffer write message: XXX: acc0? */
+send (16) 0 acc0<1>UW g0<8,8,1>UW write (
+	0, /* binding table index 0 */
+	8, /* pixel scoreboard clear */
+	4, /* render target write */
+	0 /* no write commit message */
+	) mlen 10 rlen 0 { align1 EOT };
+   /* padding */
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
diff --git a/src/rotation_wm90.g4a b/src/rotation_wm90.g4a
new file mode 100644
index 0000000..fd600bf
--- /dev/null
+++ b/src/rotation_wm90.g4a
@@ -0,0 +1,127 @@
+/* The initial payload of the thread is always g0.
+ * WM_URB (incoming URB entries) is g3
+ * X0_R is g4
+ * X1_R is g5
+ * Y0_R is g6
+ * Y1_R is g7
+ */
+
+    /* Set up the X/Y screen coordinates of the pixels in our 4 subspans.  Each
+     * subspan is a 2x2 rectangle, and the screen x/y of the upper left of each
+     * subspan are given in GRF register 1.2 through 1.5 (which, with the word
+     * addressing below, are 1.4 through 1.11).
+     *
+     * The result is WM_X*_R and WM_Y*R being:
+     *
+     * X0: {ss0.x, ss0.x+1, ss0.x,   ss0.x+1, ss1.x, ss1.x+1, ss1.x,   ss1.x+y}
+     * Y0: {ss0.y, ss0.y,   ss0.y+1, ss0.y+1, ss1.y, ss1.y,   ss1.y+1, ss1.y+1}
+     * X1: {ss2.x, ss2.x+1, ss2.x,   ss2.x+1, ss3.x, ss3.x+1, ss3.x,   ss3.x+y}
+     * Y1: {ss2.y, ss2.y,   ss2.y+1, ss2.y+1, ss3.y, ss3.y,   ss3.y+1, ss3.y+1}
+     */
+
+    /* Set up ss0.x coordinates*/
+mov (1) g4<1>F g1.8<0,1,0>UW { align1 };
+add (1) g4.4<1>F g1.8<0,1,0>UW 1UB { align1 };
+mov (1) g4.8<1>F g1.8<0,1,0>UW { align1 };
+add (1) g4.12<1>F g1.8<0,1,0>UW 1UB { align1 };
+    /* Set up ss0.y coordinates */
+mov (1) g6<1>F g1.10<0,1,0>UW { align1 };
+mov (1) g6.4<1>F g1.10<0,1,0>UW { align1 };
+add (1) g6.8<1>F g1.10<0,1,0>UW 1UB { align1 };
+add (1) g6.12<1>F g1.10<0,1,0>UW 1UB { align1 };
+    /* set up ss1.x coordinates */
+mov (1) g4.16<1>F g1.12<0,1,0>UW { align1 };
+add (1) g4.20<1>F g1.12<0,1,0>UW 1UB { align1 };
+mov (1) g4.24<1>F g1.12<0,1,0>UW { align1 };
+add (1) g4.28<1>F g1.12<0,1,0>UW 1UB { align1 };
+    /* set up ss1.y coordinates */
+mov (1) g6.16<1>F g1.14<0,1,0>UW { align1 };
+mov (1) g6.20<1>F g1.14<0,1,0>UW { align1 };
+add (1) g6.24<1>F g1.14<0,1,0>UW 1UB { align1 };
+add (1) g6.28<1>F g1.14<0,1,0>UW 1UB { align1 };
+    /* Set up ss2.x coordinates */
+mov (1) g5<1>F g1.16<0,1,0>UW { align1 };
+add (1) g5.4<1>F g1.16<0,1,0>UW 1UB { align1 };
+mov (1) g5.8<1>F g1.16<0,1,0>UW { align1 };
+add (1) g5.12<1>F g1.16<0,1,0>UW 1UB { align1 };
+    /* Set up ss2.y coordinates */
+mov (1) g7<1>F g1.18<0,1,0>UW { align1 };
+mov (1) g7.4<1>F g1.18<0,1,0>UW { align1 };
+add (1) g7.8<1>F g1.18<0,1,0>UW 1UB { align1 };
+add (1) g7.12<1>F g1.18<0,1,0>UW 1UB { align1 };
+    /* Set up ss3.x coordinates */
+mov (1) g5.16<1>F g1.20<0,1,0>UW { align1 };
+add (1) g5.20<1>F g1.20<0,1,0>UW 1UB { align1 };
+mov (1) g5.24<1>F g1.20<0,1,0>UW { align1 };
+add (1) g5.28<1>F g1.20<0,1,0>UW 1UB { align1 };
+    /* Set up ss3.y coordinates */
+mov (1) g7.16<1>F g1.22<0,1,0>UW { align1 };
+mov (1) g7.20<1>F g1.22<0,1,0>UW { align1 };
+add (1) g7.24<1>F g1.22<0,1,0>UW 1UB { align1 };
+add (1) g7.28<1>F g1.22<0,1,0>UW 1UB { align1 };
+
+    /* Now, map these screen space coordinates into texture coordinates. */
+/* XXX: convert it to calculate (u,v) in 90 and 270 case */
+    /* subtract screen-space Y origin of vertex 0. */
+add (8) g6<1>F g6<8,8,1>F -g1.4<0,1,0>F { align1 };
+add (8) g7<1>F g7<8,8,1>F -g1.4<0,1,0>F { align1 };
+
+/* (Yp - Ystart) * Cx */
+mul (8) g6<1>F g6<8,8,1>F g3<0,1,0>F { align1 };
+mul (8) g7<1>F g7<8,8,1>F g3<0,1,0>F { align1 };
+
+    /* scale by texture Y increment */
+add (8) g6<1>F g6<8,8,1>F g3.12<0,1,0>F { align1 };
+add (8) g7<1>F g7<8,8,1>F g3.12<0,1,0>F { align1 };
+
+    /* subtract screen-space X origin of vertex 0. */
+add (8) g4<1>F g4<8,8,1>F -g1<0,1,0>F { align1 };
+add (8) g5<1>F g5<8,8,1>F -g1<0,1,0>F { align1 };
+    /* scale by texture X increment */
+mul (8) g4<1>F g4<8,8,1>F g3.20<0,1,0>F { align1 };
+mul (8) g5<1>F g5<8,8,1>F g3.20<0,1,0>F { align1 };
+    /* add in texture X offset */
+add (8) g4<1>F g4<8,8,1>F g3.28<0,1,0>F { align1 };
+add (8) g5<1>F g5<8,8,1>F g3.28<0,1,0>F { align1 };
+
+    /* sampler  */
+mov (8) m1<1>F g6<8,8,1>F { align1 };
+mov (8) m2<1>F g7<8,8,1>F { align1 };
+mov (8) m3<1>F g4<8,8,1>F { align1 };
+mov (8) m4<1>F g5<8,8,1>F { align1 };
+
+    /*
+     * g0 holds the PS thread payload, which (oddly) contains
+     * precisely what the sampler wants to see in m0
+     */
+send  (16) 0 g12<1>UW g0<8,8,1>UW sampler (1,0,F) mlen 5 rlen 8 { align1 };
+mov (8) g19<1>UD g19<8,8,1>UD { align1 };
+
+mov (8) m2<1>F g12<8,8,1>F { align1 };
+mov (8) m3<1>F g14<8,8,1>F { align1 };
+mov (8) m4<1>F g16<8,8,1>F { align1 };
+mov (8) m5<1>F g18<8,8,1>F { align1 };
+mov (8) m6<1>F g13<8,8,1>F { align1 };
+mov (8) m7<1>F g15<8,8,1>F { align1 };
+mov (8) m8<1>F g17<8,8,1>F { align1 };
+mov (8) m9<1>F g19<8,8,1>F { align1 };
+
+   /* Pass through control information:
+    */
+mov (8) m1<1>UD g1<8,8,1>UD { align1 mask_disable };
+   /* Send framebuffer write message: XXX: acc0? */
+send (16) 0 acc0<1>UW g0<8,8,1>UW write (
+	0, /* binding table index 0 */
+	8, /* pixel scoreboard clear */
+	4, /* render target write */
+	0 /* no write commit message */
+	) mlen 10 rlen 0 { align1 EOT };
+   /* padding */
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
diff --git a/src/rotation_wm_prog0.h b/src/rotation_wm_prog0.h
new file mode 100644
index 0000000..08269b7
--- /dev/null
+++ b/src/rotation_wm_prog0.h
@@ -0,0 +1,68 @@
+   { 0x00000001, 0x2080013d, 0x00000028, 0x00000000 },
+   { 0x00000040, 0x20840d3d, 0x00000028, 0x00000001 },
+   { 0x00000001, 0x2088013d, 0x00000028, 0x00000000 },
+   { 0x00000040, 0x208c0d3d, 0x00000028, 0x00000001 },
+   { 0x00000001, 0x20c0013d, 0x0000002a, 0x00000000 },
+   { 0x00000001, 0x20c4013d, 0x0000002a, 0x00000000 },
+   { 0x00000040, 0x20c80d3d, 0x0000002a, 0x00000001 },
+   { 0x00000040, 0x20cc0d3d, 0x0000002a, 0x00000001 },
+   { 0x00000001, 0x2090013d, 0x0000002c, 0x00000000 },
+   { 0x00000040, 0x20940d3d, 0x0000002c, 0x00000001 },
+   { 0x00000001, 0x2098013d, 0x0000002c, 0x00000000 },
+   { 0x00000040, 0x209c0d3d, 0x0000002c, 0x00000001 },
+   { 0x00000001, 0x20d0013d, 0x0000002e, 0x00000000 },
+   { 0x00000001, 0x20d4013d, 0x0000002e, 0x00000000 },
+   { 0x00000040, 0x20d80d3d, 0x0000002e, 0x00000001 },
+   { 0x00000040, 0x20dc0d3d, 0x0000002e, 0x00000001 },
+   { 0x00000001, 0x20a0013d, 0x00000030, 0x00000000 },
+   { 0x00000040, 0x20a40d3d, 0x00000030, 0x00000001 },
+   { 0x00000001, 0x20a8013d, 0x00000030, 0x00000000 },
+   { 0x00000040, 0x20ac0d3d, 0x00000030, 0x00000001 },
+   { 0x00000001, 0x20e0013d, 0x00000032, 0x00000000 },
+   { 0x00000001, 0x20e4013d, 0x00000032, 0x00000000 },
+   { 0x00000040, 0x20e80d3d, 0x00000032, 0x00000001 },
+   { 0x00000040, 0x20ec0d3d, 0x00000032, 0x00000001 },
+   { 0x00000001, 0x20b0013d, 0x00000034, 0x00000000 },
+   { 0x00000040, 0x20b40d3d, 0x00000034, 0x00000001 },
+   { 0x00000001, 0x20b8013d, 0x00000034, 0x00000000 },
+   { 0x00000040, 0x20bc0d3d, 0x00000034, 0x00000001 },
+   { 0x00000001, 0x20f0013d, 0x00000036, 0x00000000 },
+   { 0x00000001, 0x20f4013d, 0x00000036, 0x00000000 },
+   { 0x00000040, 0x20f80d3d, 0x00000036, 0x00000001 },
+   { 0x00000040, 0x20fc0d3d, 0x00000036, 0x00000001 },
+   { 0x00600040, 0x208077bd, 0x008d0080, 0x00004020 },
+   { 0x00600040, 0x20a077bd, 0x008d00a0, 0x00004020 },
+   { 0x00600041, 0x208077bd, 0x008d0080, 0x00000060 },
+   { 0x00600041, 0x20a077bd, 0x008d00a0, 0x00000060 },
+   { 0x00600040, 0x208077bd, 0x008d0080, 0x0000006c },
+   { 0x00600040, 0x20a077bd, 0x008d00a0, 0x0000006c },
+   { 0x00600040, 0x20c077bd, 0x008d00c0, 0x00004024 },
+   { 0x00600040, 0x20e077bd, 0x008d00e0, 0x00004024 },
+   { 0x00600041, 0x20c077bd, 0x008d00c0, 0x00000074 },
+   { 0x00600041, 0x20e077bd, 0x008d00e0, 0x00000074 },
+   { 0x00600040, 0x20c077bd, 0x008d00c0, 0x0000007c },
+   { 0x00600040, 0x20e077bd, 0x008d00e0, 0x0000007c },
+   { 0x00600001, 0x202003be, 0x008d0080, 0x00000000 },
+   { 0x00600001, 0x204003be, 0x008d00a0, 0x00000000 },
+   { 0x00600001, 0x206003be, 0x008d00c0, 0x00000000 },
+   { 0x00600001, 0x208003be, 0x008d00e0, 0x00000000 },
+   { 0x00800031, 0x21801d29, 0x008d0000, 0x02580001 },
+   { 0x00600001, 0x22600021, 0x008d0260, 0x00000000 },
+   { 0x00600001, 0x204003be, 0x008d0180, 0x00000000 },
+   { 0x00600001, 0x206003be, 0x008d01c0, 0x00000000 },
+   { 0x00600001, 0x208003be, 0x008d0200, 0x00000000 },
+   { 0x00600001, 0x20a003be, 0x008d0240, 0x00000000 },
+   { 0x00600001, 0x20c003be, 0x008d01a0, 0x00000000 },
+   { 0x00600001, 0x20e003be, 0x008d01e0, 0x00000000 },
+   { 0x00600001, 0x210003be, 0x008d0220, 0x00000000 },
+   { 0x00600001, 0x212003be, 0x008d0260, 0x00000000 },
+   { 0x00600201, 0x20200022, 0x008d0020, 0x00000000 },
+   { 0x00800031, 0x24001d28, 0x008d0000, 0x85a04800 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
diff --git a/src/rotation_wm_prog90.h b/src/rotation_wm_prog90.h
new file mode 100644
index 0000000..9b87750
--- /dev/null
+++ b/src/rotation_wm_prog90.h
@@ -0,0 +1,68 @@
+   { 0x00000001, 0x2080013d, 0x00000028, 0x00000000 },
+   { 0x00000040, 0x20840d3d, 0x00000028, 0x00000001 },
+   { 0x00000001, 0x2088013d, 0x00000028, 0x00000000 },
+   { 0x00000040, 0x208c0d3d, 0x00000028, 0x00000001 },
+   { 0x00000001, 0x20c0013d, 0x0000002a, 0x00000000 },
+   { 0x00000001, 0x20c4013d, 0x0000002a, 0x00000000 },
+   { 0x00000040, 0x20c80d3d, 0x0000002a, 0x00000001 },
+   { 0x00000040, 0x20cc0d3d, 0x0000002a, 0x00000001 },
+   { 0x00000001, 0x2090013d, 0x0000002c, 0x00000000 },
+   { 0x00000040, 0x20940d3d, 0x0000002c, 0x00000001 },
+   { 0x00000001, 0x2098013d, 0x0000002c, 0x00000000 },
+   { 0x00000040, 0x209c0d3d, 0x0000002c, 0x00000001 },
+   { 0x00000001, 0x20d0013d, 0x0000002e, 0x00000000 },
+   { 0x00000001, 0x20d4013d, 0x0000002e, 0x00000000 },
+   { 0x00000040, 0x20d80d3d, 0x0000002e, 0x00000001 },
+   { 0x00000040, 0x20dc0d3d, 0x0000002e, 0x00000001 },
+   { 0x00000001, 0x20a0013d, 0x00000030, 0x00000000 },
+   { 0x00000040, 0x20a40d3d, 0x00000030, 0x00000001 },
+   { 0x00000001, 0x20a8013d, 0x00000030, 0x00000000 },
+   { 0x00000040, 0x20ac0d3d, 0x00000030, 0x00000001 },
+   { 0x00000001, 0x20e0013d, 0x00000032, 0x00000000 },
+   { 0x00000001, 0x20e4013d, 0x00000032, 0x00000000 },
+   { 0x00000040, 0x20e80d3d, 0x00000032, 0x00000001 },
+   { 0x00000040, 0x20ec0d3d, 0x00000032, 0x00000001 },
+   { 0x00000001, 0x20b0013d, 0x00000034, 0x00000000 },
+   { 0x00000040, 0x20b40d3d, 0x00000034, 0x00000001 },
+   { 0x00000001, 0x20b8013d, 0x00000034, 0x00000000 },
+   { 0x00000040, 0x20bc0d3d, 0x00000034, 0x00000001 },
+   { 0x00000001, 0x20f0013d, 0x00000036, 0x00000000 },
+   { 0x00000001, 0x20f4013d, 0x00000036, 0x00000000 },
+   { 0x00000040, 0x20f80d3d, 0x00000036, 0x00000001 },
+   { 0x00000040, 0x20fc0d3d, 0x00000036, 0x00000001 },
+   { 0x00600040, 0x20c077bd, 0x008d00c0, 0x00004024 },
+   { 0x00600040, 0x20e077bd, 0x008d00e0, 0x00004024 },
+   { 0x00600041, 0x20c077bd, 0x008d00c0, 0x00000060 },
+   { 0x00600041, 0x20e077bd, 0x008d00e0, 0x00000060 },
+   { 0x00600040, 0x20c077bd, 0x008d00c0, 0x0000006c },
+   { 0x00600040, 0x20e077bd, 0x008d00e0, 0x0000006c },
+   { 0x00600040, 0x208077bd, 0x008d0080, 0x00004020 },
+   { 0x00600040, 0x20a077bd, 0x008d00a0, 0x00004020 },
+   { 0x00600041, 0x208077bd, 0x008d0080, 0x00000074 },
+   { 0x00600041, 0x20a077bd, 0x008d00a0, 0x00000074 },
+   { 0x00600040, 0x208077bd, 0x008d0080, 0x0000007c },
+   { 0x00600040, 0x20a077bd, 0x008d00a0, 0x0000007c },
+   { 0x00600001, 0x202003be, 0x008d00c0, 0x00000000 },
+   { 0x00600001, 0x204003be, 0x008d00e0, 0x00000000 },
+   { 0x00600001, 0x206003be, 0x008d0080, 0x00000000 },
+   { 0x00600001, 0x208003be, 0x008d00a0, 0x00000000 },
+   { 0x00800031, 0x21801d29, 0x008d0000, 0x02580001 },
+   { 0x00600001, 0x22600021, 0x008d0260, 0x00000000 },
+   { 0x00600001, 0x204003be, 0x008d0180, 0x00000000 },
+   { 0x00600001, 0x206003be, 0x008d01c0, 0x00000000 },
+   { 0x00600001, 0x208003be, 0x008d0200, 0x00000000 },
+   { 0x00600001, 0x20a003be, 0x008d0240, 0x00000000 },
+   { 0x00600001, 0x20c003be, 0x008d01a0, 0x00000000 },
+   { 0x00600001, 0x20e003be, 0x008d01e0, 0x00000000 },
+   { 0x00600001, 0x210003be, 0x008d0220, 0x00000000 },
+   { 0x00600001, 0x212003be, 0x008d0260, 0x00000000 },
+   { 0x00600201, 0x20200022, 0x008d0020, 0x00000000 },
+   { 0x00800031, 0x24001d28, 0x008d0000, 0x85a04800 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
diff-tree 35cebed70827999812f8343ac97ad0dffda20786 (from 33e912aca08fa11ef588eb386e16ba5f9ea13727)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Nov 16 15:12:43 2006 -0800

    [PATCH] Replace broken PCI resource size detection with pciGetBaseSize() call.
    
    Signed-off-by: Keith Packard <keithp at neko.keithp.com>

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 94cba05..6b76d12 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1189,16 +1189,12 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       }
    } else {
       if (IS_I9XX(pI830)) {
-	 if (pI830->PciInfo->memBase[2] & 0x08000000)
-	    pI830->FbMapSize = 0x8000000;	/* 128MB aperture */
-	 else
-	    pI830->FbMapSize = 0x10000000;	/* 256MB aperture */
-
-   	 if (pI830->PciInfo->chipType == PCI_CHIP_E7221_G)
-	    pI830->FbMapSize = 0x8000000;	/* 128MB aperture */
-      } else
-	 /* 128MB aperture for later chips */
+	 pI830->FbMapSize = 1UL << pciGetBaseSize(pI830->PciTag, 2, TRUE,
+						  NULL);
+      } else {
+	 /* 128MB aperture for later i8xx series. */
 	 pI830->FbMapSize = 0x8000000;
+      }
    }
 
    if (pI830->PciInfo->chipType == PCI_CHIP_E7221_G)
diff-tree 33e912aca08fa11ef588eb386e16ba5f9ea13727 (from fa54a3c08301e59558ab0493b3d22324f4162496)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Thu Jan 4 11:25:31 2007 +0800

    [PATCH] Fix EXA mem binding
    
    We should check if EXA is really enabled.
    
    Signed-off-by: Keith Packard <keithp at neko.keithp.com>

diff --git a/src/i830_memory.c b/src/i830_memory.c
index 20e3afb..60257b9 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -841,7 +841,7 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
 		       pI830->Offscreen.Start, pI830->Offscreen.Size/1024);
 	 }
       }
-      if (IS_I965G(pI830)) {
+      if (pI830->useEXA && IS_I965G(pI830)) {
           memset(&(pI830->EXAStateMem), 0, sizeof(I830MemRange));
           pI830->EXAStateMem.Key = -1;
           size = ROUND_TO_PAGE(EXA_LINEAR_EXTRA);
@@ -1513,9 +1513,11 @@ I830FixupOffsets(ScrnInfoPtr pScrn)
    }
 #endif
 #ifdef I830_USE_EXA
-   I830FixOffset(pScrn, &(pI830->Offscreen));
-   if (IS_I965G(pI830))
-       I830FixOffset(pScrn, &(pI830->EXAStateMem));
+   if (pI830->useEXA) {
+       I830FixOffset(pScrn, &(pI830->Offscreen));
+       if (IS_I965G(pI830))
+           I830FixOffset(pScrn, &(pI830->EXAStateMem));
+    }
 #endif
    return TRUE;
 }
@@ -1919,10 +1921,12 @@ I830BindAGPMemory(ScrnInfoPtr pScrn)
       }
 #endif
 #ifdef I830_USE_EXA
-     if (!BindMemRange(pScrn, &(pI830->Offscreen)))
-	return FALSE;
-     if (IS_I965G(pI830) && !BindMemRange(pScrn, &(pI830->EXAStateMem)))
-	return FALSE;
+     if (pI830->useEXA) {
+         if (!BindMemRange(pScrn, &(pI830->Offscreen)))
+	    return FALSE;
+         if (IS_I965G(pI830) && !BindMemRange(pScrn, &(pI830->EXAStateMem)))
+	    return FALSE;
+     }
 #endif
       pI830->GttBound = 1;
    }
diff-tree fa54a3c08301e59558ab0493b3d22324f4162496 (from 2f2c443e971faa54ffcf751b6acb444e8e7875ce)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Dec 6 13:24:44 2006 +0800

    [PATCH] fix Makefile.am
    
    Signed-off-by: Keith Packard <keithp at neko.keithp.com>

diff --git a/src/Makefile.am b/src/Makefile.am
index a9f427d..80cea10 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -94,7 +94,6 @@ i810_drv_la_SOURCES = \
 	 i830_xaa.c \
 	 i830_exa_render.c \
 	 i915_exa_render.c \
-	 i965_composite_wm_nomask.h \
 	 i965_exa_render.c
 
 if HAVE_GEN4ASM
@@ -102,8 +101,14 @@ sf_prog.h: packed_yuv_sf.g4a
 	intel-gen4asm -o sf_prog.h packed_yuv_sf.g4a
 wm_prog.h: packed_yuv_wm.g4a
 	intel-gen4asm -o wm_prog.h packed_yuv_wm.g4a
+exa_sf_prog.h: exa_sf.g4a
+	intel-gen4asm -o exa_sf_prog.h exa_sf.g4a
+exa_sf_mask_prog.h: exa_sf_mask.g4a
+	intel-gen4asm -o exa_sf_mask_prog.h exa_sf_mask.g4a
 exa_wm_nomask_prog.h: exa_wm_nomask.g4a
 	intel-gen4asm -o exa_wm_nomask_prog.h exa_wm_nomask.g4a
+exa_wm_masknoca_prog.h: exa_wm_masknoca.g4a
+	intel-gen4asm -o exa_wm_masknoca_prog.h exa_wm_masknoca.g4a
 endif
 
 if DRI
diff-tree 2f2c443e971faa54ffcf751b6acb444e8e7875ce (from 0bf04fe78a8a915310ef8a90f5c7872be7476e2e)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Dec 6 10:43:29 2006 +0800

    [PATCH] Formats fixes
    
    We should use card_fmt for src/mask picture, and use dest color
    buffer format helper. Also fix wrong name for G965 texture formats,
    and pict_x1r5g5b5 isn't supported by sampler engine.
    
    Signed-off-by: Keith Packard <keithp at neko.keithp.com>

diff --git a/src/i965_exa_render.c b/src/i965_exa_render.c
index 7e9c1e3..583bc26 100644
--- a/src/i965_exa_render.c
+++ b/src/i965_exa_render.c
@@ -121,13 +121,12 @@ static struct blendinfo I965BlendOp[] = 
 
 /* FIXME: surface format defined in brw_defines.h, shared Sampling engine 1.7.2*/
 static struct formatinfo I965TexFormats[] = {
-        {PICT_a8r8g8b8, BRW_SURFACEFORMAT_R8G8B8A8_UNORM },
-        {PICT_x8r8g8b8, BRW_SURFACEFORMAT_R8G8B8X8_UNORM },
-        {PICT_a8b8g8r8, BRW_SURFACEFORMAT_B8G8R8A8_UNORM },
-        {PICT_x8b8g8r8, BRW_SURFACEFORMAT_B8G8R8X8_UNORM },
+        {PICT_a8r8g8b8, BRW_SURFACEFORMAT_B8G8R8A8_UNORM },
+        {PICT_x8r8g8b8, BRW_SURFACEFORMAT_B8G8R8X8_UNORM },
+        {PICT_a8b8g8r8, BRW_SURFACEFORMAT_R8G8B8A8_UNORM },
+        {PICT_x8b8g8r8, BRW_SURFACEFORMAT_R8G8B8X8_UNORM },
         {PICT_r5g6b5,   BRW_SURFACEFORMAT_B5G6R5_UNORM   },
         {PICT_a1r5g5b5, BRW_SURFACEFORMAT_B5G5R5A1_UNORM },
-        {PICT_x1r5g5b5, BRW_SURFACEFORMAT_B5G5R5X1_UNORM },
         {PICT_a8,       BRW_SURFACEFORMAT_A8_UNORM	 },
 };
 
@@ -366,6 +365,16 @@ static const CARD32 ps_kernel_static_mas
 #include "exa_wm_masknoca_prog.h"
 };
 
+static CARD32 i965_get_card_format(PicturePtr pPict) 
+{
+	int i;
+        for (i = 0; i < sizeof(I965TexFormats) / sizeof(I965TexFormats[0]); i++) {
+            if (I965TexFormats[i].fmt == pPict->format)
+                break;
+        }
+	return I965TexFormats[i].card_fmt;
+}
+
 Bool
 I965EXAPrepareComposite(int op, PicturePtr pSrcPicture,
 			PicturePtr pMaskPicture, PicturePtr pDstPicture,
@@ -376,10 +385,7 @@ I965EXAPrepareComposite(int op, PictureP
     CARD32 src_offset, src_pitch;
     CARD32 mask_offset = 0, mask_pitch = 0;
     CARD32 dst_format, dst_offset, dst_pitch;
- 
-ErrorF("i965 prepareComposite\n");
 
-    I965GetDestFormat(pDstPicture, &dst_format);
     src_offset = exaGetPixmapOffset(pSrc);
     src_pitch = exaGetPixmapPitch(pSrc);
     dst_offset = exaGetPixmapOffset(pDst);
@@ -590,11 +596,9 @@ ErrorF("i965 prepareComposite\n");
    memset(dest_surf_state, 0, sizeof(*dest_surf_state));
    dest_surf_state->ss0.surface_type = BRW_SURFACE_2D;
    dest_surf_state->ss0.data_return_format = BRW_SURFACERETURNFORMAT_FLOAT32;
-   if (pDst->drawable.bitsPerPixel == 16) {
-      dest_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B5G6R5_UNORM;
-   } else {
-      dest_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
-   }
+   I965GetDestFormat(pDstPicture, &dst_format);
+   dest_surf_state->ss0.surface_format = dst_format;
+
    dest_surf_state->ss0.writedisable_alpha = 0;
    dest_surf_state->ss0.writedisable_red = 0;
    dest_surf_state->ss0.writedisable_green = 0;
@@ -615,12 +619,7 @@ ErrorF("i965 prepareComposite\n");
    /* Set up the source surface state buffer */
    memset(src_surf_state, 0, sizeof(*src_surf_state));
    src_surf_state->ss0.surface_type = BRW_SURFACE_2D;
-   if (pSrc->drawable.bitsPerPixel == 8)
-      src_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_A8_UNORM; //XXX? 
-   else if (pSrc->drawable.bitsPerPixel == 16)
-      src_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B5G6R5_UNORM;
-   else 
-      src_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
+   src_surf_state->ss0.surface_format = i965_get_card_format(pSrcPicture);
 
    src_surf_state->ss0.writedisable_alpha = 0;
    src_surf_state->ss0.writedisable_red = 0;
@@ -643,12 +642,7 @@ ErrorF("i965 prepareComposite\n");
    if (pMask) {
    	memset(mask_surf_state, 0, sizeof(*mask_surf_state));
 	mask_surf_state->ss0.surface_type = BRW_SURFACE_2D;
-   	if (pMask->drawable.bitsPerPixel == 8)
-      	    mask_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_A8_UNORM; //XXX? 
-   	else if (pMask->drawable.bitsPerPixel == 16)
-      	    mask_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B5G6R5_UNORM;
-   	else 
-      	    mask_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
+   	mask_surf_state->ss0.surface_format = i965_get_card_format(pMaskPicture);
 
    	mask_surf_state->ss0.writedisable_alpha = 0;
    	mask_surf_state->ss0.writedisable_red = 0;
diff-tree 0bf04fe78a8a915310ef8a90f5c7872be7476e2e (from 5c461063cde68092e778c44ac6abd9129cd8019e)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Mon Dec 4 15:48:04 2006 +0800

    [PATCH] set correct default border color
    
    Signed-off-by: Keith Packard <keithp at neko.keithp.com>

diff --git a/src/i965_exa_render.c b/src/i965_exa_render.c
index 2d1ce5f..7e9c1e3 100644
--- a/src/i965_exa_render.c
+++ b/src/i965_exa_render.c
@@ -691,10 +691,10 @@ ErrorF("i965 prepareComposite\n");
    }
 
    memset(default_color_state, 0, sizeof(*default_color_state));
-   default_color_state->color[0] = 1.0; /* RGBA format */
-   default_color_state->color[1] = 0.0; 
-   default_color_state->color[2] = 0.0; 
-   default_color_state->color[3] = 0.0; 
+   default_color_state->color[0] = 0.0; /* R */
+   default_color_state->color[1] = 0.0; /* G */
+   default_color_state->color[2] = 0.0; /* B */
+   default_color_state->color[3] = 1.0; /* A */
 
    src_sampler_state->ss0.default_color_mode = 0; /* GL mode */
 
diff-tree 5c461063cde68092e778c44ac6abd9129cd8019e (from 89a42d489bd370b89e5ff4e01f026b4d64723cd8)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Mon Dec 4 15:47:31 2006 +0800

    [PATCH] fix typo in ps kernel
    
    fix corrupt in some subspans
    
    Signed-off-by: Keith Packard <keithp at neko.keithp.com>

diff --git a/src/exa_wm_masknoca.g4a b/src/exa_wm_masknoca.g4a
index 195203c..c2049fd 100644
--- a/src/exa_wm_masknoca.g4a
+++ b/src/exa_wm_masknoca.g4a
@@ -51,10 +51,10 @@ mov (1) g8.20<1>F g1.14<0,1,0>UW { align
 add (1) g8.24<1>F g1.14<0,1,0>UW 1UB { align1 };
 add (1) g8.28<1>F g1.14<0,1,0>UW 1UB { align1 };
     /* Set up ss2.x coordinates */
-mov (1) g9<1>F g1.16<0,1,0>UW { align1 };
-add (1) g9.4<1>F g1.16<0,1,0>UW 1UB { align1 };
-mov (1) g9.8<1>F g1.16<0,1,0>UW { align1 };
-add (1) g9.12<1>F g1.16<0,1,0>UW 1UB { align1 };
+mov (1) g7<1>F g1.16<0,1,0>UW { align1 };
+add (1) g7.4<1>F g1.16<0,1,0>UW 1UB { align1 };
+mov (1) g7.8<1>F g1.16<0,1,0>UW { align1 };
+add (1) g7.12<1>F g1.16<0,1,0>UW 1UB { align1 };
     /* Set up ss2.y coordinates */
 mov (1) g9<1>F g1.18<0,1,0>UW { align1 };
 mov (1) g9.4<1>F g1.18<0,1,0>UW { align1 };
diff --git a/src/exa_wm_masknoca_prog.h b/src/exa_wm_masknoca_prog.h
index 66eb960..5fcf3b5 100644
--- a/src/exa_wm_masknoca_prog.h
+++ b/src/exa_wm_masknoca_prog.h
@@ -14,10 +14,10 @@
    { 0x00000001, 0x2114013d, 0x0000002e, 0x00000000 },
    { 0x00000040, 0x21180d3d, 0x0000002e, 0x00000001 },
    { 0x00000040, 0x211c0d3d, 0x0000002e, 0x00000001 },
-   { 0x00000001, 0x2120013d, 0x00000030, 0x00000000 },
-   { 0x00000040, 0x21240d3d, 0x00000030, 0x00000001 },
-   { 0x00000001, 0x2128013d, 0x00000030, 0x00000000 },
-   { 0x00000040, 0x212c0d3d, 0x00000030, 0x00000001 },
+   { 0x00000001, 0x20e0013d, 0x00000030, 0x00000000 },
+   { 0x00000040, 0x20e40d3d, 0x00000030, 0x00000001 },
+   { 0x00000001, 0x20e8013d, 0x00000030, 0x00000000 },
+   { 0x00000040, 0x20ec0d3d, 0x00000030, 0x00000001 },
    { 0x00000001, 0x2120013d, 0x00000032, 0x00000000 },
    { 0x00000001, 0x2124013d, 0x00000032, 0x00000000 },
    { 0x00000040, 0x21280d3d, 0x00000032, 0x00000001 },
diff-tree 89a42d489bd370b89e5ff4e01f026b4d64723cd8 (from 01bfa4fa6fc0ceec8581676e5d72c68dd71efa96)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Nov 29 17:16:46 2006 +0800

    [PATCH] shut up warning
    
    Signed-off-by: Keith Packard <keithp at neko.keithp.com>

diff --git a/src/i965_exa_render.c b/src/i965_exa_render.c
index 6f2bc84..2d1ce5f 100644
--- a/src/i965_exa_render.c
+++ b/src/i965_exa_render.c
@@ -1011,10 +1011,8 @@ I965EXAComposite(PixmapPtr pDst, int src
 
     srcXend = srcX + w;
     srcYend = srcY + h;
-    if (pMask) {
-        maskXend = maskX + w;
-        maskYend = maskY + h;
-    }
+    maskXend = maskX + w;
+    maskYend = maskY + h;
     if (is_transform[0]) {
         v.vector[0] = IntToxFixed(srcX);
         v.vector[1] = IntToxFixed(srcY);
diff-tree 01bfa4fa6fc0ceec8581676e5d72c68dd71efa96 (from 79018bb47c43510d59c592592f06204189bd12dc)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Nov 29 17:14:55 2006 +0800

    [PATCH] fix alpha blending state
    
    Signed-off-by: Keith Packard <keithp at neko.keithp.com>

diff --git a/src/i965_exa_render.c b/src/i965_exa_render.c
index c4a3f97..6f2bc84 100644
--- a/src/i965_exa_render.c
+++ b/src/i965_exa_render.c
@@ -562,21 +562,26 @@ ErrorF("i965 prepareComposite\n");
    cc_state->cc0.stencil_enable = 0;   /* disable stencil */
    cc_state->cc2.depth_test = 0;       /* disable depth test */
    cc_state->cc2.logicop_enable = 0;   /* disable logic op */
-   cc_state->cc3.ia_blend_enable = 0;  /* blend alpha just like colors */
+   cc_state->cc3.ia_blend_enable = 1;  /* blend alpha just like colors */
    cc_state->cc3.blend_enable = 1;     /* enable color blend */
    cc_state->cc3.alpha_test = 0;       /* disable alpha test */
    cc_state->cc4.cc_viewport_state_offset = (state_base_offset + cc_viewport_offset) >> 5;
    cc_state->cc5.dither_enable = 0;    /* disable dither */
-//   cc_state->cc5.logicop_func = 0xc;   /* COPY */
-//   cc_state->cc5.statistics_enable = 1;
-//   cc_state->cc5.ia_blend_function = BRW_BLENDFUNCTION_ADD;
-//   cc_state->cc5.ia_src_blend_factor = BRW_BLENDFACTOR_ONE;
-//   cc_state->cc5.ia_dest_blend_factor = BRW_BLENDFACTOR_ONE;
-   cc_state->cc6.blend_function = BRW_BLENDFUNCTION_ADD;
+   cc_state->cc5.logicop_func = 0xc;   /* COPY */
+   cc_state->cc5.statistics_enable = 1;
+   cc_state->cc5.ia_blend_function = BRW_BLENDFUNCTION_ADD;
    I965GetBlendCntl(op, pMaskPicture, pDstPicture->format, 
 		    &src_blend, &dst_blend);
+   /* XXX: alpha blend factor should be same as color, but check
+	   for CA case in future */
+   cc_state->cc5.ia_src_blend_factor = src_blend;
+   cc_state->cc5.ia_dest_blend_factor = dst_blend;
+   cc_state->cc6.blend_function = BRW_BLENDFUNCTION_ADD;
    cc_state->cc6.src_blend_factor = src_blend;
    cc_state->cc6.dest_blend_factor = dst_blend;
+   cc_state->cc6.clamp_post_alpha_blend = 1; 
+   cc_state->cc6.clamp_pre_alpha_blend = 1; 
+   cc_state->cc6.clamp_range = 0;  /* clamp range [0,1] */
 
    /* Upload system kernel */
    memcpy (sip_kernel, sip_kernel_static, sizeof (sip_kernel_static));
diff-tree 79018bb47c43510d59c592592f06204189bd12dc (from a5b9b438469f171b002fa0b99d8cab83e51ec968)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Nov 29 17:05:32 2006 +0800

    [PATCH] Add in sf/wm program for mask picture without CA
    
    Signed-off-by: Keith Packard <keithp at neko.keithp.com>

diff --git a/src/exa_sf_mask.g4a b/src/exa_sf_mask.g4a
new file mode 100644
index 0000000..ab519ce
--- /dev/null
+++ b/src/exa_sf_mask.g4a
@@ -0,0 +1,53 @@
+
+/* FIXME how to setup second coeffient for mask tex coord */
+
+/* 
+   g3 (v0) { u0, v0, 1.0, 1.0 }  ==> {u0, v0, 1.0, 1.0, mu0, mv0, 1.0, 1.0}  Co[0](u0) Co[1](v0) Co[2](mu0) Co[3](mv0)
+   g4 (v1) { u1, v1, 1.0, 1.0 }  ==> {u1, v1, 1.0, 1.0, mu1, mv1, 1.0, 1.0}
+   g5 (v2) { u2, v2 }  ==> (u2, v2, mu2, mv2}
+   g6      { 1/(x1-x0), 1/(y1-y0) }
+   g7      { u1-u0, v1-v0, 0, 0}  ==>{u1-u0, v1-v0,0, 0, mu1-mu0, mv1-mv0, 0, 0}
+	   -> { (u1-u0)/(x1-x0), (v1-v0)/(y1-y0) }  ==>{(u1-u0)/(x1-x0), (v1-v0)/(y1-y0),(mu1-mu0)/(x1-x0), (mv1-mv0)/(y1-y0)
+		Cx,		 Cy 			Cx[0],		 Cy[0],		 Cx[1], 	    Cy[1]
+ */
+
+/* assign Cx[0], Cx[1] to src, same to Cy, Co 
+          Cx[2], Cx[3] to mask, same to Cy, Co */
+
+send (1) 0 g6<1>F g1.12<0,1,0>F math inv scalar mlen 1 rlen 1 { align1 };
+send (1) 0 g6.4<1>F g1.20<0,1,0>F math inv scalar mlen 1 rlen 1 { align1 };
+add (8) g7<1>F g4<8,8,1>F -g3<8,8,1>F { align1 };
+/* Cx[0] */
+mul (1) g7<1>F g7<0,1,0>F g6<0,1,0>F { align1 };
+/* Cy[0] */
+mul (1) g7.4<1>F g7.4<0,1,0>F g6.4<0,1,0>F { align1 };
+/* Cx[2] */
+mul (1) g7.16<1>F g7.16<0,1,0>F g6<0,1,0>F { align1 };
+/* Cy[2] */
+mul (1) g7.20<1>F g7.20<0,1,0>F g6.4<0,1,0>F { align1 };
+
+/* src Cx[0], Cx[1] */
+mov (8) m1<1>F g7<0,1,0>F { align1 };
+/* mask Cx[2], Cx[3] */
+mov (1) m1.8<1>F g7.16<0,1,0>F { align1 };
+mov (1) m1.12<1>F g7.16<0,1,0>F { align1 };
+/* src Cy[0], Cy[1] */
+mov (8) m2<1>F g7.4<0,1,0>F { align1 };
+/* mask Cy[2], Cy[3] */
+mov (1) m2.8<1>F g7.20<0,1,0>F { align1 };
+mov (1) m2.12<1>F g7.20<0,1,0>F { align1 };
+/* src Co[0], Co[1] */
+mov (8) m3<1>F g3<8,8,1>F { align1 };
+/* mask Co[2], Co[3] */
+mov (1) m3.8<1>F g3.16<0,1,0>F { align1 };
+mov (1) m3.12<1>F g3.20<0,1,0>F { align1 };
+
+send (8) 0 null g0<8,8,1>F urb 0 transpose used complete mlen 4 rlen 0 { align1 EOT };
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
diff --git a/src/exa_sf_mask_prog.h b/src/exa_sf_mask_prog.h
new file mode 100644
index 0000000..cd7f460
--- /dev/null
+++ b/src/exa_sf_mask_prog.h
@@ -0,0 +1,25 @@
+   { 0x00000031, 0x20c01fbd, 0x0000002c, 0x01110081 },
+   { 0x00000031, 0x20c41fbd, 0x00000034, 0x01110081 },
+   { 0x00600040, 0x20e077bd, 0x008d0080, 0x008d4060 },
+   { 0x00000041, 0x20e077bd, 0x000000e0, 0x000000c0 },
+   { 0x00000041, 0x20e477bd, 0x000000e4, 0x000000c4 },
+   { 0x00000041, 0x20f077bd, 0x000000f0, 0x000000c0 },
+   { 0x00000041, 0x20f477bd, 0x000000f4, 0x000000c4 },
+   { 0x00600001, 0x202003be, 0x000000e0, 0x00000000 },
+   { 0x00000001, 0x202803be, 0x000000f0, 0x00000000 },
+   { 0x00000001, 0x202c03be, 0x000000f0, 0x00000000 },
+   { 0x00600001, 0x204003be, 0x000000e4, 0x00000000 },
+   { 0x00000001, 0x204803be, 0x000000f4, 0x00000000 },
+   { 0x00000001, 0x204c03be, 0x000000f4, 0x00000000 },
+   { 0x00600001, 0x206003be, 0x008d0060, 0x00000000 },
+   { 0x00000001, 0x206803be, 0x00000070, 0x00000000 },
+   { 0x00000001, 0x206c03be, 0x00000074, 0x00000000 },
+   { 0x00600031, 0x20001fbc, 0x008d0000, 0x8640c800 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
diff --git a/src/exa_wm_masknoca.g4a b/src/exa_wm_masknoca.g4a
new file mode 100644
index 0000000..195203c
--- /dev/null
+++ b/src/exa_wm_masknoca.g4a
@@ -0,0 +1,202 @@
+/*
+ * This's for exa composite operation in no mask picture case.
+ * The simplest case is just sending what src picture has to dst picture.
+ * XXX: This is still experimental, and should be fixed to support multiple texture
+ * map, and conditional mul actions. 
+ */
+
+/* I think this should be same as in g4a program for texture video,
+   as we also use 16-pixel dispatch. and SF scale in g3 is useful for us. */
+
+/* The initial payload of the thread is always g0.
+ * WM_URB (incoming URB entries) is g3
+   As mask texture coeffient needs extra setup urb starting from g4, we should
+   shift this location. 
+
+ * X0_R is g4->g6
+ * X1_R is g5->g7
+ * Y0_R is g6->g8
+ * Y1_R is g7->g9
+
+     * X0: {ss0.x, ss0.x+1, ss0.x,   ss0.x+1, ss1.x, ss1.x+1, ss1.x,   ss1.x+y}
+     * Y0: {ss0.y, ss0.y,   ss0.y+1, ss0.y+1, ss1.y, ss1.y,   ss1.y+1, ss1.y+1}
+     * X1: {ss2.x, ss2.x+1, ss2.x,   ss2.x+1, ss3.x, ss3.x+1, ss3.x,   ss3.x+y}
+     * Y1: {ss2.y, ss2.y,   ss2.y+1, ss2.y+1, ss3.y, ss3.y,   ss3.y+1, ss3.y+1}
+ */
+
+/* multitexture program with src and mask texture */
+/* - load src texture */
+/* - load mask texture */
+/* - mul src.X with mask's alpha */
+/* - write out src.X */
+
+    /* Set up ss0.x coordinates*/
+mov (1) g6<1>F g1.8<0,1,0>UW { align1 };
+add (1) g6.4<1>F g1.8<0,1,0>UW 1UB { align1 };
+mov (1) g6.8<1>F g1.8<0,1,0>UW { align1 };
+add (1) g6.12<1>F g1.8<0,1,0>UW 1UB { align1 };
+    /* Set up ss0.y coordinates */
+mov (1) g8<1>F g1.10<0,1,0>UW { align1 };
+mov (1) g8.4<1>F g1.10<0,1,0>UW { align1 };
+add (1) g8.8<1>F g1.10<0,1,0>UW 1UB { align1 };
+add (1) g8.12<1>F g1.10<0,1,0>UW 1UB { align1 };
+    /* set up ss1.x coordinates */
+mov (1) g6.16<1>F g1.12<0,1,0>UW { align1 };
+add (1) g6.20<1>F g1.12<0,1,0>UW 1UB { align1 };
+mov (1) g6.24<1>F g1.12<0,1,0>UW { align1 };
+add (1) g6.28<1>F g1.12<0,1,0>UW 1UB { align1 };
+    /* set up ss1.y coordinates */
+mov (1) g8.16<1>F g1.14<0,1,0>UW { align1 };
+mov (1) g8.20<1>F g1.14<0,1,0>UW { align1 };
+add (1) g8.24<1>F g1.14<0,1,0>UW 1UB { align1 };
+add (1) g8.28<1>F g1.14<0,1,0>UW 1UB { align1 };
+    /* Set up ss2.x coordinates */
+mov (1) g9<1>F g1.16<0,1,0>UW { align1 };
+add (1) g9.4<1>F g1.16<0,1,0>UW 1UB { align1 };
+mov (1) g9.8<1>F g1.16<0,1,0>UW { align1 };
+add (1) g9.12<1>F g1.16<0,1,0>UW 1UB { align1 };
+    /* Set up ss2.y coordinates */
+mov (1) g9<1>F g1.18<0,1,0>UW { align1 };
+mov (1) g9.4<1>F g1.18<0,1,0>UW { align1 };
+add (1) g9.8<1>F g1.18<0,1,0>UW 1UB { align1 };
+add (1) g9.12<1>F g1.18<0,1,0>UW 1UB { align1 };
+    /* Set up ss3.x coordinates */
+mov (1) g7.16<1>F g1.20<0,1,0>UW { align1 };
+add (1) g7.20<1>F g1.20<0,1,0>UW 1UB { align1 };
+mov (1) g7.24<1>F g1.20<0,1,0>UW { align1 };
+add (1) g7.28<1>F g1.20<0,1,0>UW 1UB { align1 };
+    /* Set up ss3.y coordinates */
+mov (1) g9.16<1>F g1.22<0,1,0>UW { align1 };
+mov (1) g9.20<1>F g1.22<0,1,0>UW { align1 };
+add (1) g9.24<1>F g1.22<0,1,0>UW 1UB { align1 };
+add (1) g9.28<1>F g1.22<0,1,0>UW 1UB { align1 };
+
+    /* Now, map these screen space coordinates into texture coordinates. */
+/* This is for src texture */
+/* I don't want to change origin ssX coords, as it will be used later in mask */
+/* so store tex coords in g10, g11, g12, g13 */
+
+    /* subtract screen-space X origin of vertex 0. */
+add (8) g10<1>F g6<8,8,1>F -g1<0,1,0>F { align1 };
+add (8) g11<1>F g7<8,8,1>F -g1<0,1,0>F { align1 };
+    /* scale by texture X increment */
+/* Cx[0] */
+mul (8) g10<1>F g10<8,8,1>F g3<0,1,0>F { align1 };
+mul (8) g11<1>F g11<8,8,1>F g3<0,1,0>F { align1 };
+    /* add in texture X offset */
+/* Co[0] */
+add (8) g10<1>F g10<8,8,1>F g3.12<0,1,0>F { align1 };
+add (8) g11<1>F g11<8,8,1>F g3.12<0,1,0>F { align1 };
+    /* subtract screen-space Y origin of vertex 0. */
+add (8) g12<1>F g8<8,8,1>F -g1.4<0,1,0>F { align1 };
+add (8) g13<1>F g9<8,8,1>F -g1.4<0,1,0>F { align1 };
+    /* scale by texture Y increment */
+/* Cy[0] */
+mul (8) g12<1>F g12<8,8,1>F g3.4<0,1,0>F { align1 };
+mul (8) g13<1>F g13<8,8,1>F g3.4<0,1,0>F { align1 };
+    /* add in texture Y offset */
+/* Co[1] */
+add (8) g12<1>F g12<8,8,1>F g3.28<0,1,0>F { align1 };
+add (8) g13<1>F g13<8,8,1>F g3.28<0,1,0>F { align1 };
+
+/* prepare sampler read back gX register, which would be written back to output */
+
+/* use simd16 sampler, param 0 is u, param 1 is v. */
+/* 'payload' loading, assuming tex coord start from g4 */
+mov (8) m1<1>F g10<8,8,1>F { align1 };
+mov (8) m2<1>F g11<8,8,1>F { align1 }; /* param 0 u in m1, m2 */
+mov (8) m3<1>F g12<8,8,1>F { align1 };
+mov (8) m4<1>F g13<8,8,1>F { align1 }; /* param 1 v in m3, m4 */
+
+/* m0 will be copied with g0, as it contains send desc */
+/* emit sampler 'send' cmd */
+
+/* src texture readback: g14-g21 */
+send (16) 0 		/* msg reg index */
+	g14<1>UW 	/* readback */
+	g0<8,8,1>UW  	/* copy to msg start reg*/
+	sampler (1,0,F)  /* sampler message description, 
+				(binding_table,sampler_index,datatype). 
+			    here(src->dst) we should use src_sampler and 
+			    src_surface */
+	mlen 5 rlen 8 { align1 };   /* required message len 5, readback len 8 */
+
+mov (8) g21<1>UD g21<8,8,1>UD { align1 };  /* wait sampler return */
+
+/* sampler mask texture, use g10, g11, g12, g13 */
+    /* subtract screen-space X origin of vertex 0. */
+add (8) g10<1>F g6<8,8,1>F -g1<0,1,0>F { align1 };
+add (8) g11<1>F g7<8,8,1>F -g1<0,1,0>F { align1 };
+    /* scale by texture X increment */
+/* Cx[2] */
+mul (8) g10<1>F g10<8,8,1>F g4<0,1,0>F { align1 };
+mul (8) g11<1>F g11<8,8,1>F g4<0,1,0>F { align1 };
+    /* add in texture X offset */
+/* Co[2] */
+add (8) g10<1>F g10<8,8,1>F g4.12<0,1,0>F { align1 };
+add (8) g11<1>F g11<8,8,1>F g4.12<0,1,0>F { align1 };
+    /* subtract screen-space Y origin of vertex 0. */
+add (8) g12<1>F g8<8,8,1>F -g1.4<0,1,0>F { align1 };
+add (8) g13<1>F g9<8,8,1>F -g1.4<0,1,0>F { align1 };
+    /* scale by texture Y increment */
+/* Cy[2] */
+mul (8) g12<1>F g12<8,8,1>F g4.4<0,1,0>F { align1 };
+mul (8) g13<1>F g13<8,8,1>F g4.4<0,1,0>F { align1 };
+    /* add in texture Y offset */
+/* Co[3] */
+add (8) g12<1>F g12<8,8,1>F g4.28<0,1,0>F { align1 };
+add (8) g13<1>F g13<8,8,1>F g4.28<0,1,0>F { align1 };
+
+mov (8) m1<1>F g10<8,8,1>F { align1 };
+mov (8) m2<1>F g11<8,8,1>F { align1 }; 
+mov (8) m3<1>F g12<8,8,1>F { align1 };
+mov (8) m4<1>F g13<8,8,1>F { align1 };
+
+/* mask sampler g22-g29 */
+/* binding_table (2), sampler (1) */
+send (16) 0 g22<1>UW g0<8,8,1>UW sampler (2,1,F) mlen 5 rlen 8 { align1 };
+mov (8) g29<1>UD g29<8,8,1>UD { align1 };  /* wait sampler return */
+
+/* mul mask's alpha channel g28,g29 to src (g14-g21), then write out src */
+mul (8) g14<1>F g14<8,8,1>F g28<8,8,1>F { align1 };
+mul (8) g15<1>F g15<8,8,1>F g29<8,8,1>F { align1 };
+mul (8) g16<1>F g16<8,8,1>F g28<8,8,1>F { align1 };
+mul (8) g17<1>F g17<8,8,1>F g29<8,8,1>F { align1 };
+mul (8) g18<1>F g18<8,8,1>F g28<8,8,1>F { align1 };
+mul (8) g19<1>F g19<8,8,1>F g29<8,8,1>F { align1 };
+mul (8) g20<1>F g20<8,8,1>F g28<8,8,1>F { align1 };
+mul (8) g21<1>F g21<8,8,1>F g29<8,8,1>F { align1 };
+
+/* prepare data in m2-m5 for subspan(1,0), m6-m9 for subspan(3,2), then it's ready to write */
+mov (8) m2<1>F g14<8,8,1>F { align1 };
+mov (8) m3<1>F g16<8,8,1>F { align1 };
+mov (8) m4<1>F g18<8,8,1>F { align1 };
+mov (8) m5<1>F g20<8,8,1>F { align1 };
+mov (8) m6<1>F g15<8,8,1>F { align1 };
+mov (8) m7<1>F g17<8,8,1>F { align1 };
+mov (8) m8<1>F g19<8,8,1>F { align1 };
+mov (8) m9<1>F g21<8,8,1>F { align1 };
+
+/* m0, m1 are all direct passed by PS thread payload */
+mov (8) m1<1>UD g1<8,8,1>UD { align1 mask_disable };
+
+/* write */
+send (16) 0 acc0<1>UW g0<8,8,1>UW write (
+	0,  /* binding_table */
+	8,  /* pixel scordboard clear, msg type simd16 single source */
+	4,  /* render target write */
+	0   /* no write commit message */
+	) 
+	mlen 10
+	rlen 0
+	{ align1 EOT };
+
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
diff --git a/src/exa_wm_masknoca_prog.h b/src/exa_wm_masknoca_prog.h
new file mode 100644
index 0000000..66eb960
--- /dev/null
+++ b/src/exa_wm_masknoca_prog.h
@@ -0,0 +1,95 @@
+   { 0x00000001, 0x20c0013d, 0x00000028, 0x00000000 },
+   { 0x00000040, 0x20c40d3d, 0x00000028, 0x00000001 },
+   { 0x00000001, 0x20c8013d, 0x00000028, 0x00000000 },
+   { 0x00000040, 0x20cc0d3d, 0x00000028, 0x00000001 },
+   { 0x00000001, 0x2100013d, 0x0000002a, 0x00000000 },
+   { 0x00000001, 0x2104013d, 0x0000002a, 0x00000000 },
+   { 0x00000040, 0x21080d3d, 0x0000002a, 0x00000001 },
+   { 0x00000040, 0x210c0d3d, 0x0000002a, 0x00000001 },
+   { 0x00000001, 0x20d0013d, 0x0000002c, 0x00000000 },
+   { 0x00000040, 0x20d40d3d, 0x0000002c, 0x00000001 },
+   { 0x00000001, 0x20d8013d, 0x0000002c, 0x00000000 },
+   { 0x00000040, 0x20dc0d3d, 0x0000002c, 0x00000001 },
+   { 0x00000001, 0x2110013d, 0x0000002e, 0x00000000 },
+   { 0x00000001, 0x2114013d, 0x0000002e, 0x00000000 },
+   { 0x00000040, 0x21180d3d, 0x0000002e, 0x00000001 },
+   { 0x00000040, 0x211c0d3d, 0x0000002e, 0x00000001 },
+   { 0x00000001, 0x2120013d, 0x00000030, 0x00000000 },
+   { 0x00000040, 0x21240d3d, 0x00000030, 0x00000001 },
+   { 0x00000001, 0x2128013d, 0x00000030, 0x00000000 },
+   { 0x00000040, 0x212c0d3d, 0x00000030, 0x00000001 },
+   { 0x00000001, 0x2120013d, 0x00000032, 0x00000000 },
+   { 0x00000001, 0x2124013d, 0x00000032, 0x00000000 },
+   { 0x00000040, 0x21280d3d, 0x00000032, 0x00000001 },
+   { 0x00000040, 0x212c0d3d, 0x00000032, 0x00000001 },
+   { 0x00000001, 0x20f0013d, 0x00000034, 0x00000000 },
+   { 0x00000040, 0x20f40d3d, 0x00000034, 0x00000001 },
+   { 0x00000001, 0x20f8013d, 0x00000034, 0x00000000 },
+   { 0x00000040, 0x20fc0d3d, 0x00000034, 0x00000001 },
+   { 0x00000001, 0x2130013d, 0x00000036, 0x00000000 },
+   { 0x00000001, 0x2134013d, 0x00000036, 0x00000000 },
+   { 0x00000040, 0x21380d3d, 0x00000036, 0x00000001 },
+   { 0x00000040, 0x213c0d3d, 0x00000036, 0x00000001 },
+   { 0x00600040, 0x214077bd, 0x008d00c0, 0x00004020 },
+   { 0x00600040, 0x216077bd, 0x008d00e0, 0x00004020 },
+   { 0x00600041, 0x214077bd, 0x008d0140, 0x00000060 },
+   { 0x00600041, 0x216077bd, 0x008d0160, 0x00000060 },
+   { 0x00600040, 0x214077bd, 0x008d0140, 0x0000006c },
+   { 0x00600040, 0x216077bd, 0x008d0160, 0x0000006c },
+   { 0x00600040, 0x218077bd, 0x008d0100, 0x00004024 },
+   { 0x00600040, 0x21a077bd, 0x008d0120, 0x00004024 },
+   { 0x00600041, 0x218077bd, 0x008d0180, 0x00000064 },
+   { 0x00600041, 0x21a077bd, 0x008d01a0, 0x00000064 },
+   { 0x00600040, 0x218077bd, 0x008d0180, 0x0000007c },
+   { 0x00600040, 0x21a077bd, 0x008d01a0, 0x0000007c },
+   { 0x00600001, 0x202003be, 0x008d0140, 0x00000000 },
+   { 0x00600001, 0x204003be, 0x008d0160, 0x00000000 },
+   { 0x00600001, 0x206003be, 0x008d0180, 0x00000000 },
+   { 0x00600001, 0x208003be, 0x008d01a0, 0x00000000 },
+   { 0x00800031, 0x21c01d29, 0x008d0000, 0x02580001 },
+   { 0x00600001, 0x22a00021, 0x008d02a0, 0x00000000 },
+   { 0x00600040, 0x214077bd, 0x008d00c0, 0x00004020 },
+   { 0x00600040, 0x216077bd, 0x008d00e0, 0x00004020 },
+   { 0x00600041, 0x214077bd, 0x008d0140, 0x00000080 },
+   { 0x00600041, 0x216077bd, 0x008d0160, 0x00000080 },
+   { 0x00600040, 0x214077bd, 0x008d0140, 0x0000008c },
+   { 0x00600040, 0x216077bd, 0x008d0160, 0x0000008c },
+   { 0x00600040, 0x218077bd, 0x008d0100, 0x00004024 },
+   { 0x00600040, 0x21a077bd, 0x008d0120, 0x00004024 },
+   { 0x00600041, 0x218077bd, 0x008d0180, 0x00000084 },
+   { 0x00600041, 0x21a077bd, 0x008d01a0, 0x00000084 },
+   { 0x00600040, 0x218077bd, 0x008d0180, 0x0000009c },
+   { 0x00600040, 0x21a077bd, 0x008d01a0, 0x0000009c },
+   { 0x00600001, 0x202003be, 0x008d0140, 0x00000000 },
+   { 0x00600001, 0x204003be, 0x008d0160, 0x00000000 },
+   { 0x00600001, 0x206003be, 0x008d0180, 0x00000000 },
+   { 0x00600001, 0x208003be, 0x008d01a0, 0x00000000 },
+   { 0x00800031, 0x22c01d29, 0x008d0000, 0x02580102 },
+   { 0x00600001, 0x23a00021, 0x008d03a0, 0x00000000 },
+   { 0x00600041, 0x21c077bd, 0x008d01c0, 0x008d0380 },
+   { 0x00600041, 0x21e077bd, 0x008d01e0, 0x008d03a0 },
+   { 0x00600041, 0x220077bd, 0x008d0200, 0x008d0380 },
+   { 0x00600041, 0x222077bd, 0x008d0220, 0x008d03a0 },
+   { 0x00600041, 0x224077bd, 0x008d0240, 0x008d0380 },
+   { 0x00600041, 0x226077bd, 0x008d0260, 0x008d03a0 },
+   { 0x00600041, 0x228077bd, 0x008d0280, 0x008d0380 },
+   { 0x00600041, 0x22a077bd, 0x008d02a0, 0x008d03a0 },
+   { 0x00600001, 0x204003be, 0x008d01c0, 0x00000000 },
+   { 0x00600001, 0x206003be, 0x008d0200, 0x00000000 },
+   { 0x00600001, 0x208003be, 0x008d0240, 0x00000000 },
+   { 0x00600001, 0x20a003be, 0x008d0280, 0x00000000 },
+   { 0x00600001, 0x20c003be, 0x008d01e0, 0x00000000 },
+   { 0x00600001, 0x20e003be, 0x008d0220, 0x00000000 },
+   { 0x00600001, 0x210003be, 0x008d0260, 0x00000000 },
+   { 0x00600001, 0x212003be, 0x008d02a0, 0x00000000 },
+   { 0x00600201, 0x20200022, 0x008d0020, 0x00000000 },
+   { 0x00800031, 0x24001d28, 0x008d0000, 0x85a04800 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
diff --git a/src/i965_exa_render.c b/src/i965_exa_render.c
index 4bc90c1..c4a3f97 100644
--- a/src/i965_exa_render.c
+++ b/src/i965_exa_render.c
@@ -344,12 +344,16 @@ static const CARD32 sf_kernel_static[][4
 #include "exa_sf_prog.h"
 };
 
+static const CARD32 sf_kernel_static_mask[][4] = {
+#include "exa_sf_mask_prog.h"
+};
+
 /* ps kernels */
 #define PS_KERNEL_NUM_GRF   32
 #define PS_MAX_THREADS	   32
 /* 1: no mask */
 static const CARD32 ps_kernel_static_nomask [][4] = {
-	#include "exa_wm_nomask_prog.h"
+#include "exa_wm_nomask_prog.h"
 };
 
 /* 2: mask with componentAlpha, src * mask color, XXX: later */
@@ -359,7 +363,7 @@ static const CARD32 ps_kernel_static_mas
 
 /* 3: mask without componentAlpha, src * mask alpha */
 static const CARD32 ps_kernel_static_masknoca [][4] = {
-/*#include "i965_composite_wm_masknoca.h" */
+#include "exa_wm_masknoca_prog.h"
 };
 
 Bool
@@ -375,11 +379,6 @@ I965EXAPrepareComposite(int op, PictureP
  
 ErrorF("i965 prepareComposite\n");
 
-    /* FIXME: fallback in pMask for now, would be enable after finish
-	wm kernel program */
-    if (pMask)
-	I830FALLBACK("No mask support yet.\n");
-
     I965GetDestFormat(pDstPicture, &dst_format);
     src_offset = exaGetPixmapOffset(pSrc);
     src_pitch = exaGetPixmapPitch(pSrc);
@@ -436,7 +435,10 @@ ErrorF("i965 prepareComposite\n");
    /* keep current sf_kernel, which will send one setup urb entry to
 	PS kernel */
    sf_kernel_offset = ALIGN(next_offset, 64);
-   next_offset = sf_kernel_offset + sizeof (sf_kernel_static);
+   if (pMask) 
+       next_offset = sf_kernel_offset + sizeof (sf_kernel_static_mask);
+   else
+       next_offset = sf_kernel_offset + sizeof (sf_kernel_static);
 
    //XXX: ps_kernel may be seperated, fix with offset
    ps_kernel_offset = ALIGN(next_offset, 64);
@@ -746,7 +748,10 @@ ErrorF("i965 prepareComposite\n");
     * calculate dA/dx and dA/dy.  Hand these interpolation coefficients
     * back to SF which then hands pixels off to WM.
     */
-   memcpy (sf_kernel, sf_kernel_static, sizeof (sf_kernel_static));
+   if (pMask) 
+       memcpy (sf_kernel, sf_kernel_static_mask, sizeof (sf_kernel_static));
+   else
+       memcpy (sf_kernel, sf_kernel_static, sizeof (sf_kernel_static));
 
    memset(sf_state, 0, sizeof(*sf_state));
    sf_state->thread0.kernel_start_pointer = 
@@ -780,7 +785,6 @@ ErrorF("i965 prepareComposite\n");
    /* Set up the PS kernel (dispatched by WM) 
     */
     
-    // XXX: replace to texture blend shader, and different cases 
    if (pMask) {
 	if (pMaskPicture->componentAlpha)
    	    memcpy (ps_kernel, ps_kernel_static_maskca, sizeof (ps_kernel_static_maskca));
diff-tree a5b9b438469f171b002fa0b99d8cab83e51ec968 (from b7c1e1656f45e43ea2f9a47f1a487050c0884c22)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Nov 29 16:52:44 2006 +0800

    [PATCH] misc cleanup for G965 vs/sf/wm states
    
    Signed-off-by: Keith Packard <keithp at neko.keithp.com>

diff --git a/src/i965_exa_render.c b/src/i965_exa_render.c
index 51b2c60..4bc90c1 100644
--- a/src/i965_exa_render.c
+++ b/src/i965_exa_render.c
@@ -266,6 +266,7 @@ I965EXACheckComposite(int op, PicturePtr
 
 #define ALIGN(i,m)    (((i) + (m) - 1) & ~((m) - 1))
 #define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define BRW_GRF_BLOCKS(nreg)    ((nreg + 15) / 16 - 1)
 
 int urb_vs_start, urb_vs_size;
 int urb_gs_start, urb_gs_size;
@@ -336,9 +337,8 @@ static const CARD32 sip_kernel_static[][
  * with the base texture coordinate. It was extracted from the Mesa driver
  */
 
-#define SF_KERNEL_NUM_GRF  10
-#define SF_KERNEL_NUM_URB  8
-#define SF_MAX_THREADS	   4
+#define SF_KERNEL_NUM_GRF  16
+#define SF_MAX_THREADS	   1
 
 static const CARD32 sf_kernel_static[][4] = {
 #include "exa_sf_prog.h"
@@ -468,7 +468,6 @@ ErrorF("i965 prepareComposite\n");
    next_offset = vb_offset + vb_size;
 
    /* And then the general state: */
-   //XXX: fix for texture map and target surface
    dest_surf_offset = ALIGN(next_offset, 32);
    next_offset = dest_surf_offset + sizeof(*dest_surf_state);
 
@@ -534,8 +533,8 @@ ErrorF("i965 prepareComposite\n");
 #define URB_CLIP_ENTRY_SIZE   0
 #define URB_CLIP_ENTRIES      0
    
-#define URB_SF_ENTRY_SIZE     4
-#define URB_SF_ENTRIES	      8
+#define URB_SF_ENTRY_SIZE     2
+#define URB_SF_ENTRIES	      1
 
    urb_vs_start = 0;
    urb_vs_size = URB_VS_ENTRIES * URB_VS_ENTRY_SIZE;
@@ -564,7 +563,6 @@ ErrorF("i965 prepareComposite\n");
    cc_state->cc3.ia_blend_enable = 0;  /* blend alpha just like colors */
    cc_state->cc3.blend_enable = 1;     /* enable color blend */
    cc_state->cc3.alpha_test = 0;       /* disable alpha test */
-   // XXX:cc_viewport needed? 
    cc_state->cc4.cc_viewport_state_offset = (state_base_offset + cc_viewport_offset) >> 5;
    cc_state->cc5.dither_enable = 0;    /* disable dither */
 //   cc_state->cc5.logicop_func = 0xc;   /* COPY */
@@ -585,7 +583,6 @@ ErrorF("i965 prepareComposite\n");
    memset(dest_surf_state, 0, sizeof(*dest_surf_state));
    dest_surf_state->ss0.surface_type = BRW_SURFACE_2D;
    dest_surf_state->ss0.data_return_format = BRW_SURFACERETURNFORMAT_FLOAT32;
-   // XXX: should compare with picture's cpp?...8 bit surf?
    if (pDst->drawable.bitsPerPixel == 16) {
       dest_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B5G6R5_UNORM;
    } else {
@@ -601,14 +598,12 @@ ErrorF("i965 prepareComposite\n");
    dest_surf_state->ss0.mipmap_layout_mode = 0;
    dest_surf_state->ss0.render_cache_read_mode = 0;
    
-   // XXX: fix to picture address & size
    dest_surf_state->ss1.base_addr = dst_offset;
    dest_surf_state->ss2.height = pDst->drawable.height - 1;
    dest_surf_state->ss2.width = pDst->drawable.width - 1;
    dest_surf_state->ss2.mip_count = 0;
    dest_surf_state->ss2.render_target_rotation = 0;
    dest_surf_state->ss3.pitch = dst_pitch - 1; 
-   // tiled surface?
 
    /* Set up the source surface state buffer */
    memset(src_surf_state, 0, sizeof(*src_surf_state));
@@ -741,8 +736,10 @@ ErrorF("i965 prepareComposite\n");
 
    /* Set up the vertex shader to be disabled (passthrough) */
    memset(vs_state, 0, sizeof(*vs_state));
-   // XXX: vs URB should be defined for VF vertex URB store. done already?
+   vs_state->thread4.nr_urb_entries = URB_VS_ENTRIES;
+   vs_state->thread4.urb_entry_allocation_size = URB_VS_ENTRY_SIZE - 1;
    vs_state->vs6.vs_enable = 0;
+   vs_state->vs6.vert_cache_disable = 1;
 
    // XXX: sf_kernel? keep it as now
    /* Set up the SF kernel to do coord interp: for each attribute,
@@ -754,7 +751,7 @@ ErrorF("i965 prepareComposite\n");
    memset(sf_state, 0, sizeof(*sf_state));
    sf_state->thread0.kernel_start_pointer = 
 	       (state_base_offset + sf_kernel_offset) >> 6;
-   sf_state->thread0.grf_reg_count = ((SF_KERNEL_NUM_GRF & ~15) / 16);
+   sf_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(SF_KERNEL_NUM_GRF);
    sf_state->sf1.single_program_flow = 1;
    sf_state->sf1.binding_table_entry_count = 0;
    sf_state->sf1.thread_priority = 0;
@@ -795,7 +792,7 @@ ErrorF("i965 prepareComposite\n");
    memset (wm_state, 0, sizeof (*wm_state));
    wm_state->thread0.kernel_start_pointer = 
 	    (state_base_offset + ps_kernel_offset) >> 6;
-   wm_state->thread0.grf_reg_count = ((PS_KERNEL_NUM_GRF & ~15) / 16);
+   wm_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(PS_KERNEL_NUM_GRF);
    wm_state->thread1.single_program_flow = 1;
    if (!pMask)
        wm_state->thread1.binding_table_entry_count = 2; /* 1 tex and fb */
@@ -808,7 +805,10 @@ ErrorF("i965 prepareComposite\n");
    // XXX: urb allocation
    wm_state->thread3.const_urb_entry_read_length = 0;
    wm_state->thread3.const_urb_entry_read_offset = 0;
-   wm_state->thread3.urb_entry_read_length = 1;  /* one per pair of attrib */
+   if (pMask)
+       wm_state->thread3.urb_entry_read_length = 2;  /* two per pair of attrib */
+   else 
+       wm_state->thread3.urb_entry_read_length = 1;  /* one per pair of attrib */
    wm_state->thread3.urb_entry_read_offset = 0;
    // wm kernel use urb from 3, see wm_program in compiler module
    wm_state->thread3.dispatch_grf_start_reg = 3; /* must match kernel */
diff-tree b7c1e1656f45e43ea2f9a47f1a487050c0884c22 (from db9cfaa35adaf79ea57bc06b27c7e37935d3e1a7)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Nov 29 16:40:15 2006 +0800

    [PATCH] WM kernel needs scratch space
    
    Signed-off-by: Keith Packard <keithp at neko.keithp.com>

diff --git a/src/i965_exa_render.c b/src/i965_exa_render.c
index 51c2006..51b2c60 100644
--- a/src/i965_exa_render.c
+++ b/src/i965_exa_render.c
@@ -297,6 +297,7 @@ int dest_surf_offset, src_surf_offset, m
 int src_sampler_offset, mask_sampler_offset,vs_offset;
 int sf_offset, wm_offset, cc_offset, vb_offset, cc_viewport_offset;
 int sf_kernel_offset, ps_kernel_offset, sip_kernel_offset;
+int wm_scratch_offset;
 int binding_table_offset;
 int default_color_offset; 
 int next_offset, total_state_size;
@@ -426,6 +427,9 @@ ErrorF("i965 prepareComposite\n");
    wm_offset = ALIGN(next_offset, 32);
    next_offset = wm_offset + sizeof(*wm_state);
     
+   wm_scratch_offset = ALIGN(next_offset, 1024);
+   next_offset = wm_scratch_offset + 1024 * PS_MAX_THREADS;
+
    cc_offset = ALIGN(next_offset, 32);
    next_offset = cc_offset + sizeof(*cc_state);
 
@@ -798,7 +802,8 @@ ErrorF("i965 prepareComposite\n");
    else
        wm_state->thread1.binding_table_entry_count = 3; /* 2 tex and fb */
 
-   wm_state->thread2.scratch_space_base_pointer = 0;
+   wm_state->thread2.scratch_space_base_pointer = (state_base_offset + 
+						   wm_scratch_offset)>>10;
    wm_state->thread2.per_thread_scratch_space = 0;
    // XXX: urb allocation
    wm_state->thread3.const_urb_entry_read_length = 0;
diff-tree db9cfaa35adaf79ea57bc06b27c7e37935d3e1a7 (from 70276e4e9a8a5026ec436d2be5bf5eab868aa178)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Nov 29 16:37:06 2006 +0800

    [PATCH] Setup default border color for our samplers
    
    Signed-off-by: Keith Packard <keithp at neko.keithp.com>

diff --git a/src/i965_exa_render.c b/src/i965_exa_render.c
index 94eabfb..51c2006 100644
--- a/src/i965_exa_render.c
+++ b/src/i965_exa_render.c
@@ -278,6 +278,7 @@ struct brw_surface_state *src_surf_state
 struct brw_surface_state *mask_surf_state;
 struct brw_sampler_state *src_sampler_state;
 struct brw_sampler_state *mask_sampler_state;  
+struct brw_sampler_default_color *default_color_state;
 
 struct brw_vs_unit_state *vs_state;
 struct brw_sf_unit_state *sf_state;
@@ -297,6 +298,7 @@ int src_sampler_offset, mask_sampler_off
 int sf_offset, wm_offset, cc_offset, vb_offset, cc_viewport_offset;
 int sf_kernel_offset, ps_kernel_offset, sip_kernel_offset;
 int binding_table_offset;
+int default_color_offset; 
 int next_offset, total_state_size;
 char *state_base;
 int state_base_offset;
@@ -478,6 +480,9 @@ ErrorF("i965 prepareComposite\n");
    binding_table_offset = ALIGN(next_offset, 32);
    next_offset = binding_table_offset + (binding_table_entries * 4);
 
+   default_color_offset = ALIGN(next_offset, 32);
+   next_offset = default_color_offset + sizeof(*default_color_state);
+
    total_state_size = next_offset;
    assert(total_state_size < EXA_LINEAR_EXTRA);
 
@@ -508,6 +513,8 @@ ErrorF("i965 prepareComposite\n");
 
    vb = (void *)(state_base + vb_offset);
 
+   default_color_state = (void*)(state_base + default_color_offset);
+
    /* Set up a default static partitioning of the URB, which is supposed to
     * allow anything we would want to do, at potentially lower performance.
     */
@@ -541,7 +548,6 @@ ErrorF("i965 prepareComposite\n");
     * here, but we should have synced the 3D engine already in I830PutImage.
     */
 
-// needed?
    memset (cc_viewport, 0, sizeof (*cc_viewport));
    cc_viewport->min_depth = -1.e35;
    cc_viewport->max_depth = 1.e35;
@@ -678,18 +684,25 @@ ErrorF("i965 prepareComposite\n");
 	I830FALLBACK("Bad filter 0x%x\n", pSrcPicture->filter);
    }
 
+   memset(default_color_state, 0, sizeof(*default_color_state));
+   default_color_state->color[0] = 1.0; /* RGBA format */
+   default_color_state->color[1] = 0.0; 
+   default_color_state->color[2] = 0.0; 
+   default_color_state->color[3] = 0.0; 
+
+   src_sampler_state->ss0.default_color_mode = 0; /* GL mode */
+
    if (!pSrcPicture->repeat) {
-	/* XXX: clamp_border and set border to 0 */
-   	src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP; 
-   	src_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
-   	src_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
+   	src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER; 
+   	src_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER;
+   	src_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER;
+	src_sampler_state->ss2.default_color_pointer = 
+			(state_base_offset + default_color_offset) >> 5;
    } else {
    	src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_WRAP; 
    	src_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_WRAP;
    	src_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_WRAP;
    }
-   /* XXX: ss2 has border color pointer, which should be in general state address,
-    	   and just a single texel tex map, with R32G32B32A32_FLOAT */
    src_sampler_state->ss3.chroma_key_enable = 0; /* disable chromakey */
 
    if (pMask) {
@@ -709,17 +722,16 @@ ErrorF("i965 prepareComposite\n");
    	}
 
    	if (!pMaskPicture->repeat) {
-	/* XXX: clamp_border and set border to 0 */
-   	    mask_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP; 
-   	    mask_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
-   	    mask_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
+   	    mask_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER; 
+   	    mask_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER;
+   	    mask_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER;
+            mask_sampler_state->ss2.default_color_pointer = 
+				(state_base_offset + default_color_offset)>>5;
    	} else {
    	    mask_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_WRAP; 
    	    mask_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_WRAP;
    	    mask_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_WRAP;
     	}
-   /* XXX: ss2 has border color pointer, which should be in general state address,
-    	   and just a single texel tex map, with R32G32B32A32_FLOAT */
    	mask_sampler_state->ss3.chroma_key_enable = 0; /* disable chromakey */
    }
 
diff-tree 70276e4e9a8a5026ec436d2be5bf5eab868aa178 (from e8a4cbdeff4125e28d807d0a563efc0606d21a75)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Nov 29 16:30:53 2006 +0800

    [PATCH] fix vertex buffer size
    
    Signed-off-by: Keith Packard <keithp at neko.keithp.com>

diff --git a/src/i965_exa_render.c b/src/i965_exa_render.c
index 9127d65..94eabfb 100644
--- a/src/i965_exa_render.c
+++ b/src/i965_exa_render.c
@@ -233,16 +233,12 @@ Bool
 I965EXACheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
 		      PicturePtr pDstPicture)
 {
-	/* check op*/
-	/* check op with mask's componentAlpha*/
-	/* check textures */
-	/* check dst buffer format */
     CARD32 tmp1;
     
     /* Check for unsupported compositing operations. */
     if (op >= sizeof(I965BlendOp) / sizeof(I965BlendOp[0]))
         I830FALLBACK("Unsupported Composite op 0x%x\n", op);
-                                                                                                                                                            
+
     if (pMaskPicture != NULL && pMaskPicture->componentAlpha) {
         /* Check if it's component alpha that relies on a source alpha and on
          * the source value.  We can only get one of those into the single
@@ -305,7 +301,7 @@ int next_offset, total_state_size;
 char *state_base;
 int state_base_offset;
 float *vb;
-int vb_size = 4 * 4 ; /* 4 DWORDS per vertex, 4 vertices for TRIFAN*/ 
+int vb_size = (4 * 4) * 4 ; /* 4 DWORDS per vertex*/ 
 
 CARD32 src_blend, dst_blend;
 
diff-tree e8a4cbdeff4125e28d807d0a563efc0606d21a75 (from 42534474fd2556e5987205626cca8f30e25855a8)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Nov 29 16:24:24 2006 +0800

    [PATCH] clean up issue cmd to ring buffer
    
    Make it easy to track different part of ring state, and
    use rectlist primitive instead.
    
    Signed-off-by: Keith Packard <keithp at neko.keithp.com>

diff --git a/src/i965_exa_render.c b/src/i965_exa_render.c
index 2c3e43b..9127d65 100644
--- a/src/i965_exa_render.c
+++ b/src/i965_exa_render.c
@@ -376,11 +376,6 @@ I965EXAPrepareComposite(int op, PictureP
  
 ErrorF("i965 prepareComposite\n");
 
-//    i965_3d_pipeline_setup(pScrn);
-//    i965_surf_setup(pScrn, pSrcPicture, pMaskPicture, pDstPicture,
-//   			pSrc, pMask, pDst);
-    // then setup blend, and shader program 
-    
     /* FIXME: fallback in pMask for now, would be enable after finish
 	wm kernel program */
     if (pMask)
@@ -819,62 +814,65 @@ ErrorF("i965 prepareComposite\n");
     * rendering pipe
     */
    {
-   
-   BEGIN_LP_RING((pMask?48:46));
-   // MI_FLUSH prior to PIPELINE_SELECT
-   OUT_RING(MI_FLUSH | 
+	BEGIN_LP_RING(2);
+   	OUT_RING(MI_FLUSH | 
 	    MI_STATE_INSTRUCTION_CACHE_FLUSH |
 	    BRW_MI_GLOBAL_SNAPSHOT_RESET);
+	OUT_RING(MI_NOOP);
+	ADVANCE_LP_RING();
+   }
+   {
+        BEGIN_LP_RING(12);
    
-   /* Match Mesa driver setup */
-   OUT_RING(BRW_PIPELINE_SELECT | PIPELINE_SELECT_3D);
+        /* Match Mesa driver setup */
+        OUT_RING(BRW_PIPELINE_SELECT | PIPELINE_SELECT_3D);
    
+   	OUT_RING(BRW_CS_URB_STATE | 0);
+   	OUT_RING((0 << 4) |  /* URB Entry Allocation Size */
+            (0 << 0));  /* Number of URB Entries */
+
    /* Zero out the two base address registers so all offsets are absolute */
-   // XXX: zero out...
-   OUT_RING(BRW_STATE_BASE_ADDRESS | 4);
-   // why this's not state_base_offset? -> because later we'll always add on
-   // state_base_offset to offset params. see SIP
-   OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* Generate state base address */
-   OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* Surface state base address */
-   OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* media base addr, don't care */
-   OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY);  /* general state max addr, disabled */
-   OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY);  /* media object state max addr, disabled */
+   	OUT_RING(BRW_STATE_BASE_ADDRESS | 4);
+   	OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* Generate state base address */
+   	OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* Surface state base address */
+   	OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* media base addr, don't care */
+   	OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY);  /* general state max addr, disabled */
+   	OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY);  /* media object state max addr, disabled */
 
    /* Set system instruction pointer */
-   OUT_RING(BRW_STATE_SIP | 0);
-   OUT_RING(state_base_offset + sip_kernel_offset); /* system instruction pointer */
-      
+   	OUT_RING(BRW_STATE_SIP | 0);
+   	OUT_RING(state_base_offset + sip_kernel_offset); /* system instruction pointer */
+	OUT_RING(MI_NOOP);
+	ADVANCE_LP_RING();
+   }
+   {
+	BEGIN_LP_RING(26);
    /* Pipe control */
-   // XXX: pipe control write cache before enabling color blending
-   // vol2, geometry pipeline 1.8.4
-   OUT_RING(BRW_PIPE_CONTROL |
+   	OUT_RING(BRW_PIPE_CONTROL |
 	    BRW_PIPE_CONTROL_NOWRITE |
 	    BRW_PIPE_CONTROL_IS_FLUSH |
 	    2);
-   OUT_RING(0);			       /* Destination address */
-   OUT_RING(0);			       /* Immediate data low DW */
-   OUT_RING(0);			       /* Immediate data high DW */
+   	OUT_RING(0);			       /* Destination address */
+   	OUT_RING(0);			       /* Immediate data low DW */
+   	OUT_RING(0);			       /* Immediate data high DW */
 
    /* Binding table pointers */
-   OUT_RING(BRW_3DSTATE_BINDING_TABLE_POINTERS | 4);
-   OUT_RING(0); /* vs */
-   OUT_RING(0); /* gs */
-   OUT_RING(0); /* clip */
-   OUT_RING(0); /* sf */
+   	OUT_RING(BRW_3DSTATE_BINDING_TABLE_POINTERS | 4);
+   	OUT_RING(0); /* vs */
+   	OUT_RING(0); /* gs */
+   	OUT_RING(0); /* clip */
+   	OUT_RING(0); /* sf */
    /* Only the PS uses the binding table */
-   OUT_RING(state_base_offset + binding_table_offset); /* ps */
-
-   //ring 20
+   	OUT_RING(state_base_offset + binding_table_offset); /* ps */
 
    /* The drawing rectangle clipping is always on.  Set it to values that
     * shouldn't do any clipping.
     */
-    //XXX: fix for picture size
-   OUT_RING(BRW_3DSTATE_DRAWING_RECTANGLE | 2);	/* XXX 3 for BLC or CTG */
-   OUT_RING(0x00000000);	/* ymin, xmin */
-   OUT_RING((pScrn->virtualX - 1) |
-	    (pScrn->virtualY - 1) << 16); /* ymax, xmax */
-   OUT_RING(0x00000000);	/* yorigin, xorigin */
+   	OUT_RING(BRW_3DSTATE_DRAWING_RECTANGLE | 2);	/* XXX 3 for BLC or CTG */
+   	OUT_RING(0x00000000);	/* ymin, xmin */
+   	OUT_RING((pScrn->virtualX - 1) |
+ 	         (pScrn->virtualY - 1) << 16); /* ymax, xmax */
+   	OUT_RING(0x00000000);	/* yorigin, xorigin */
 
    /* skip the depth buffer */
    /* skip the polygon stipple */
@@ -882,90 +880,82 @@ ErrorF("i965 prepareComposite\n");
    /* skip the line stipple */
    
    /* Set the pointers to the 3d pipeline state */
-   OUT_RING(BRW_3DSTATE_PIPELINED_POINTERS | 5);
-   OUT_RING(state_base_offset + vs_offset);  /* 32 byte aligned */
-   OUT_RING(BRW_GS_DISABLE);		     /* disable GS, resulting in passthrough */
-   OUT_RING(BRW_CLIP_DISABLE);		     /* disable CLIP, resulting in passthrough */
-   OUT_RING(state_base_offset + sf_offset);  /* 32 byte aligned */
-   OUT_RING(state_base_offset + wm_offset);  /* 32 byte aligned */
-   OUT_RING(state_base_offset + cc_offset);  /* 64 byte aligned */
+   	OUT_RING(BRW_3DSTATE_PIPELINED_POINTERS | 5);
+   	OUT_RING(state_base_offset + vs_offset);  /* 32 byte aligned */
+   	OUT_RING(BRW_GS_DISABLE);		     /* disable GS, resulting in passthrough */
+   	OUT_RING(BRW_CLIP_DISABLE);		     /* disable CLIP, resulting in passthrough */
+   	OUT_RING(state_base_offset + sf_offset);  /* 32 byte aligned */
+   	OUT_RING(state_base_offset + wm_offset);  /* 32 byte aligned */
+   	OUT_RING(state_base_offset + cc_offset);  /* 64 byte aligned */
 
    /* URB fence */
-   // XXX: CS for const URB needed? if not, cs_fence should be equal to sf_fence
-   OUT_RING(BRW_URB_FENCE |
-	    UF0_CS_REALLOC |
-	    UF0_SF_REALLOC |
-	    UF0_CLIP_REALLOC |
-	    UF0_GS_REALLOC |
-	    UF0_VS_REALLOC |
-	    1);
-   OUT_RING(((urb_clip_start + urb_clip_size) << UF1_CLIP_FENCE_SHIFT) |
-	    ((urb_gs_start + urb_gs_size) << UF1_GS_FENCE_SHIFT) |
-	    ((urb_vs_start + urb_vs_size) << UF1_VS_FENCE_SHIFT));
-   OUT_RING(((urb_cs_start + urb_cs_size) << UF2_CS_FENCE_SHIFT) |
-	    ((urb_sf_start + urb_sf_size) << UF2_SF_FENCE_SHIFT));
+   	OUT_RING(BRW_URB_FENCE |
+        	 UF0_CS_REALLOC |
+	    	 UF0_SF_REALLOC |
+	    	 UF0_CLIP_REALLOC |
+	         UF0_GS_REALLOC |
+	         UF0_VS_REALLOC |
+	    	 1);
+   	OUT_RING(((urb_clip_start + urb_clip_size) << UF1_CLIP_FENCE_SHIFT) |
+	    	 ((urb_gs_start + urb_gs_size) << UF1_GS_FENCE_SHIFT) |
+	    	 ((urb_vs_start + urb_vs_size) << UF1_VS_FENCE_SHIFT));
+   	OUT_RING(((urb_cs_start + urb_cs_size) << UF2_CS_FENCE_SHIFT) |
+	     	 ((urb_sf_start + urb_sf_size) << UF2_SF_FENCE_SHIFT));
 
    /* Constant buffer state */
-   // XXX: needed? seems no usage, as we don't have CONSTANT_BUFFER definition
-   OUT_RING(BRW_CS_URB_STATE | 0);
-   OUT_RING(((URB_CS_ENTRY_SIZE - 1) << 4) | /* URB Entry Allocation Size */
-	    (URB_CS_ENTRIES << 0));	     /* Number of URB Entries */
-   
+   	OUT_RING(BRW_CS_URB_STATE | 0);
+   	OUT_RING(((URB_CS_ENTRY_SIZE - 1) << 4) | /* URB Entry Allocation Size */
+	    	 (URB_CS_ENTRIES << 0));	     /* Number of URB Entries */
+	ADVANCE_LP_RING();
+   }
+   {
+        int nelem = pMask ? 3: 2;
+   	BEGIN_LP_RING(pMask?12:10);
    /* Set up the pointer to our vertex buffer */
-   // XXX: double check
-  // int vb_pitch = 4 * 4;  // XXX: pitch should include mask's coords? possible
-  // all three coords on one row?
-   int nelem = pMask ? 3: 2;
-   OUT_RING(BRW_3DSTATE_VERTEX_BUFFERS | 3); //XXX: should be 4n-1 -> 3
-   OUT_RING((0 << VB0_BUFFER_INDEX_SHIFT) |
-	    VB0_VERTEXDATA |
-	    ((4 * 2 * nelem) << VB0_BUFFER_PITCH_SHIFT)); 
-   		// pitch includes all vertex data, 4bytes for 1 dword, each
-		// element has 2 coords (x,y)(s0,t0), nelem to reflect possible
-		// mask
-   OUT_RING(state_base_offset + vb_offset);
-   OUT_RING(4 * nelem); // max index, prim has 4 coords
-   OUT_RING(0); // ignore for VERTEXDATA, but still there
+   	OUT_RING(BRW_3DSTATE_VERTEX_BUFFERS | 3); 
+   	OUT_RING((0 << VB0_BUFFER_INDEX_SHIFT) |
+	    	 VB0_VERTEXDATA |
+	    	 ((4 * 2 * nelem) << VB0_BUFFER_PITCH_SHIFT)); 
+   	OUT_RING(state_base_offset + vb_offset);
+   	OUT_RING(2); // max index, prim has 4 coords
+   	OUT_RING(0); // ignore for VERTEXDATA, but still there
 
    /* Set up our vertex elements, sourced from the single vertex buffer. */
-   OUT_RING(BRW_3DSTATE_VERTEX_ELEMENTS | ((2 * nelem) - 1));  // XXX: 2n-1, (x,y) + (s0,t0) +
-						//   possible (s1, t1)
+   	OUT_RING(BRW_3DSTATE_VERTEX_ELEMENTS | ((2 * nelem) - 1));  
    /* offset 0: X,Y -> {X, Y, 1.0, 1.0} */
-   OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
-	    VE0_VALID |
-	    (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
-	    (0 << VE0_OFFSET_SHIFT));
-   OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
-	    (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
-	    (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
-	    (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
-	    (0 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
+   	OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
+	    	 VE0_VALID |
+	    	 (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
+	    	 (0 << VE0_OFFSET_SHIFT));
+   	OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
+	    	 (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
+	     	 (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
+	    	 (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
+	    	 (0 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
    /* offset 8: S0, T0 -> {S0, T0, 1.0, 1.0} */
-   OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
-	    VE0_VALID |
-	    (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
-	    (8 << VE0_OFFSET_SHIFT));
-   OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
-	    (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
-	    (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
-	    (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
-	    (4 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
-
-   if (pMask) {
    	OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
-	    VE0_VALID |
-	    (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
-	    (16 << VE0_OFFSET_SHIFT));
-	OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
-	    (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
-	    (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
-	    (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
-	    (8 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); 
-		//XXX: is this has alignment issue? and thread access problem?
-   }
+	    	 VE0_VALID |
+	    	 (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
+	    	 (8 << VE0_OFFSET_SHIFT));
+   	OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
+	    	 (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
+	    	 (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
+	     	 (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
+	    	 (4 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
+
+   	if (pMask) {
+   		OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
+	    		 VE0_VALID |
+	    		 (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
+	    		 (16 << VE0_OFFSET_SHIFT));
+		OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
+	    		 (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
+	    		 (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
+	    		 (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
+	    		 (8 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); 
+   	}
    
-   ADVANCE_LP_RING();
-    
+   	ADVANCE_LP_RING();
    }
 
 #ifdef I830DEBUG
@@ -983,7 +973,7 @@ I965EXAComposite(PixmapPtr pDst, int src
     I830Ptr pI830 = I830PTR(pScrn);
     int srcXend, srcYend, maskXend, maskYend;
     PictVector v;
-    int pMask = 1, i = 0;
+    int pMask = 1, i;
 
     DPRINTF(PFX, "Composite: srcX %d, srcY %d\n\t maskX %d, maskY %d\n\t"
 	    "dstX %d, dstY %d\n\twidth %d, height %d\n\t"
@@ -999,8 +989,10 @@ I965EXAComposite(PixmapPtr pDst, int src
 
     srcXend = srcX + w;
     srcYend = srcY + h;
-    maskXend = maskX + w;
-    maskYend = maskY + h;
+    if (pMask) {
+        maskXend = maskX + w;
+        maskYend = maskY + h;
+    }
     if (is_transform[0]) {
         v.vector[0] = IntToxFixed(srcX);
         v.vector[1] = IntToxFixed(srcY);
@@ -1035,51 +1027,45 @@ I965EXAComposite(PixmapPtr pDst, int src
 		"dstX %d, dstY %d\n", srcX, srcY, srcXend, srcYend,
 		maskX, maskY, maskXend, maskYend, dstX, dstY);
 
- 
-    vb[i++] = (float)dstX;
-    vb[i++] = (float)dstY;
-    vb[i++] = (float)srcX / scale_units[0][0];
-    vb[i++] = (float)srcY / scale_units[0][1];
-    if (pMask) {
-        vb[i++] = (float)maskX / scale_units[1][0];
-        vb[i++] = (float)maskY / scale_units[1][1];
-    }
-
-    vb[i++] = (float)dstX;
-    vb[i++] = (float)(dstY + h);
-    vb[i++] = (float)srcX / scale_units[0][0];
-    vb[i++] = (float)srcYend / scale_units[0][1];
+    i = 0;
+    /* rect (x2,y2) */
+    vb[i++] = (float)(srcXend) / scale_units[0][0];
+    vb[i++] = (float)(srcYend) / scale_units[0][1];
     if (pMask) {
-        vb[i++] = (float)maskX / scale_units[1][0];
+        vb[i++] = (float)maskXend / scale_units[1][0];
         vb[i++] = (float)maskYend / scale_units[1][1];
     }
-
     vb[i++] = (float)(dstX + w);
     vb[i++] = (float)(dstY + h);
-    vb[i++] = (float)srcXend / scale_units[0][0];
-    vb[i++] = (float)srcYend / scale_units[0][1];
+
+    /* rect (x1,y2) */
+    vb[i++] = (float)(srcX)/ scale_units[0][0];
+    vb[i++] = (float)(srcYend)/ scale_units[0][1];
     if (pMask) {
-        vb[i++] = (float)maskXend / scale_units[1][0];
+        vb[i++] = (float)maskX / scale_units[1][0];
         vb[i++] = (float)maskYend / scale_units[1][1];
     }
+    vb[i++] = (float)dstX;
+    vb[i++] = (float)(dstY + h);
 
-    vb[i++] = (float)(dstX + w);
-    vb[i++] = (float)dstY;
-    vb[i++] = (float)srcXend / scale_units[0][0];
-    vb[i++] = (float)srcY / scale_units[0][1];
+    /* rect (x1,y1) */
+    vb[i++] = (float)(srcX) / scale_units[0][0];
+    vb[i++] = (float)(srcY) / scale_units[0][1];
     if (pMask) {
-        vb[i++] = (float)maskXend / scale_units[1][0];
+        vb[i++] = (float)maskX / scale_units[1][0];
         vb[i++] = (float)maskY / scale_units[1][1];
     }
-
+    vb[i++] = (float)dstX;
+    vb[i++] = (float)dstY;
+   
     {
       BEGIN_LP_RING(6);
       OUT_RING(BRW_3DPRIMITIVE | 
 	       BRW_3DPRIMITIVE_VERTEX_SEQUENTIAL |
-	       (_3DPRIM_TRIFAN << BRW_3DPRIMITIVE_TOPOLOGY_SHIFT) | 
+	       (_3DPRIM_RECTLIST << BRW_3DPRIMITIVE_TOPOLOGY_SHIFT) | 
 	       (0 << 9) |  /* CTG - indirect vertex count */
 	       4);
-      OUT_RING(4);  /* vertex count per instance */
+      OUT_RING(3);  /* vertex count per instance */
       OUT_RING(0); /* start vertex offset */
       OUT_RING(1); /* single instance */
       OUT_RING(0); /* start instance location */
@@ -1090,4 +1076,19 @@ I965EXAComposite(PixmapPtr pDst, int src
     ErrorF("sync after 3dprimitive");
     I830Sync(pScrn);
 #endif
+    /* we must be sure that the pipeline is flushed before next exa draw,
+       because that will be new state, binding state and instructions*/
+    {
+	BEGIN_LP_RING(4);
+   	OUT_RING(BRW_PIPE_CONTROL |
+	    BRW_PIPE_CONTROL_NOWRITE |
+	    BRW_PIPE_CONTROL_WC_FLUSH |
+	    BRW_PIPE_CONTROL_IS_FLUSH |
+	    (1 << 10) |  /* XXX texture cache flush for BLC/CTG */
+	    2);
+   	OUT_RING(0); /* Destination address */
+   	OUT_RING(0); /* Immediate data low DW */
+   	OUT_RING(0); /* Immediate data high DW */
+	ADVANCE_LP_RING();
+    }
 }
diff-tree 42534474fd2556e5987205626cca8f30e25855a8 (from 05e8a7989db1b8b9dfa7b688629af65d9910cc53)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Nov 29 16:04:16 2006 +0800

    [PATCH] remove wrong scale_units
    
    Signed-off-by: Keith Packard <keithp at neko.keithp.com>

diff --git a/src/i965_exa_render.c b/src/i965_exa_render.c
index 2751778..2c3e43b 100644
--- a/src/i965_exa_render.c
+++ b/src/i965_exa_render.c
@@ -397,8 +397,6 @@ ErrorF("i965 prepareComposite\n");
     }
     scale_units[0][0] = pSrc->drawable.width;
     scale_units[0][1] = pSrc->drawable.height;
-    scale_units[2][0] = pDst->drawable.width;
-    scale_units[2][1] = pDst->drawable.height;
 
     if (pSrcPicture->transform) {
 	is_transform[0] = TRUE;
diff-tree 05e8a7989db1b8b9dfa7b688629af65d9910cc53 (from 1329c86f2a4b3664920ded970a984a745a530da4)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Nov 29 16:02:16 2006 +0800

    [PATCH] Rename exa sf/wm program files
    
    Also fix some minors in wm program.
    
    Signed-off-by: Keith Packard <keithp at neko.keithp.com>

diff --git a/src/Makefile.am b/src/Makefile.am
index 54e5657..a9f427d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -102,8 +102,8 @@ sf_prog.h: packed_yuv_sf.g4a
 	intel-gen4asm -o sf_prog.h packed_yuv_sf.g4a
 wm_prog.h: packed_yuv_wm.g4a
 	intel-gen4asm -o wm_prog.h packed_yuv_wm.g4a
-i965_composite_wm_nomask.h: i965_composite_wm_nomask.g4a
-	intel-gen4asm -o i965_composite_wm_nomask.h i965_composite_wm_nomask.g4a
+exa_wm_nomask_prog.h: exa_wm_nomask.g4a
+	intel-gen4asm -o exa_wm_nomask_prog.h exa_wm_nomask.g4a
 endif
 
 if DRI
diff --git a/src/exa_sf.g4a b/src/exa_sf.g4a
new file mode 100644
index 0000000..8c1398f
--- /dev/null
+++ b/src/exa_sf.g4a
@@ -0,0 +1,17 @@
+send (1) 0 g6<1>F g1.12<0,1,0>F math inv scalar mlen 1 rlen 1 { align1 };
+send (1) 0 g6.4<1>F g1.20<0,1,0>F math inv scalar mlen 1 rlen 1 { align1 };
+add (8) g7<1>F g4<8,8,1>F -g3<8,8,1>F { align1 };
+mul (1) g7<1>F g7<0,1,0>F g6<0,1,0>F { align1 };
+mul (1) g7.4<1>F g7.4<0,1,0>F g6.4<0,1,0>F { align1 };
+mov (8) m1<1>F g7<0,1,0>F { align1 };
+mov (8) m2<1>F g7.4<0,1,0>F { align1 };
+mov (8) m3<1>F g3<8,8,1>F { align1 };
+send (8) 0 null g0<8,8,1>F urb 0 transpose used complete mlen 4 rlen 0 { align1 EOT };
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
diff --git a/src/exa_sf_prog.h b/src/exa_sf_prog.h
new file mode 100644
index 0000000..830d176
--- /dev/null
+++ b/src/exa_sf_prog.h
@@ -0,0 +1,17 @@
+   { 0x00000031, 0x20c01fbd, 0x0000002c, 0x01110081 },
+   { 0x00000031, 0x20c41fbd, 0x00000034, 0x01110081 },
+   { 0x00600040, 0x20e077bd, 0x008d0080, 0x008d4060 },
+   { 0x00000041, 0x20e077bd, 0x000000e0, 0x000000c0 },
+   { 0x00000041, 0x20e477bd, 0x000000e4, 0x000000c4 },
+   { 0x00600001, 0x202003be, 0x000000e0, 0x00000000 },
+   { 0x00600001, 0x204003be, 0x000000e4, 0x00000000 },
+   { 0x00600001, 0x206003be, 0x008d0060, 0x00000000 },
+   { 0x00600031, 0x20001fbc, 0x008d0000, 0x8640c800 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
diff --git a/src/exa_wm_nomask.g4a b/src/exa_wm_nomask.g4a
new file mode 100644
index 0000000..8e851a3
--- /dev/null
+++ b/src/exa_wm_nomask.g4a
@@ -0,0 +1,143 @@
+/*
+ * This's for exa composite operation in no mask picture case.
+ * The simplest case is just sending what src picture has to dst picture.
+ */
+
+/* I think this should be same as in g4a program for texture video,
+   as we also use 16-pixel dispatch. and SF scale in g3 is useful for us. */
+
+/* The initial payload of the thread is always g0.
+ * WM_URB (incoming URB entries) is g3
+ * X0_R is g4
+ * X1_R is g5
+ * Y0_R is g6
+ * Y1_R is g7
+ */
+
+    /* Set up ss0.x coordinates*/
+mov (1) g4<1>F g1.8<0,1,0>UW { align1 };
+add (1) g4.4<1>F g1.8<0,1,0>UW 1UB { align1 };
+mov (1) g4.8<1>F g1.8<0,1,0>UW { align1 };
+add (1) g4.12<1>F g1.8<0,1,0>UW 1UB { align1 };
+    /* Set up ss0.y coordinates */
+mov (1) g6<1>F g1.10<0,1,0>UW { align1 };
+mov (1) g6.4<1>F g1.10<0,1,0>UW { align1 };
+add (1) g6.8<1>F g1.10<0,1,0>UW 1UB { align1 };
+add (1) g6.12<1>F g1.10<0,1,0>UW 1UB { align1 };
+    /* set up ss1.x coordinates */
+mov (1) g4.16<1>F g1.12<0,1,0>UW { align1 };
+add (1) g4.20<1>F g1.12<0,1,0>UW 1UB { align1 };
+mov (1) g4.24<1>F g1.12<0,1,0>UW { align1 };
+add (1) g4.28<1>F g1.12<0,1,0>UW 1UB { align1 };
+    /* set up ss1.y coordinates */
+mov (1) g6.16<1>F g1.14<0,1,0>UW { align1 };
+mov (1) g6.20<1>F g1.14<0,1,0>UW { align1 };
+add (1) g6.24<1>F g1.14<0,1,0>UW 1UB { align1 };
+add (1) g6.28<1>F g1.14<0,1,0>UW 1UB { align1 };
+    /* Set up ss2.x coordinates */
+mov (1) g5<1>F g1.16<0,1,0>UW { align1 };
+add (1) g5.4<1>F g1.16<0,1,0>UW 1UB { align1 };
+mov (1) g5.8<1>F g1.16<0,1,0>UW { align1 };
+add (1) g5.12<1>F g1.16<0,1,0>UW 1UB { align1 };
+    /* Set up ss2.y coordinates */
+mov (1) g7<1>F g1.18<0,1,0>UW { align1 };
+mov (1) g7.4<1>F g1.18<0,1,0>UW { align1 };
+add (1) g7.8<1>F g1.18<0,1,0>UW 1UB { align1 };
+add (1) g7.12<1>F g1.18<0,1,0>UW 1UB { align1 };
+    /* Set up ss3.x coordinates */
+mov (1) g5.16<1>F g1.20<0,1,0>UW { align1 };
+add (1) g5.20<1>F g1.20<0,1,0>UW 1UB { align1 };
+mov (1) g5.24<1>F g1.20<0,1,0>UW { align1 };
+add (1) g5.28<1>F g1.20<0,1,0>UW 1UB { align1 };
+    /* Set up ss3.y coordinates */
+mov (1) g7.16<1>F g1.22<0,1,0>UW { align1 };
+mov (1) g7.20<1>F g1.22<0,1,0>UW { align1 };
+add (1) g7.24<1>F g1.22<0,1,0>UW 1UB { align1 };
+add (1) g7.28<1>F g1.22<0,1,0>UW 1UB { align1 };
+
+    /* Now, map these screen space coordinates into texture coordinates. */
+    /* subtract screen-space X origin of vertex 0. */
+add (8) g4<1>F g4<8,8,1>F -g1<0,1,0>F { align1 };
+add (8) g5<1>F g5<8,8,1>F -g1<0,1,0>F { align1 };
+    /* scale by texture X increment */
+mul (8) g4<1>F g4<8,8,1>F g3<0,1,0>F { align1 };
+mul (8) g5<1>F g5<8,8,1>F g3<0,1,0>F { align1 };
+    /* add in texture X offset */
+add (8) g4<1>F g4<8,8,1>F g3.12<0,1,0>F { align1 };
+add (8) g5<1>F g5<8,8,1>F g3.12<0,1,0>F { align1 };
+    /* subtract screen-space Y origin of vertex 0. */
+add (8) g6<1>F g6<8,8,1>F -g1.4<0,1,0>F { align1 };
+add (8) g7<1>F g7<8,8,1>F -g1.4<0,1,0>F { align1 };
+    /* scale by texture Y increment */
+mul (8) g6<1>F g6<8,8,1>F g3.20<0,1,0>F { align1 };
+mul (8) g7<1>F g7<8,8,1>F g3.20<0,1,0>F { align1 };
+    /* add in texture Y offset */
+add (8) g6<1>F g6<8,8,1>F g3.28<0,1,0>F { align1 };
+add (8) g7<1>F g7<8,8,1>F g3.28<0,1,0>F { align1 };
+
+/* prepare sampler read back gX register, which would be written back to output */
+
+/* use simd16 sampler, param 0 is u, param 1 is v. */
+/* 'payload' loading, assuming tex coord start from g4 */
+mov (8) m1<1>F g4<8,8,1>F { align1 };
+mov (8) m2<1>F g5<8,8,1>F { align1 };  /* param 0 u in m1, m2 */
+mov (8) m3<1>F g6<8,8,1>F { align1 };
+mov (8) m4<1>F g7<8,8,1>F { align1 };  /* param 1 v in m3, m4 */
+
+/* m0 will be copied with g0, as it contains send desc */
+/* emit sampler 'send' cmd */
+send (16) 0 		/* msg reg index */
+	g12<1>UW 	/* readback */
+	g0<8,8,1>UW  	/* copy to msg start reg*/
+	sampler (1,0,F)  /* sampler message description, (binding_table,sampler_index,datatype)
+			 /* here(src->dst) we should use src_sampler and src_surface */
+	mlen 5 rlen 8 { align1 };   /* required message len 5, readback len 8 */
+
+mov (8) g19<1>UD g19<8,8,1>UD { align1 };  /* wait sampler return */
+/* if we set up read-back reg correctly, emit dataport write 'send' cmd with EOT */
+
+/* m0, m1 are all direct passed by PS thread payload */
+mov (8) m1<1>F g1<8,8,1>F { align1 };
+
+/* prepare data in m2-m5 for subspan(1,0), m6-m9 for subspan(3,2), then it's ready to write */
+/* g12 -> m2
+   g13 -> m6
+   g14 -> m3
+   g15 -> m7
+   g16 -> m4
+   g17 -> m8
+   g18 -> m5
+   g19 -> m9
+*/
+mov (8) m2<1>F g12<8,8,1>F { align1 };
+mov (8) m3<1>F g14<8,8,1>F { align1 };
+mov (8) m4<1>F g16<8,8,1>F { align1 };
+mov (8) m5<1>F g18<8,8,1>F { align1 };
+mov (8) m6<1>F g13<8,8,1>F { align1 };
+mov (8) m7<1>F g15<8,8,1>F { align1 };
+mov (8) m8<1>F g17<8,8,1>F { align1 };
+mov (8) m9<1>F g19<8,8,1>F { align1 };
+
+/* m0, m1 are all direct passed by PS thread payload */
+mov (8) m1<1>UD g1<8,8,1>UD { align1 mask_disable };
+
+/* write */
+send (16) 0 acc0<1>UW g0<8,8,1>UW write (
+	0,  /* binding_table */
+	8,  /* pixel scordboard clear, msg type simd16 single source */
+	4,  /* render target write */
+	0   /* no write commit message */
+	) 
+	mlen 10
+	rlen 0
+	{ align1 EOT };
+
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
diff --git a/src/exa_wm_nomask_prog.h b/src/exa_wm_nomask_prog.h
new file mode 100644
index 0000000..7870b3b
--- /dev/null
+++ b/src/exa_wm_nomask_prog.h
@@ -0,0 +1,70 @@
+   { 0x00000001, 0x2080013d, 0x00000028, 0x00000000 },
+   { 0x00000040, 0x20840d3d, 0x00000028, 0x00000001 },
+   { 0x00000001, 0x2088013d, 0x00000028, 0x00000000 },
+   { 0x00000040, 0x208c0d3d, 0x00000028, 0x00000001 },
+   { 0x00000001, 0x20c0013d, 0x0000002a, 0x00000000 },
+   { 0x00000001, 0x20c4013d, 0x0000002a, 0x00000000 },
+   { 0x00000040, 0x20c80d3d, 0x0000002a, 0x00000001 },
+   { 0x00000040, 0x20cc0d3d, 0x0000002a, 0x00000001 },
+   { 0x00000001, 0x2090013d, 0x0000002c, 0x00000000 },
+   { 0x00000040, 0x20940d3d, 0x0000002c, 0x00000001 },
+   { 0x00000001, 0x2098013d, 0x0000002c, 0x00000000 },
+   { 0x00000040, 0x209c0d3d, 0x0000002c, 0x00000001 },
+   { 0x00000001, 0x20d0013d, 0x0000002e, 0x00000000 },
+   { 0x00000001, 0x20d4013d, 0x0000002e, 0x00000000 },
+   { 0x00000040, 0x20d80d3d, 0x0000002e, 0x00000001 },
+   { 0x00000040, 0x20dc0d3d, 0x0000002e, 0x00000001 },
+   { 0x00000001, 0x20a0013d, 0x00000030, 0x00000000 },
+   { 0x00000040, 0x20a40d3d, 0x00000030, 0x00000001 },
+   { 0x00000001, 0x20a8013d, 0x00000030, 0x00000000 },
+   { 0x00000040, 0x20ac0d3d, 0x00000030, 0x00000001 },
+   { 0x00000001, 0x20e0013d, 0x00000032, 0x00000000 },
+   { 0x00000001, 0x20e4013d, 0x00000032, 0x00000000 },
+   { 0x00000040, 0x20e80d3d, 0x00000032, 0x00000001 },
+   { 0x00000040, 0x20ec0d3d, 0x00000032, 0x00000001 },
+   { 0x00000001, 0x20b0013d, 0x00000034, 0x00000000 },
+   { 0x00000040, 0x20b40d3d, 0x00000034, 0x00000001 },
+   { 0x00000001, 0x20b8013d, 0x00000034, 0x00000000 },
+   { 0x00000040, 0x20bc0d3d, 0x00000034, 0x00000001 },
+   { 0x00000001, 0x20f0013d, 0x00000036, 0x00000000 },
+   { 0x00000001, 0x20f4013d, 0x00000036, 0x00000000 },
+   { 0x00000040, 0x20f80d3d, 0x00000036, 0x00000001 },
+   { 0x00000040, 0x20fc0d3d, 0x00000036, 0x00000001 },
+   { 0x00600040, 0x208077bd, 0x008d0080, 0x00004020 },
+   { 0x00600040, 0x20a077bd, 0x008d00a0, 0x00004020 },
+   { 0x00600041, 0x208077bd, 0x008d0080, 0x00000060 },
+   { 0x00600041, 0x20a077bd, 0x008d00a0, 0x00000060 },
+   { 0x00600040, 0x208077bd, 0x008d0080, 0x0000006c },
+   { 0x00600040, 0x20a077bd, 0x008d00a0, 0x0000006c },
+   { 0x00600040, 0x20c077bd, 0x008d00c0, 0x00004024 },
+   { 0x00600040, 0x20e077bd, 0x008d00e0, 0x00004024 },
+   { 0x00600041, 0x20c077bd, 0x008d00c0, 0x00000074 },
+   { 0x00600041, 0x20e077bd, 0x008d00e0, 0x00000074 },
+   { 0x00600040, 0x20c077bd, 0x008d00c0, 0x0000007c },
+   { 0x00600040, 0x20e077bd, 0x008d00e0, 0x0000007c },
+   { 0x00600001, 0x202003be, 0x008d0080, 0x00000000 },
+   { 0x00600001, 0x204003be, 0x008d00a0, 0x00000000 },
+   { 0x00600001, 0x206003be, 0x008d00c0, 0x00000000 },
+   { 0x00600001, 0x208003be, 0x008d00e0, 0x00000000 },
+   { 0x00800031, 0x21801d29, 0x008d0000, 0x02580001 },
+   { 0x00600001, 0x22600021, 0x008d0260, 0x00000000 },
+   { 0x00600001, 0x202003be, 0x008d0020, 0x00000000 },
+   { 0x00600001, 0x204003be, 0x008d0180, 0x00000000 },
+   { 0x00600001, 0x206003be, 0x008d01c0, 0x00000000 },
+   { 0x00600001, 0x208003be, 0x008d0200, 0x00000000 },
+   { 0x00600001, 0x20a003be, 0x008d0240, 0x00000000 },
+   { 0x00600001, 0x20c003be, 0x008d01a0, 0x00000000 },
+   { 0x00600001, 0x20e003be, 0x008d01e0, 0x00000000 },
+   { 0x00600001, 0x210003be, 0x008d0220, 0x00000000 },
+   { 0x00600001, 0x212003be, 0x008d0260, 0x00000000 },
+   { 0x00600201, 0x20200022, 0x008d0020, 0x00000000 },
+   { 0x00800031, 0x24001d28, 0x008d0000, 0x85a04800 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
diff --git a/src/i965_composite_wm_nomask.g4a b/src/i965_composite_wm_nomask.g4a
deleted file mode 100644
index 927d86a..0000000
--- a/src/i965_composite_wm_nomask.g4a
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * This's for exa composite operation in no mask picture case.
- * The simplest case is just sending what src picture has to dst picture.
- * XXX: This is still experimental, and should be fixed to support multiple texture
- * map, and conditional mul actions. 
- */
-
-/* I think this should be same as in g4a program for texture video,
-   as we also use 16-pixel dispatch. and SF scale in g3 is useful for us. */
-
-/* The initial payload of the thread is always g0.
- * WM_URB (incoming URB entries) is g3
- * X0_R is g4
- * X1_R is g5
- * Y0_R is g6
- * Y1_R is g7
- */
-
-    /* Set up ss0.x coordinates*/
-mov (1) g4<1>F g1.8<0,1,0>UW { align1 };
-add (1) g4.4<1>F g1.8<0,1,0>UW 1UB { align1 };
-mov (1) g4.8<1>F g1.8<0,1,0>UW { align1 };
-add (1) g4.12<1>F g1.8<0,1,0>UW 1UB { align1 };
-    /* Set up ss0.y coordinates */
-mov (1) g6<1>F g1.10<0,1,0>UW { align1 };
-mov (1) g6.4<1>F g1.10<0,1,0>UW { align1 };
-add (1) g6.8<1>F g1.10<0,1,0>UW 1UB { align1 };
-add (1) g6.12<1>F g1.10<0,1,0>UW 1UB { align1 };
-    /* set up ss1.x coordinates */
-mov (1) g4.16<1>F g1.12<0,1,0>UW { align1 };
-add (1) g4.20<1>F g1.12<0,1,0>UW 1UB { align1 };
-mov (1) g4.24<1>F g1.12<0,1,0>UW { align1 };
-add (1) g4.28<1>F g1.12<0,1,0>UW 1UB { align1 };
-    /* set up ss1.y coordinates */
-mov (1) g6.16<1>F g1.14<0,1,0>UW { align1 };
-mov (1) g6.20<1>F g1.14<0,1,0>UW { align1 };
-add (1) g6.24<1>F g1.14<0,1,0>UW 1UB { align1 };
-add (1) g6.28<1>F g1.14<0,1,0>UW 1UB { align1 };
-    /* Set up ss2.x coordinates */
-mov (1) g5<1>F g1.16<0,1,0>UW { align1 };
-add (1) g5.4<1>F g1.16<0,1,0>UW 1UB { align1 };
-mov (1) g5.8<1>F g1.16<0,1,0>UW { align1 };
-add (1) g5.12<1>F g1.16<0,1,0>UW 1UB { align1 };
-    /* Set up ss2.y coordinates */
-mov (1) g7<1>F g1.18<0,1,0>UW { align1 };
-mov (1) g7.4<1>F g1.18<0,1,0>UW { align1 };
-add (1) g7.8<1>F g1.18<0,1,0>UW 1UB { align1 };
-add (1) g7.12<1>F g1.18<0,1,0>UW 1UB { align1 };
-    /* Set up ss3.x coordinates */
-mov (1) g5.16<1>F g1.20<0,1,0>UW { align1 };
-add (1) g5.20<1>F g1.20<0,1,0>UW 1UB { align1 };
-mov (1) g5.24<1>F g1.20<0,1,0>UW { align1 };
-add (1) g5.28<1>F g1.20<0,1,0>UW 1UB { align1 };
-    /* Set up ss3.y coordinates */
-mov (1) g7.16<1>F g1.22<0,1,0>UW { align1 };
-mov (1) g7.20<1>F g1.22<0,1,0>UW { align1 };
-add (1) g7.24<1>F g1.22<0,1,0>UW 1UB { align1 };
-add (1) g7.28<1>F g1.22<0,1,0>UW 1UB { align1 };
-
-    /* Now, map these screen space coordinates into texture coordinates. */
-    /* subtract screen-space X origin of vertex 0. */
-add (8) g4<1>F g4<8,8,1>F -g1<0,1,0>F { align1 };
-add (8) g5<1>F g5<8,8,1>F -g1<0,1,0>F { align1 };
-    /* scale by texture X increment */
-mul (8) g4<1>F g4<8,8,1>F g3<0,1,0>F { align1 };
-mul (8) g5<1>F g5<8,8,1>F g3<0,1,0>F { align1 };
-    /* add in texture X offset */
-add (8) g4<1>F g4<8,8,1>F g3.12<0,1,0>F { align1 };
-add (8) g5<1>F g5<8,8,1>F g3.12<0,1,0>F { align1 };
-    /* subtract screen-space Y origin of vertex 0. */
-add (8) g6<1>F g6<8,8,1>F -g1.4<0,1,0>F { align1 };
-add (8) g7<1>F g7<8,8,1>F -g1.4<0,1,0>F { align1 };
-    /* scale by texture Y increment */
-mul (8) g6<1>F g6<8,8,1>F g3.20<0,1,0>F { align1 };
-mul (8) g7<1>F g7<8,8,1>F g3.20<0,1,0>F { align1 };
-    /* add in texture Y offset */
-add (8) g6<1>F g6<8,8,1>F g3.28<0,1,0>F { align1 };
-add (8) g7<1>F g7<8,8,1>F g3.28<0,1,0>F { align1 };
-
-/* prepare sampler read back gX register, which would be written back to output */
-
-/* use simd16 sampler, param 0 is u, param 1 is v. */
-/* 'payload' loading, assuming tex coord start from g4 */
-mov (8) m1<1>F g4<8,8,1>F { align1 };
-mov (8) m2<1>F g5<8,8,1>F { align1 };  /* param 0 u in m1, m2 */
-mov (8) m3<1>F g6<8,8,1>F { align1 };
-mov (8) m4<1>F g7<8,8,1>F { align1 };  /* param 1 v in m3, m4 */
-
-/* m0 will be copied with g0, as it contains send desc */
-/* emit sampler 'send' cmd */
-send (16) 0 		/* msg reg index */
-	g12<1>UW 	/* readback */
-	g0<8,8,1>UW  	/* copy to msg start reg*/
-	sampler (1,0,F)  /* sampler message description, (binding_table,sampler_index,datatype)
-			 /* here(src->dst) we should use src_sampler and src_surface */
-	mlen 5 rlen 8 { align1 };   /* required message len 5, readback len 8 */
-
-/* if we set up read-back reg correctly, emit dataport write 'send' cmd with EOT */
-
-/* m0, m1 are all direct passed by PS thread payload */
-mov (8) m1<1>F g1<8,8,1>F { align1 };
-
-/* prepare data in m2-m5 for subspan(1,0), m6-m9 for subspan(3,2), then it's ready to write */
-/* g12 -> m2
-   g13 -> m6
-   g14 -> m3
-   g15 -> m7
-   g16 -> m4
-   g17 -> m8
-   g18 -> m5
-   g19 -> m9
-*/
-mov (8) m2<1>F g12<8,8,1>F { align1 };
-mov (8) m3<1>F g14<8,8,1>F { align1 };
-mov (8) m4<1>F g16<8,8,1>F { align1 };
-mov (8) m5<1>F g18<8,8,1>F { align1 };
-mov (8) m6<1>F g13<8,8,1>F { align1 };
-mov (8) m7<1>F g15<8,8,1>F { align1 };
-mov (8) m8<1>F g17<8,8,1>F { align1 };
-mov (8) m9<1>F g19<8,8,1>F { align1 };
-
-/* write */
-send (16) 0 null g0<8,8,1>UW write (
-	0,  /* binding_table */
-	8,  /* pixel scordboard clear, msg type simd16 single source */
-	4,  /* render target write */
-	0   /* no write commit message */
-	) 
-	mlen 10
-	rlen 0
-	{ align1 EOT };
-
-nop;
-nop;
-nop;
-nop;
-nop;
-nop;
-nop;
-nop;
-nop;
diff --git a/src/i965_composite_wm_nomask.h b/src/i965_composite_wm_nomask.h
deleted file mode 100644
index bd99dd9..0000000
--- a/src/i965_composite_wm_nomask.h
+++ /dev/null
@@ -1,68 +0,0 @@
-   { 0x00000001, 0x2080013d, 0x00000028, 0x00000000 },
-   { 0x00000040, 0x20840d3d, 0x00000028, 0x00000001 },
-   { 0x00000001, 0x2088013d, 0x00000028, 0x00000000 },
-   { 0x00000040, 0x208c0d3d, 0x00000028, 0x00000001 },
-   { 0x00000001, 0x20c0013d, 0x0000002a, 0x00000000 },
-   { 0x00000001, 0x20c4013d, 0x0000002a, 0x00000000 },
-   { 0x00000040, 0x20c80d3d, 0x0000002a, 0x00000001 },
-   { 0x00000040, 0x20cc0d3d, 0x0000002a, 0x00000001 },
-   { 0x00000001, 0x2090013d, 0x0000002c, 0x00000000 },
-   { 0x00000040, 0x20940d3d, 0x0000002c, 0x00000001 },
-   { 0x00000001, 0x2098013d, 0x0000002c, 0x00000000 },
-   { 0x00000040, 0x209c0d3d, 0x0000002c, 0x00000001 },
-   { 0x00000001, 0x20d0013d, 0x0000002e, 0x00000000 },
-   { 0x00000001, 0x20d4013d, 0x0000002e, 0x00000000 },
-   { 0x00000040, 0x20d80d3d, 0x0000002e, 0x00000001 },
-   { 0x00000040, 0x20dc0d3d, 0x0000002e, 0x00000001 },
-   { 0x00000001, 0x20a0013d, 0x00000030, 0x00000000 },
-   { 0x00000040, 0x20a40d3d, 0x00000030, 0x00000001 },
-   { 0x00000001, 0x20a8013d, 0x00000030, 0x00000000 },
-   { 0x00000040, 0x20ac0d3d, 0x00000030, 0x00000001 },
-   { 0x00000001, 0x20e0013d, 0x00000032, 0x00000000 },
-   { 0x00000001, 0x20e4013d, 0x00000032, 0x00000000 },
-   { 0x00000040, 0x20e80d3d, 0x00000032, 0x00000001 },
-   { 0x00000040, 0x20ec0d3d, 0x00000032, 0x00000001 },
-   { 0x00000001, 0x20b0013d, 0x00000034, 0x00000000 },
-   { 0x00000040, 0x20b40d3d, 0x00000034, 0x00000001 },
-   { 0x00000001, 0x20b8013d, 0x00000034, 0x00000000 },
-   { 0x00000040, 0x20bc0d3d, 0x00000034, 0x00000001 },
-   { 0x00000001, 0x20f0013d, 0x00000036, 0x00000000 },
-   { 0x00000001, 0x20f4013d, 0x00000036, 0x00000000 },
-   { 0x00000040, 0x20f80d3d, 0x00000036, 0x00000001 },
-   { 0x00000040, 0x20fc0d3d, 0x00000036, 0x00000001 },
-   { 0x00600040, 0x208077bd, 0x008d0080, 0x00004020 },
-   { 0x00600040, 0x20a077bd, 0x008d00a0, 0x00004020 },
-   { 0x00600041, 0x208077bd, 0x008d0080, 0x00000060 },
-   { 0x00600041, 0x20a077bd, 0x008d00a0, 0x00000060 },
-   { 0x00600040, 0x208077bd, 0x008d0080, 0x0000006c },
-   { 0x00600040, 0x20a077bd, 0x008d00a0, 0x0000006c },
-   { 0x00600040, 0x20c077bd, 0x008d00c0, 0x00004024 },
-   { 0x00600040, 0x20e077bd, 0x008d00e0, 0x00004024 },
-   { 0x00600041, 0x20c077bd, 0x008d00c0, 0x00000074 },
-   { 0x00600041, 0x20e077bd, 0x008d00e0, 0x00000074 },
-   { 0x00600040, 0x20c077bd, 0x008d00c0, 0x0000007c },
-   { 0x00600040, 0x20e077bd, 0x008d00e0, 0x0000007c },
-   { 0x00600001, 0x202003be, 0x008d0080, 0x00000000 },
-   { 0x00600001, 0x204003be, 0x008d00a0, 0x00000000 },
-   { 0x00600001, 0x206003be, 0x008d00c0, 0x00000000 },
-   { 0x00600001, 0x208003be, 0x008d00e0, 0x00000000 },
-   { 0x00800031, 0x21801d29, 0x008d0000, 0x02580001 },
-   { 0x00600001, 0x202003be, 0x008d0020, 0x00000000 },
-   { 0x00600001, 0x204003be, 0x008d0180, 0x00000000 },
-   { 0x00600001, 0x206003be, 0x008d01c0, 0x00000000 },
-   { 0x00600001, 0x208003be, 0x008d0200, 0x00000000 },
-   { 0x00600001, 0x20a003be, 0x008d0240, 0x00000000 },
-   { 0x00600001, 0x20c003be, 0x008d01a0, 0x00000000 },
-   { 0x00600001, 0x20e003be, 0x008d01e0, 0x00000000 },
-   { 0x00600001, 0x210003be, 0x008d0220, 0x00000000 },
-   { 0x00600001, 0x212003be, 0x008d0260, 0x00000000 },
-   { 0x00800031, 0x20001d3c, 0x008d0000, 0x85a04800 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
-   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
diff --git a/src/i965_exa_render.c b/src/i965_exa_render.c
index fe3007b..2751778 100644
--- a/src/i965_exa_render.c
+++ b/src/i965_exa_render.c
@@ -342,7 +342,7 @@ static const CARD32 sip_kernel_static[][
 #define SF_MAX_THREADS	   4
 
 static const CARD32 sf_kernel_static[][4] = {
-#include "sf_prog.h"
+#include "exa_sf_prog.h"
 };
 
 /* ps kernels */
@@ -350,7 +350,7 @@ static const CARD32 sf_kernel_static[][4
 #define PS_MAX_THREADS	   32
 /* 1: no mask */
 static const CARD32 ps_kernel_static_nomask [][4] = {
-	#include "i965_composite_wm_nomask.h"
+	#include "exa_wm_nomask_prog.h"
 };
 
 /* 2: mask with componentAlpha, src * mask color, XXX: later */
diff-tree 1329c86f2a4b3664920ded970a984a745a530da4 (from f9c3ef40100acb85fca6e49c5c0e98f5c9ac97ca)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Nov 29 15:47:19 2006 +0800

    [PATCH] EXA state mem for G965
    
    Not split offscreen mem for exa, but alloc a dedicated one
    for G965 states.
    
    Signed-off-by: Keith Packard <keithp at neko.keithp.com>

diff --git a/src/i830.h b/src/i830.h
index d5ca5d4..3b7301e 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -73,6 +73,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #ifdef I830_USE_EXA
 #include "exa.h"
 Bool I830EXAInit(ScreenPtr pScreen);
+#define EXA_LINEAR_EXTRA	(64*1024)
 #endif
 
 #ifdef I830_USE_XAA
@@ -267,6 +268,7 @@ typedef struct _I830Rec {
    I830MemRange Scratch2;
 #ifdef I830_USE_EXA
    I830MemRange Offscreen;
+   I830MemRange EXAStateMem;  /* specific exa state for G965 */
 #endif
    /* Regions allocated either from the above pools, or from agpgart. */
    I830MemRange	*CursorMem;
diff --git a/src/i830_exa.c b/src/i830_exa.c
index c5b91b0..3e874c9 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -425,7 +425,6 @@ IntelEXADoneComposite(PixmapPtr pDst)
 #endif
 }
 
-#define BRW_LINEAR_EXTRA (32*1024)
 /*
  * TODO:
  *   - Dual head?
@@ -448,11 +447,7 @@ I830EXAInit(ScreenPtr pScreen)
     pI830->EXADriverPtr->exa_minor = 0;
     pI830->EXADriverPtr->memoryBase = pI830->FbBase;
     pI830->EXADriverPtr->offScreenBase = pI830->Offscreen.Start;
-    if (IS_I965G(pI830))
-    	pI830->EXADriverPtr->memorySize = pI830->Offscreen.End -
-					BRW_LINEAR_EXTRA; /* BRW needs state buffer*/
-    else
-    	pI830->EXADriverPtr->memorySize = pI830->Offscreen.End;
+    pI830->EXADriverPtr->memorySize = pI830->Offscreen.End;
 	   
     DPRINTF(PFX, "EXA Mem: memoryBase 0x%x, end 0x%x, offscreen base 0x%x, memorySize 0x%x\n",
 		pI830->EXADriverPtr->memoryBase,
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 5bbf3e3..20e3afb 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -841,6 +841,25 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
 		       pI830->Offscreen.Start, pI830->Offscreen.Size/1024);
 	 }
       }
+      if (IS_I965G(pI830)) {
+          memset(&(pI830->EXAStateMem), 0, sizeof(I830MemRange));
+          pI830->EXAStateMem.Key = -1;
+          size = ROUND_TO_PAGE(EXA_LINEAR_EXTRA);
+          align = GTT_PAGE_SIZE;
+          alloced = I830AllocVidMem(pScrn, &(pI830->EXAStateMem),
+				&(pI830->StolenPool), size, align,
+				flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
+          if (alloced < size) {
+             if (!dryrun) {
+         	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		    "G965: Failed to allocate exa state buffer space.\n");
+             }
+             return FALSE;
+          }
+          xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+ 		  "%sAllocated %ld kB for the G965 exa state buffer at 0x%lx - 0x%lx.\n", s, 
+ 		alloced / 1024, pI830->EXAStateMem.Start, pI830->EXAStateMem.End);
+      }
 #endif
    } else {
       long lineSize;
@@ -1493,6 +1512,11 @@ I830FixupOffsets(ScrnInfoPtr pScrn)
       }
    }
 #endif
+#ifdef I830_USE_EXA
+   I830FixOffset(pScrn, &(pI830->Offscreen));
+   if (IS_I965G(pI830))
+       I830FixOffset(pScrn, &(pI830->EXAStateMem));
+#endif
    return TRUE;
 }
 
@@ -1894,6 +1918,12 @@ I830BindAGPMemory(ScrnInfoPtr pScrn)
 	    return FALSE;
       }
 #endif
+#ifdef I830_USE_EXA
+     if (!BindMemRange(pScrn, &(pI830->Offscreen)))
+	return FALSE;
+     if (IS_I965G(pI830) && !BindMemRange(pScrn, &(pI830->EXAStateMem)))
+	return FALSE;
+#endif
       pI830->GttBound = 1;
    }
 
@@ -1979,6 +2009,12 @@ I830UnbindAGPMemory(ScrnInfoPtr pScrn)
 	    return FALSE;
       }
 #endif
+#ifdef I830_USE_EXA
+     if (!UnbindMemRange(pScrn, &(pI830->Offscreen)))
+	return FALSE;
+     if (IS_I965G(pI830) && !UnbindMemRange(pScrn, &(pI830->EXAStateMem)))
+	return FALSE;
+#endif
       if (!xf86ReleaseGART(pScrn->scrnIndex))
 	 return FALSE;
 
diff --git a/src/i965_exa_render.c b/src/i965_exa_render.c
index 7fbf99c..fe3007b 100644
--- a/src/i965_exa_render.c
+++ b/src/i965_exa_render.c
@@ -490,21 +490,12 @@ ErrorF("i965 prepareComposite\n");
    next_offset = binding_table_offset + (binding_table_entries * 4);
 
    total_state_size = next_offset;
+   assert(total_state_size < EXA_LINEAR_EXTRA);
 
-   /*
-    * XXX: Use the extra space allocated at the end of the exa offscreen buffer?
-    */
-#define BRW_LINEAR_EXTRA	(32*1024)
-
-   state_base_offset = (pI830->Offscreen.End -
-			BRW_LINEAR_EXTRA);
-   
+   state_base_offset = pI830->EXAStateMem.Start;
    state_base_offset = ALIGN(state_base_offset, 64);
    state_base = (char *)(pI830->FbBase + state_base_offset);
-   /* Set up our pointers to state structures in framebuffer.  It would probably
-    * be a good idea to fill these structures out in system memory and then dump
-    * them there, instead.
-    */
+
    vs_state = (void *)(state_base + vs_offset);
    sf_state = (void *)(state_base + sf_offset);
    wm_state = (void *)(state_base + wm_offset);
diff-tree 4c790f614ecba1f6468e51779cfaf0e36b6b17ad (from 5a793b0dcf2d5de408b55073858fcfba6d99f994)
Author: Jesse Barnes <jbarnes at nietzche.virtuousgeek.org>
Date:   Sat Jan 6 08:21:36 2007 -0800

    More sparse cleanups:
      NULL vs. 0
      make some variables static
      remove redundant variables
    
    There are only a few sparse warnings left now: some bitfield warnings
    and a few 'mixing code and declarations' warnings from the ring macros.

diff --git a/src/i810_driver.c b/src/i810_driver.c
index 6ba0030..7574fb5 100644
--- a/src/i810_driver.c
+++ b/src/i810_driver.c
@@ -381,7 +381,7 @@ static int i810_pitches[] = {
 #endif
 #endif
 
-int I830EntityIndex = -1;
+static int I830EntityIndex = -1;
 
 #ifdef XFree86LOADER
 
@@ -400,7 +400,7 @@ static XF86ModuleVersionInfo i810VersRec
    {0, 0, 0, 0}
 };
 
-_X_EXPORT XF86ModuleData i810ModuleData = { &i810VersRec, i810Setup, 0 };
+_X_EXPORT XF86ModuleData i810ModuleData = { &i810VersRec, i810Setup, NULL };
 
 static pointer
 i810Setup(pointer module, pointer opts, int *errmaj, int *errmin)
@@ -468,7 +468,7 @@ I810FreeRec(ScrnInfoPtr pScrn)
    if (!pScrn->driverPrivate)
       return;
    xfree(pScrn->driverPrivate);
-   pScrn->driverPrivate = 0;
+   pScrn->driverPrivate = NULL;
 }
 #endif
 
@@ -577,7 +577,8 @@ I810Probe(DriverPtr drv, int flags)
 
 	 /* Allocate new ScrnInfoRec and claim the slot */
 	 if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i],
-					  I810PciChipsets, 0, 0, 0, 0, 0))) {
+					  I810PciChipsets, NULL, NULL, NULL,
+					  NULL, NULL))) {
 	    EntityInfoPtr pEnt;
 
 	    pEnt = xf86GetEntityInfo(usedChips[i]);
@@ -609,23 +610,23 @@ I810Probe(DriverPtr drv, int flags)
     	       if (I830EntityIndex < 0)					
 		  I830EntityIndex = xf86AllocateEntityPrivateIndex();	
 
-    	       pPriv = xf86GetEntityPrivate(pScrn->entityList[0],		
+    	       pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
 						I830EntityIndex);	
-    	       if (!pPriv->ptr) {						
-		  pPriv->ptr = xnfcalloc(sizeof(I830EntRec), 1);		
-		  pI830Ent = pPriv->ptr;					
-		  pI830Ent->lastInstance = -1;				
-    	       } else {							
-		  pI830Ent = pPriv->ptr;					
+    	       if (!pPriv->ptr) {
+		  pPriv->ptr = xnfcalloc(sizeof(I830EntRec), 1);
+		  pI830Ent = pPriv->ptr;
+		  pI830Ent->lastInstance = -1;
+    	       } else {
+		   pI830Ent = pPriv->ptr;
     	       }
-								
-    	       /*								
-     	        * Set the entity instance for this instance of the driver.	
-     	        * For dual head per card, instance 0 is the "master" 	
-     	        * instance, driving the primary head, and instance 1 is 	
-     	        * the "slave".						
-     	        */								
-    	       pI830Ent->lastInstance++;					
+
+    	       /*
+		* Set the entity instance for this instance of the driver.
+     	        * For dual head per card, instance 0 is the "master"
+     	        * instance, driving the primary head, and instance 1 is
+     	        * the "slave".
+     	        */
+    	       pI830Ent->lastInstance++;
                xf86SetEntityInstanceForScreen(pScrn,			
 			pScrn->entityList[0], pI830Ent->lastInstance);	
 	       I830InitpScrn(pScrn);
@@ -746,7 +747,7 @@ I810PreInit(ScrnInfoPtr pScrn, int flags
    pI810->PciTag = pciTag(pI810->PciInfo->bus, pI810->PciInfo->device,
 			  pI810->PciInfo->func);
 
-   if (xf86RegisterResources(pI810->pEnt->index, 0, ResNone))
+   if (xf86RegisterResources(pI810->pEnt->index, NULL, ResNone))
       return FALSE;
    pScrn->racMemFlags = RAC_FB | RAC_COLORMAP;
 
@@ -1222,7 +1223,7 @@ I810UnmapMMIO(ScrnInfoPtr pScrn)
 
    xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pI810->MMIOBase,
 		   I810_REG_SIZE);
-   pI810->MMIOBase = 0;
+   pI810->MMIOBase = NULL;
 }
 
 static Bool
@@ -1232,7 +1233,7 @@ I810UnmapMem(ScrnInfoPtr pScrn)
 
    xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pI810->FbBase,
 		   pI810->FbMapSize);
-   pI810->FbBase = 0;
+   pI810->FbBase = NULL;
    I810UnmapMMIO(pScrn);
    return TRUE;
 }
diff --git a/src/i810_video.c b/src/i810_video.c
index e65a7f6..b3dc90e 100644
--- a/src/i810_video.c
+++ b/src/i810_video.c
@@ -1301,7 +1301,7 @@ I810GetSurfaceAttribute(
     Atom attribute,
     INT32 *value
 ){
-    return I810GetPortAttribute(pScrn, attribute, value, 0);
+    return I810GetPortAttribute(pScrn, attribute, value, NULL);
 }
 
 static int
@@ -1310,7 +1310,7 @@ I810SetSurfaceAttribute(
     Atom attribute,
     INT32 value
 ){
-    return I810SetPortAttribute(pScrn, attribute, value, 0);
+    return I810SetPortAttribute(pScrn, attribute, value, NULL);
 }
 
 
diff --git a/src/i810_wmark.c b/src/i810_wmark.c
index 6540cbb..85d55ef 100644
--- a/src/i810_wmark.c
+++ b/src/i810_wmark.c
@@ -57,7 +57,7 @@ struct wm_info {
    unsigned int wm;
 };
 
-struct wm_info i810_wm_8_100[] = {
+static struct wm_info i810_wm_8_100[] = {
    {0, 0x22003000},
    {25.2, 0x22003000},
    {28.0, 0x22003000},
@@ -87,7 +87,7 @@ struct wm_info i810_wm_8_100[] = {
    {202.5, 0x2220e000}
 };
 
-struct wm_info i810_wm_16_100[] = {
+static struct wm_info i810_wm_16_100[] = {
    {0, 0x22004000},
    {25.2, 0x22006000},
    {28.0, 0x22006000},
@@ -118,7 +118,7 @@ struct wm_info i810_wm_16_100[] = {
    {202.5, 0x22416000}
 };
 
-struct wm_info i810_wm_24_100[] = {
+static struct wm_info i810_wm_24_100[] = {
    {0, 0x22006000},
    {25.2, 0x22009000},
    {28.0, 0x22009000},
@@ -149,13 +149,13 @@ struct wm_info i810_wm_24_100[] = {
    {202.5, 0x44419000}
 };
 
-struct wm_info i810_wm_32_100[] = {
+static struct wm_info i810_wm_32_100[] = {
    {0, 0x2210b000},
    {60, 0x22415000},			/* 0x314000 works too */
    {80, 0x22419000}			/* 0x518000 works too */
 };
 
-struct wm_info i810_wm_8_133[] = {
+static struct wm_info i810_wm_8_133[] = {
    {0, 0x22003000},
    {25.2, 0x22003000},
    {28.0, 0x22003000},
@@ -185,7 +185,7 @@ struct wm_info i810_wm_8_133[] = {
    {202.5, 0x2220e000}
 };
 
-struct wm_info i810_wm_16_133[] = {
+static struct wm_info i810_wm_16_133[] = {
    {0, 0x22004000},
    {25.2, 0x22006000},
    {28.0, 0x22006000},
@@ -216,7 +216,7 @@ struct wm_info i810_wm_16_133[] = {
    {202.5, 0x22416000}
 };
 
-struct wm_info i810_wm_24_133[] = {
+static struct wm_info i810_wm_24_133[] = {
    {0, 0x22006000},
    {25.2, 0x22009000},
    {28.0, 0x22009000},
diff --git a/src/i830_accel.c b/src/i830_accel.c
index 2260b71..5fdd101 100644
--- a/src/i830_accel.c
+++ b/src/i830_accel.c
@@ -180,10 +180,12 @@ I830EmitFlush(ScrnInfoPtr pScrn)
    if (IS_I965G(pI830))
       flags = 0;
 
-   BEGIN_LP_RING(2);
-   OUT_RING(MI_FLUSH | flags);
-   OUT_RING(MI_NOOP);		/* pad to quadword */
-   ADVANCE_LP_RING();
+   {
+       BEGIN_LP_RING(2);
+       OUT_RING(MI_FLUSH | flags);
+       OUT_RING(MI_NOOP);		/* pad to quadword */
+       ADVANCE_LP_RING();
+   }
 }
 
 void
diff --git a/src/i830_exa.c b/src/i830_exa.c
index 9356c79..e9ded73 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -57,9 +57,9 @@ do { 							\
 } while(0) 
 #endif
 
-float scale_units[2][2];
+static float scale_units[2][2];
 
-const int I830CopyROP[16] =
+const static int I830CopyROP[16] =
 {
    ROP_0,               /* GXclear */
    ROP_DSa,             /* GXand */
@@ -79,7 +79,7 @@ const int I830CopyROP[16] =
    ROP_1                /* GXset */
 };
 
-const int I830PatternROP[16] =
+const static int I830PatternROP[16] =
 {
     ROP_0,
     ROP_DPa,
@@ -111,8 +111,8 @@ union intfloat {
 	OUT_RING(tmp.ui);			\
 } while(0)				
 
-Bool is_transform[2];
-PictTransform *transform[2];
+static Bool is_transform[2];
+static PictTransform *transform[2];
 
 extern Bool I830EXACheckComposite(int, PicturePtr, PicturePtr, PicturePtr);
 extern Bool I830EXAPrepareComposite(int, PicturePtr, PicturePtr, PicturePtr, 
diff --git a/src/i830_rotate.c b/src/i830_rotate.c
index 9fa3290..2afd712 100644
--- a/src/i830_rotate.c
+++ b/src/i830_rotate.c
@@ -827,7 +827,7 @@ I830Rotate(ScrnInfoPtr pScrn, DisplayMod
    if (pI830->rotation != RR_Rotate_0)
       shadowAdd (pScrn->pScreen, 
 		 (*pScrn->pScreen->GetScreenPixmap) (pScrn->pScreen),
-		 func, I830WindowLinear, pI830->rotation, 0);
+		 func, I830WindowLinear, pI830->rotation, NULL);
 
    if (I830IsPrimary(pScrn)) {
       if (pI830->rotation != RR_Rotate_0)
@@ -1045,7 +1045,7 @@ BAIL0:
    if (pI830->rotation != RR_Rotate_0)
       shadowAdd (pScrn->pScreen, 
 		 (*pScrn->pScreen->GetScreenPixmap) (pScrn->pScreen),
-		 func, I830WindowLinear, pI830->rotation, 0);
+		 func, I830WindowLinear, pI830->rotation, NULL);
 
    if (I830IsPrimary(pScrn)) {
       if (pI830->rotation != RR_Rotate_0)
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 19b4b93..ea62ad9 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -124,7 +124,7 @@ static Bool i830_sdvo_write_byte(xf86Out
 
 #define SDVO_CMD_NAME_ENTRY(cmd) {cmd, #cmd}
 /** Mapping of command numbers to names, for debug output */
-const struct _sdvo_cmd_name {
+const static struct _sdvo_cmd_name {
     CARD8 cmd;
     char *name;
 } sdvo_cmd_names[] = {
diff --git a/src/i830_tv.c b/src/i830_tv.c
index 5cf36a5..ad3b262 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -155,7 +155,7 @@ typedef struct {
  * These values account for -1s required.
  */
 
-const tv_mode_t tv_modes[] = {
+const static tv_mode_t tv_modes[] = {
     {
 	.name		= "NTSC 480i",
 	.oversample	= TV_OVERSAMPLE_8X,
@@ -945,7 +945,7 @@ i830_tv_get_modes(xf86OutputPtr output)
 {
     ScrnInfoPtr	    pScrn = output->scrn;
     I830Ptr	    pI830 = I830PTR(pScrn);
-    DisplayModePtr  new, first = NULL, *tail = &first;;
+    DisplayModePtr  new, first = NULL, *tail = &first;
     int		    i;
 
     (void) pI830;
diff --git a/src/i830_video.c b/src/i830_video.c
index f031a87..6b76faa 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -2695,13 +2695,13 @@ I830FreeSurface(XF86SurfacePtr surface)
 static int
 I830GetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 * value)
 {
-   return I830GetPortAttribute(pScrn, attribute, value, 0);
+   return I830GetPortAttribute(pScrn, attribute, value, NULL);
 }
 
 static int
 I830SetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value)
 {
-   return I830SetPortAttribute(pScrn, attribute, value, 0);
+   return I830SetPortAttribute(pScrn, attribute, value, NULL);
 }
 
 static int
@@ -2880,10 +2880,10 @@ i830_crtc_dpms_video(xf86CrtcPtr crtc, B
       /* Check we have an LFP connected */
       if (i830PipeHasType(xf86_config->crtc[pPriv->pipe],
 			  I830_OUTPUT_LVDS)) {
+	 int vtotal_reg = pPriv->pipe ? VTOTAL_A : VTOTAL_B;
 	 size = pPriv->pipe ? INREG(PIPEBSRC) : INREG(PIPEASRC);
 	 hsize = (size >> 16) & 0x7FF;
 	 vsize = size & 0x7FF;
-	 int vtotal_reg = pPriv->pipe ? VTOTAL_A : VTOTAL_B;
 	 active = INREG(vtotal_reg) & 0x7FF;
 
 	 if (vsize < active && hsize > 1024)
diff --git a/src/i830_xaa.c b/src/i830_xaa.c
index 9c994d3..cad9c71 100644
--- a/src/i830_xaa.c
+++ b/src/i830_xaa.c
@@ -214,7 +214,6 @@ I830XAAInit(ScreenPtr pScreen)
 
     {
 	Bool shared_accel = FALSE;
-	int i;
 
 	for(i = 0; i < pScrn->numEntities; i++) {
 	    if(xf86IsEntityShared(pScrn->entityList[i]))
diff-tree f9c3ef40100acb85fca6e49c5c0e98f5c9ac97ca (from ef2f25e5c6ce04c202698c5122bc8627130073c0)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Tue Oct 10 15:50:10 2006 +0800

    [PATCH] Mark current ps kernel is experimential with little test.
    
    
    Signed-off-by: Keith Packard <keithp at neko.keithp.com>

diff --git a/src/i965_composite_wm_nomask.g4a b/src/i965_composite_wm_nomask.g4a
index 8791631..927d86a 100644
--- a/src/i965_composite_wm_nomask.g4a
+++ b/src/i965_composite_wm_nomask.g4a
@@ -1,6 +1,8 @@
 /*
  * This's for exa composite operation in no mask picture case.
- * The simplest case is just sending what src picture has to dst picture
+ * The simplest case is just sending what src picture has to dst picture.
+ * XXX: This is still experimental, and should be fixed to support multiple texture
+ * map, and conditional mul actions. 
  */
 
 /* I think this should be same as in g4a program for texture video,
diff-tree ef2f25e5c6ce04c202698c5122bc8627130073c0 (from ca608028c5301700444d39a1c631cc0d5648e1a2)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Tue Oct 10 14:11:35 2006 +0800

    [PATCH] Use sf_prog.h instead
    
    
    Signed-off-by: Keith Packard <keithp at neko.keithp.com>

diff --git a/src/i965_exa_render.c b/src/i965_exa_render.c
index 5528388..7fbf99c 100644
--- a/src/i965_exa_render.c
+++ b/src/i965_exa_render.c
@@ -89,7 +89,6 @@ struct formatinfo {
 
 // refer vol2, 3d rasterization 3.8.1
 
-/* XXX: bad!bad! broadwater has different blend factor definition */
 /* defined in brw_defines.h */
 static struct blendinfo I965BlendOp[] = { 
     /* Clear */
@@ -163,8 +162,6 @@ static void I965GetBlendCntl(int op, Pic
 
 }
 
-
-/* FIXME */
 static Bool I965GetDestFormat(PicturePtr pDstPicture, CARD32 *dst_format)
 {
     switch (pDstPicture->format) {
@@ -221,7 +218,6 @@ static Bool I965CheckCompositeTexture(Pi
         I830FALLBACK("Unsupported picture format 0x%x\n",
                          (int)pPict->format);
 
-    /* XXX: fallback when repeat? */
     if (pPict->repeat && pPict->repeatType != RepeatNormal)
 	I830FALLBACK("extended repeat (%d) not supported\n",
 		     pPict->repeatType);
@@ -346,40 +342,7 @@ static const CARD32 sip_kernel_static[][
 #define SF_MAX_THREADS	   4
 
 static const CARD32 sf_kernel_static[][4] = {
-/*    send   0 (1) g6<1>F g1.12<0,1,0>F math mlen 1 rlen 1 { align1 +  } */
-   { 0x00000031, 0x20c01fbd, 0x0000002c, 0x01110081 },
-/*    send   0 (1) g6.4<1>F g1.20<0,1,0>F math mlen 1 rlen 1 { align1 +  } */
-   { 0x00000031, 0x20c41fbd, 0x00000034, 0x01110081 },
-/*    add (8) g7<1>F g4<8,8,1>F g3<8,8,1>F { align1 +  } */
-   { 0x00600040, 0x20e077bd, 0x008d0080, 0x008d4060 },
-/*    mul (1) g7<1>F g7<0,1,0>F g6<0,1,0>F { align1 +  } */
-   { 0x00000041, 0x20e077bd, 0x000000e0, 0x000000c0 },
-/*    mul (1) g7.4<1>F g7.4<0,1,0>F g6.4<0,1,0>F { align1 +  } */
-   { 0x00000041, 0x20e477bd, 0x000000e4, 0x000000c4 },
-/*    mov (8) m1<1>F g7<0,1,0>F { align1 +  } */
-   { 0x00600001, 0x202003be, 0x000000e0, 0x00000000 },
-/*    mov (8) m2<1>F g7.4<0,1,0>F { align1 +  } */
-   { 0x00600001, 0x204003be, 0x000000e4, 0x00000000 },
-/*    mov (8) m3<1>F g3<8,8,1>F { align1 +  } */
-   { 0x00600001, 0x206003be, 0x008d0060, 0x00000000 },
-/*    send   0 (8) a0<1>F g0<8,8,1>F urb mlen 4 rlen 0 write +0 transpose used complete EOT{ align1 +  } */
-   { 0x00600031, 0x20001fbc, 0x008d0000, 0x8640c800 },
-/*    nop (4) g0<1>UD { align1 +  } */
-   { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
-/*    nop (4) g0<1>UD { align1 +  } */
-   { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
-/*    nop (4) g0<1>UD { align1 +  } */
-   { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
-/*    nop (4) g0<1>UD { align1 +  } */
-   { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
-/*    nop (4) g0<1>UD { align1 +  } */
-   { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
-/*    nop (4) g0<1>UD { align1 +  } */
-   { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
-/*    nop (4) g0<1>UD { align1 +  } */
-   { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
-/*    nop (4) g0<1>UD { align1 +  } */
-   { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+#include "sf_prog.h"
 };
 
 /* ps kernels */
@@ -475,9 +438,8 @@ ErrorF("i965 prepareComposite\n");
    cc_offset = ALIGN(next_offset, 32);
    next_offset = cc_offset + sizeof(*cc_state);
 
-// fixup sf_kernel_static, is sf_kernel needed? or not? why? 
-//	-> just keep current sf_kernel, which will send one setup urb entry to
-//	PS kernel
+   /* keep current sf_kernel, which will send one setup urb entry to
+	PS kernel */
    sf_kernel_offset = ALIGN(next_offset, 64);
    next_offset = sf_kernel_offset + sizeof (sf_kernel_static);
 
@@ -965,7 +927,7 @@ ErrorF("i965 prepareComposite\n");
   // int vb_pitch = 4 * 4;  // XXX: pitch should include mask's coords? possible
   // all three coords on one row?
    int nelem = pMask ? 3: 2;
-   OUT_RING(BRW_3DSTATE_VERTEX_BUFFERS | 3); //should be 4n-1 -> 3
+   OUT_RING(BRW_3DSTATE_VERTEX_BUFFERS | 3); //XXX: should be 4n-1 -> 3
    OUT_RING((0 << VB0_BUFFER_INDEX_SHIFT) |
 	    VB0_VERTEXDATA |
 	    ((4 * 2 * nelem) << VB0_BUFFER_PITCH_SHIFT)); 
diff-tree ca608028c5301700444d39a1c631cc0d5648e1a2 (from 848368d5d0b90e03d3ec447cb5bd39fc87aea8df)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Thu Sep 28 13:55:52 2006 +0800

    [PATCH] Fix picture's transform checking
    
    
    Signed-off-by: Keith Packard <keithp at neko.keithp.com>

diff --git a/src/i965_exa_render.c b/src/i965_exa_render.c
index f7093f2..5528388 100644
--- a/src/i965_exa_render.c
+++ b/src/i965_exa_render.c
@@ -437,11 +437,22 @@ ErrorF("i965 prepareComposite\n");
     scale_units[2][0] = pDst->drawable.width;
     scale_units[2][1] = pDst->drawable.height;
 
+    if (pSrcPicture->transform) {
+	is_transform[0] = TRUE;
+	transform[0] = pSrcPicture->transform;
+    } else 
+	is_transform[0] = FALSE;
+
     if (!pMask) {
 	is_transform[1] = FALSE;
 	scale_units[1][0] = -1;
 	scale_units[1][1] = -1;
     } else {
+	if (pMaskPicture->transform) {
+	    is_transform[1] = TRUE;
+	    transform[1] = pMaskPicture->transform;
+	} else
+	    is_transform[1] = FALSE;
 	scale_units[1][0] = pMask->drawable.width;
 	scale_units[1][1] = pMask->drawable.height;
     }
diff-tree 848368d5d0b90e03d3ec447cb5bd39fc87aea8df (from df23624eebe938fa444c80cbedcd61919ec1aeda)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Thu Sep 28 11:15:33 2006 +0800

    [PATCH] Fallback in mask picture for now
    
    Do it later after finish wm kernel program.
    
    Signed-off-by: Keith Packard <keithp at neko.keithp.com>

diff --git a/src/i965_exa_render.c b/src/i965_exa_render.c
index b56bf7f..f7093f2 100644
--- a/src/i965_exa_render.c
+++ b/src/i965_exa_render.c
@@ -417,6 +417,11 @@ ErrorF("i965 prepareComposite\n");
 //    i965_surf_setup(pScrn, pSrcPicture, pMaskPicture, pDstPicture,
 //   			pSrc, pMask, pDst);
     // then setup blend, and shader program 
+    
+    /* FIXME: fallback in pMask for now, would be enable after finish
+	wm kernel program */
+    if (pMask)
+	I830FALLBACK("No mask support yet.\n");
 
     I965GetDestFormat(pDstPicture, &dst_format);
     src_offset = exaGetPixmapOffset(pSrc);
@@ -995,68 +1000,12 @@ ErrorF("i965 prepareComposite\n");
 	    (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
 	    (8 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); 
 		//XXX: is this has alignment issue? and thread access problem?
-	    
    }
    
    ADVANCE_LP_RING();
     
    }
 
-    {
-	/* cc states */
-	/* dest buffer */
-	/* urbs */
-	/* binding tables */
-	/* clipping */
-	/* color blend (color calculator, dataport shared function)
-		COLOR_CALC_STATE/SURFACE_STATE(rendertarget's color blend enable
-		bit)
-		Errata!!!: brw-a/b, rendertarget 'local' color blending always
-		enabled! only control by global enable bit.
-	   surface format for blend, "Surface format table in Sampling Engine"
-	   XXX: if surface format not support, we should fallback.
-	*/
-	/* 
-	    render target should be defined in SURFACE_STATE
-	    	o render target SURFTYPE_BUFFER? 2D? Keith has 2D set.
-		o depth buffer SURFTYPE_NULL?
-	    color blend:
-	        o Errata!!: mush issue PIPE_CONTROL with Write Cache Flush
-		enable set, before transite to read-write color buffer. 
-	    	o disable pre/post-blending clamping
-		o enable color buffer blending enable in COLOR_CALC_STATE,(vol2, 3d rasterization 3.8) 
-		  enable color blending enable in SURFACE_STATE.(shared,
-		  sampling engine 1.7) 
-		  disable depth test
-		o (we don't use BLENDFACT_SRC_ALPHA_SATURATE, so don't care
-		the Errata for independent alpha blending, just use color
-		blending factor for all) disable independent alpha blending
-		in COLOR_CALC_STATE
-		o set src/dst blend factor in COLOR_CALC_STATE
-
-	*/
-    }
-
-	/* shader program 
-		o use sampler shared function for texture data
-		o submit result to dataport for later color blending */
-    {
-	 /* PS program:
-	 	o declare sampler and variables??
-		o 'send' cmd to Sampling Engine to load 'src' picture
-		o if (!pMask) then 'send' 'src' texture value to DataPort
-		target render cache
-		o else 
-		    - 'send' cmd to SE to load 'mask' picture
-		    - if no alpha, force to 1 (move 1 to W element of mask)
-		    - if (mask->componentAlpha) then mul 'src' & 'mask', 'send'
-		    	output to DataPort render cache
-		    - else mul 'src' & 'mask''s W element(alpha), 'send' output
-		    	to Dataport render cache
-	 */
-
-    }
-
 #ifdef I830DEBUG
     ErrorF("try to sync to show any errors...");
     I830Sync(pScrn);
diff-tree df23624eebe938fa444c80cbedcd61919ec1aeda (from fc944859b1b9605c748162bad1c93a6303c84aae)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Thu Sep 28 11:09:52 2006 +0800

    [PATCH] Fix compile, add wm header file.
    
    
    Signed-off-by: Keith Packard <keithp at neko.keithp.com>

diff --git a/src/Makefile.am b/src/Makefile.am
index b0c6c92..54e5657 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -94,6 +94,7 @@ i810_drv_la_SOURCES = \
 	 i830_xaa.c \
 	 i830_exa_render.c \
 	 i915_exa_render.c \
+	 i965_composite_wm_nomask.h \
 	 i965_exa_render.c
 
 if HAVE_GEN4ASM
diff --git a/src/i965_composite_wm_nomask.h b/src/i965_composite_wm_nomask.h
new file mode 100644
index 0000000..bd99dd9
--- /dev/null
+++ b/src/i965_composite_wm_nomask.h
@@ -0,0 +1,68 @@
+   { 0x00000001, 0x2080013d, 0x00000028, 0x00000000 },
+   { 0x00000040, 0x20840d3d, 0x00000028, 0x00000001 },
+   { 0x00000001, 0x2088013d, 0x00000028, 0x00000000 },
+   { 0x00000040, 0x208c0d3d, 0x00000028, 0x00000001 },
+   { 0x00000001, 0x20c0013d, 0x0000002a, 0x00000000 },
+   { 0x00000001, 0x20c4013d, 0x0000002a, 0x00000000 },
+   { 0x00000040, 0x20c80d3d, 0x0000002a, 0x00000001 },
+   { 0x00000040, 0x20cc0d3d, 0x0000002a, 0x00000001 },
+   { 0x00000001, 0x2090013d, 0x0000002c, 0x00000000 },
+   { 0x00000040, 0x20940d3d, 0x0000002c, 0x00000001 },
+   { 0x00000001, 0x2098013d, 0x0000002c, 0x00000000 },
+   { 0x00000040, 0x209c0d3d, 0x0000002c, 0x00000001 },
+   { 0x00000001, 0x20d0013d, 0x0000002e, 0x00000000 },
+   { 0x00000001, 0x20d4013d, 0x0000002e, 0x00000000 },
+   { 0x00000040, 0x20d80d3d, 0x0000002e, 0x00000001 },
+   { 0x00000040, 0x20dc0d3d, 0x0000002e, 0x00000001 },
+   { 0x00000001, 0x20a0013d, 0x00000030, 0x00000000 },
+   { 0x00000040, 0x20a40d3d, 0x00000030, 0x00000001 },
+   { 0x00000001, 0x20a8013d, 0x00000030, 0x00000000 },
+   { 0x00000040, 0x20ac0d3d, 0x00000030, 0x00000001 },
+   { 0x00000001, 0x20e0013d, 0x00000032, 0x00000000 },
+   { 0x00000001, 0x20e4013d, 0x00000032, 0x00000000 },
+   { 0x00000040, 0x20e80d3d, 0x00000032, 0x00000001 },
+   { 0x00000040, 0x20ec0d3d, 0x00000032, 0x00000001 },
+   { 0x00000001, 0x20b0013d, 0x00000034, 0x00000000 },
+   { 0x00000040, 0x20b40d3d, 0x00000034, 0x00000001 },
+   { 0x00000001, 0x20b8013d, 0x00000034, 0x00000000 },
+   { 0x00000040, 0x20bc0d3d, 0x00000034, 0x00000001 },
+   { 0x00000001, 0x20f0013d, 0x00000036, 0x00000000 },
+   { 0x00000001, 0x20f4013d, 0x00000036, 0x00000000 },
+   { 0x00000040, 0x20f80d3d, 0x00000036, 0x00000001 },
+   { 0x00000040, 0x20fc0d3d, 0x00000036, 0x00000001 },
+   { 0x00600040, 0x208077bd, 0x008d0080, 0x00004020 },
+   { 0x00600040, 0x20a077bd, 0x008d00a0, 0x00004020 },
+   { 0x00600041, 0x208077bd, 0x008d0080, 0x00000060 },
+   { 0x00600041, 0x20a077bd, 0x008d00a0, 0x00000060 },
+   { 0x00600040, 0x208077bd, 0x008d0080, 0x0000006c },
+   { 0x00600040, 0x20a077bd, 0x008d00a0, 0x0000006c },
+   { 0x00600040, 0x20c077bd, 0x008d00c0, 0x00004024 },
+   { 0x00600040, 0x20e077bd, 0x008d00e0, 0x00004024 },
+   { 0x00600041, 0x20c077bd, 0x008d00c0, 0x00000074 },
+   { 0x00600041, 0x20e077bd, 0x008d00e0, 0x00000074 },
+   { 0x00600040, 0x20c077bd, 0x008d00c0, 0x0000007c },
+   { 0x00600040, 0x20e077bd, 0x008d00e0, 0x0000007c },
+   { 0x00600001, 0x202003be, 0x008d0080, 0x00000000 },
+   { 0x00600001, 0x204003be, 0x008d00a0, 0x00000000 },
+   { 0x00600001, 0x206003be, 0x008d00c0, 0x00000000 },
+   { 0x00600001, 0x208003be, 0x008d00e0, 0x00000000 },
+   { 0x00800031, 0x21801d29, 0x008d0000, 0x02580001 },
+   { 0x00600001, 0x202003be, 0x008d0020, 0x00000000 },
+   { 0x00600001, 0x204003be, 0x008d0180, 0x00000000 },
+   { 0x00600001, 0x206003be, 0x008d01c0, 0x00000000 },
+   { 0x00600001, 0x208003be, 0x008d0200, 0x00000000 },
+   { 0x00600001, 0x20a003be, 0x008d0240, 0x00000000 },
+   { 0x00600001, 0x20c003be, 0x008d01a0, 0x00000000 },
+   { 0x00600001, 0x20e003be, 0x008d01e0, 0x00000000 },
+   { 0x00600001, 0x210003be, 0x008d0220, 0x00000000 },
+   { 0x00600001, 0x212003be, 0x008d0260, 0x00000000 },
+   { 0x00800031, 0x20001d3c, 0x008d0000, 0x85a04800 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
diff --git a/src/i965_exa_render.c b/src/i965_exa_render.c
index dfa9a04..b56bf7f 100644
--- a/src/i965_exa_render.c
+++ b/src/i965_exa_render.c
@@ -68,6 +68,9 @@ extern void
 I965EXAComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
 		int dstX, int dstY, int width, int height);
 
+static void I965GetBlendCntl(int op, PicturePtr pMask, CARD32 dst_format, 
+			     CARD32 *sblend, CARD32 *dblend);
+
 extern float scale_units[2][2];
 extern Bool is_transform[2];
 extern PictTransform *transform[2];
@@ -90,31 +93,31 @@ struct formatinfo {
 /* defined in brw_defines.h */
 static struct blendinfo I965BlendOp[] = { 
     /* Clear */
-    {0, 0, BRW_BLENDFACT_ZERO,          BRW_BLENDFACT_ZERO},
+    {0, 0, BRW_BLENDFACTOR_ZERO,          BRW_BLENDFACTOR_ZERO},
     /* Src */
-    {0, 0, BRW_BLENDFACT_ONE,           BRW_BLENDFACT_ZERO},
+    {0, 0, BRW_BLENDFACTOR_ONE,           BRW_BLENDFACTOR_ZERO},
     /* Dst */
-    {0, 0, BRW_BLENDFACT_ZERO,          BRW_BLENDFACT_ONE},
+    {0, 0, BRW_BLENDFACTOR_ZERO,          BRW_BLENDFACTOR_ONE},
     /* Over */
-    {0, 1, BRW_BLENDFACT_ONE,           BRW_BLENDFACT_INV_SRC_ALPHA},
+    {0, 1, BRW_BLENDFACTOR_ONE,           BRW_BLENDFACTOR_INV_SRC_ALPHA},
     /* OverReverse */
-    {1, 0, BRW_BLENDFACT_INV_DST_ALPHA, BRW_BLENDFACT_ONE},
+    {1, 0, BRW_BLENDFACTOR_INV_DST_ALPHA, BRW_BLENDFACTOR_ONE},
     /* In */
-    {1, 0, BRW_BLENDFACT_DST_ALPHA,     BRW_BLENDFACT_ZERO},
+    {1, 0, BRW_BLENDFACTOR_DST_ALPHA,     BRW_BLENDFACTOR_ZERO},
     /* InReverse */
-    {0, 1, BRW_BLENDFACT_ZERO,          BRW_BLENDFACT_SRC_ALPHA},
+    {0, 1, BRW_BLENDFACTOR_ZERO,          BRW_BLENDFACTOR_SRC_ALPHA},
     /* Out */
-    {1, 0, BRW_BLENDFACT_INV_DST_ALPHA, BRW_BLENDFACT_ZERO},
+    {1, 0, BRW_BLENDFACTOR_INV_DST_ALPHA, BRW_BLENDFACTOR_ZERO},
     /* OutReverse */
-    {0, 1, BRW_BLENDFACT_ZERO,          BRW_BLENDFACT_INV_SRC_ALPHA},
+    {0, 1, BRW_BLENDFACTOR_ZERO,          BRW_BLENDFACTOR_INV_SRC_ALPHA},
     /* Atop */
-    {1, 1, BRW_BLENDFACT_DST_ALPHA,     BRW_BLENDFACT_INV_SRC_ALPHA},
+    {1, 1, BRW_BLENDFACTOR_DST_ALPHA,     BRW_BLENDFACTOR_INV_SRC_ALPHA},
     /* AtopReverse */
-    {1, 1, BRW_BLENDFACT_INV_DST_ALPHA, BRW_BLENDFACT_SRC_ALPHA},
+    {1, 1, BRW_BLENDFACTOR_INV_DST_ALPHA, BRW_BLENDFACTOR_SRC_ALPHA},
     /* Xor */
-    {1, 1, BRW_BLENDFACT_INV_DST_ALPHA, BRW_BLENDFACT_INV_SRC_ALPHA},
+    {1, 1, BRW_BLENDFACTOR_INV_DST_ALPHA, BRW_BLENDFACTOR_INV_SRC_ALPHA},
     /* Add */
-    {0, 0, BRW_BLENDFACT_ONE,           BRW_BLENDFACT_ONE},
+    {0, 0, BRW_BLENDFACTOR_ONE,           BRW_BLENDFACTOR_ONE},
 };
 
 /* FIXME: surface format defined in brw_defines.h, shared Sampling engine 1.7.2*/
@@ -124,8 +127,8 @@ static struct formatinfo I965TexFormats[
         {PICT_a8b8g8r8, BRW_SURFACEFORMAT_B8G8R8A8_UNORM },
         {PICT_x8b8g8r8, BRW_SURFACEFORMAT_B8G8R8X8_UNORM },
         {PICT_r5g6b5,   BRW_SURFACEFORMAT_B5G6R5_UNORM   },
-        {PICT_a1r5g5b5, BRW_SURFACEFORMAT_B5G6R5A1_UNORM },
-        {PICT_x1r5g5b5, BRW_SURFACEFORMAT_B5G6R5X1_UNORM },
+        {PICT_a1r5g5b5, BRW_SURFACEFORMAT_B5G5R5A1_UNORM },
+        {PICT_x1r5g5b5, BRW_SURFACEFORMAT_B5G5R5X1_UNORM },
         {PICT_a8,       BRW_SURFACEFORMAT_A8_UNORM	 },
 };
 
@@ -140,10 +143,10 @@ static void I965GetBlendCntl(int op, Pic
      * it as always 1.
      */
     if (PICT_FORMAT_A(dst_format) == 0 && I965BlendOp[op].dst_alpha) {
-        if (*sblend == BRW_BLENDFACT_DST_ALPHA)
-            *sblend = BRW_BLENDFACT_ONE;
-        else if (*sblend == BRW_BLENDFACT_INV_DST_ALPHA)
-            *sblend = BRW_BLENDFACT_ZERO;
+        if (*sblend == BRW_BLENDFACTOR_DST_ALPHA)
+            *sblend = BRW_BLENDFACTOR_ONE;
+        else if (*sblend == BRW_BLENDFACTOR_INV_DST_ALPHA)
+            *sblend = BRW_BLENDFACTOR_ZERO;
     }
 
     /* If the source alpha is being used, then we should only be in a case where
@@ -151,10 +154,10 @@ static void I965GetBlendCntl(int op, Pic
      * channels multiplied by the source picture's alpha.
      */
     if (pMask && pMask->componentAlpha && I965BlendOp[op].src_alpha) {
-        if (*dblend == BRW_BLENDFACT_SRC_ALPHA) {
-	    *dblend = BRW_BLENDFACT_SRC_COLR;
-        } else if (*dblend == BRW_BLENDFACT_INV_SRC_ALPHA) {
-	    *dblend = BRW_BLENDFACT_INV_SRC_COLR;
+        if (*dblend == BRW_BLENDFACTOR_SRC_ALPHA) {
+	    *dblend = BRW_BLENDFACTOR_SRC_COLOR;
+        } else if (*dblend == BRW_BLENDFACTOR_INV_SRC_ALPHA) {
+	    *dblend = BRW_BLENDFACTOR_INV_SRC_COLOR;
         }
     }
 
@@ -173,10 +176,10 @@ static Bool I965GetDestFormat(PicturePtr
         *dst_format = BRW_SURFACEFORMAT_B5G6R5_UNORM;
         break;
     case PICT_a1r5g5b5:
-    	*dst_format = BRW_SURFACEFORMAT_B5G6R5A1_UNORM;
+    	*dst_format = BRW_SURFACEFORMAT_B5G5R5A1_UNORM;
 	break;
     case PICT_x1r5g5b5:
-        *dst_format = BRW_SURFACEFORMAT_B5G6R5X1_UNORM;
+        *dst_format = BRW_SURFACEFORMAT_B5G5R5X1_UNORM;
         break;
     /* COLR_BUF_8BIT is special for YUV surfaces.  While we may end up being
      * able to use it depending on how the hardware implements it, disable it
@@ -250,7 +253,7 @@ I965EXACheckComposite(int op, PicturePtr
          * source value that we get to blend with.
          */
         if (I965BlendOp[op].src_alpha &&
-            (I965BlendOp[op].src_blend != BRW_BLENDFACT_ZERO))
+            (I965BlendOp[op].src_blend != BRW_BLENDFACTOR_ZERO))
             	I830FALLBACK("Component alpha not supported with source "
                             "alpha and source value blending.\n");
 	/* XXX: fallback now for mask with componentAlpha */
@@ -297,7 +300,7 @@ struct brw_instruction *sip_kernel;
 CARD32 *binding_table;
 int binding_table_entries; 
 
-int dest_surf_offset, src_surf_offset;
+int dest_surf_offset, src_surf_offset, mask_surf_offset;
 int src_sampler_offset, mask_sampler_offset,vs_offset;
 int sf_offset, wm_offset, cc_offset, vb_offset, cc_viewport_offset;
 int sf_kernel_offset, ps_kernel_offset, sip_kernel_offset;
@@ -308,7 +311,7 @@ int state_base_offset;
 float *vb;
 int vb_size = 4 * 4 ; /* 4 DWORDS per vertex, 4 vertices for TRIFAN*/ 
 
-int src_blend, dst_blend;
+CARD32 src_blend, dst_blend;
 
 static const CARD32 sip_kernel_static[][4] = {
 /*    wait (1) a0<1>UW a145<0,1,0>UW { align1 +  } */
@@ -380,6 +383,8 @@ static const CARD32 sf_kernel_static[][4
 };
 
 /* ps kernels */
+#define PS_KERNEL_NUM_GRF   32
+#define PS_MAX_THREADS	   32
 /* 1: no mask */
 static const CARD32 ps_kernel_static_nomask [][4] = {
 	#include "i965_composite_wm_nomask.h"
@@ -387,12 +392,12 @@ static const CARD32 ps_kernel_static_nom
 
 /* 2: mask with componentAlpha, src * mask color, XXX: later */
 static const CARD32 ps_kernel_static_maskca [][4] = {
-	#include "i965_composite_wm_maskca.h"
+/*#include "i965_composite_wm_maskca.h" */
 };
 
 /* 3: mask without componentAlpha, src * mask alpha */
 static const CARD32 ps_kernel_static_masknoca [][4] = {
-	#include "i965_composite_wm_masknoca.h"
+/*#include "i965_composite_wm_masknoca.h" */
 };
 
 Bool
@@ -403,9 +408,8 @@ I965EXAPrepareComposite(int op, PictureP
     ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
     CARD32 src_offset, src_pitch;
-    CARD32 mask_offset, mask_pitch;
+    CARD32 mask_offset = 0, mask_pitch = 0;
     CARD32 dst_format, dst_offset, dst_pitch;
-    CARD32 blendctl;
  
 ErrorF("i965 prepareComposite\n");
 
@@ -437,7 +441,6 @@ ErrorF("i965 prepareComposite\n");
 	scale_units[1][1] = pMask->drawable.height;
     }
 
-/* FIXME */
 	/* setup 3d pipeline state */
 
    binding_table_entries = 2; /* default no mask */
@@ -602,7 +605,7 @@ ErrorF("i965 prepareComposite\n");
 //   cc_state->cc5.ia_src_blend_factor = BRW_BLENDFACTOR_ONE;
 //   cc_state->cc5.ia_dest_blend_factor = BRW_BLENDFACTOR_ONE;
    cc_state->cc6.blend_function = BRW_BLENDFUNCTION_ADD;
-   I965GetBlendCntl(op, pMask, pDstPicture->format, 
+   I965GetBlendCntl(op, pMaskPicture, pDstPicture->format, 
 		    &src_blend, &dst_blend);
    cc_state->cc6.src_blend_factor = src_blend;
    cc_state->cc6.dest_blend_factor = dst_blend;
@@ -703,7 +706,7 @@ ErrorF("i965 prepareComposite\n");
 
    /* PS kernel use this sampler */
    memset(src_sampler_state, 0, sizeof(*src_sampler_state));
-   src_sampler_state->ss0.lod_peclamp = 1; /* GL mode */
+   src_sampler_state->ss0.lod_preclamp = 1; /* GL mode */
    switch(pSrcPicture->filter) {
    case PictFilterNearest:
    	src_sampler_state->ss0.min_filter = BRW_MAPFILTER_NEAREST; 
@@ -733,7 +736,7 @@ ErrorF("i965 prepareComposite\n");
 
    if (pMask) {
    	memset(mask_sampler_state, 0, sizeof(*mask_sampler_state));
-   	mask_sampler_state->ss0.lod_peclamp = 1; /* GL mode */
+   	mask_sampler_state->ss0.lod_preclamp = 1; /* GL mode */
    	switch(pMaskPicture->filter) {
    	case PictFilterNearest:
    	    mask_sampler_state->ss0.min_filter = BRW_MAPFILTER_NEAREST; 
@@ -1065,6 +1068,8 @@ void
 I965EXAComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
 		int dstX, int dstY, int w, int h)
 {
+    ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
     int srcXend, srcYend, maskXend, maskYend;
     PictVector v;
     int pMask = 1, i = 0;
diff-tree fc944859b1b9605c748162bad1c93a6303c84aae (from acdc2da77b445e9347a4c6e53e35c81763cbb0b8)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Thu Sep 28 10:36:00 2006 +0800

    [PATCH] Add simplest wm kernel program for no mask picture composite
    
    This is a try to use new gen4asm language, and will finish
    composite program for mask picture with or without CA case later.
    
    Signed-off-by: Keith Packard <keithp at neko.keithp.com>

diff --git a/src/Makefile.am b/src/Makefile.am
index 8285406..b0c6c92 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -101,6 +101,8 @@ sf_prog.h: packed_yuv_sf.g4a
 	intel-gen4asm -o sf_prog.h packed_yuv_sf.g4a
 wm_prog.h: packed_yuv_wm.g4a
 	intel-gen4asm -o wm_prog.h packed_yuv_wm.g4a
+i965_composite_wm_nomask.h: i965_composite_wm_nomask.g4a
+	intel-gen4asm -o i965_composite_wm_nomask.h i965_composite_wm_nomask.g4a
 endif
 
 if DRI
diff --git a/src/i965_composite_wm_nomask.g4a b/src/i965_composite_wm_nomask.g4a
new file mode 100644
index 0000000..8791631
--- /dev/null
+++ b/src/i965_composite_wm_nomask.g4a
@@ -0,0 +1,139 @@
+/*
+ * This's for exa composite operation in no mask picture case.
+ * The simplest case is just sending what src picture has to dst picture
+ */
+
+/* I think this should be same as in g4a program for texture video,
+   as we also use 16-pixel dispatch. and SF scale in g3 is useful for us. */
+
+/* The initial payload of the thread is always g0.
+ * WM_URB (incoming URB entries) is g3
+ * X0_R is g4
+ * X1_R is g5
+ * Y0_R is g6
+ * Y1_R is g7
+ */
+
+    /* Set up ss0.x coordinates*/
+mov (1) g4<1>F g1.8<0,1,0>UW { align1 };
+add (1) g4.4<1>F g1.8<0,1,0>UW 1UB { align1 };
+mov (1) g4.8<1>F g1.8<0,1,0>UW { align1 };
+add (1) g4.12<1>F g1.8<0,1,0>UW 1UB { align1 };
+    /* Set up ss0.y coordinates */
+mov (1) g6<1>F g1.10<0,1,0>UW { align1 };
+mov (1) g6.4<1>F g1.10<0,1,0>UW { align1 };
+add (1) g6.8<1>F g1.10<0,1,0>UW 1UB { align1 };
+add (1) g6.12<1>F g1.10<0,1,0>UW 1UB { align1 };
+    /* set up ss1.x coordinates */
+mov (1) g4.16<1>F g1.12<0,1,0>UW { align1 };
+add (1) g4.20<1>F g1.12<0,1,0>UW 1UB { align1 };
+mov (1) g4.24<1>F g1.12<0,1,0>UW { align1 };
+add (1) g4.28<1>F g1.12<0,1,0>UW 1UB { align1 };
+    /* set up ss1.y coordinates */
+mov (1) g6.16<1>F g1.14<0,1,0>UW { align1 };
+mov (1) g6.20<1>F g1.14<0,1,0>UW { align1 };
+add (1) g6.24<1>F g1.14<0,1,0>UW 1UB { align1 };
+add (1) g6.28<1>F g1.14<0,1,0>UW 1UB { align1 };
+    /* Set up ss2.x coordinates */
+mov (1) g5<1>F g1.16<0,1,0>UW { align1 };
+add (1) g5.4<1>F g1.16<0,1,0>UW 1UB { align1 };
+mov (1) g5.8<1>F g1.16<0,1,0>UW { align1 };
+add (1) g5.12<1>F g1.16<0,1,0>UW 1UB { align1 };
+    /* Set up ss2.y coordinates */
+mov (1) g7<1>F g1.18<0,1,0>UW { align1 };
+mov (1) g7.4<1>F g1.18<0,1,0>UW { align1 };
+add (1) g7.8<1>F g1.18<0,1,0>UW 1UB { align1 };
+add (1) g7.12<1>F g1.18<0,1,0>UW 1UB { align1 };
+    /* Set up ss3.x coordinates */
+mov (1) g5.16<1>F g1.20<0,1,0>UW { align1 };
+add (1) g5.20<1>F g1.20<0,1,0>UW 1UB { align1 };
+mov (1) g5.24<1>F g1.20<0,1,0>UW { align1 };
+add (1) g5.28<1>F g1.20<0,1,0>UW 1UB { align1 };
+    /* Set up ss3.y coordinates */
+mov (1) g7.16<1>F g1.22<0,1,0>UW { align1 };
+mov (1) g7.20<1>F g1.22<0,1,0>UW { align1 };
+add (1) g7.24<1>F g1.22<0,1,0>UW 1UB { align1 };
+add (1) g7.28<1>F g1.22<0,1,0>UW 1UB { align1 };
+
+    /* Now, map these screen space coordinates into texture coordinates. */
+    /* subtract screen-space X origin of vertex 0. */
+add (8) g4<1>F g4<8,8,1>F -g1<0,1,0>F { align1 };
+add (8) g5<1>F g5<8,8,1>F -g1<0,1,0>F { align1 };
+    /* scale by texture X increment */
+mul (8) g4<1>F g4<8,8,1>F g3<0,1,0>F { align1 };
+mul (8) g5<1>F g5<8,8,1>F g3<0,1,0>F { align1 };
+    /* add in texture X offset */
+add (8) g4<1>F g4<8,8,1>F g3.12<0,1,0>F { align1 };
+add (8) g5<1>F g5<8,8,1>F g3.12<0,1,0>F { align1 };
+    /* subtract screen-space Y origin of vertex 0. */
+add (8) g6<1>F g6<8,8,1>F -g1.4<0,1,0>F { align1 };
+add (8) g7<1>F g7<8,8,1>F -g1.4<0,1,0>F { align1 };
+    /* scale by texture Y increment */
+mul (8) g6<1>F g6<8,8,1>F g3.20<0,1,0>F { align1 };
+mul (8) g7<1>F g7<8,8,1>F g3.20<0,1,0>F { align1 };
+    /* add in texture Y offset */
+add (8) g6<1>F g6<8,8,1>F g3.28<0,1,0>F { align1 };
+add (8) g7<1>F g7<8,8,1>F g3.28<0,1,0>F { align1 };
+
+/* prepare sampler read back gX register, which would be written back to output */
+
+/* use simd16 sampler, param 0 is u, param 1 is v. */
+/* 'payload' loading, assuming tex coord start from g4 */
+mov (8) m1<1>F g4<8,8,1>F { align1 };
+mov (8) m2<1>F g5<8,8,1>F { align1 };  /* param 0 u in m1, m2 */
+mov (8) m3<1>F g6<8,8,1>F { align1 };
+mov (8) m4<1>F g7<8,8,1>F { align1 };  /* param 1 v in m3, m4 */
+
+/* m0 will be copied with g0, as it contains send desc */
+/* emit sampler 'send' cmd */
+send (16) 0 		/* msg reg index */
+	g12<1>UW 	/* readback */
+	g0<8,8,1>UW  	/* copy to msg start reg*/
+	sampler (1,0,F)  /* sampler message description, (binding_table,sampler_index,datatype)
+			 /* here(src->dst) we should use src_sampler and src_surface */
+	mlen 5 rlen 8 { align1 };   /* required message len 5, readback len 8 */
+
+/* if we set up read-back reg correctly, emit dataport write 'send' cmd with EOT */
+
+/* m0, m1 are all direct passed by PS thread payload */
+mov (8) m1<1>F g1<8,8,1>F { align1 };
+
+/* prepare data in m2-m5 for subspan(1,0), m6-m9 for subspan(3,2), then it's ready to write */
+/* g12 -> m2
+   g13 -> m6
+   g14 -> m3
+   g15 -> m7
+   g16 -> m4
+   g17 -> m8
+   g18 -> m5
+   g19 -> m9
+*/
+mov (8) m2<1>F g12<8,8,1>F { align1 };
+mov (8) m3<1>F g14<8,8,1>F { align1 };
+mov (8) m4<1>F g16<8,8,1>F { align1 };
+mov (8) m5<1>F g18<8,8,1>F { align1 };
+mov (8) m6<1>F g13<8,8,1>F { align1 };
+mov (8) m7<1>F g15<8,8,1>F { align1 };
+mov (8) m8<1>F g17<8,8,1>F { align1 };
+mov (8) m9<1>F g19<8,8,1>F { align1 };
+
+/* write */
+send (16) 0 null g0<8,8,1>UW write (
+	0,  /* binding_table */
+	8,  /* pixel scordboard clear, msg type simd16 single source */
+	4,  /* render target write */
+	0   /* no write commit message */
+	) 
+	mlen 10
+	rlen 0
+	{ align1 EOT };
+
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
diff-tree acdc2da77b445e9347a4c6e53e35c81763cbb0b8 (from 926d7fb09aaaabf050949ce7c6127c68441c8801)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Sep 27 16:48:43 2006 +0800

    [PATCH] Add mask sampler state
    
    
    Signed-off-by: Keith Packard <keithp at neko.keithp.com>

diff --git a/src/i965_exa_render.c b/src/i965_exa_render.c
index 942f0eb..dfa9a04 100644
--- a/src/i965_exa_render.c
+++ b/src/i965_exa_render.c
@@ -282,7 +282,7 @@ struct brw_surface_state *dest_surf_stat
 struct brw_surface_state *src_surf_state;
 struct brw_surface_state *mask_surf_state;
 struct brw_sampler_state *src_sampler_state;
-struct brw_sampler_state *mask_sampler_state;  // could just use one sampler?
+struct brw_sampler_state *mask_sampler_state;  
 
 struct brw_vs_unit_state *vs_state;
 struct brw_sf_unit_state *sf_state;
@@ -297,7 +297,8 @@ struct brw_instruction *sip_kernel;
 CARD32 *binding_table;
 int binding_table_entries; 
 
-int dest_surf_offset, src_surf_offset, src_sampler_offset, vs_offset;
+int dest_surf_offset, src_surf_offset;
+int src_sampler_offset, mask_sampler_offset,vs_offset;
 int sf_offset, wm_offset, cc_offset, vb_offset, cc_viewport_offset;
 int sf_kernel_offset, ps_kernel_offset, sip_kernel_offset;
 int binding_table_offset;
@@ -381,17 +382,17 @@ static const CARD32 sf_kernel_static[][4
 /* ps kernels */
 /* 1: no mask */
 static const CARD32 ps_kernel_static_nomask [][4] = {
-	#include "i965_composite_ps_nomask.h"
+	#include "i965_composite_wm_nomask.h"
 };
 
 /* 2: mask with componentAlpha, src * mask color, XXX: later */
 static const CARD32 ps_kernel_static_maskca [][4] = {
-	#include "i965_composite_ps_maskca.h"
+	#include "i965_composite_wm_maskca.h"
 };
 
 /* 3: mask without componentAlpha, src * mask alpha */
 static const CARD32 ps_kernel_static_masknoca [][4] = {
-	#include "i965_composite_ps_masknoca.h"
+	#include "i965_composite_wm_masknoca.h"
 };
 
 Bool
@@ -478,11 +479,14 @@ ErrorF("i965 prepareComposite\n");
    cc_viewport_offset = ALIGN(next_offset, 32);
    next_offset = cc_viewport_offset + sizeof(*cc_viewport);
 
-   // : fix for texture sampler
-   // XXX: -> use only one sampler
+   // for texture sampler
    src_sampler_offset = ALIGN(next_offset, 32);
    next_offset = src_sampler_offset + sizeof(*src_sampler_state);
 
+   if (pMask) {
+   	mask_sampler_offset = ALIGN(next_offset, 32);
+   	next_offset = mask_sampler_offset + sizeof(*mask_sampler_state);
+   }
    /* Align VB to native size of elements, for safety */
    vb_offset = ALIGN(next_offset, 8);
    next_offset = vb_offset + vb_size;
@@ -536,6 +540,9 @@ ErrorF("i965 prepareComposite\n");
 	mask_surf_state = (void *)(state_base + mask_surf_offset);
 
    src_sampler_state = (void *)(state_base + src_sampler_offset);
+   if (pMask)
+	mask_sampler_state = (void *)(state_base + mask_sampler_offset);
+
    binding_table = (void *)(state_base + binding_table_offset);
 
    vb = (void *)(state_base + vb_offset);
@@ -724,6 +731,37 @@ ErrorF("i965 prepareComposite\n");
     	   and just a single texel tex map, with R32G32B32A32_FLOAT */
    src_sampler_state->ss3.chroma_key_enable = 0; /* disable chromakey */
 
+   if (pMask) {
+   	memset(mask_sampler_state, 0, sizeof(*mask_sampler_state));
+   	mask_sampler_state->ss0.lod_peclamp = 1; /* GL mode */
+   	switch(pMaskPicture->filter) {
+   	case PictFilterNearest:
+   	    mask_sampler_state->ss0.min_filter = BRW_MAPFILTER_NEAREST; 
+   	    mask_sampler_state->ss0.mag_filter = BRW_MAPFILTER_NEAREST;
+	    break;
+   	case PictFilterBilinear:
+   	    mask_sampler_state->ss0.min_filter = BRW_MAPFILTER_LINEAR; 
+   	    mask_sampler_state->ss0.mag_filter = BRW_MAPFILTER_LINEAR;
+	    break;
+   	default:
+	    I830FALLBACK("Bad filter 0x%x\n", pMaskPicture->filter);
+   	}
+
+   	if (!pMaskPicture->repeat) {
+	/* XXX: clamp_border and set border to 0 */
+   	    mask_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP; 
+   	    mask_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
+   	    mask_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
+   	} else {
+   	    mask_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_WRAP; 
+   	    mask_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_WRAP;
+   	    mask_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_WRAP;
+    	}
+   /* XXX: ss2 has border color pointer, which should be in general state address,
+    	   and just a single texel tex map, with R32G32B32A32_FLOAT */
+   	mask_sampler_state->ss3.chroma_key_enable = 0; /* disable chromakey */
+   }
+
    /* Set up the vertex shader to be disabled (passthrough) */
    memset(vs_state, 0, sizeof(*vs_state));
    // XXX: vs URB should be defined for VF vertex URB store. done already?
@@ -783,26 +821,26 @@ ErrorF("i965 prepareComposite\n");
    wm_state->thread0.grf_reg_count = ((PS_KERNEL_NUM_GRF & ~15) / 16);
    wm_state->thread1.single_program_flow = 1;
    if (!pMask)
-       wm_state->thread1.binding_table_entry_count = 2; /* tex and fb */
+       wm_state->thread1.binding_table_entry_count = 2; /* 1 tex and fb */
    else
-       wm_state->thread1.binding_table_entry_count = 3; /* tex and fb */
+       wm_state->thread1.binding_table_entry_count = 3; /* 2 tex and fb */
 
    wm_state->thread2.scratch_space_base_pointer = 0;
    wm_state->thread2.per_thread_scratch_space = 0;
    // XXX: urb allocation
-   wm_state->thread3.dispatch_grf_start_reg = 3; /* must match kernel */
-   // wm kernel use urb from 3, see wm_program in compiler module
-   wm_state->thread3.urb_entry_read_length = 1;  /* one per pair of attrib */
    wm_state->thread3.const_urb_entry_read_length = 0;
    wm_state->thread3.const_urb_entry_read_offset = 0;
+   wm_state->thread3.urb_entry_read_length = 1;  /* one per pair of attrib */
    wm_state->thread3.urb_entry_read_offset = 0;
+   // wm kernel use urb from 3, see wm_program in compiler module
+   wm_state->thread3.dispatch_grf_start_reg = 3; /* must match kernel */
 
-   wm_state->wm4.stats_enable = 1;
-   wm_state->wm4.sampler_state_pointer = (state_base_offset + src_sampler_offset) >> 5;
+   wm_state->wm4.stats_enable = 1;  /* statistic */
+   wm_state->wm4.sampler_state_pointer = (state_base_offset + src_sampler_offset) >> 5; 
    wm_state->wm4.sampler_count = 1; /* 1-4 samplers used */
    wm_state->wm5.max_threads = PS_MAX_THREADS - 1;
    wm_state->wm5.thread_dispatch_enable = 1;
-   //just use 16-pixel dispatch, don't need to change kernel start point
+   //just use 16-pixel dispatch (4 subspans), don't need to change kernel start point
    wm_state->wm5.enable_16_pix = 1;
    wm_state->wm5.enable_8_pix = 0;
    wm_state->wm5.early_depth_test = 1;
diff-tree 926d7fb09aaaabf050949ce7c6127c68441c8801 (from ed73bbaf5c2e9d555c884037a249cf03e7f60fa0)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Sep 27 13:54:14 2006 +0800

    [PATCH] change some src sampler states
    
    sampler for mask should also be set up, and fix
    default border texel.
    
    Signed-off-by: Keith Packard <keithp at neko.keithp.com>

diff --git a/src/i965_exa_render.c b/src/i965_exa_render.c
index 24e0ba2..942f0eb 100644
--- a/src/i965_exa_render.c
+++ b/src/i965_exa_render.c
@@ -546,8 +546,8 @@ ErrorF("i965 prepareComposite\n");
 #define URB_CS_ENTRY_SIZE     0
 #define URB_CS_ENTRIES	      0
    
-#define URB_VS_ENTRY_SIZE     1	  // XXX: VUE row num? double check, 1 row is enough
-#define URB_VS_ENTRIES	      8
+#define URB_VS_ENTRY_SIZE     1	  // each 512-bit row
+#define URB_VS_ENTRIES	      8	  // we needs at least 8 entries
    
 #define URB_GS_ENTRY_SIZE     0
 #define URB_GS_ENTRIES	      0
@@ -630,6 +630,7 @@ ErrorF("i965 prepareComposite\n");
    dest_surf_state->ss2.mip_count = 0;
    dest_surf_state->ss2.render_target_rotation = 0;
    dest_surf_state->ss3.pitch = dst_pitch - 1; 
+   // tiled surface?
 
    /* Set up the source surface state buffer */
    memset(src_surf_state, 0, sizeof(*src_surf_state));
@@ -695,19 +696,33 @@ ErrorF("i965 prepareComposite\n");
 
    /* PS kernel use this sampler */
    memset(src_sampler_state, 0, sizeof(*src_sampler_state));
-   src_sampler_state->ss0.min_filter = BRW_MAPFILTER_LINEAR;
-   src_sampler_state->ss0.mag_filter = BRW_MAPFILTER_LINEAR;
+   src_sampler_state->ss0.lod_peclamp = 1; /* GL mode */
+   switch(pSrcPicture->filter) {
+   case PictFilterNearest:
+   	src_sampler_state->ss0.min_filter = BRW_MAPFILTER_NEAREST; 
+   	src_sampler_state->ss0.mag_filter = BRW_MAPFILTER_NEAREST;
+	break;
+   case PictFilterBilinear:
+   	src_sampler_state->ss0.min_filter = BRW_MAPFILTER_LINEAR; 
+   	src_sampler_state->ss0.mag_filter = BRW_MAPFILTER_LINEAR;
+	break;
+   default:
+	I830FALLBACK("Bad filter 0x%x\n", pSrcPicture->filter);
+   }
 
-   /* XXX: fix for repeat */
    if (!pSrcPicture->repeat) {
-   	src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP; // XXX: clamp_border and set border to 0?
+	/* XXX: clamp_border and set border to 0 */
+   	src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP; 
    	src_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
    	src_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
    } else {
-   	src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_WRAP; // XXX: clamp_border and set border to 0?
+   	src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_WRAP; 
    	src_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_WRAP;
    	src_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_WRAP;
    }
+   /* XXX: ss2 has border color pointer, which should be in general state address,
+    	   and just a single texel tex map, with R32G32B32A32_FLOAT */
+   src_sampler_state->ss3.chroma_key_enable = 0; /* disable chromakey */
 
    /* Set up the vertex shader to be disabled (passthrough) */
    memset(vs_state, 0, sizeof(*vs_state));
diff-tree ed73bbaf5c2e9d555c884037a249cf03e7f60fa0 (from 5a793b0dcf2d5de408b55073858fcfba6d99f994)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Mon Sep 25 14:35:51 2006 +0800

    [PATCH] Add file for i965 exa composite
    
    This does not include ps program, which will be added
    in g4a form.
    
    Signed-off-by: Keith Packard <keithp at neko.keithp.com>

diff --git a/src/Makefile.am b/src/Makefile.am
index 5309eea..8285406 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -93,7 +93,8 @@ i810_drv_la_SOURCES = \
 	 i830_exa.c \
 	 i830_xaa.c \
 	 i830_exa_render.c \
-	 i915_exa_render.c
+	 i915_exa_render.c \
+	 i965_exa_render.c
 
 if HAVE_GEN4ASM
 sf_prog.h: packed_yuv_sf.g4a
diff --git a/src/i830_exa.c b/src/i830_exa.c
index 9356c79..c5b91b0 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -121,6 +121,11 @@ extern Bool I915EXACheckComposite(int, P
 extern Bool I915EXAPrepareComposite(int, PicturePtr, PicturePtr, PicturePtr, 
 				PixmapPtr, PixmapPtr, PixmapPtr);
 
+extern Bool I965EXACheckComposite(int, PicturePtr, PicturePtr, PicturePtr);
+extern Bool I965EXAPrepareComposite(int, PicturePtr, PicturePtr, PicturePtr, 
+				PixmapPtr, PixmapPtr, PixmapPtr);
+extern void I965EXAComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, 
+			int maskY, int dstX, int dstY, int width, int height);
 /**
  * I830EXASync - wait for a command to finish
  * @pScreen: current screen
@@ -419,6 +424,8 @@ IntelEXADoneComposite(PixmapPtr pDst)
     I830Sync(pScrn);
 #endif
 }
+
+#define BRW_LINEAR_EXTRA (32*1024)
 /*
  * TODO:
  *   - Dual head?
@@ -441,7 +448,11 @@ I830EXAInit(ScreenPtr pScreen)
     pI830->EXADriverPtr->exa_minor = 0;
     pI830->EXADriverPtr->memoryBase = pI830->FbBase;
     pI830->EXADriverPtr->offScreenBase = pI830->Offscreen.Start;
-    pI830->EXADriverPtr->memorySize = pI830->Offscreen.End;
+    if (IS_I965G(pI830))
+    	pI830->EXADriverPtr->memorySize = pI830->Offscreen.End -
+					BRW_LINEAR_EXTRA; /* BRW needs state buffer*/
+    else
+    	pI830->EXADriverPtr->memorySize = pI830->Offscreen.End;
 	   
     DPRINTF(PFX, "EXA Mem: memoryBase 0x%x, end 0x%x, offscreen base 0x%x, memorySize 0x%x\n",
 		pI830->EXADriverPtr->memoryBase,
@@ -492,6 +503,11 @@ I830EXAInit(ScreenPtr pScreen)
     	pI830->EXADriverPtr->PrepareComposite = I830EXAPrepareComposite;
     	pI830->EXADriverPtr->Composite = IntelEXAComposite;
     	pI830->EXADriverPtr->DoneComposite = IntelEXADoneComposite;
+    } else if (IS_I965G(pI830)) {
+ 	pI830->EXADriverPtr->CheckComposite = I965EXACheckComposite;
+ 	pI830->EXADriverPtr->PrepareComposite = I965EXAPrepareComposite;
+ 	pI830->EXADriverPtr->Composite = I965EXAComposite;
+ 	pI830->EXADriverPtr->DoneComposite = IntelEXADoneComposite;
     }
 
     if(!exaDriverInit(pScreen, pI830->EXADriverPtr)) {
diff --git a/src/i965_exa_render.c b/src/i965_exa_render.c
new file mode 100644
index 0000000..24e0ba2
--- /dev/null
+++ b/src/i965_exa_render.c
@@ -0,0 +1,1124 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Wang Zhenyu <zhenyu.z.wang at intel.com>
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "i830.h"
+#include "i915_reg.h"
+
+/* bring in brw structs */
+#include "brw_defines.h"
+#include "brw_structs.h"
+
+#ifdef I830DEBUG
+#define DEBUG_I830FALLBACK 1
+#endif
+
+#ifdef DEBUG_I830FALLBACK
+#define I830FALLBACK(s, arg...)				\
+do {							\
+	DPRINTF(PFX, "EXA fallback: " s "\n", ##arg); 	\
+	return FALSE;					\
+} while(0)
+#else
+#define I830FALLBACK(s, arg...) 			\
+do { 							\
+	return FALSE;					\
+} while(0) 
+#endif
+
+extern Bool
+I965EXACheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+		      PicturePtr pDstPicture);
+
+extern Bool
+I965EXAPrepareComposite(int op, PicturePtr pSrcPicture,
+			PicturePtr pMaskPicture, PicturePtr pDstPicture,
+			PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst);
+
+extern void
+I965EXAComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
+		int dstX, int dstY, int width, int height);
+
+extern float scale_units[2][2];
+extern Bool is_transform[2];
+extern PictTransform *transform[2];
+
+struct blendinfo {
+    Bool dst_alpha;
+    Bool src_alpha;
+    CARD32 src_blend;
+    CARD32 dst_blend;
+};
+
+struct formatinfo {
+    int fmt;
+    CARD32 card_fmt;
+};
+
+// refer vol2, 3d rasterization 3.8.1
+
+/* XXX: bad!bad! broadwater has different blend factor definition */
+/* defined in brw_defines.h */
+static struct blendinfo I965BlendOp[] = { 
+    /* Clear */
+    {0, 0, BRW_BLENDFACT_ZERO,          BRW_BLENDFACT_ZERO},
+    /* Src */
+    {0, 0, BRW_BLENDFACT_ONE,           BRW_BLENDFACT_ZERO},
+    /* Dst */
+    {0, 0, BRW_BLENDFACT_ZERO,          BRW_BLENDFACT_ONE},
+    /* Over */
+    {0, 1, BRW_BLENDFACT_ONE,           BRW_BLENDFACT_INV_SRC_ALPHA},
+    /* OverReverse */
+    {1, 0, BRW_BLENDFACT_INV_DST_ALPHA, BRW_BLENDFACT_ONE},
+    /* In */
+    {1, 0, BRW_BLENDFACT_DST_ALPHA,     BRW_BLENDFACT_ZERO},
+    /* InReverse */
+    {0, 1, BRW_BLENDFACT_ZERO,          BRW_BLENDFACT_SRC_ALPHA},
+    /* Out */
+    {1, 0, BRW_BLENDFACT_INV_DST_ALPHA, BRW_BLENDFACT_ZERO},
+    /* OutReverse */
+    {0, 1, BRW_BLENDFACT_ZERO,          BRW_BLENDFACT_INV_SRC_ALPHA},
+    /* Atop */
+    {1, 1, BRW_BLENDFACT_DST_ALPHA,     BRW_BLENDFACT_INV_SRC_ALPHA},
+    /* AtopReverse */
+    {1, 1, BRW_BLENDFACT_INV_DST_ALPHA, BRW_BLENDFACT_SRC_ALPHA},
+    /* Xor */
+    {1, 1, BRW_BLENDFACT_INV_DST_ALPHA, BRW_BLENDFACT_INV_SRC_ALPHA},
+    /* Add */
+    {0, 0, BRW_BLENDFACT_ONE,           BRW_BLENDFACT_ONE},
+};
+
+/* FIXME: surface format defined in brw_defines.h, shared Sampling engine 1.7.2*/
+static struct formatinfo I965TexFormats[] = {
+        {PICT_a8r8g8b8, BRW_SURFACEFORMAT_R8G8B8A8_UNORM },
+        {PICT_x8r8g8b8, BRW_SURFACEFORMAT_R8G8B8X8_UNORM },
+        {PICT_a8b8g8r8, BRW_SURFACEFORMAT_B8G8R8A8_UNORM },
+        {PICT_x8b8g8r8, BRW_SURFACEFORMAT_B8G8R8X8_UNORM },
+        {PICT_r5g6b5,   BRW_SURFACEFORMAT_B5G6R5_UNORM   },
+        {PICT_a1r5g5b5, BRW_SURFACEFORMAT_B5G6R5A1_UNORM },
+        {PICT_x1r5g5b5, BRW_SURFACEFORMAT_B5G6R5X1_UNORM },
+        {PICT_a8,       BRW_SURFACEFORMAT_A8_UNORM	 },
+};
+
+static void I965GetBlendCntl(int op, PicturePtr pMask, CARD32 dst_format, 
+			     CARD32 *sblend, CARD32 *dblend)
+{
+
+    *sblend = I965BlendOp[op].src_blend;
+    *dblend = I965BlendOp[op].dst_blend;
+
+    /* If there's no dst alpha channel, adjust the blend op so that we'll treat
+     * it as always 1.
+     */
+    if (PICT_FORMAT_A(dst_format) == 0 && I965BlendOp[op].dst_alpha) {
+        if (*sblend == BRW_BLENDFACT_DST_ALPHA)
+            *sblend = BRW_BLENDFACT_ONE;
+        else if (*sblend == BRW_BLENDFACT_INV_DST_ALPHA)
+            *sblend = BRW_BLENDFACT_ZERO;
+    }
+
+    /* If the source alpha is being used, then we should only be in a case where
+     * the source blend factor is 0, and the source blend value is the mask
+     * channels multiplied by the source picture's alpha.
+     */
+    if (pMask && pMask->componentAlpha && I965BlendOp[op].src_alpha) {
+        if (*dblend == BRW_BLENDFACT_SRC_ALPHA) {
+	    *dblend = BRW_BLENDFACT_SRC_COLR;
+        } else if (*dblend == BRW_BLENDFACT_INV_SRC_ALPHA) {
+	    *dblend = BRW_BLENDFACT_INV_SRC_COLR;
+        }
+    }
+
+}
+
+
+/* FIXME */
+static Bool I965GetDestFormat(PicturePtr pDstPicture, CARD32 *dst_format)
+{
+    switch (pDstPicture->format) {
+    case PICT_a8r8g8b8:
+    case PICT_x8r8g8b8:
+        *dst_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
+        break;
+    case PICT_r5g6b5:
+        *dst_format = BRW_SURFACEFORMAT_B5G6R5_UNORM;
+        break;
+    case PICT_a1r5g5b5:
+    	*dst_format = BRW_SURFACEFORMAT_B5G6R5A1_UNORM;
+	break;
+    case PICT_x1r5g5b5:
+        *dst_format = BRW_SURFACEFORMAT_B5G6R5X1_UNORM;
+        break;
+    /* COLR_BUF_8BIT is special for YUV surfaces.  While we may end up being
+     * able to use it depending on how the hardware implements it, disable it
+     * for now while we don't know what exactly it does (what channel does it
+     * read from?
+     */
+    /*
+    case PICT_a8:
+        *dst_format = COLR_BUF_8BIT;
+        break;
+    */
+    case PICT_a4r4g4b4:
+    case PICT_x4r4g4b4:
+	*dst_format = BRW_SURFACEFORMAT_B4G4R4A4_UNORM; 
+	break;
+    default:
+        I830FALLBACK("Unsupported dest format 0x%x\n",
+                        (int)pDstPicture->format);
+    }
+
+    return TRUE;
+}
+
+static Bool I965CheckCompositeTexture(PicturePtr pPict, int unit)
+{
+    int w = pPict->pDrawable->width;
+    int h = pPict->pDrawable->height;
+    int i;
+                                                                                                                                                            
+    if ((w > 0x7ff) || (h > 0x7ff))
+        I830FALLBACK("Picture w/h too large (%dx%d)\n", w, h);
+
+    for (i = 0; i < sizeof(I965TexFormats) / sizeof(I965TexFormats[0]); i++)
+    {
+        if (I965TexFormats[i].fmt == pPict->format)
+            break;
+    }
+    if (i == sizeof(I965TexFormats) / sizeof(I965TexFormats[0]))
+        I830FALLBACK("Unsupported picture format 0x%x\n",
+                         (int)pPict->format);
+
+    /* XXX: fallback when repeat? */
+    if (pPict->repeat && pPict->repeatType != RepeatNormal)
+	I830FALLBACK("extended repeat (%d) not supported\n",
+		     pPict->repeatType);
+
+    if (pPict->filter != PictFilterNearest &&
+        pPict->filter != PictFilterBilinear)
+        I830FALLBACK("Unsupported filter 0x%x\n", pPict->filter);
+
+    return TRUE;
+}
+
+Bool
+I965EXACheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+		      PicturePtr pDstPicture)
+{
+	/* check op*/
+	/* check op with mask's componentAlpha*/
+	/* check textures */
+	/* check dst buffer format */
+    CARD32 tmp1;
+    
+    /* Check for unsupported compositing operations. */
+    if (op >= sizeof(I965BlendOp) / sizeof(I965BlendOp[0]))
+        I830FALLBACK("Unsupported Composite op 0x%x\n", op);
+                                                                                                                                                            
+    if (pMaskPicture != NULL && pMaskPicture->componentAlpha) {
+        /* Check if it's component alpha that relies on a source alpha and on
+         * the source value.  We can only get one of those into the single
+         * source value that we get to blend with.
+         */
+        if (I965BlendOp[op].src_alpha &&
+            (I965BlendOp[op].src_blend != BRW_BLENDFACT_ZERO))
+            	I830FALLBACK("Component alpha not supported with source "
+                            "alpha and source value blending.\n");
+	/* XXX: fallback now for mask with componentAlpha */
+	I830FALLBACK("mask componentAlpha not ready.\n");
+    }
+
+    if (!I965CheckCompositeTexture(pSrcPicture, 0))
+        I830FALLBACK("Check Src picture texture\n");
+    if (pMaskPicture != NULL && !I965CheckCompositeTexture(pMaskPicture, 1))
+        I830FALLBACK("Check Mask picture texture\n");
+
+    if (!I965GetDestFormat(pDstPicture, &tmp1)) 
+	I830FALLBACK("Get Color buffer format\n");
+
+    return TRUE;
+
+}
+
+#define ALIGN(i,m)    (((i) + (m) - 1) & ~((m) - 1))
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+
+int urb_vs_start, urb_vs_size;
+int urb_gs_start, urb_gs_size;
+int urb_clip_start, urb_clip_size;
+int urb_sf_start, urb_sf_size;
+int urb_cs_start, urb_cs_size;
+
+struct brw_surface_state *dest_surf_state;
+struct brw_surface_state *src_surf_state;
+struct brw_surface_state *mask_surf_state;
+struct brw_sampler_state *src_sampler_state;
+struct brw_sampler_state *mask_sampler_state;  // could just use one sampler?
+
+struct brw_vs_unit_state *vs_state;
+struct brw_sf_unit_state *sf_state;
+struct brw_wm_unit_state *wm_state;
+struct brw_cc_unit_state *cc_state;
+struct brw_cc_viewport *cc_viewport;
+
+struct brw_instruction *sf_kernel;
+struct brw_instruction *ps_kernel;
+struct brw_instruction *sip_kernel;
+
+CARD32 *binding_table;
+int binding_table_entries; 
+
+int dest_surf_offset, src_surf_offset, src_sampler_offset, vs_offset;
+int sf_offset, wm_offset, cc_offset, vb_offset, cc_viewport_offset;
+int sf_kernel_offset, ps_kernel_offset, sip_kernel_offset;
+int binding_table_offset;
+int next_offset, total_state_size;
+char *state_base;
+int state_base_offset;
+float *vb;
+int vb_size = 4 * 4 ; /* 4 DWORDS per vertex, 4 vertices for TRIFAN*/ 
+
+int src_blend, dst_blend;
+
+static const CARD32 sip_kernel_static[][4] = {
+/*    wait (1) a0<1>UW a145<0,1,0>UW { align1 +  } */
+    { 0x00000030, 0x20000108, 0x00001220, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+};
+
+/*
+ * this program computes dA/dx and dA/dy for the texture coordinates along
+ * with the base texture coordinate. It was extracted from the Mesa driver
+ */
+
+#define SF_KERNEL_NUM_GRF  10
+#define SF_KERNEL_NUM_URB  8
+#define SF_MAX_THREADS	   4
+
+static const CARD32 sf_kernel_static[][4] = {
+/*    send   0 (1) g6<1>F g1.12<0,1,0>F math mlen 1 rlen 1 { align1 +  } */
+   { 0x00000031, 0x20c01fbd, 0x0000002c, 0x01110081 },
+/*    send   0 (1) g6.4<1>F g1.20<0,1,0>F math mlen 1 rlen 1 { align1 +  } */
+   { 0x00000031, 0x20c41fbd, 0x00000034, 0x01110081 },
+/*    add (8) g7<1>F g4<8,8,1>F g3<8,8,1>F { align1 +  } */
+   { 0x00600040, 0x20e077bd, 0x008d0080, 0x008d4060 },
+/*    mul (1) g7<1>F g7<0,1,0>F g6<0,1,0>F { align1 +  } */
+   { 0x00000041, 0x20e077bd, 0x000000e0, 0x000000c0 },
+/*    mul (1) g7.4<1>F g7.4<0,1,0>F g6.4<0,1,0>F { align1 +  } */
+   { 0x00000041, 0x20e477bd, 0x000000e4, 0x000000c4 },
+/*    mov (8) m1<1>F g7<0,1,0>F { align1 +  } */
+   { 0x00600001, 0x202003be, 0x000000e0, 0x00000000 },
+/*    mov (8) m2<1>F g7.4<0,1,0>F { align1 +  } */
+   { 0x00600001, 0x204003be, 0x000000e4, 0x00000000 },
+/*    mov (8) m3<1>F g3<8,8,1>F { align1 +  } */
+   { 0x00600001, 0x206003be, 0x008d0060, 0x00000000 },
+/*    send   0 (8) a0<1>F g0<8,8,1>F urb mlen 4 rlen 0 write +0 transpose used complete EOT{ align1 +  } */
+   { 0x00600031, 0x20001fbc, 0x008d0000, 0x8640c800 },
+/*    nop (4) g0<1>UD { align1 +  } */
+   { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+   { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+   { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+   { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+   { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+   { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+   { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+   { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+};
+
+/* ps kernels */
+/* 1: no mask */
+static const CARD32 ps_kernel_static_nomask [][4] = {
+	#include "i965_composite_ps_nomask.h"
+};
+
+/* 2: mask with componentAlpha, src * mask color, XXX: later */
+static const CARD32 ps_kernel_static_maskca [][4] = {
+	#include "i965_composite_ps_maskca.h"
+};
+
+/* 3: mask without componentAlpha, src * mask alpha */
+static const CARD32 ps_kernel_static_masknoca [][4] = {
+	#include "i965_composite_ps_masknoca.h"
+};
+
+Bool
+I965EXAPrepareComposite(int op, PicturePtr pSrcPicture,
+			PicturePtr pMaskPicture, PicturePtr pDstPicture,
+			PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD32 src_offset, src_pitch;
+    CARD32 mask_offset, mask_pitch;
+    CARD32 dst_format, dst_offset, dst_pitch;
+    CARD32 blendctl;
+ 
+ErrorF("i965 prepareComposite\n");
+
+//    i965_3d_pipeline_setup(pScrn);
+//    i965_surf_setup(pScrn, pSrcPicture, pMaskPicture, pDstPicture,
+//   			pSrc, pMask, pDst);
+    // then setup blend, and shader program 
+
+    I965GetDestFormat(pDstPicture, &dst_format);
+    src_offset = exaGetPixmapOffset(pSrc);
+    src_pitch = exaGetPixmapPitch(pSrc);
+    dst_offset = exaGetPixmapOffset(pDst);
+    dst_pitch = exaGetPixmapPitch(pDst);
+    if (pMask) {
+	mask_offset = exaGetPixmapOffset(pMask);
+	mask_pitch = exaGetPixmapPitch(pMask);
+    }
+    scale_units[0][0] = pSrc->drawable.width;
+    scale_units[0][1] = pSrc->drawable.height;
+    scale_units[2][0] = pDst->drawable.width;
+    scale_units[2][1] = pDst->drawable.height;
+
+    if (!pMask) {
+	is_transform[1] = FALSE;
+	scale_units[1][0] = -1;
+	scale_units[1][1] = -1;
+    } else {
+	scale_units[1][0] = pMask->drawable.width;
+	scale_units[1][1] = pMask->drawable.height;
+    }
+
+/* FIXME */
+	/* setup 3d pipeline state */
+
+   binding_table_entries = 2; /* default no mask */
+
+   /* Set up our layout of state in framebuffer.  First the general state: */
+   next_offset = 0;
+   vs_offset = ALIGN(next_offset, 64);
+   next_offset = vs_offset + sizeof(*vs_state);
+    
+   sf_offset = ALIGN(next_offset, 32);
+   next_offset = sf_offset + sizeof(*sf_state);
+    
+   wm_offset = ALIGN(next_offset, 32);
+   next_offset = wm_offset + sizeof(*wm_state);
+    
+   cc_offset = ALIGN(next_offset, 32);
+   next_offset = cc_offset + sizeof(*cc_state);
+
+// fixup sf_kernel_static, is sf_kernel needed? or not? why? 
+//	-> just keep current sf_kernel, which will send one setup urb entry to
+//	PS kernel
+   sf_kernel_offset = ALIGN(next_offset, 64);
+   next_offset = sf_kernel_offset + sizeof (sf_kernel_static);
+
+   //XXX: ps_kernel may be seperated, fix with offset
+   ps_kernel_offset = ALIGN(next_offset, 64);
+   if (pMask) {
+	if (pMaskPicture->componentAlpha)
+	    next_offset = ps_kernel_offset + sizeof(ps_kernel_static_maskca);
+	else 
+	    next_offset = ps_kernel_offset + sizeof(ps_kernel_static_masknoca);
+   } else 
+   	next_offset = ps_kernel_offset + sizeof (ps_kernel_static_nomask);
+    
+   sip_kernel_offset = ALIGN(next_offset, 64);
+   next_offset = sip_kernel_offset + sizeof (sip_kernel_static);
+   
+   // needed?
+   cc_viewport_offset = ALIGN(next_offset, 32);
+   next_offset = cc_viewport_offset + sizeof(*cc_viewport);
+
+   // : fix for texture sampler
+   // XXX: -> use only one sampler
+   src_sampler_offset = ALIGN(next_offset, 32);
+   next_offset = src_sampler_offset + sizeof(*src_sampler_state);
+
+   /* Align VB to native size of elements, for safety */
+   vb_offset = ALIGN(next_offset, 8);
+   next_offset = vb_offset + vb_size;
+
+   /* And then the general state: */
+   //XXX: fix for texture map and target surface
+   dest_surf_offset = ALIGN(next_offset, 32);
+   next_offset = dest_surf_offset + sizeof(*dest_surf_state);
+
+   src_surf_offset = ALIGN(next_offset, 32);
+   next_offset = src_surf_offset + sizeof(*src_surf_state);
+
+   if (pMask) {
+   	mask_surf_offset = ALIGN(next_offset, 32);
+   	next_offset = mask_surf_offset + sizeof(*mask_surf_state);
+	binding_table_entries = 3;
+   }
+
+   binding_table_offset = ALIGN(next_offset, 32);
+   next_offset = binding_table_offset + (binding_table_entries * 4);
+
+   total_state_size = next_offset;
+
+   /*
+    * XXX: Use the extra space allocated at the end of the exa offscreen buffer?
+    */
+#define BRW_LINEAR_EXTRA	(32*1024)
+
+   state_base_offset = (pI830->Offscreen.End -
+			BRW_LINEAR_EXTRA);
+   
+   state_base_offset = ALIGN(state_base_offset, 64);
+   state_base = (char *)(pI830->FbBase + state_base_offset);
+   /* Set up our pointers to state structures in framebuffer.  It would probably
+    * be a good idea to fill these structures out in system memory and then dump
+    * them there, instead.
+    */
+   vs_state = (void *)(state_base + vs_offset);
+   sf_state = (void *)(state_base + sf_offset);
+   wm_state = (void *)(state_base + wm_offset);
+   cc_state = (void *)(state_base + cc_offset);
+   sf_kernel = (void *)(state_base + sf_kernel_offset);
+   ps_kernel = (void *)(state_base + ps_kernel_offset);
+   sip_kernel = (void *)(state_base + sip_kernel_offset);
+   
+   cc_viewport = (void *)(state_base + cc_viewport_offset);
+   
+   dest_surf_state = (void *)(state_base + dest_surf_offset);
+   src_surf_state = (void *)(state_base + src_surf_offset);
+   if (pMask)
+	mask_surf_state = (void *)(state_base + mask_surf_offset);
+
+   src_sampler_state = (void *)(state_base + src_sampler_offset);
+   binding_table = (void *)(state_base + binding_table_offset);
+
+   vb = (void *)(state_base + vb_offset);
+
+   /* Set up a default static partitioning of the URB, which is supposed to
+    * allow anything we would want to do, at potentially lower performance.
+    */
+#define URB_CS_ENTRY_SIZE     0
+#define URB_CS_ENTRIES	      0
+   
+#define URB_VS_ENTRY_SIZE     1	  // XXX: VUE row num? double check, 1 row is enough
+#define URB_VS_ENTRIES	      8
+   
+#define URB_GS_ENTRY_SIZE     0
+#define URB_GS_ENTRIES	      0
+   
+#define URB_CLIP_ENTRY_SIZE   0
+#define URB_CLIP_ENTRIES      0
+   
+#define URB_SF_ENTRY_SIZE     4
+#define URB_SF_ENTRIES	      8
+
+   urb_vs_start = 0;
+   urb_vs_size = URB_VS_ENTRIES * URB_VS_ENTRY_SIZE;
+   urb_gs_start = urb_vs_start + urb_vs_size;
+   urb_gs_size = URB_GS_ENTRIES * URB_GS_ENTRY_SIZE;
+   urb_clip_start = urb_gs_start + urb_gs_size;
+   urb_clip_size = URB_CLIP_ENTRIES * URB_CLIP_ENTRY_SIZE;
+   urb_sf_start = urb_clip_start + urb_clip_size;
+   urb_sf_size = URB_SF_ENTRIES * URB_SF_ENTRY_SIZE;
+   urb_cs_start = urb_sf_start + urb_sf_size;
+   urb_cs_size = URB_CS_ENTRIES * URB_CS_ENTRY_SIZE;
+
+   /* We'll be poking the state buffers that could be in use by the 3d hardware
+    * here, but we should have synced the 3D engine already in I830PutImage.
+    */
+
+// needed?
+   memset (cc_viewport, 0, sizeof (*cc_viewport));
+   cc_viewport->min_depth = -1.e35;
+   cc_viewport->max_depth = 1.e35;
+
+   /* Color calculator state */
+   memset(cc_state, 0, sizeof(*cc_state));
+   cc_state->cc0.stencil_enable = 0;   /* disable stencil */
+   cc_state->cc2.depth_test = 0;       /* disable depth test */
+   cc_state->cc2.logicop_enable = 0;   /* disable logic op */
+   cc_state->cc3.ia_blend_enable = 0;  /* blend alpha just like colors */
+   cc_state->cc3.blend_enable = 1;     /* enable color blend */
+   cc_state->cc3.alpha_test = 0;       /* disable alpha test */
+   // XXX:cc_viewport needed? 
+   cc_state->cc4.cc_viewport_state_offset = (state_base_offset + cc_viewport_offset) >> 5;
+   cc_state->cc5.dither_enable = 0;    /* disable dither */
+//   cc_state->cc5.logicop_func = 0xc;   /* COPY */
+//   cc_state->cc5.statistics_enable = 1;
+//   cc_state->cc5.ia_blend_function = BRW_BLENDFUNCTION_ADD;
+//   cc_state->cc5.ia_src_blend_factor = BRW_BLENDFACTOR_ONE;
+//   cc_state->cc5.ia_dest_blend_factor = BRW_BLENDFACTOR_ONE;
+   cc_state->cc6.blend_function = BRW_BLENDFUNCTION_ADD;
+   I965GetBlendCntl(op, pMask, pDstPicture->format, 
+		    &src_blend, &dst_blend);
+   cc_state->cc6.src_blend_factor = src_blend;
+   cc_state->cc6.dest_blend_factor = dst_blend;
+
+   /* Upload system kernel */
+   memcpy (sip_kernel, sip_kernel_static, sizeof (sip_kernel_static));
+   
+   /* Set up the state buffer for the destination surface */
+   memset(dest_surf_state, 0, sizeof(*dest_surf_state));
+   dest_surf_state->ss0.surface_type = BRW_SURFACE_2D;
+   dest_surf_state->ss0.data_return_format = BRW_SURFACERETURNFORMAT_FLOAT32;
+   // XXX: should compare with picture's cpp?...8 bit surf?
+   if (pDst->drawable.bitsPerPixel == 16) {
+      dest_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B5G6R5_UNORM;
+   } else {
+      dest_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
+   }
+   dest_surf_state->ss0.writedisable_alpha = 0;
+   dest_surf_state->ss0.writedisable_red = 0;
+   dest_surf_state->ss0.writedisable_green = 0;
+   dest_surf_state->ss0.writedisable_blue = 0;
+   dest_surf_state->ss0.color_blend = 1;
+   dest_surf_state->ss0.vert_line_stride = 0;
+   dest_surf_state->ss0.vert_line_stride_ofs = 0;
+   dest_surf_state->ss0.mipmap_layout_mode = 0;
+   dest_surf_state->ss0.render_cache_read_mode = 0;
+   
+   // XXX: fix to picture address & size
+   dest_surf_state->ss1.base_addr = dst_offset;
+   dest_surf_state->ss2.height = pDst->drawable.height - 1;
+   dest_surf_state->ss2.width = pDst->drawable.width - 1;
+   dest_surf_state->ss2.mip_count = 0;
+   dest_surf_state->ss2.render_target_rotation = 0;
+   dest_surf_state->ss3.pitch = dst_pitch - 1; 
+
+   /* Set up the source surface state buffer */
+   memset(src_surf_state, 0, sizeof(*src_surf_state));
+   src_surf_state->ss0.surface_type = BRW_SURFACE_2D;
+   if (pSrc->drawable.bitsPerPixel == 8)
+      src_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_A8_UNORM; //XXX? 
+   else if (pSrc->drawable.bitsPerPixel == 16)
+      src_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B5G6R5_UNORM;
+   else 
+      src_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
+
+   src_surf_state->ss0.writedisable_alpha = 0;
+   src_surf_state->ss0.writedisable_red = 0;
+   src_surf_state->ss0.writedisable_green = 0;
+   src_surf_state->ss0.writedisable_blue = 0;
+   src_surf_state->ss0.color_blend = 1;
+   src_surf_state->ss0.vert_line_stride = 0;
+   src_surf_state->ss0.vert_line_stride_ofs = 0;
+   src_surf_state->ss0.mipmap_layout_mode = 0;
+   src_surf_state->ss0.render_cache_read_mode = 0;
+   
+   src_surf_state->ss1.base_addr = src_offset;
+   src_surf_state->ss2.width = pSrc->drawable.width - 1;
+   src_surf_state->ss2.height = pSrc->drawable.height - 1;
+   src_surf_state->ss2.mip_count = 0;
+   src_surf_state->ss2.render_target_rotation = 0;
+   src_surf_state->ss3.pitch = src_pitch - 1; 
+
+   /* setup mask surface */
+   if (pMask) {
+   	memset(mask_surf_state, 0, sizeof(*mask_surf_state));
+	mask_surf_state->ss0.surface_type = BRW_SURFACE_2D;
+   	if (pMask->drawable.bitsPerPixel == 8)
+      	    mask_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_A8_UNORM; //XXX? 
+   	else if (pMask->drawable.bitsPerPixel == 16)
+      	    mask_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B5G6R5_UNORM;
+   	else 
+      	    mask_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
+
+   	mask_surf_state->ss0.writedisable_alpha = 0;
+   	mask_surf_state->ss0.writedisable_red = 0;
+   	mask_surf_state->ss0.writedisable_green = 0;
+   	mask_surf_state->ss0.writedisable_blue = 0;
+   	mask_surf_state->ss0.color_blend = 1;
+   	mask_surf_state->ss0.vert_line_stride = 0;
+   	mask_surf_state->ss0.vert_line_stride_ofs = 0;
+   	mask_surf_state->ss0.mipmap_layout_mode = 0;
+   	mask_surf_state->ss0.render_cache_read_mode = 0;
+   
+   	mask_surf_state->ss1.base_addr = mask_offset;
+   	mask_surf_state->ss2.width = pMask->drawable.width - 1;
+   	mask_surf_state->ss2.height = pMask->drawable.height - 1;
+   	mask_surf_state->ss2.mip_count = 0;
+   	mask_surf_state->ss2.render_target_rotation = 0;
+   	mask_surf_state->ss3.pitch = mask_pitch - 1; 
+   }
+
+   /* Set up a binding table for our surfaces.  Only the PS will use it */
+   binding_table[0] = state_base_offset + dest_surf_offset;
+   binding_table[1] = state_base_offset + src_surf_offset;
+   if (pMask)
+   	binding_table[2] = state_base_offset + mask_surf_offset;
+
+   /* PS kernel use this sampler */
+   memset(src_sampler_state, 0, sizeof(*src_sampler_state));
+   src_sampler_state->ss0.min_filter = BRW_MAPFILTER_LINEAR;
+   src_sampler_state->ss0.mag_filter = BRW_MAPFILTER_LINEAR;
+
+   /* XXX: fix for repeat */
+   if (!pSrcPicture->repeat) {
+   	src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP; // XXX: clamp_border and set border to 0?
+   	src_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
+   	src_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
+   } else {
+   	src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_WRAP; // XXX: clamp_border and set border to 0?
+   	src_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_WRAP;
+   	src_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_WRAP;
+   }
+
+   /* Set up the vertex shader to be disabled (passthrough) */
+   memset(vs_state, 0, sizeof(*vs_state));
+   // XXX: vs URB should be defined for VF vertex URB store. done already?
+   vs_state->vs6.vs_enable = 0;
+
+   // XXX: sf_kernel? keep it as now
+   /* Set up the SF kernel to do coord interp: for each attribute,
+    * calculate dA/dx and dA/dy.  Hand these interpolation coefficients
+    * back to SF which then hands pixels off to WM.
+    */
+   memcpy (sf_kernel, sf_kernel_static, sizeof (sf_kernel_static));
+
+   memset(sf_state, 0, sizeof(*sf_state));
+   sf_state->thread0.kernel_start_pointer = 
+	       (state_base_offset + sf_kernel_offset) >> 6;
+   sf_state->thread0.grf_reg_count = ((SF_KERNEL_NUM_GRF & ~15) / 16);
+   sf_state->sf1.single_program_flow = 1;
+   sf_state->sf1.binding_table_entry_count = 0;
+   sf_state->sf1.thread_priority = 0;
+   sf_state->sf1.floating_point_mode = 0; /* Mesa does this */
+   sf_state->sf1.illegal_op_exception_enable = 1;
+   sf_state->sf1.mask_stack_exception_enable = 1;
+   sf_state->sf1.sw_exception_enable = 1;
+   sf_state->thread2.per_thread_scratch_space = 0;
+   sf_state->thread2.scratch_space_base_pointer = 0; /* not used in our kernel */
+   sf_state->thread3.const_urb_entry_read_length = 0; /* no const URBs */
+   sf_state->thread3.const_urb_entry_read_offset = 0; /* no const URBs */
+   sf_state->thread3.urb_entry_read_length = 1; /* 1 URB per vertex */
+   sf_state->thread3.urb_entry_read_offset = 0;
+   sf_state->thread3.dispatch_grf_start_reg = 3;
+   sf_state->thread4.max_threads = SF_MAX_THREADS - 1;
+   sf_state->thread4.urb_entry_allocation_size = URB_SF_ENTRY_SIZE - 1;
+   sf_state->thread4.nr_urb_entries = URB_SF_ENTRIES;
+   sf_state->thread4.stats_enable = 1;
+   sf_state->sf5.viewport_transform = FALSE; /* skip viewport */
+   sf_state->sf6.cull_mode = BRW_CULLMODE_NONE;
+   sf_state->sf6.scissor = 0;
+   sf_state->sf7.trifan_pv = 2;
+   sf_state->sf6.dest_org_vbias = 0x8;
+   sf_state->sf6.dest_org_hbias = 0x8;
+
+   /* Set up the PS kernel (dispatched by WM) 
+    */
+    
+    // XXX: replace to texture blend shader, and different cases 
+   if (pMask) {
+	if (pMaskPicture->componentAlpha)
+   	    memcpy (ps_kernel, ps_kernel_static_maskca, sizeof (ps_kernel_static_maskca));
+	else
+   	    memcpy (ps_kernel, ps_kernel_static_masknoca, sizeof (ps_kernel_static_masknoca));
+   } else 
+   	memcpy (ps_kernel, ps_kernel_static_nomask, sizeof (ps_kernel_static_nomask));
+
+   memset (wm_state, 0, sizeof (*wm_state));
+   wm_state->thread0.kernel_start_pointer = 
+	    (state_base_offset + ps_kernel_offset) >> 6;
+   wm_state->thread0.grf_reg_count = ((PS_KERNEL_NUM_GRF & ~15) / 16);
+   wm_state->thread1.single_program_flow = 1;
+   if (!pMask)
+       wm_state->thread1.binding_table_entry_count = 2; /* tex and fb */
+   else
+       wm_state->thread1.binding_table_entry_count = 3; /* tex and fb */
+
+   wm_state->thread2.scratch_space_base_pointer = 0;
+   wm_state->thread2.per_thread_scratch_space = 0;
+   // XXX: urb allocation
+   wm_state->thread3.dispatch_grf_start_reg = 3; /* must match kernel */
+   // wm kernel use urb from 3, see wm_program in compiler module
+   wm_state->thread3.urb_entry_read_length = 1;  /* one per pair of attrib */
+   wm_state->thread3.const_urb_entry_read_length = 0;
+   wm_state->thread3.const_urb_entry_read_offset = 0;
+   wm_state->thread3.urb_entry_read_offset = 0;
+
+   wm_state->wm4.stats_enable = 1;
+   wm_state->wm4.sampler_state_pointer = (state_base_offset + src_sampler_offset) >> 5;
+   wm_state->wm4.sampler_count = 1; /* 1-4 samplers used */
+   wm_state->wm5.max_threads = PS_MAX_THREADS - 1;
+   wm_state->wm5.thread_dispatch_enable = 1;
+   //just use 16-pixel dispatch, don't need to change kernel start point
+   wm_state->wm5.enable_16_pix = 1;
+   wm_state->wm5.enable_8_pix = 0;
+   wm_state->wm5.early_depth_test = 1;
+
+   /* Begin the long sequence of commands needed to set up the 3D 
+    * rendering pipe
+    */
+   {
+   
+   BEGIN_LP_RING((pMask?48:46));
+   // MI_FLUSH prior to PIPELINE_SELECT
+   OUT_RING(MI_FLUSH | 
+	    MI_STATE_INSTRUCTION_CACHE_FLUSH |
+	    BRW_MI_GLOBAL_SNAPSHOT_RESET);
+   
+   /* Match Mesa driver setup */
+   OUT_RING(BRW_PIPELINE_SELECT | PIPELINE_SELECT_3D);
+   
+   /* Zero out the two base address registers so all offsets are absolute */
+   // XXX: zero out...
+   OUT_RING(BRW_STATE_BASE_ADDRESS | 4);
+   // why this's not state_base_offset? -> because later we'll always add on
+   // state_base_offset to offset params. see SIP
+   OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* Generate state base address */
+   OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* Surface state base address */
+   OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* media base addr, don't care */
+   OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY);  /* general state max addr, disabled */
+   OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY);  /* media object state max addr, disabled */
+
+   /* Set system instruction pointer */
+   OUT_RING(BRW_STATE_SIP | 0);
+   OUT_RING(state_base_offset + sip_kernel_offset); /* system instruction pointer */
+      
+   /* Pipe control */
+   // XXX: pipe control write cache before enabling color blending
+   // vol2, geometry pipeline 1.8.4
+   OUT_RING(BRW_PIPE_CONTROL |
+	    BRW_PIPE_CONTROL_NOWRITE |
+	    BRW_PIPE_CONTROL_IS_FLUSH |
+	    2);
+   OUT_RING(0);			       /* Destination address */
+   OUT_RING(0);			       /* Immediate data low DW */
+   OUT_RING(0);			       /* Immediate data high DW */
+
+   /* Binding table pointers */
+   OUT_RING(BRW_3DSTATE_BINDING_TABLE_POINTERS | 4);
+   OUT_RING(0); /* vs */
+   OUT_RING(0); /* gs */
+   OUT_RING(0); /* clip */
+   OUT_RING(0); /* sf */
+   /* Only the PS uses the binding table */
+   OUT_RING(state_base_offset + binding_table_offset); /* ps */
+
+   //ring 20
+
+   /* The drawing rectangle clipping is always on.  Set it to values that
+    * shouldn't do any clipping.
+    */
+    //XXX: fix for picture size
+   OUT_RING(BRW_3DSTATE_DRAWING_RECTANGLE | 2);	/* XXX 3 for BLC or CTG */
+   OUT_RING(0x00000000);	/* ymin, xmin */
+   OUT_RING((pScrn->virtualX - 1) |
+	    (pScrn->virtualY - 1) << 16); /* ymax, xmax */
+   OUT_RING(0x00000000);	/* yorigin, xorigin */
+
+   /* skip the depth buffer */
+   /* skip the polygon stipple */
+   /* skip the polygon stipple offset */
+   /* skip the line stipple */
+   
+   /* Set the pointers to the 3d pipeline state */
+   OUT_RING(BRW_3DSTATE_PIPELINED_POINTERS | 5);
+   OUT_RING(state_base_offset + vs_offset);  /* 32 byte aligned */
+   OUT_RING(BRW_GS_DISABLE);		     /* disable GS, resulting in passthrough */
+   OUT_RING(BRW_CLIP_DISABLE);		     /* disable CLIP, resulting in passthrough */
+   OUT_RING(state_base_offset + sf_offset);  /* 32 byte aligned */
+   OUT_RING(state_base_offset + wm_offset);  /* 32 byte aligned */
+   OUT_RING(state_base_offset + cc_offset);  /* 64 byte aligned */
+
+   /* URB fence */
+   // XXX: CS for const URB needed? if not, cs_fence should be equal to sf_fence
+   OUT_RING(BRW_URB_FENCE |
+	    UF0_CS_REALLOC |
+	    UF0_SF_REALLOC |
+	    UF0_CLIP_REALLOC |
+	    UF0_GS_REALLOC |
+	    UF0_VS_REALLOC |
+	    1);
+   OUT_RING(((urb_clip_start + urb_clip_size) << UF1_CLIP_FENCE_SHIFT) |
+	    ((urb_gs_start + urb_gs_size) << UF1_GS_FENCE_SHIFT) |
+	    ((urb_vs_start + urb_vs_size) << UF1_VS_FENCE_SHIFT));
+   OUT_RING(((urb_cs_start + urb_cs_size) << UF2_CS_FENCE_SHIFT) |
+	    ((urb_sf_start + urb_sf_size) << UF2_SF_FENCE_SHIFT));
+
+   /* Constant buffer state */
+   // XXX: needed? seems no usage, as we don't have CONSTANT_BUFFER definition
+   OUT_RING(BRW_CS_URB_STATE | 0);
+   OUT_RING(((URB_CS_ENTRY_SIZE - 1) << 4) | /* URB Entry Allocation Size */
+	    (URB_CS_ENTRIES << 0));	     /* Number of URB Entries */
+   
+   /* Set up the pointer to our vertex buffer */
+   // XXX: double check
+  // int vb_pitch = 4 * 4;  // XXX: pitch should include mask's coords? possible
+  // all three coords on one row?
+   int nelem = pMask ? 3: 2;
+   OUT_RING(BRW_3DSTATE_VERTEX_BUFFERS | 3); //should be 4n-1 -> 3
+   OUT_RING((0 << VB0_BUFFER_INDEX_SHIFT) |
+	    VB0_VERTEXDATA |
+	    ((4 * 2 * nelem) << VB0_BUFFER_PITCH_SHIFT)); 
+   		// pitch includes all vertex data, 4bytes for 1 dword, each
+		// element has 2 coords (x,y)(s0,t0), nelem to reflect possible
+		// mask
+   OUT_RING(state_base_offset + vb_offset);
+   OUT_RING(4 * nelem); // max index, prim has 4 coords
+   OUT_RING(0); // ignore for VERTEXDATA, but still there
+
+   /* Set up our vertex elements, sourced from the single vertex buffer. */
+   OUT_RING(BRW_3DSTATE_VERTEX_ELEMENTS | ((2 * nelem) - 1));  // XXX: 2n-1, (x,y) + (s0,t0) +
+						//   possible (s1, t1)
+   /* offset 0: X,Y -> {X, Y, 1.0, 1.0} */
+   OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
+	    VE0_VALID |
+	    (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
+	    (0 << VE0_OFFSET_SHIFT));
+   OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
+	    (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
+	    (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
+	    (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
+	    (0 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
+   /* offset 8: S0, T0 -> {S0, T0, 1.0, 1.0} */
+   OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
+	    VE0_VALID |
+	    (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
+	    (8 << VE0_OFFSET_SHIFT));
+   OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
+	    (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
+	    (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
+	    (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
+	    (4 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
+
+   if (pMask) {
+   	OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
+	    VE0_VALID |
+	    (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
+	    (16 << VE0_OFFSET_SHIFT));
+	OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
+	    (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
+	    (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
+	    (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
+	    (8 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); 
+		//XXX: is this has alignment issue? and thread access problem?
+	    
+   }
+   
+   ADVANCE_LP_RING();
+    
+   }
+
+    {
+	/* cc states */
+	/* dest buffer */
+	/* urbs */
+	/* binding tables */
+	/* clipping */
+	/* color blend (color calculator, dataport shared function)
+		COLOR_CALC_STATE/SURFACE_STATE(rendertarget's color blend enable
+		bit)
+		Errata!!!: brw-a/b, rendertarget 'local' color blending always
+		enabled! only control by global enable bit.
+	   surface format for blend, "Surface format table in Sampling Engine"
+	   XXX: if surface format not support, we should fallback.
+	*/
+	/* 
+	    render target should be defined in SURFACE_STATE
+	    	o render target SURFTYPE_BUFFER? 2D? Keith has 2D set.
+		o depth buffer SURFTYPE_NULL?
+	    color blend:
+	        o Errata!!: mush issue PIPE_CONTROL with Write Cache Flush
+		enable set, before transite to read-write color buffer. 
+	    	o disable pre/post-blending clamping
+		o enable color buffer blending enable in COLOR_CALC_STATE,(vol2, 3d rasterization 3.8) 
+		  enable color blending enable in SURFACE_STATE.(shared,
+		  sampling engine 1.7) 
+		  disable depth test
+		o (we don't use BLENDFACT_SRC_ALPHA_SATURATE, so don't care
+		the Errata for independent alpha blending, just use color
+		blending factor for all) disable independent alpha blending
+		in COLOR_CALC_STATE
+		o set src/dst blend factor in COLOR_CALC_STATE
+
+	*/
+    }
+
+	/* shader program 
+		o use sampler shared function for texture data
+		o submit result to dataport for later color blending */
+    {
+	 /* PS program:
+	 	o declare sampler and variables??
+		o 'send' cmd to Sampling Engine to load 'src' picture
+		o if (!pMask) then 'send' 'src' texture value to DataPort
+		target render cache
+		o else 
+		    - 'send' cmd to SE to load 'mask' picture
+		    - if no alpha, force to 1 (move 1 to W element of mask)
+		    - if (mask->componentAlpha) then mul 'src' & 'mask', 'send'
+		    	output to DataPort render cache
+		    - else mul 'src' & 'mask''s W element(alpha), 'send' output
+		    	to Dataport render cache
+	 */
+
+    }
+
+#ifdef I830DEBUG
+    ErrorF("try to sync to show any errors...");
+    I830Sync(pScrn);
+#endif
+    return TRUE;
+}	
+
+void
+I965EXAComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
+		int dstX, int dstY, int w, int h)
+{
+    int srcXend, srcYend, maskXend, maskYend;
+    PictVector v;
+    int pMask = 1, i = 0;
+
+    DPRINTF(PFX, "Composite: srcX %d, srcY %d\n\t maskX %d, maskY %d\n\t"
+	    "dstX %d, dstY %d\n\twidth %d, height %d\n\t"
+	    "src_scale_x %f, src_scale_y %f, "
+	    "mask_scale_x %f, mask_scale_y %f\n",
+	    srcX, srcY, maskX, maskY, dstX, dstY, w, h,
+	    scale_units[0][0], scale_units[0][1],
+	    scale_units[1][0], scale_units[1][1]);
+
+    if (scale_units[1][0] == -1 || scale_units[1][1] == -1) {
+	pMask = 0;
+    }
+
+    srcXend = srcX + w;
+    srcYend = srcY + h;
+    maskXend = maskX + w;
+    maskYend = maskY + h;
+    if (is_transform[0]) {
+        v.vector[0] = IntToxFixed(srcX);
+        v.vector[1] = IntToxFixed(srcY);
+        v.vector[2] = xFixed1;
+        PictureTransformPoint(transform[0], &v);
+        srcX = xFixedToInt(v.vector[0]);
+        srcY = xFixedToInt(v.vector[1]);
+        v.vector[0] = IntToxFixed(srcXend);
+        v.vector[1] = IntToxFixed(srcYend);
+        v.vector[2] = xFixed1;
+        PictureTransformPoint(transform[0], &v);
+        srcXend = xFixedToInt(v.vector[0]);
+        srcYend = xFixedToInt(v.vector[1]);
+    }
+    if (is_transform[1]) {
+        v.vector[0] = IntToxFixed(maskX);
+        v.vector[1] = IntToxFixed(maskY);
+        v.vector[2] = xFixed1;
+        PictureTransformPoint(transform[1], &v);
+        maskX = xFixedToInt(v.vector[0]);
+        maskY = xFixedToInt(v.vector[1]);
+        v.vector[0] = IntToxFixed(maskXend);
+        v.vector[1] = IntToxFixed(maskYend);
+        v.vector[2] = xFixed1;
+        PictureTransformPoint(transform[1], &v);
+        maskXend = xFixedToInt(v.vector[0]);
+        maskYend = xFixedToInt(v.vector[1]);
+    }
+
+    DPRINTF(PFX, "After transform: srcX %d, srcY %d,srcXend %d, srcYend %d\n\t"
+		"maskX %d, maskY %d, maskXend %d, maskYend %d\n\t"
+		"dstX %d, dstY %d\n", srcX, srcY, srcXend, srcYend,
+		maskX, maskY, maskXend, maskYend, dstX, dstY);
+
+ 
+    vb[i++] = (float)dstX;
+    vb[i++] = (float)dstY;
+    vb[i++] = (float)srcX / scale_units[0][0];
+    vb[i++] = (float)srcY / scale_units[0][1];
+    if (pMask) {
+        vb[i++] = (float)maskX / scale_units[1][0];
+        vb[i++] = (float)maskY / scale_units[1][1];
+    }
+
+    vb[i++] = (float)dstX;
+    vb[i++] = (float)(dstY + h);
+    vb[i++] = (float)srcX / scale_units[0][0];
+    vb[i++] = (float)srcYend / scale_units[0][1];
+    if (pMask) {
+        vb[i++] = (float)maskX / scale_units[1][0];
+        vb[i++] = (float)maskYend / scale_units[1][1];
+    }
+
+    vb[i++] = (float)(dstX + w);
+    vb[i++] = (float)(dstY + h);
+    vb[i++] = (float)srcXend / scale_units[0][0];
+    vb[i++] = (float)srcYend / scale_units[0][1];
+    if (pMask) {
+        vb[i++] = (float)maskXend / scale_units[1][0];
+        vb[i++] = (float)maskYend / scale_units[1][1];
+    }
+
+    vb[i++] = (float)(dstX + w);
+    vb[i++] = (float)dstY;
+    vb[i++] = (float)srcXend / scale_units[0][0];
+    vb[i++] = (float)srcY / scale_units[0][1];
+    if (pMask) {
+        vb[i++] = (float)maskXend / scale_units[1][0];
+        vb[i++] = (float)maskY / scale_units[1][1];
+    }
+
+    {
+      BEGIN_LP_RING(6);
+      OUT_RING(BRW_3DPRIMITIVE | 
+	       BRW_3DPRIMITIVE_VERTEX_SEQUENTIAL |
+	       (_3DPRIM_TRIFAN << BRW_3DPRIMITIVE_TOPOLOGY_SHIFT) | 
+	       (0 << 9) |  /* CTG - indirect vertex count */
+	       4);
+      OUT_RING(4);  /* vertex count per instance */
+      OUT_RING(0); /* start vertex offset */
+      OUT_RING(1); /* single instance */
+      OUT_RING(0); /* start instance location */
+      OUT_RING(0); /* index buffer offset, ignored */
+      ADVANCE_LP_RING();
+    }
+#ifdef I830DEBUG
+    ErrorF("sync after 3dprimitive");
+    I830Sync(pScrn);
+#endif
+}
diff-tree 5a793b0dcf2d5de408b55073858fcfba6d99f994 (from parents)
Merge: f188525030a8fac59e41520449b1aec9b123e4ea 394124ceaadb46d976ad5c3bdeb1b77d351c57f6
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Wed Jan 3 21:54:05 2007 -0800

    Merge branch 'modesetting-origin' into modesetting

diff-tree f188525030a8fac59e41520449b1aec9b123e4ea (from 5057769d3a7c1b3a94f49bbff47b9697f368d975)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Wed Jan 3 21:53:07 2007 -0800

    Add interlace defines for pipeconf regs

diff --git a/src/i810_reg.h b/src/i810_reg.h
index 7c85cff..c2eb854 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -1683,6 +1683,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define PIPEACONF_PALETTE	0
 #define PIPEACONF_GAMMA 	(1<<24)
 #define PIPECONF_FORCE_BORDER	(1<<25)
+#define PIPECONF_PROGRESSIVE	(0 << 21)
+#define PIPECONF_INTERLACE_W_FIELD_INDICATION	(6 << 21)
+#define PIPECONF_INTERLACE_FIELD_0_ONLY		(7 << 21)
 
 #define PIPEAGCMAXRED		0x70010
 #define PIPEAGCMAXGREEN		0x70014
diff-tree 394124ceaadb46d976ad5c3bdeb1b77d351c57f6 (from 69f250af60220a875f4a04c6d682bffa352281e4)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Jan 2 16:57:33 2007 -0800

    Add per-CRTC gamma control support for RandR.
    
    This makes the CRTCs now always run in gamma-enabled mode, rather than having
    flaky logic for switching modes.  Also, it should clear up issues with the LUTs
    being uninitialized when outputs are first brought up.

diff --git a/src/i830.h b/src/i830.h
index c2670cd..d5ca5d4 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -194,7 +194,8 @@ extern const char *i830_output_type_name
 
 typedef struct _I830CrtcPrivateRec {
     int			    pipe;
-    Bool		    gammaEnabled;
+    /* Lookup table values to be set when the CRTC is enabled */
+    CARD8 lut_r[256], lut_g[256], lut_b[256];
 } I830CrtcPrivateRec, *I830CrtcPrivatePtr;
 
 #define I830CrtcPrivate(c) ((I830CrtcPrivatePtr) (c)->driver_private)
@@ -221,7 +222,6 @@ enum last_3d {
 
 typedef struct _I830PipeRec {
    Bool		  enabled;
-   Bool		  gammaEnabled;
    int		  x;
    int		  y;
    Bool		  cursorInRange;
diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index cb1585f..81cb3bd 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -130,9 +130,7 @@ I830SetPipeCursor (xf86CrtcPtr crtc, Boo
 	    temp = INREG(cursor_control);
 	    temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
 	    if (pI830->CursorIsARGB) {
-		temp |= CURSOR_MODE_64_ARGB_AX;
-		if (intel_crtc->gammaEnabled)
-		    temp |= MCURSOR_GAMMA_ENABLE;
+		temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
 	    } else
 		temp |= CURSOR_MODE_64_4C_AX;
 	    
@@ -144,9 +142,7 @@ I830SetPipeCursor (xf86CrtcPtr crtc, Boo
 	    temp &= ~(CURSOR_FORMAT_MASK);
 	    temp |= CURSOR_ENABLE;
 	    if (pI830->CursorIsARGB) {
-		temp |= CURSOR_FORMAT_ARGB;
-		if (intel_crtc->gammaEnabled)
-		    temp |= CURSOR_GAMMA_ENABLE;
+		temp |= CURSOR_FORMAT_ARGB | CURSOR_GAMMA_ENABLE;
 	    } else
 		temp |= CURSOR_FORMAT_3C;
 	    OUTREG(CURSOR_CONTROL, temp);
diff --git a/src/i830_display.c b/src/i830_display.c
index d124ba0..f47a9db 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -536,6 +536,8 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mod
 	    OUTREG(dspbase_reg, INREG(dspbase_reg));
 	}
 
+	i830_crtc_load_lut(crtc);
+
 	/* Give the overlay scaler a chance to enable if it's on this pipe */
 	i830_crtc_dpms_video(crtc, TRUE);
 	break;
@@ -718,10 +720,10 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
 	dpll |= PLL_REF_INPUT_DREFCLK;
 
     /* Set up the display plane register */
-    dspcntr = 0;
+    dspcntr = DISPPLANE_GAMMA_ENABLE;
     switch (pScrn->bitsPerPixel) {
     case 8:
-	dspcntr |= DISPPLANE_8BPP | DISPPLANE_GAMMA_ENABLE;
+	dspcntr |= DISPPLANE_8BPP;
 	break;
     case 16:
 	if (pScrn->depth == 15)
@@ -736,10 +738,6 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
 	FatalError("unknown display bpp\n");
     }
 
-    if (intel_crtc->gammaEnabled) {
- 	dspcntr |= DISPPLANE_GAMMA_ENABLE;
-    }
-
     if (pipe == 0)
 	dspcntr |= DISPPLANE_SEL_PIPE_A;
     else
@@ -840,6 +838,48 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
     i830WaitForVblank(pScrn);
 }
 
+
+/** Loads the palette/gamma unit for the CRTC with the prepared values */
+void
+i830_crtc_load_lut(xf86CrtcPtr crtc)
+{
+    ScrnInfoPtr pScrn = crtc->scrn;
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+    int palreg = (intel_crtc->pipe == 0) ? PALETTE_A : PALETTE_B;
+    int i;
+
+    /* The clocks have to be on to load the palette. */
+    if (!crtc->enabled)
+	return;
+
+    for (i = 0; i < 256; i++) {
+	OUTREG(palreg + 4 * i,
+	       (intel_crtc->lut_r[i] << 16) |
+	       (intel_crtc->lut_g[i] << 8) |
+	       intel_crtc->lut_b[i]);
+    }
+}
+
+/** Sets the color ramps on behalf of RandR */
+static void
+i830_crtc_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue,
+		    int size)
+{
+    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+    int i;
+
+    assert(size == 256);
+
+    for (i = 0; i < 256; i++) {
+	intel_crtc->lut_r[i] = red[i] >> 8;
+	intel_crtc->lut_g[i] = green[i] >> 8;
+	intel_crtc->lut_b[i] = blue[i] >> 8;
+    }
+
+    i830_crtc_load_lut(crtc);
+}
+
 /**
  * Sets the given video mode on the given pipe.
  *
@@ -1147,6 +1187,7 @@ static const xf86CrtcFuncsRec i830_crtc_
     .restore = NULL, /* XXX */
     .mode_fixup = i830_crtc_mode_fixup,
     .mode_set = i830_crtc_mode_set,
+    .gamma_set = i830_crtc_gamma_set,
     .destroy = NULL, /* XXX */
 };
 
@@ -1155,6 +1196,7 @@ i830_crtc_init(ScrnInfoPtr pScrn, int pi
 {
     xf86CrtcPtr crtc;
     I830CrtcPrivatePtr intel_crtc;
+    int i;
 
     crtc = xf86CrtcCreate (pScrn, &i830_crtc_funcs);
     if (crtc == NULL)
@@ -1163,6 +1205,12 @@ i830_crtc_init(ScrnInfoPtr pScrn, int pi
     intel_crtc = xnfcalloc (sizeof (I830CrtcPrivateRec), 1);
     intel_crtc->pipe = pipe;
 
+    /* Initialize the LUTs for when we turn on the CRTC. */
+    for (i = 0; i < 256; i++) {
+	intel_crtc->lut_r[i] = i;
+	intel_crtc->lut_g[i] = i;
+	intel_crtc->lut_b[i] = i;
+    }
     crtc->driver_private = intel_crtc;
 }
 
diff --git a/src/i830_display.h b/src/i830_display.h
index 5517d27..66ab17e 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -42,3 +42,4 @@ xf86CrtcPtr i830GetLoadDetectPipe(xf86Ou
 void i830ReleaseLoadDetectPipe(xf86OutputPtr output);
 Bool i830PipeInUse(xf86CrtcPtr crtc);
 void i830_crtc_init(ScrnInfoPtr pScrn, int pipe);
+void i830_crtc_load_lut(xf86CrtcPtr crtc);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 694c96f..94cba05 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -579,106 +579,67 @@ I830LoadPalette(ScrnInfoPtr pScrn, int n
 		LOCO * colors, VisualPtr pVisual)
 {
    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-   I830Ptr pI830;
    int i,j, index;
-   unsigned char r, g, b;
-   CARD32 val, temp;
-   int palreg;
-   int dspreg, dspbase, dspsurf;
    int p;
+   CARD16 lut_r[256], lut_g[256], lut_b[256];
 
    DPRINTF(PFX, "I830LoadPalette: numColors: %d\n", numColors);
-   pI830 = I830PTR(pScrn);
 
-   for(p=0; p < xf86_config->num_crtc; p++) 
-   {
+   for(p = 0; p < xf86_config->num_crtc; p++) {
       xf86CrtcPtr	   crtc = xf86_config->crtc[p];
       I830CrtcPrivatePtr   intel_crtc = crtc->driver_private;
 
-      if (p == 0) {
-         palreg = PALETTE_A;
-         dspreg = DSPACNTR;
-         dspbase = DSPABASE;
-	 dspsurf = DSPASURF;
-      } else {
-         palreg = PALETTE_B;
-         dspreg = DSPBCNTR;
-         dspbase = DSPBBASE;
-	 dspsurf = DSPBSURF;
+      /* Initialize to the old lookup table values. */
+      for (i = 0; i < 256; i++) {
+	 lut_r[i] = intel_crtc->lut_r[i] << 8;
+	 lut_g[i] = intel_crtc->lut_g[i] << 8;
+	 lut_b[i] = intel_crtc->lut_b[i] << 8;
       }
 
-      if (crtc->enabled == 0)
-	 continue;  
-
-      intel_crtc->gammaEnabled = 1;
-      
-      /* To ensure gamma is enabled we need to turn off and on the plane */
-      temp = INREG(dspreg);
-      OUTREG(dspreg, temp & ~(1<<31));
-      OUTREG(dspbase, INREG(dspbase));
-      OUTREG(dspreg, temp | DISPPLANE_GAMMA_ENABLE);
-      OUTREG(dspbase, INREG(dspbase));
-      if (IS_I965G(pI830))
-	 OUTREG(dspsurf, INREG(dspsurf));
-
-      /* It seems that an initial read is needed. */
-      temp = INREG(palreg);
-
       switch(pScrn->depth) {
       case 15:
-        for (i = 0; i < numColors; i++) {
-         index = indices[i];
-         r = colors[index].red;
-         g = colors[index].green;
-         b = colors[index].blue;
-	 val = (r << 16) | (g << 8) | b;
-         for (j = 0; j < 8; j++) {
-	    OUTREG(palreg + index * 32 + (j * 4), val);
+	 for (i = 0; i < numColors; i++) {
+	    index = indices[i];
+	    for (j = 0; j < 8; j++) {
+	       lut_r[index * 8 + j] = colors[index].red << 8;
+	       lut_g[index * 8 + j] = colors[index].green << 8;
+	       lut_b[index * 8 + j] = colors[index].blue << 8;
+	    }
          }
-        }
-      break;
+	 break;
       case 16:
-        for (i = 0; i < numColors; i++) {
-         index = indices[i];
-	 r   = colors[index / 2].red;
-	 g   = colors[index].green;
-	 b   = colors[index / 2].blue;
-
-	 val = (r << 16) | (g << 8) | b;
-	 OUTREG(palreg + index * 16, val);
-	 OUTREG(palreg + index * 16 + 4, val);
-	 OUTREG(palreg + index * 16 + 8, val);
-	 OUTREG(palreg + index * 16 + 12, val);
-
-   	 if (index <= 31) {
-            r   = colors[index].red;
-	    g   = colors[(index * 2) + 1].green;
-	    b   = colors[index].blue;
-
-	    val = (r << 16) | (g << 8) | b;
-	    OUTREG(palreg + index * 32, val);
-	    OUTREG(palreg + index * 32 + 4, val);
-	    OUTREG(palreg + index * 32 + 8, val);
-	    OUTREG(palreg + index * 32 + 12, val);
-	 }
-        }
+	 for (i = 0; i < numColors; i++) {
+	    index = indices[i];
+
+	    if (i <= 31) {
+	       for (j = 0; j < 8; j++) {
+		  lut_r[index * 8 + j] = colors[index].red << 8;
+		  lut_b[index * 8 + j] = colors[index].blue << 8;
+	       }
+	    }
+
+	    for (j = 0; j < 4; j++) {
+	       lut_g[index * 4 + j] = colors[index].green << 8;
+	    }
+         }
         break;
       default:
-        for(i = 0; i < numColors; i++) {
-	 index = indices[i];
-	 r = colors[index].red;
-	 g = colors[index].green;
-	 b = colors[index].blue;
-	 val = (r << 16) | (g << 8) | b;
-	 OUTREG(palreg + index * 4, val);
-        }
-        break;
-     }
+	 for (i = 0; i < numColors; i++) {
+	    index = indices[i];
+	    lut_r[index] = colors[index].red << 8;
+	    lut_g[index] = colors[index].green << 8;
+	    lut_b[index] = colors[index].blue << 8;
+	 }
+	 break;
+      }
+
+      /* Make the change through RandR */
+#ifdef RANDR_12_INTERFACE
+      RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b);
+#else
+      crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256);
+#endif
    }
-   
-   /* Enable gamma for Cursor if ARGB */
-   if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn)
-      pI830->CursorInfoRec->ShowCursor(pScrn);
 }
 
 int
diff --git a/src/i830_randr.c b/src/i830_randr.c
index 83cf023..533322b 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -663,9 +663,17 @@ xf86RandR12CrtcSet (ScreenPtr	pScreen,
 
 static Bool
 xf86RandR12CrtcSetGamma (ScreenPtr    pScreen,
-		       RRCrtcPtr    crtc)
+			 RRCrtcPtr    randr_crtc)
 {
-    return FALSE;
+    xf86CrtcPtr		crtc = randr_crtc->devPrivate;
+
+    if (crtc->funcs->gamma_set == NULL)
+	return FALSE;
+
+    crtc->funcs->gamma_set(crtc, randr_crtc->gammaRed, randr_crtc->gammaGreen,
+			   randr_crtc->gammaBlue, randr_crtc->gammaSize);
+
+    return TRUE;
 }
 
 /**
diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h
index 2555c55..8fea162 100644
--- a/src/i830_xf86Crtc.h
+++ b/src/i830_xf86Crtc.h
@@ -89,6 +89,11 @@ typedef struct _xf86CrtcFuncs {
 		DisplayModePtr mode,
 		DisplayModePtr adjusted_mode);
 
+    /* Set the color ramps for the CRTC to the given values. */
+    void
+    (*gamma_set)(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue,
+		 int size);
+
     /**
      * Clean up driver-specific bits of the crtc
      */
diff-tree 69f250af60220a875f4a04c6d682bffa352281e4 (from parents)
Merge: 232e2094321dbcdd6a67ef230eb50494a1c7d6df d960deab39eef91fb82b9f23118323aeb4c9c63e
Author: Keith Packard <keithp at mandolin.keithp.com>
Date:   Wed Jan 3 00:39:15 2007 -0800

    Merge branch 'modesetting-origin' into modesetting

diff-tree 232e2094321dbcdd6a67ef230eb50494a1c7d6df (from 58e797b2caa6effa5455fc1f13dc4c58d0658744)
Author: Keith Packard <keithp at mandolin.keithp.com>
Date:   Wed Jan 3 00:38:34 2007 -0800

    Allow initial position to be set in config file. Increase 965 max size.
    
    Add relative and absolute position configuration code, using per-output
    monitor sections. Options include:
    
    	PreferredMode	selects a preferred mode for this output by name
    	Position	absolute position, x and y in a single string.
    
    	Below		relative positions; argument names other monitor.
    	RightOf
    	Above
    	LeftOf
    
    	Enable		force the monitor to be disabled by setting
    	Disable		enable to no or disable to yes.
    
    	MinClock	Set valid clock ranges
    	MaxClock
    
    Monitor sections can also include sync ranges, physical size and mode lines
    as documented in xorg.conf(5).
    
    Monitors are associated with outputs through options in the Device section:
    
    	Option "monitor-VGA" "My VGA Monitor"
    
    Output named 'VGA' will use monitor section "My VGA Monitor".

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 5264767..694c96f 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -912,7 +912,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    Bool enable;
    const char *chipname;
    int num_pipe;
-   int max_width;
+   int max_width, max_height;
 #ifdef XF86DRI
    unsigned long savedMMSize;
 #endif
@@ -1183,10 +1183,16 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
    
    if (IS_I965G(pI830))
+   {
       max_width = 16384;
+      max_height = 4096;
+   }
    else
-      max_width = 8192 / pI830->cpp;
-   xf86CrtcSetSizeRange (pScrn, 320, 200, max_width, 2048);
+   {
+      max_width = 2048;
+      max_height = 2048;
+   }
+   xf86CrtcSetSizeRange (pScrn, 320, 200, max_width, max_height);
 
    /* Some of the probing needs MMIO access, so map it here. */
    I830MapMMIO(pScrn);
@@ -1830,14 +1836,14 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 	      pI830->pEnt->device->videoRam ? X_CONFIG : X_DEFAULT,
 	      "VideoRam: %d KB\n", pScrn->videoRam);
 
-   if (!IS_I965G(pI830) && pScrn->displayWidth * pI830->cpp > 8192) {
+   if (!IS_I965G(pI830) && pScrn->displayWidth > 2048) {
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		 "Cannot support DRI with frame buffer stride > 8K.\n");
+		 "Cannot support DRI with frame buffer width > 2048.\n");
       pI830->disableTiling = TRUE;
       pI830->directRenderingDisabled = TRUE;
    }
 
-   if (pScrn->virtualY > 2048) {
+   if (!IS_I965G(pI830) && pScrn->virtualY > 2048) {
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot support > 2048 vertical lines. disabling acceleration.\n");
       pI830->noAccel = TRUE;
    }
@@ -3047,7 +3053,8 @@ i830AdjustFrame(int scrnIndex, int x, in
    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
    I830Ptr pI830 = I830PTR(pScrn);
-   xf86CrtcPtr	crtc = config->output[config->compat_output]->crtc;
+   xf86OutputPtr  output = config->output[config->compat_output];
+   xf86CrtcPtr	crtc = output->crtc;
 
    DPRINTF(PFX, "i830AdjustFrame: y = %d (+ %d), x = %d (+ %d)\n",
 	   x, pI830->xoffset, y, pI830->yoffset);
@@ -3059,7 +3066,7 @@ i830AdjustFrame(int scrnIndex, int x, in
 	 (*pI830->AccelInfoRec->Sync)(pScrn);
 	 pI830->AccelInfoRec->NeedToSync = FALSE;
       }
-      i830PipeSetBase(crtc, x, y);
+      i830PipeSetBase(crtc, output->initial_x + x, output->initial_y + y);
    }
 }
 
@@ -3596,7 +3603,7 @@ I830CheckDevicesTimer(OsTimerPtr timer, 
        * is this.
        */
       
-      xf86ProbeOutputModes (pScrn);
+      xf86ProbeOutputModes (pScrn, 0, 0);
       xf86SetScrnInfoModes (pScrn);
       I830DGAReInit (pScrn->pScreen);
       xf86SwitchMode(pScrn->pScreen, pScrn->currentMode);
diff --git a/src/i830_randr.c b/src/i830_randr.c
index d5ccce3..83cf023 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -95,7 +95,7 @@ xf86RandR12GetInfo (ScreenPtr pScreen, R
     }
 
     /* Re-probe the outputs for new monitors or modes */
-    xf86ProbeOutputModes (scrp);
+    xf86ProbeOutputModes (scrp, 0, 0);
     xf86SetScrnInfoModes (scrp);
     I830DGAReInit (pScreen);
 
@@ -818,7 +818,7 @@ xf86RandR12GetInfo12 (ScreenPtr pScreen,
 {
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
 
-    xf86ProbeOutputModes (pScrn);
+    xf86ProbeOutputModes (pScrn, 0, 0);
     xf86SetScrnInfoModes (pScrn);
     I830DGAReInit (pScreen);
     return xf86RandR12SetInfo12 (pScreen);
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index b5116be..19b4b93 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -1207,7 +1207,12 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
     }
     strcpy (name, name_prefix);
     strcat (name, name_suffix);
-    xf86OutputRename (output, name);
+    if (!xf86OutputRename (output, name))
+    {
+	xf86OutputDestroy (output);
+	return;
+    }
+	
     
     /* Set the input timing to the screen. Assume always input 0. */
     i830_sdvo_set_target_input(output, TRUE, FALSE);
diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index a0f44df..ceb8f2e 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -127,6 +127,33 @@ xf86CrtcDestroy (xf86CrtcPtr crtc)
 
 extern XF86ConfigPtr xf86configptr;
 
+typedef enum {
+    OPTION_PREFERRED_MODE,
+    OPTION_POSITION,
+    OPTION_BELOW,
+    OPTION_RIGHT_OF,
+    OPTION_ABOVE,
+    OPTION_LEFT_OF,
+    OPTION_ENABLE,
+    OPTION_DISABLE,
+    OPTION_MIN_CLOCK,
+    OPTION_MAX_CLOCK,
+} OutputOpts;
+
+static OptionInfoRec xf86OutputOptions[] = {
+    {OPTION_PREFERRED_MODE, "PreferredMode",	OPTV_STRING,  {0}, FALSE },
+    {OPTION_POSITION,	    "Position",		OPTV_STRING,  {0}, FALSE },
+    {OPTION_BELOW,	    "Below",		OPTV_STRING,  {0}, FALSE },
+    {OPTION_RIGHT_OF,	    "RightOf",		OPTV_STRING,  {0}, FALSE },
+    {OPTION_ABOVE,	    "Above",		OPTV_STRING,  {0}, FALSE },
+    {OPTION_LEFT_OF,	    "LeftOf",		OPTV_STRING,  {0}, FALSE },
+    {OPTION_ENABLE,	    "Enable",		OPTV_BOOLEAN, {0}, FALSE },
+    {OPTION_DISABLE,	    "Disable",		OPTV_BOOLEAN, {0}, FALSE },
+    {OPTION_MIN_CLOCK,	    "MinClock",		OPTV_FREQ,    {0}, FALSE },
+    {OPTION_MAX_CLOCK,	    "MaxClock",		OPTV_FREQ,    {0}, FALSE },
+    {-1,		    NULL,		OPTV_NONE,    {0}, FALSE },
+};
+
 static void
 xf86OutputSetMonitor (xf86OutputPtr output)
 {
@@ -134,6 +161,12 @@ xf86OutputSetMonitor (xf86OutputPtr outp
     static const char monitor_prefix[] = "monitor-";
     char    *monitor;
 
+    if (output->options)
+	xfree (output->options);
+
+    output->options = xnfalloc (sizeof (xf86OutputOptions));
+    memcpy (output->options, xf86OutputOptions, sizeof (xf86OutputOptions));
+    
     option_name = xnfalloc (strlen (monitor_prefix) +
 			    strlen (output->name) + 1);
     strcpy (option_name, monitor_prefix);
@@ -144,7 +177,24 @@ xf86OutputSetMonitor (xf86OutputPtr outp
     else
 	xf86MarkOptionUsedByName (output->scrn->options, option_name);
     xfree (option_name);
-    output->conf_monitor = xf86findMonitor (monitor, xf86configptr->conf_monitor_lst);
+    output->conf_monitor = xf86findMonitor (monitor,
+					    xf86configptr->conf_monitor_lst);
+    if (output->conf_monitor)
+	xf86ProcessOptions (output->scrn->scrnIndex,
+			    output->conf_monitor->mon_option_lst,
+			    output->options);
+}
+
+static Bool
+xf86OutputEnabled (xf86OutputPtr    output)
+{
+    /* Check to see if this output was disabled in the config file */
+    if (xf86ReturnOptValBool (output->options, OPTION_ENABLE, TRUE) == FALSE ||
+	xf86ReturnOptValBool (output->options, OPTION_DISABLE, FALSE) == TRUE)
+    {
+	return FALSE;
+    }
+    return TRUE;
 }
 
 xf86OutputPtr
@@ -167,6 +217,8 @@ xf86OutputCreate (ScrnInfoPtr		    scrn,
 #ifdef RANDR_12_INTERFACE
     output->randr_output = NULL;
 #endif
+    xf86OutputSetMonitor (output);
+    
     if (xf86_config->output)
 	outputs = xrealloc (xf86_config->output,
 			  (xf86_config->num_output + 1) * sizeof (xf86OutputPtr));
@@ -181,24 +233,24 @@ xf86OutputCreate (ScrnInfoPtr		    scrn,
     xf86_config->output = outputs;
     xf86_config->output[xf86_config->num_output++] = output;
     
-    xf86OutputSetMonitor (output);
     return output;
 }
 
-void
+Bool
 xf86OutputRename (xf86OutputPtr output, const char *name)
 {
     int	    len = strlen(name);
     char    *newname = xalloc (len + 1);
     
     if (!newname)
-	return;	/* so sorry... */
+	return FALSE;	/* so sorry... */
     
     strcpy (newname, name);
     if (output->name != (char *) (output + 1))
 	xfree (output->name);
     output->name = newname;
     xf86OutputSetMonitor (output);
+    return TRUE;
 }
 
 void
@@ -375,7 +427,9 @@ xf86PickCrtcs (ScrnInfoPtr	pScrn,
 	     * If the two outputs desire the same mode,
 	     * see if they can be cloned
 	     */
-	    if (xf86ModesEqual (modes[o], modes[n]))
+	    if (xf86ModesEqual (modes[o], modes[n]) &&
+		config->output[o]->initial_x == config->output[n]->initial_x &&
+		config->output[o]->initial_y == config->output[n]->initial_y)
 	    {
 		for (l = 0; l < config->num_output; l++)
 		    if (output->possible_clones & (1 << l))
@@ -403,7 +457,8 @@ xf86PickCrtcs (ScrnInfoPtr	pScrn,
 
 /*
  * Compute the virtual size necessary to place all of the available
- * crtcs in a panorama configuration
+ * crtcs in the specified configuration and also large enough to
+ * resize any crtc to the largest available mode
  */
 
 static void
@@ -418,7 +473,13 @@ xf86DefaultScreenLimits (ScrnInfoPtr pSc
     for (c = 0; c < config->num_crtc; c++)
     {
 	int	    crtc_width = 0, crtc_height = 0;
+	xf86CrtcPtr crtc = config->crtc[c];
 
+	if (crtc->enabled)
+	{
+	    crtc_width = crtc->x + crtc->desiredMode.HDisplay;
+	    crtc_height = crtc->y + crtc->desiredMode.VDisplay;
+	}
 	for (o = 0; o < config->num_output; o++) 
 	{
 	    xf86OutputPtr   output = config->output[o];
@@ -436,7 +497,8 @@ xf86DefaultScreenLimits (ScrnInfoPtr pSc
 		    }
 		}
 	}
-	width += crtc_width;
+	if (crtc_width > width)
+	    width = crtc_width;
 	if (crtc_height > height)
 	    height = crtc_height;
     }
@@ -448,6 +510,186 @@ xf86DefaultScreenLimits (ScrnInfoPtr pSc
     *heightp = height;
 }
 
+#define POSITION_UNSET	-100000
+
+static Bool
+xf86InitialOutputPositions (ScrnInfoPtr pScrn, DisplayModePtr *modes)
+{
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int			o;
+    int			min_x, min_y;
+    
+    for (o = 0; o < config->num_output; o++)
+    {
+	xf86OutputPtr	output = config->output[o];
+
+	output->initial_x = output->initial_y = POSITION_UNSET;
+    }
+    
+    /*
+     * Loop until all outputs are set
+     */
+    for (;;)
+    {
+	Bool	any_set = FALSE;
+	Bool	keep_going = FALSE;
+
+	for (o = 0; o < config->num_output; o++)	
+	{
+	    static const OutputOpts	relations[] = {
+		OPTION_BELOW, OPTION_RIGHT_OF, OPTION_ABOVE, OPTION_LEFT_OF
+	    };
+	    xf86OutputPtr   output = config->output[o];
+	    xf86OutputPtr   relative;
+	    char	    *relative_name;
+	    char	    *position;
+	    OutputOpts	    relation;
+	    int		    r;
+
+	    if (output->initial_x != POSITION_UNSET)
+		continue;
+	    position = xf86GetOptValString (output->options,
+					    OPTION_POSITION);
+	    /*
+	     * Absolute position wins
+	     */
+	    if (position)
+	    {
+		int		    x, y;
+		if (sscanf (position, "%d %d", &x, &y) == 2)
+		{
+		    output->initial_x = x;
+		    output->initial_y = y;
+		}
+		else
+		{
+		    xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
+				"Output %s position not of form \"x y\"\n",
+				output->name);
+		    output->initial_x = output->initial_y = 0;
+		}
+		any_set = TRUE;
+		continue;
+	    }
+	    /*
+	     * Next comes relative positions
+	     */
+	    relation = 0;
+	    relative_name = NULL;
+	    for (r = 0; r < 4; r++)
+	    {
+		relation = relations[r];
+		relative_name = xf86GetOptValString (output->options,
+						     relation);
+		if (relative_name)
+		    break;
+	    }
+	    if (relative_name)
+	    {
+		int or;
+		relative = NULL;
+		for (or = 0; or < config->num_output; or++)
+		{
+		    xf86OutputPtr	out_rel = config->output[or];
+		    XF86ConfMonitorPtr	rel_mon = out_rel->conf_monitor;
+		    char		*name;
+
+		    if (rel_mon)
+			name = rel_mon->mon_identifier;
+		    else
+			name = out_rel->name;
+		    if (!strcmp (relative_name, name))
+		    {
+			relative = config->output[or];
+			break;
+		    }
+		}
+		if (!relative)
+		{
+		    xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
+				"Cannot position output %s relative to unknown output %s\n",
+				output->name, relative_name);
+		    output->initial_x = 0;
+		    output->initial_y = 0;
+		    any_set = TRUE;
+		    continue;
+		}
+		if (relative->initial_x == POSITION_UNSET)
+		{
+		    keep_going = TRUE;
+		    continue;
+		}
+		output->initial_x = relative->initial_x;
+		output->initial_y = relative->initial_y;
+		switch (relation) {
+		case OPTION_BELOW:
+		    output->initial_y += modes[or]->VDisplay;
+		    break;
+		case OPTION_RIGHT_OF:
+		    output->initial_x += modes[or]->HDisplay;
+		    break;
+		case OPTION_ABOVE:
+		    output->initial_y -= modes[o]->VDisplay;
+		    break;
+		case OPTION_LEFT_OF:
+		    output->initial_x -= modes[o]->HDisplay;
+		    break;
+		default:
+		    break;
+		}
+		any_set = TRUE;
+		continue;
+	    }
+	    
+	    /* Nothing set, just stick them at 0,0 */
+	    output->initial_x = 0;
+	    output->initial_y = 0;
+	    any_set = TRUE;
+	}
+	if (!keep_going)
+	    break;
+	if (!any_set) 
+	{
+	    for (o = 0; o < config->num_output; o++)
+	    {
+		xf86OutputPtr   output = config->output[o];
+		if (output->initial_x == POSITION_UNSET)
+		{
+		    xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
+				"Output position loop. Moving %s to 0,0\n",
+				output->name);
+		    output->initial_x = output->initial_y = 0;
+		    break;
+		}
+	    }
+	}
+    }
+
+    /*
+     * normalize positions
+     */
+    min_x = 1000000;
+    min_y = 1000000;
+    for (o = 0; o < config->num_output; o++)
+    {
+	xf86OutputPtr	output = config->output[o];
+
+	if (output->initial_x < min_x)
+	    min_x = output->initial_x;
+	if (output->initial_y < min_y)
+	    min_y = output->initial_y;
+    }
+    
+    for (o = 0; o < config->num_output; o++)
+    {
+	xf86OutputPtr	output = config->output[o];
+
+	output->initial_x -= min_x;
+	output->initial_y -= min_y;
+    }
+    return TRUE;
+}
+
 /*
  * XXX walk the monitor mode list and prune out duplicates that
  * are inserted by xf86DDCMonitorSet. In an ideal world, that
@@ -536,13 +778,13 @@ i830xf86SortModes (DisplayModePtr input)
 #define DEBUG_REPROBE 1
 
 void
-xf86ProbeOutputModes (ScrnInfoPtr pScrn)
+xf86ProbeOutputModes (ScrnInfoPtr pScrn, int maxX, int maxY)
 {
     xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
     int			o;
-    int			virtualX, virtualY;
 
-    xf86RandR12GetOriginalVirtualSize (pScrn, &virtualX, &virtualY);
+    if (maxX == 0 || maxY == 0)
+	xf86RandR12GetOriginalVirtualSize (pScrn, &maxX, &maxY);
 
     /* Elide duplicate modes before defaulting code uses them */
     xf86PruneDuplicateMonitorModes (pScrn->monitor);
@@ -553,11 +795,13 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn)
 	xf86OutputPtr	    output = config->output[o];
 	DisplayModePtr	    mode;
 	DisplayModePtr	    config_modes = NULL, output_modes, default_modes;
-	XF86ConfMonitorPtr  conf_monitor;
+	char		    *preferred_mode;
 	xf86MonPtr	    edid_monitor;
+	XF86ConfMonitorPtr  conf_monitor;
 	MonRec		    mon_rec;
 	int		    min_clock = 0;
 	int		    max_clock = 0;
+	double		    clock;
 	enum { sync_config, sync_edid, sync_default } sync_source = sync_default;
 	
 	while (output->probed_modes != NULL)
@@ -632,6 +876,14 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn)
 		}
 	    }
 	}
+
+	if (xf86GetOptValFreq (output->options, OPTION_MIN_CLOCK,
+			       OPTUNITS_KHZ, &clock))
+	    min_clock = (int) clock;
+	if (xf86GetOptValFreq (output->options, OPTION_MAX_CLOCK,
+			       OPTUNITS_KHZ, &clock))
+	    max_clock = (int) clock;
+
 	/*
 	 * These limits will end up setting a 1024x768 at 60Hz mode by default,
 	 * which seems like a fairly good mode to use when nothing else is
@@ -677,9 +929,11 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn)
 	output->probed_modes = xf86ModesAdd (output->probed_modes, default_modes);
 	
 	/*
-	 * Check all modes against virtual size
+	 * Check all modes against max size
 	 */
-	i830xf86ValidateModesSize (pScrn, output->probed_modes, virtualX, virtualY, 0);
+	if (maxX && maxY)
+	    i830xf86ValidateModesSize (pScrn, output->probed_modes,
+				       maxX, maxY, 0);
 	 
 	/*
 	 * Check all modes against output
@@ -693,27 +947,28 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn)
 	output->probed_modes = i830xf86SortModes (output->probed_modes);
 	
 	/* Check for a configured preference for a particular mode */
-	if (conf_monitor)
-	{
-	    char  *preferred_mode = xf86findOptionValue (conf_monitor->mon_option_lst,
-							 "Preferred Mode");
+	preferred_mode = xf86GetOptValString (output->options,
+					      OPTION_PREFERRED_MODE);
 
-	    if (preferred_mode)
+	if (preferred_mode)
+	{
+	    for (mode = output->probed_modes; mode; mode = mode->next)
 	    {
-		for (mode = output->probed_modes; mode; mode = mode->next)
-		    if (!strcmp (preferred_mode, mode->name))
-			break;
-		if (mode && mode != output->probed_modes)
+		if (!strcmp (preferred_mode, mode->name))
 		{
-		    if (mode->prev)
-			mode->prev->next = mode->next;
-		    if (mode->next)
-			mode->next->prev = mode->prev;
-		    mode->next = output->probed_modes;
-		    output->probed_modes->prev = mode;
-		    mode->prev = NULL;
-		    output->probed_modes = mode;
+		    if (mode != output->probed_modes)
+		    {
+			if (mode->prev)
+			    mode->prev->next = mode->next;
+			if (mode->next)
+			    mode->next->prev = mode->prev;
+			mode->next = output->probed_modes;
+			output->probed_modes->prev = mode;
+			mode->prev = NULL;
+			output->probed_modes = mode;
+		    }
 		    mode->type |= M_T_PREFERRED;
+		    break;
 		}
 	    }
 	}
@@ -760,7 +1015,6 @@ xf86SetScrnInfoModes (ScrnInfoPtr pScrn)
     xf86OutputPtr	output;
     xf86CrtcPtr		crtc;
     DisplayModePtr	last, mode;
-    int			originalVirtualX, originalVirtualY;
 
     output = config->output[config->compat_output];
     if (!output->crtc)
@@ -788,18 +1042,6 @@ xf86SetScrnInfoModes (ScrnInfoPtr pScrn)
     /* Set pScrn->modes to the mode list for the 'compat' output */
     pScrn->modes = xf86DuplicateModes(pScrn, output->probed_modes);
 
-    xf86RandR12GetOriginalVirtualSize(pScrn, &originalVirtualX, &originalVirtualY);
-
-    /* Disable modes in the XFree86 DDX list that are larger than the current
-     * virtual size.
-     */
-    i830xf86ValidateModesSize(pScrn, pScrn->modes,
-			      originalVirtualX, originalVirtualY,
-			      pScrn->displayWidth);
-
-    /* Strip out anything that we threw out for virtualX/Y. */
-    i830xf86PruneInvalidModes(pScrn, &pScrn->modes, TRUE);
-
     for (mode = pScrn->modes; mode; mode = mode->next)
 	if (xf86ModesEqual (mode, &crtc->desiredMode))
 	    break;
@@ -835,35 +1077,33 @@ xf86InitialConfiguration (ScrnInfoPtr	  
     DisplayModePtr	target_mode = NULL;
     xf86CrtcPtr		*crtcs;
     DisplayModePtr	*modes;
-    int			width, height;
-
-    xf86ProbeOutputModes (pScrn);
+    Bool		*enabled;
+    int			width;
+    int			height;
 
-    if (pScrn->display->virtualX == 0)
-    {
-	/*
-	 * Expand virtual size to cover potential mode switches
-	 */
-	xf86DefaultScreenLimits (pScrn, &width, &height);
-    
-	pScrn->display->virtualX = width;
-	pScrn->display->virtualY = height;
-    }
-    else
-    {
+    if (pScrn->display->virtualX)
 	width = pScrn->display->virtualX;
+    else
+	width = config->maxWidth;
+    if (pScrn->display->virtualY)
 	height = pScrn->display->virtualY;
-    }
-    if (width > pScrn->virtualX)
-	pScrn->virtualX = width;
-    if (height > pScrn->virtualY)
-	pScrn->virtualY = height;
-    
+    else
+	height = config->maxHeight;
+
+    xf86ProbeOutputModes (pScrn, width, height);
+
     crtcs = xnfcalloc (config->num_output, sizeof (xf86CrtcPtr));
     modes = xnfcalloc (config->num_output, sizeof (DisplayModePtr));
+    enabled = xnfcalloc (config->num_output, sizeof (Bool));
     
     for (o = 0; o < config->num_output; o++)
+    {
+	xf86OutputPtr output = config->output[o];
+	
 	modes[o] = NULL;
+	enabled[o] = (xf86OutputEnabled (output) &&
+		      output->status != XF86OutputStatusDisconnected);
+    }
     
     /*
      * Let outputs with preferred modes drive screen size
@@ -872,7 +1112,7 @@ xf86InitialConfiguration (ScrnInfoPtr	  
     {
 	xf86OutputPtr output = config->output[o];
 
-	if (output->status != XF86OutputStatusDisconnected &&
+	if (enabled[o] &&
 	    xf86OutputHasPreferredMode (output, width, height))
 	{
 	    target_mode = xf86DefaultMode (output, width, height);
@@ -889,7 +1129,7 @@ xf86InitialConfiguration (ScrnInfoPtr	  
 	for (o = 0; o < config->num_output; o++)
 	{
 	    xf86OutputPtr output = config->output[o];
-	    if (output->status != XF86OutputStatusDisconnected)
+	    if (enabled[o])
 	    {
 		target_mode = xf86DefaultMode (output, width, height);
 		if (target_mode)
@@ -905,10 +1145,23 @@ xf86InitialConfiguration (ScrnInfoPtr	  
     {
 	xf86OutputPtr output = config->output[o];
 	
-	if (output->status != XF86OutputStatusDisconnected && !modes[o])
+	if (enabled[o] && !modes[o])
 	    modes[o] = xf86ClosestMode (output, target_mode, width, height);
     }
 
+    /*
+     * Set the position of each output
+     */
+    if (!xf86InitialOutputPositions (pScrn, modes))
+    {
+	xfree (crtcs);
+	xfree (modes);
+	return FALSE;
+    }
+	
+    /*
+     * Assign CRTCs to fit output configuration
+     */
     if (!xf86PickCrtcs (pScrn, crtcs, modes, 0, width, height))
     {
 	xfree (crtcs);
@@ -928,7 +1181,7 @@ xf86InitialConfiguration (ScrnInfoPtr	  
 	crtc->enabled = FALSE;
 	memset (&crtc->desiredMode, '\0', sizeof (crtc->desiredMode));
     }
-	
+    
     /*
      * Set initial configuration
      */
@@ -942,13 +1195,28 @@ xf86InitialConfiguration (ScrnInfoPtr	  
 	{
 	    crtc->desiredMode = *mode;
 	    crtc->enabled = TRUE;
-	    crtc->x = 0;
-	    crtc->y = 0;
+	    crtc->x = output->initial_x;
+	    crtc->y = output->initial_y;
 	    output->crtc = crtc;
-	    /* XXX set position; for now, we clone */
 	}
     }
     
+    if (pScrn->display->virtualX == 0)
+    {
+	/*
+	 * Expand virtual size to cover potential mode switches
+	 */
+	xf86DefaultScreenLimits (pScrn, &width, &height);
+    
+	pScrn->display->virtualX = width;
+	pScrn->display->virtualY = height;
+    }
+
+    if (width > pScrn->virtualX)
+	pScrn->virtualX = width;
+    if (height > pScrn->virtualY)
+	pScrn->virtualY = height;
+    
     /* Mirror output modes to pScrn mode list */
     xf86SetScrnInfoModes (pScrn);
     
diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h
index b30003e..2555c55 100644
--- a/src/i830_xf86Crtc.h
+++ b/src/i830_xf86Crtc.h
@@ -289,6 +289,16 @@ struct _xf86Output {
     DisplayModePtr	probed_modes;
 
     /**
+     * Options parsed from the related monitor section
+     */
+    OptionInfoPtr	options;
+    
+    /**
+     * Configured monitor section
+     */
+    XF86ConfMonitorPtr  conf_monitor;
+    
+    /**
      * Desired initial position
      */
     int			initial_x, initial_y;
@@ -313,12 +323,6 @@ struct _xf86Output {
     /** Output name */
     char		*name;
 
-    /** Configured monitor name */
-    char		*monitor_name;
-
-    /** Monitor information from config file */
-    XF86ConfMonitorPtr	conf_monitor;
-
     /** output-specific functions */
     const xf86OutputFuncsRec *funcs;
 
@@ -410,14 +414,14 @@ xf86OutputCreate (ScrnInfoPtr		scrn,
 		      const xf86OutputFuncsRec *funcs,
 		      const char	*name);
 
-void
+Bool
 xf86OutputRename (xf86OutputPtr output, const char *name);
 
 void
 xf86OutputDestroy (xf86OutputPtr	output);
 
 void
-xf86ProbeOutputModes (ScrnInfoPtr pScrn);
+xf86ProbeOutputModes (ScrnInfoPtr pScrn, int maxX, int maxY);
 
 void
 xf86SetScrnInfoModes (ScrnInfoPtr pScrn);
diff-tree 58e797b2caa6effa5455fc1f13dc4c58d0658744 (from 5057769d3a7c1b3a94f49bbff47b9697f368d975)
Author: Keith Packard <keithp at mandolin.keithp.com>
Date:   Wed Jan 3 00:04:58 2007 -0800

    Sync dspbase/dspsurf registers by re-reading them.
    
    This seems to eliminate base/surf value confusion during EnterVT.

diff --git a/src/i830_display.c b/src/i830_display.c
index 9ec46a4..d124ba0 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -351,9 +351,12 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x,
 
     if (IS_I965G(pI830)) {
         OUTREG(dspbase, ((y * pScrn->displayWidth + x) * pI830->cpp));
+	(void) INREG(dspbase);
         OUTREG(dspsurf, Start);
+	(void) INREG(dspsurf);
     } else {
 	OUTREG(dspbase, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
+	(void) INREG(dspbase);
     }
 
     crtc->x = x;
diff-tree d960deab39eef91fb82b9f23118323aeb4c9c63e (from 5057769d3a7c1b3a94f49bbff47b9697f368d975)
Author: Jesse Barnes <jbarnes at nietzche.virtuousgeek.org>
Date:   Tue Jan 2 20:23:37 2007 -0800

      Various sparse cleanups:
        NULL vs. 0
        remove redundant pScrn in I830DRISwapContext
        make I830DRISwapContext static

diff --git a/src/i830_dri.c b/src/i830_dri.c
index 5fdacc7..eeef289 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -216,9 +216,9 @@ I830InitVisualConfigs(ScreenPtr pScreen)
    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
    I830Ptr pI830 = I830PTR(pScrn);
    int numConfigs = 0;
-   __GLXvisualConfig *pConfigs = 0;
-   I830ConfigPrivPtr pI830Configs = 0;
-   I830ConfigPrivPtr *pI830ConfigPtrs = 0;
+   __GLXvisualConfig *pConfigs = NULL;
+   I830ConfigPrivPtr pI830Configs = NULL;
+   I830ConfigPrivPtr *pI830ConfigPtrs = NULL;
    int accum, stencil, db, depth;
    int i;
 
@@ -538,7 +538,7 @@ I830DRIScreenInit(ScreenPtr pScreen)
 
    if (!(pI830DRI = (I830DRIPtr) xcalloc(sizeof(I830DRIRec), 1))) {
       DRIDestroyInfoRec(pI830->pDRIInfo);
-      pI830->pDRIInfo = 0;
+      pI830->pDRIInfo = NULL;
       return FALSE;
    }
    pDRIInfo->devPrivate = pI830DRI;
@@ -561,9 +561,9 @@ I830DRIScreenInit(ScreenPtr pScreen)
       xf86DrvMsg(pScreen->myNum, X_ERROR,
 		 "[dri] DRIScreenInit failed. Disabling DRI.\n");
       xfree(pDRIInfo->devPrivate);
-      pDRIInfo->devPrivate = 0;
+      pDRIInfo->devPrivate = NULL;
       DRIDestroyInfoRec(pI830->pDRIInfo);
-      pI830->pDRIInfo = 0;
+      pI830->pDRIInfo = NULL;
       return FALSE;
    }
 
@@ -951,10 +951,10 @@ I830DRICloseScreen(ScreenPtr pScreen)
    if (pI830->pDRIInfo) {
       if (pI830->pDRIInfo->devPrivate) {
 	 xfree(pI830->pDRIInfo->devPrivate);
-	 pI830->pDRIInfo->devPrivate = 0;
+	 pI830->pDRIInfo->devPrivate = NULL;
       }
       DRIDestroyInfoRec(pI830->pDRIInfo);
-      pI830->pDRIInfo = 0;
+      pI830->pDRIInfo = NULL;
    }
    if (pI830->pVisualConfigs)
       xfree(pI830->pVisualConfigs);
@@ -1025,7 +1025,7 @@ I830DRIFinishScreenInit(ScreenPtr pScree
    }
 }
 
-void
+static void
 I830DRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
 		   DRIContextType oldContextType, void *oldContext,
 		   DRIContextType newContextType, void *newContext)
@@ -1035,7 +1035,6 @@ I830DRISwapContext(ScreenPtr pScreen, DR
 
    if (syncType == DRI_3D_SYNC &&
        oldContextType == DRI_2D_CONTEXT && newContextType == DRI_2D_CONTEXT) {
-      ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
 
       if (I810_DEBUG & DEBUG_VERBOSE_DRI)
 	 ErrorF("i830DRISwapContext (in)\n");
@@ -1128,9 +1127,9 @@ I830DRIMoveBuffers(WindowPtr pParent, DD
    BoxPtr pbox = REGION_RECTS(prgnSrc);
    int nbox = REGION_NUM_RECTS(prgnSrc);
 
-   BoxPtr pboxNew1 = 0;
-   BoxPtr pboxNew2 = 0;
-   DDXPointPtr pptNew1 = 0;
+   BoxPtr pboxNew1 = NULL;
+   BoxPtr pboxNew2 = NULL;
+   DDXPointPtr pptNew1 = NULL;
    DDXPointPtr pptSrc = &ptOldOrg;
 
    int dx = pParent->drawable.x - ptOldOrg.x;
diff-tree 5057769d3a7c1b3a94f49bbff47b9697f368d975 (from 2bb9bb951e664d704bdf7a808edbe8b2f50c4366)
Author: Dave Airlie <airlied at linux.ie>
Date:   Tue Jan 2 19:25:08 2007 -0800

    Use correct variable to initialize DVO I2C bus.
    
    intel_output->pI2CBus isn't initialized until the output is all happy and
    running, so using it before that is rather unlikely to do much good.

diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index 37caf00..d938f46 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -294,7 +294,7 @@ i830_dvo_init(ScrnInfoPtr pScrn)
 	if (gpio_inited != gpio) {
 	    if (pI2CBus != NULL)
 		xf86DestroyI2CBusRec(pI2CBus, TRUE, TRUE);
-	    if (!I830I2CInit(pScrn, &intel_output->pI2CBus, gpio,
+	    if (!I830I2CInit(pScrn, &pI2CBus, gpio,
 			     gpio == GPIOB ? "DVOI2C_B" : "DVOI2C_E")) {
 		continue;
 	    }
diff-tree 2bb9bb951e664d704bdf7a808edbe8b2f50c4366 (from 5080307230d534b84090bfefc13ac437d53f915d)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Tue Jan 2 14:04:10 2007 -0800

    Typo disabled new DRI MM on all chips.
    
    Detection for new DRI MM wasn't converted to #define correctly because of a
    typo.

diff --git a/configure.ac b/configure.ac
index b295c5a..70ae807 100644
--- a/configure.ac
+++ b/configure.ac
@@ -124,7 +124,7 @@ if test "$DRI" = yes; then
         AC_DEFINE(XF86DRI,1,[Enable DRI driver support])
         AC_DEFINE(XF86DRI_DEVEL,1,[Enable developmental DRI driver support])
 	PKG_CHECK_MODULES(DRI_MM, [libdrm >= 2.2],[DRI_MM=yes], [DRI_MM=no])
-	if test "x$DRM_MM" = xyes; then
+	if test "x$DRI_MM" = xyes; then
 		AC_DEFINE(XF86DRI_MM,1,[Extended DRI memory management])
 	fi
 fi
diff-tree 5080307230d534b84090bfefc13ac437d53f915d (from 237847007afb5a429a50b6aa0b1acc239326571b)
Author: Keith Packard <keithp at mandolin.keithp.com>
Date:   Tue Jan 2 00:16:41 2007 -0800

    Fix driver to build on RandR 1.2 systems again.
    
    Changes to move initial config code to RandR 1.1/1.2 common path broke
    code required only for RandR 1.2.

diff --git a/src/i830_randr.c b/src/i830_randr.c
index 55ff31e..d5ccce3 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -864,7 +864,11 @@ xf86RandR12CreateObjects12 (ScreenPtr pS
 static Bool
 xf86RandR12CreateScreenResources12 (ScreenPtr pScreen)
 {
-    
+    int			c;
+    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
+    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
+
     for (c = 0; c < config->num_crtc; c++)
 	xf86RandR12CrtcNotify (config->crtc[c]->randr_crtc);
     
diff-tree 237847007afb5a429a50b6aa0b1acc239326571b (from 25d5a892319b02dc6eb81390dea29cd88a1e7da4)
Author: Keith Packard <keithp at mandolin.keithp.com>
Date:   Tue Jan 2 00:09:35 2007 -0800

    Make driver build and run on Xorg 7.1. Delay DSP*BASE setting until last.
    
    Autodetect libdrm version, disable new memory manager on older libraries.
    Move new M_T_ defines from i830.h to i830_xf86Crtc.h. Add many system
    headers to define functions. Use i830PipeSetBase at end of mode setting
    code to set DSP*BASE and flush changes. Don't duplicate PipeSetBase call
    from screen init function. Make initial RandR configuration code usable on
    older versions of extension so the server doesn't start in a panning mode.
    Use xfree instead of free in i830_tv.c.

diff --git a/configure.ac b/configure.ac
index be80a87..b295c5a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -120,9 +120,13 @@ fi
 
 AM_CONDITIONAL(DRI, test x$DRI = xyes)
 if test "$DRI" = yes; then
-        PKG_CHECK_MODULES(DRI, [libdrm >= 2.2 xf86driproto])
+        PKG_CHECK_MODULES(DRI, [libdrm xf86driproto])
         AC_DEFINE(XF86DRI,1,[Enable DRI driver support])
         AC_DEFINE(XF86DRI_DEVEL,1,[Enable developmental DRI driver support])
+	PKG_CHECK_MODULES(DRI_MM, [libdrm >= 2.2],[DRI_MM=yes], [DRI_MM=no])
+	if test "x$DRM_MM" = xyes; then
+		AC_DEFINE(XF86DRI_MM,1,[Extended DRI memory management])
+	fi
 fi
 
 AM_CONDITIONAL(VIDEO_DEBUG, test x$VIDEO_DEBUG = xyes)
diff --git a/src/i830.h b/src/i830.h
index 06f6838..c2670cd 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -628,14 +628,6 @@ void i830_tv_init(ScrnInfoPtr pScrn);
 #define _845_DRAM_RW_CONTROL 0x90
 #define DRAM_WRITE    0x33330000
 
-/* Compat definitions for older X Servers. */
-#ifndef M_T_PREFERRED
-#define M_T_PREFERRED	0x08
-#endif
-#ifndef M_T_DRIVER
-#define M_T_DRIVER	0x40
-#endif
-
 /* 
  * Xserver MM compatibility. Remove code guarded by this when the
  * XServer contains the libdrm mm code
diff --git a/src/i830_debug.c b/src/i830_debug.c
index 25245fb..897ab92 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -32,6 +32,7 @@
 #include "xf86.h"
 #include "i830.h"
 #include "i830_debug.h"
+#include <strings.h>
 
 #define DEBUGSTRING(func) static char *func(I830Ptr pI830, int reg, CARD32 val)
 
diff --git a/src/i830_display.c b/src/i830_display.c
index c5880d6..9ec46a4 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -350,8 +350,8 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x,
     }
 
     if (IS_I965G(pI830)) {
-	OUTREG(dspbase, ((y * pScrn->displayWidth + x) * pI830->cpp));
-	OUTREG(dspsurf, Start);
+        OUTREG(dspbase, ((y * pScrn->displayWidth + x) * pI830->cpp));
+        OUTREG(dspsurf, Start);
     } else {
 	OUTREG(dspbase, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
     }
@@ -603,7 +603,6 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
     int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
     int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD;
     int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
-    int dspbase_reg = (pipe == 0) ? DSPABASE : DSPBBASE;
     int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
     int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
     int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
@@ -828,13 +827,12 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
     OUTREG(dspsize_reg, ((mode->VDisplay - 1) << 16) | (mode->HDisplay - 1));
     OUTREG(dsppos_reg, 0);
     OUTREG(pipesrc_reg, ((mode->HDisplay - 1) << 16) | (mode->VDisplay - 1));
-    i830PipeSetBase(crtc, crtc->x, crtc->y);
     OUTREG(pipeconf_reg, pipeconf);
     i830WaitForVblank(pScrn);
     
     OUTREG(dspcntr_reg, dspcntr);
     /* Flush the plane changes */
-    OUTREG(dspbase_reg, INREG(dspbase_reg));
+    i830PipeSetBase(crtc, crtc->x, crtc->y);
     
     i830WaitForVblank(pScrn);
 }
diff --git a/src/i830_dri.c b/src/i830_dri.c
index c5d7a94..5fdacc7 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -655,11 +655,14 @@ I830DRIScreenInit(ScreenPtr pScreen)
 	 }
 	 pI830->drmMinor = version->version_minor;
 	 if (!(pI830->mmModeFlags & I830_KERNEL_TEX)) {
+#ifdef XF86DRI_MM	    
 	    if ((version->version_major > 1) ||
 		((version->version_minor >= 7) && 
 		 (version->version_major == 1))) {
 	       pI830->mmModeFlags |= I830_KERNEL_MM;
-	    } else {
+	    } else 
+#endif
+	    {
 	       pI830->mmModeFlags |= I830_KERNEL_TEX;
 	    }		
 	 } else {
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 7f535ac..5264767 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2469,11 +2469,7 @@ IntelEmitInvarientState(ScrnInfoPtr pScr
    }
 }
 
-#ifdef XF86DRI
-#ifndef DRM_BO_MEM_TT
-#error "Wrong drm.h file included. You need to compile and install a recent libdrm."
-#endif
-
+#ifdef XF86DRI_MM
 #ifndef XSERVER_LIBDRM_MM
 
 static int
@@ -2548,7 +2544,7 @@ static int I830DrmMMUnlock(int fd, unsig
 }
 
 #endif
-#endif
+#endif /* XF86DRI_MM */
 
 static Bool
 I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
@@ -3001,7 +2997,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
          break;
    }
 
-#ifdef XF86DRI
+#ifdef XF86DRI_MM
    if (pI830->directRenderingEnabled && (pI830->mmModeFlags & I830_KERNEL_MM)) {
       unsigned long aperEnd = ROUND_DOWN_TO(pI830->FbMapSize, GTT_PAGE_SIZE) 
 	 / GTT_PAGE_SIZE;
@@ -3040,7 +3036,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 	 }
       }
    }
-#endif
+#endif /* XF86DRI_MM */
 
    return TRUE;
 }
@@ -3101,6 +3097,7 @@ I830LeaveVT(int scrnIndex, int flags)
 #ifdef XF86DRI
    if (pI830->directRenderingOpen) {
       DRILock(screenInfo.screens[pScrn->scrnIndex], 0);
+#ifdef XF86DRI_MM
       if (pI830->mmModeFlags & I830_KERNEL_MM) {
 #ifndef XSERVER_LIBDRM_MM
 	 I830DrmMMLock(pI830->drmSubFD, DRM_BO_MEM_TT);
@@ -3108,6 +3105,7 @@ I830LeaveVT(int scrnIndex, int flags)
 	 drmMMLock(pI830->drmSubFD, DRM_BO_MEM_TT);
 #endif
       }
+#endif /* XF86DRI_MM */
       I830DRISetVBlankInterrupt (pScrn, FALSE);
       
       drmCtlUninstHandler(pI830->drmSubFD);
@@ -3185,8 +3183,6 @@ I830EnterVT(int scrnIndex, int flags)
       
       if (!i830PipeSetMode (crtc, &crtc->desiredMode, TRUE))
 	 return FALSE;
-      
-      i830PipeSetBase(crtc, crtc->x, crtc->y);
    }
 
    i830DumpRegs (pScrn);
@@ -3221,6 +3217,7 @@ I830EnterVT(int scrnIndex, int flags)
 	 for(i = 0; i < I830_NR_TEX_REGIONS+1 ; i++)
 	    sarea->texList[i].age = sarea->texAge;
 
+#ifdef XF86DRI_MM
 	 if (pI830->mmModeFlags & I830_KERNEL_MM) {
 #ifndef XSERVER_LIBDRM_MM
 	    I830DrmMMUnlock(pI830->drmSubFD, DRM_BO_MEM_TT);
@@ -3228,6 +3225,7 @@ I830EnterVT(int scrnIndex, int flags)
 	    drmMMUnlock(pI830->drmSubFD, DRM_BO_MEM_TT);
 #endif
 	 }
+#endif /* XF86DRI_MM */
 
 	 DPRINTF(PFX, "calling dri unlock\n");
 	 DRIUnlock(screenInfo.screens[pScrn->scrnIndex]);
@@ -3371,6 +3369,7 @@ I830CloseScreen(int scrnIndex, ScreenPtr
    pI830->closing = TRUE;
 #ifdef XF86DRI
    if (pI830->directRenderingOpen) {
+#ifdef XF86DRI_MM
       if (pI830->mmModeFlags & I830_KERNEL_MM) {
 #ifndef XSERVER_LIBDRM_MM
 	 I830DrmMMTakedown(pI830->drmSubFD, DRM_BO_MEM_TT);
@@ -3378,6 +3377,7 @@ I830CloseScreen(int scrnIndex, ScreenPtr
 	 drmMMTakedown(pI830->drmSubFD, DRM_BO_MEM_TT);	 
 #endif
       }
+#endif /* XF86DRI_MM */
       pI830->directRenderingOpen = FALSE;
       I830DRICloseScreen(pScreen);
    }
diff --git a/src/i830_edid_modes.c b/src/i830_edid_modes.c
index c121610..31ce100 100644
--- a/src/i830_edid_modes.c
+++ b/src/i830_edid_modes.c
@@ -37,6 +37,8 @@
 #include "xf86DDC.h"
 #include "i830.h"
 #include "i830_display.h"
+#include <string.h>
+#include <math.h>
 
 #if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0)
 
diff --git a/src/i830_exa.c b/src/i830_exa.c
index 7de5617..9356c79 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -36,6 +36,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "i830.h"
 #include "i810_reg.h"
 #include "i830_reg.h"
+#include <string.h>
 
 #ifdef I830DEBUG
 #define DEBUG_I830FALLBACK 1
diff --git a/src/i830_randr.c b/src/i830_randr.c
index aa50254..55ff31e 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -325,6 +325,44 @@ xf86RandR12SetConfig (ScreenPtr		pScreen
     return TRUE;
 }
 
+static Bool
+xf86RandR12ScreenSetSize (ScreenPtr	pScreen,
+			CARD16		width,
+			CARD16		height,
+			CARD32		mmWidth,
+			CARD32		mmHeight)
+{
+    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
+    ScrnInfoPtr		pScrn = XF86SCRNINFO(pScreen);
+    WindowPtr		pRoot = WindowTable[pScreen->myNum];
+    Bool 		ret = TRUE;
+
+    if (randrp->virtualX == -1 || randrp->virtualY == -1)
+    {
+	randrp->virtualX = pScrn->virtualX;
+	randrp->virtualY = pScrn->virtualY;
+    }
+    if (pRoot)
+	(*pScrn->EnableDisableFBAccess) (pScreen->myNum, FALSE);
+    pScrn->virtualX = width;
+    pScrn->virtualY = height;
+
+    pScreen->width = pScrn->virtualX;
+    pScreen->height = pScrn->virtualY;
+    pScreen->mmWidth = mmWidth;
+    pScreen->mmHeight = mmHeight;
+
+    xf86SetViewport (pScreen, pScreen->width-1, pScreen->height-1);
+    xf86SetViewport (pScreen, 0, 0);
+    if (pRoot)
+	(*pScrn->EnableDisableFBAccess) (pScreen->myNum, TRUE);
+#if RANDR_12_INTERFACE
+    if (WindowTable[pScreen->myNum])
+	RRScreenSizeNotify (pScreen);
+#endif
+    return ret;
+}
+
 Rotation
 xf86RandR12GetRotation(ScreenPtr pScreen)
 {
@@ -336,38 +374,68 @@ xf86RandR12GetRotation(ScreenPtr pScreen
 Bool
 xf86RandR12CreateScreenResources (ScreenPtr pScreen)
 {
-#if 0
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
-    I830Ptr		pI830 = I830PTR(pScrn);
-#endif
+    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
+    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
+    int			c;
+    int			width, height;
+    int			mmWidth, mmHeight;
 #ifdef PANORAMIX
     /* XXX disable RandR when using Xinerama */
     if (!noPanoramiXExtension)
 	return TRUE;
 #endif
+
+    /*
+     * Compute size of screen
+     */
+    width = 0; height = 0;
+    for (c = 0; c < config->num_crtc; c++)
+    {
+	xf86CrtcPtr crtc = config->crtc[c];
+	int	    crtc_width = crtc->x + crtc->curMode.HDisplay;
+	int	    crtc_height = crtc->y + crtc->curMode.VDisplay;
+	
+	if (crtc->enabled && crtc_width > width)
+	    width = crtc_width;
+	if (crtc->enabled && crtc_height > height)
+	    height = crtc_height;
+    }
+    
+    if (width && height)
+    {
+	/*
+	 * Compute physical size of screen
+	 */
+	if (monitorResolution) 
+	{
+	    mmWidth = width * 25.4 / monitorResolution;
+	    mmHeight = height * 25.4 / monitorResolution;
+	}
+	else
+	{
+	    mmWidth = pScreen->mmWidth;
+	    mmHeight = pScreen->mmHeight;
+	}
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		   "Setting screen physical size to %d x %d\n",
+		   mmWidth, mmHeight);
+	xf86RandR12ScreenSetSize (pScreen,
+				  width,
+				  height,
+				  mmWidth,
+				  mmHeight);
+    }
+
+    if (randrp->virtualX == -1 || randrp->virtualY == -1)
+    {
+	randrp->virtualX = pScrn->virtualX;
+	randrp->virtualY = pScrn->virtualY;
+    }
 #if RANDR_12_INTERFACE
     if (xf86RandR12CreateScreenResources12 (pScreen))
 	return TRUE;
 #endif
-#if 0
-    /* XXX deal with initial rotation */
-    if (pI830->rotation != RR_Rotate_0) {
-	RRScreenSize p;
-	Rotation requestedRotation = pI830->rotation;
-
-	pI830->rotation = RR_Rotate_0;
-
-	/* Just setup enough for an initial rotate */
-	p.width = pScreen->width;
-	p.height = pScreen->height;
-	p.mmWidth = pScreen->mmWidth;
-	p.mmHeight = pScreen->mmHeight;
-
-	pI830->starting = TRUE; /* abuse this for dual head & rotation */
-	xf86RandR12SetConfig (pScreen, requestedRotation, 0, &p);
-	pI830->starting = FALSE;
-    }
-#endif
     return TRUE;
 }
 
@@ -450,42 +518,6 @@ xf86RandR12GetOriginalVirtualSize(ScrnIn
 
 #if RANDR_12_INTERFACE
 static Bool
-xf86RandR12ScreenSetSize (ScreenPtr	pScreen,
-			CARD16		width,
-			CARD16		height,
-			CARD32		mmWidth,
-			CARD32		mmHeight)
-{
-    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
-    ScrnInfoPtr		pScrn = XF86SCRNINFO(pScreen);
-    WindowPtr		pRoot = WindowTable[pScreen->myNum];
-    Bool 		ret = TRUE;
-
-    if (randrp->virtualX == -1 || randrp->virtualY == -1)
-    {
-	randrp->virtualX = pScrn->virtualX;
-	randrp->virtualY = pScrn->virtualY;
-    }
-    if (pRoot)
-	(*pScrn->EnableDisableFBAccess) (pScreen->myNum, FALSE);
-    pScrn->virtualX = width;
-    pScrn->virtualY = height;
-
-    pScreen->width = pScrn->virtualX;
-    pScreen->height = pScrn->virtualY;
-    pScreen->mmWidth = mmWidth;
-    pScreen->mmHeight = mmHeight;
-
-    xf86SetViewport (pScreen, pScreen->width, pScreen->height);
-    xf86SetViewport (pScreen, 0, 0);
-    if (pRoot)
-	(*pScrn->EnableDisableFBAccess) (pScreen->myNum, TRUE);
-    if (WindowTable[pScreen->myNum])
-	RRScreenSizeNotify (pScreen);
-    return ret;
-}
-
-static Bool
 xf86RandR12CrtcNotify (RRCrtcPtr	randr_crtc)
 {
     ScreenPtr		pScreen = randr_crtc->pScreen;
@@ -832,62 +864,10 @@ xf86RandR12CreateObjects12 (ScreenPtr pS
 static Bool
 xf86RandR12CreateScreenResources12 (ScreenPtr pScreen)
 {
-    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
-    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
-    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
-    int			c;
-    int			width, height;
-    int			mmWidth, mmHeight;
-
-    /*
-     * Compute size of screen
-     */
-    width = 0; height = 0;
-    for (c = 0; c < config->num_crtc; c++)
-    {
-	xf86CrtcPtr crtc = config->crtc[c];
-	int	    crtc_width = crtc->x + crtc->curMode.HDisplay;
-	int	    crtc_height = crtc->y + crtc->curMode.VDisplay;
-	
-	if (crtc->enabled && crtc_width > width)
-	    width = crtc_width;
-	if (crtc->enabled && crtc_height > height)
-	    height = crtc_height;
-    }
     
-    if (width && height)
-    {
-	/*
-	 * Compute physical size of screen
-	 */
-	if (monitorResolution) 
-	{
-	    mmWidth = width * 25.4 / monitorResolution;
-	    mmHeight = height * 25.4 / monitorResolution;
-	}
-	else
-	{
-	    mmWidth = pScreen->mmWidth;
-	    mmHeight = pScreen->mmHeight;
-	}
-	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		   "Setting screen physical size to %d x %d\n",
-		   mmWidth, mmHeight);
-	xf86RandR12ScreenSetSize (pScreen,
-				  width,
-				  height,
-				  mmWidth,
-				  mmHeight);
-    }
-
     for (c = 0; c < config->num_crtc; c++)
 	xf86RandR12CrtcNotify (config->crtc[c]->randr_crtc);
     
-    if (randrp->virtualX == -1 || randrp->virtualY == -1)
-    {
-	randrp->virtualX = pScrn->virtualX;
-	randrp->virtualY = pScrn->virtualY;
-    }
     
     RRScreenSetSizeRange (pScreen, 320, 240,
 			  randrp->virtualX, randrp->virtualY);
diff --git a/src/i830_tv.c b/src/i830_tv.c
index f17a353..5cf36a5 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -36,6 +36,7 @@
 #include "xf86.h"
 #include "i830.h"
 #include "i830_display.h"
+#include <string.h>
 
 enum tv_type {
     TV_TYPE_NONE,
diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index 33f96ab..a0f44df 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -143,7 +143,7 @@ xf86OutputSetMonitor (xf86OutputPtr outp
 	monitor = output->name;
     else
 	xf86MarkOptionUsedByName (output->scrn->options, option_name);
-    free (option_name);
+    xfree (option_name);
     output->conf_monitor = xf86findMonitor (monitor, xf86configptr->conf_monitor_lst);
 }
 
@@ -1026,7 +1026,10 @@ i830_xf86OutputSetEDID (xf86OutputPtr ou
 {
     ScrnInfoPtr		pScrn = output->scrn;
     xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
-    int			i, size;
+    int			i;
+#ifdef RANDR_12_INTERFACE
+    int			size;
+#endif
     
     if (output->MonInfo != NULL)
 	xfree(output->MonInfo);
diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h
index 3e70563..b30003e 100644
--- a/src/i830_xf86Crtc.h
+++ b/src/i830_xf86Crtc.h
@@ -27,6 +27,14 @@
 #include "i830_xf86Modes.h"
 #include "xf86Parser.h"
 
+/* Compat definitions for older X Servers. */
+#ifndef M_T_PREFERRED
+#define M_T_PREFERRED	0x08
+#endif
+#ifndef M_T_DRIVER
+#define M_T_DRIVER	0x40
+#endif
+
 typedef struct _xf86Crtc xf86CrtcRec, *xf86CrtcPtr;
 typedef struct _xf86Output xf86OutputRec, *xf86OutputPtr;
 
diff --git a/src/i830_xf86cvt.c b/src/i830_xf86cvt.c
index dba57c8..1a2b786 100644
--- a/src/i830_xf86cvt.c
+++ b/src/i830_xf86cvt.c
@@ -39,6 +39,7 @@
 
 #include "i830.h"
 #include "i830_display.h"
+#include <string.h>
 
 #if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0)
 /*
diff --git a/src/i965_video.c b/src/i965_video.c
index 0d1bec6..9e96527 100644
--- a/src/i965_video.c
+++ b/src/i965_video.c
@@ -39,6 +39,7 @@
 #include "i830_video.h"
 #include "brw_defines.h"
 #include "brw_structs.h"
+#include <string.h>
 
 /* Make assert() work. */
 #undef NDEBUG
diff-tree 25d5a892319b02dc6eb81390dea29cd88a1e7da4 (from feeefc92e450e9de58da51147325300ffabd2059)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Sun Dec 31 15:39:20 2006 -0800

    Elide identical modes from reported list.
    
    Where two modes would produce precisely the same crtc settings and have the
    same name, remove the latter mode from the mode list.

diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index 3a68985..33f96ab 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -499,8 +499,9 @@ i830xf86ModeCompare (DisplayModePtr a, D
 static DisplayModePtr
 i830xf86SortModes (DisplayModePtr input)
 {
-    DisplayModePtr  output = NULL, i, o, *op, prev;
+    DisplayModePtr  output = NULL, i, o, n, *op, prev;
 
+    /* sort by preferred status and pixel area */
     while (input)
     {
 	i = input;
@@ -511,6 +512,17 @@ i830xf86SortModes (DisplayModePtr input)
 	i->next = *op;
 	*op = i;
     }
+    /* prune identical modes */
+    for (o = output; o && (n = o->next); o = n)
+    {
+	if (!strcmp (o->name, n->name) && xf86ModesEqual (o, n))
+	{
+	    o->next = n->next;
+	    xfree (n->name);
+	    xfree (n);
+	    n = o;
+	}
+    }
     /* hook up backward links */
     prev = NULL;
     for (o = output; o; o = o->next)
diff-tree feeefc92e450e9de58da51147325300ffabd2059 (from 5e456251f0d6c8bef3241267f6c1b3bca4670c0d)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Sun Dec 31 14:22:53 2006 -0800

    Replace author-specific license with generic license.
    
    This file retained the old MIT license with the embedded author name.
    Replace that with the version that uses generic 'copyright holders' instead.

diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index 91f6071..3a68985 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -1,25 +1,23 @@
 /*
- * $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.
+ * 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.
  *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * THE COPYRIGHT HOLDERS DISCLAIM 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
+ * 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.
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
  */
 
 #ifdef HAVE_CONFIG_H
diff-tree 5e456251f0d6c8bef3241267f6c1b3bca4670c0d (from 2330b341c925e60bc2c991b4ca8450badbc459a4)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Sun Dec 31 14:21:12 2006 -0800

    Replace author-specific license with generic license.
    
    This file retained the old MIT license with the embedded author name.
    Replace that with the version that uses generic 'copyright holders' instead.

diff --git a/src/i830_randr.c b/src/i830_randr.c
index 64d7d1f..aa50254 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -6,21 +6,21 @@
  *
  * 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.
+ * 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.
  *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * THE COPYRIGHT HOLDERS DISCLAIM 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
+ * 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.
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
  */
 
 #ifdef HAVE_CONFIG_H
diff-tree 2330b341c925e60bc2c991b4ca8450badbc459a4 (from c70e7bc701cba3092acfdd66ed4d63487ac8ff9f)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Sat Dec 30 22:47:58 2006 -0800

    Prune default modes to EDID clock limit.
    
    Pick out the EDID max clock value and use that to elide default modes which
    are too fast.

diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index 6e9e52a..91f6071 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -546,6 +546,8 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn)
 	XF86ConfMonitorPtr  conf_monitor;
 	xf86MonPtr	    edid_monitor;
 	MonRec		    mon_rec;
+	int		    min_clock = 0;
+	int		    max_clock = 0;
 	enum { sync_config, sync_edid, sync_default } sync_source = sync_default;
 	
 	while (output->probed_modes != NULL)
@@ -615,6 +617,8 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn)
 			if (sync_source == sync_default)
 			    sync_source = sync_edid;
 		    }
+		    if (ranges->max_clock > max_clock)
+			max_clock = ranges->max_clock;
 		}
 	    }
 	}
@@ -650,6 +654,12 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn)
 	 * Check default modes against sync range
 	 */
         i830xf86ValidateModesSync (pScrn, default_modes, &mon_rec);
+	/*
+	 * Check default modes against monitor max clock
+	 */
+	if (max_clock)
+	    i830xf86ValidateModesClocks(pScrn, default_modes,
+					&min_clock, &max_clock, 1);
 	
 	output->probed_modes = NULL;
 	output->probed_modes = xf86ModesAdd (output->probed_modes, config_modes);
diff-tree c70e7bc701cba3092acfdd66ed4d63487ac8ff9f (from parents)
Merge: 8b6c456e16c81f719bb68178e3e4d26f4108a9c2 4ed79a2ba6250354ffc24fa1f7a21ca914ad157e
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Sat Dec 30 21:58:36 2006 -0800

    Merge branch 'modesetting-origin' into modesetting

diff-tree 8b6c456e16c81f719bb68178e3e4d26f4108a9c2 (from b8692e646227e56c9ae4f72b9aaa75457b4c0f5f)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Sat Dec 30 21:57:42 2006 -0800

    Detect in ProbeModes. Let get_modes set edid. Prune interlace/dblscan.
    
    Move output connection status detection from RandR code up to ProbeModes so
    it is done before mode sets are built. Otherwise, the mode building code
    will elide all modes the first time through as it ignores outputs that are
    disconnected.
    
    Most get_modes functions fetch EDID data; make sure that any
    EDID changes are used in the ProbeModes filtering of default modes.
    Otherwise, stale EDID data will be used.
    
    Allow outputs to advertise support for interlaced and double scan modes;
    prune such modes from the default mode list when outputs do not support them.

diff --git a/src/i830_crt.c b/src/i830_crt.c
index 85c25de..4e9e370 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -365,6 +365,8 @@ i830_crt_init(ScrnInfoPtr pScrn)
     i830_output->type = I830_OUTPUT_ANALOG;
     
     output->driver_private = i830_output;
+    output->interlaceAllowed = FALSE;
+    output->doubleScanAllowed = FALSE;
 
     /* Set up the DDC bus. */
     I830I2CInit(pScrn, &i830_output->pDDCBus, GPIOA, "CRTDDC_A");
diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index d101054..37caf00 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -257,6 +257,8 @@ i830_dvo_init(ScrnInfoPtr pScrn)
     intel_output->type = I830_OUTPUT_DVO;
     output->driver_private = intel_output;
     output->subpixel_order = SubPixelHorizontalRGB;
+    output->interlaceAllowed = FALSE;
+    output->doubleScanAllowed = FALSE;
     
     /* Set up the DDC bus */
     ret = I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOD, "DVODDC_D");
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index fe96413..18ac76b 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -361,6 +361,8 @@ i830_lvds_init(ScrnInfoPtr pScrn)
     intel_output->type = I830_OUTPUT_LVDS;
     output->driver_private = intel_output;
     output->subpixel_order = SubPixelHorizontalRGB;
+    output->interlaceAllowed = FALSE;
+    output->doubleScanAllowed = FALSE;
 
     /* Set up the LVDS DDC channel.  Most panels won't support it, but it can
      * be useful if available.
diff --git a/src/i830_randr.c b/src/i830_randr.c
index 3d6febc..64d7d1f 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -740,7 +740,7 @@ xf86RandR12SetInfo12 (ScreenPtr pScreen)
 				output->mm_height);
 	xf86RROutputSetModes (output->randr_output, output->probed_modes);
 
-	switch (output->status = (*output->funcs->detect)(output)) {
+	switch (output->status) {
 	case XF86OutputStatusConnected:
 	    RROutputSetConnection (output->randr_output, RR_Connected);
 	    break;
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index cb68802..b5116be 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -1091,6 +1091,8 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
 	return;
     }
     output->driver_private = intel_output;
+    output->interlaceAllowed = FALSE;
+    output->doubleScanAllowed = FALSE;
     
     dev_priv = (struct i830_sdvo_priv *) (intel_output + 1);
     intel_output->type = I830_OUTPUT_SDVO;
diff --git a/src/i830_tv.c b/src/i830_tv.c
index 6231891..f17a353 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -1035,4 +1035,6 @@ i830_tv_init(ScrnInfoPtr pScrn)
     dev_priv->type = TV_TYPE_UNKNOWN;
     
     output->driver_private = intel_output;
+    output->interlaceAllowed = FALSE;
+    output->doubleScanAllowed = FALSE;
 }
diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index f2d6026..6e9e52a 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -542,19 +542,27 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn)
     {
 	xf86OutputPtr	    output = config->output[o];
 	DisplayModePtr	    mode;
-	DisplayModePtr	    config_modes, output_modes, default_modes;
-	XF86ConfMonitorPtr  conf_monitor = output->conf_monitor;
-	xf86MonPtr	    edid_monitor = output->MonInfo;
+	DisplayModePtr	    config_modes = NULL, output_modes, default_modes;
+	XF86ConfMonitorPtr  conf_monitor;
+	xf86MonPtr	    edid_monitor;
 	MonRec		    mon_rec;
 	enum { sync_config, sync_edid, sync_default } sync_source = sync_default;
 	
 	while (output->probed_modes != NULL)
 	    xf86DeleteMode(&output->probed_modes, output->probed_modes);
 
+	/*
+	 * Check connection status
+	 */
+	output->status = (*output->funcs->detect)(output);
+
 	if (output->status == XF86OutputStatusDisconnected)
 	    continue;
 
 	memset (&mon_rec, '\0', sizeof (mon_rec));
+	
+	conf_monitor = output->conf_monitor;
+	
 	if (conf_monitor)
 	{
 	    int	i;
@@ -573,7 +581,13 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn)
 		mon_rec.nVrefresh++;
 		sync_source = sync_config;
 	    }
+	    config_modes = i830xf86GetMonitorModes (pScrn, conf_monitor);
 	}
+	
+	output_modes = (*output->funcs->get_modes) (output);
+	
+	edid_monitor = output->MonInfo;
+	
 	if (edid_monitor)
 	{
 	    int			    i;
@@ -621,10 +635,8 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn)
 	    mon_rec.vrefresh[0].hi = 62.0;
 	    mon_rec.nVrefresh = 1;
 	}
-	
-	config_modes = i830xf86GetMonitorModes (pScrn, conf_monitor);
-	output_modes = (*output->funcs->get_modes) (output);
-	default_modes = i830xf86GetDefaultModes ();
+	default_modes = i830xf86GetDefaultModes (output->interlaceAllowed,
+						 output->doubleScanAllowed);
 	
 	if (sync_source == sync_config)
 	{
diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h
index 168d89d..3e70563 100644
--- a/src/i830_xf86Crtc.h
+++ b/src/i830_xf86Crtc.h
@@ -261,6 +261,17 @@ struct _xf86Output {
      * Possible outputs to share the same CRTC as a mask of output indices
      */
     CARD32		possible_clones;
+    
+    /**
+     * Whether this output can support interlaced modes
+     */
+    Bool		interlaceAllowed;
+
+    /**
+     * Whether this output can support double scan modes
+     */
+    Bool		doubleScanAllowed;
+
     /**
      * List of available modes on this output.
      *
@@ -270,6 +281,11 @@ struct _xf86Output {
     DisplayModePtr	probed_modes;
 
     /**
+     * Desired initial position
+     */
+    int			initial_x, initial_y;
+
+    /**
      * Current connection status
      *
      * This indicates whether a monitor is known to be connected
diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c
index 3a272cb..482a332 100644
--- a/src/i830_xf86Modes.c
+++ b/src/i830_xf86Modes.c
@@ -636,13 +636,20 @@ i830xf86GetMonitorModes (ScrnInfoPtr pSc
  * Build a mode list containing all of the default modes
  */
 DisplayModePtr
-i830xf86GetDefaultModes (void)
+i830xf86GetDefaultModes (Bool interlaceAllowed, Bool doubleScanAllowed)
 {
     DisplayModePtr  head = NULL, prev = NULL, mode;
     int		    i;
 
     for (i = 0; xf86DefaultModes[i].name != NULL; i++)
     {
+	DisplayModePtr	defMode = &xf86DefaultModes[i];
+	
+	if (!interlaceAllowed && (defMode->Flags & V_INTERLACE))
+	    continue;
+	if (!doubleScanAllowed && (defMode->Flags & V_DBLSCAN))
+	    continue;
+
 	mode = xalloc(sizeof(DisplayModeRec));
 	if (!mode)
 	    continue;
diff --git a/src/i830_xf86Modes.h b/src/i830_xf86Modes.h
index 280743b..a7d0839 100644
--- a/src/i830_xf86Modes.h
+++ b/src/i830_xf86Modes.h
@@ -90,6 +90,6 @@ DisplayModePtr
 i830xf86GetMonitorModes (ScrnInfoPtr pScrn, XF86ConfMonitorPtr conf_monitor);
 
 DisplayModePtr
-i830xf86GetDefaultModes (void);
+i830xf86GetDefaultModes (Bool interlaceAllowed, Bool doubleScanAllowed);
 
 #endif /* _I830_XF86MODES_H_ */
diff-tree 4ed79a2ba6250354ffc24fa1f7a21ca914ad157e (from b8692e646227e56c9ae4f72b9aaa75457b4c0f5f)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Dec 29 12:19:41 2006 -0800

    Relax tiling requirements on G965.
    
    For the 965, we can tile with the pitch at any integer multiple of a tile size
    (128 or 512B), up to 128KB.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 8ca79f1..7f535ac 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1663,9 +1663,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    
    pScrn->currentMode = pScrn->modes;
 
-#ifndef USE_PITCHES
-#define USE_PITCHES 1
-#endif
    pI830->disableTiling = FALSE;
 
    /*
@@ -1685,18 +1682,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    if (I830IsPrimary(pScrn) && !pI830->directRenderingDisabled) {
       int savedDisplayWidth = pScrn->displayWidth;
       int memNeeded = 0;
-      /* Good pitches to allow tiling.  Don't care about pitches < 1024. */
-      static const int pitches[] = {
-/*
-	 128 * 2,
-	 128 * 4,
-*/
-	 128 * 8,
-	 128 * 16,
-	 128 * 32,
-	 128 * 64,
-	 0
-      };
+      Bool tiled = FALSE;
 
 #ifdef I830_XV
       /*
@@ -1706,16 +1692,28 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       pI830->XvEnabled = !pI830->XvDisabled;
 #endif
 
-      for (i = 0; pitches[i] != 0; i++) {
-#if USE_PITCHES
-	 if (pitches[i] >= pScrn->displayWidth) {
-	    pScrn->displayWidth = pitches[i];
-	    break;
+      if (IS_I965G(pI830)) {
+	 int tile_pixels = 512 / pI830->cpp;
+	 pScrn->displayWidth = (pScrn->displayWidth + tile_pixels - 1) &
+	    ~(tile_pixels - 1);
+	 tiled = TRUE;
+      } else {
+	 /* Good pitches to allow tiling.  Don't care about pitches < 1024. */
+	 static const int pitches[] = {
+	    KB(1),
+	    KB(2),
+	    KB(4),
+	    KB(8),
+	    0
+	 };
+
+	 for (i = 0; pitches[i] != 0; i++) {
+	    if (pitches[i] >= pScrn->displayWidth) {
+	       pScrn->displayWidth = pitches[i];
+	       tiled = TRUE;
+	       break;
+	    }
 	 }
-#else
-	 if (pitches[i] == pScrn->displayWidth)
-	    break;
-#endif
       }
 
       /*
@@ -1723,7 +1721,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
        * memory available to enable tiling.
        */
       savedMMSize = pI830->mmSize;
-      if (pScrn->displayWidth == pitches[i]) {
+      if (tiled) {
       retry_dryrun:
 	 I830ResetAllocations(pScrn, 0);
 	 if (I830Allocate2DMemory(pScrn, ALLOCATE_DRY_RUN | ALLOC_INITIAL) &&
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 3264a2d..5bbf3e3 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -438,20 +438,33 @@ AllocateOverlay(ScrnInfoPtr pScrn, int f
 #endif
 
 static Bool
-IsTileable(int pitch)
+IsTileable(ScrnInfoPtr pScrn, int pitch)
 {
+   I830Ptr pI830 = I830PTR(pScrn);
+
+   if (IS_I965G(pI830)) {
+      if (pitch / 512 * 512 == pitch && pitch <= KB(128))
+	 return TRUE;
+      else
+	 return FALSE;
+   }
+
    /*
     * Allow tiling for pitches that are a power of 2 multiple of 128 bytes,
     * up to 64 * 128 (= 8192) bytes.
     */
    switch (pitch) {
-   case 128 * 1:
-   case 128 * 2:
-   case 128 * 4:
-   case 128 * 8:
-   case 128 * 16:
-   case 128 * 32:
-   case 128 * 64:
+   case 128:
+   case 256:
+      if (IS_I945G(pI830) || IS_I945GM(pI830))
+	 return TRUE;
+      else
+	 return FALSE;
+   case 512:
+   case KB(1):
+   case KB(2):
+   case KB(4):
+   case KB(8):
       return TRUE;
    default:
       return FALSE;
@@ -475,7 +488,7 @@ I830AllocateRotatedBuffer(ScrnInfoPtr pS
    memset(&(pI830->RotatedMem), 0, sizeof(I830MemRange));
    pI830->RotatedMem.Key = -1;
    tileable = !(flags & ALLOC_NO_TILING) &&
-	      IsTileable(pScrn->displayWidth * pI830->cpp);
+	      IsTileable(pScrn, pScrn->displayWidth * pI830->cpp);
    if (tileable) {
       /* Make the height a multiple of the tile height (16) */
       lines = (height + 15) / 16 * 16;
@@ -540,7 +553,7 @@ I830AllocateRotated2Buffer(ScrnInfoPtr p
    memset(&(pI830->RotatedMem2), 0, sizeof(I830MemRange));
    pI830->RotatedMem2.Key = -1;
    tileable = !(flags & ALLOC_NO_TILING) &&
-	      IsTileable(pI830Ent->pScrn_2->displayWidth * pI8302->cpp);
+	      IsTileable(pScrn, pI830Ent->pScrn_2->displayWidth * pI8302->cpp);
    if (tileable) {
       /* Make the height a multiple of the tile height (16) */
       lines = (height + 15) / 16 * 16;
@@ -699,7 +712,7 @@ I830AllocateFramebuffer(ScrnInfoPtr pScr
    }
 
    tileable = !(flags & ALLOC_NO_TILING) && pI830->allowPageFlip &&
-      IsTileable(pScrn->displayWidth * pI830->cpp);
+      IsTileable(pScrn, pScrn->displayWidth * pI830->cpp);
    if (tileable) {
       if (IS_I9XX(pI830))
 	 align = MB(1);
@@ -886,7 +899,7 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
 			maxFb / lineSize - pScrn->virtualY);
 	 pI830->FbMemBox.y2 = maxFb / lineSize;
 	 tileable = !(flags & ALLOC_NO_TILING) && pI830->allowPageFlip &&
-		 IsTileable(pScrn->displayWidth * pI830->cpp);
+		 IsTileable(pScrn, pScrn->displayWidth * pI830->cpp);
 	 if (tileable) {
             if (IS_I9XX(pI830))
                align = MB(1);
@@ -1113,7 +1126,7 @@ I830AllocateBackBuffer(ScrnInfoPtr pScrn
    memset(&(pI830->BackBuffer), 0, sizeof(pI830->BackBuffer));
    pI830->BackBuffer.Key = -1;
    tileable = !(flags & ALLOC_NO_TILING) &&
-	      IsTileable(pScrn->displayWidth * pI830->cpp);
+	      IsTileable(pScrn, pScrn->displayWidth * pI830->cpp);
    if (tileable) {
       /* Make the height a multiple of the tile height (16) */
       lines = (height + 15) / 16 * 16;
@@ -1176,7 +1189,7 @@ I830AllocateDepthBuffer(ScrnInfoPtr pScr
    memset(&(pI830->DepthBuffer), 0, sizeof(pI830->DepthBuffer));
    pI830->DepthBuffer.Key = -1;
    tileable = !(flags & ALLOC_NO_TILING) &&
-	      IsTileable(pScrn->displayWidth * pI830->cpp);
+	      IsTileable(pScrn, pScrn->displayWidth * pI830->cpp);
    if (tileable) {
       /* Make the height a multiple of the tile height (16) */
       lines = (height + 15) / 16 * 16;
@@ -1714,7 +1727,7 @@ I830SetupMemoryTiling(ScrnInfoPtr pScrn)
    if (!pI830->directRenderingEnabled)
       return;
 
-   if (!IsTileable(pScrn->displayWidth * pI830->cpp)) {
+   if (!IsTileable(pScrn, pScrn->displayWidth * pI830->cpp)) {
       xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		 "I830SetupMemoryTiling: Not tileable 0x%x\n",
 		 pScrn->displayWidth * pI830->cpp);
diff-tree b8692e646227e56c9ae4f72b9aaa75457b4c0f5f (from 973da654219ea43916b0b44acfa09a415bed3d7a)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Dec 28 22:23:16 2006 -0800

    Lack of configured monitor implies no configured modes.
    
    Missing check for missing monitor configuration would result in segfault.

diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c
index 58a6e6f..3a272cb 100644
--- a/src/i830_xf86Modes.c
+++ b/src/i830_xf86Modes.c
@@ -609,6 +609,9 @@ i830xf86GetMonitorModes (ScrnInfoPtr pSc
     DisplayModePtr	    modes = NULL;
     XF86ConfModesLinkPtr    modes_link;
     
+    if (!conf_monitor)
+	return NULL;
+
     /*
      * first we collect the mode lines from the UseModes directive
      */
diff-tree 973da654219ea43916b0b44acfa09a415bed3d7a (from f7b1d4c1f7d17a811e17c6a17861ff70be9fbdd7)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Dec 28 22:22:22 2006 -0800

    Sync ranges from EDID/default should not limit configured modelines.
    
    Limit the effect of sync ranges so that sync ranges found via EDID will not
    eliminate modes explicitly added by the user. Limit default sync range to
    eliminating only default modes, not configured or EDID modes.

diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index 763df43..f2d6026 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -542,9 +542,11 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn)
     {
 	xf86OutputPtr	    output = config->output[o];
 	DisplayModePtr	    mode;
+	DisplayModePtr	    config_modes, output_modes, default_modes;
 	XF86ConfMonitorPtr  conf_monitor = output->conf_monitor;
 	xf86MonPtr	    edid_monitor = output->MonInfo;
 	MonRec		    mon_rec;
+	enum { sync_config, sync_edid, sync_default } sync_source = sync_default;
 	
 	while (output->probed_modes != NULL)
 	    xf86DeleteMode(&output->probed_modes, output->probed_modes);
@@ -562,12 +564,14 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn)
 		mon_rec.hsync[mon_rec.nHsync].lo = conf_monitor->mon_hsync[i].lo;
 		mon_rec.hsync[mon_rec.nHsync].hi = conf_monitor->mon_hsync[i].hi;
 		mon_rec.nHsync++;
+		sync_source = sync_config;
 	    }
 	    for (i = 0; i < conf_monitor->mon_n_vrefresh; i++)
 	    {
 		mon_rec.vrefresh[mon_rec.nVrefresh].lo = conf_monitor->mon_vrefresh[i].lo;
 		mon_rec.vrefresh[mon_rec.nVrefresh].hi = conf_monitor->mon_vrefresh[i].hi;
 		mon_rec.nVrefresh++;
+		sync_source = sync_config;
 	    }
 	}
 	if (edid_monitor)
@@ -586,12 +590,16 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn)
 			mon_rec.hsync[mon_rec.nHsync].lo = ranges->min_h;
 			mon_rec.hsync[mon_rec.nHsync].hi = ranges->max_h;
 			mon_rec.nHsync++;
+			if (sync_source == sync_default)
+			    sync_source = sync_edid;
 		    }
 		    if (set_vrefresh && ranges->max_v)
 		    {
 			mon_rec.vrefresh[mon_rec.nVrefresh].lo = ranges->min_v;
 			mon_rec.vrefresh[mon_rec.nVrefresh].hi = ranges->max_v;
 			mon_rec.nVrefresh++;
+			if (sync_source == sync_default)
+			    sync_source = sync_edid;
 		    }
 		}
 	    }
@@ -614,19 +622,36 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn)
 	    mon_rec.nVrefresh = 1;
 	}
 	
+	config_modes = i830xf86GetMonitorModes (pScrn, conf_monitor);
+	output_modes = (*output->funcs->get_modes) (output);
+	default_modes = i830xf86GetDefaultModes ();
+	
+	if (sync_source == sync_config)
+	{
+	    /* 
+	     * Check output and config modes against sync range from config file
+	     */
+	    i830xf86ValidateModesSync (pScrn, output_modes, &mon_rec);
+	    i830xf86ValidateModesSync (pScrn, config_modes, &mon_rec);
+	}
+	/*
+	 * Check default modes against sync range
+	 */
+        i830xf86ValidateModesSync (pScrn, default_modes, &mon_rec);
+	
 	output->probed_modes = NULL;
-	if (conf_monitor)
-	    output->probed_modes = xf86ModesAdd (output->probed_modes,
-						 i830xf86GetMonitorModes (pScrn, conf_monitor));
-	output->probed_modes = xf86ModesAdd (output->probed_modes,
-					     (*output->funcs->get_modes) (output));
-	output->probed_modes = xf86ModesAdd (output->probed_modes,
-					     i830xf86GetDefaultModes ());
-
+	output->probed_modes = xf86ModesAdd (output->probed_modes, config_modes);
+	output->probed_modes = xf86ModesAdd (output->probed_modes, output_modes);
+	output->probed_modes = xf86ModesAdd (output->probed_modes, default_modes);
+	
+	/*
+	 * Check all modes against virtual size
+	 */
 	i830xf86ValidateModesSize (pScrn, output->probed_modes, virtualX, virtualY, 0);
-	i830xf86ValidateModesSync (pScrn, output->probed_modes, &mon_rec);
 	 
-	/* Strip out any modes that can't be supported on this output. */
+	/*
+	 * Check all modes against output
+	 */
 	for (mode = output->probed_modes; mode != NULL; mode = mode->next) 
 	    if (mode->status == MODE_OK)
 		mode->status = (*output->funcs->mode_valid)(output, mode);
diff-tree f7b1d4c1f7d17a811e17c6a17861ff70be9fbdd7 (from bedab1654e2dfcf7800bd0101e6991800a544019)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Dec 28 22:18:57 2006 -0800

    Belinea 10 15 55 monitor quirk - override preferred mode with largest @60Hz
    
    Belinea 10 15 55 model monitor reports a preferred mode of 640x350, when in
    fact it wants a 1024x768 mode @ 60Hz. Add an edid quirk that selects the
    largest size mode, preferring those closer to 60hz among equal sized modes.

diff --git a/src/i830_edid_modes.c b/src/i830_edid_modes.c
index 5cef46d..c121610 100644
--- a/src/i830_edid_modes.c
+++ b/src/i830_edid_modes.c
@@ -48,6 +48,8 @@ typedef enum {
     DDC_QUIRK_NONE = 0,
     /* Force detailed sync polarity to -h +v */
     DDC_QUIRK_DT_SYNC_HM_VP = 1 << 0,
+    /* First detailed mode is bogus, prefer largest mode at 60hz */
+    DDC_QUIRK_PREFER_LARGE_60 = 1 << 1,
 } ddc_quirk_t;
 
 static Bool quirk_dt_sync_hm_vp (int scrnIndex, xf86MonPtr DDC)
@@ -64,6 +66,16 @@ static Bool quirk_dt_sync_hm_vp (int scr
     return FALSE;
 }
 
+static Bool quirk_prefer_large_60 (int scrnIndex, xf86MonPtr DDC)
+{
+    /* Belinea 10 15 55 */
+    if (memcmp (DDC->vendor.name, "MAX", 4) == 0 &&
+	DDC->vendor.prod_id == 1516)
+	return TRUE;
+    
+    return FALSE;
+}
+
 typedef struct {
     Bool	(*detect) (int scrnIndex, xf86MonPtr DDC);
     ddc_quirk_t	quirk;
@@ -75,6 +87,10 @@ static const ddc_quirk_map_t ddc_quirks[
 	quirk_dt_sync_hm_vp,	DDC_QUIRK_DT_SYNC_HM_VP,
 	"Set detailed timing sync polarity to -h +v"
     },
+    {
+	quirk_prefer_large_60,   DDC_QUIRK_PREFER_LARGE_60,
+	"Detailed timing is not preferred, use largest mode at 60Hz"
+    },
     { 
 	NULL,		DDC_QUIRK_NONE,
 	"No known quirks"
@@ -234,8 +250,9 @@ xf86DDCGetModes(int scrnIndex, xf86MonPt
 	    quirks |= ddc_quirks[i].quirk;
 	}
     
-
     preferred = PREFERRED_TIMING_MODE(DDC->features.msc);
+    if (quirks & DDC_QUIRK_PREFER_LARGE_60)
+	preferred = 0;
 
     for (i = 0; i < DET_TIMINGS; i++) {
 	struct detailed_monitor_section *det_mon = &DDC->det_mon[i];
@@ -268,6 +285,33 @@ xf86DDCGetModes(int scrnIndex, xf86MonPt
     Mode = DDCModesFromStandardTiming(scrnIndex, DDC->timings2, quirks);
     Modes = xf86ModesAdd(Modes, Mode);
 
+    if (quirks & DDC_QUIRK_PREFER_LARGE_60)
+    {
+	DisplayModePtr	best = Modes;
+	for (Mode = Modes; Mode; Mode = Mode->next)
+	{
+	    if (Mode == best) continue;
+	    if (Mode->HDisplay * Mode->VDisplay > best->HDisplay * best->VDisplay)
+	    {
+		best = Mode;
+		continue;
+	    }
+	    if (Mode->HDisplay * Mode->VDisplay == best->HDisplay * best->VDisplay)
+	    {
+		double	mode_refresh = xf86ModeVRefresh (Mode);
+		double	best_refresh = xf86ModeVRefresh (best);
+		double	mode_dist = fabs(mode_refresh - 60.0);
+		double	best_dist = fabs(best_refresh - 60.0);
+		if (mode_dist < best_dist)
+		{
+		    best = Mode;
+		    continue;
+		}
+	    }
+	}
+	if (best)
+	    best->type |= M_T_PREFERRED;
+    }
     return Modes;
 }
 
diff-tree bedab1654e2dfcf7800bd0101e6991800a544019 (from 4cc5dcf6d7423239f0181f246638366edcb8be87)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Dec 28 16:34:40 2006 -0800

    Remove 8MB/32MB default VideoRam limits.
    
    With modern monitors and increased XV and EXA memory requirements, these small
    limits were resulting in DRI and other initialization failures because we
    wouldn't allow them enough memory.  Instead, allow each piece of the system
    (DRI, EXA, XAA, etc) to request as much memory as it wants, and choose the
    actual videoRam to be used for laying out the memory afterwards.
    
    With this change, in the absence of a VideoRam option, 32MB will be allocated
    for textures.

diff --git a/src/i830.h b/src/i830.h
index fd9f9aa..06f6838 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -604,14 +604,6 @@ DisplayModePtr i830_ddc_get_modes(xf86Ou
 /* i830_tv.c */
 void i830_tv_init(ScrnInfoPtr pScrn);
 
-/*
- * 12288 is set as the maximum, chosen because it is enough for
- * 1920x1440 at 32bpp with a 2048 pixel line pitch with some to spare.
- */
-#define I830_MAXIMUM_VBIOS_MEM		12288
-#define I830_DEFAULT_VIDEOMEM_2D	(MB(32) / 1024)
-#define I830_DEFAULT_VIDEOMEM_3D	(MB(64) / 1024)
-
 /* Flags for memory allocation function */
 #define FROM_ANYWHERE			0x00000000
 #define FROM_POOL_ONLY			0x00000001
diff --git a/src/i830_driver.c b/src/i830_driver.c
index e2653c1..8ca79f1 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1450,52 +1450,26 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       pI830->checkDevices = FALSE;
 
    /*
-    * The "VideoRam" config file parameter specifies the total amount of
-    * memory that will be used/allocated.  When agpgart support isn't
-    * available (StolenOnly == TRUE), this is limited to the amount of
-    * pre-allocated ("stolen") memory.
-    */
-
-   /*
-    * Default to I830_DEFAULT_VIDEOMEM_2D (8192KB) for 2D-only,
-    * or I830_DEFAULT_VIDEOMEM_3D (32768KB) for 3D.  If the stolen memory
-    * amount is higher, default to it rounded up to the nearest MB.  This
-    * guarantees that by default there will be at least some run-time
-    * space for things that need a physical address.
-    * But, we double the amounts when dual head is enabled, and therefore
-    * for 2D-only we use 16384KB, and 3D we use 65536KB. The VideoRAM 
-    * for the second head is never used, as the primary head does the 
-    * allocation.
+    * The "VideoRam" config file parameter specifies the maximum amount of
+    * memory that will be used/allocated.  When not present, we allow the
+    * driver to allocate as much memory as it wishes to satisfy its
+    * allocations, but if agpgart support isn't available (StolenOnly == TRUE),
+    * it gets limited to the amount of pre-allocated ("stolen") memory.
     */
    if (!pI830->pEnt->device->videoRam) {
       from = X_DEFAULT;
-#ifdef XF86DRI
-      if (!pI830->directRenderingDisabled)
-	 pScrn->videoRam = I830_DEFAULT_VIDEOMEM_3D;
-      else
-#endif
-	 pScrn->videoRam = I830_DEFAULT_VIDEOMEM_2D;
-
-      if (xf86IsEntityShared(pScrn->entityList[0])) {
-         if (I830IsPrimary(pScrn))
-            pScrn->videoRam += I830_DEFAULT_VIDEOMEM_2D;
-      else
-            pScrn->videoRam = I830_MAXIMUM_VBIOS_MEM;
-      } 
-
-      if (pI830->StolenMemory.Size / 1024 > pScrn->videoRam)
-	 pScrn->videoRam = ROUND_TO(pI830->StolenMemory.Size / 1024, 1024);
+      pScrn->videoRam = pI830->FbMapSize / KB(1);
    } else {
       from = X_CONFIG;
       pScrn->videoRam = pI830->pEnt->device->videoRam;
    }
 
    /* Make sure it's on a page boundary */
-   if (pScrn->videoRam & (GTT_PAGE_SIZE - 1)) {
-      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		    "VideoRAM reduced to %d kByte "
-		    "(page aligned - was %d)\n", pScrn->videoRam & ~(GTT_PAGE_SIZE - 1), pScrn->videoRam);
-      pScrn->videoRam &= ~(GTT_PAGE_SIZE - 1);
+   if (pScrn->videoRam & 3) {
+      xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VideoRam reduced to %d KB "
+		 "(page aligned - was %d KB)\n",
+		 pScrn->videoRam & ~3, pScrn->videoRam);
+      pScrn->videoRam &= ~3;
    }
 
    DPRINTF(PFX,
@@ -1523,9 +1497,9 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    }
 
    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
-	      "Pre-allocated VideoRAM: %ld kByte\n",
+	      "Pre-allocated VideoRam: %ld kByte\n",
 	      pI830->StolenMemory.Size / 1024);
-   xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d kByte\n",
+   xf86DrvMsg(pScrn->scrnIndex, from, "Potential VideoRam: %d kByte\n",
 	      pScrn->videoRam);
 
    pI830->TotalVideoRam = KB(pScrn->videoRam);
@@ -1656,9 +1630,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       pScrn->videoRam -= (MIN_SCRATCH_BUFFER_SIZE / 1024);
    }
 
-   xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
-	      "Maximum frambuffer space: %d kByte\n", pScrn->videoRam);
-
    if (!xf86RandR12PreInit (pScrn))
    {
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "RandR initialization failure\n");
@@ -1771,7 +1742,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 				      "to make room in AGP aperture for tiling.");
 		     goto retry_dryrun;
 		  }
-
+		  /* XXX */
 		  xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 			     "Allocation with DRI tiling enabled would "
 			     "exceed the\n"
@@ -1840,6 +1811,27 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 #endif
       pI830->disableTiling = TRUE; /* no DRI - so disableTiling */
 
+   if (pI830->pEnt->device->videoRam == 0) {
+      int default_videoram;
+
+      /* Now that we've sized the allocations, reduce our default VideoRam
+       * allocation from the aperture size to just what we need to cover our
+       * allocations.  Only, put in some slop for alignment and such.
+       */
+      default_videoram = pI830->StolenPool.Total.Size + pI830->allocatedMemory;
+      default_videoram += KB(512); /* slop */
+      /* align to 1MB increments */
+      default_videoram = (default_videoram + MB(1) - 1) / MB(1) * MB(1);
+
+      if (default_videoram < KB(pScrn->videoRam)) {
+	 pScrn->videoRam = default_videoram / KB(1);
+	 pI830->TotalVideoRam = KB(pScrn->videoRam);
+      }
+   }
+   xf86DrvMsg(pScrn->scrnIndex,
+	      pI830->pEnt->device->videoRam ? X_CONFIG : X_DEFAULT,
+	      "VideoRam: %d KB\n", pScrn->videoRam);
+
    if (!IS_I965G(pI830) && pScrn->displayWidth * pI830->cpp > 8192) {
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		 "Cannot support DRI with frame buffer stride > 8K.\n");
diff --git a/src/i830_memory.c b/src/i830_memory.c
index b41a73d..3264a2d 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -1239,7 +1239,14 @@ I830AllocateTextureMemory(ScrnInfoPtr pS
 
    if (pI830->mmModeFlags & I830_KERNEL_TEX) {
 
-      size = GetFreeSpace(pScrn);
+      if (dryrun && pI830->pEnt->device->videoRam == 0) {
+	 /* If we're laying out a default-sized allocation, then don't be
+	  * too greedy and just ask for 32MB.
+	  */
+	 size = MB(32);
+      } else {
+	 size = GetFreeSpace(pScrn);
+      }
       if (dryrun && (size < MB(1)))
 	 size = MB(1);
       i = myLog2(size / I830_NR_TEX_REGIONS);
diff-tree 4cc5dcf6d7423239f0181f246638366edcb8be87 (from 86da0d05e4e338e7f4c841577002eb1ba9f6b2ac)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Dec 28 16:43:39 2006 -0800

    Oops, dont use symlinks for stolen xf86 header files

diff --git a/src/xf86Optrec.h b/src/xf86Optrec.h
deleted file mode 120000
index a6ad9ce..183b857
--- a/src/xf86Optrec.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../xserver/hw/xfree86/parser/xf86Optrec.h
\ No newline at end of file
diff --git a/src/xf86Optrec.h b/src/xf86Optrec.h
new file mode 100644
index a6ad9ce..183b857
--- /dev/null
+++ b/src/xf86Optrec.h
@@ -0,0 +1,112 @@
+/* 
+ * 
+ * Copyright (c) 1997  Metro Link Incorporated
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"), 
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ * 
+ * Except as contained in this notice, the name of the Metro Link shall not be
+ * used in advertising or otherwise to promote the sale, use or other dealings
+ * in this Software without prior written authorization from Metro Link.
+ * 
+ */
+/*
+ * Copyright (c) 1997-2001 by The XFree86 Project, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the copyright holder(s)
+ * and author(s) shall not be used in advertising or otherwise to promote
+ * the sale, use or other dealings in this Software without prior written
+ * authorization from the copyright holder(s) and author(s).
+ */
+
+
+/* 
+ * This file contains the Option Record that is passed between the Parser,
+ * and Module setup procs.
+ */
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#ifndef _xf86Optrec_h_
+#define _xf86Optrec_h_
+#include <stdio.h>
+
+/* 
+ * all records that need to be linked lists should contain a GenericList as
+ * their first field.
+ */
+typedef struct generic_list_rec
+{
+	void *next;
+}
+GenericListRec, *GenericListPtr, *glp;
+
+/*
+ * All options are stored using this data type.
+ */
+typedef struct
+{
+	GenericListRec list;
+	char *opt_name;
+	char *opt_val;
+	int opt_used;
+	char *opt_comment;
+}
+XF86OptionRec, *XF86OptionPtr;
+
+
+XF86OptionPtr xf86addNewOption(XF86OptionPtr head, char *name, char *val);
+XF86OptionPtr xf86optionListDup(XF86OptionPtr opt);
+void xf86optionListFree(XF86OptionPtr opt);
+char *xf86optionName(XF86OptionPtr opt);
+char *xf86optionValue(XF86OptionPtr opt);
+XF86OptionPtr xf86newOption(char *name, char *value);
+XF86OptionPtr xf86nextOption(XF86OptionPtr list);
+XF86OptionPtr xf86findOption(XF86OptionPtr list, const char *name);
+char *xf86findOptionValue(XF86OptionPtr list, const char *name);
+int xf86findOptionBoolean (XF86OptionPtr, const char *, int);
+XF86OptionPtr xf86optionListCreate(const char **options, int count, int used);
+XF86OptionPtr xf86optionListMerge(XF86OptionPtr head, XF86OptionPtr tail);
+char *xf86configStrdup (const char *s);
+int xf86nameCompare (const char *s1, const char *s2);
+char *xf86uLongToString(unsigned long i);
+void xf86debugListOptions(XF86OptionPtr);
+XF86OptionPtr xf86parseOption(XF86OptionPtr head);
+void xf86printOptionList(FILE *fp, XF86OptionPtr list, int tabs);
+
+
+#endif /* _xf86Optrec_h_ */
diff --git a/src/xf86Parser.h b/src/xf86Parser.h
deleted file mode 120000
index 83b3aba..a682927
--- a/src/xf86Parser.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../xserver/hw/xfree86/parser/xf86Parser.h
\ No newline at end of file
diff --git a/src/xf86Parser.h b/src/xf86Parser.h
new file mode 100644
index 83b3aba..a682927
--- /dev/null
+++ b/src/xf86Parser.h
@@ -0,0 +1,483 @@
+/* 
+ * 
+ * Copyright (c) 1997  Metro Link Incorporated
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"), 
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ * 
+ * Except as contained in this notice, the name of the Metro Link shall not be
+ * used in advertising or otherwise to promote the sale, use or other dealings
+ * in this Software without prior written authorization from Metro Link.
+ * 
+ */
+/*
+ * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the copyright holder(s)
+ * and author(s) shall not be used in advertising or otherwise to promote
+ * the sale, use or other dealings in this Software without prior written
+ * authorization from the copyright holder(s) and author(s).
+ */
+
+
+/* 
+ * This file contains the external interfaces for the XFree86 configuration
+ * file parser.
+ */
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#ifndef _xf86Parser_h_
+#define _xf86Parser_h_
+
+#include "xf86Optrec.h"
+
+#define HAVE_PARSER_DECLS
+
+typedef struct
+{
+	char *file_logfile;
+	char *file_rgbpath;
+	char *file_modulepath;
+	char *file_inputdevs;
+	char *file_fontpath;
+	char *file_comment;
+}
+XF86ConfFilesRec, *XF86ConfFilesPtr;
+
+/* Values for load_type */
+#define XF86_LOAD_MODULE	0
+#define XF86_LOAD_DRIVER	1
+
+typedef struct
+{
+	GenericListRec list;
+	int load_type;
+	char *load_name;
+	XF86OptionPtr load_opt;
+	char *load_comment;
+        int ignore;
+}
+XF86LoadRec, *XF86LoadPtr;
+
+typedef struct
+{
+	XF86LoadPtr mod_load_lst;
+	char *mod_comment;
+}
+XF86ConfModuleRec, *XF86ConfModulePtr;
+
+#define CONF_IMPLICIT_KEYBOARD	"Implicit Core Keyboard"
+
+#define CONF_IMPLICIT_POINTER	"Implicit Core Pointer"
+
+#define XF86CONF_PHSYNC    0x0001
+#define XF86CONF_NHSYNC    0x0002
+#define XF86CONF_PVSYNC    0x0004
+#define XF86CONF_NVSYNC    0x0008
+#define XF86CONF_INTERLACE 0x0010
+#define XF86CONF_DBLSCAN   0x0020
+#define XF86CONF_CSYNC     0x0040
+#define XF86CONF_PCSYNC    0x0080
+#define XF86CONF_NCSYNC    0x0100
+#define XF86CONF_HSKEW     0x0200	/* hskew provided */
+#define XF86CONF_BCAST     0x0400
+#define XF86CONF_CUSTOM    0x0800	/* timing numbers customized by editor */
+#define XF86CONF_VSCAN     0x1000
+
+typedef struct
+{
+	GenericListRec list;
+	char *ml_identifier;
+	int ml_clock;
+	int ml_hdisplay;
+	int ml_hsyncstart;
+	int ml_hsyncend;
+	int ml_htotal;
+	int ml_vdisplay;
+	int ml_vsyncstart;
+	int ml_vsyncend;
+	int ml_vtotal;
+	int ml_vscan;
+	int ml_flags;
+	int ml_hskew;
+	char *ml_comment;
+}
+XF86ConfModeLineRec, *XF86ConfModeLinePtr;
+
+typedef struct
+{
+	GenericListRec list;
+	char *vp_identifier;
+	XF86OptionPtr vp_option_lst;
+	char *vp_comment;
+}
+XF86ConfVideoPortRec, *XF86ConfVideoPortPtr;
+
+typedef struct
+{
+	GenericListRec list;
+	char *va_identifier;
+	char *va_vendor;
+	char *va_board;
+	char *va_busid;
+	char *va_driver;
+	XF86OptionPtr va_option_lst;
+	XF86ConfVideoPortPtr va_port_lst;
+	char *va_fwdref;
+	char *va_comment;
+}
+XF86ConfVideoAdaptorRec, *XF86ConfVideoAdaptorPtr;
+
+#define CONF_MAX_HSYNC 8
+#define CONF_MAX_VREFRESH 8
+
+typedef struct
+{
+	float hi, lo;
+}
+parser_range;
+
+typedef struct
+{
+	int red, green, blue;
+}
+parser_rgb;
+
+typedef struct
+{
+	GenericListRec list;
+	char *modes_identifier;
+	XF86ConfModeLinePtr mon_modeline_lst;
+	char *modes_comment;
+}
+XF86ConfModesRec, *XF86ConfModesPtr;
+
+typedef struct
+{
+	GenericListRec list;
+	char *ml_modes_str;
+	XF86ConfModesPtr ml_modes;
+}
+XF86ConfModesLinkRec, *XF86ConfModesLinkPtr;
+
+typedef struct
+{
+	GenericListRec list;
+	char *mon_identifier;
+	char *mon_vendor;
+	char *mon_modelname;
+	int mon_width;				/* in mm */
+	int mon_height;				/* in mm */
+	XF86ConfModeLinePtr mon_modeline_lst;
+	int mon_n_hsync;
+	parser_range mon_hsync[CONF_MAX_HSYNC];
+	int mon_n_vrefresh;
+	parser_range mon_vrefresh[CONF_MAX_VREFRESH];
+	float mon_gamma_red;
+	float mon_gamma_green;
+	float mon_gamma_blue;
+	XF86OptionPtr mon_option_lst;
+	XF86ConfModesLinkPtr mon_modes_sect_lst;
+	char *mon_comment;
+}
+XF86ConfMonitorRec, *XF86ConfMonitorPtr;
+
+#define CONF_MAXDACSPEEDS 4
+#define CONF_MAXCLOCKS    128
+
+typedef struct
+{
+	GenericListRec list;
+	char *dev_identifier;
+	char *dev_vendor;
+	char *dev_board;
+	char *dev_chipset;
+	char *dev_busid;
+	char *dev_card;
+	char *dev_driver;
+	char *dev_ramdac;
+	int dev_dacSpeeds[CONF_MAXDACSPEEDS];
+	int dev_videoram;
+	int dev_textclockfreq;
+	unsigned long dev_bios_base;
+	unsigned long dev_mem_base;
+	unsigned long dev_io_base;
+	char *dev_clockchip;
+	int dev_clocks;
+	int dev_clock[CONF_MAXCLOCKS];
+	int dev_chipid;
+	int dev_chiprev;
+	int dev_irq;
+	int dev_screen;
+	XF86OptionPtr dev_option_lst;
+	char *dev_comment;
+}
+XF86ConfDeviceRec, *XF86ConfDevicePtr;
+
+typedef struct
+{
+	GenericListRec list;
+	char *mode_name;
+}
+XF86ModeRec, *XF86ModePtr;
+
+typedef struct
+{
+	GenericListRec list;
+	int disp_frameX0;
+	int disp_frameY0;
+	int disp_virtualX;
+	int disp_virtualY;
+	int disp_depth;
+	int disp_bpp;
+	char *disp_visual;
+	parser_rgb disp_weight;
+	parser_rgb disp_black;
+	parser_rgb disp_white;
+	XF86ModePtr disp_mode_lst;
+	XF86OptionPtr disp_option_lst;
+	char *disp_comment;
+}
+XF86ConfDisplayRec, *XF86ConfDisplayPtr;
+
+typedef struct
+{
+	XF86OptionPtr flg_option_lst;
+	char *flg_comment;
+}
+XF86ConfFlagsRec, *XF86ConfFlagsPtr;
+
+typedef struct
+{
+	GenericListRec list;
+	char *al_adaptor_str;
+	XF86ConfVideoAdaptorPtr al_adaptor;
+}
+XF86ConfAdaptorLinkRec, *XF86ConfAdaptorLinkPtr;
+
+typedef struct
+{
+	GenericListRec list;
+	char *scrn_identifier;
+	char *scrn_obso_driver;
+	int scrn_defaultdepth;
+	int scrn_defaultbpp;
+	int scrn_defaultfbbpp;
+	char *scrn_monitor_str;
+	XF86ConfMonitorPtr scrn_monitor;
+	char *scrn_device_str;
+	XF86ConfDevicePtr scrn_device;
+	XF86ConfAdaptorLinkPtr scrn_adaptor_lst;
+	XF86ConfDisplayPtr scrn_display_lst;
+	XF86OptionPtr scrn_option_lst;
+	char *scrn_comment;
+}
+XF86ConfScreenRec, *XF86ConfScreenPtr;
+
+typedef struct
+{
+	GenericListRec list;
+	char *inp_identifier;
+	char *inp_driver;
+	XF86OptionPtr inp_option_lst;
+	char *inp_comment;
+}
+XF86ConfInputRec, *XF86ConfInputPtr;
+
+typedef struct
+{
+	GenericListRec list;
+	XF86ConfInputPtr iref_inputdev;
+	char *iref_inputdev_str;
+	XF86OptionPtr iref_option_lst;
+}
+XF86ConfInputrefRec, *XF86ConfInputrefPtr;
+
+/* Values for adj_where */
+#define CONF_ADJ_OBSOLETE	-1
+#define CONF_ADJ_ABSOLUTE	0
+#define CONF_ADJ_RIGHTOF	1
+#define CONF_ADJ_LEFTOF		2
+#define CONF_ADJ_ABOVE		3
+#define CONF_ADJ_BELOW		4
+#define CONF_ADJ_RELATIVE	5
+
+typedef struct
+{
+	GenericListRec list;
+	int adj_scrnum;
+	XF86ConfScreenPtr adj_screen;
+	char *adj_screen_str;
+	XF86ConfScreenPtr adj_top;
+	char *adj_top_str;
+	XF86ConfScreenPtr adj_bottom;
+	char *adj_bottom_str;
+	XF86ConfScreenPtr adj_left;
+	char *adj_left_str;
+	XF86ConfScreenPtr adj_right;
+	char *adj_right_str;
+	int adj_where;
+	int adj_x;
+	int adj_y;
+	char *adj_refscreen;
+}
+XF86ConfAdjacencyRec, *XF86ConfAdjacencyPtr;
+
+typedef struct
+{
+	GenericListRec list;
+	char *inactive_device_str;
+	XF86ConfDevicePtr inactive_device;
+}
+XF86ConfInactiveRec, *XF86ConfInactivePtr;
+
+typedef struct
+{
+	GenericListRec list;
+	char *lay_identifier;
+	XF86ConfAdjacencyPtr lay_adjacency_lst;
+	XF86ConfInactivePtr lay_inactive_lst;
+	XF86ConfInputrefPtr lay_input_lst;
+	XF86OptionPtr lay_option_lst;
+	char *lay_comment;
+}
+XF86ConfLayoutRec, *XF86ConfLayoutPtr;
+
+typedef struct 
+{ 
+	GenericListRec list; 
+	char *vs_name;
+	char *vs_identifier;
+	XF86OptionPtr vs_option_lst;
+	char *vs_comment;
+}
+XF86ConfVendSubRec, *XF86ConfVendSubPtr;
+
+typedef struct
+{
+	GenericListRec list;
+	char *vnd_identifier;
+	XF86OptionPtr vnd_option_lst;
+	XF86ConfVendSubPtr vnd_sub_lst;
+	char *vnd_comment;
+}
+XF86ConfVendorRec, *XF86ConfVendorPtr;
+
+typedef struct
+{
+	GenericListRec list;
+	int buf_count;
+	int buf_size;
+	char *buf_flags;
+	char *buf_comment;
+}
+XF86ConfBuffersRec, *XF86ConfBuffersPtr;
+
+typedef struct
+{
+	char *dri_group_name;
+	int dri_group;
+	int dri_mode;
+	XF86ConfBuffersPtr dri_buffers_lst;
+	char *dri_comment;
+}
+XF86ConfDRIRec, *XF86ConfDRIPtr;
+
+typedef struct
+{
+	XF86OptionPtr ext_option_lst;
+	char *extensions_comment;
+}
+XF86ConfExtensionsRec, *XF86ConfExtensionsPtr;
+
+typedef struct
+{
+	XF86ConfFilesPtr conf_files;
+	XF86ConfModulePtr conf_modules;
+	XF86ConfFlagsPtr conf_flags;
+	XF86ConfVideoAdaptorPtr conf_videoadaptor_lst;
+	XF86ConfModesPtr conf_modes_lst;
+	XF86ConfMonitorPtr conf_monitor_lst;
+	XF86ConfDevicePtr conf_device_lst;
+	XF86ConfScreenPtr conf_screen_lst;
+	XF86ConfInputPtr conf_input_lst;
+	XF86ConfLayoutPtr conf_layout_lst;
+	XF86ConfVendorPtr conf_vendor_lst;
+	XF86ConfDRIPtr conf_dri;
+	XF86ConfExtensionsPtr conf_extensions;
+	char *conf_comment;
+}
+XF86ConfigRec, *XF86ConfigPtr;
+
+typedef struct
+{
+	int token;			/* id of the token */
+	char *name;			/* pointer to the LOWERCASED name */
+}
+xf86ConfigSymTabRec, *xf86ConfigSymTabPtr;
+
+/*
+ * prototypes for public functions
+ */
+extern const char *xf86openConfigFile (const char *, const char *,
+					const char *);
+extern void xf86setBuiltinConfig(const char *config[]);
+extern XF86ConfigPtr xf86readConfigFile (void);
+extern void xf86closeConfigFile (void);
+extern void xf86freeConfig (XF86ConfigPtr p);
+extern int xf86writeConfigFile (const char *, XF86ConfigPtr);
+XF86ConfDevicePtr xf86findDevice(const char *ident, XF86ConfDevicePtr p);
+XF86ConfLayoutPtr xf86findLayout(const char *name, XF86ConfLayoutPtr list);
+XF86ConfMonitorPtr xf86findMonitor(const char *ident, XF86ConfMonitorPtr p);
+XF86ConfModesPtr xf86findModes(const char *ident, XF86ConfModesPtr p);
+XF86ConfModeLinePtr xf86findModeLine(const char *ident, XF86ConfModeLinePtr p);
+XF86ConfScreenPtr xf86findScreen(const char *ident, XF86ConfScreenPtr p);
+XF86ConfInputPtr xf86findInput(const char *ident, XF86ConfInputPtr p);
+XF86ConfInputPtr xf86findInputByDriver(const char *driver, XF86ConfInputPtr p);
+XF86ConfVendorPtr xf86findVendor(const char *name, XF86ConfVendorPtr list);
+XF86ConfVideoAdaptorPtr xf86findVideoAdaptor(const char *ident,
+						XF86ConfVideoAdaptorPtr p);
+
+GenericListPtr xf86addListItem(GenericListPtr head, GenericListPtr c_new);
+int xf86itemNotSublist(GenericListPtr list_1, GenericListPtr list_2);
+
+int xf86pathIsAbsolute(const char *path);
+int xf86pathIsSafe(const char *path);
+char *xf86addComment(char *cur, char *add);
+
+#endif /* _xf86Parser_h_ */
diff-tree 86da0d05e4e338e7f4c841577002eb1ba9f6b2ac (from 2b0a997e5b4b51267fa4f6725f8a965093392434)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Dec 28 16:40:54 2006 -0800

    Add stolen xf86 header files to driver source

diff --git a/src/xf86Optrec.h b/src/xf86Optrec.h
new file mode 120000
index 0000000..a6ad9ce
--- /dev/null
+++ b/src/xf86Optrec.h
@@ -0,0 +1 @@
+../../../xserver/hw/xfree86/parser/xf86Optrec.h
\ No newline at end of file
diff --git a/src/xf86Parser.h b/src/xf86Parser.h
new file mode 120000
index 0000000..83b3aba
--- /dev/null
+++ b/src/xf86Parser.h
@@ -0,0 +1 @@
+../../../xserver/hw/xfree86/parser/xf86Parser.h
\ No newline at end of file
diff-tree 2b0a997e5b4b51267fa4f6725f8a965093392434 (from parents)
Merge: bb238a8fc234a8e5e86cd2f42c58c9816a15732c 9cfbf1ceda8f153438df1ba4b1712c55cc872017
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Dec 28 16:34:38 2006 -0800

    Merge branch 'modesetting-origin' into modesetting

diff-tree bb238a8fc234a8e5e86cd2f42c58c9816a15732c (from c87462ded20904dbc6c6cbdb9547523b75fe5471)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Dec 28 16:27:22 2006 -0800

    Configuration support: per-output mode lines, preferred mode.
    
    Add the modelines specified in the per-output monitor and all of the default
    modes to the list to each output. Prune the resulting list to specified sync
    limits and virtual sizes. Sort the resulting mode list on
    preferred/size/refresh.

diff --git a/src/i830_crt.c b/src/i830_crt.c
index 3be10ec..85c25de 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -328,38 +328,6 @@ i830_crt_detect(xf86OutputPtr output)
     return XF86OutputStatusUnknown;
 }
 
-static DisplayModePtr
-i830_crt_get_modes(xf86OutputPtr output)
-{
-    ScrnInfoPtr		pScrn = output->scrn;
-    DisplayModePtr	modes;
-    MonRec fixed_mon;
-
-    modes = i830_ddc_get_modes(output);
-    if (modes != NULL)
-	return modes;
-
-    if ((*output->funcs->detect)(output) == XF86OutputStatusDisconnected)
-	return NULL;
-
-    /* We've got a potentially-connected monitor that we can't DDC.  Return a
-     * fixed set of VESA plus user modes for a presumed multisync monitor with
-     * some reasonable limits.
-     */
-    fixed_mon.nHsync = 1;
-    fixed_mon.hsync[0].lo = 31.0;
-    fixed_mon.hsync[0].hi = 100.0;
-    fixed_mon.nVrefresh = 1;
-    fixed_mon.vrefresh[0].lo = 50.0;
-    fixed_mon.vrefresh[0].hi = 70.0;
-
-    modes = xf86DuplicateModes(pScrn, pScrn->monitor->Modes);
-    i830xf86ValidateModesSync(pScrn, modes, &fixed_mon);
-    i830xf86PruneInvalidModes(pScrn, &modes, TRUE);
-
-    return modes;
-}
-
 static void
 i830_crt_destroy (xf86OutputPtr output)
 {
@@ -375,7 +343,7 @@ static const xf86OutputFuncsRec i830_crt
     .mode_fixup = i830_crt_mode_fixup,
     .mode_set = i830_crt_mode_set,
     .detect = i830_crt_detect,
-    .get_modes = i830_crt_get_modes,
+    .get_modes = i830_ddc_get_modes,
     .destroy = i830_crt_destroy
 };
 
diff --git a/src/i830_display.h b/src/i830_display.h
index 8a982ab..5517d27 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -42,14 +42,3 @@ xf86CrtcPtr i830GetLoadDetectPipe(xf86Ou
 void i830ReleaseLoadDetectPipe(xf86OutputPtr output);
 Bool i830PipeInUse(xf86CrtcPtr crtc);
 void i830_crtc_init(ScrnInfoPtr pScrn, int pipe);
-
-/** @{
- */
-#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,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,2,99,2) */
-/** @} */
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index b682b27..fe96413 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -127,7 +127,19 @@ i830_lvds_restore(xf86OutputPtr output)
 static int
 i830_lvds_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
 {
-   return MODE_OK;
+    ScrnInfoPtr pScrn = output->scrn;
+    I830Ptr pI830 = I830PTR(pScrn);
+    DisplayModePtr  pFixedMode = pI830->panel_fixed_mode;
+
+    if (pFixedMode)
+    {
+	if (pMode->HDisplay > pFixedMode->HDisplay)
+	    return MODE_PANEL;
+	if (pMode->VDisplay > pFixedMode->VDisplay)
+	    return MODE_PANEL;
+    }
+
+    return MODE_OK;
 }
 
 static Bool
@@ -236,14 +248,37 @@ i830_lvds_detect(xf86OutputPtr output)
 static DisplayModePtr
 i830_lvds_get_modes(xf86OutputPtr output)
 {
-    ScrnInfoPtr	    pScrn = output->scrn;
-    I830Ptr	    pI830 = I830PTR(pScrn);
-    DisplayModePtr  modes;
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    ScrnInfoPtr		    pScrn = output->scrn;
+    I830Ptr		    pI830 = I830PTR(pScrn);
+    xf86MonPtr		    edid_mon;
+    DisplayModePtr	    modes;
 
-    modes = i830_ddc_get_modes(output);
+    edid_mon = i830_xf86OutputGetEDID (output, intel_output->pDDCBus);
+    i830_xf86OutputSetEDID (output, edid_mon);
+    
+    modes = i830_xf86OutputGetEDIDModes (output);
     if (modes != NULL)
 	return modes;
 
+    if (!output->MonInfo)
+    {
+	edid_mon = xcalloc (1, sizeof (xf86Monitor));
+	if (edid_mon)
+	{
+	    /* Set wide sync ranges so we get all modes
+	     * handed to valid_mode for checking
+	     */
+	    edid_mon->det_mon[0].type = DS_RANGES;
+	    edid_mon->det_mon[0].section.ranges.min_v = 0;
+	    edid_mon->det_mon[0].section.ranges.max_v = 200;
+	    edid_mon->det_mon[0].section.ranges.min_h = 0;
+	    edid_mon->det_mon[0].section.ranges.max_h = 200;
+	    
+	    output->MonInfo = edid_mon;
+	}
+    }
+
     if (pI830->panel_fixed_mode != NULL)
 	return xf86DuplicateMode(pI830->panel_fixed_mode);
 
diff --git a/src/i830_modes.c b/src/i830_modes.c
index 42ee79d..b4e22c3 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -55,98 +55,16 @@
 #include "i830_xf86Modes.h"
 #include <randrstr.h>
 
-#define DEBUG_REPROBE 1
-
-#ifdef RANDR_12_INTERFACE
-
-#define EDID_ATOM_NAME		"EDID_DATA"
-
-static void
-i830_ddc_set_edid_property(xf86OutputPtr output, void *data, int data_len)
-{
-    Atom edid_atom = MakeAtom(EDID_ATOM_NAME, sizeof(EDID_ATOM_NAME), TRUE);
-
-    /* This may get called before the RandR resources have been created */
-    if (output->randr_output == NULL)
-	return;
-
-    if (data_len != 0) {
-	RRChangeOutputProperty(output->randr_output, edid_atom, XA_INTEGER, 8,
-			       PropModeReplace, data_len, data, FALSE);
-    } else {
-	RRDeleteOutputProperty(output->randr_output, edid_atom);
-    }
-}
-#endif
-
-/**
- * Generic get_modes function using DDC, used by many outputs.
- */
 DisplayModePtr
-i830_ddc_get_modes(xf86OutputPtr output)
+i830_ddc_get_modes (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, intel_output->pDDCBus);
-    if (ddc_mon == NULL) {
-#ifdef RANDR_12_INTERFACE
-	i830_ddc_set_edid_property(output, NULL, 0);
-#endif
-	return NULL;
-    }
-
-    if (output->MonInfo != NULL)
-	xfree(output->MonInfo);
-    output->MonInfo = ddc_mon;
-
-#ifdef RANDR_12_INTERFACE
-    if (output->MonInfo->ver.version == 1) {
-	i830_ddc_set_edid_property(output, ddc_mon->rawData, 128);
-    } else if (output->MonInfo->ver.version == 2) {
-	i830_ddc_set_edid_property(output, ddc_mon->rawData, 256);
-    } else {
-	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", output->name);
-    xf86PrintEDID(output->MonInfo);
-
-    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) {
-	int status = (*output->funcs->mode_valid)(output, mode);
-
-	if (status != MODE_OK)
-	    mode->status = status;
-    }
-    i830xf86PruneInvalidModes(pScrn, &ddc_modes, TRUE);
-
-    /* Pull out a phyiscal size from a detailed timing if available. */
-    for (i = 0; i < 4; i++) {
-	if (ddc_mon->det_mon[i].type == DT &&
-	    ddc_mon->det_mon[i].section.d_timings.h_size != 0 &&
-	    ddc_mon->det_mon[i].section.d_timings.v_size != 0)
-	{
-	    output->mm_width = ddc_mon->det_mon[i].section.d_timings.h_size;
-	    output->mm_height = ddc_mon->det_mon[i].section.d_timings.v_size;
-	    break;
-	}
-    }
-
-    /* if no mm size is available from a detailed timing, check the max size field */
-    if ((!output->mm_width || !output->mm_height) &&
-	(ddc_mon->features.hsize && ddc_mon->features.vsize))
-    {
-	output->mm_width = ddc_mon->features.hsize * 10;
-	output->mm_height = ddc_mon->features.vsize * 10;
-    }
-
-    return ddc_modes;
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    xf86MonPtr		    edid_mon;
+    DisplayModePtr	    modes;
+
+    edid_mon = i830_xf86OutputGetEDID (output, intel_output->pDDCBus);
+    i830_xf86OutputSetEDID (output, edid_mon);
+    
+    modes = i830_xf86OutputGetEDIDModes (output);
+    return modes;
 }
diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index 0c482a2..763df43 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -32,9 +32,14 @@
 
 #include "xf86.h"
 #include "xf86DDC.h"
-#include "i830.h"
+/*#include "i830.h" */
 #include "i830_xf86Crtc.h"
+#include "i830_xf86Modes.h"
+#include "i830_randr.h"
 #include "X11/extensions/render.h"
+#define DPMS_SERVER
+#include "X11/extensions/dpms.h"
+#include "X11/Xatom.h"
 
 /*
  * Initialize xf86CrtcConfig structure
@@ -121,6 +126,29 @@ xf86CrtcDestroy (xf86CrtcPtr crtc)
 /*
  * Output functions
  */
+
+extern XF86ConfigPtr xf86configptr;
+
+static void
+xf86OutputSetMonitor (xf86OutputPtr output)
+{
+    char    *option_name;
+    static const char monitor_prefix[] = "monitor-";
+    char    *monitor;
+
+    option_name = xnfalloc (strlen (monitor_prefix) +
+			    strlen (output->name) + 1);
+    strcpy (option_name, monitor_prefix);
+    strcat (option_name, output->name);
+    monitor = xf86findOptionValue (output->scrn->options, option_name);
+    if (!monitor)
+	monitor = output->name;
+    else
+	xf86MarkOptionUsedByName (output->scrn->options, option_name);
+    free (option_name);
+    output->conf_monitor = xf86findMonitor (monitor, xf86configptr->conf_monitor_lst);
+}
+
 xf86OutputPtr
 xf86OutputCreate (ScrnInfoPtr		    scrn,
 		  const xf86OutputFuncsRec *funcs,
@@ -151,8 +179,11 @@ xf86OutputCreate (ScrnInfoPtr		    scrn,
 	xfree (output);
 	return NULL;
     }
+    
     xf86_config->output = outputs;
     xf86_config->output[xf86_config->num_output++] = output;
+    
+    xf86OutputSetMonitor (output);
     return output;
 }
 
@@ -169,6 +200,7 @@ xf86OutputRename (xf86OutputPtr output, 
     if (output->name != (char *) (output + 1))
 	xfree (output->name);
     output->name = newname;
+    xf86OutputSetMonitor (output);
 }
 
 void
@@ -446,12 +478,61 @@ xf86PruneDuplicateMonitorModes (MonPtr M
     }
 }
 
+/** Return - 0 + if a should be earlier, same or later than b in list
+ */
+static int
+i830xf86ModeCompare (DisplayModePtr a, DisplayModePtr b)
+{
+    int	diff;
+
+    diff = ((b->type & M_T_PREFERRED) != 0) - ((a->type & M_T_PREFERRED) != 0);
+    if (diff)
+	return diff;
+    diff = b->HDisplay * b->VDisplay - a->HDisplay * a->VDisplay;
+    if (diff)
+	return diff;
+    diff = b->Clock - a->Clock;
+    return diff;
+}
+
+/**
+ * Insertion sort input in-place and return the resulting head
+ */
+static DisplayModePtr
+i830xf86SortModes (DisplayModePtr input)
+{
+    DisplayModePtr  output = NULL, i, o, *op, prev;
+
+    while (input)
+    {
+	i = input;
+	input = input->next;
+	for (op = &output; (o = *op); op = &o->next)
+	    if (i830xf86ModeCompare (o, i) > 0)
+		break;
+	i->next = *op;
+	*op = i;
+    }
+    /* hook up backward links */
+    prev = NULL;
+    for (o = output; o; o = o->next)
+    {
+	o->prev = prev;
+	prev = o;
+    }
+    return output;
+}
+
+#define DEBUG_REPROBE 1
+
 void
 xf86ProbeOutputModes (ScrnInfoPtr pScrn)
 {
     xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
-    Bool		properties_set = FALSE;
     int			o;
+    int			virtualX, virtualY;
+
+    xf86RandR12GetOriginalVirtualSize (pScrn, &virtualX, &virtualY);
 
     /* Elide duplicate modes before defaulting code uses them */
     xf86PruneDuplicateMonitorModes (pScrn->monitor);
@@ -459,21 +540,127 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn)
     /* Probe the list of modes for each output. */
     for (o = 0; o < config->num_output; o++) 
     {
-	xf86OutputPtr  output = config->output[o];
-	DisplayModePtr mode;
-
+	xf86OutputPtr	    output = config->output[o];
+	DisplayModePtr	    mode;
+	XF86ConfMonitorPtr  conf_monitor = output->conf_monitor;
+	xf86MonPtr	    edid_monitor = output->MonInfo;
+	MonRec		    mon_rec;
+	
 	while (output->probed_modes != NULL)
 	    xf86DeleteMode(&output->probed_modes, output->probed_modes);
 
-	output->probed_modes = (*output->funcs->get_modes) (output);
+	if (output->status == XF86OutputStatusDisconnected)
+	    continue;
 
-	/* Set the DDC properties to whatever first output has DDC information.
+	memset (&mon_rec, '\0', sizeof (mon_rec));
+	if (conf_monitor)
+	{
+	    int	i;
+	    
+	    for (i = 0; i < conf_monitor->mon_n_hsync; i++)
+	    {
+		mon_rec.hsync[mon_rec.nHsync].lo = conf_monitor->mon_hsync[i].lo;
+		mon_rec.hsync[mon_rec.nHsync].hi = conf_monitor->mon_hsync[i].hi;
+		mon_rec.nHsync++;
+	    }
+	    for (i = 0; i < conf_monitor->mon_n_vrefresh; i++)
+	    {
+		mon_rec.vrefresh[mon_rec.nVrefresh].lo = conf_monitor->mon_vrefresh[i].lo;
+		mon_rec.vrefresh[mon_rec.nVrefresh].hi = conf_monitor->mon_vrefresh[i].hi;
+		mon_rec.nVrefresh++;
+	    }
+	}
+	if (edid_monitor)
+	{
+	    int			    i;
+	    Bool		    set_hsync = mon_rec.nHsync == 0;
+	    Bool		    set_vrefresh = mon_rec.nVrefresh == 0;
+
+	    for (i = 0; i < sizeof (edid_monitor->det_mon) / sizeof (edid_monitor->det_mon[0]); i++)
+	    {
+		if (edid_monitor->det_mon[i].type == DS_RANGES)
+		{
+		    struct monitor_ranges   *ranges = &edid_monitor->det_mon[i].section.ranges;
+		    if (set_hsync && ranges->max_h)
+		    {
+			mon_rec.hsync[mon_rec.nHsync].lo = ranges->min_h;
+			mon_rec.hsync[mon_rec.nHsync].hi = ranges->max_h;
+			mon_rec.nHsync++;
+		    }
+		    if (set_vrefresh && ranges->max_v)
+		    {
+			mon_rec.vrefresh[mon_rec.nVrefresh].lo = ranges->min_v;
+			mon_rec.vrefresh[mon_rec.nVrefresh].hi = ranges->max_v;
+			mon_rec.nVrefresh++;
+		    }
+		}
+	    }
+	}
+	/*
+	 * These limits will end up setting a 1024x768 at 60Hz mode by default,
+	 * which seems like a fairly good mode to use when nothing else is
+	 * specified
 	 */
-	if (output->MonInfo != NULL && !properties_set) {
-	    xf86SetDDCproperties(pScrn, output->MonInfo);
-	    properties_set = TRUE;
+	if (mon_rec.nHsync == 0)
+	{
+	    mon_rec.hsync[0].lo = 31.0;
+	    mon_rec.hsync[0].hi = 55.0;
+	    mon_rec.nHsync = 1;
+	}
+	if (mon_rec.nVrefresh == 0)
+	{
+	    mon_rec.vrefresh[0].lo = 58.0;
+	    mon_rec.vrefresh[0].hi = 62.0;
+	    mon_rec.nVrefresh = 1;
 	}
+	
+	output->probed_modes = NULL;
+	if (conf_monitor)
+	    output->probed_modes = xf86ModesAdd (output->probed_modes,
+						 i830xf86GetMonitorModes (pScrn, conf_monitor));
+	output->probed_modes = xf86ModesAdd (output->probed_modes,
+					     (*output->funcs->get_modes) (output));
+	output->probed_modes = xf86ModesAdd (output->probed_modes,
+					     i830xf86GetDefaultModes ());
+
+	i830xf86ValidateModesSize (pScrn, output->probed_modes, virtualX, virtualY, 0);
+	i830xf86ValidateModesSync (pScrn, output->probed_modes, &mon_rec);
+	 
+	/* Strip out any modes that can't be supported on this output. */
+	for (mode = output->probed_modes; mode != NULL; mode = mode->next) 
+	    if (mode->status == MODE_OK)
+		mode->status = (*output->funcs->mode_valid)(output, mode);
+	
+	i830xf86PruneInvalidModes(pScrn, &output->probed_modes, TRUE);
+	
+	output->probed_modes = i830xf86SortModes (output->probed_modes);
+	
+	/* Check for a configured preference for a particular mode */
+	if (conf_monitor)
+	{
+	    char  *preferred_mode = xf86findOptionValue (conf_monitor->mon_option_lst,
+							 "Preferred Mode");
 
+	    if (preferred_mode)
+	    {
+		for (mode = output->probed_modes; mode; mode = mode->next)
+		    if (!strcmp (preferred_mode, mode->name))
+			break;
+		if (mode && mode != output->probed_modes)
+		{
+		    if (mode->prev)
+			mode->prev->next = mode->next;
+		    if (mode->next)
+			mode->next->prev = mode->prev;
+		    mode->next = output->probed_modes;
+		    output->probed_modes->prev = mode;
+		    mode->prev = NULL;
+		    output->probed_modes = mode;
+		    mode->type |= M_T_PREFERRED;
+		}
+	    }
+	}
+	
 #ifdef DEBUG_REPROBE
 	if (output->probed_modes != NULL) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
@@ -747,3 +934,112 @@ xf86DPMSSet(ScrnInfoPtr pScrn, int mode,
 	}
     }
 }
+
+#ifdef RANDR_12_INTERFACE
+
+#define EDID_ATOM_NAME		"EDID_DATA"
+
+/**
+ * Set the RandR EDID property
+ */
+static void
+xf86OutputSetEDIDProperty (xf86OutputPtr output, void *data, int data_len)
+{
+    Atom edid_atom = MakeAtom(EDID_ATOM_NAME, sizeof(EDID_ATOM_NAME), TRUE);
+
+    /* This may get called before the RandR resources have been created */
+    if (output->randr_output == NULL)
+	return;
+
+    if (data_len != 0) {
+	RRChangeOutputProperty(output->randr_output, edid_atom, XA_INTEGER, 8,
+			       PropModeReplace, data_len, data, FALSE);
+    } else {
+	RRDeleteOutputProperty(output->randr_output, edid_atom);
+    }
+}
+
+#endif
+
+/**
+ * Set the EDID information for the specified output
+ */
+void
+i830_xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon)
+{
+    ScrnInfoPtr		pScrn = output->scrn;
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int			i, size;
+    
+    if (output->MonInfo != NULL)
+	xfree(output->MonInfo);
+    
+    output->MonInfo = edid_mon;
+
+    /* Debug info for now, at least */
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID for output %s\n", output->name);
+    xf86PrintEDID(edid_mon);
+    
+    /* Set the DDC properties for the 'compat' output */
+    if (output == config->output[config->compat_output])
+        xf86SetDDCproperties(pScrn, edid_mon);
+
+#ifdef RANDR_12_INTERFACE
+    /* Set the RandR output properties */
+    size = 0;
+    if (edid_mon)
+    {
+	if (edid_mon->ver.version == 1)
+	    size = 128;
+	else if (edid_mon->ver.version == 2)
+	    size = 256;
+    }
+    xf86OutputSetEDIDProperty (output, edid_mon ? edid_mon->rawData : NULL, size);
+#endif
+
+    if (edid_mon)
+    {
+	/* Pull out a phyiscal size from a detailed timing if available. */
+	for (i = 0; i < 4; i++) {
+	    if (edid_mon->det_mon[i].type == DT &&
+		edid_mon->det_mon[i].section.d_timings.h_size != 0 &&
+		edid_mon->det_mon[i].section.d_timings.v_size != 0)
+	    {
+		output->mm_width = edid_mon->det_mon[i].section.d_timings.h_size;
+		output->mm_height = edid_mon->det_mon[i].section.d_timings.v_size;
+		break;
+	    }
+	}
+    
+	/* if no mm size is available from a detailed timing, check the max size field */
+	if ((!output->mm_width || !output->mm_height) &&
+	    (edid_mon->features.hsize && edid_mon->features.vsize))
+	{
+	    output->mm_width = edid_mon->features.hsize * 10;
+	    output->mm_height = edid_mon->features.vsize * 10;
+	}
+    }
+}
+
+/**
+ * Return the list of modes supported by the EDID information
+ * stored in 'output'
+ */
+DisplayModePtr
+i830_xf86OutputGetEDIDModes (xf86OutputPtr output)
+{
+    ScrnInfoPtr	pScrn = output->scrn;
+    xf86MonPtr	edid_mon = output->MonInfo;
+
+    if (!edid_mon)
+	return NULL;
+    return xf86DDCGetModes(pScrn->scrnIndex, edid_mon);
+}
+
+xf86MonPtr
+i830_xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus)
+{
+    ScrnInfoPtr	pScrn = output->scrn;
+
+    return xf86DoEDID_DDC2 (pScrn->scrnIndex, pDDCBus);
+}
diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h
index 9294ccc..168d89d 100644
--- a/src/i830_xf86Crtc.h
+++ b/src/i830_xf86Crtc.h
@@ -25,6 +25,7 @@
 #include <edid.h>
 #include "randrstr.h"
 #include "i830_xf86Modes.h"
+#include "xf86Parser.h"
 
 typedef struct _xf86Crtc xf86CrtcRec, *xf86CrtcPtr;
 typedef struct _xf86Output xf86OutputRec, *xf86OutputPtr;
@@ -288,6 +289,12 @@ struct _xf86Output {
     /** Output name */
     char		*name;
 
+    /** Configured monitor name */
+    char		*monitor_name;
+
+    /** Monitor information from config file */
+    XF86ConfMonitorPtr	conf_monitor;
+
     /** output-specific functions */
     const xf86OutputFuncsRec *funcs;
 
@@ -396,5 +403,21 @@ xf86InitialConfiguration (ScrnInfoPtr pS
 
 void
 xf86DPMSSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags);
+    
+/**
+ * Set the EDID information for the specified output
+ */
+void
+i830_xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon);
+
+/**
+ * Return the list of modes supported by the EDID information
+ * stored in 'output'
+ */
+DisplayModePtr
+i830_xf86OutputGetEDIDModes (xf86OutputPtr output);
+
+xf86MonPtr
+i830_xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus);
 
 #endif /* _XF86CRTC_H_ */
diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c
index 1afda95..58a6e6f 100644
--- a/src/i830_xf86Modes.c
+++ b/src/i830_xf86Modes.c
@@ -39,6 +39,9 @@
 #include "xf86.h"
 #include "i830.h"
 #include "i830_xf86Modes.h"
+#include "xf86Priv.h"
+
+extern XF86ConfigPtr xf86configptr;
 
 /**
  * @file this file contains symbols from xf86Mode.c and friends that are static
@@ -550,3 +553,110 @@ xf86ModesAdd(DisplayModePtr modes, Displ
 
     return modes;
 }
+
+/**
+ * Build a mode list from a list of config file modes
+ */
+static DisplayModePtr
+i830xf86GetConfigModes (XF86ConfModeLinePtr conf_mode)
+{
+    DisplayModePtr  head = NULL, prev = NULL, mode;
+    
+    for (; conf_mode; conf_mode = (XF86ConfModeLinePtr) conf_mode->list.next)
+    {
+        mode = xalloc(sizeof(DisplayModeRec));
+	if (!mode)
+	    continue;
+        mode->name       = xstrdup(conf_mode->ml_identifier);
+	if (!mode->name)
+	{
+	    xfree (mode);
+	    continue;
+	}
+	
+        memset(mode,'\0',sizeof(DisplayModeRec));
+	mode->type       = 0;
+        mode->Clock      = conf_mode->ml_clock;
+        mode->HDisplay   = conf_mode->ml_hdisplay;
+        mode->HSyncStart = conf_mode->ml_hsyncstart;
+        mode->HSyncEnd   = conf_mode->ml_hsyncend;
+        mode->HTotal     = conf_mode->ml_htotal;
+        mode->VDisplay   = conf_mode->ml_vdisplay;
+        mode->VSyncStart = conf_mode->ml_vsyncstart;
+        mode->VSyncEnd   = conf_mode->ml_vsyncend;
+        mode->VTotal     = conf_mode->ml_vtotal;
+        mode->Flags      = conf_mode->ml_flags;
+        mode->HSkew      = conf_mode->ml_hskew;
+        mode->VScan      = conf_mode->ml_vscan;
+
+        mode->prev = prev;
+	mode->next = NULL;
+	if (prev)
+	    prev->next = mode;
+	else
+	    head = mode;
+	prev = mode;
+    }
+    return head;
+}
+
+/**
+ * Build a mode list from a monitor configuration
+ */
+DisplayModePtr
+i830xf86GetMonitorModes (ScrnInfoPtr pScrn, XF86ConfMonitorPtr conf_monitor)
+{
+    DisplayModePtr	    modes = NULL;
+    XF86ConfModesLinkPtr    modes_link;
+    
+    /*
+     * first we collect the mode lines from the UseModes directive
+     */
+    for (modes_link = conf_monitor->mon_modes_sect_lst; 
+	 modes_link; 
+	 modes_link = modes_link->list.next)
+    {
+	/* If this modes link hasn't been resolved, go look it up now */
+	if (!modes_link->ml_modes)
+	    modes_link->ml_modes = xf86findModes (modes_link->ml_modes_str, 
+						  xf86configptr->conf_modes_lst);
+	if (modes_link->ml_modes)
+	    modes = xf86ModesAdd (modes,
+				  i830xf86GetConfigModes (modes_link->ml_modes->mon_modeline_lst));
+    }
+
+    return xf86ModesAdd (modes,
+			 i830xf86GetConfigModes (conf_monitor->mon_modeline_lst));
+}
+
+/**
+ * Build a mode list containing all of the default modes
+ */
+DisplayModePtr
+i830xf86GetDefaultModes (void)
+{
+    DisplayModePtr  head = NULL, prev = NULL, mode;
+    int		    i;
+
+    for (i = 0; xf86DefaultModes[i].name != NULL; i++)
+    {
+	mode = xalloc(sizeof(DisplayModeRec));
+	if (!mode)
+	    continue;
+        memcpy(mode,&xf86DefaultModes[i],sizeof(DisplayModeRec));
+        mode->name = xstrdup(xf86DefaultModes[i].name);
+        if (!mode->name)
+	{
+	    xfree (mode);
+	    continue;
+	}
+        mode->prev = prev;
+	mode->next = NULL;
+	if (prev)
+	    prev->next = mode;
+	else
+	    head = mode;
+	prev = mode;
+    }
+    return head;
+}
diff --git a/src/i830_xf86Modes.h b/src/i830_xf86Modes.h
index 9830003..280743b 100644
--- a/src/i830_xf86Modes.h
+++ b/src/i830_xf86Modes.h
@@ -28,6 +28,7 @@
 #ifndef _I830_XF86MODES_H_
 #define _I830_XF86MODES_H_
 #include "xorgVersion.h"
+#include "xf86Parser.h"
 
 #if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0)
 double i830_xf86ModeHSync(DisplayModePtr mode);
@@ -41,6 +42,10 @@ Bool i830_xf86ModesEqual(DisplayModePtr 
 void i830_xf86PrintModeline(int scrnIndex,DisplayModePtr mode);
 DisplayModePtr i830_xf86ModesAdd(DisplayModePtr modes, DisplayModePtr new);
 
+DisplayModePtr i830_xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC);
+DisplayModePtr i830_xf86CVTMode(int HDisplay, int VDisplay, float VRefresh,
+				Bool Reduced, Bool Interlaced);
+
 #define xf86ModeHSync i830_xf86ModeHSync
 #define xf86ModeVRefresh i830_xf86ModeVRefresh
 #define xf86DuplicateMode i830_xf86DuplicateMode
@@ -50,6 +55,8 @@ DisplayModePtr i830_xf86ModesAdd(Display
 #define xf86ModesEqual i830_xf86ModesEqual
 #define xf86PrintModeline i830_xf86PrintModeline
 #define xf86ModesAdd i830_xf86ModesAdd
+#define xf86DDCGetModes i830_xf86DDCGetModes
+#define xf86CVTMode i830_xf86CVTMode
 #endif /* XORG_VERSION_CURRENT <= 7.2.99.2 */
 
 void
@@ -79,4 +86,10 @@ i830xf86ValidateModesFlags(ScrnInfoPtr p
 void
 i830xf86ValidateModesUserConfig(ScrnInfoPtr pScrn, DisplayModePtr modeList);
 
+DisplayModePtr
+i830xf86GetMonitorModes (ScrnInfoPtr pScrn, XF86ConfMonitorPtr conf_monitor);
+
+DisplayModePtr
+i830xf86GetDefaultModes (void);
+
 #endif /* _I830_XF86MODES_H_ */
diff-tree 9cfbf1ceda8f153438df1ba4b1712c55cc872017 (from e889bde13dcc2438181a03319e204ae7b9235a78)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Dec 28 12:59:23 2006 -0800

    In EXA mode, force backing pixmaps into memory when doing XV to them.

diff --git a/src/i830_video.c b/src/i830_video.c
index b50b21b..f031a87 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -140,6 +140,11 @@ static Atom xvGamma0, xvGamma1, xvGamma2
 #define OVERLAY_DEBUG if (0) ErrorF
 #endif
 
+/* Oops, I never exported this function in EXA.  I meant to. */
+#ifndef exaMoveInPixmap
+void exaMoveInPixmap (PixmapPtr pPixmap);
+#endif
+
 /*
  * This is more or less the correct way to initalise, update, and shut down
  * the overlay.  Note OVERLAY_OFF should be used only after disabling the
@@ -2388,6 +2393,13 @@ I830PutImage(ScrnInfoPtr pScrn,
       pPixmap = (PixmapPtr)pDraw;
    }
 
+#ifdef I830_USE_EXA
+   if (pI830->useEXA) {
+       /* Force the pixmap into framebuffer so we can draw to it. */
+       exaMoveInPixmap(pPixmap);
+   }
+#endif
+
    if (((char *)pPixmap->devPrivate.ptr < (char *)pI830->FbBase) ||
        ((char *)pPixmap->devPrivate.ptr >= (char *)pI830->FbBase +
 	pI830->FbMapSize)) {
diff-tree e889bde13dcc2438181a03319e204ae7b9235a78 (from c7083a6f30fdf1859f60beba4c352bd790af4773)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Dec 28 12:49:24 2006 -0800

    Draw textured video to the backing pixmap in the composited case.
    
    Currently, when the backing pixmap is not in framebuffer, we just BadAlloc
    rather than drawing garbage to the front buffer.  This can be fixed with EXA.

diff --git a/src/i830_video.c b/src/i830_video.c
index 76d4f9c..b50b21b 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -76,6 +76,8 @@ THE USE OR OTHER DEALINGS IN THE SOFTWAR
 #include "xf86fbman.h"
 #include "regionstr.h"
 #include "randrstr.h"
+#include "windowstr.h"
+#include "damage.h"
 #include "i830.h"
 #include "i830_video.h"
 #include "xf86xv.h"
@@ -2016,7 +2018,6 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
    OVERLAY_UPDATE;
 }
 
-
 #ifdef I830_USE_EXA
 static void
 I830VideoSave(ScreenPtr pScreen, ExaOffscreenArea *area)
@@ -2167,6 +2168,7 @@ I830PutImage(ScrnInfoPtr pScrn,
    ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
    I830OverlayRegPtr overlay =
 	 (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start);
+   PixmapPtr pPixmap;
    INT32 x1, x2, y1, y2;
    int srcPitch, srcPitch2 = 0, dstPitch, destId;
    int top, left, npixels, nlines, size, loops;
@@ -2380,6 +2382,21 @@ I830PutImage(ScrnInfoPtr pScrn,
       break;
    }
 
+   if (pDraw->type == DRAWABLE_WINDOW) {
+      pPixmap = (*pScreen->GetWindowPixmap)((WindowPtr)pDraw);
+   } else {
+      pPixmap = (PixmapPtr)pDraw;
+   }
+
+   if (((char *)pPixmap->devPrivate.ptr < (char *)pI830->FbBase) ||
+       ((char *)pPixmap->devPrivate.ptr >= (char *)pI830->FbBase +
+	pI830->FbMapSize)) {
+      /* If the pixmap wasn't in framebuffer, then we have no way in XAA to
+       * force it there.  So, we simply refuse to draw and fail.
+       */
+      return BadAlloc;
+   }
+
    if (!pPriv->textured) {
       /* update cliplist */
       if (!RegionsEqual(&pPriv->clip, clipBoxes)) {
@@ -2392,12 +2409,16 @@ I830PutImage(ScrnInfoPtr pScrn,
    } else if (IS_I965G(pI830)) {
       I965DisplayVideoTextured(pScrn, pPriv, destId, clipBoxes, width, height,
 			       dstPitch, x1, y1, x2, y2,
-			       src_w, src_h, drw_w, drw_h, pDraw);
+			       src_w, src_h, drw_w, drw_h, pPixmap);
    } else {
       I915DisplayVideoTextured(pScrn, pPriv, destId, clipBoxes, width, height,
 			       dstPitch, x1, y1, x2, y2,
-			       src_w, src_h, drw_w, drw_h, pDraw);
+			       src_w, src_h, drw_w, drw_h, pPixmap);
    }
+   if (pPriv->textured) {
+      DamageDamageRegion(pDraw, clipBoxes);
+   }
+
    pPriv->videoStatus = CLIENT_VIDEO_ON;
 
    return Success;
diff --git a/src/i830_video.h b/src/i830_video.h
index 90c58b7..854d0b8 100644
--- a/src/i830_video.h
+++ b/src/i830_video.h
@@ -92,7 +92,7 @@ void I915DisplayVideoTextured(ScrnInfoPt
 			      int x1, int y1, int x2, int y2,
 			      short src_w, short src_h,
 			      short drw_w, short drw_h,
-			      DrawablePtr pDraw);
+			      PixmapPtr pPixmap);
 
 void I965DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv,
 			      int id, RegionPtr dstRegion, short width,
@@ -100,4 +100,4 @@ void I965DisplayVideoTextured(ScrnInfoPt
 			      int x1, int y1, int x2, int y2,
 			      short src_w, short src_h,
 			      short drw_w, short drw_h,
-			      DrawablePtr pDraw);
+			      PixmapPtr pPixmap);
diff --git a/src/i915_video.c b/src/i915_video.c
index 636b2cb..52fe1a5 100644
--- a/src/i915_video.c
+++ b/src/i915_video.c
@@ -57,12 +57,12 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
 			 short width, short height, int video_pitch,
 			 int x1, int y1, int x2, int y2,
 			 short src_w, short src_h, short drw_w, short drw_h,
-			 DrawablePtr pDraw)
+			 PixmapPtr pPixmap)
 {
    I830Ptr pI830 = I830PTR(pScrn);
    CARD32 format, ms3, s2, s5;
    BoxPtr pbox;
-   int nbox, dxo, dyo;
+   int nbox, dxo, dyo, pix_xoff, pix_yoff;
    Bool planar;
 
 #if 0
@@ -103,7 +103,8 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
 
    /* draw rect -- just clipping */
    OUT_RING(_3DSTATE_DRAW_RECT_CMD);
-   OUT_RING(DRAW_DITHER_OFS_X(pDraw->x & 3)| DRAW_DITHER_OFS_Y(pDraw->y & 3)); /* flags */
+   OUT_RING(DRAW_DITHER_OFS_X(pPixmap->drawable.x & 3) |
+	    DRAW_DITHER_OFS_Y(pPixmap->drawable.y & 3));
    OUT_RING(0x00000000);	/* ymin, xmin */
    OUT_RING((pScrn->virtualX - 1) |
 	    (pScrn->virtualY - 1) << 16); /* ymax, xmax */
@@ -155,8 +156,8 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
    /* front buffer, pitch, offset */
    OUT_RING(_3DSTATE_BUF_INFO_CMD);
    OUT_RING(BUF_3D_ID_COLOR_BACK | BUF_3D_USE_FENCE |
-	    (((pI830->displayWidth * pI830->cpp) / 4) << 2));
-   OUT_RING(pI830->bufferOffset);
+	    BUF_3D_PITCH(pPixmap->devKind));
+   OUT_RING(BUF_3D_ADDR((long)pPixmap->devPrivate.ptr - (long)pI830->FbBase));
    ADVANCE_LP_RING();
 
    if (!planar) {
@@ -340,6 +341,17 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
       ADVANCE_LP_RING();
    }
 
+   /* Set up the offset for translating from the given region (in screen
+    * coordinates) to the backing pixmap.
+    */
+#ifdef COMPOSITE
+   pix_xoff = -pPixmap->screen_x + pPixmap->drawable.x;
+   pix_yoff = -pPixmap->screen_y + pPixmap->drawable.y;
+#else
+   pix_xoff = 0;
+   pix_yoff = 0;
+#endif
+
    dxo = dstRegion->extents.x1;
    dyo = dstRegion->extents.y1;
 
@@ -380,8 +392,8 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
 	       (vert_data_count - 1));
 
       /* bottom right */
-      OUT_RING_F(box_x2);
-      OUT_RING_F(box_y2);
+      OUT_RING_F(box_x2 + pix_xoff);
+      OUT_RING_F(box_y2 + pix_yoff);
       if (!planar) {
 	 OUT_RING_F((box_x2 - dxo) * src_scale_x);
 	 OUT_RING_F((box_y2 - dyo) * src_scale_y);
@@ -393,8 +405,8 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
       }
 
       /* bottom left */
-      OUT_RING_F(box_x1);
-      OUT_RING_F(box_y2);
+      OUT_RING_F(box_x1 + pix_xoff);
+      OUT_RING_F(box_y2 + pix_yoff);
       if (!planar) {
 	 OUT_RING_F((box_x1 - dxo) * src_scale_x);
 	 OUT_RING_F((box_y2 - dyo) * src_scale_y);
@@ -406,8 +418,8 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
       }
 
       /* top left */
-      OUT_RING_F(box_x1);
-      OUT_RING_F(box_y1);
+      OUT_RING_F(box_x1 + pix_xoff);
+      OUT_RING_F(box_y1 + pix_yoff);
       if (!planar) {
 	 OUT_RING_F((box_x1 - dxo) * src_scale_x);
 	 OUT_RING_F((box_y1 - dyo) * src_scale_y);
diff --git a/src/i965_video.c b/src/i965_video.c
index af22cb2..0d1bec6 100644
--- a/src/i965_video.c
+++ b/src/i965_video.c
@@ -149,11 +149,11 @@ I965DisplayVideoTextured(ScrnInfoPtr pSc
 			 int x1, int y1, int x2, int y2,
 			 short src_w, short src_h,
 			 short drw_w, short drw_h,
-			 DrawablePtr pDraw)
+			 PixmapPtr pPixmap)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     BoxPtr pbox;
-    int nbox, dxo, dyo;
+    int nbox, dxo, dyo, pix_xoff, pix_yoff;
     int urb_vs_start, urb_vs_size;
     int urb_gs_start, urb_gs_size;
     int urb_clip_start, urb_clip_size;
@@ -381,12 +381,13 @@ I965DisplayVideoTextured(ScrnInfoPtr pSc
     dest_surf_state->ss0.mipmap_layout_mode = 0;
     dest_surf_state->ss0.render_cache_read_mode = 0;
 
-    dest_surf_state->ss1.base_addr = pI830->FrontBuffer.Start;
+    dest_surf_state->ss1.base_addr = (long)pPixmap->devPrivate.ptr -
+	(long)pI830->FbBase;
     dest_surf_state->ss2.height = pScrn->virtualY - 1;
     dest_surf_state->ss2.width = pScrn->virtualX - 1;
     dest_surf_state->ss2.mip_count = 0;
     dest_surf_state->ss2.render_target_rotation = 0;
-    dest_surf_state->ss3.pitch = (pI830->displayWidth * pI830->cpp) - 1;
+    dest_surf_state->ss3.pitch = pPixmap->devKind - 1;
 
     /* Set up the source surface state buffer */
     memset(src_surf_state, 0, sizeof(*src_surf_state));
@@ -656,6 +657,17 @@ I965DisplayVideoTextured(ScrnInfoPtr pSc
        ADVANCE_LP_RING();
     }
 
+   /* Set up the offset for translating from the given region (in screen
+    * coordinates) to the backing pixmap.
+    */
+#ifdef COMPOSITE
+    pix_xoff = -pPixmap->screen_x + pPixmap->drawable.x;
+    pix_yoff = -pPixmap->screen_y + pPixmap->drawable.y;
+#else
+    pix_xoff = 0;
+    pix_yoff = 0;
+#endif
+
     dxo = dstRegion->extents.x1;
     dyo = dstRegion->extents.y1;
 
@@ -685,18 +697,18 @@ I965DisplayVideoTextured(ScrnInfoPtr pSc
 	i = 0;
 	vb[i++] = (box_x2 - dxo) * src_scale_x;
 	vb[i++] = (box_y2 - dyo) * src_scale_y;
-	vb[i++] = (float) box_x2;
-	vb[i++] = (float) box_y2;
+	vb[i++] = (float) box_x2 + pix_xoff;
+	vb[i++] = (float) box_y2 + pix_yoff;
 
 	vb[i++] = (box_x1 - dxo) * src_scale_x;
 	vb[i++] = (box_y2 - dyo) * src_scale_y;
-	vb[i++] = (float) box_x1;
-	vb[i++] = (float) box_y2;
+	vb[i++] = (float) box_x1 + pix_xoff;
+	vb[i++] = (float) box_y2 + pix_yoff;
 
 	vb[i++] = (box_x1 - dxo) * src_scale_x;
 	vb[i++] = (box_y1 - dyo) * src_scale_y;
-	vb[i++] = (float) box_x1;
-	vb[i++] = (float) box_y1;
+	vb[i++] = (float) box_x1 + pix_xoff;
+	vb[i++] = (float) box_y1 + pix_yoff;
 
 #if 0
 	ErrorF ("before EU_ATT 0x%08x%08x EU_ATT_DATA 0x%08x%08x\n",
diff-tree c7083a6f30fdf1859f60beba4c352bd790af4773 (from 778db49616b233f5a2f4f007ceb62a1a878a6e25)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Dec 28 11:53:33 2006 -0800

    Add WIP CH7017 LVDS driver.  This is disconnected because it's untested.

diff --git a/configure.ac b/configure.ac
index 30a69bc..be80a87 100644
--- a/configure.ac
+++ b/configure.ac
@@ -148,6 +148,7 @@ AC_OUTPUT([
 	src/Makefile
 	src/xvmc/Makefile
 	src/bios_reader/Makefile
+	src/ch7017/Makefile
 	src/ch7xxx/Makefile
 	src/ivch/Makefile
 	src/sil164/Makefile
diff --git a/src/Makefile.am b/src/Makefile.am
index 77a1917..5309eea 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -18,7 +18,7 @@
 #  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 #  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
-SUBDIRS = xvmc bios_reader ch7xxx ivch sil164
+SUBDIRS = xvmc bios_reader ch7017 ch7xxx ivch sil164
 
 # this is obnoxious:
 # -module lets us name the module exactly how we want
diff --git a/src/ch7017/Makefile.am b/src/ch7017/Makefile.am
new file mode 100644
index 0000000..9cf2fa4
--- /dev/null
+++ b/src/ch7017/Makefile.am
@@ -0,0 +1,15 @@
+# this is obnoxious:
+# -module lets us name the module exactly how we want
+# -avoid-version prevents gratuitous .0.0.0 version numbers on the end
+# _ladir passes a dummy rpath to libtool so the thing will actually link
+# TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
+AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@
+
+ch7017_la_LTLIBRARIES = ch7017.la
+ch7017_la_LDFLAGS = -module -avoid-version
+ch7017_ladir = @moduledir@/drivers
+
+ch7017_la_SOURCES = \
+	ch7017.c \
+	ch7017_module.c \
+	ch7017_reg.h
diff --git a/src/ch7017/ch7017.c b/src/ch7017/ch7017.c
new file mode 100644
index 0000000..28bce0d
--- /dev/null
+++ b/src/ch7017/ch7017.c
@@ -0,0 +1,302 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86Resources.h"
+#include "compiler.h"
+#include "miscstruct.h"
+#include "xf86i2c.h"
+#include "../i830_xf86Crtc.h"
+#define DPMS_SERVER
+#include <X11/extensions/dpms.h>
+
+#include "../i2c_vid.h"
+#include "ch7017_reg.h"
+
+struct ch7017_priv {
+    I2CDevRec d;
+
+    CARD8 save_hapi;
+    CARD8 save_vali;
+    CARD8 save_valo;
+    CARD8 save_lvds_pll_vco;
+    CARD8 save_feedback_div;
+    CARD8 save_lvds_control_2;
+    CARD8 save_outputs_enable;
+    CARD8 save_lvds_power_down;
+};
+
+static void
+ch7017_dump_regs(I2CDevPtr d);
+
+static Bool
+ch7017_read(struct ch7017_priv *priv, int addr, CARD8 *val)
+{
+    if (!xf86I2CReadByte(&priv->d, addr, val)) {
+	xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_ERROR,
+		   "Unable to read from %s Slave %d.\n",
+		   priv->d.pI2CBus->BusName, priv->d.SlaveAddr);
+	return FALSE;
+    }
+    return TRUE;
+}
+
+static Bool
+ch7017_write(struct ch7017_priv *priv, int addr, CARD8 val)
+{
+    if (!xf86I2CWriteByte(&priv->d, addr, val)) {
+	xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_ERROR,
+		   "Unable to write to %s Slave %d.\n",
+		   priv->d.pI2CBus->BusName, priv->d.SlaveAddr);
+	return FALSE;
+    }
+    return TRUE;
+}
+
+/** Probes for a CH7017 on the given bus and slave address. */
+static void *
+ch7017_init(I2CBusPtr b, I2CSlaveAddr addr)
+{
+    struct ch7017_priv *priv;
+    CARD8 val;
+
+    xf86DrvMsg(b->scrnIndex, X_INFO, "detecting ch7017\n");
+
+    priv = xcalloc(1, sizeof(struct ch7017_priv));
+    if (priv == NULL)
+	return NULL;
+
+    priv->d.DevName = "CH7017/7018 TMDS Controller";
+    priv->d.SlaveAddr = addr;
+    priv->d.pI2CBus = b;
+    priv->d.StartTimeout = b->StartTimeout;
+    priv->d.BitTimeout = b->BitTimeout;
+    priv->d.AcknTimeout = b->AcknTimeout;
+    priv->d.ByteTimeout = b->ByteTimeout;
+    priv->d.DriverPrivate.ptr = priv;
+
+    if (!xf86I2CReadByte(&priv->d, CH7017_DEVICE_ID, &val))
+	goto fail;
+
+    if (val != CH7017_DEVICE_ID_VALUE && val != CH7018_DEVICE_ID_VALUE) {
+	xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_ERROR,
+		   "ch7017 not detected, got %d: from %s Slave %d.\n",
+		   val, priv->d.pI2CBus->BusName, priv->d.SlaveAddr);
+	goto fail;
+    }
+
+    if (!xf86I2CDevInit(&(priv->d)))
+	goto fail;
+
+    return priv;
+
+fail:
+    xfree(priv);
+    return NULL;
+}
+
+static xf86OutputStatus
+ch7017_detect(I2CDevPtr d)
+{
+    return XF86OutputStatusUnknown;
+}
+
+static ModeStatus
+ch7017_mode_valid(I2CDevPtr d, DisplayModePtr mode)
+{
+    if (mode->Clock > 160000)
+	return MODE_CLOCK_HIGH;
+
+    return MODE_OK;
+}
+
+static void
+ch7017_mode_set(I2CDevPtr d, DisplayModePtr mode)
+{
+    struct ch7017_priv *priv = d->DriverPrivate.ptr;
+    CARD8 lvds_pll_feedback_div, lvds_pll_vco_control;
+    CARD8 outputs_enable, lvds_control_2, lvds_power_down;
+    CARD8 horizontal_active_pixel_input;
+    CARD8 horizontal_active_pixel_output, vertical_active_line_output;
+    CARD8 active_input_line_output;
+
+    xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO,
+	       "Registers before mode setting\n");
+    ch7017_dump_regs(d);
+
+    /* LVDS PLL settings from page 75 of 7017-7017ds.pdf*/
+    if (mode->Clock < 50000) {
+	lvds_pll_feedback_div = 45;
+	lvds_pll_vco_control = (2 << 4) | (3 << 0);
+	outputs_enable = (0 << 0); /* XXX: enables */
+	lvds_control_2 = (1 << CH7017_LOOP_FILTER_SHIFT) |
+	    (0 << CH7017_PHASE_DETECTOR_SHIFT);
+    } else if (mode->Clock < 100000) {
+	lvds_pll_feedback_div = 45;
+	lvds_pll_vco_control = (2 << 4) | (3 << 0);
+	outputs_enable = (0 << 0); /* XXX: enables */
+	lvds_control_2 = (1 << CH7017_LOOP_FILTER_SHIFT) |
+	    (0 << CH7017_PHASE_DETECTOR_SHIFT);
+    } else if (mode->Clock < 160000) {
+	lvds_pll_feedback_div = 35;
+	outputs_enable = (3 << 0); /* XXX: enables */
+	lvds_control_2 = (3 << CH7017_LOOP_FILTER_SHIFT) |
+	    (0 << CH7017_PHASE_DETECTOR_SHIFT);
+	if (1) { /* XXX: dual panel */
+	    lvds_pll_vco_control = (2 << 4) | (13 << 0);
+	} else {
+	    lvds_pll_vco_control = (1 << 4) | (13 << 0);
+	}
+    } else {
+	FatalError("Invalid mode clock (%.1fMHz)\n",
+		   (float)mode->Clock / 1000.0);
+    }
+
+    horizontal_active_pixel_input = mode->HDisplay & 0x00ff;
+
+    vertical_active_line_output = mode->VDisplay & 0x00ff;
+    horizontal_active_pixel_output = mode->HDisplay & 0x00ff;
+
+    active_input_line_output = ((mode->HDisplay & 0x0700) >> 9) |
+	((mode->VDisplay & 0x0700) >> 8);
+
+    lvds_power_down = (mode->HDisplay & 0x0f00) >> 8;
+
+    ch7017Power(d, FALSE);
+    ch7017_write(priv, CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT,
+		    horizontal_active_pixel_input);
+    ch7017_write(priv, CH7017_HORIZONTAL_ACTIVE_PIXEL_OUTPUT,
+		    horizontal_active_pixel_output);
+    ch7017_write(priv, CH7017_VERTICAL_ACTIVE_LINE_OUTPUT,
+		    vertical_active_line_output);
+    ch7017_write(priv, CH7017_LVDS_PLL_VCO_CONTROL, lvds_pll_vco_control);
+    ch7017_write(priv, CH7017_LVDS_PLL_FEEDBACK_DIV, lvds_pll_feedback_div);
+    ch7017_write(priv, CH7017_LVDS_CONTROL_2, lvds_control_2);
+    ch7017_write(priv, CH7017_OUTPUTS_ENABLE, outputs_enable);
+
+    /* Turn the LVDS back on with new settings. */
+    ch7017_write(priv, CH7017_LVDS_POWER_DOWN, lvds_power_down);
+
+    xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO,
+	       "Registers after mode setting\n");
+    ch7017PrintRegs(d);
+}
+
+/* set the CH7017 power state */
+static void
+ch7017_dpms(I2CDevPtr d, int mode)
+{
+    struct ch7017_priv *priv = d->DriverPrivate.ptr;
+    CARD8 val;
+
+    ch7017_read(priv, CH7017_LVDS_POWER_DOWN, &val);
+
+    if (mode == DPMSModeOn) {
+	/* Turn on the LVDS */
+	ch7017_write(priv, CH7017_LVDS_POWER_DOWN,
+			val & ~CH7017_LVDS_POWER_DOWN_EN);
+    } else {
+	/* Turn on the LVDS */
+	ch7017_write(priv, CH7017_LVDS_POWER_DOWN,
+			val | CH7017_LVDS_POWER_DOWN_EN);
+    }
+
+    /* XXX: Should actually wait for update power status somehow */
+    usleep(50000);
+}
+
+static void
+ch7017_dump_regs(I2CDevPtr d)
+{
+    struct ch7017_priv *priv = d->DriverPrivate.ptr;
+    CARD8 val;
+
+#define DUMP(reg)					\
+do {							\
+	ch7017_read(priv, reg, &val);			\
+	xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO,	\
+		   #reg ": %02x\n", val);		\
+} while (0)
+
+    DUMP(CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT);
+    DUMP(CH7017_HORIZONTAL_ACTIVE_PIXEL_OUTPUT);
+    DUMP(CH7017_VERTICAL_ACTIVE_LINE_OUTPUT);
+    DUMP(CH7017_LVDS_PLL_VCO_CONTROL);
+    DUMP(CH7017_LVDS_PLL_FEEDBACK_DIV);
+    DUMP(CH7017_LVDS_CONTROL_2);
+    DUMP(CH7017_OUTPUTS_ENABLE);
+    DUMP(CH7017_LVDS_POWER_DOWN);
+}
+
+static void
+ch7017_save(I2CDevPtr d)
+{
+    struct ch7017_priv *priv = d->DriverPrivate.ptr;
+
+    ch7017_read(priv, CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT, &priv->save_hapi);
+    ch7017_read(priv, CH7017_VERTICAL_ACTIVE_LINE_OUTPUT, &priv->save_valo);
+    ch7017_read(priv, CH7017_LVDS_PLL_VCO_CONTROL, &priv->save_lvds_pll_vco);
+    ch7017_read(priv, CH7017_LVDS_PLL_FEEDBACK_DIV, &priv->save_feedback_div);
+    ch7017_read(priv, CH7017_LVDS_CONTROL_2, &priv->save_lvds_control_2);
+    ch7017_read(priv, CH7017_OUTPUTS_ENABLE, &priv->save_outputs_enable);
+    ch7017_read(priv, CH7017_LVDS_POWER_DOWN, &priv->save_lvds_power_down);
+}
+
+static void
+ch7017_restore(I2CDevPtr d)
+{
+    struct ch7017_priv *priv = d->DriverPrivate.ptr;
+
+    /* Power down before changing mode */
+    ch7017Power(d, FALSE);
+
+    ch7017_write(priv, CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT, priv->save_hapi);
+    ch7017_write(priv, CH7017_VERTICAL_ACTIVE_LINE_OUTPUT, priv->save_valo);
+    ch7017_write(priv, CH7017_LVDS_PLL_VCO_CONTROL, priv->save_lvds_pll_vco);
+    ch7017_write(priv, CH7017_LVDS_PLL_FEEDBACK_DIV, priv->save_feedback_div);
+    ch7017_write(priv, CH7017_LVDS_CONTROL_2, priv->save_lvds_control_2);
+    ch7017_write(priv, CH7017_OUTPUTS_ENABLE, priv->save_outputs_enable);
+    ch7017_write(priv, CH7017_LVDS_POWER_DOWN, priv->save_lvds_power_down);
+}
+
+I830I2CVidOutputRec ch7017_methods = {
+    .init = ch7017_init,
+    .detect = ch7017_detect,
+    .mode_valid = ch7017_mode_valid,
+    .mode_set = ch7017_mode_set,
+    .dpms = ch7017_dpms,
+    .dump_regs = ch7017_dump_regs,
+    .save = ch7017_save,
+    .restore = ch7017_restore,
+};
diff --git a/src/ch7017/ch7017_module.c b/src/ch7017/ch7017_module.c
new file mode 100644
index 0000000..135f3c6
--- /dev/null
+++ b/src/ch7017/ch7017_module.c
@@ -0,0 +1,36 @@
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86Module.h"
+
+static MODULESETUPPROTO(ch7017Setup);
+
+static XF86ModuleVersionInfo ch7017VersRec = 
+  {
+    "ch7017",
+    MODULEVENDORSTRING,
+    MODINFOSTRING1,
+    MODINFOSTRING2,
+    XORG_VERSION_CURRENT,
+    1, 0, 0,
+    ABI_CLASS_VIDEODRV,
+    ABI_VIDEODRV_VERSION,
+    MOD_CLASS_NONE,
+    { 0,0,0,0 }
+  };
+
+_X_EXPORT XF86ModuleData ch7017ModuleData = {
+  &ch7017VersRec,
+  ch7017Setup,
+  NULL
+};
+
+static pointer
+ch7017Setup(pointer module, pointer opts, int *errmaj, int *errmin) {
+  return (pointer)1;
+}
diff --git a/src/ch7017/ch7017_reg.h b/src/ch7017/ch7017_reg.h
new file mode 100644
index 0000000..89f81cc
--- /dev/null
+++ b/src/ch7017/ch7017_reg.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
+#ifndef CH7017_REG_H
+#define CH7017_REG_H
+
+#define CH7017_TV_DISPLAY_MODE		0x00
+#define CH7017_FLICKER_FILTER		0x01
+#define CH7017_VIDEO_BANDWIDTH		0x02
+#define CH7017_TEXT_ENHANCEMENT		0x03
+#define CH7017_START_ACTIVE_VIDEO	0x04
+#define CH7017_HORIZONTAL_POSITION	0x05
+#define CH7017_VERTICAL_POSITION	0x06
+#define CH7017_BLACK_LEVEL		0x07
+#define CH7017_CONTRAST_ENHANCEMENT	0x08
+#define CH7017_TV_PLL			0x09
+#define CH7017_TV_PLL_M			0x0a
+#define CH7017_TV_PLL_N			0x0b
+#define CH7017_SUB_CARRIER_0		0x0c
+#define CH7017_CIV_CONTROL		0x10
+#define CH7017_CIV_0			0x11
+#define CH7017_CHROMA_BOOST		0x14
+#define CH7017_CLOCK_MODE		0x1c
+#define CH7017_INPUT_CLOCK		0x1d
+#define CH7017_GPIO_CONTROL		0x1e
+#define CH7017_INPUT_DATA_FORMAT	0x1f
+#define CH7017_CONNECTION_DETECT	0x20
+#define CH7017_DAC_CONTROL		0x21
+#define CH7017_BUFFERED_CLOCK_OUTPUT	0x22
+#define CH7017_DEFEAT_VSYNC		0x47
+#define CH7017_TEST_PATTERN		0x48
+
+#define CH7017_POWER_MANAGEMENT		0x49
+/** Enables the TV output path. */
+#define CH7017_TV_EN			(1 << 0)
+#define CH7017_DAC0_POWER_DOWN		(1 << 1)
+#define CH7017_DAC1_POWER_DOWN		(1 << 2)
+#define CH7017_DAC2_POWER_DOWN		(1 << 3)
+#define CH7017_DAC3_POWER_DOWN		(1 << 4)
+/** Powers down the TV out block, and DAC0-3 */
+#define CH7017_TV_POWER_DOWN_EN		(1 << 5)
+
+#define CH7017_VERSION_ID		0x4a
+
+#define CH7017_DEVICE_ID		0x4b
+#define CH7017_DEVICE_ID_VALUE		0x1b
+#define CH7018_DEVICE_ID_VALUE		0x1a
+
+#define CH7017_XCLK_D2_ADJUST		0x53
+#define CH7017_UP_SCALER_COEFF_0	0x55
+#define CH7017_UP_SCALER_COEFF_1	0x56
+#define CH7017_UP_SCALER_COEFF_2	0x57
+#define CH7017_UP_SCALER_COEFF_3	0x58
+#define CH7017_UP_SCALER_COEFF_4	0x59
+#define CH7017_UP_SCALER_VERTICAL_INC_0	0x5a
+#define CH7017_UP_SCALER_VERTICAL_INC_1	0x5b
+#define CH7017_GPIO_INVERT		0x5c
+#define CH7017_UP_SCALER_HORIZONTAL_INC_0	0x5d
+#define CH7017_UP_SCALER_HORIZONTAL_INC_1	0x5e
+
+#define CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT	0x5f
+/**< Low bits of horizontal active pixel input */
+
+#define CH7017_ACTIVE_INPUT_LINE_OUTPUT	0x60
+/** High bits of horizontal active pixel input */
+#define CH7017_LVDS_HAP_INPUT_MASK	(0x7 << 0)
+/** High bits of vertical active line output */
+#define CH7017_LVDS_VAL_HIGH_MASK	(0x7 << 3)
+
+#define CH7017_VERTICAL_ACTIVE_LINE_OUTPUT	0x61
+/**< Low bits of vertical active line output */
+
+#define CH7017_HORIZONTAL_ACTIVE_PIXEL_OUTPUT	0x62
+/**< Low bits of horizontal active pixel output */
+
+#define CH7017_LVDS_POWER_DOWN		0x63
+/** High bits of horizontal active pixel output */
+#define CH7017_LVDS_HAP_HIGH_MASK	(0xf << 0)
+/** Enables the LVDS power down state transition */
+#define CH7017_LVDS_POWER_DOWN_EN	(1 << 6)
+/** Enables the LVDS upscaler */
+#define CH7017_LVDS_UPSCALER_EN		(1 << 7)
+
+#define CH7017_LVDS_ENCODING		0x64
+#define CH7017_LVDS_DITHER_2D		(1 << 2)
+#define CH7017_LVDS_DITHER_DIS		(1 << 3)
+#define CH7017_LVDS_DUAL_CHANNEL_EN	(1 << 4)
+#define CH7017_LVDS_24_BIT		(1 << 5)
+
+#define CH7017_LVDS_ENCODING_2		0x65
+
+#define CH7017_LVDS_PLL_CONTROL		0x66
+/** Enables the LVDS panel output path */
+#define CH7017_LVDS_PANEN		(1 << 0)
+/** Enables the LVDS panel backlight */
+#define CH7017_LVDS_BKLEN		(1 << 3)
+
+#define CH7017_POWER_SEQUENCING_T1	0x67
+#define CH7017_POWER_SEQUENCING_T2	0x68
+#define CH7017_POWER_SEQUENCING_T3	0x69
+#define CH7017_POWER_SEQUENCING_T4	0x6a
+#define CH7017_POWER_SEQUENCING_T5	0x6b
+#define CH7017_GPIO_DRIVER_TYPE		0x6c
+#define CH7017_GPIO_DATA		0x6d
+#define CH7017_GPIO_DIRECTION_CONTROL	0x6e
+#define CH7017_LVDS_PLL_FEEDBACK_DIV	0x71
+#define CH7017_LVDS_PLL_VCO_CONTROL	0x72
+
+#define CH7017_OUTPUTS_ENABLE		0x73
+# define CH7017_LVDS_CHANNEL_A		(1 << 3)
+# define CH7017_LVDS_CHANNEL_B		(1 << 4)
+# define CH7017_TV_DAC_A		(1 << 5)
+# define CH7017_TV_DAC_B		(1 << 6)
+# define CH7017_DDC_SELECT_DC2		(1 << 7)
+
+#define CH7017_LVDS_OUTPUT_AMPLITUDE	0x74
+#define CH7017_LVDS_PLL_EMI_REDUCTION	0x75
+#define CH7017_LVDS_POWER_DOWN_FLICKER	0x76
+
+#define CH7017_LVDS_CONTROL_2		0x78
+# define CH7017_LOOP_FILTER_SHIFT	5
+# define CH7017_PHASE_DETECTOR_SHIFT	0
+
+#define CH7017_BANG_LIMIT_CONTROL	0x7f
+
+#endif /* CH7017_REG_H */
diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index 6d4039a..d101054 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -51,6 +51,12 @@ static const char *ivch_symbols[] = {
     NULL
 };
 #endif
+#if 0
+static const char *ch7017_symbols[] = {
+    "ch7017_methods",
+    NULL
+};
+#endif
 
 /* driver list */
 struct _I830DVODriver i830_dvo_drivers[] =
@@ -63,6 +69,10 @@ struct _I830DVODriver i830_dvo_drivers[]
     {I830_DVO_CHIP_LVDS, "ivch", "ivch_methods",
      (0x2 << 1), ivch_symbols, NULL, NULL, NULL},
     */
+    /*
+    { I830_DVO_CHIP_LVDS, "ch7017", "ch7017_methods",
+      (CH7017_ADDR_1 << 1), ch7017_symbols, NULL, NULL, NULL }
+    */
 };
 
 #define I830_NUM_DVO_DRIVERS (sizeof(i830_dvo_drivers)/sizeof(struct _I830DVODriver))
diff-tree 778db49616b233f5a2f4f007ceb62a1a878a6e25 (from 5806f670eb3a5171ffb0b75701640d5311b34c80)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Dec 28 11:36:15 2006 -0800

    Add WIP IVCH (i82807aa) driver.
    
    It is not currently hooked up as it hasn't been tested.  The hardware that this
    was written for decided to stop working.

diff --git a/configure.ac b/configure.ac
index b1dd287..30a69bc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -149,6 +149,7 @@ AC_OUTPUT([
 	src/xvmc/Makefile
 	src/bios_reader/Makefile
 	src/ch7xxx/Makefile
+	src/ivch/Makefile
 	src/sil164/Makefile
 	man/Makefile
 ])
diff --git a/src/Makefile.am b/src/Makefile.am
index d843ecf..77a1917 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -18,7 +18,8 @@
 #  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 #  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
-SUBDIRS = xvmc bios_reader ch7xxx sil164
+SUBDIRS = xvmc bios_reader ch7xxx ivch sil164
+
 # this is obnoxious:
 # -module lets us name the module exactly how we want
 # -avoid-version prevents gratuitous .0.0.0 version numbers on the end
diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index 6d11972..6d4039a 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -45,13 +45,24 @@ static const char *CH7xxxSymbols[] = {
     NULL
 };
 
+#if 0
+static const char *ivch_symbols[] = {
+    "ivch_methods",
+    NULL
+};
+#endif
+
 /* driver list */
 struct _I830DVODriver i830_dvo_drivers[] =
 {
     {I830_DVO_CHIP_TMDS, "sil164", "SIL164VidOutput",
      (SIL164_ADDR_1<<1), SIL164Symbols, NULL , NULL, NULL},
     {I830_DVO_CHIP_TMDS | I830_DVO_CHIP_TVOUT, "ch7xxx", "CH7xxxVidOutput",
-     (CH7xxx_ADDR_1<<1), CH7xxxSymbols, NULL , NULL, NULL}
+     (CH7xxx_ADDR_1<<1), CH7xxxSymbols, NULL , NULL, NULL},
+    /*
+    {I830_DVO_CHIP_LVDS, "ivch", "ivch_methods",
+     (0x2 << 1), ivch_symbols, NULL, NULL, NULL},
+    */
 };
 
 #define I830_NUM_DVO_DRIVERS (sizeof(i830_dvo_drivers)/sizeof(struct _I830DVODriver))
diff --git a/src/ivch/Makefile.am b/src/ivch/Makefile.am
new file mode 100644
index 0000000..fac074d
--- /dev/null
+++ b/src/ivch/Makefile.am
@@ -0,0 +1,15 @@
+# this is obnoxious:
+# -module lets us name the module exactly how we want
+# -avoid-version prevents gratuitous .0.0.0 version numbers on the end
+# _ladir passes a dummy rpath to libtool so the thing will actually link
+# TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
+AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@
+
+ivch_la_LTLIBRARIES = ivch.la
+ivch_la_LDFLAGS = -module -avoid-version
+ivch_ladir = @moduledir@/drivers
+
+ivch_la_SOURCES = \
+	ivch.c \
+	ivch_module.c \
+	ivch_reg.h
diff --git a/src/ivch/ivch.c b/src/ivch/ivch.c
new file mode 100644
index 0000000..6c5db6c
--- /dev/null
+++ b/src/ivch/ivch.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86Resources.h"
+#include "compiler.h"
+#include "miscstruct.h"
+#include "xf86i2c.h"
+#include "../i830_xf86Crtc.h"
+#define DPMS_SERVER
+#include <X11/extensions/dpms.h>
+
+#include "../i2c_vid.h"
+#include "ivch_reg.h"
+
+struct ivch_priv {
+    I2CDevRec d;
+
+    CARD16 save_VR01;
+    CARD16 save_VR40;
+};
+
+static void
+ivch_dump_regs(I2CDevPtr d);
+
+/**
+ * Reads a register on the ivch.
+ *
+ * Each of the 256 registers are 16 bits long.
+ */
+static Bool
+ivch_read(struct ivch_priv *priv, int addr, CARD16 *data)
+{
+    if (!xf86I2CReadWord(&priv->d, addr, data)) {
+	xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_ERROR,
+		   "Unable to read register 0x%02x from %s:%d.\n",
+		   addr, priv->d.pI2CBus->BusName, priv->d.SlaveAddr);
+	return FALSE;
+    }
+    return TRUE;
+}
+
+/** Writes a 16-bit register on the ivch */
+static Bool
+ivch_write(struct ivch_priv *priv, int addr, CARD16 data)
+{
+    if (!xf86I2CWriteWord(&priv->d, addr, data)) {
+	xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_ERROR,
+		   "Unable to write register 0x%02x to %s:%d.\n",
+		   addr, priv->d.pI2CBus->BusName, priv->d.SlaveAddr);
+	return FALSE;
+    }
+    return TRUE;
+}
+
+/** Probes the given bus and slave address for an ivch */
+static void *
+ivch_init(I2CBusPtr b, I2CSlaveAddr addr)
+{
+    struct ivch_priv *priv;
+    CARD16 temp;
+
+    xf86DrvMsg(b->scrnIndex, X_INFO, "detecting ivch\n");
+
+    priv = xcalloc(1, sizeof(struct ivch_priv));
+    if (priv = NULL)
+	return NULL;
+
+    priv->d.DevName = "i82807aa \"ivch\" LVDS/CMOS panel controller";
+    priv->d.SlaveAddr = addr;
+    priv->d.pI2CBus = b;
+    priv->d.StartTimeout = b->StartTimeout;
+    priv->d.BitTimeout = b->BitTimeout;
+    priv->d.AcknTimeout = b->AcknTimeout;
+    priv->d.ByteTimeout = b->ByteTimeout;
+    priv->d.DriverPrivate.ptr = priv;
+
+    if (!xf86I2CReadWord(&priv->d, VR00, &temp))
+	goto out;
+
+    /* Since the identification bits are probably zeroes, which doesn't seem
+     * very unique, check that the value in the base address field matches
+     * the address it's responding on.
+     */
+    if ((temp & VR00_BASE_ADDRESS_MASK) != priv->d.SlaveAddr) {
+	xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_ERROR,
+		   "ivch detect failed due to address mismatch "
+		   "(%d vs %d)\n",
+		   (temp & VR00_BASE_ADDRESS_MASK), priv->d.SlaveAddr);
+    }
+
+    if (!xf86I2CDevInit(&priv->d)) {
+	goto out;
+    }
+
+    return priv;
+
+out:
+    xfree(priv);
+    return NULL;
+}
+
+static xf86OutputStatus
+ivch_detect(I2CDevPtr d)
+{
+    return XF86OutputStatusUnknown;
+}
+
+static ModeStatus
+ivch_mode_valid(I2CDevPtr d, DisplayModePtr mode)
+{
+    if (mode->Clock > 112000)
+	return MODE_CLOCK_HIGH;
+
+    return MODE_OK;
+}
+
+/** Sets the power state of the panel connected to the ivch */
+static void
+ivch_dpms(I2CDevPtr d, int mode)
+{
+    struct ivch_priv *priv = d->DriverPrivate.ptr;
+    int i;
+    CARD16 temp;
+
+    /* Set the new power state of the panel. */
+    if (!ivch_read(priv, VR01, &temp))
+	return;
+
+    if (mode == DPMSModeOn)
+	temp |= VR01_LCD_ENABLE | VR01_DVO_ENABLE;
+    else
+	temp &= ~(VR01_LCD_ENABLE | VR01_DVO_ENABLE);
+
+    ivch_write(priv, VR01, temp);
+
+    /* Wait for the panel to make its state transition */
+    for (i = 0; i < 1000; i++) {
+	if (!ivch_read(priv, VR30, &temp))
+	    break;
+
+	if (((temp & VR30_PANEL_ON) != 0) == (mode == DPMSModeOn))
+	    break;
+    }
+}
+
+static void
+ivch_mode_set(I2CDevPtr d, DisplayModePtr mode)
+{
+    struct ivch_priv *priv = d->DriverPrivate.ptr;
+
+    /* Disable panel fitting for now, until we can test. */
+    ivch_write(priv, VR40, 0);
+
+    ivch_dpms(d, DPMSModeOn);
+
+    ivch_dump_regs(d);
+}
+
+static void
+ivch_dump_regs(I2CDevPtr d)
+{
+    struct ivch_priv *priv = d->DriverPrivate.ptr;
+    CARD16 val;
+
+    ivch_read(priv, VR00, &val);
+    xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR00: 0x%04x\n", val);
+    ivch_read(priv, VR01, &val);
+    xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR01: 0x%04x\n", val);
+    ivch_read(priv, VR30, &val);
+    xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR30: 0x%04x\n", val);
+    ivch_read(priv, VR40, &val);
+    xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR40: 0x%04x\n", val);
+
+}
+
+static void
+ivch_save(I2CDevPtr d)
+{
+    struct ivch_priv *priv = d->DriverPrivate.ptr;
+
+    ivch_read(priv, VR01, &priv->save_VR01);
+    ivch_read(priv, VR40, &priv->save_VR40);
+}
+
+static void
+ivch_restore(I2CDevPtr d)
+{
+    struct ivch_priv *priv = d->DriverPrivate.ptr;
+
+    ivch_write(priv, VR01, priv->save_VR01);
+    ivch_write(priv, VR40, priv->save_VR40);
+}
+
+
+I830I2CVidOutputRec ivch_methods = {
+    .init = ivch_init,
+    .detect = ivch_detect,
+    .mode_valid = ivch_mode_valid,
+    .mode_set = ivch_mode_set,
+    .dpms = ivch_dpms,
+    .dump_regs = ivch_dump_regs,
+    .save = ivch_save,
+    .restore = ivch_restore,
+};
diff --git a/src/ivch/ivch_module.c b/src/ivch/ivch_module.c
new file mode 100644
index 0000000..1ed483b
--- /dev/null
+++ b/src/ivch/ivch_module.c
@@ -0,0 +1,64 @@
+/* -*- c-basic-offset: 4 -*- */
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86Module.h"
+
+static MODULESETUPPROTO(ivch_setup);
+
+static XF86ModuleVersionInfo ivch_version = {
+    "ivch",
+    MODULEVENDORSTRING,
+    MODINFOSTRING1,
+    MODINFOSTRING2,
+    XORG_VERSION_CURRENT,
+    1, 0, 0,
+    ABI_CLASS_VIDEODRV,
+    ABI_VIDEODRV_VERSION,
+    MOD_CLASS_NONE,
+    { 0,0,0,0 }
+};
+
+_X_EXPORT XF86ModuleData ivchModuleData = {
+    &ivch_version,
+    ivch_setup,
+    NULL
+};
+
+static pointer
+ivch_setup(pointer module, pointer opts, int *errmaj, int *errmin)
+{
+    return (pointer)1;
+}
diff --git a/src/ivch/ivch_reg.h b/src/ivch/ivch_reg.h
new file mode 100644
index 0000000..112c97d
--- /dev/null
+++ b/src/ivch/ivch_reg.h
@@ -0,0 +1,97 @@
+/* -*- c-basic-offset: 4 -*- */
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
+/** @file
+ * This file contains the register definitions for the i82807aa.
+ *
+ * Documentation on this chipset can be found in datasheet #29069001 at
+ * intel.com.
+ */
+#ifndef I82807AA_REG_H
+#define I82807AA_REG_H
+
+/** @defgroup VR00
+ * @{
+ */
+#define VR00		0x00
+# define VR00_BASE_ADDRESS_MASK		0x007f
+/** @} */
+
+/** @defgroup VR01
+ * @{
+ */
+#define VR01		0x01
+# define VR01_PANEL_FIT_ENABLE		(1 << 3)
+/**
+ * Enables the LCD display.
+ *
+ * This must not be set while VR01_DVO_BYPASS_ENABLE is set.
+ */
+# define VR01_LCD_ENABLE		(1 << 2)
+/** Enables the DVO repeater. */
+# define VR01_DVO_BYPASS_ENABLE		(1 << 1)
+/** Enables the DVO clock */
+# define VR01_DVO_ENABLE		(1 << 0)
+/** @} */
+
+/** @defgroup VR10
+ * @{
+ */
+#define VR10		0x10
+/** Enables LVDS output instead of CMOS */
+# define VR10_LVDS_ENABLE		(1 << 4)
+/** Enables 18-bit LVDS output. */
+# define VR10_INTERFACE_1X18		(0 << 2)
+/** Enables 24-bit LVDS or CMOS output */
+# define VR10_INTERFACE_1X24		(1 << 2)
+/** Enables 2x18-bit LVDS or CMOS output. */
+# define VR10_INTERFACE_2X18		(2 << 2)
+/** Enables 2x24-bit LVDS output */
+# define VR10_INTERFACE_2X24		(3 << 2)
+/** @} */
+
+/** @defgroup VR30
+ * @{
+ */
+#define VR30		0x30
+/** Read only bit indicating that the panel is not in a safe poweroff state. */
+# define VR30_PANEL_ON			(1 << 15)
+/** @} */
+
+/** @defgroup VR40
+ * @{
+ */
+#define VR40		0x40
+# define VR40_STALL_ENABLE		(1 << 13)
+# define VR40_VERTICAL_INTERP_ENABLE	(1 << 11)
+# define VR40_HORIZONTAL_INTERP_ENABLE	(1 << 10)
+# define VR40_RATIO_ENABLE		(1 << 9)
+# define VR40_PANEL_FIT_ENABLE		(1 << 8)
+/** @} */
+
+#endif /* I82807AA_REG_H */
diff-tree 5806f670eb3a5171ffb0b75701640d5311b34c80 (from b928cef9cd5b3f88dc0880f406300d246a59e0fe)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Dec 21 16:22:14 2006 -0800

    Reformat the DVO drivers table to be a bit more normal style.

diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index 283e975..6d11972 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -48,10 +48,10 @@ static const char *CH7xxxSymbols[] = {
 /* driver list */
 struct _I830DVODriver i830_dvo_drivers[] =
 {
-	{ I830_DVO_CHIP_TMDS, "sil164", "SIL164VidOutput",
-		(SIL164_ADDR_1<<1), SIL164Symbols, NULL , NULL, NULL},
-	{ I830_DVO_CHIP_TMDS | I830_DVO_CHIP_TVOUT, "ch7xxx", "CH7xxxVidOutput",
-		(CH7xxx_ADDR_1<<1), CH7xxxSymbols, NULL , NULL, NULL}
+    {I830_DVO_CHIP_TMDS, "sil164", "SIL164VidOutput",
+     (SIL164_ADDR_1<<1), SIL164Symbols, NULL , NULL, NULL},
+    {I830_DVO_CHIP_TMDS | I830_DVO_CHIP_TVOUT, "ch7xxx", "CH7xxxVidOutput",
+     (CH7xxx_ADDR_1<<1), CH7xxxSymbols, NULL , NULL, NULL}
 };
 
 #define I830_NUM_DVO_DRIVERS (sizeof(i830_dvo_drivers)/sizeof(struct _I830DVODriver))
diff-tree b928cef9cd5b3f88dc0880f406300d246a59e0fe (from c87462ded20904dbc6c6cbdb9547523b75fe5471)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Dec 21 16:21:28 2006 -0800

    Move dvo driver detection into i830_dvo_init(), and use GPIOB for LVDS drivers.
    
    The documentation states that GPIOB is (generally) used for devices on DVOA
    on the motherboard, which appears to be the case on the laptop we have with
    LVDS on the motherboard.
    
    This patch is probably not entirely accurate, as there was apparently an LVDS
    DVO card sold that could be put in desktop machines, which would likely be on
    GPIOE like other ADD cards.  Given that we couldn't find one of these cards for
    purchase, I'm not worrying about it.

diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index 97453de..283e975 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -183,37 +183,6 @@ i830_dvo_detect(xf86OutputPtr output)
     return intel_output->i2c_drv->vid_rec->detect(dev_priv);
 }
 
-static Bool
-I830I2CDetectDVOControllers(ScrnInfoPtr pScrn, I2CBusPtr pI2CBus,
-			    struct _I830DVODriver **retdrv)
-{
-    int i;
-    void *ret_ptr;
-    struct _I830DVODriver *drv;
-
-    for (i = 0; i < I830_NUM_DVO_DRIVERS; i++) {
-	drv = &i830_dvo_drivers[i];
-	drv->modhandle = xf86LoadSubModule(pScrn, drv->modulename);
-	if (drv->modhandle == NULL)
-	    continue;
-
-	xf86LoaderReqSymLists(drv->symbols, NULL);
-
-	ret_ptr = NULL;
-	drv->vid_rec = LoaderSymbol(drv->fntablename);
-	if (drv->vid_rec != NULL)
-	    ret_ptr = drv->vid_rec->init(pI2CBus, drv->address);
-
-	if (ret_ptr != NULL) {
-	    drv->dev_priv = ret_ptr;
-	    *retdrv = drv;
-	    return TRUE;
-	}
-	xf86UnloadSubModule(drv->modhandle);
-    }
-    return FALSE;
-}
-
 static void
 i830_dvo_destroy (xf86OutputPtr output)
 {
@@ -245,9 +214,14 @@ static const xf86OutputFuncsRec i830_dvo
 void
 i830_dvo_init(ScrnInfoPtr pScrn)
 {
-    xf86OutputPtr	    output;
-    I830OutputPrivatePtr    intel_output;
-    int			    ret;
+    xf86OutputPtr output;
+    I830OutputPrivatePtr intel_output;
+    int ret;
+    int i;
+    void *ret_ptr;
+    struct _I830DVODriver *drv;
+    int gpio_inited = 0;
+    I2CBusPtr pI2CBus = NULL;
 
     output = xf86OutputCreate (pScrn, &i830_dvo_output_funcs,
 				   "TMDS");
@@ -263,14 +237,7 @@ i830_dvo_init(ScrnInfoPtr pScrn)
     output->driver_private = intel_output;
     output->subpixel_order = SubPixelHorizontalRGB;
     
-    /* Set up the I2C and DDC buses */
-    ret = I830I2CInit(pScrn, &intel_output->pI2CBus, GPIOE, "DVOI2C_E");
-    if (!ret)
-    {
-	xf86OutputDestroy (output);
-	return;
-    }
-
+    /* Set up the DDC bus */
     ret = I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOD, "DVODDC_D");
     if (!ret)
     {
@@ -279,17 +246,51 @@ i830_dvo_init(ScrnInfoPtr pScrn)
     }
 
     /* Now, try to find a controller */
-    ret = I830I2CDetectDVOControllers(pScrn, intel_output->pI2CBus,
-				      &intel_output->i2c_drv);
-    if (ret)
-    {
-	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08lX\n",
-		   intel_output->i2c_drv->modulename,
-		   intel_output->pI2CBus->DriverPrivate.uval);
-    }
-    else
-    {
-	xf86OutputDestroy (output);
-	return;
+    for (i = 0; i < I830_NUM_DVO_DRIVERS; i++) {
+	int gpio;
+
+	drv = &i830_dvo_drivers[i];
+	drv->modhandle = xf86LoadSubModule(pScrn, drv->modulename);
+	if (drv->modhandle == NULL)
+	    continue;
+
+	xf86LoaderReqSymLists(drv->symbols, NULL);
+
+	ret_ptr = NULL;
+	drv->vid_rec = LoaderSymbol(drv->fntablename);
+
+	if (drv->type & I830_DVO_CHIP_LVDS)
+	    gpio = GPIOB;
+	else
+	    gpio = GPIOE;
+
+	/* Set up the I2C bus necessary for the chip we're probing.  It appears
+	 * that everything is on GPIOE except for panels on i830 laptops, which
+	 * are on GPIOB (DVOA).
+	 */
+	if (gpio_inited != gpio) {
+	    if (pI2CBus != NULL)
+		xf86DestroyI2CBusRec(pI2CBus, TRUE, TRUE);
+	    if (!I830I2CInit(pScrn, &intel_output->pI2CBus, gpio,
+			     gpio == GPIOB ? "DVOI2C_B" : "DVOI2C_E")) {
+		continue;
+	    }
+	}
+
+	if (drv->vid_rec != NULL)
+	    ret_ptr = drv->vid_rec->init(pI2CBus, drv->address);
+
+	if (ret_ptr != NULL) {
+	    drv->dev_priv = ret_ptr;
+	    intel_output->i2c_drv = drv;
+	    intel_output->pI2CBus = pI2CBus;
+	    return;
+	}
+	xf86UnloadSubModule(drv->modhandle);
     }
+
+    /* Didn't find a chip, so tear down. */
+    if (pI2CBus != NULL)
+	xf86DestroyI2CBusRec(pI2CBus, TRUE, TRUE);
+    xf86OutputDestroy (output);
 }
diff-tree c87462ded20904dbc6c6cbdb9547523b75fe5471 (from 6dc3387219b2b31e0c7dbaa88b568fbd54d72878)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Dec 27 19:14:14 2006 -0800

    Remove the nasty #define away of ErrorF in i830_video.c.
    
    Every new person touching this file hits this trap, so it's now removed.

diff --git a/src/i830_video.c b/src/i830_video.c
index 0ffa189..76d4f9c 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -131,12 +131,11 @@ static Atom xvGamma0, xvGamma1, xvGamma2
 #define IMAGE_MAX_WIDTH_LEGACY	1024
 #define IMAGE_MAX_HEIGHT_LEGACY	1088
 
-#if !VIDEO_DEBUG
-#define ErrorF Edummy
-static void
-Edummy(const char *dummy, ...)
-{
-}
+/* overlay debugging printf function */
+#if 0
+#define OVERLAY_DEBUG ErrorF
+#else
+#define OVERLAY_DEBUG if (0) ErrorF
 #endif
 
 /*
@@ -157,7 +156,7 @@ Edummy(const char *dummy, ...)
 	 OUT_RING(MI_NOOP);						\
 	 OUT_RING(MI_NOOP);						\
 	 OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_ON);		\
-	 ErrorF("Overlay goes from off to on\n");			\
+	 OVERLAY_DEBUG("Overlay goes from off to on\n");		\
 	 *pI830->overlayOn = TRUE;					\
       } else {								\
 	 OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);	\
@@ -171,7 +170,7 @@ Edummy(const char *dummy, ...)
       OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);		\
       OUT_RING(MI_NOOP);						\
       ADVANCE_LP_RING();						\
-      ErrorF("OVERLAY_UPDATE\n");					\
+      OVERLAY_DEBUG("OVERLAY_UPDATE\n");				\
    } while(0)
 
 #define OVERLAY_OFF							\
@@ -190,13 +189,14 @@ Edummy(const char *dummy, ...)
 	 OUT_RING(MI_NOOP);						\
 	 ADVANCE_LP_RING();						\
 	 *pI830->overlayOn = FALSE;					\
-	 ErrorF("Overlay goes from on to off\n");			\
+	 OVERLAY_DEBUG("Overlay goes from on to off\n");		\
          while (spin != 0 && (INREG(OCMD_REGISTER) & OVERLAY_ENABLE)){	\
-		ErrorF("SPIN %d\n",spin);				\
+		OVERLAY_DEBUG("SPIN %d\n",spin);			\
 		spin--;							\
  	 }								\
-	 if (spin == 0) ErrorF("OVERLAY FAILED TO GO OFF\n");		\
-	 ErrorF("OVERLAY_OFF\n");					\
+	 if (spin == 0)							\
+		OVERLAY_DEBUG("OVERLAY FAILED TO GO OFF\n");		\
+	 OVERLAY_DEBUG("OVERLAY_OFF\n");				\
       }									\
    } while(0)
 
@@ -387,13 +387,13 @@ CompareOverlay(I830Ptr pI830, CARD32 * o
    for (i = 0; i < size; i += 4) {
       val = INREG(0x30100 + i);
       if (val != overlay[i / 4]) {
-	 ErrorF("0x%05x value doesn't match (0x%lx != 0x%lx)\n",
+	 OVERLAY_DEBUG("0x%05x value doesn't match (0x%lx != 0x%lx)\n",
 		0x30100 + i, val, overlay[i / 4]);
 	 bad++;
       }
    }
    if (!bad)
-      ErrorF("CompareOverlay: no differences\n");
+      OVERLAY_DEBUG("CompareOverlay: no differences\n");
 }
 #endif
 
@@ -406,8 +406,6 @@ I830InitVideo(ScreenPtr pScreen)
    XF86VideoAdaptorPtr overlayAdaptor = NULL, texturedAdaptor = NULL;
    int num_adaptors;
 
-   ErrorF("I830InitVideo\n");
-
 #if 0
    {
       I830OverlayRegRec tmp;
@@ -480,7 +478,7 @@ I830ResetVideo(ScrnInfoPtr pScrn)
    I830OverlayRegPtr overlay =
 	 (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start);
 
-   ErrorF("I830ResetVideo: base: %p, offset: 0x%lx, obase: %p\n",
+   OVERLAY_DEBUG("I830ResetVideo: base: %p, offset: 0x%lx, obase: %p\n",
 	   pI830->FbBase, pI830->OverlayMem->Start, overlay);
    /*
     * Default to maximum image size in YV12
@@ -622,15 +620,19 @@ I830UpdateGamma(ScrnInfoPtr pScrn)
    CARD32   gamma4 = pPriv->gamma4;
    CARD32   gamma5 = pPriv->gamma5;
 
+#if 0
    ErrorF ("Original gamma: 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n",
 	   gamma0, gamma1, gamma2, gamma3, gamma4, gamma5);
+#endif
    gamma1 = I830BoundGamma (gamma1, gamma0);
    gamma2 = I830BoundGamma (gamma2, gamma1);
    gamma3 = I830BoundGamma (gamma3, gamma2);
    gamma4 = I830BoundGamma (gamma4, gamma3);
    gamma5 = I830BoundGamma (gamma5, gamma4);
+#if 0
    ErrorF ("Bounded  gamma: 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n",
 	   gamma0, gamma1, gamma2, gamma3, gamma4, gamma5);
+#endif
 
    OUTREG(OGAMC5, gamma5);
    OUTREG(OGAMC4, gamma4);
@@ -649,7 +651,7 @@ I830SetupImageVideoOverlay(ScreenPtr pSc
    I830PortPrivPtr pPriv;
    XF86AttributePtr att;
 
-   ErrorF("I830SetupImageVideoOverlay\n");
+   OVERLAY_DEBUG("I830SetupImageVideoOverlay\n");
 
    if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
 			 sizeof(I830PortPrivRec) + sizeof(DevUnion))))
@@ -775,7 +777,7 @@ I830SetupImageVideoTextured(ScreenPtr pS
    int nports = 16, i;
    int nAttributes;
 
-   ErrorF("I830SetupImageVideoOverlay\n");
+   OVERLAY_DEBUG("I830SetupImageVideoOverlay\n");
 
    nAttributes = NUM_TEXTURED_ATTRIBUTES;
 
@@ -881,7 +883,7 @@ I830StopVideo(ScrnInfoPtr pScrn, pointer
    if (pPriv->textured)
       return;
 
-   ErrorF("I830StopVideo\n");
+   OVERLAY_DEBUG("I830StopVideo\n");
 
    REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
 
@@ -928,14 +930,14 @@ I830SetPortAttribute(ScrnInfoPtr pScrn,
 	 return BadValue;
       pPriv->brightness = value;
       overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff);
-      ErrorF("BRIGHTNESS\n");
+      OVERLAY_DEBUG("BRIGHTNESS\n");
       OVERLAY_UPDATE;
    } else if (attribute == xvContrast) {
       if ((value < 0) || (value > 255))
 	 return BadValue;
       pPriv->contrast = value;
       overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff);
-      ErrorF("CONTRAST\n");
+      OVERLAY_DEBUG("CONTRAST\n");
       OVERLAY_UPDATE;
    } else if (attribute == xvSaturation) {
       if ((value < 0) || (value > 1023))
@@ -956,7 +958,7 @@ I830SetPortAttribute(ScrnInfoPtr pScrn,
          overlay->OCONFIG |= OVERLAY_PIPE_A;
       else 
          overlay->OCONFIG |= OVERLAY_PIPE_B;
-      ErrorF("PIPE CHANGE\n");
+      OVERLAY_DEBUG("PIPE CHANGE\n");
       OVERLAY_UPDATE;
    } else if (attribute == xvGamma0 && (IS_I9XX(pI830))) {
       pPriv->gamma0 = value; 
@@ -983,7 +985,7 @@ I830SetPortAttribute(ScrnInfoPtr pScrn,
 	 overlay->DCLRKV = pPriv->colorKey;
 	 break;
       }
-      ErrorF("COLORKEY\n");
+      OVERLAY_DEBUG("COLORKEY\n");
       OVERLAY_UPDATE;
       REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
    } else if(attribute == xvDoubleBuffer) {
@@ -1003,7 +1005,7 @@ I830SetPortAttribute(ScrnInfoPtr pScrn,
         attribute == xvGamma4 ||
         attribute == xvGamma5) && (IS_I9XX(pI830))) {
 	CARD32 r = overlay->OCMD & OVERLAY_ENABLE;
-        ErrorF("GAMMA\n");
+        OVERLAY_DEBUG("GAMMA\n");
         overlay->OCMD &= ~OVERLAY_ENABLE;
         OVERLAY_UPDATE;
 	I830UpdateGamma(pScrn);
@@ -1078,8 +1080,11 @@ I830CopyPackedData(ScrnInfoPtr pScrn, I8
    int i,j;
    unsigned char *s;
 
+#if 0
    ErrorF("I830CopyPackedData: (%d,%d) (%d,%d)\n"
-	   "srcPitch: %d, dstPitch: %d\n", top, left, h, w, srcPitch, dstPitch);
+	  "srcPitch: %d, dstPitch: %d\n", top, left, h, w,
+	  srcPitch, dstPitch);
+#endif
 
    src = buf + (top * srcPitch) + (left << 1);
 
@@ -1232,14 +1237,19 @@ I830CopyPlanarData(ScrnInfoPtr pScrn, I8
    unsigned char *s;
    int dstPitch2 = dstPitch << 1;
 
+#if 0
    ErrorF("I830CopyPlanarData: srcPitch %d, srcPitch %d, dstPitch %d\n"
-	   "nlines %d, npixels %d, top %d, left %d\n", srcPitch, srcPitch2, dstPitch,
-	   h, w, top, left);
+	  "nlines %d, npixels %d, top %d, left %d\n",
+	  srcPitch, srcPitch2, dstPitch,
+	  h, w, top, left);
+#endif
 
    /* Copy Y data */
    src1 = buf + (top * srcPitch) + left;
+#if 0
    ErrorF("src1 is %p, offset is %ld\n", src1,
 	  (unsigned long)src1 - (unsigned long)buf);
+#endif
    if (pPriv->currentBuf == 0)
       dst1 = pI830->FbBase + pPriv->YBuf0offset;
    else
@@ -1284,8 +1294,10 @@ I830CopyPlanarData(ScrnInfoPtr pScrn, I8
 
    /* Copy V data for YV12, or U data for I420 */
    src2 = buf + (srcH * srcPitch) + ((top * srcPitch) >> 2) + (left >> 1);
+#if 0
    ErrorF("src2 is %p, offset is %ld\n", src2,
 	  (unsigned long)src2 - (unsigned long)buf);
+#endif
    if (pPriv->currentBuf == 0) {
       if (id == FOURCC_I420)
 	 dst2 = pI830->FbBase + pPriv->UBuf0offset;
@@ -1338,8 +1350,10 @@ I830CopyPlanarData(ScrnInfoPtr pScrn, I8
    /* Copy U data for YV12, or V data for I420 */
    src3 = buf + (srcH * srcPitch) + ((srcH >> 1) * srcPitch2) +
 	 ((top * srcPitch) >> 2) + (left >> 1);
+#if 0
    ErrorF("src3 is %p, offset is %ld\n", src3,
 	  (unsigned long)src3 - (unsigned long)buf);
+#endif
    if (pPriv->currentBuf == 0) {
       if (id == FOURCC_I420)
 	 dst3 = pI830->FbBase + pPriv->VBuf0offset;
@@ -1533,8 +1547,8 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
    unsigned int mask, shift, offsety, offsetu;
    int tmp;
 
-   ErrorF("I830DisplayVideo: %dx%d (pitch %d)\n", width, height,
-	   dstPitch);
+   OVERLAY_DEBUG("I830DisplayVideo: %dx%d (pitch %d)\n", width, height,
+		 dstPitch);
 
    if (!pPriv->overlayOK)
       return;
@@ -1590,7 +1604,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
 
    /* Ensure overlay is turned on with OVERLAY_ENABLE at 0 */
    if (!*pI830->overlayOn) {
-      ErrorF("TURNING ON OVERLAY BEFORE UPDATE\n");
+      OVERLAY_DEBUG("TURNING ON OVERLAY BEFORE UPDATE\n");
       I830ResetVideo(pScrn);
       OVERLAY_UPDATE;
    }
@@ -1673,22 +1687,22 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
 
       /* nothing do to */
       if ((!dstBox->x1 && !dstBox->x2) || (!dstBox->y1 && !dstBox->y2)) {
-         ErrorF("NOTHING TO DO\n");
+         OVERLAY_DEBUG("NOTHING TO DO\n");
          return;
       }
       if ((dstBox->x1 == (pScrn->currentMode->HDisplay - 1) && 
            dstBox->x2 == (pScrn->currentMode->HDisplay - 1)) || 
           (dstBox->y1 == vactive && 
            dstBox->y2 == vactive)) {
-         ErrorF("NOTHING TO DO\n");
+         OVERLAY_DEBUG("NOTHING TO DO\n");
          return;
       }
       if ((dstBox->y2 - dstBox->y1) <= N_VERT_Y_TAPS) {
-         ErrorF("NOTHING TO DO\n");
+         OVERLAY_DEBUG("NOTHING TO DO\n");
          return;
       }
       if ((dstBox->x2 - dstBox->x1) <= 2) {
-         ErrorF("NOTHING TO DO\n");
+         OVERLAY_DEBUG("NOTHING TO DO\n");
          return;
       }
    }
@@ -1726,7 +1740,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
 
       swidth -= 1;
 
-      ErrorF("Y width is %d, swidth is %d\n", width, swidth);
+      OVERLAY_DEBUG("Y width is %d, swidth is %d\n", width, swidth);
 
       overlay->SWIDTHSW = swidth << 2;
 
@@ -1738,11 +1752,11 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
 
       swidth -= 1;
 
-      ErrorF("UV width is %d, swidthsw is %d\n", width / 2, swidth);
+      OVERLAY_DEBUG("UV width is %d, swidthsw is %d\n", width / 2, swidth);
 
       overlay->SWIDTHSW |= swidth << 18;
 
-      ErrorF("HEIGHT is %d\n",height);
+      OVERLAY_DEBUG("HEIGHT is %d\n",height);
 
       overlay->SHEIGHT = height | ((height / 2) << 16);
       break;
@@ -1752,7 +1766,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
       swidth = width;
       overlay->SWIDTH = swidth;
 
-      ErrorF("Y width is %d\n", swidth);
+      OVERLAY_DEBUG("Y width is %d\n", swidth);
 
       swidth = ((offsety + (width << 1) + mask) >> shift) -
 	    (offsety >> shift);
@@ -1762,11 +1776,11 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
 
       swidth -= 1;
 
-      ErrorF("swidthsw is %d\n", swidth);
+      OVERLAY_DEBUG("swidthsw is %d\n", swidth);
 
       overlay->SWIDTHSW = swidth << 2;
 
-      ErrorF("HEIGHT is %d\n",height);
+      OVERLAY_DEBUG("HEIGHT is %d\n",height);
 
       overlay->SHEIGHT = height;
       break;
@@ -1779,8 +1793,8 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
    overlay->DWINSZ = ((dstBox->y2 - dstBox->y1) << 16) |
 	 (dstBox->x2 - dstBox->x1);
 
-   ErrorF("dstBox: x1: %d, y1: %d, x2: %d, y2: %d\n", dstBox->x1, dstBox->y1,
-			dstBox->x2, dstBox->y2);
+   OVERLAY_DEBUG("dstBox: x1: %d, y1: %d, x2: %d, y2: %d\n",
+		 dstBox->x1, dstBox->y1, dstBox->x2, dstBox->y2);
 
    /* buffer locations */
    if (IS_I965G(pI830))
@@ -1810,10 +1824,10 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
       }
    }
 
-   ErrorF("Buffers: Y0: 0x%lx, U0: 0x%lx, V0: 0x%lx\n", overlay->OBUF_0Y,
-	  overlay->OBUF_0U, overlay->OBUF_0V);
-   ErrorF("Buffers: Y1: 0x%lx, U1: 0x%lx, V1: 0x%lx\n", overlay->OBUF_1Y,
-	  overlay->OBUF_1U, overlay->OBUF_1V);
+   OVERLAY_DEBUG("Buffers: Y0: 0x%lx, U0: 0x%lx, V0: 0x%lx\n",
+		 overlay->OBUF_0Y, overlay->OBUF_0U, overlay->OBUF_0V);
+   OVERLAY_DEBUG("Buffers: Y1: 0x%lx, U1: 0x%lx, V1: 0x%lx\n",
+		 overlay->OBUF_1Y, overlay->OBUF_1U, overlay->OBUF_1V);
 
 #if 0
    {
@@ -1837,8 +1851,9 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
    }
 #endif
 
-   ErrorF("pos: 0x%lx, size: 0x%lx\n", overlay->DWINPOS, overlay->DWINSZ);
-   ErrorF("dst: %d x %d, src: %d x %d\n", drw_w, drw_h, src_w, src_h);
+   OVERLAY_DEBUG("pos: 0x%lx, size: 0x%lx\n",
+		 overlay->DWINPOS, overlay->DWINSZ);
+   OVERLAY_DEBUG("dst: %d x %d, src: %d x %d\n", drw_w, drw_h, src_w, src_h);
 
    /* 
     * Calculate horizontal and vertical scaling factors and polyphase
@@ -1881,20 +1896,20 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
       xscaleIntUV = xscaleFractUV >> 12;
       yscaleIntUV = yscaleFractUV >> 12;
 
-      ErrorF("xscale: %x.%03x, yscale: %x.%03x\n", xscaleInt,
-	     xscaleFract & 0xFFF, yscaleInt, yscaleFract & 0xFFF);
-      ErrorF("UV xscale: %x.%03x, UV yscale: %x.%03x\n", xscaleIntUV,
-	     xscaleFractUV & 0xFFF, yscaleIntUV, yscaleFractUV & 0xFFF);
+      OVERLAY_DEBUG("xscale: %x.%03x, yscale: %x.%03x\n", xscaleInt,
+		    xscaleFract & 0xFFF, yscaleInt, yscaleFract & 0xFFF);
+      OVERLAY_DEBUG("UV xscale: %x.%03x, UV yscale: %x.%03x\n", xscaleIntUV,
+		    xscaleFractUV & 0xFFF, yscaleIntUV, yscaleFractUV & 0xFFF);
 
       /* shouldn't get here */
-      if (xscaleInt > 7) { 
-         ErrorF("xscale: bad scale\n");
+      if (xscaleInt > 7) {
+         OVERLAY_DEBUG("xscale: bad scale\n");
 	 return;
       }
 
       /* shouldn't get here */
-      if (xscaleIntUV > 7) { 
-         ErrorF("xscaleUV: bad scale\n");
+      if (xscaleIntUV > 7) {
+         OVERLAY_DEBUG("xscaleUV: bad scale\n");
          return;
       }
 
@@ -1965,12 +1980,13 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
    switch (id) {
    case FOURCC_YV12:
    case FOURCC_I420:
-      ErrorF("YUV420\n");
+      OVERLAY_DEBUG("YUV420\n");
 #if 0
       /* set UV vertical phase to -0.25 */
       overlay->UV_VPH = 0x30003000;
 #endif
-      ErrorF("UV stride is %d, Y stride is %d\n", dstPitch, dstPitch * 2);
+      OVERLAY_DEBUG("UV stride is %d, Y stride is %d\n",
+		    dstPitch, dstPitch * 2);
       overlay->OSTRIDE = (dstPitch * 2) | (dstPitch << 16);
       overlay->OCMD &= ~SOURCE_FORMAT;
       overlay->OCMD &= ~OV_BYTE_ORDER;
@@ -1979,7 +1995,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
    case FOURCC_UYVY:
    case FOURCC_YUY2:
    default:
-      ErrorF("YUV422\n");
+      OVERLAY_DEBUG("YUV422\n");
       overlay->OSTRIDE = dstPitch;
       overlay->OCMD &= ~SOURCE_FORMAT;
       overlay->OCMD |= YUV_422;
@@ -1995,7 +2011,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
    else
       overlay->OCMD |= BUFFER1;
 
-   ErrorF("OCMD is 0x%lx\n", overlay->OCMD);
+   OVERLAY_DEBUG("OCMD is 0x%lx\n", overlay->OCMD);
 
    OVERLAY_UPDATE;
 }
@@ -2158,9 +2174,11 @@ I830PutImage(ScrnInfoPtr pScrn,
    int pitchAlignMask;
    int extraLinear;
 
+#if 0
    ErrorF("I830PutImage: src: (%d,%d)(%d,%d), dst: (%d,%d)(%d,%d)\n"
 	   "width %d, height %d\n", src_x, src_y, src_w, src_h, drw_x, drw_y,
 	   drw_w, drw_h, width, height);
+#endif
 
    if (pI830->entityPrivate) {
 	 if (pI830->entityPrivate->XvInUse != -1 &&
@@ -2441,6 +2459,7 @@ I830QueryImageAttributes(ScrnInfoPtr pSc
       if (offsets)
 	 offsets[2] = size;
       size += tmp;
+#if 0
       if (pitches)
 	 ErrorF("pitch 0 is %d, pitch 1 is %d, pitch 2 is %d\n", pitches[0],
 		pitches[1], pitches[2]);
@@ -2448,6 +2467,7 @@ I830QueryImageAttributes(ScrnInfoPtr pSc
 	 ErrorF("offset 1 is %d, offset 2 is %d\n", offsets[1], offsets[2]);
       if (offsets)
 	 ErrorF("size is %d\n", size);
+#endif
       break;
    case FOURCC_UYVY:
    case FOURCC_YUY2:
@@ -2504,7 +2524,7 @@ I830BlockHandler(int i,
       if (pPriv->videoStatus & OFF_TIMER) {
 	 if (pPriv->offTime < now) {
 	    /* Turn off the overlay */
-	    ErrorF("BLOCKHANDLER\n");
+	    OVERLAY_DEBUG("BLOCKHANDLER\n");
 
 	    I830ResetVideo(pScrn);
             OVERLAY_UPDATE;
@@ -2544,7 +2564,7 @@ I830AllocateSurface(ScrnInfoPtr pScrn,
    OffscreenPrivPtr pPriv;
    I830Ptr pI830 = I830PTR(pScrn);
 
-   ErrorF("I830AllocateSurface\n");
+   OVERLAY_DEBUG("I830AllocateSurface\n");
 
    if (IS_845G(pI830) || IS_I830(pI830)) {
       if ((w > IMAGE_MAX_WIDTH_LEGACY) || (h > IMAGE_MAX_HEIGHT_LEGACY))
@@ -2608,7 +2628,7 @@ I830StopSurface(XF86SurfacePtr surface)
    if (pPriv->isOn) {
       I830Ptr pI830 = I830PTR(pScrn);
 
-      ErrorF("StopSurface\n");
+      OVERLAY_DEBUG("StopSurface\n");
 
       I830ResetVideo(pScrn);
       OVERLAY_UPDATE;
@@ -2669,7 +2689,7 @@ I830DisplaySurface(XF86SurfacePtr surfac
    INT32 loops = 0;
    BoxRec dstBox;
 
-   ErrorF("I830DisplaySurface\n");
+   OVERLAY_DEBUG("I830DisplaySurface\n");
 
    if (pI830->entityPrivate) {
 	 if (pI830->entityPrivate->XvInUse != -1 &&
diff-tree 6dc3387219b2b31e0c7dbaa88b568fbd54d72878 (from 210f30bd75529d0064bc46af15464a2a47f9d4c6)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Dec 27 18:58:40 2006 -0800

    Fix operator precedence issue that stuck 965 t-v state into the front buffer.

diff --git a/src/i830_video.c b/src/i830_video.c
index a0ab932..0ffa189 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -2273,7 +2273,7 @@ I830PutImage(ScrnInfoPtr pScrn,
       return BadAlloc;
 
    pPriv->extra_offset = pPriv->linear.offset +
-      pPriv->doubleBuffer ? size * 2 : size;
+      (pPriv->doubleBuffer ? size * 2 : size);
 
    /* fixup pointers */
    pPriv->YBuf0offset = pPriv->linear.offset;
diff-tree 210f30bd75529d0064bc46af15464a2a47f9d4c6 (from 82738e60769a4798d7425ffc67882d1f74043b76)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Dec 27 18:57:50 2006 -0800

    debugging for location of various 965 textured-video state.

diff --git a/src/i965_video.c b/src/i965_video.c
index d4403df..af22cb2 100644
--- a/src/i965_video.c
+++ b/src/i965_video.c
@@ -281,6 +281,22 @@ I965DisplayVideoTextured(ScrnInfoPtr pSc
     binding_table = (void *)(state_base + binding_table_offset);
     vb = (void *)(state_base + vb_offset);
 
+#if 0
+    ErrorF("vs:            0x%08x\n", state_base_offset + vs_offset);
+    ErrorF("wm:            0x%08x\n", state_base_offset + wm_offset);
+    ErrorF("sf:            0x%08x\n", state_base_offset + sf_offset);
+    ErrorF("cc:            0x%08x\n", state_base_offset + cc_offset);
+    ErrorF("sf kernel:     0x%08x\n", state_base_offset + sf_kernel_offset);
+    ErrorF("ps kernel:     0x%08x\n", state_base_offset + ps_kernel_offset);
+    ErrorF("sip kernel:    0x%08x\n", state_base_offset + sip_kernel_offset);
+    ErrorF("cc_vp:         0x%08x\n", state_base_offset + cc_viewport_offset);
+    ErrorF("src sampler:   0x%08x\n", state_base_offset + src_sampler_offset);
+    ErrorF("vb:            0x%08x\n", state_base_offset + vb_offset);
+    ErrorF("dst surf:      0x%08x\n", state_base_offset + dest_surf_offset);
+    ErrorF("src surf:      0x%08x\n", state_base_offset + src_surf_offset);
+    ErrorF("binding table: 0x%08x\n", state_base_offset + binding_table_offset);
+#endif
+
     /* For 3D, the VS must have 8, 12, 16, 24, or 32 VUEs allocated to it.
      * A VUE consists of a 256-bit vertex header followed by the vertex data,
      * which in our case is 4 floats (128 bits), thus a single 512-bit URB
@@ -430,9 +446,6 @@ I965DisplayVideoTextured(ScrnInfoPtr pSc
 
     memcpy (sf_kernel, sf_kernel_static, sizeof (sf_kernel_static));
     memset(sf_state, 0, sizeof(*sf_state));
-#if 0
-    ErrorF ("sf kernel: 0x%08x\n", state_base_offset + sf_kernel_offset);
-#endif
     sf_state->thread0.kernel_start_pointer =
 	(state_base_offset + sf_kernel_offset) >> 6;
     sf_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(SF_KERNEL_NUM_GRF);
@@ -463,9 +476,6 @@ I965DisplayVideoTextured(ScrnInfoPtr pSc
     sf_state->sf6.dest_org_hbias = 0x8;
 
     memcpy (ps_kernel, ps_kernel_static, sizeof (ps_kernel_static));
-#if 0
-    ErrorF ("ps kernel: 0x%08x\n", state_base_offset + ps_kernel_offset);
-#endif
     memset (wm_state, 0, sizeof (*wm_state));
     wm_state->thread0.kernel_start_pointer =
 	(state_base_offset + ps_kernel_offset) >> 6;
diff-tree 82738e60769a4798d7425ffc67882d1f74043b76 (from 8165e043670f6a7fee5e7e8f33644adda5757591)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Dec 27 18:35:35 2006 -0800

    Fix discrepancy between XAA/EXA linear allocations that broke EXA XV.
    
    The XAA allocator returned an offset from the beginning of the frontbuffer
    allocation (where the linear allocations come from), while EXA returned one
    from the start of framebuffer.  Now, both of them use the start of framebuffer
    as the reference.

diff --git a/src/i830_video.c b/src/i830_video.c
index 3153041..a0ab932 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -2018,7 +2018,8 @@ I830VideoSave(ScreenPtr pScreen, ExaOffs
  * \param pPriv adaptor the memory is being allocated for.
  * \param size size of the allocation, in bytes.
  * \param alignment offset alignment of the allocation, in bytes.
- * \return offset of the allocated memory.
+ *
+ * \return byte offset of the allocated memory from the start of framebuffer.
  */
 static void
 I830AllocateMemory(ScrnInfoPtr pScrn, struct linear_alloc *linear, int size,
@@ -2048,6 +2049,11 @@ I830AllocateMemory(ScrnInfoPtr pScrn, st
    if (!pI830->useEXA) {
       int max_size;
 
+      /* Converts an offset from XAA's linear allocator to an offset from the
+       * start of fb.
+       */
+#define XAA_OFFSET_TO_OFFSET(x) (pI830->FrontBuffer.Start + (x * pI830->cpp))
+
       /* The XFree86 linear allocator operates in units of screen pixels,
        * sadly.
        */
@@ -2056,12 +2062,12 @@ I830AllocateMemory(ScrnInfoPtr pScrn, st
 
       if (linear->xaa != NULL) {
 	 if (linear->xaa->size >= size) {
-	    linear->offset = linear->xaa->offset * pI830->cpp;
+	    linear->offset = XAA_OFFSET_TO_OFFSET(linear->xaa->offset);
 	    return;
 	 }
 
 	 if (xf86ResizeOffscreenLinear(linear->xaa, size)) {
-	    linear->offset = linear->xaa->offset * pI830->cpp;
+	    linear->offset = XAA_OFFSET_TO_OFFSET(linear->xaa->offset);
 	    return;
 	 }
 
@@ -2071,7 +2077,7 @@ I830AllocateMemory(ScrnInfoPtr pScrn, st
       linear->xaa = xf86AllocateOffscreenLinear(pScreen, size, align,
 						NULL, NULL, NULL);
       if (linear->xaa != NULL) {
-	 linear->offset = linear->xaa->offset * pI830->cpp;
+	 linear->offset = XAA_OFFSET_TO_OFFSET(linear->xaa->offset);
 	 return;
       }
 
@@ -2087,7 +2093,7 @@ I830AllocateMemory(ScrnInfoPtr pScrn, st
       xf86PurgeUnlockedOffscreenAreas(pScreen);
       linear->xaa = xf86AllocateOffscreenLinear(pScreen, size, 4,
 						NULL, NULL, NULL);
-      linear->offset = linear->xaa->offset * pI830->cpp;
+      linear->offset = XAA_OFFSET_TO_OFFSET(linear->xaa->offset);
    }
 #endif /* I830_USE_XAA */
 }
@@ -2270,11 +2276,7 @@ I830PutImage(ScrnInfoPtr pScrn,
       pPriv->doubleBuffer ? size * 2 : size;
 
    /* fixup pointers */
-#if 0
-   pPriv->YBuf0offset = pScrn->fbOffset + pPriv->linear.offset;
-#else
-   pPriv->YBuf0offset = pI830->FrontBuffer.Start + pPriv->linear.offset;
-#endif
+   pPriv->YBuf0offset = pPriv->linear.offset;
    if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
       pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * width);
       pPriv->VBuf0offset = pPriv->UBuf0offset + (dstPitch * width / 2);
@@ -2592,11 +2594,7 @@ I830AllocateSurface(ScrnInfoPtr pScrn,
    surface->offsets[0] = pPriv->linear.offset;
    surface->devPrivate.ptr = (pointer) pPriv;
 
-#if 0
-   memset(pI830->FbBase + pScrn->fbOffset + surface->offsets[0], 0, size);
-#else
-   memset(pI830->FbBase + pI830->FrontBuffer.Start + surface->offsets[0], 0, size);
-#endif
+   memset(pI830->FbBase + surface->offsets[0], 0, size);
 
    return Success;
 }
diff-tree 8165e043670f6a7fee5e7e8f33644adda5757591 (from f830c55e5f4efc97451240f8f18b49f46e8bce0f)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Dec 27 18:17:37 2006 -0800

    Bump the size of the extra space for 965 so it actually fits.

diff --git a/src/i830_video.h b/src/i830_video.h
index 356a8f7..90c58b7 100644
--- a/src/i830_video.h
+++ b/src/i830_video.h
@@ -84,7 +84,7 @@ typedef struct {
 /*
  * Broadwater requires a bit of extra video memory for state information
  */
-#define BRW_LINEAR_EXTRA	(32*1024)
+#define BRW_LINEAR_EXTRA	(36*1024)
 
 void I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv,
 			      int id, RegionPtr dstRegion, short width,
diff-tree f830c55e5f4efc97451240f8f18b49f46e8bce0f (from a75b416c91085df1db4027a25eafcd04fef1e57c)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Dec 27 18:14:59 2006 -0800

    Make the assert() in i965_video.c actually work and expose an error.

diff --git a/src/i830_video.c b/src/i830_video.c
index 2e4a85b..3153041 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -131,11 +131,6 @@ static Atom xvGamma0, xvGamma1, xvGamma2
 #define IMAGE_MAX_WIDTH_LEGACY	1024
 #define IMAGE_MAX_HEIGHT_LEGACY	1088
 
-/*
- * Broadwater requires a bit of extra video memory for state information
- */
-#define BRW_LINEAR_EXTRA	(32*1024)
-
 #if !VIDEO_DEBUG
 #define ErrorF Edummy
 static void
diff --git a/src/i830_video.h b/src/i830_video.h
index a00cd50..356a8f7 100644
--- a/src/i830_video.h
+++ b/src/i830_video.h
@@ -81,6 +81,11 @@ typedef struct {
 #define GET_PORT_PRIVATE(pScrn) \
    (I830PortPrivPtr)((I830PTR(pScrn))->adaptor->pPortPrivates[0].ptr)
 
+/*
+ * Broadwater requires a bit of extra video memory for state information
+ */
+#define BRW_LINEAR_EXTRA	(32*1024)
+
 void I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv,
 			      int id, RegionPtr dstRegion, short width,
 			      short height, int video_pitch,
diff --git a/src/i965_video.c b/src/i965_video.c
index 96ba8f1..d4403df 100644
--- a/src/i965_video.c
+++ b/src/i965_video.c
@@ -40,6 +40,10 @@
 #include "brw_defines.h"
 #include "brw_structs.h"
 
+/* Make assert() work. */
+#undef NDEBUG
+#include <assert.h>
+
 static const CARD32 sip_kernel_static[][4] = {
 /*    wait (1) a0<1>UW a145<0,1,0>UW { align1 +  } */
     { 0x00000030, 0x20000108, 0x00001220, 0x00000000 },
diff-tree a75b416c91085df1db4027a25eafcd04fef1e57c (from 150010d2f20f4a57f8507eba8762e36966b0f426)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Dec 27 17:58:57 2006 -0800

    Replace XAA mark/waitsyncs with the XAA/EXA wrappers.

diff --git a/src/i965_video.c b/src/i965_video.c
index 07ee360..96ba8f1 100644
--- a/src/i965_video.c
+++ b/src/i965_video.c
@@ -659,10 +659,7 @@ I965DisplayVideoTextured(ScrnInfoPtr pSc
 	    /* Since we use the same little vertex buffer over and over, sync
 	     * for subsequent rectangles.
 	     */
-	    if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
-		(*pI830->AccelInfoRec->Sync)(pScrn);
-		pI830->AccelInfoRec->NeedToSync = FALSE;
-	    }
+	    i830WaitSync(pScrn);
 	}
 
 	pbox++;
@@ -831,12 +828,10 @@ I965DisplayVideoTextured(ScrnInfoPtr pSc
 	}
 #endif
 	first_output = FALSE;
-	if (pI830->AccelInfoRec)
-	    pI830->AccelInfoRec->NeedToSync = TRUE;
+	i830MarkSync(pScrn);
     }
 
-    if (pI830->AccelInfoRec)
-	(*pI830->AccelInfoRec->Sync)(pScrn);
+    i830WaitSync(pScrn);
 #if WATCH_STATS
     i830_dump_error_state(pScrn);
 #endif
diff-tree 150010d2f20f4a57f8507eba8762e36966b0f426 (from 05066632b068ae91d7be77e3a199ea0d337d975b)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Dec 27 17:57:34 2006 -0800

    reformat i965_video.c to 4-space indents, 80 columns, no trailing whitespace.

diff --git a/src/i965_video.c b/src/i965_video.c
index 3677d9d..07ee360 100644
--- a/src/i965_video.c
+++ b/src/i965_video.c
@@ -62,7 +62,7 @@ static const CARD32 sip_kernel_static[][
 /*    nop (4) g0<1>UD { align1 +  } */
     { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
 };
-   
+
 /*
  * this program computes dA/dx and dA/dy for the texture coordinates along
  * with the base texture coordinate. It was extracted from the Mesa driver.
@@ -98,39 +98,39 @@ static const CARD32 ps_kernel_static[][4
 #define WM_BINDING_TABLE_ENTRIES    2
 
 static CARD32 float_to_uint (float f) {
-   union {CARD32 i; float f;} x;
-   x.f = f;
-   return x.i;
+    union {CARD32 i; float f;} x;
+    x.f = f;
+    return x.i;
 }
 
 #if 0
 static struct {
-   CARD32   svg_ctl;
-   char	    *name;
+    CARD32 svg_ctl;
+    char *name;
 } svg_ctl_bits[] = {
-   { BRW_SVG_CTL_GS_BA, "General State Base Address" },
-   { BRW_SVG_CTL_SS_BA, "Surface State Base Address" },
-   { BRW_SVG_CTL_IO_BA, "Indirect Object Base Address" },
-   { BRW_SVG_CTL_GS_AUB, "Generate State Access Upper Bound" },
-   { BRW_SVG_CTL_IO_AUB, "Indirect Object Access Upper Bound" },
-   { BRW_SVG_CTL_SIP, "System Instruction Pointer" },
-   { 0, 0 },
+    { BRW_SVG_CTL_GS_BA, "General State Base Address" },
+    { BRW_SVG_CTL_SS_BA, "Surface State Base Address" },
+    { BRW_SVG_CTL_IO_BA, "Indirect Object Base Address" },
+    { BRW_SVG_CTL_GS_AUB, "Generate State Access Upper Bound" },
+    { BRW_SVG_CTL_IO_AUB, "Indirect Object Access Upper Bound" },
+    { BRW_SVG_CTL_SIP, "System Instruction Pointer" },
+    { 0, 0 },
 };
 
 static void
 brw_debug (ScrnInfoPtr pScrn, char *when)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
-   int	    i;
-   CARD32   v;
-   
-   I830Sync (pScrn);
-   ErrorF("brw_debug: %s\n", when);
-   for (i = 0; svg_ctl_bits[i].name; i++) {
-      OUTREG(BRW_SVG_CTL, svg_ctl_bits[i].svg_ctl);
-      v = INREG(BRW_SVG_RDATA);
-      ErrorF("\t%34.34s: 0x%08x\n", svg_ctl_bits[i].name, v);
-   }
+    I830Ptr pI830 = I830PTR(pScrn);
+    int	i;
+    CARD32 v;
+
+    I830Sync (pScrn);
+    ErrorF("brw_debug: %s\n", when);
+    for (i = 0; svg_ctl_bits[i].name; i++) {
+	OUTREG(BRW_SVG_CTL, svg_ctl_bits[i].svg_ctl);
+	v = INREG(BRW_SVG_RDATA);
+	ErrorF("\t%34.34s: 0x%08x\n", svg_ctl_bits[i].name, v);
+    }
 }
 #endif
 
@@ -147,681 +147,697 @@ I965DisplayVideoTextured(ScrnInfoPtr pSc
 			 short drw_w, short drw_h,
 			 DrawablePtr pDraw)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
-   BoxPtr pbox;
-   int nbox, dxo, dyo;
-   int urb_vs_start, urb_vs_size;
-   int urb_gs_start, urb_gs_size;
-   int urb_clip_start, urb_clip_size;
-   int urb_sf_start, urb_sf_size;
-   int urb_cs_start, urb_cs_size;
-   struct brw_surface_state *dest_surf_state;
-   struct brw_surface_state *src_surf_state;
-   struct brw_sampler_state *src_sampler_state;
-   struct brw_vs_unit_state *vs_state;
-   struct brw_sf_unit_state *sf_state;
-   struct brw_wm_unit_state *wm_state;
-   struct brw_cc_unit_state *cc_state;
-   struct brw_cc_viewport *cc_viewport;
-   struct brw_instruction *sf_kernel;
-   struct brw_instruction *ps_kernel;
-   struct brw_instruction *sip_kernel;
-   float *vb;
+    I830Ptr pI830 = I830PTR(pScrn);
+    BoxPtr pbox;
+    int nbox, dxo, dyo;
+    int urb_vs_start, urb_vs_size;
+    int urb_gs_start, urb_gs_size;
+    int urb_clip_start, urb_clip_size;
+    int urb_sf_start, urb_sf_size;
+    int urb_cs_start, urb_cs_size;
+    struct brw_surface_state *dest_surf_state;
+    struct brw_surface_state *src_surf_state;
+    struct brw_sampler_state *src_sampler_state;
+    struct brw_vs_unit_state *vs_state;
+    struct brw_sf_unit_state *sf_state;
+    struct brw_wm_unit_state *wm_state;
+    struct brw_cc_unit_state *cc_state;
+    struct brw_cc_viewport *cc_viewport;
+    struct brw_instruction *sf_kernel;
+    struct brw_instruction *ps_kernel;
+    struct brw_instruction *sip_kernel;
+    float *vb;
     CARD32 *binding_table;
-   Bool first_output = TRUE;
-   int dest_surf_offset, src_surf_offset, src_sampler_offset, vs_offset;
-   int sf_offset, wm_offset, cc_offset, vb_offset, cc_viewport_offset;
-   int wm_scratch_offset;
-   int sf_kernel_offset, ps_kernel_offset, sip_kernel_offset;
-   int binding_table_offset;
-   int next_offset, total_state_size;
-   int vb_size = (4 * 4) * 4; /* 4 DWORDS per vertex */
-   char *state_base;
-   int state_base_offset;
-
-#if 0
-   ErrorF("BroadwaterDisplayVideoTextured: %dx%d (pitch %d)\n", width, height,
-	  video_pitch);
-#endif
-
-   /* enable debug */
-   OUTREG (INST_PM,
-	   (1 << (16 + 4)) |
-	   (1 << 4));
-#if 0
-   ErrorF ("INST_PM 0x%08x\n", INREG(INST_PM));
-#endif
-   
-   assert((id == FOURCC_UYVY) || (id == FOURCC_YUY2));
-
-   /* Tell the rotation code that we have stomped its invariant state by
-    * setting a high bit.  We don't use any invariant 3D state for video, so we
-    * don't have to worry about it ourselves.
-    */
-   *pI830->used3D |= 1 << 30;
+    Bool first_output = TRUE;
+    int dest_surf_offset, src_surf_offset, src_sampler_offset, vs_offset;
+    int sf_offset, wm_offset, cc_offset, vb_offset, cc_viewport_offset;
+    int wm_scratch_offset;
+    int sf_kernel_offset, ps_kernel_offset, sip_kernel_offset;
+    int binding_table_offset;
+    int next_offset, total_state_size;
+    int vb_size = (4 * 4) * 4; /* 4 DWORDS per vertex */
+    char *state_base;
+    int state_base_offset;
+
+#if 0
+    ErrorF("BroadwaterDisplayVideoTextured: %dx%d (pitch %d)\n", width, height,
+	   video_pitch);
+#endif
+
+    /* enable debug */
+    OUTREG (INST_PM,
+	    (1 << (16 + 4)) |
+	    (1 << 4));
+#if 0
+    ErrorF ("INST_PM 0x%08x\n", INREG(INST_PM));
+#endif
+
+    assert((id == FOURCC_UYVY) || (id == FOURCC_YUY2));
+
+    /* Tell the rotation code that we have stomped its invariant state by
+     * setting a high bit.  We don't use any invariant 3D state for video, so
+     * we don't have to worry about it ourselves.
+     */
+    *pI830->used3D |= 1 << 30;
 
 #ifdef XF86DRI
-   /* Tell the DRI that we're smashing its state. */
-   if (pI830->directRenderingEnabled) {
-     drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
+    /* Tell the DRI that we're smashing its state. */
+    if (pI830->directRenderingEnabled) {
+	drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
 
-     pSAREAPriv->ctxOwner = DRIGetContext(pScrn->pScreen);
-   }
+	pSAREAPriv->ctxOwner = DRIGetContext(pScrn->pScreen);
+    }
 #endif /* XF86DRI */
 
-   next_offset = 0;
+    next_offset = 0;
 
-   /* Set up our layout of state in framebuffer.  First the general state: */
-   vs_offset = ALIGN(next_offset, 64);
-   next_offset = vs_offset + sizeof(*vs_state);
-   sf_offset = ALIGN(next_offset, 32);
-   next_offset = sf_offset + sizeof(*sf_state);
-   wm_offset = ALIGN(next_offset, 32);
-   next_offset = wm_offset + sizeof(*wm_state);
-   wm_scratch_offset = ALIGN(next_offset, 1024);
-   next_offset = wm_scratch_offset + 1024 * PS_MAX_THREADS;
-   cc_offset = ALIGN(next_offset, 32);
-   next_offset = cc_offset + sizeof(*cc_state);
-
-   sf_kernel_offset = ALIGN(next_offset, 64);
-   next_offset = sf_kernel_offset + sizeof (sf_kernel_static);
-   ps_kernel_offset = ALIGN(next_offset, 64);
-   next_offset = ps_kernel_offset + sizeof (ps_kernel_static);
-   sip_kernel_offset = ALIGN(next_offset, 64);
-   next_offset = sip_kernel_offset + sizeof (sip_kernel_static);
-   cc_viewport_offset = ALIGN(next_offset, 32);
-   next_offset = cc_viewport_offset + sizeof(*cc_viewport);
-
-   src_sampler_offset = ALIGN(next_offset, 32);
-   next_offset = src_sampler_offset + sizeof(*src_sampler_state);
-
-   /* Align VB to native size of elements, for safety */
-   vb_offset = ALIGN(next_offset, 8);
-   next_offset = vb_offset + vb_size;
-
-   /* And then the general state: */
-   dest_surf_offset = ALIGN(next_offset, 32);
-   next_offset = dest_surf_offset + sizeof(*dest_surf_state);
-   src_surf_offset = ALIGN(next_offset, 32);
-   next_offset = src_surf_offset + sizeof(*src_surf_state);
-   binding_table_offset = ALIGN(next_offset, 32);
-   next_offset = binding_table_offset + (WM_BINDING_TABLE_ENTRIES * 4);
-
-   /* Allocate an area in framebuffer for our state layout we just set up */
-   total_state_size = next_offset;
-   assert (total_state_size < BRW_LINEAR_EXTRA);
-
-   /*
-    * Use the extra space allocated at the end of the Xv buffer
-    */
-   state_base_offset = pPriv->extra_offset;
-   state_base_offset = ALIGN(state_base_offset, 64);
-
-   state_base = (char *)(pI830->FbBase + state_base_offset);
-   /* Set up our pointers to state structures in framebuffer.  It would probably
-    * be a good idea to fill these structures out in system memory and then dump
-    * them there, instead.
-    */
-   vs_state = (void *)(state_base + vs_offset);
-   sf_state = (void *)(state_base + sf_offset);
-   wm_state = (void *)(state_base + wm_offset);
-   cc_state = (void *)(state_base + cc_offset);
-   sf_kernel = (void *)(state_base + sf_kernel_offset);
-   ps_kernel = (void *)(state_base + ps_kernel_offset);
-   sip_kernel = (void *)(state_base + sip_kernel_offset);
-   
-   cc_viewport = (void *)(state_base + cc_viewport_offset);
-   dest_surf_state = (void *)(state_base + dest_surf_offset);
-   src_surf_state = (void *)(state_base + src_surf_offset);
-   src_sampler_state = (void *)(state_base + src_sampler_offset);
-   binding_table = (void *)(state_base + binding_table_offset);
-   vb = (void *)(state_base + vb_offset);
-
-   /* For 3D, the VS must have 8, 12, 16, 24, or 32 VUEs allocated to it.
-    * A VUE consists of a 256-bit vertex header followed by the vertex data,
-    * which in our case is 4 floats (128 bits), thus a single 512-bit URB
-    * entry.
-    */
+    /* Set up our layout of state in framebuffer.  First the general state: */
+    vs_offset = ALIGN(next_offset, 64);
+    next_offset = vs_offset + sizeof(*vs_state);
+    sf_offset = ALIGN(next_offset, 32);
+    next_offset = sf_offset + sizeof(*sf_state);
+    wm_offset = ALIGN(next_offset, 32);
+    next_offset = wm_offset + sizeof(*wm_state);
+    wm_scratch_offset = ALIGN(next_offset, 1024);
+    next_offset = wm_scratch_offset + 1024 * PS_MAX_THREADS;
+    cc_offset = ALIGN(next_offset, 32);
+    next_offset = cc_offset + sizeof(*cc_state);
+
+    sf_kernel_offset = ALIGN(next_offset, 64);
+    next_offset = sf_kernel_offset + sizeof (sf_kernel_static);
+    ps_kernel_offset = ALIGN(next_offset, 64);
+    next_offset = ps_kernel_offset + sizeof (ps_kernel_static);
+    sip_kernel_offset = ALIGN(next_offset, 64);
+    next_offset = sip_kernel_offset + sizeof (sip_kernel_static);
+    cc_viewport_offset = ALIGN(next_offset, 32);
+    next_offset = cc_viewport_offset + sizeof(*cc_viewport);
+
+    src_sampler_offset = ALIGN(next_offset, 32);
+    next_offset = src_sampler_offset + sizeof(*src_sampler_state);
+
+    /* Align VB to native size of elements, for safety */
+    vb_offset = ALIGN(next_offset, 8);
+    next_offset = vb_offset + vb_size;
+
+    /* And then the general state: */
+    dest_surf_offset = ALIGN(next_offset, 32);
+    next_offset = dest_surf_offset + sizeof(*dest_surf_state);
+    src_surf_offset = ALIGN(next_offset, 32);
+    next_offset = src_surf_offset + sizeof(*src_surf_state);
+    binding_table_offset = ALIGN(next_offset, 32);
+    next_offset = binding_table_offset + (WM_BINDING_TABLE_ENTRIES * 4);
+
+    /* Allocate an area in framebuffer for our state layout we just set up */
+    total_state_size = next_offset;
+    assert (total_state_size < BRW_LINEAR_EXTRA);
+
+    /*
+     * Use the extra space allocated at the end of the Xv buffer
+     */
+    state_base_offset = pPriv->extra_offset;
+    state_base_offset = ALIGN(state_base_offset, 64);
+
+    state_base = (char *)(pI830->FbBase + state_base_offset);
+    /* Set up our pointers to state structures in framebuffer.  It would
+     * probably be a good idea to fill these structures out in system memory
+     * and then dump them there, instead.
+     */
+    vs_state = (void *)(state_base + vs_offset);
+    sf_state = (void *)(state_base + sf_offset);
+    wm_state = (void *)(state_base + wm_offset);
+    cc_state = (void *)(state_base + cc_offset);
+    sf_kernel = (void *)(state_base + sf_kernel_offset);
+    ps_kernel = (void *)(state_base + ps_kernel_offset);
+    sip_kernel = (void *)(state_base + sip_kernel_offset);
+
+    cc_viewport = (void *)(state_base + cc_viewport_offset);
+    dest_surf_state = (void *)(state_base + dest_surf_offset);
+    src_surf_state = (void *)(state_base + src_surf_offset);
+    src_sampler_state = (void *)(state_base + src_sampler_offset);
+    binding_table = (void *)(state_base + binding_table_offset);
+    vb = (void *)(state_base + vb_offset);
+
+    /* For 3D, the VS must have 8, 12, 16, 24, or 32 VUEs allocated to it.
+     * A VUE consists of a 256-bit vertex header followed by the vertex data,
+     * which in our case is 4 floats (128 bits), thus a single 512-bit URB
+     * entry.
+     */
 #define URB_VS_ENTRIES	      8
 #define URB_VS_ENTRY_SIZE     1
-   
+
 #define URB_GS_ENTRIES	      0
 #define URB_GS_ENTRY_SIZE     0
-   
+
 #define URB_CLIP_ENTRIES      0
 #define URB_CLIP_ENTRY_SIZE   0
-   
-   /* The SF kernel we use outputs only 4 256-bit registers, leading to an
-    * entry size of 2 512-bit URBs.  We don't need to have many entries to
-    * output as we're generally working on large rectangles and don't care
-    * about having WM threads running on different rectangles simultaneously.
-    */
+
+    /* The SF kernel we use outputs only 4 256-bit registers, leading to an
+     * entry size of 2 512-bit URBs.  We don't need to have many entries to
+     * output as we're generally working on large rectangles and don't care
+     * about having WM threads running on different rectangles simultaneously.
+     */
 #define URB_SF_ENTRIES	      1
 #define URB_SF_ENTRY_SIZE     2
 
 #define URB_CS_ENTRIES	      0
 #define URB_CS_ENTRY_SIZE     0
-   
-   urb_vs_start = 0;
-   urb_vs_size = URB_VS_ENTRIES * URB_VS_ENTRY_SIZE;
-   urb_gs_start = urb_vs_start + urb_vs_size;
-   urb_gs_size = URB_GS_ENTRIES * URB_GS_ENTRY_SIZE;
-   urb_clip_start = urb_gs_start + urb_gs_size;
-   urb_clip_size = URB_CLIP_ENTRIES * URB_CLIP_ENTRY_SIZE;
-   urb_sf_start = urb_clip_start + urb_clip_size;
-   urb_sf_size = URB_SF_ENTRIES * URB_SF_ENTRY_SIZE;
-   urb_cs_start = urb_sf_start + urb_sf_size;
-   urb_cs_size = URB_CS_ENTRIES * URB_CS_ENTRY_SIZE;
-
-   /* We'll be poking the state buffers that could be in use by the 3d hardware
-    * here, but we should have synced the 3D engine already in I830PutImage.
-    */
-
-   memset (cc_viewport, 0, sizeof (*cc_viewport));
-   cc_viewport->min_depth = -1.e35;
-   cc_viewport->max_depth = 1.e35;
-
-   /* Color calculator state */
-   memset(cc_state, 0, sizeof(*cc_state));
-   cc_state->cc0.stencil_enable = 0;   /* disable stencil */
-   cc_state->cc2.depth_test = 0;       /* disable depth test */
-   cc_state->cc2.logicop_enable = 1;   /* enable logic op */
-   cc_state->cc3.ia_blend_enable = 1;  /* blend alpha just like colors */
-   cc_state->cc3.blend_enable = 0;     /* disable color blend */
-   cc_state->cc3.alpha_test = 0;       /* disable alpha test */
-   cc_state->cc4.cc_viewport_state_offset = (state_base_offset + cc_viewport_offset) >> 5;
-   cc_state->cc5.dither_enable = 0;    /* disable dither */
-   cc_state->cc5.logicop_func = 0xc;   /* WHITE */
-   cc_state->cc5.statistics_enable = 1;
-   cc_state->cc5.ia_blend_function = BRW_BLENDFUNCTION_ADD;
-   cc_state->cc5.ia_src_blend_factor = BRW_BLENDFACTOR_ONE;
-   cc_state->cc5.ia_dest_blend_factor = BRW_BLENDFACTOR_ONE;
-
-   /* Upload system kernel */
-   memcpy (sip_kernel, sip_kernel_static, sizeof (sip_kernel_static));
-   
-   /* Set up the state buffer for the destination surface */
-   memset(dest_surf_state, 0, sizeof(*dest_surf_state));
-   dest_surf_state->ss0.surface_type = BRW_SURFACE_2D;
-   dest_surf_state->ss0.data_return_format = BRW_SURFACERETURNFORMAT_FLOAT32;
-   if (pI830->cpp == 2) {
-      dest_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B5G6R5_UNORM;
-   } else {
-      dest_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
-   }
-   dest_surf_state->ss0.writedisable_alpha = 0;
-   dest_surf_state->ss0.writedisable_red = 0;
-   dest_surf_state->ss0.writedisable_green = 0;
-   dest_surf_state->ss0.writedisable_blue = 0;
-   dest_surf_state->ss0.color_blend = 1;
-   dest_surf_state->ss0.vert_line_stride = 0;
-   dest_surf_state->ss0.vert_line_stride_ofs = 0;
-   dest_surf_state->ss0.mipmap_layout_mode = 0;
-   dest_surf_state->ss0.render_cache_read_mode = 0;
-   
-   dest_surf_state->ss1.base_addr = pI830->FrontBuffer.Start;
-   dest_surf_state->ss2.height = pScrn->virtualY - 1;
-   dest_surf_state->ss2.width = pScrn->virtualX - 1;
-   dest_surf_state->ss2.mip_count = 0;
-   dest_surf_state->ss2.render_target_rotation = 0;
-   dest_surf_state->ss3.pitch = (pI830->displayWidth * pI830->cpp) - 1;
-
-   /* Set up the source surface state buffer */
-   memset(src_surf_state, 0, sizeof(*src_surf_state));
-   src_surf_state->ss0.surface_type = BRW_SURFACE_2D;
-/*   src_surf_state->ss0.data_return_format = BRW_SURFACERETURNFORMAT_FLOAT32; */
-   switch (id) {
-   case FOURCC_YUY2:
-      src_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_YCRCB_NORMAL;
-      break;
-   case FOURCC_UYVY:
-      src_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_YCRCB_SWAPY;
-      break;
-   }
-   src_surf_state->ss0.writedisable_alpha = 0;
-   src_surf_state->ss0.writedisable_red = 0;
-   src_surf_state->ss0.writedisable_green = 0;
-   src_surf_state->ss0.writedisable_blue = 0;
-   src_surf_state->ss0.color_blend = 1;
-   src_surf_state->ss0.vert_line_stride = 0;
-   src_surf_state->ss0.vert_line_stride_ofs = 0;
-   src_surf_state->ss0.mipmap_layout_mode = 0;
-   src_surf_state->ss0.render_cache_read_mode = 0;
-   
-   src_surf_state->ss1.base_addr = pPriv->YBuf0offset;
-   src_surf_state->ss2.width = width - 1;
-   src_surf_state->ss2.height = height - 1;
-   src_surf_state->ss2.mip_count = 0;
-   src_surf_state->ss2.render_target_rotation = 0;
-   src_surf_state->ss3.pitch = video_pitch - 1;
-
-   /* Set up a binding table for our two surfaces.  Only the PS will use it */
-   /* XXX: are these offset from the right place? */
-   binding_table[0] = state_base_offset + dest_surf_offset;
-   binding_table[1] = state_base_offset + src_surf_offset;
-
-   /* Set up the packed YUV source sampler.  Doesn't do colorspace conversion.
-    */
-   memset(src_sampler_state, 0, sizeof(*src_sampler_state));
-   src_sampler_state->ss0.min_filter = BRW_MAPFILTER_LINEAR;
-   src_sampler_state->ss0.mag_filter = BRW_MAPFILTER_LINEAR;
-   src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
-   src_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
-   src_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
-
-   /* Set up the vertex shader to be disabled (passthrough) */
-   memset(vs_state, 0, sizeof(*vs_state));
-   vs_state->thread4.nr_urb_entries = URB_VS_ENTRIES;
-   vs_state->thread4.urb_entry_allocation_size = URB_VS_ENTRY_SIZE - 1;
-   vs_state->vs6.vs_enable = 0;
-   vs_state->vs6.vert_cache_disable = 1;
-
-   /* Set up the SF kernel to do coord interp: for each attribute,
-    * calculate dA/dx and dA/dy.  Hand these interpolation coefficients
-    * back to SF which then hands pixels off to WM.
-    */
-
-   memcpy (sf_kernel, sf_kernel_static, sizeof (sf_kernel_static));
-   memset(sf_state, 0, sizeof(*sf_state));
-#if 0
-   ErrorF ("sf kernel: 0x%08x\n", state_base_offset + sf_kernel_offset);
-#endif
-   sf_state->thread0.kernel_start_pointer = 
-	       (state_base_offset + sf_kernel_offset) >> 6;
-   sf_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(SF_KERNEL_NUM_GRF);
-   sf_state->sf1.single_program_flow = 1; /* XXX */
-   sf_state->sf1.binding_table_entry_count = 0;
-   sf_state->sf1.thread_priority = 0;
-   sf_state->sf1.floating_point_mode = 0; /* Mesa does this */
-   sf_state->sf1.illegal_op_exception_enable = 1;
-   sf_state->sf1.mask_stack_exception_enable = 1;
-   sf_state->sf1.sw_exception_enable = 1;
-   sf_state->thread2.per_thread_scratch_space = 0;
-   sf_state->thread2.scratch_space_base_pointer = 0; /* not used in our kernel */
-   sf_state->thread3.const_urb_entry_read_length = 0; /* no const URBs */
-   sf_state->thread3.const_urb_entry_read_offset = 0; /* no const URBs */
-   sf_state->thread3.urb_entry_read_length = 1; /* 1 URB per vertex */
-   sf_state->thread3.urb_entry_read_offset = 0;
-   sf_state->thread3.dispatch_grf_start_reg = 3;
-   sf_state->thread4.max_threads = SF_MAX_THREADS - 1;
-   sf_state->thread4.urb_entry_allocation_size = URB_SF_ENTRY_SIZE - 1;
-   sf_state->thread4.nr_urb_entries = URB_SF_ENTRIES;
-   sf_state->thread4.stats_enable = 1;
-   sf_state->sf5.viewport_transform = FALSE; /* skip viewport */
-   sf_state->sf6.cull_mode = BRW_CULLMODE_NONE;
-   sf_state->sf6.scissor = 0;
-   sf_state->sf7.trifan_pv = 2;
-   sf_state->sf6.dest_org_vbias = 0x8;
-   sf_state->sf6.dest_org_hbias = 0x8;
-
-   memcpy (ps_kernel, ps_kernel_static, sizeof (ps_kernel_static));
-#if 0
-   ErrorF ("ps kernel: 0x%08x\n", state_base_offset + ps_kernel_offset);
-#endif
-   memset (wm_state, 0, sizeof (*wm_state));
-   wm_state->thread0.kernel_start_pointer = 
-	    (state_base_offset + ps_kernel_offset) >> 6;
-   wm_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(PS_KERNEL_NUM_GRF);
-   wm_state->thread1.single_program_flow = 1; /* XXX */
-   wm_state->thread1.binding_table_entry_count = 2;
-   /* Though we never use the scratch space in our WM kernel, it has to be
-    * set, and the minimum allocation is 1024 bytes.
-    */
-   wm_state->thread2.scratch_space_base_pointer = (state_base_offset +
-						   wm_scratch_offset) >> 10;
-   wm_state->thread2.per_thread_scratch_space = 0; /* 1024 bytes */
-   wm_state->thread3.dispatch_grf_start_reg = 3; /* XXX */
-   wm_state->thread3.const_urb_entry_read_length = 0;
-   wm_state->thread3.const_urb_entry_read_offset = 0;
-   wm_state->thread3.urb_entry_read_length = 1; /* XXX */
-   wm_state->thread3.urb_entry_read_offset = 0; /* XXX */
-   wm_state->wm4.stats_enable = 1;
-   wm_state->wm4.sampler_state_pointer = (state_base_offset + src_sampler_offset) >> 5;
-   wm_state->wm4.sampler_count = 1; /* 1-4 samplers used */
-   wm_state->wm5.max_threads = PS_MAX_THREADS - 1;
-   wm_state->wm5.thread_dispatch_enable = 1;
-   wm_state->wm5.enable_16_pix = 1;
-   wm_state->wm5.enable_8_pix = 0;
-   wm_state->wm5.early_depth_test = 1;
-
-   {
-      BEGIN_LP_RING(2);
-      OUT_RING(MI_FLUSH | 
-	       MI_STATE_INSTRUCTION_CACHE_FLUSH |
-	       BRW_MI_GLOBAL_SNAPSHOT_RESET);
-      OUT_RING(MI_NOOP);
-      ADVANCE_LP_RING();
-   }
-   
-/*    brw_debug (pScrn, "before base address modify"); */
-   { BEGIN_LP_RING(12);
-   /* Match Mesa driver setup */
-   OUT_RING(BRW_PIPELINE_SELECT | PIPELINE_SELECT_3D);
-
-   /* Mesa does this. Who knows... */
-   OUT_RING(BRW_CS_URB_STATE | 0);
-   OUT_RING((0 << 4) |	/* URB Entry Allocation Size */
-	    (0 << 0));	/* Number of URB Entries */
-   
-   /* Zero out the two base address registers so all offsets are absolute */
-   OUT_RING(BRW_STATE_BASE_ADDRESS | 4);
-   OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* Generate state base address */
-   OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* Surface state base address */
-   OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* media base addr, don't care */
-   OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY);  /* general state max addr, disabled */
-   OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY);  /* media object state max addr, disabled */
-
-   /* Set system instruction pointer */
-   OUT_RING(BRW_STATE_SIP | 0);
-   OUT_RING(state_base_offset + sip_kernel_offset); /* system instruction pointer */
-      
-   OUT_RING(MI_NOOP);
-   ADVANCE_LP_RING(); }
-   
-/*   brw_debug (pScrn, "after base address modify"); */
-
-   { BEGIN_LP_RING(42);
-   /* Enable VF statistics */
-   OUT_RING(BRW_3DSTATE_VF_STATISTICS | 1);
-   
-   /* Pipe control */
-   OUT_RING(BRW_PIPE_CONTROL |
-	    BRW_PIPE_CONTROL_NOWRITE |
-	    BRW_PIPE_CONTROL_IS_FLUSH |
-	    2);
-   OUT_RING(0);			       /* Destination address */
-   OUT_RING(0);			       /* Immediate data low DW */
-   OUT_RING(0);			       /* Immediate data high DW */
-
-   /* Binding table pointers */
-   OUT_RING(BRW_3DSTATE_BINDING_TABLE_POINTERS | 4);
-   OUT_RING(0); /* vs */
-   OUT_RING(0); /* gs */
-   OUT_RING(0); /* clip */
-   OUT_RING(0); /* sf */
-   /* Only the PS uses the binding table */
-   OUT_RING(state_base_offset + binding_table_offset); /* ps */
-   
-   /* Blend constant color (magenta is fun) */
-   OUT_RING(BRW_3DSTATE_CONSTANT_COLOR | 3);
-   OUT_RING(float_to_uint (1.0));
-   OUT_RING(float_to_uint (0.0));
-   OUT_RING(float_to_uint (1.0));
-   OUT_RING(float_to_uint (1.0));
-   
-   /* The drawing rectangle clipping is always on.  Set it to values that
-    * shouldn't do any clipping.
-    */
-   OUT_RING(BRW_3DSTATE_DRAWING_RECTANGLE | 2);	/* XXX 3 for BLC or CTG */
-   OUT_RING(0x00000000);	/* ymin, xmin */
-   OUT_RING((pScrn->virtualX - 1) |
-	    (pScrn->virtualY - 1) << 16); /* ymax, xmax */
-   OUT_RING(0x00000000);	/* yorigin, xorigin */
-
-   /* skip the depth buffer */
-   /* skip the polygon stipple */
-   /* skip the polygon stipple offset */
-   /* skip the line stipple */
-   
-   /* Set the pointers to the 3d pipeline state */
-   OUT_RING(BRW_3DSTATE_PIPELINED_POINTERS | 5);
-   OUT_RING(state_base_offset + vs_offset);  /* 32 byte aligned */
-   OUT_RING(BRW_GS_DISABLE);		     /* disable GS, resulting in passthrough */
-   OUT_RING(BRW_CLIP_DISABLE);		     /* disable CLIP, resulting in passthrough */
-   OUT_RING(state_base_offset + sf_offset);  /* 32 byte aligned */
-   OUT_RING(state_base_offset + wm_offset);  /* 32 byte aligned */
-   OUT_RING(state_base_offset + cc_offset);  /* 64 byte aligned */
-
-   /* URB fence */
-   OUT_RING(BRW_URB_FENCE |
-	    UF0_CS_REALLOC |
-	    UF0_SF_REALLOC |
-	    UF0_CLIP_REALLOC |
-	    UF0_GS_REALLOC |
-	    UF0_VS_REALLOC |
-	    1);
-   OUT_RING(((urb_clip_start + urb_clip_size) << UF1_CLIP_FENCE_SHIFT) |
-	    ((urb_gs_start + urb_gs_size) << UF1_GS_FENCE_SHIFT) |
-	    ((urb_vs_start + urb_vs_size) << UF1_VS_FENCE_SHIFT));
-   OUT_RING(((urb_cs_start + urb_cs_size) << UF2_CS_FENCE_SHIFT) |
-	    ((urb_sf_start + urb_sf_size) << UF2_SF_FENCE_SHIFT));
-
-   /* Constant buffer state */
-   OUT_RING(BRW_CS_URB_STATE | 0);
-   OUT_RING(((URB_CS_ENTRY_SIZE - 1) << 4) | /* URB Entry Allocation Size */
-	    (URB_CS_ENTRIES << 0));	     /* Number of URB Entries */
-   
-   /* Set up the pointer to our vertex buffer */
-   OUT_RING(BRW_3DSTATE_VERTEX_BUFFERS | 2);
-   OUT_RING((0 << VB0_BUFFER_INDEX_SHIFT) |
-	    VB0_VERTEXDATA |
-	    ((4 * 4) << VB0_BUFFER_PITCH_SHIFT)); /* four 32-bit floats per vertex */
-   OUT_RING(state_base_offset + vb_offset);
-   OUT_RING(3); /* four corners to our rectangle */
-
-   /* Set up our vertex elements, sourced from the single vertex buffer. */
-   OUT_RING(BRW_3DSTATE_VERTEX_ELEMENTS | 3);
-   /* offset 0: X,Y -> {X, Y, 1.0, 1.0} */
-   OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
-	    VE0_VALID |
-	    (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
-	    (0 << VE0_OFFSET_SHIFT));
-   OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
-	    (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
-	    (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
-	    (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
-	    (0 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
-   /* offset 8: S0, T0 -> {S0, T0, 1.0, 1.0} */
-   OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
-	    VE0_VALID |
-	    (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
-	    (8 << VE0_OFFSET_SHIFT));
-   OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
-	    (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
-	    (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
-	    (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
-	    (4 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
-
-   OUT_RING(MI_NOOP);			/* pad to quadword */
-   ADVANCE_LP_RING(); }
-
-   dxo = dstRegion->extents.x1;
-   dyo = dstRegion->extents.y1;
-
-   pbox = REGION_RECTS(dstRegion);
-   nbox = REGION_NUM_RECTS(dstRegion);
-   while (nbox--)
-   {
-      int box_x1 = pbox->x1;
-      int box_y1 = pbox->y1;
-      int box_x2 = pbox->x2;
-      int box_y2 = pbox->y2;
-      int i;
-      float src_scale_x, src_scale_y;
-
-      if (!first_output) {
-	 /* Since we use the same little vertex buffer over and over, sync for
-	  * subsequent rectangles.
-	  */
-	 if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
-	    (*pI830->AccelInfoRec->Sync)(pScrn);
-	    pI830->AccelInfoRec->NeedToSync = FALSE;
-	 }
-      }
-
-      pbox++;
-
-      /* Use normalized texture coordinates */
-      src_scale_x = (float)1.0 / (float)drw_w;
-      src_scale_y  = (float)1.0 / (float)drw_h;
-
-      i = 0;
-      vb[i++] = (box_x2 - dxo) * src_scale_x;
-      vb[i++] = (box_y2 - dyo) * src_scale_y;
-      vb[i++] = (float) box_x2;
-      vb[i++] = (float) box_y2;
-
-      vb[i++] = (box_x1 - dxo) * src_scale_x;
-      vb[i++] = (box_y2 - dyo) * src_scale_y;
-      vb[i++] = (float) box_x1;
-      vb[i++] = (float) box_y2;
-
-      vb[i++] = (box_x1 - dxo) * src_scale_x;
-      vb[i++] = (box_y1 - dyo) * src_scale_y;
-      vb[i++] = (float) box_x1;
-      vb[i++] = (float) box_y1;
-
-#if 0
-      ErrorF ("before EU_ATT 0x%08x%08x EU_ATT_DATA 0x%08x%08x\n",
-	      INREG(BRW_EU_ATT_1), INREG(BRW_EU_ATT_0),
-	      INREG(BRW_EU_ATT_DATA_1), INREG(BRW_EU_ATT_DATA_0));
-
-      OUTREG(BRW_VF_CTL,
-	     BRW_VF_CTL_SNAPSHOT_MUX_SELECT_THREADID |
-	     BRW_VF_CTL_SNAPSHOT_TYPE_VERTEX_INDEX |
-	     BRW_VF_CTL_SNAPSHOT_ENABLE);
-      OUTREG(BRW_VF_STRG_VAL, 0);
-#endif
-      
-#if 0
-      OUTREG(BRW_VS_CTL,
-	     BRW_VS_CTL_SNAPSHOT_ALL_THREADS |
-	     BRW_VS_CTL_SNAPSHOT_MUX_VALID_COUNT |
-	     BRW_VS_CTL_THREAD_SNAPSHOT_ENABLE);
-      
-      OUTREG(BRW_VS_STRG_VAL, 0);
+
+    urb_vs_start = 0;
+    urb_vs_size = URB_VS_ENTRIES * URB_VS_ENTRY_SIZE;
+    urb_gs_start = urb_vs_start + urb_vs_size;
+    urb_gs_size = URB_GS_ENTRIES * URB_GS_ENTRY_SIZE;
+    urb_clip_start = urb_gs_start + urb_gs_size;
+    urb_clip_size = URB_CLIP_ENTRIES * URB_CLIP_ENTRY_SIZE;
+    urb_sf_start = urb_clip_start + urb_clip_size;
+    urb_sf_size = URB_SF_ENTRIES * URB_SF_ENTRY_SIZE;
+    urb_cs_start = urb_sf_start + urb_sf_size;
+    urb_cs_size = URB_CS_ENTRIES * URB_CS_ENTRY_SIZE;
+
+    /* We'll be poking the state buffers that could be in use by the 3d
+     * hardware here, but we should have synced the 3D engine already in
+     * I830PutImage.
+     */
+
+    memset (cc_viewport, 0, sizeof (*cc_viewport));
+    cc_viewport->min_depth = -1.e35;
+    cc_viewport->max_depth = 1.e35;
+
+    /* Color calculator state */
+    memset(cc_state, 0, sizeof(*cc_state));
+    cc_state->cc0.stencil_enable = 0;   /* disable stencil */
+    cc_state->cc2.depth_test = 0;       /* disable depth test */
+    cc_state->cc2.logicop_enable = 1;   /* enable logic op */
+    cc_state->cc3.ia_blend_enable = 1;  /* blend alpha just like colors */
+    cc_state->cc3.blend_enable = 0;     /* disable color blend */
+    cc_state->cc3.alpha_test = 0;       /* disable alpha test */
+    cc_state->cc4.cc_viewport_state_offset = (state_base_offset +
+					      cc_viewport_offset) >> 5;
+    cc_state->cc5.dither_enable = 0;    /* disable dither */
+    cc_state->cc5.logicop_func = 0xc;   /* WHITE */
+    cc_state->cc5.statistics_enable = 1;
+    cc_state->cc5.ia_blend_function = BRW_BLENDFUNCTION_ADD;
+    cc_state->cc5.ia_src_blend_factor = BRW_BLENDFACTOR_ONE;
+    cc_state->cc5.ia_dest_blend_factor = BRW_BLENDFACTOR_ONE;
+
+    /* Upload system kernel */
+    memcpy (sip_kernel, sip_kernel_static, sizeof (sip_kernel_static));
+
+    /* Set up the state buffer for the destination surface */
+    memset(dest_surf_state, 0, sizeof(*dest_surf_state));
+    dest_surf_state->ss0.surface_type = BRW_SURFACE_2D;
+    dest_surf_state->ss0.data_return_format = BRW_SURFACERETURNFORMAT_FLOAT32;
+    if (pI830->cpp == 2) {
+	dest_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B5G6R5_UNORM;
+    } else {
+	dest_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
+    }
+    dest_surf_state->ss0.writedisable_alpha = 0;
+    dest_surf_state->ss0.writedisable_red = 0;
+    dest_surf_state->ss0.writedisable_green = 0;
+    dest_surf_state->ss0.writedisable_blue = 0;
+    dest_surf_state->ss0.color_blend = 1;
+    dest_surf_state->ss0.vert_line_stride = 0;
+    dest_surf_state->ss0.vert_line_stride_ofs = 0;
+    dest_surf_state->ss0.mipmap_layout_mode = 0;
+    dest_surf_state->ss0.render_cache_read_mode = 0;
+
+    dest_surf_state->ss1.base_addr = pI830->FrontBuffer.Start;
+    dest_surf_state->ss2.height = pScrn->virtualY - 1;
+    dest_surf_state->ss2.width = pScrn->virtualX - 1;
+    dest_surf_state->ss2.mip_count = 0;
+    dest_surf_state->ss2.render_target_rotation = 0;
+    dest_surf_state->ss3.pitch = (pI830->displayWidth * pI830->cpp) - 1;
+
+    /* Set up the source surface state buffer */
+    memset(src_surf_state, 0, sizeof(*src_surf_state));
+    src_surf_state->ss0.surface_type = BRW_SURFACE_2D;
+    /* src_surf_state->ss0.data_return_format =
+       BRW_SURFACERETURNFORMAT_FLOAT32; */
+    switch (id) {
+    case FOURCC_YUY2:
+	src_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_YCRCB_NORMAL;
+	break;
+    case FOURCC_UYVY:
+	src_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_YCRCB_SWAPY;
+	break;
+    }
+    src_surf_state->ss0.writedisable_alpha = 0;
+    src_surf_state->ss0.writedisable_red = 0;
+    src_surf_state->ss0.writedisable_green = 0;
+    src_surf_state->ss0.writedisable_blue = 0;
+    src_surf_state->ss0.color_blend = 1;
+    src_surf_state->ss0.vert_line_stride = 0;
+    src_surf_state->ss0.vert_line_stride_ofs = 0;
+    src_surf_state->ss0.mipmap_layout_mode = 0;
+    src_surf_state->ss0.render_cache_read_mode = 0;
+
+    src_surf_state->ss1.base_addr = pPriv->YBuf0offset;
+    src_surf_state->ss2.width = width - 1;
+    src_surf_state->ss2.height = height - 1;
+    src_surf_state->ss2.mip_count = 0;
+    src_surf_state->ss2.render_target_rotation = 0;
+    src_surf_state->ss3.pitch = video_pitch - 1;
+
+    /* Set up a binding table for our two surfaces.  Only the PS will use it */
+    /* XXX: are these offset from the right place? */
+    binding_table[0] = state_base_offset + dest_surf_offset;
+    binding_table[1] = state_base_offset + src_surf_offset;
+
+    /* Set up the packed YUV source sampler.  Doesn't do colorspace conversion.
+     */
+    memset(src_sampler_state, 0, sizeof(*src_sampler_state));
+    src_sampler_state->ss0.min_filter = BRW_MAPFILTER_LINEAR;
+    src_sampler_state->ss0.mag_filter = BRW_MAPFILTER_LINEAR;
+    src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
+    src_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
+    src_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
+
+    /* Set up the vertex shader to be disabled (passthrough) */
+    memset(vs_state, 0, sizeof(*vs_state));
+    vs_state->thread4.nr_urb_entries = URB_VS_ENTRIES;
+    vs_state->thread4.urb_entry_allocation_size = URB_VS_ENTRY_SIZE - 1;
+    vs_state->vs6.vs_enable = 0;
+    vs_state->vs6.vert_cache_disable = 1;
+
+    /* Set up the SF kernel to do coord interp: for each attribute,
+     * calculate dA/dx and dA/dy.  Hand these interpolation coefficients
+     * back to SF which then hands pixels off to WM.
+     */
+
+    memcpy (sf_kernel, sf_kernel_static, sizeof (sf_kernel_static));
+    memset(sf_state, 0, sizeof(*sf_state));
+#if 0
+    ErrorF ("sf kernel: 0x%08x\n", state_base_offset + sf_kernel_offset);
+#endif
+    sf_state->thread0.kernel_start_pointer =
+	(state_base_offset + sf_kernel_offset) >> 6;
+    sf_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(SF_KERNEL_NUM_GRF);
+    sf_state->sf1.single_program_flow = 1; /* XXX */
+    sf_state->sf1.binding_table_entry_count = 0;
+    sf_state->sf1.thread_priority = 0;
+    sf_state->sf1.floating_point_mode = 0; /* Mesa does this */
+    sf_state->sf1.illegal_op_exception_enable = 1;
+    sf_state->sf1.mask_stack_exception_enable = 1;
+    sf_state->sf1.sw_exception_enable = 1;
+    sf_state->thread2.per_thread_scratch_space = 0;
+    /* scratch space is not used in our kernel */
+    sf_state->thread2.scratch_space_base_pointer = 0;
+    sf_state->thread3.const_urb_entry_read_length = 0; /* no const URBs */
+    sf_state->thread3.const_urb_entry_read_offset = 0; /* no const URBs */
+    sf_state->thread3.urb_entry_read_length = 1; /* 1 URB per vertex */
+    sf_state->thread3.urb_entry_read_offset = 0;
+    sf_state->thread3.dispatch_grf_start_reg = 3;
+    sf_state->thread4.max_threads = SF_MAX_THREADS - 1;
+    sf_state->thread4.urb_entry_allocation_size = URB_SF_ENTRY_SIZE - 1;
+    sf_state->thread4.nr_urb_entries = URB_SF_ENTRIES;
+    sf_state->thread4.stats_enable = 1;
+    sf_state->sf5.viewport_transform = FALSE; /* skip viewport */
+    sf_state->sf6.cull_mode = BRW_CULLMODE_NONE;
+    sf_state->sf6.scissor = 0;
+    sf_state->sf7.trifan_pv = 2;
+    sf_state->sf6.dest_org_vbias = 0x8;
+    sf_state->sf6.dest_org_hbias = 0x8;
+
+    memcpy (ps_kernel, ps_kernel_static, sizeof (ps_kernel_static));
+#if 0
+    ErrorF ("ps kernel: 0x%08x\n", state_base_offset + ps_kernel_offset);
+#endif
+    memset (wm_state, 0, sizeof (*wm_state));
+    wm_state->thread0.kernel_start_pointer =
+	(state_base_offset + ps_kernel_offset) >> 6;
+    wm_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(PS_KERNEL_NUM_GRF);
+    wm_state->thread1.single_program_flow = 1; /* XXX */
+    wm_state->thread1.binding_table_entry_count = 2;
+    /* Though we never use the scratch space in our WM kernel, it has to be
+     * set, and the minimum allocation is 1024 bytes.
+     */
+    wm_state->thread2.scratch_space_base_pointer = (state_base_offset +
+						    wm_scratch_offset) >> 10;
+    wm_state->thread2.per_thread_scratch_space = 0; /* 1024 bytes */
+    wm_state->thread3.dispatch_grf_start_reg = 3; /* XXX */
+    wm_state->thread3.const_urb_entry_read_length = 0;
+    wm_state->thread3.const_urb_entry_read_offset = 0;
+    wm_state->thread3.urb_entry_read_length = 1; /* XXX */
+    wm_state->thread3.urb_entry_read_offset = 0; /* XXX */
+    wm_state->wm4.stats_enable = 1;
+    wm_state->wm4.sampler_state_pointer = (state_base_offset +
+					   src_sampler_offset) >> 5;
+    wm_state->wm4.sampler_count = 1; /* 1-4 samplers used */
+    wm_state->wm5.max_threads = PS_MAX_THREADS - 1;
+    wm_state->wm5.thread_dispatch_enable = 1;
+    wm_state->wm5.enable_16_pix = 1;
+    wm_state->wm5.enable_8_pix = 0;
+    wm_state->wm5.early_depth_test = 1;
+
+    {
+	BEGIN_LP_RING(2);
+	OUT_RING(MI_FLUSH |
+		 MI_STATE_INSTRUCTION_CACHE_FLUSH |
+		 BRW_MI_GLOBAL_SNAPSHOT_RESET);
+	OUT_RING(MI_NOOP);
+	ADVANCE_LP_RING();
+    }
+
+    /* brw_debug (pScrn, "before base address modify"); */
+    {
+	BEGIN_LP_RING(12);
+	/* Match Mesa driver setup */
+	OUT_RING(BRW_PIPELINE_SELECT | PIPELINE_SELECT_3D);
+
+	/* Mesa does this. Who knows... */
+	OUT_RING(BRW_CS_URB_STATE | 0);
+	OUT_RING((0 << 4) |	/* URB Entry Allocation Size */
+		 (0 << 0));	/* Number of URB Entries */
+
+	/* Zero out the two base address registers so all offsets are
+	 * absolute
+	 */
+	OUT_RING(BRW_STATE_BASE_ADDRESS | 4);
+	OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* Generate state base address */
+	OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* Surface state base address */
+	OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* media base addr, don't care */
+	/* general state max addr, disabled */
+	OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY);
+	/* media object state max addr, disabled */
+	OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY);
+
+	/* Set system instruction pointer */
+	OUT_RING(BRW_STATE_SIP | 0);
+	/* system instruction pointer */
+	OUT_RING(state_base_offset + sip_kernel_offset);
+
+	OUT_RING(MI_NOOP);
+	ADVANCE_LP_RING();
+    }
+
+    /* brw_debug (pScrn, "after base address modify"); */
+
+    {
+       BEGIN_LP_RING(42);
+       /* Enable VF statistics */
+       OUT_RING(BRW_3DSTATE_VF_STATISTICS | 1);
+
+       /* Pipe control */
+       OUT_RING(BRW_PIPE_CONTROL |
+		BRW_PIPE_CONTROL_NOWRITE |
+		BRW_PIPE_CONTROL_IS_FLUSH |
+		2);
+       OUT_RING(0);			/* Destination address */
+       OUT_RING(0);			/* Immediate data low DW */
+       OUT_RING(0);			/* Immediate data high DW */
+
+       /* Binding table pointers */
+       OUT_RING(BRW_3DSTATE_BINDING_TABLE_POINTERS | 4);
+       OUT_RING(0); /* vs */
+       OUT_RING(0); /* gs */
+       OUT_RING(0); /* clip */
+       OUT_RING(0); /* sf */
+       /* Only the PS uses the binding table */
+       OUT_RING(state_base_offset + binding_table_offset); /* ps */
+
+       /* Blend constant color (magenta is fun) */
+       OUT_RING(BRW_3DSTATE_CONSTANT_COLOR | 3);
+       OUT_RING(float_to_uint (1.0));
+       OUT_RING(float_to_uint (0.0));
+       OUT_RING(float_to_uint (1.0));
+       OUT_RING(float_to_uint (1.0));
+
+       /* The drawing rectangle clipping is always on.  Set it to values that
+	* shouldn't do any clipping.
+	*/
+       OUT_RING(BRW_3DSTATE_DRAWING_RECTANGLE | 2); /* XXX 3 for BLC or CTG */
+       OUT_RING(0x00000000);			/* ymin, xmin */
+       OUT_RING((pScrn->virtualX - 1) |
+		(pScrn->virtualY - 1) << 16);	/* ymax, xmax */
+       OUT_RING(0x00000000);			/* yorigin, xorigin */
+
+       /* skip the depth buffer */
+       /* skip the polygon stipple */
+       /* skip the polygon stipple offset */
+       /* skip the line stipple */
+
+       /* Set the pointers to the 3d pipeline state */
+       OUT_RING(BRW_3DSTATE_PIPELINED_POINTERS | 5);
+       OUT_RING(state_base_offset + vs_offset);  /* 32 byte aligned */
+       /* disable GS, resulting in passthrough */
+       OUT_RING(BRW_GS_DISABLE);
+       /* disable CLIP, resulting in passthrough */
+       OUT_RING(BRW_CLIP_DISABLE);
+       OUT_RING(state_base_offset + sf_offset);  /* 32 byte aligned */
+       OUT_RING(state_base_offset + wm_offset);  /* 32 byte aligned */
+       OUT_RING(state_base_offset + cc_offset);  /* 64 byte aligned */
+
+       /* URB fence */
+       OUT_RING(BRW_URB_FENCE |
+		UF0_CS_REALLOC |
+		UF0_SF_REALLOC |
+		UF0_CLIP_REALLOC |
+		UF0_GS_REALLOC |
+		UF0_VS_REALLOC |
+		1);
+       OUT_RING(((urb_clip_start + urb_clip_size) << UF1_CLIP_FENCE_SHIFT) |
+		((urb_gs_start + urb_gs_size) << UF1_GS_FENCE_SHIFT) |
+		((urb_vs_start + urb_vs_size) << UF1_VS_FENCE_SHIFT));
+       OUT_RING(((urb_cs_start + urb_cs_size) << UF2_CS_FENCE_SHIFT) |
+		((urb_sf_start + urb_sf_size) << UF2_SF_FENCE_SHIFT));
+
+       /* Constant buffer state */
+       OUT_RING(BRW_CS_URB_STATE | 0);
+       OUT_RING(((URB_CS_ENTRY_SIZE - 1) << 4) |
+		(URB_CS_ENTRIES << 0));
+
+       /* Set up the pointer to our vertex buffer */
+       OUT_RING(BRW_3DSTATE_VERTEX_BUFFERS | 2);
+       /* four 32-bit floats per vertex */
+       OUT_RING((0 << VB0_BUFFER_INDEX_SHIFT) |
+		VB0_VERTEXDATA |
+		((4 * 4) << VB0_BUFFER_PITCH_SHIFT));
+       OUT_RING(state_base_offset + vb_offset);
+       OUT_RING(3); /* four corners to our rectangle */
+
+       /* Set up our vertex elements, sourced from the single vertex buffer. */
+       OUT_RING(BRW_3DSTATE_VERTEX_ELEMENTS | 3);
+       /* offset 0: X,Y -> {X, Y, 1.0, 1.0} */
+       OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
+		VE0_VALID |
+		(BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
+		(0 << VE0_OFFSET_SHIFT));
+       OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
+		(BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
+		(BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
+		(BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
+		(0 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
+       /* offset 8: S0, T0 -> {S0, T0, 1.0, 1.0} */
+       OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
+		VE0_VALID |
+		(BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
+		(8 << VE0_OFFSET_SHIFT));
+       OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
+		(BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
+		(BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
+		(BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
+		(4 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
+
+       OUT_RING(MI_NOOP);			/* pad to quadword */
+       ADVANCE_LP_RING();
+    }
+
+    dxo = dstRegion->extents.x1;
+    dyo = dstRegion->extents.y1;
+
+    pbox = REGION_RECTS(dstRegion);
+    nbox = REGION_NUM_RECTS(dstRegion);
+    while (nbox--) {
+	int box_x1 = pbox->x1;
+	int box_y1 = pbox->y1;
+	int box_x2 = pbox->x2;
+	int box_y2 = pbox->y2;
+	int i;
+	float src_scale_x, src_scale_y;
+
+	if (!first_output) {
+	    /* Since we use the same little vertex buffer over and over, sync
+	     * for subsequent rectangles.
+	     */
+	    if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
+		(*pI830->AccelInfoRec->Sync)(pScrn);
+		pI830->AccelInfoRec->NeedToSync = FALSE;
+	    }
+	}
+
+	pbox++;
+
+	/* Use normalized texture coordinates */
+	src_scale_x = (float)1.0 / (float)drw_w;
+	src_scale_y = (float)1.0 / (float)drw_h;
+
+	i = 0;
+	vb[i++] = (box_x2 - dxo) * src_scale_x;
+	vb[i++] = (box_y2 - dyo) * src_scale_y;
+	vb[i++] = (float) box_x2;
+	vb[i++] = (float) box_y2;
+
+	vb[i++] = (box_x1 - dxo) * src_scale_x;
+	vb[i++] = (box_y2 - dyo) * src_scale_y;
+	vb[i++] = (float) box_x1;
+	vb[i++] = (float) box_y2;
+
+	vb[i++] = (box_x1 - dxo) * src_scale_x;
+	vb[i++] = (box_y1 - dyo) * src_scale_y;
+	vb[i++] = (float) box_x1;
+	vb[i++] = (float) box_y1;
+
+#if 0
+	ErrorF ("before EU_ATT 0x%08x%08x EU_ATT_DATA 0x%08x%08x\n",
+		INREG(BRW_EU_ATT_1), INREG(BRW_EU_ATT_0),
+		INREG(BRW_EU_ATT_DATA_1), INREG(BRW_EU_ATT_DATA_0));
+
+	OUTREG(BRW_VF_CTL,
+	       BRW_VF_CTL_SNAPSHOT_MUX_SELECT_THREADID |
+	       BRW_VF_CTL_SNAPSHOT_TYPE_VERTEX_INDEX |
+	       BRW_VF_CTL_SNAPSHOT_ENABLE);
+	OUTREG(BRW_VF_STRG_VAL, 0);
+#endif
+
+#if 0
+	OUTREG(BRW_VS_CTL,
+	       BRW_VS_CTL_SNAPSHOT_ALL_THREADS |
+	       BRW_VS_CTL_SNAPSHOT_MUX_VALID_COUNT |
+	       BRW_VS_CTL_THREAD_SNAPSHOT_ENABLE);
+
+	OUTREG(BRW_VS_STRG_VAL, 0);
 #endif
-      
+
 #if WATCH_SF
-      OUTREG(BRW_SF_CTL,
-	     BRW_SF_CTL_SNAPSHOT_MUX_VERTEX_COUNT |
-	     BRW_SF_CTL_SNAPSHOT_ALL_THREADS |
-	     BRW_SF_CTL_THREAD_SNAPSHOT_ENABLE);
-      OUTREG(BRW_SF_STRG_VAL, 0);
+	OUTREG(BRW_SF_CTL,
+	       BRW_SF_CTL_SNAPSHOT_MUX_VERTEX_COUNT |
+	       BRW_SF_CTL_SNAPSHOT_ALL_THREADS |
+	       BRW_SF_CTL_THREAD_SNAPSHOT_ENABLE);
+	OUTREG(BRW_SF_STRG_VAL, 0);
 #endif
 
 #if WATCH_WIZ
-      OUTREG(BRW_WIZ_CTL,
-	     BRW_WIZ_CTL_SNAPSHOT_MUX_SUBSPAN_INSTANCE |
-	     BRW_WIZ_CTL_SNAPSHOT_ALL_THREADS |
-	     BRW_WIZ_CTL_SNAPSHOT_ENABLE);
-      OUTREG(BRW_WIZ_STRG_VAL,
-	     (box_x1) | (box_y1 << 16));
-#endif
-      
-#if 0
-      OUTREG(BRW_TS_CTL,
-	     BRW_TS_CTL_SNAPSHOT_MESSAGE_ERROR |
-	     BRW_TS_CTL_SNAPSHOT_ALL_CHILD_THREADS |
-	     BRW_TS_CTL_SNAPSHOT_ALL_ROOT_THREADS |
-	     BRW_TS_CTL_SNAPSHOT_ENABLE);
-#endif
-
-      BEGIN_LP_RING(6);
-      OUT_RING(BRW_3DPRIMITIVE | 
-	       BRW_3DPRIMITIVE_VERTEX_SEQUENTIAL |
-	       (_3DPRIM_RECTLIST << BRW_3DPRIMITIVE_TOPOLOGY_SHIFT) | 
-	       (0 << 9) |  /* CTG - indirect vertex count */
-	       4);
-      OUT_RING(3); /* vertex count per instance */
-      OUT_RING(0); /* start vertex offset */
-      OUT_RING(1); /* single instance */
-      OUT_RING(0); /* start instance location */
-      OUT_RING(0); /* index buffer offset, ignored */
-      ADVANCE_LP_RING();
-
-#if 0
-      for (j = 0; j < 100000; j++) {
-	ctl = INREG(BRW_VF_CTL);
-	 if (ctl & BRW_VF_CTL_SNAPSHOT_COMPLETE)
-	    break;
-      }
-      
-      rdata = INREG(BRW_VF_RDATA);
-      OUTREG(BRW_VF_CTL, 0);
-      ErrorF ("VF_CTL: 0x%08x VF_RDATA: 0x%08x\n", ctl, rdata);
+	OUTREG(BRW_WIZ_CTL,
+	       BRW_WIZ_CTL_SNAPSHOT_MUX_SUBSPAN_INSTANCE |
+	       BRW_WIZ_CTL_SNAPSHOT_ALL_THREADS |
+	       BRW_WIZ_CTL_SNAPSHOT_ENABLE);
+	OUTREG(BRW_WIZ_STRG_VAL,
+	       (box_x1) | (box_y1 << 16));
 #endif
 
 #if 0
-      for (j = 0; j < 1000000; j++) {
-	ctl = INREG(BRW_VS_CTL);
-	 if (ctl & BRW_VS_CTL_SNAPSHOT_COMPLETE)
-	    break;
-      }
-
-      rdata = INREG(BRW_VS_RDATA);
-      for (k = 0; k <= 3; k++) {
-	 OUTREG(BRW_VS_CTL,
-		BRW_VS_CTL_SNAPSHOT_COMPLETE |
-		(k << 8));
-	 rdata = INREG(BRW_VS_RDATA);
-	 ErrorF ("VS_CTL: 0x%08x VS_RDATA(%d): 0x%08x\n", ctl, k, rdata);
-      }
-      
-      OUTREG(BRW_VS_CTL, 0);
+	OUTREG(BRW_TS_CTL,
+	       BRW_TS_CTL_SNAPSHOT_MESSAGE_ERROR |
+	       BRW_TS_CTL_SNAPSHOT_ALL_CHILD_THREADS |
+	       BRW_TS_CTL_SNAPSHOT_ALL_ROOT_THREADS |
+	       BRW_TS_CTL_SNAPSHOT_ENABLE);
+#endif
+
+	BEGIN_LP_RING(6);
+	OUT_RING(BRW_3DPRIMITIVE |
+		 BRW_3DPRIMITIVE_VERTEX_SEQUENTIAL |
+		 (_3DPRIM_RECTLIST << BRW_3DPRIMITIVE_TOPOLOGY_SHIFT) |
+		 (0 << 9) |  /* CTG - indirect vertex count */
+		 4);
+	OUT_RING(3); /* vertex count per instance */
+	OUT_RING(0); /* start vertex offset */
+	OUT_RING(1); /* single instance */
+	OUT_RING(0); /* start instance location */
+	OUT_RING(0); /* index buffer offset, ignored */
+	ADVANCE_LP_RING();
+
+#if 0
+	for (j = 0; j < 100000; j++) {
+	    ctl = INREG(BRW_VF_CTL);
+	    if (ctl & BRW_VF_CTL_SNAPSHOT_COMPLETE)
+		break;
+	}
+
+	rdata = INREG(BRW_VF_RDATA);
+	OUTREG(BRW_VF_CTL, 0);
+	ErrorF ("VF_CTL: 0x%08x VF_RDATA: 0x%08x\n", ctl, rdata);
+#endif
+
+#if 0
+	for (j = 0; j < 1000000; j++) {
+	    ctl = INREG(BRW_VS_CTL);
+	    if (ctl & BRW_VS_CTL_SNAPSHOT_COMPLETE)
+		break;
+	}
+
+	rdata = INREG(BRW_VS_RDATA);
+	for (k = 0; k <= 3; k++) {
+	    OUTREG(BRW_VS_CTL,
+		   BRW_VS_CTL_SNAPSHOT_COMPLETE |
+		   (k << 8));
+	    rdata = INREG(BRW_VS_RDATA);
+	    ErrorF ("VS_CTL: 0x%08x VS_RDATA(%d): 0x%08x\n", ctl, k, rdata);
+	}
+
+	OUTREG(BRW_VS_CTL, 0);
 #endif
 
 #if WATCH_SF
-      for (j = 0; j < 1000000; j++) {
-	ctl = INREG(BRW_SF_CTL);
-	 if (ctl & BRW_SF_CTL_SNAPSHOT_COMPLETE)
-	    break;
-      }
-
-      for (k = 0; k <= 7; k++) {
-	 OUTREG(BRW_SF_CTL,
-		BRW_SF_CTL_SNAPSHOT_COMPLETE |
-		(k << 8));
-	 rdata = INREG(BRW_SF_RDATA);
-	 ErrorF ("SF_CTL: 0x%08x SF_RDATA(%d): 0x%08x\n", ctl, k, rdata);
-      }
-      
-      OUTREG(BRW_SF_CTL, 0);
+	for (j = 0; j < 1000000; j++) {
+	    ctl = INREG(BRW_SF_CTL);
+	    if (ctl & BRW_SF_CTL_SNAPSHOT_COMPLETE)
+		break;
+	}
+
+	for (k = 0; k <= 7; k++) {
+	    OUTREG(BRW_SF_CTL,
+		   BRW_SF_CTL_SNAPSHOT_COMPLETE |
+		   (k << 8));
+	    rdata = INREG(BRW_SF_RDATA);
+	    ErrorF("SF_CTL: 0x%08x SF_RDATA(%d): 0x%08x\n", ctl, k, rdata);
+	}
+
+	OUTREG(BRW_SF_CTL, 0);
 #endif
 
 #if WATCH_WIZ
-      for (j = 0; j < 100000; j++) {
-	ctl = INREG(BRW_WIZ_CTL);
-	 if (ctl & BRW_WIZ_CTL_SNAPSHOT_COMPLETE)
-	    break;
-      }
-      
-      rdata = INREG(BRW_WIZ_RDATA);
-      OUTREG(BRW_WIZ_CTL, 0);
-      ErrorF ("WIZ_CTL: 0x%08x WIZ_RDATA: 0x%08x\n", ctl, rdata);
-#endif
-      
-#if 0
-      for (j = 0; j < 100000; j++) {
-	ctl = INREG(BRW_TS_CTL);
-	 if (ctl & BRW_TS_CTL_SNAPSHOT_COMPLETE)
-	    break;
-      }
-      
-      rdata = INREG(BRW_TS_RDATA);
-      OUTREG(BRW_TS_CTL, 0);
-      ErrorF ("TS_CTL: 0x%08x TS_RDATA: 0x%08x\n", ctl, rdata);
-      
-      ErrorF ("after EU_ATT 0x%08x%08x EU_ATT_DATA 0x%08x%08x\n",
-	      INREG(BRW_EU_ATT_1), INREG(BRW_EU_ATT_0),
-	      INREG(BRW_EU_ATT_DATA_1), INREG(BRW_EU_ATT_DATA_0));
+	for (j = 0; j < 100000; j++) {
+	    ctl = INREG(BRW_WIZ_CTL);
+	    if (ctl & BRW_WIZ_CTL_SNAPSHOT_COMPLETE)
+		break;
+	}
+
+	rdata = INREG(BRW_WIZ_RDATA);
+	OUTREG(BRW_WIZ_CTL, 0);
+	ErrorF("WIZ_CTL: 0x%08x WIZ_RDATA: 0x%08x\n", ctl, rdata);
 #endif
 
 #if 0
-      for (j = 0; j < 256; j++) {
-	 OUTREG(BRW_TD_CTL, j << BRW_TD_CTL_MUX_SHIFT);
-	 rdata = INREG(BRW_TD_RDATA);
-	 ErrorF ("TD_RDATA(%d): 0x%08x\n", j, rdata);
-      }
-#endif
-      first_output = FALSE;
-      if (pI830->AccelInfoRec)
-	 pI830->AccelInfoRec->NeedToSync = TRUE;
-   }
+	for (j = 0; j < 100000; j++) {
+	    ctl = INREG(BRW_TS_CTL);
+	    if (ctl & BRW_TS_CTL_SNAPSHOT_COMPLETE)
+		break;
+	}
+
+	rdata = INREG(BRW_TS_RDATA);
+	OUTREG(BRW_TS_CTL, 0);
+	ErrorF("TS_CTL: 0x%08x TS_RDATA: 0x%08x\n", ctl, rdata);
+
+	ErrorF("after EU_ATT 0x%08x%08x EU_ATT_DATA 0x%08x%08x\n",
+	       INREG(BRW_EU_ATT_1), INREG(BRW_EU_ATT_0),
+	       INREG(BRW_EU_ATT_DATA_1), INREG(BRW_EU_ATT_DATA_0));
+#endif
+
+#if 0
+	for (j = 0; j < 256; j++) {
+	    OUTREG(BRW_TD_CTL, j << BRW_TD_CTL_MUX_SHIFT);
+	    rdata = INREG(BRW_TD_RDATA);
+	    ErrorF ("TD_RDATA(%d): 0x%08x\n", j, rdata);
+	}
+#endif
+	first_output = FALSE;
+	if (pI830->AccelInfoRec)
+	    pI830->AccelInfoRec->NeedToSync = TRUE;
+    }
 
-   if (pI830->AccelInfoRec)
-      (*pI830->AccelInfoRec->Sync)(pScrn);
+    if (pI830->AccelInfoRec)
+	(*pI830->AccelInfoRec->Sync)(pScrn);
 #if WATCH_STATS
-   i830_dump_error_state (pScrn);
+    i830_dump_error_state(pScrn);
 #endif
 }
diff-tree 05066632b068ae91d7be77e3a199ea0d337d975b (from 46df75ccd4647ea033583130253a2a2218b34a20)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Dec 27 17:41:45 2006 -0800

    Move 965 textured-video out to a separate file.

diff --git a/src/Makefile.am b/src/Makefile.am
index 976a95a..d843ecf 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -88,6 +88,7 @@ i810_drv_la_SOURCES = \
 	 i915_3d.h \
 	 i915_reg.h \
 	 i915_video.c \
+	 i965_video.c \
 	 i830_exa.c \
 	 i830_xaa.c \
 	 i830_exa_render.c \
diff --git a/src/i830_video.c b/src/i830_video.c
index 946a447..2e4a85b 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -84,8 +84,6 @@ THE USE OR OTHER DEALINGS IN THE SOFTWAR
 #include "xaalocal.h"
 #include "dixstruct.h"
 #include "fourcc.h"
-#include "brw_defines.h"
-#include "brw_structs.h"
 
 #ifndef USE_USLEEP_FOR_VIDEO
 #define USE_USLEEP_FOR_VIDEO 0
@@ -2007,791 +2005,6 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
    OVERLAY_UPDATE;
 }
 
-static const CARD32 sip_kernel_static[][4] = {
-/*    wait (1) a0<1>UW a145<0,1,0>UW { align1 +  } */
-    { 0x00000030, 0x20000108, 0x00001220, 0x00000000 },
-/*    nop (4) g0<1>UD { align1 +  } */
-    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
-/*    nop (4) g0<1>UD { align1 +  } */
-    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
-/*    nop (4) g0<1>UD { align1 +  } */
-    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
-/*    nop (4) g0<1>UD { align1 +  } */
-    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
-/*    nop (4) g0<1>UD { align1 +  } */
-    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
-/*    nop (4) g0<1>UD { align1 +  } */
-    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
-/*    nop (4) g0<1>UD { align1 +  } */
-    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
-/*    nop (4) g0<1>UD { align1 +  } */
-    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
-/*    nop (4) g0<1>UD { align1 +  } */
-    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
-};
-   
-/*
- * this program computes dA/dx and dA/dy for the texture coordinates along
- * with the base texture coordinate. It was extracted from the Mesa driver.
- * It uses about 10 GRF registers.
- */
-
-#define SF_KERNEL_NUM_GRF  16
-#define SF_MAX_THREADS	   1
-
-static const CARD32 sf_kernel_static[][4] = {
-#include "sf_prog.h"
-};
-
-/*
- * Ok, this kernel picks up the required data flow values in g0 and g1
- * and passes those along in m0 and m1. In m2-m9, it sticks constant
- * values (bright pink).
- */
-
-/* Our PS kernel uses less than 32 GRF registers (about 20) */
-#define PS_KERNEL_NUM_GRF   32
-#define PS_MAX_THREADS	   32
-
-#define BRW_GRF_BLOCKS(nreg)	((nreg + 15) / 16 - 1)
-
-static const CARD32 ps_kernel_static[][4] = {
-#include "wm_prog.h"
-};
-
-#define ALIGN(i,m)    (((i) + (m) - 1) & ~((m) - 1))
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-
-#define WM_BINDING_TABLE_ENTRIES    2
-
-static CARD32 float_to_uint (float f) {
-   union {CARD32 i; float f;} x;
-   x.f = f;
-   return x.i;
-}
-
-#if 0
-static struct {
-   CARD32   svg_ctl;
-   char	    *name;
-} svg_ctl_bits[] = {
-   { BRW_SVG_CTL_GS_BA, "General State Base Address" },
-   { BRW_SVG_CTL_SS_BA, "Surface State Base Address" },
-   { BRW_SVG_CTL_IO_BA, "Indirect Object Base Address" },
-   { BRW_SVG_CTL_GS_AUB, "Generate State Access Upper Bound" },
-   { BRW_SVG_CTL_IO_AUB, "Indirect Object Access Upper Bound" },
-   { BRW_SVG_CTL_SIP, "System Instruction Pointer" },
-   { 0, 0 },
-};
-
-static void
-brw_debug (ScrnInfoPtr pScrn, char *when)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   int	    i;
-   CARD32   v;
-   
-   I830Sync (pScrn);
-   ErrorF("brw_debug: %s\n", when);
-   for (i = 0; svg_ctl_bits[i].name; i++) {
-      OUTREG(BRW_SVG_CTL, svg_ctl_bits[i].svg_ctl);
-      v = INREG(BRW_SVG_RDATA);
-      ErrorF("\t%34.34s: 0x%08x\n", svg_ctl_bits[i].name, v);
-   }
-}
-#endif
-
-#define WATCH_SF 0
-#define WATCH_WIZ 0
-#define WATCH_STATS 0
-
-static void
-BroadwaterDisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id,
-			       RegionPtr dstRegion,
-			       short width, short height, int video_pitch,
-			       int x1, int y1, int x2, int y2,
-			       short src_w, short src_h,
-			       short drw_w, short drw_h,
-			       DrawablePtr pDraw)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   BoxPtr pbox;
-   int nbox, dxo, dyo;
-   int urb_vs_start, urb_vs_size;
-   int urb_gs_start, urb_gs_size;
-   int urb_clip_start, urb_clip_size;
-   int urb_sf_start, urb_sf_size;
-   int urb_cs_start, urb_cs_size;
-   struct brw_surface_state *dest_surf_state;
-   struct brw_surface_state *src_surf_state;
-   struct brw_sampler_state *src_sampler_state;
-   struct brw_vs_unit_state *vs_state;
-   struct brw_sf_unit_state *sf_state;
-   struct brw_wm_unit_state *wm_state;
-   struct brw_cc_unit_state *cc_state;
-   struct brw_cc_viewport *cc_viewport;
-   struct brw_instruction *sf_kernel;
-   struct brw_instruction *ps_kernel;
-   struct brw_instruction *sip_kernel;
-   float *vb;
-    CARD32 *binding_table;
-   Bool first_output = TRUE;
-   int dest_surf_offset, src_surf_offset, src_sampler_offset, vs_offset;
-   int sf_offset, wm_offset, cc_offset, vb_offset, cc_viewport_offset;
-   int wm_scratch_offset;
-   int sf_kernel_offset, ps_kernel_offset, sip_kernel_offset;
-   int binding_table_offset;
-   int next_offset, total_state_size;
-   int vb_size = (4 * 4) * 4; /* 4 DWORDS per vertex */
-   char *state_base;
-   int state_base_offset;
-
-#if 0
-   ErrorF("BroadwaterDisplayVideoTextured: %dx%d (pitch %d)\n", width, height,
-	  video_pitch);
-#endif
-
-   /* enable debug */
-   OUTREG (INST_PM,
-	   (1 << (16 + 4)) |
-	   (1 << 4));
-#if 0
-   ErrorF ("INST_PM 0x%08x\n", INREG(INST_PM));
-#endif
-   
-   assert((id == FOURCC_UYVY) || (id == FOURCC_YUY2));
-
-   /* Tell the rotation code that we have stomped its invariant state by
-    * setting a high bit.  We don't use any invariant 3D state for video, so we
-    * don't have to worry about it ourselves.
-    */
-   *pI830->used3D |= 1 << 30;
-
-#ifdef XF86DRI
-   /* Tell the DRI that we're smashing its state. */
-   if (pI830->directRenderingEnabled) {
-     drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
-
-     pSAREAPriv->ctxOwner = DRIGetContext(pScrn->pScreen);
-   }
-#endif /* XF86DRI */
-
-   next_offset = 0;
-
-   /* Set up our layout of state in framebuffer.  First the general state: */
-   vs_offset = ALIGN(next_offset, 64);
-   next_offset = vs_offset + sizeof(*vs_state);
-   sf_offset = ALIGN(next_offset, 32);
-   next_offset = sf_offset + sizeof(*sf_state);
-   wm_offset = ALIGN(next_offset, 32);
-   next_offset = wm_offset + sizeof(*wm_state);
-   wm_scratch_offset = ALIGN(next_offset, 1024);
-   next_offset = wm_scratch_offset + 1024 * PS_MAX_THREADS;
-   cc_offset = ALIGN(next_offset, 32);
-   next_offset = cc_offset + sizeof(*cc_state);
-
-   sf_kernel_offset = ALIGN(next_offset, 64);
-   next_offset = sf_kernel_offset + sizeof (sf_kernel_static);
-   ps_kernel_offset = ALIGN(next_offset, 64);
-   next_offset = ps_kernel_offset + sizeof (ps_kernel_static);
-   sip_kernel_offset = ALIGN(next_offset, 64);
-   next_offset = sip_kernel_offset + sizeof (sip_kernel_static);
-   cc_viewport_offset = ALIGN(next_offset, 32);
-   next_offset = cc_viewport_offset + sizeof(*cc_viewport);
-
-   src_sampler_offset = ALIGN(next_offset, 32);
-   next_offset = src_sampler_offset + sizeof(*src_sampler_state);
-
-   /* Align VB to native size of elements, for safety */
-   vb_offset = ALIGN(next_offset, 8);
-   next_offset = vb_offset + vb_size;
-
-   /* And then the general state: */
-   dest_surf_offset = ALIGN(next_offset, 32);
-   next_offset = dest_surf_offset + sizeof(*dest_surf_state);
-   src_surf_offset = ALIGN(next_offset, 32);
-   next_offset = src_surf_offset + sizeof(*src_surf_state);
-   binding_table_offset = ALIGN(next_offset, 32);
-   next_offset = binding_table_offset + (WM_BINDING_TABLE_ENTRIES * 4);
-
-   /* Allocate an area in framebuffer for our state layout we just set up */
-   total_state_size = next_offset;
-   assert (total_state_size < BRW_LINEAR_EXTRA);
-
-   /*
-    * Use the extra space allocated at the end of the Xv buffer
-    */
-   state_base_offset = pPriv->extra_offset;
-   state_base_offset = ALIGN(state_base_offset, 64);
-
-   state_base = (char *)(pI830->FbBase + state_base_offset);
-   /* Set up our pointers to state structures in framebuffer.  It would probably
-    * be a good idea to fill these structures out in system memory and then dump
-    * them there, instead.
-    */
-   vs_state = (void *)(state_base + vs_offset);
-   sf_state = (void *)(state_base + sf_offset);
-   wm_state = (void *)(state_base + wm_offset);
-   cc_state = (void *)(state_base + cc_offset);
-   sf_kernel = (void *)(state_base + sf_kernel_offset);
-   ps_kernel = (void *)(state_base + ps_kernel_offset);
-   sip_kernel = (void *)(state_base + sip_kernel_offset);
-   
-   cc_viewport = (void *)(state_base + cc_viewport_offset);
-   dest_surf_state = (void *)(state_base + dest_surf_offset);
-   src_surf_state = (void *)(state_base + src_surf_offset);
-   src_sampler_state = (void *)(state_base + src_sampler_offset);
-   binding_table = (void *)(state_base + binding_table_offset);
-   vb = (void *)(state_base + vb_offset);
-
-   /* For 3D, the VS must have 8, 12, 16, 24, or 32 VUEs allocated to it.
-    * A VUE consists of a 256-bit vertex header followed by the vertex data,
-    * which in our case is 4 floats (128 bits), thus a single 512-bit URB
-    * entry.
-    */
-#define URB_VS_ENTRIES	      8
-#define URB_VS_ENTRY_SIZE     1
-   
-#define URB_GS_ENTRIES	      0
-#define URB_GS_ENTRY_SIZE     0
-   
-#define URB_CLIP_ENTRIES      0
-#define URB_CLIP_ENTRY_SIZE   0
-   
-   /* The SF kernel we use outputs only 4 256-bit registers, leading to an
-    * entry size of 2 512-bit URBs.  We don't need to have many entries to
-    * output as we're generally working on large rectangles and don't care
-    * about having WM threads running on different rectangles simultaneously.
-    */
-#define URB_SF_ENTRIES	      1
-#define URB_SF_ENTRY_SIZE     2
-
-#define URB_CS_ENTRIES	      0
-#define URB_CS_ENTRY_SIZE     0
-   
-   urb_vs_start = 0;
-   urb_vs_size = URB_VS_ENTRIES * URB_VS_ENTRY_SIZE;
-   urb_gs_start = urb_vs_start + urb_vs_size;
-   urb_gs_size = URB_GS_ENTRIES * URB_GS_ENTRY_SIZE;
-   urb_clip_start = urb_gs_start + urb_gs_size;
-   urb_clip_size = URB_CLIP_ENTRIES * URB_CLIP_ENTRY_SIZE;
-   urb_sf_start = urb_clip_start + urb_clip_size;
-   urb_sf_size = URB_SF_ENTRIES * URB_SF_ENTRY_SIZE;
-   urb_cs_start = urb_sf_start + urb_sf_size;
-   urb_cs_size = URB_CS_ENTRIES * URB_CS_ENTRY_SIZE;
-
-   /* We'll be poking the state buffers that could be in use by the 3d hardware
-    * here, but we should have synced the 3D engine already in I830PutImage.
-    */
-
-   memset (cc_viewport, 0, sizeof (*cc_viewport));
-   cc_viewport->min_depth = -1.e35;
-   cc_viewport->max_depth = 1.e35;
-
-   /* Color calculator state */
-   memset(cc_state, 0, sizeof(*cc_state));
-   cc_state->cc0.stencil_enable = 0;   /* disable stencil */
-   cc_state->cc2.depth_test = 0;       /* disable depth test */
-   cc_state->cc2.logicop_enable = 1;   /* enable logic op */
-   cc_state->cc3.ia_blend_enable = 1;  /* blend alpha just like colors */
-   cc_state->cc3.blend_enable = 0;     /* disable color blend */
-   cc_state->cc3.alpha_test = 0;       /* disable alpha test */
-   cc_state->cc4.cc_viewport_state_offset = (state_base_offset + cc_viewport_offset) >> 5;
-   cc_state->cc5.dither_enable = 0;    /* disable dither */
-   cc_state->cc5.logicop_func = 0xc;   /* WHITE */
-   cc_state->cc5.statistics_enable = 1;
-   cc_state->cc5.ia_blend_function = BRW_BLENDFUNCTION_ADD;
-   cc_state->cc5.ia_src_blend_factor = BRW_BLENDFACTOR_ONE;
-   cc_state->cc5.ia_dest_blend_factor = BRW_BLENDFACTOR_ONE;
-
-   /* Upload system kernel */
-   memcpy (sip_kernel, sip_kernel_static, sizeof (sip_kernel_static));
-   
-   /* Set up the state buffer for the destination surface */
-   memset(dest_surf_state, 0, sizeof(*dest_surf_state));
-   dest_surf_state->ss0.surface_type = BRW_SURFACE_2D;
-   dest_surf_state->ss0.data_return_format = BRW_SURFACERETURNFORMAT_FLOAT32;
-   if (pI830->cpp == 2) {
-      dest_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B5G6R5_UNORM;
-   } else {
-      dest_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
-   }
-   dest_surf_state->ss0.writedisable_alpha = 0;
-   dest_surf_state->ss0.writedisable_red = 0;
-   dest_surf_state->ss0.writedisable_green = 0;
-   dest_surf_state->ss0.writedisable_blue = 0;
-   dest_surf_state->ss0.color_blend = 1;
-   dest_surf_state->ss0.vert_line_stride = 0;
-   dest_surf_state->ss0.vert_line_stride_ofs = 0;
-   dest_surf_state->ss0.mipmap_layout_mode = 0;
-   dest_surf_state->ss0.render_cache_read_mode = 0;
-   
-   dest_surf_state->ss1.base_addr = pI830->FrontBuffer.Start;
-   dest_surf_state->ss2.height = pScrn->virtualY - 1;
-   dest_surf_state->ss2.width = pScrn->virtualX - 1;
-   dest_surf_state->ss2.mip_count = 0;
-   dest_surf_state->ss2.render_target_rotation = 0;
-   dest_surf_state->ss3.pitch = (pI830->displayWidth * pI830->cpp) - 1;
-
-   /* Set up the source surface state buffer */
-   memset(src_surf_state, 0, sizeof(*src_surf_state));
-   src_surf_state->ss0.surface_type = BRW_SURFACE_2D;
-/*   src_surf_state->ss0.data_return_format = BRW_SURFACERETURNFORMAT_FLOAT32; */
-   switch (id) {
-   case FOURCC_YUY2:
-      src_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_YCRCB_NORMAL;
-      break;
-   case FOURCC_UYVY:
-      src_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_YCRCB_SWAPY;
-      break;
-   }
-   src_surf_state->ss0.writedisable_alpha = 0;
-   src_surf_state->ss0.writedisable_red = 0;
-   src_surf_state->ss0.writedisable_green = 0;
-   src_surf_state->ss0.writedisable_blue = 0;
-   src_surf_state->ss0.color_blend = 1;
-   src_surf_state->ss0.vert_line_stride = 0;
-   src_surf_state->ss0.vert_line_stride_ofs = 0;
-   src_surf_state->ss0.mipmap_layout_mode = 0;
-   src_surf_state->ss0.render_cache_read_mode = 0;
-   
-   src_surf_state->ss1.base_addr = pPriv->YBuf0offset;
-   src_surf_state->ss2.width = width - 1;
-   src_surf_state->ss2.height = height - 1;
-   src_surf_state->ss2.mip_count = 0;
-   src_surf_state->ss2.render_target_rotation = 0;
-   src_surf_state->ss3.pitch = video_pitch - 1;
-
-   /* Set up a binding table for our two surfaces.  Only the PS will use it */
-   /* XXX: are these offset from the right place? */
-   binding_table[0] = state_base_offset + dest_surf_offset;
-   binding_table[1] = state_base_offset + src_surf_offset;
-
-   /* Set up the packed YUV source sampler.  Doesn't do colorspace conversion.
-    */
-   memset(src_sampler_state, 0, sizeof(*src_sampler_state));
-   src_sampler_state->ss0.min_filter = BRW_MAPFILTER_LINEAR;
-   src_sampler_state->ss0.mag_filter = BRW_MAPFILTER_LINEAR;
-   src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
-   src_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
-   src_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
-
-   /* Set up the vertex shader to be disabled (passthrough) */
-   memset(vs_state, 0, sizeof(*vs_state));
-   vs_state->thread4.nr_urb_entries = URB_VS_ENTRIES;
-   vs_state->thread4.urb_entry_allocation_size = URB_VS_ENTRY_SIZE - 1;
-   vs_state->vs6.vs_enable = 0;
-   vs_state->vs6.vert_cache_disable = 1;
-
-   /* Set up the SF kernel to do coord interp: for each attribute,
-    * calculate dA/dx and dA/dy.  Hand these interpolation coefficients
-    * back to SF which then hands pixels off to WM.
-    */
-
-   memcpy (sf_kernel, sf_kernel_static, sizeof (sf_kernel_static));
-   memset(sf_state, 0, sizeof(*sf_state));
-#if 0
-   ErrorF ("sf kernel: 0x%08x\n", state_base_offset + sf_kernel_offset);
-#endif
-   sf_state->thread0.kernel_start_pointer = 
-	       (state_base_offset + sf_kernel_offset) >> 6;
-   sf_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(SF_KERNEL_NUM_GRF);
-   sf_state->sf1.single_program_flow = 1; /* XXX */
-   sf_state->sf1.binding_table_entry_count = 0;
-   sf_state->sf1.thread_priority = 0;
-   sf_state->sf1.floating_point_mode = 0; /* Mesa does this */
-   sf_state->sf1.illegal_op_exception_enable = 1;
-   sf_state->sf1.mask_stack_exception_enable = 1;
-   sf_state->sf1.sw_exception_enable = 1;
-   sf_state->thread2.per_thread_scratch_space = 0;
-   sf_state->thread2.scratch_space_base_pointer = 0; /* not used in our kernel */
-   sf_state->thread3.const_urb_entry_read_length = 0; /* no const URBs */
-   sf_state->thread3.const_urb_entry_read_offset = 0; /* no const URBs */
-   sf_state->thread3.urb_entry_read_length = 1; /* 1 URB per vertex */
-   sf_state->thread3.urb_entry_read_offset = 0;
-   sf_state->thread3.dispatch_grf_start_reg = 3;
-   sf_state->thread4.max_threads = SF_MAX_THREADS - 1;
-   sf_state->thread4.urb_entry_allocation_size = URB_SF_ENTRY_SIZE - 1;
-   sf_state->thread4.nr_urb_entries = URB_SF_ENTRIES;
-   sf_state->thread4.stats_enable = 1;
-   sf_state->sf5.viewport_transform = FALSE; /* skip viewport */
-   sf_state->sf6.cull_mode = BRW_CULLMODE_NONE;
-   sf_state->sf6.scissor = 0;
-   sf_state->sf7.trifan_pv = 2;
-   sf_state->sf6.dest_org_vbias = 0x8;
-   sf_state->sf6.dest_org_hbias = 0x8;
-
-   memcpy (ps_kernel, ps_kernel_static, sizeof (ps_kernel_static));
-#if 0
-   ErrorF ("ps kernel: 0x%08x\n", state_base_offset + ps_kernel_offset);
-#endif
-   memset (wm_state, 0, sizeof (*wm_state));
-   wm_state->thread0.kernel_start_pointer = 
-	    (state_base_offset + ps_kernel_offset) >> 6;
-   wm_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(PS_KERNEL_NUM_GRF);
-   wm_state->thread1.single_program_flow = 1; /* XXX */
-   wm_state->thread1.binding_table_entry_count = 2;
-   /* Though we never use the scratch space in our WM kernel, it has to be
-    * set, and the minimum allocation is 1024 bytes.
-    */
-   wm_state->thread2.scratch_space_base_pointer = (state_base_offset +
-						   wm_scratch_offset) >> 10;
-   wm_state->thread2.per_thread_scratch_space = 0; /* 1024 bytes */
-   wm_state->thread3.dispatch_grf_start_reg = 3; /* XXX */
-   wm_state->thread3.const_urb_entry_read_length = 0;
-   wm_state->thread3.const_urb_entry_read_offset = 0;
-   wm_state->thread3.urb_entry_read_length = 1; /* XXX */
-   wm_state->thread3.urb_entry_read_offset = 0; /* XXX */
-   wm_state->wm4.stats_enable = 1;
-   wm_state->wm4.sampler_state_pointer = (state_base_offset + src_sampler_offset) >> 5;
-   wm_state->wm4.sampler_count = 1; /* 1-4 samplers used */
-   wm_state->wm5.max_threads = PS_MAX_THREADS - 1;
-   wm_state->wm5.thread_dispatch_enable = 1;
-   wm_state->wm5.enable_16_pix = 1;
-   wm_state->wm5.enable_8_pix = 0;
-   wm_state->wm5.early_depth_test = 1;
-
-   {
-      BEGIN_LP_RING(2);
-      OUT_RING(MI_FLUSH | 
-	       MI_STATE_INSTRUCTION_CACHE_FLUSH |
-	       BRW_MI_GLOBAL_SNAPSHOT_RESET);
-      OUT_RING(MI_NOOP);
-      ADVANCE_LP_RING();
-   }
-   
-/*    brw_debug (pScrn, "before base address modify"); */
-   { BEGIN_LP_RING(12);
-   /* Match Mesa driver setup */
-   OUT_RING(BRW_PIPELINE_SELECT | PIPELINE_SELECT_3D);
-
-   /* Mesa does this. Who knows... */
-   OUT_RING(BRW_CS_URB_STATE | 0);
-   OUT_RING((0 << 4) |	/* URB Entry Allocation Size */
-	    (0 << 0));	/* Number of URB Entries */
-   
-   /* Zero out the two base address registers so all offsets are absolute */
-   OUT_RING(BRW_STATE_BASE_ADDRESS | 4);
-   OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* Generate state base address */
-   OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* Surface state base address */
-   OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* media base addr, don't care */
-   OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY);  /* general state max addr, disabled */
-   OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY);  /* media object state max addr, disabled */
-
-   /* Set system instruction pointer */
-   OUT_RING(BRW_STATE_SIP | 0);
-   OUT_RING(state_base_offset + sip_kernel_offset); /* system instruction pointer */
-      
-   OUT_RING(MI_NOOP);
-   ADVANCE_LP_RING(); }
-   
-/*   brw_debug (pScrn, "after base address modify"); */
-
-   { BEGIN_LP_RING(42);
-   /* Enable VF statistics */
-   OUT_RING(BRW_3DSTATE_VF_STATISTICS | 1);
-   
-   /* Pipe control */
-   OUT_RING(BRW_PIPE_CONTROL |
-	    BRW_PIPE_CONTROL_NOWRITE |
-	    BRW_PIPE_CONTROL_IS_FLUSH |
-	    2);
-   OUT_RING(0);			       /* Destination address */
-   OUT_RING(0);			       /* Immediate data low DW */
-   OUT_RING(0);			       /* Immediate data high DW */
-
-   /* Binding table pointers */
-   OUT_RING(BRW_3DSTATE_BINDING_TABLE_POINTERS | 4);
-   OUT_RING(0); /* vs */
-   OUT_RING(0); /* gs */
-   OUT_RING(0); /* clip */
-   OUT_RING(0); /* sf */
-   /* Only the PS uses the binding table */
-   OUT_RING(state_base_offset + binding_table_offset); /* ps */
-   
-   /* Blend constant color (magenta is fun) */
-   OUT_RING(BRW_3DSTATE_CONSTANT_COLOR | 3);
-   OUT_RING(float_to_uint (1.0));
-   OUT_RING(float_to_uint (0.0));
-   OUT_RING(float_to_uint (1.0));
-   OUT_RING(float_to_uint (1.0));
-   
-   /* The drawing rectangle clipping is always on.  Set it to values that
-    * shouldn't do any clipping.
-    */
-   OUT_RING(BRW_3DSTATE_DRAWING_RECTANGLE | 2);	/* XXX 3 for BLC or CTG */
-   OUT_RING(0x00000000);	/* ymin, xmin */
-   OUT_RING((pScrn->virtualX - 1) |
-	    (pScrn->virtualY - 1) << 16); /* ymax, xmax */
-   OUT_RING(0x00000000);	/* yorigin, xorigin */
-
-   /* skip the depth buffer */
-   /* skip the polygon stipple */
-   /* skip the polygon stipple offset */
-   /* skip the line stipple */
-   
-   /* Set the pointers to the 3d pipeline state */
-   OUT_RING(BRW_3DSTATE_PIPELINED_POINTERS | 5);
-   OUT_RING(state_base_offset + vs_offset);  /* 32 byte aligned */
-   OUT_RING(BRW_GS_DISABLE);		     /* disable GS, resulting in passthrough */
-   OUT_RING(BRW_CLIP_DISABLE);		     /* disable CLIP, resulting in passthrough */
-   OUT_RING(state_base_offset + sf_offset);  /* 32 byte aligned */
-   OUT_RING(state_base_offset + wm_offset);  /* 32 byte aligned */
-   OUT_RING(state_base_offset + cc_offset);  /* 64 byte aligned */
-
-   /* URB fence */
-   OUT_RING(BRW_URB_FENCE |
-	    UF0_CS_REALLOC |
-	    UF0_SF_REALLOC |
-	    UF0_CLIP_REALLOC |
-	    UF0_GS_REALLOC |
-	    UF0_VS_REALLOC |
-	    1);
-   OUT_RING(((urb_clip_start + urb_clip_size) << UF1_CLIP_FENCE_SHIFT) |
-	    ((urb_gs_start + urb_gs_size) << UF1_GS_FENCE_SHIFT) |
-	    ((urb_vs_start + urb_vs_size) << UF1_VS_FENCE_SHIFT));
-   OUT_RING(((urb_cs_start + urb_cs_size) << UF2_CS_FENCE_SHIFT) |
-	    ((urb_sf_start + urb_sf_size) << UF2_SF_FENCE_SHIFT));
-
-   /* Constant buffer state */
-   OUT_RING(BRW_CS_URB_STATE | 0);
-   OUT_RING(((URB_CS_ENTRY_SIZE - 1) << 4) | /* URB Entry Allocation Size */
-	    (URB_CS_ENTRIES << 0));	     /* Number of URB Entries */
-   
-   /* Set up the pointer to our vertex buffer */
-   OUT_RING(BRW_3DSTATE_VERTEX_BUFFERS | 2);
-   OUT_RING((0 << VB0_BUFFER_INDEX_SHIFT) |
-	    VB0_VERTEXDATA |
-	    ((4 * 4) << VB0_BUFFER_PITCH_SHIFT)); /* four 32-bit floats per vertex */
-   OUT_RING(state_base_offset + vb_offset);
-   OUT_RING(3); /* four corners to our rectangle */
-
-   /* Set up our vertex elements, sourced from the single vertex buffer. */
-   OUT_RING(BRW_3DSTATE_VERTEX_ELEMENTS | 3);
-   /* offset 0: X,Y -> {X, Y, 1.0, 1.0} */
-   OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
-	    VE0_VALID |
-	    (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
-	    (0 << VE0_OFFSET_SHIFT));
-   OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
-	    (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
-	    (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
-	    (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
-	    (0 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
-   /* offset 8: S0, T0 -> {S0, T0, 1.0, 1.0} */
-   OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
-	    VE0_VALID |
-	    (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
-	    (8 << VE0_OFFSET_SHIFT));
-   OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
-	    (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
-	    (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
-	    (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
-	    (4 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
-
-   OUT_RING(MI_NOOP);			/* pad to quadword */
-   ADVANCE_LP_RING(); }
-
-   dxo = dstRegion->extents.x1;
-   dyo = dstRegion->extents.y1;
-
-   pbox = REGION_RECTS(dstRegion);
-   nbox = REGION_NUM_RECTS(dstRegion);
-   while (nbox--)
-   {
-      int box_x1 = pbox->x1;
-      int box_y1 = pbox->y1;
-      int box_x2 = pbox->x2;
-      int box_y2 = pbox->y2;
-      int i;
-      float src_scale_x, src_scale_y;
-
-      if (!first_output) {
-	 /* Since we use the same little vertex buffer over and over, sync for
-	  * subsequent rectangles.
-	  */
-	 if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
-	    (*pI830->AccelInfoRec->Sync)(pScrn);
-	    pI830->AccelInfoRec->NeedToSync = FALSE;
-	 }
-      }
-
-      pbox++;
-
-      /* Use normalized texture coordinates */
-      src_scale_x = (float)1.0 / (float)drw_w;
-      src_scale_y  = (float)1.0 / (float)drw_h;
-
-      i = 0;
-      vb[i++] = (box_x2 - dxo) * src_scale_x;
-      vb[i++] = (box_y2 - dyo) * src_scale_y;
-      vb[i++] = (float) box_x2;
-      vb[i++] = (float) box_y2;
-
-      vb[i++] = (box_x1 - dxo) * src_scale_x;
-      vb[i++] = (box_y2 - dyo) * src_scale_y;
-      vb[i++] = (float) box_x1;
-      vb[i++] = (float) box_y2;
-
-      vb[i++] = (box_x1 - dxo) * src_scale_x;
-      vb[i++] = (box_y1 - dyo) * src_scale_y;
-      vb[i++] = (float) box_x1;
-      vb[i++] = (float) box_y1;
-
-#if 0
-      ErrorF ("before EU_ATT 0x%08x%08x EU_ATT_DATA 0x%08x%08x\n",
-	      INREG(BRW_EU_ATT_1), INREG(BRW_EU_ATT_0),
-	      INREG(BRW_EU_ATT_DATA_1), INREG(BRW_EU_ATT_DATA_0));
-
-      OUTREG(BRW_VF_CTL,
-	     BRW_VF_CTL_SNAPSHOT_MUX_SELECT_THREADID |
-	     BRW_VF_CTL_SNAPSHOT_TYPE_VERTEX_INDEX |
-	     BRW_VF_CTL_SNAPSHOT_ENABLE);
-      OUTREG(BRW_VF_STRG_VAL, 0);
-#endif
-      
-#if 0
-      OUTREG(BRW_VS_CTL,
-	     BRW_VS_CTL_SNAPSHOT_ALL_THREADS |
-	     BRW_VS_CTL_SNAPSHOT_MUX_VALID_COUNT |
-	     BRW_VS_CTL_THREAD_SNAPSHOT_ENABLE);
-      
-      OUTREG(BRW_VS_STRG_VAL, 0);
-#endif
-      
-#if WATCH_SF
-      OUTREG(BRW_SF_CTL,
-	     BRW_SF_CTL_SNAPSHOT_MUX_VERTEX_COUNT |
-	     BRW_SF_CTL_SNAPSHOT_ALL_THREADS |
-	     BRW_SF_CTL_THREAD_SNAPSHOT_ENABLE);
-      OUTREG(BRW_SF_STRG_VAL, 0);
-#endif
-
-#if WATCH_WIZ
-      OUTREG(BRW_WIZ_CTL,
-	     BRW_WIZ_CTL_SNAPSHOT_MUX_SUBSPAN_INSTANCE |
-	     BRW_WIZ_CTL_SNAPSHOT_ALL_THREADS |
-	     BRW_WIZ_CTL_SNAPSHOT_ENABLE);
-      OUTREG(BRW_WIZ_STRG_VAL,
-	     (box_x1) | (box_y1 << 16));
-#endif
-      
-#if 0
-      OUTREG(BRW_TS_CTL,
-	     BRW_TS_CTL_SNAPSHOT_MESSAGE_ERROR |
-	     BRW_TS_CTL_SNAPSHOT_ALL_CHILD_THREADS |
-	     BRW_TS_CTL_SNAPSHOT_ALL_ROOT_THREADS |
-	     BRW_TS_CTL_SNAPSHOT_ENABLE);
-#endif
-
-      BEGIN_LP_RING(6);
-      OUT_RING(BRW_3DPRIMITIVE | 
-	       BRW_3DPRIMITIVE_VERTEX_SEQUENTIAL |
-	       (_3DPRIM_RECTLIST << BRW_3DPRIMITIVE_TOPOLOGY_SHIFT) | 
-	       (0 << 9) |  /* CTG - indirect vertex count */
-	       4);
-      OUT_RING(3); /* vertex count per instance */
-      OUT_RING(0); /* start vertex offset */
-      OUT_RING(1); /* single instance */
-      OUT_RING(0); /* start instance location */
-      OUT_RING(0); /* index buffer offset, ignored */
-      ADVANCE_LP_RING();
-
-#if 0
-      for (j = 0; j < 100000; j++) {
-	ctl = INREG(BRW_VF_CTL);
-	 if (ctl & BRW_VF_CTL_SNAPSHOT_COMPLETE)
-	    break;
-      }
-      
-      rdata = INREG(BRW_VF_RDATA);
-      OUTREG(BRW_VF_CTL, 0);
-      ErrorF ("VF_CTL: 0x%08x VF_RDATA: 0x%08x\n", ctl, rdata);
-#endif
-
-#if 0
-      for (j = 0; j < 1000000; j++) {
-	ctl = INREG(BRW_VS_CTL);
-	 if (ctl & BRW_VS_CTL_SNAPSHOT_COMPLETE)
-	    break;
-      }
-
-      rdata = INREG(BRW_VS_RDATA);
-      for (k = 0; k <= 3; k++) {
-	 OUTREG(BRW_VS_CTL,
-		BRW_VS_CTL_SNAPSHOT_COMPLETE |
-		(k << 8));
-	 rdata = INREG(BRW_VS_RDATA);
-	 ErrorF ("VS_CTL: 0x%08x VS_RDATA(%d): 0x%08x\n", ctl, k, rdata);
-      }
-      
-      OUTREG(BRW_VS_CTL, 0);
-#endif
-
-#if WATCH_SF
-      for (j = 0; j < 1000000; j++) {
-	ctl = INREG(BRW_SF_CTL);
-	 if (ctl & BRW_SF_CTL_SNAPSHOT_COMPLETE)
-	    break;
-      }
-
-      for (k = 0; k <= 7; k++) {
-	 OUTREG(BRW_SF_CTL,
-		BRW_SF_CTL_SNAPSHOT_COMPLETE |
-		(k << 8));
-	 rdata = INREG(BRW_SF_RDATA);
-	 ErrorF ("SF_CTL: 0x%08x SF_RDATA(%d): 0x%08x\n", ctl, k, rdata);
-      }
-      
-      OUTREG(BRW_SF_CTL, 0);
-#endif
-
-#if WATCH_WIZ
-      for (j = 0; j < 100000; j++) {
-	ctl = INREG(BRW_WIZ_CTL);
-	 if (ctl & BRW_WIZ_CTL_SNAPSHOT_COMPLETE)
-	    break;
-      }
-      
-      rdata = INREG(BRW_WIZ_RDATA);
-      OUTREG(BRW_WIZ_CTL, 0);
-      ErrorF ("WIZ_CTL: 0x%08x WIZ_RDATA: 0x%08x\n", ctl, rdata);
-#endif
-      
-#if 0
-      for (j = 0; j < 100000; j++) {
-	ctl = INREG(BRW_TS_CTL);
-	 if (ctl & BRW_TS_CTL_SNAPSHOT_COMPLETE)
-	    break;
-      }
-      
-      rdata = INREG(BRW_TS_RDATA);
-      OUTREG(BRW_TS_CTL, 0);
-      ErrorF ("TS_CTL: 0x%08x TS_RDATA: 0x%08x\n", ctl, rdata);
-      
-      ErrorF ("after EU_ATT 0x%08x%08x EU_ATT_DATA 0x%08x%08x\n",
-	      INREG(BRW_EU_ATT_1), INREG(BRW_EU_ATT_0),
-	      INREG(BRW_EU_ATT_DATA_1), INREG(BRW_EU_ATT_DATA_0));
-#endif
-
-#if 0
-      for (j = 0; j < 256; j++) {
-	 OUTREG(BRW_TD_CTL, j << BRW_TD_CTL_MUX_SHIFT);
-	 rdata = INREG(BRW_TD_RDATA);
-	 ErrorF ("TD_RDATA(%d): 0x%08x\n", j, rdata);
-      }
-#endif
-      first_output = FALSE;
-      if (pI830->AccelInfoRec)
-	 pI830->AccelInfoRec->NeedToSync = TRUE;
-   }
-
-   if (pI830->AccelInfoRec)
-      (*pI830->AccelInfoRec->Sync)(pScrn);
-#if WATCH_STATS
-   i830_dump_error_state (pScrn);
-#endif
-}
 
 #ifdef I830_USE_EXA
 static void
@@ -3162,9 +2375,9 @@ I830PutImage(ScrnInfoPtr pScrn,
       I830DisplayVideo(pScrn, destId, width, height, dstPitch,
 		       x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
    } else if (IS_I965G(pI830)) {
-      BroadwaterDisplayVideoTextured (pScrn, pPriv, destId, clipBoxes, width, height,
-				      dstPitch, x1, y1, x2, y2,
-				      src_w, src_h, drw_w, drw_h, pDraw);
+      I965DisplayVideoTextured(pScrn, pPriv, destId, clipBoxes, width, height,
+			       dstPitch, x1, y1, x2, y2,
+			       src_w, src_h, drw_w, drw_h, pDraw);
    } else {
       I915DisplayVideoTextured(pScrn, pPriv, destId, clipBoxes, width, height,
 			       dstPitch, x1, y1, x2, y2,
diff --git a/src/i830_video.h b/src/i830_video.h
index 12a5bda..a00cd50 100644
--- a/src/i830_video.h
+++ b/src/i830_video.h
@@ -88,3 +88,11 @@ void I915DisplayVideoTextured(ScrnInfoPt
 			      short src_w, short src_h,
 			      short drw_w, short drw_h,
 			      DrawablePtr pDraw);
+
+void I965DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv,
+			      int id, RegionPtr dstRegion, short width,
+			      short height, int video_pitch,
+			      int x1, int y1, int x2, int y2,
+			      short src_w, short src_h,
+			      short drw_w, short drw_h,
+			      DrawablePtr pDraw);
diff --git a/src/i965_video.c b/src/i965_video.c
new file mode 100644
index 0000000..3677d9d
--- /dev/null
+++ b/src/i965_video.c
@@ -0,0 +1,827 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric at anholt.net>
+ *    Keith Packard <keithp at keithp.com>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86xv.h"
+#include "fourcc.h"
+
+#include "i830.h"
+#include "i830_video.h"
+#include "brw_defines.h"
+#include "brw_structs.h"
+
+static const CARD32 sip_kernel_static[][4] = {
+/*    wait (1) a0<1>UW a145<0,1,0>UW { align1 +  } */
+    { 0x00000030, 0x20000108, 0x00001220, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/*    nop (4) g0<1>UD { align1 +  } */
+    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+};
+   
+/*
+ * this program computes dA/dx and dA/dy for the texture coordinates along
+ * with the base texture coordinate. It was extracted from the Mesa driver.
+ * It uses about 10 GRF registers.
+ */
+
+#define SF_KERNEL_NUM_GRF  16
+#define SF_MAX_THREADS	   1
+
+static const CARD32 sf_kernel_static[][4] = {
+#include "sf_prog.h"
+};
+
+/*
+ * Ok, this kernel picks up the required data flow values in g0 and g1
+ * and passes those along in m0 and m1. In m2-m9, it sticks constant
+ * values (bright pink).
+ */
+
+/* Our PS kernel uses less than 32 GRF registers (about 20) */
+#define PS_KERNEL_NUM_GRF   32
+#define PS_MAX_THREADS	   32
+
+#define BRW_GRF_BLOCKS(nreg)	((nreg + 15) / 16 - 1)
+
+static const CARD32 ps_kernel_static[][4] = {
+#include "wm_prog.h"
+};
+
+#define ALIGN(i,m)    (((i) + (m) - 1) & ~((m) - 1))
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+
+#define WM_BINDING_TABLE_ENTRIES    2
+
+static CARD32 float_to_uint (float f) {
+   union {CARD32 i; float f;} x;
+   x.f = f;
+   return x.i;
+}
+
+#if 0
+static struct {
+   CARD32   svg_ctl;
+   char	    *name;
+} svg_ctl_bits[] = {
+   { BRW_SVG_CTL_GS_BA, "General State Base Address" },
+   { BRW_SVG_CTL_SS_BA, "Surface State Base Address" },
+   { BRW_SVG_CTL_IO_BA, "Indirect Object Base Address" },
+   { BRW_SVG_CTL_GS_AUB, "Generate State Access Upper Bound" },
+   { BRW_SVG_CTL_IO_AUB, "Indirect Object Access Upper Bound" },
+   { BRW_SVG_CTL_SIP, "System Instruction Pointer" },
+   { 0, 0 },
+};
+
+static void
+brw_debug (ScrnInfoPtr pScrn, char *when)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+   int	    i;
+   CARD32   v;
+   
+   I830Sync (pScrn);
+   ErrorF("brw_debug: %s\n", when);
+   for (i = 0; svg_ctl_bits[i].name; i++) {
+      OUTREG(BRW_SVG_CTL, svg_ctl_bits[i].svg_ctl);
+      v = INREG(BRW_SVG_RDATA);
+      ErrorF("\t%34.34s: 0x%08x\n", svg_ctl_bits[i].name, v);
+   }
+}
+#endif
+
+#define WATCH_SF 0
+#define WATCH_WIZ 0
+#define WATCH_STATS 0
+
+void
+I965DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id,
+			 RegionPtr dstRegion,
+			 short width, short height, int video_pitch,
+			 int x1, int y1, int x2, int y2,
+			 short src_w, short src_h,
+			 short drw_w, short drw_h,
+			 DrawablePtr pDraw)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+   BoxPtr pbox;
+   int nbox, dxo, dyo;
+   int urb_vs_start, urb_vs_size;
+   int urb_gs_start, urb_gs_size;
+   int urb_clip_start, urb_clip_size;
+   int urb_sf_start, urb_sf_size;
+   int urb_cs_start, urb_cs_size;
+   struct brw_surface_state *dest_surf_state;
+   struct brw_surface_state *src_surf_state;
+   struct brw_sampler_state *src_sampler_state;
+   struct brw_vs_unit_state *vs_state;
+   struct brw_sf_unit_state *sf_state;
+   struct brw_wm_unit_state *wm_state;
+   struct brw_cc_unit_state *cc_state;
+   struct brw_cc_viewport *cc_viewport;
+   struct brw_instruction *sf_kernel;
+   struct brw_instruction *ps_kernel;
+   struct brw_instruction *sip_kernel;
+   float *vb;
+    CARD32 *binding_table;
+   Bool first_output = TRUE;
+   int dest_surf_offset, src_surf_offset, src_sampler_offset, vs_offset;
+   int sf_offset, wm_offset, cc_offset, vb_offset, cc_viewport_offset;
+   int wm_scratch_offset;
+   int sf_kernel_offset, ps_kernel_offset, sip_kernel_offset;
+   int binding_table_offset;
+   int next_offset, total_state_size;
+   int vb_size = (4 * 4) * 4; /* 4 DWORDS per vertex */
+   char *state_base;
+   int state_base_offset;
+
+#if 0
+   ErrorF("BroadwaterDisplayVideoTextured: %dx%d (pitch %d)\n", width, height,
+	  video_pitch);
+#endif
+
+   /* enable debug */
+   OUTREG (INST_PM,
+	   (1 << (16 + 4)) |
+	   (1 << 4));
+#if 0
+   ErrorF ("INST_PM 0x%08x\n", INREG(INST_PM));
+#endif
+   
+   assert((id == FOURCC_UYVY) || (id == FOURCC_YUY2));
+
+   /* Tell the rotation code that we have stomped its invariant state by
+    * setting a high bit.  We don't use any invariant 3D state for video, so we
+    * don't have to worry about it ourselves.
+    */
+   *pI830->used3D |= 1 << 30;
+
+#ifdef XF86DRI
+   /* Tell the DRI that we're smashing its state. */
+   if (pI830->directRenderingEnabled) {
+     drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
+
+     pSAREAPriv->ctxOwner = DRIGetContext(pScrn->pScreen);
+   }
+#endif /* XF86DRI */
+
+   next_offset = 0;
+
+   /* Set up our layout of state in framebuffer.  First the general state: */
+   vs_offset = ALIGN(next_offset, 64);
+   next_offset = vs_offset + sizeof(*vs_state);
+   sf_offset = ALIGN(next_offset, 32);
+   next_offset = sf_offset + sizeof(*sf_state);
+   wm_offset = ALIGN(next_offset, 32);
+   next_offset = wm_offset + sizeof(*wm_state);
+   wm_scratch_offset = ALIGN(next_offset, 1024);
+   next_offset = wm_scratch_offset + 1024 * PS_MAX_THREADS;
+   cc_offset = ALIGN(next_offset, 32);
+   next_offset = cc_offset + sizeof(*cc_state);
+
+   sf_kernel_offset = ALIGN(next_offset, 64);
+   next_offset = sf_kernel_offset + sizeof (sf_kernel_static);
+   ps_kernel_offset = ALIGN(next_offset, 64);
+   next_offset = ps_kernel_offset + sizeof (ps_kernel_static);
+   sip_kernel_offset = ALIGN(next_offset, 64);
+   next_offset = sip_kernel_offset + sizeof (sip_kernel_static);
+   cc_viewport_offset = ALIGN(next_offset, 32);
+   next_offset = cc_viewport_offset + sizeof(*cc_viewport);
+
+   src_sampler_offset = ALIGN(next_offset, 32);
+   next_offset = src_sampler_offset + sizeof(*src_sampler_state);
+
+   /* Align VB to native size of elements, for safety */
+   vb_offset = ALIGN(next_offset, 8);
+   next_offset = vb_offset + vb_size;
+
+   /* And then the general state: */
+   dest_surf_offset = ALIGN(next_offset, 32);
+   next_offset = dest_surf_offset + sizeof(*dest_surf_state);
+   src_surf_offset = ALIGN(next_offset, 32);
+   next_offset = src_surf_offset + sizeof(*src_surf_state);
+   binding_table_offset = ALIGN(next_offset, 32);
+   next_offset = binding_table_offset + (WM_BINDING_TABLE_ENTRIES * 4);
+
+   /* Allocate an area in framebuffer for our state layout we just set up */
+   total_state_size = next_offset;
+   assert (total_state_size < BRW_LINEAR_EXTRA);
+
+   /*
+    * Use the extra space allocated at the end of the Xv buffer
+    */
+   state_base_offset = pPriv->extra_offset;
+   state_base_offset = ALIGN(state_base_offset, 64);
+
+   state_base = (char *)(pI830->FbBase + state_base_offset);
+   /* Set up our pointers to state structures in framebuffer.  It would probably
+    * be a good idea to fill these structures out in system memory and then dump
+    * them there, instead.
+    */
+   vs_state = (void *)(state_base + vs_offset);
+   sf_state = (void *)(state_base + sf_offset);
+   wm_state = (void *)(state_base + wm_offset);
+   cc_state = (void *)(state_base + cc_offset);
+   sf_kernel = (void *)(state_base + sf_kernel_offset);
+   ps_kernel = (void *)(state_base + ps_kernel_offset);
+   sip_kernel = (void *)(state_base + sip_kernel_offset);
+   
+   cc_viewport = (void *)(state_base + cc_viewport_offset);
+   dest_surf_state = (void *)(state_base + dest_surf_offset);
+   src_surf_state = (void *)(state_base + src_surf_offset);
+   src_sampler_state = (void *)(state_base + src_sampler_offset);
+   binding_table = (void *)(state_base + binding_table_offset);
+   vb = (void *)(state_base + vb_offset);
+
+   /* For 3D, the VS must have 8, 12, 16, 24, or 32 VUEs allocated to it.
+    * A VUE consists of a 256-bit vertex header followed by the vertex data,
+    * which in our case is 4 floats (128 bits), thus a single 512-bit URB
+    * entry.
+    */
+#define URB_VS_ENTRIES	      8
+#define URB_VS_ENTRY_SIZE     1
+   
+#define URB_GS_ENTRIES	      0
+#define URB_GS_ENTRY_SIZE     0
+   
+#define URB_CLIP_ENTRIES      0
+#define URB_CLIP_ENTRY_SIZE   0
+   
+   /* The SF kernel we use outputs only 4 256-bit registers, leading to an
+    * entry size of 2 512-bit URBs.  We don't need to have many entries to
+    * output as we're generally working on large rectangles and don't care
+    * about having WM threads running on different rectangles simultaneously.
+    */
+#define URB_SF_ENTRIES	      1
+#define URB_SF_ENTRY_SIZE     2
+
+#define URB_CS_ENTRIES	      0
+#define URB_CS_ENTRY_SIZE     0
+   
+   urb_vs_start = 0;
+   urb_vs_size = URB_VS_ENTRIES * URB_VS_ENTRY_SIZE;
+   urb_gs_start = urb_vs_start + urb_vs_size;
+   urb_gs_size = URB_GS_ENTRIES * URB_GS_ENTRY_SIZE;
+   urb_clip_start = urb_gs_start + urb_gs_size;
+   urb_clip_size = URB_CLIP_ENTRIES * URB_CLIP_ENTRY_SIZE;
+   urb_sf_start = urb_clip_start + urb_clip_size;
+   urb_sf_size = URB_SF_ENTRIES * URB_SF_ENTRY_SIZE;
+   urb_cs_start = urb_sf_start + urb_sf_size;
+   urb_cs_size = URB_CS_ENTRIES * URB_CS_ENTRY_SIZE;
+
+   /* We'll be poking the state buffers that could be in use by the 3d hardware
+    * here, but we should have synced the 3D engine already in I830PutImage.
+    */
+
+   memset (cc_viewport, 0, sizeof (*cc_viewport));
+   cc_viewport->min_depth = -1.e35;
+   cc_viewport->max_depth = 1.e35;
+
+   /* Color calculator state */
+   memset(cc_state, 0, sizeof(*cc_state));
+   cc_state->cc0.stencil_enable = 0;   /* disable stencil */
+   cc_state->cc2.depth_test = 0;       /* disable depth test */
+   cc_state->cc2.logicop_enable = 1;   /* enable logic op */
+   cc_state->cc3.ia_blend_enable = 1;  /* blend alpha just like colors */
+   cc_state->cc3.blend_enable = 0;     /* disable color blend */
+   cc_state->cc3.alpha_test = 0;       /* disable alpha test */
+   cc_state->cc4.cc_viewport_state_offset = (state_base_offset + cc_viewport_offset) >> 5;
+   cc_state->cc5.dither_enable = 0;    /* disable dither */
+   cc_state->cc5.logicop_func = 0xc;   /* WHITE */
+   cc_state->cc5.statistics_enable = 1;
+   cc_state->cc5.ia_blend_function = BRW_BLENDFUNCTION_ADD;
+   cc_state->cc5.ia_src_blend_factor = BRW_BLENDFACTOR_ONE;
+   cc_state->cc5.ia_dest_blend_factor = BRW_BLENDFACTOR_ONE;
+
+   /* Upload system kernel */
+   memcpy (sip_kernel, sip_kernel_static, sizeof (sip_kernel_static));
+   
+   /* Set up the state buffer for the destination surface */
+   memset(dest_surf_state, 0, sizeof(*dest_surf_state));
+   dest_surf_state->ss0.surface_type = BRW_SURFACE_2D;
+   dest_surf_state->ss0.data_return_format = BRW_SURFACERETURNFORMAT_FLOAT32;
+   if (pI830->cpp == 2) {
+      dest_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B5G6R5_UNORM;
+   } else {
+      dest_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
+   }
+   dest_surf_state->ss0.writedisable_alpha = 0;
+   dest_surf_state->ss0.writedisable_red = 0;
+   dest_surf_state->ss0.writedisable_green = 0;
+   dest_surf_state->ss0.writedisable_blue = 0;
+   dest_surf_state->ss0.color_blend = 1;
+   dest_surf_state->ss0.vert_line_stride = 0;
+   dest_surf_state->ss0.vert_line_stride_ofs = 0;
+   dest_surf_state->ss0.mipmap_layout_mode = 0;
+   dest_surf_state->ss0.render_cache_read_mode = 0;
+   
+   dest_surf_state->ss1.base_addr = pI830->FrontBuffer.Start;
+   dest_surf_state->ss2.height = pScrn->virtualY - 1;
+   dest_surf_state->ss2.width = pScrn->virtualX - 1;
+   dest_surf_state->ss2.mip_count = 0;
+   dest_surf_state->ss2.render_target_rotation = 0;
+   dest_surf_state->ss3.pitch = (pI830->displayWidth * pI830->cpp) - 1;
+
+   /* Set up the source surface state buffer */
+   memset(src_surf_state, 0, sizeof(*src_surf_state));
+   src_surf_state->ss0.surface_type = BRW_SURFACE_2D;
+/*   src_surf_state->ss0.data_return_format = BRW_SURFACERETURNFORMAT_FLOAT32; */
+   switch (id) {
+   case FOURCC_YUY2:
+      src_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_YCRCB_NORMAL;
+      break;
+   case FOURCC_UYVY:
+      src_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_YCRCB_SWAPY;
+      break;
+   }
+   src_surf_state->ss0.writedisable_alpha = 0;
+   src_surf_state->ss0.writedisable_red = 0;
+   src_surf_state->ss0.writedisable_green = 0;
+   src_surf_state->ss0.writedisable_blue = 0;
+   src_surf_state->ss0.color_blend = 1;
+   src_surf_state->ss0.vert_line_stride = 0;
+   src_surf_state->ss0.vert_line_stride_ofs = 0;
+   src_surf_state->ss0.mipmap_layout_mode = 0;
+   src_surf_state->ss0.render_cache_read_mode = 0;
+   
+   src_surf_state->ss1.base_addr = pPriv->YBuf0offset;
+   src_surf_state->ss2.width = width - 1;
+   src_surf_state->ss2.height = height - 1;
+   src_surf_state->ss2.mip_count = 0;
+   src_surf_state->ss2.render_target_rotation = 0;
+   src_surf_state->ss3.pitch = video_pitch - 1;
+
+   /* Set up a binding table for our two surfaces.  Only the PS will use it */
+   /* XXX: are these offset from the right place? */
+   binding_table[0] = state_base_offset + dest_surf_offset;
+   binding_table[1] = state_base_offset + src_surf_offset;
+
+   /* Set up the packed YUV source sampler.  Doesn't do colorspace conversion.
+    */
+   memset(src_sampler_state, 0, sizeof(*src_sampler_state));
+   src_sampler_state->ss0.min_filter = BRW_MAPFILTER_LINEAR;
+   src_sampler_state->ss0.mag_filter = BRW_MAPFILTER_LINEAR;
+   src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
+   src_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
+   src_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
+
+   /* Set up the vertex shader to be disabled (passthrough) */
+   memset(vs_state, 0, sizeof(*vs_state));
+   vs_state->thread4.nr_urb_entries = URB_VS_ENTRIES;
+   vs_state->thread4.urb_entry_allocation_size = URB_VS_ENTRY_SIZE - 1;
+   vs_state->vs6.vs_enable = 0;
+   vs_state->vs6.vert_cache_disable = 1;
+
+   /* Set up the SF kernel to do coord interp: for each attribute,
+    * calculate dA/dx and dA/dy.  Hand these interpolation coefficients
+    * back to SF which then hands pixels off to WM.
+    */
+
+   memcpy (sf_kernel, sf_kernel_static, sizeof (sf_kernel_static));
+   memset(sf_state, 0, sizeof(*sf_state));
+#if 0
+   ErrorF ("sf kernel: 0x%08x\n", state_base_offset + sf_kernel_offset);
+#endif
+   sf_state->thread0.kernel_start_pointer = 
+	       (state_base_offset + sf_kernel_offset) >> 6;
+   sf_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(SF_KERNEL_NUM_GRF);
+   sf_state->sf1.single_program_flow = 1; /* XXX */
+   sf_state->sf1.binding_table_entry_count = 0;
+   sf_state->sf1.thread_priority = 0;
+   sf_state->sf1.floating_point_mode = 0; /* Mesa does this */
+   sf_state->sf1.illegal_op_exception_enable = 1;
+   sf_state->sf1.mask_stack_exception_enable = 1;
+   sf_state->sf1.sw_exception_enable = 1;
+   sf_state->thread2.per_thread_scratch_space = 0;
+   sf_state->thread2.scratch_space_base_pointer = 0; /* not used in our kernel */
+   sf_state->thread3.const_urb_entry_read_length = 0; /* no const URBs */
+   sf_state->thread3.const_urb_entry_read_offset = 0; /* no const URBs */
+   sf_state->thread3.urb_entry_read_length = 1; /* 1 URB per vertex */
+   sf_state->thread3.urb_entry_read_offset = 0;
+   sf_state->thread3.dispatch_grf_start_reg = 3;
+   sf_state->thread4.max_threads = SF_MAX_THREADS - 1;
+   sf_state->thread4.urb_entry_allocation_size = URB_SF_ENTRY_SIZE - 1;
+   sf_state->thread4.nr_urb_entries = URB_SF_ENTRIES;
+   sf_state->thread4.stats_enable = 1;
+   sf_state->sf5.viewport_transform = FALSE; /* skip viewport */
+   sf_state->sf6.cull_mode = BRW_CULLMODE_NONE;
+   sf_state->sf6.scissor = 0;
+   sf_state->sf7.trifan_pv = 2;
+   sf_state->sf6.dest_org_vbias = 0x8;
+   sf_state->sf6.dest_org_hbias = 0x8;
+
+   memcpy (ps_kernel, ps_kernel_static, sizeof (ps_kernel_static));
+#if 0
+   ErrorF ("ps kernel: 0x%08x\n", state_base_offset + ps_kernel_offset);
+#endif
+   memset (wm_state, 0, sizeof (*wm_state));
+   wm_state->thread0.kernel_start_pointer = 
+	    (state_base_offset + ps_kernel_offset) >> 6;
+   wm_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(PS_KERNEL_NUM_GRF);
+   wm_state->thread1.single_program_flow = 1; /* XXX */
+   wm_state->thread1.binding_table_entry_count = 2;
+   /* Though we never use the scratch space in our WM kernel, it has to be
+    * set, and the minimum allocation is 1024 bytes.
+    */
+   wm_state->thread2.scratch_space_base_pointer = (state_base_offset +
+						   wm_scratch_offset) >> 10;
+   wm_state->thread2.per_thread_scratch_space = 0; /* 1024 bytes */
+   wm_state->thread3.dispatch_grf_start_reg = 3; /* XXX */
+   wm_state->thread3.const_urb_entry_read_length = 0;
+   wm_state->thread3.const_urb_entry_read_offset = 0;
+   wm_state->thread3.urb_entry_read_length = 1; /* XXX */
+   wm_state->thread3.urb_entry_read_offset = 0; /* XXX */
+   wm_state->wm4.stats_enable = 1;
+   wm_state->wm4.sampler_state_pointer = (state_base_offset + src_sampler_offset) >> 5;
+   wm_state->wm4.sampler_count = 1; /* 1-4 samplers used */
+   wm_state->wm5.max_threads = PS_MAX_THREADS - 1;
+   wm_state->wm5.thread_dispatch_enable = 1;
+   wm_state->wm5.enable_16_pix = 1;
+   wm_state->wm5.enable_8_pix = 0;
+   wm_state->wm5.early_depth_test = 1;
+
+   {
+      BEGIN_LP_RING(2);
+      OUT_RING(MI_FLUSH | 
+	       MI_STATE_INSTRUCTION_CACHE_FLUSH |
+	       BRW_MI_GLOBAL_SNAPSHOT_RESET);
+      OUT_RING(MI_NOOP);
+      ADVANCE_LP_RING();
+   }
+   
+/*    brw_debug (pScrn, "before base address modify"); */
+   { BEGIN_LP_RING(12);
+   /* Match Mesa driver setup */
+   OUT_RING(BRW_PIPELINE_SELECT | PIPELINE_SELECT_3D);
+
+   /* Mesa does this. Who knows... */
+   OUT_RING(BRW_CS_URB_STATE | 0);
+   OUT_RING((0 << 4) |	/* URB Entry Allocation Size */
+	    (0 << 0));	/* Number of URB Entries */
+   
+   /* Zero out the two base address registers so all offsets are absolute */
+   OUT_RING(BRW_STATE_BASE_ADDRESS | 4);
+   OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* Generate state base address */
+   OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* Surface state base address */
+   OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* media base addr, don't care */
+   OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY);  /* general state max addr, disabled */
+   OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY);  /* media object state max addr, disabled */
+
+   /* Set system instruction pointer */
+   OUT_RING(BRW_STATE_SIP | 0);
+   OUT_RING(state_base_offset + sip_kernel_offset); /* system instruction pointer */
+      
+   OUT_RING(MI_NOOP);
+   ADVANCE_LP_RING(); }
+   
+/*   brw_debug (pScrn, "after base address modify"); */
+
+   { BEGIN_LP_RING(42);
+   /* Enable VF statistics */
+   OUT_RING(BRW_3DSTATE_VF_STATISTICS | 1);
+   
+   /* Pipe control */
+   OUT_RING(BRW_PIPE_CONTROL |
+	    BRW_PIPE_CONTROL_NOWRITE |
+	    BRW_PIPE_CONTROL_IS_FLUSH |
+	    2);
+   OUT_RING(0);			       /* Destination address */
+   OUT_RING(0);			       /* Immediate data low DW */
+   OUT_RING(0);			       /* Immediate data high DW */
+
+   /* Binding table pointers */
+   OUT_RING(BRW_3DSTATE_BINDING_TABLE_POINTERS | 4);
+   OUT_RING(0); /* vs */
+   OUT_RING(0); /* gs */
+   OUT_RING(0); /* clip */
+   OUT_RING(0); /* sf */
+   /* Only the PS uses the binding table */
+   OUT_RING(state_base_offset + binding_table_offset); /* ps */
+   
+   /* Blend constant color (magenta is fun) */
+   OUT_RING(BRW_3DSTATE_CONSTANT_COLOR | 3);
+   OUT_RING(float_to_uint (1.0));
+   OUT_RING(float_to_uint (0.0));
+   OUT_RING(float_to_uint (1.0));
+   OUT_RING(float_to_uint (1.0));
+   
+   /* The drawing rectangle clipping is always on.  Set it to values that
+    * shouldn't do any clipping.
+    */
+   OUT_RING(BRW_3DSTATE_DRAWING_RECTANGLE | 2);	/* XXX 3 for BLC or CTG */
+   OUT_RING(0x00000000);	/* ymin, xmin */
+   OUT_RING((pScrn->virtualX - 1) |
+	    (pScrn->virtualY - 1) << 16); /* ymax, xmax */
+   OUT_RING(0x00000000);	/* yorigin, xorigin */
+
+   /* skip the depth buffer */
+   /* skip the polygon stipple */
+   /* skip the polygon stipple offset */
+   /* skip the line stipple */
+   
+   /* Set the pointers to the 3d pipeline state */
+   OUT_RING(BRW_3DSTATE_PIPELINED_POINTERS | 5);
+   OUT_RING(state_base_offset + vs_offset);  /* 32 byte aligned */
+   OUT_RING(BRW_GS_DISABLE);		     /* disable GS, resulting in passthrough */
+   OUT_RING(BRW_CLIP_DISABLE);		     /* disable CLIP, resulting in passthrough */
+   OUT_RING(state_base_offset + sf_offset);  /* 32 byte aligned */
+   OUT_RING(state_base_offset + wm_offset);  /* 32 byte aligned */
+   OUT_RING(state_base_offset + cc_offset);  /* 64 byte aligned */
+
+   /* URB fence */
+   OUT_RING(BRW_URB_FENCE |
+	    UF0_CS_REALLOC |
+	    UF0_SF_REALLOC |
+	    UF0_CLIP_REALLOC |
+	    UF0_GS_REALLOC |
+	    UF0_VS_REALLOC |
+	    1);
+   OUT_RING(((urb_clip_start + urb_clip_size) << UF1_CLIP_FENCE_SHIFT) |
+	    ((urb_gs_start + urb_gs_size) << UF1_GS_FENCE_SHIFT) |
+	    ((urb_vs_start + urb_vs_size) << UF1_VS_FENCE_SHIFT));
+   OUT_RING(((urb_cs_start + urb_cs_size) << UF2_CS_FENCE_SHIFT) |
+	    ((urb_sf_start + urb_sf_size) << UF2_SF_FENCE_SHIFT));
+
+   /* Constant buffer state */
+   OUT_RING(BRW_CS_URB_STATE | 0);
+   OUT_RING(((URB_CS_ENTRY_SIZE - 1) << 4) | /* URB Entry Allocation Size */
+	    (URB_CS_ENTRIES << 0));	     /* Number of URB Entries */
+   
+   /* Set up the pointer to our vertex buffer */
+   OUT_RING(BRW_3DSTATE_VERTEX_BUFFERS | 2);
+   OUT_RING((0 << VB0_BUFFER_INDEX_SHIFT) |
+	    VB0_VERTEXDATA |
+	    ((4 * 4) << VB0_BUFFER_PITCH_SHIFT)); /* four 32-bit floats per vertex */
+   OUT_RING(state_base_offset + vb_offset);
+   OUT_RING(3); /* four corners to our rectangle */
+
+   /* Set up our vertex elements, sourced from the single vertex buffer. */
+   OUT_RING(BRW_3DSTATE_VERTEX_ELEMENTS | 3);
+   /* offset 0: X,Y -> {X, Y, 1.0, 1.0} */
+   OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
+	    VE0_VALID |
+	    (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
+	    (0 << VE0_OFFSET_SHIFT));
+   OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
+	    (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
+	    (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
+	    (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
+	    (0 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
+   /* offset 8: S0, T0 -> {S0, T0, 1.0, 1.0} */
+   OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
+	    VE0_VALID |
+	    (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
+	    (8 << VE0_OFFSET_SHIFT));
+   OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
+	    (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
+	    (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
+	    (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
+	    (4 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
+
+   OUT_RING(MI_NOOP);			/* pad to quadword */
+   ADVANCE_LP_RING(); }
+
+   dxo = dstRegion->extents.x1;
+   dyo = dstRegion->extents.y1;
+
+   pbox = REGION_RECTS(dstRegion);
+   nbox = REGION_NUM_RECTS(dstRegion);
+   while (nbox--)
+   {
+      int box_x1 = pbox->x1;
+      int box_y1 = pbox->y1;
+      int box_x2 = pbox->x2;
+      int box_y2 = pbox->y2;
+      int i;
+      float src_scale_x, src_scale_y;
+
+      if (!first_output) {
+	 /* Since we use the same little vertex buffer over and over, sync for
+	  * subsequent rectangles.
+	  */
+	 if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
+	    (*pI830->AccelInfoRec->Sync)(pScrn);
+	    pI830->AccelInfoRec->NeedToSync = FALSE;
+	 }
+      }
+
+      pbox++;
+
+      /* Use normalized texture coordinates */
+      src_scale_x = (float)1.0 / (float)drw_w;
+      src_scale_y  = (float)1.0 / (float)drw_h;
+
+      i = 0;
+      vb[i++] = (box_x2 - dxo) * src_scale_x;
+      vb[i++] = (box_y2 - dyo) * src_scale_y;
+      vb[i++] = (float) box_x2;
+      vb[i++] = (float) box_y2;
+
+      vb[i++] = (box_x1 - dxo) * src_scale_x;
+      vb[i++] = (box_y2 - dyo) * src_scale_y;
+      vb[i++] = (float) box_x1;
+      vb[i++] = (float) box_y2;
+
+      vb[i++] = (box_x1 - dxo) * src_scale_x;
+      vb[i++] = (box_y1 - dyo) * src_scale_y;
+      vb[i++] = (float) box_x1;
+      vb[i++] = (float) box_y1;
+
+#if 0
+      ErrorF ("before EU_ATT 0x%08x%08x EU_ATT_DATA 0x%08x%08x\n",
+	      INREG(BRW_EU_ATT_1), INREG(BRW_EU_ATT_0),
+	      INREG(BRW_EU_ATT_DATA_1), INREG(BRW_EU_ATT_DATA_0));
+
+      OUTREG(BRW_VF_CTL,
+	     BRW_VF_CTL_SNAPSHOT_MUX_SELECT_THREADID |
+	     BRW_VF_CTL_SNAPSHOT_TYPE_VERTEX_INDEX |
+	     BRW_VF_CTL_SNAPSHOT_ENABLE);
+      OUTREG(BRW_VF_STRG_VAL, 0);
+#endif
+      
+#if 0
+      OUTREG(BRW_VS_CTL,
+	     BRW_VS_CTL_SNAPSHOT_ALL_THREADS |
+	     BRW_VS_CTL_SNAPSHOT_MUX_VALID_COUNT |
+	     BRW_VS_CTL_THREAD_SNAPSHOT_ENABLE);
+      
+      OUTREG(BRW_VS_STRG_VAL, 0);
+#endif
+      
+#if WATCH_SF
+      OUTREG(BRW_SF_CTL,
+	     BRW_SF_CTL_SNAPSHOT_MUX_VERTEX_COUNT |
+	     BRW_SF_CTL_SNAPSHOT_ALL_THREADS |
+	     BRW_SF_CTL_THREAD_SNAPSHOT_ENABLE);
+      OUTREG(BRW_SF_STRG_VAL, 0);
+#endif
+
+#if WATCH_WIZ
+      OUTREG(BRW_WIZ_CTL,
+	     BRW_WIZ_CTL_SNAPSHOT_MUX_SUBSPAN_INSTANCE |
+	     BRW_WIZ_CTL_SNAPSHOT_ALL_THREADS |
+	     BRW_WIZ_CTL_SNAPSHOT_ENABLE);
+      OUTREG(BRW_WIZ_STRG_VAL,
+	     (box_x1) | (box_y1 << 16));
+#endif
+      
+#if 0
+      OUTREG(BRW_TS_CTL,
+	     BRW_TS_CTL_SNAPSHOT_MESSAGE_ERROR |
+	     BRW_TS_CTL_SNAPSHOT_ALL_CHILD_THREADS |
+	     BRW_TS_CTL_SNAPSHOT_ALL_ROOT_THREADS |
+	     BRW_TS_CTL_SNAPSHOT_ENABLE);
+#endif
+
+      BEGIN_LP_RING(6);
+      OUT_RING(BRW_3DPRIMITIVE | 
+	       BRW_3DPRIMITIVE_VERTEX_SEQUENTIAL |
+	       (_3DPRIM_RECTLIST << BRW_3DPRIMITIVE_TOPOLOGY_SHIFT) | 
+	       (0 << 9) |  /* CTG - indirect vertex count */
+	       4);
+      OUT_RING(3); /* vertex count per instance */
+      OUT_RING(0); /* start vertex offset */
+      OUT_RING(1); /* single instance */
+      OUT_RING(0); /* start instance location */
+      OUT_RING(0); /* index buffer offset, ignored */
+      ADVANCE_LP_RING();
+
+#if 0
+      for (j = 0; j < 100000; j++) {
+	ctl = INREG(BRW_VF_CTL);
+	 if (ctl & BRW_VF_CTL_SNAPSHOT_COMPLETE)
+	    break;
+      }
+      
+      rdata = INREG(BRW_VF_RDATA);
+      OUTREG(BRW_VF_CTL, 0);
+      ErrorF ("VF_CTL: 0x%08x VF_RDATA: 0x%08x\n", ctl, rdata);
+#endif
+
+#if 0
+      for (j = 0; j < 1000000; j++) {
+	ctl = INREG(BRW_VS_CTL);
+	 if (ctl & BRW_VS_CTL_SNAPSHOT_COMPLETE)
+	    break;
+      }
+
+      rdata = INREG(BRW_VS_RDATA);
+      for (k = 0; k <= 3; k++) {
+	 OUTREG(BRW_VS_CTL,
+		BRW_VS_CTL_SNAPSHOT_COMPLETE |
+		(k << 8));
+	 rdata = INREG(BRW_VS_RDATA);
+	 ErrorF ("VS_CTL: 0x%08x VS_RDATA(%d): 0x%08x\n", ctl, k, rdata);
+      }
+      
+      OUTREG(BRW_VS_CTL, 0);
+#endif
+
+#if WATCH_SF
+      for (j = 0; j < 1000000; j++) {
+	ctl = INREG(BRW_SF_CTL);
+	 if (ctl & BRW_SF_CTL_SNAPSHOT_COMPLETE)
+	    break;
+      }
+
+      for (k = 0; k <= 7; k++) {
+	 OUTREG(BRW_SF_CTL,
+		BRW_SF_CTL_SNAPSHOT_COMPLETE |
+		(k << 8));
+	 rdata = INREG(BRW_SF_RDATA);
+	 ErrorF ("SF_CTL: 0x%08x SF_RDATA(%d): 0x%08x\n", ctl, k, rdata);
+      }
+      
+      OUTREG(BRW_SF_CTL, 0);
+#endif
+
+#if WATCH_WIZ
+      for (j = 0; j < 100000; j++) {
+	ctl = INREG(BRW_WIZ_CTL);
+	 if (ctl & BRW_WIZ_CTL_SNAPSHOT_COMPLETE)
+	    break;
+      }
+      
+      rdata = INREG(BRW_WIZ_RDATA);
+      OUTREG(BRW_WIZ_CTL, 0);
+      ErrorF ("WIZ_CTL: 0x%08x WIZ_RDATA: 0x%08x\n", ctl, rdata);
+#endif
+      
+#if 0
+      for (j = 0; j < 100000; j++) {
+	ctl = INREG(BRW_TS_CTL);
+	 if (ctl & BRW_TS_CTL_SNAPSHOT_COMPLETE)
+	    break;
+      }
+      
+      rdata = INREG(BRW_TS_RDATA);
+      OUTREG(BRW_TS_CTL, 0);
+      ErrorF ("TS_CTL: 0x%08x TS_RDATA: 0x%08x\n", ctl, rdata);
+      
+      ErrorF ("after EU_ATT 0x%08x%08x EU_ATT_DATA 0x%08x%08x\n",
+	      INREG(BRW_EU_ATT_1), INREG(BRW_EU_ATT_0),
+	      INREG(BRW_EU_ATT_DATA_1), INREG(BRW_EU_ATT_DATA_0));
+#endif
+
+#if 0
+      for (j = 0; j < 256; j++) {
+	 OUTREG(BRW_TD_CTL, j << BRW_TD_CTL_MUX_SHIFT);
+	 rdata = INREG(BRW_TD_RDATA);
+	 ErrorF ("TD_RDATA(%d): 0x%08x\n", j, rdata);
+      }
+#endif
+      first_output = FALSE;
+      if (pI830->AccelInfoRec)
+	 pI830->AccelInfoRec->NeedToSync = TRUE;
+   }
+
+   if (pI830->AccelInfoRec)
+      (*pI830->AccelInfoRec->Sync)(pScrn);
+#if WATCH_STATS
+   i830_dump_error_state (pScrn);
+#endif
+}
diff-tree 46df75ccd4647ea033583130253a2a2218b34a20 (from 84915ac8afeb4bbc03df8f94ab3ba351788d6501)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Dec 27 13:45:06 2006 -0800

    Bug #7524: Major improvements to EXA/XAA static memory allocation.
    
    With this, we no longer allocate XV through the XF86 linear allocator in the
    EXA case.  We also no longer allocate extra space for the XF86 2D allocator
    that we don't use in EXA mode, or space for the EXA allocator in XAA mode.
    The EXA offscreen allocator now gets enough space for several screenfuls of
    pixmaps plus one 1920x1088 movie.
    
    A large duplicated section of code for allocating each framebuffer in the old
    dual-screen mode was also factored out.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index d30af07..e2653c1 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2855,20 +2855,28 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 
    DPRINTF(PFX,
 	   "assert( if(!I830InitFBManager(pScreen, &(pI830->FbMemBox))) )\n");
-   if (I830IsPrimary(pScrn)) {
-      if (!I830InitFBManager(pScreen, &(pI830->FbMemBox))) {
-         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		 "Failed to init memory manager\n");
-      }
-
-      if (pI830->LinearAlloc && xf86InitFBManagerLinear(pScreen, pI830->LinearMem.Offset / pI830->cpp, pI830->LinearMem.Size / pI830->cpp))
-            xf86DrvMsg(scrnIndex, X_INFO, 
-			"Using %ld bytes of offscreen memory for linear (offset=0x%lx)\n", pI830->LinearMem.Size, pI830->LinearMem.Offset);
+   if (!pI830->useEXA) {
+      if (I830IsPrimary(pScrn)) {
+	 if (!I830InitFBManager(pScreen, &(pI830->FbMemBox))) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Failed to init memory manager\n");
+	 }
 
-   } else {
-      if (!I830InitFBManager(pScreen, &(pI8301->FbMemBox2))) {
-         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		 "Failed to init memory manager\n");
+	 if (pI830->LinearAlloc &&
+	     xf86InitFBManagerLinear(pScreen,
+				     pI830->LinearMem.Offset / pI830->cpp,
+				     pI830->LinearMem.Size / pI830->cpp))
+	 {
+            xf86DrvMsg(scrnIndex, X_INFO,
+		       "Using %ld bytes of offscreen memory for linear "
+		       "(offset=0x%lx)\n", pI830->LinearMem.Size,
+		       pI830->LinearMem.Offset);
+	 }
+      } else {
+	 if (!I830InitFBManager(pScreen, &(pI8301->FbMemBox2))) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Failed to init memory manager\n");
+	 }
       }
    }
 
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 7b0c6fe..b41a73d 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -602,11 +602,141 @@ GetFreeSpace(ScrnInfoPtr pScrn)
    return extra;
 }
 
+/**
+ * Allocates a framebuffer for a screen.
+ *
+ * Used once for each X screen, so once with RandR 1.2 and twice with classic
+ * dualhead.
+ *
+ * \param pScrn ScrnInfoPtr for the screen being allocated
+ * \param pI830 I830Ptr for the screen being allocated.
+ * \param FbMemBox
+ */
+static Bool
+I830AllocateFramebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox,
+			I830MemRange *FrontBuffer, I830MemPool *StolenPool,
+			Bool secondary, const int flags)
+{
+   Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
+   unsigned long minspace, avail, lineSize;
+   int cacheLines, maxCacheLines;
+   int verbosity = dryrun ? 4 : 1;
+   const char *s = dryrun ? "[dryrun] " : "";
+   Bool tileable;
+   int align, alignflags;
+   long size, alloced, fb_height;
+
+   /* Clear everything first. */
+   memset(FbMemBox, 0, sizeof(*FbMemBox));
+   memset(FrontBuffer, 0, sizeof(*FrontBuffer));
+   FrontBuffer->Key = -1;
+
+   /* We'll allocate the fb such that the root window will fit regardless of
+    * rotation.
+    */
+   if (pScrn->virtualX > pScrn->virtualY)
+      fb_height = pScrn->virtualX;
+   else
+      fb_height = pScrn->virtualY;
+
+   FbMemBox->x1 = 0;
+   FbMemBox->x2 = pScrn->displayWidth;
+   FbMemBox->y1 = 0;
+   FbMemBox->y2 = fb_height;
+
+   /* Calculate how much framebuffer memory to allocate.  For the
+    * initial allocation, calculate a reasonable minimum.  This is
+    * enough for the virtual screen size, plus some pixmap cache
+    * space if we're using XAA.
+    */
+
+   lineSize = pScrn->displayWidth * pI830->cpp;
+   minspace = lineSize * pScrn->virtualY;
+   avail = pScrn->videoRam * 1024;
+
+   if (!pI830->useEXA) {
+      maxCacheLines = (avail - minspace) / lineSize;
+      /* This shouldn't happen. */
+      if (maxCacheLines < 0) {
+	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		    "Internal Error: "
+		    "maxCacheLines < 0 in I830Allocate2DMemory()\n");
+	 maxCacheLines = 0;
+      }
+      if (maxCacheLines > (MAX_DISPLAY_HEIGHT - pScrn->virtualY))
+	 maxCacheLines = MAX_DISPLAY_HEIGHT - pScrn->virtualY;
+
+      if (pI830->CacheLines >= 0) {
+	 cacheLines = pI830->CacheLines;
+      } else {
+#if 1
+	 /* Make sure there is enough for two DVD sized YUV buffers */
+	 cacheLines = (pScrn->depth == 24) ? 256 : 384;
+	 if (pScrn->displayWidth <= 1024)
+	    cacheLines *= 2;
+#else
+	 /*
+	  * Make sure there is enough for two DVD sized YUV buffers.
+	  * Make that 1.5MB, which is around what was allocated with
+	  * the old algorithm
+	  */
+	 cacheLines = (MB(1) + KB(512)) / pI830->cpp / pScrn->displayWidth;
+#endif
+      }
+      if (cacheLines > maxCacheLines)
+	 cacheLines = maxCacheLines;
+
+      FbMemBox->y2 += cacheLines;
+
+      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		     "%sAllocating at least %d scanlines for pixmap cache\n",
+		     s, cacheLines);
+   } else {
+     /* For EXA, we have a separate allocation for the linear allocator which
+      * also does the pixmap cache.
+      */
+     cacheLines = 0;
+   }
+
+   tileable = !(flags & ALLOC_NO_TILING) && pI830->allowPageFlip &&
+      IsTileable(pScrn->displayWidth * pI830->cpp);
+   if (tileable) {
+      if (IS_I9XX(pI830))
+	 align = MB(1);
+      else
+	 align = KB(512);
+      alignflags = ALIGN_BOTH_ENDS;
+   } else {
+      align = KB(64);
+      alignflags = 0;
+   }
+
+   size = lineSize * (fb_height + cacheLines);
+   size = ROUND_TO_PAGE(size);
+   xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		  "%sInitial %sframebuffer allocation size: %ld kByte\n",
+		  s, secondary ? "secondary " : "",
+		  size / 1024);
+   alloced = I830AllocVidMem(pScrn, FrontBuffer,
+			     StolenPool, size, align,
+			     flags | alignflags |
+			     FROM_ANYWHERE | ALLOCATE_AT_BOTTOM);
+   if (alloced < size) {
+      if (!dryrun) {
+	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate "
+		    "%sframebuffer. Is your VideoRAM set too low?\n",
+		    secondary ? "secondary " : "");
+      }
+      return FALSE;
+   }
+
+   return TRUE;
+}
+
 /*
  * Allocate memory for 2D operation.  This includes the (front) framebuffer,
  * ring buffer, scratch memory, HW cursor.
  */
-
 Bool
 I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags)
 {
@@ -648,8 +778,6 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
 	   pI830->StolenPool.Free.Size);
 
    if (flags & ALLOC_INITIAL) {
-      unsigned long minspace, avail, lineSize;
-      int cacheLines, maxCacheLines;
 
       if (pI830->NeedRingBufferLow)
 	 AllocateRingBuffer(pScrn, flags | FORCE_LOW);
@@ -660,242 +788,45 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
          I830EntPtr pI830Ent = pI830->entityPrivate;
          I830Ptr pI8302 = I830PTR(pI830Ent->pScrn_2);
 
-         /* Clear everything first. */
-         memset(&(pI830->FbMemBox2), 0, sizeof(pI830->FbMemBox2));
-         memset(&(pI830->FrontBuffer2), 0, sizeof(pI830->FrontBuffer2));
-         pI830->FrontBuffer2.Key = -1;
-
-#if 1 /* ROTATION */
-         pI830->FbMemBox2.x1 = 0;
-         pI830->FbMemBox2.x2 = pI830Ent->pScrn_2->displayWidth;
-         pI830->FbMemBox2.y1 = 0;
-         if (pI830Ent->pScrn_2->virtualX > pI830Ent->pScrn_2->virtualY)
-            pI830->FbMemBox2.y2 = pI830Ent->pScrn_2->virtualX;
-         else
-            pI830->FbMemBox2.y2 = pI830Ent->pScrn_2->virtualY;
-#else
-         pI830->FbMemBox2.x1 = 0;
-         pI830->FbMemBox2.x2 = pI830Ent->pScrn_2->displayWidth;
-         pI830->FbMemBox2.y1 = 0;
-         pI830->FbMemBox2.y2 = pI830Ent->pScrn_2->virtualY;
-#endif
-
-         /*
-          * Calculate how much framebuffer memory to allocate.  For the
-          * initial allocation, calculate a reasonable minimum.  This is
-          * enough for the virtual screen size, plus some pixmap cache
-          * space.
-          */
-
-         lineSize = pI830Ent->pScrn_2->displayWidth * pI8302->cpp;
-         minspace = lineSize * pI830Ent->pScrn_2->virtualY;
-         avail = pI830Ent->pScrn_2->videoRam * 1024;
-         maxCacheLines = (avail - minspace) / lineSize;
-         /* This shouldn't happen. */
-         if (maxCacheLines < 0) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		    "Internal Error: "
-		    "maxCacheLines < 0 in I830Allocate2DMemory()\n");
-	    maxCacheLines = 0;
-         }
-         if (maxCacheLines > (MAX_DISPLAY_HEIGHT - pI830Ent->pScrn_2->virtualY))
-	    maxCacheLines = MAX_DISPLAY_HEIGHT - pI830Ent->pScrn_2->virtualY;
-
-         if (pI8302->CacheLines >= 0) {
-	    cacheLines = pI8302->CacheLines;
-         } else {
-#if 1
-	    /* Make sure there is enough for two DVD sized YUV buffers */
-	    cacheLines = (pI830Ent->pScrn_2->depth == 24) ? 256 : 384;
-	    if (pI830Ent->pScrn_2->displayWidth <= 1024)
-	       cacheLines *= 2;
-#else
-	    /*
-	     * Make sure there is enough for two DVD sized YUV buffers.
-	     * Make that 1.5MB, which is around what was allocated with
-	     * the old algorithm
-	     */
-	    cacheLines = (MB(1) + KB(512)) / pI8302->cpp / pI830Ent->pScrn_2->displayWidth;
-#endif
-         }
-         if (cacheLines > maxCacheLines)
-	    cacheLines = maxCacheLines;
-
-         pI830->FbMemBox2.y2 += cacheLines;
-
-         xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-		     "%sAllocating at least %d scanlines for pixmap cache\n",
-		     s, cacheLines);
-
-         tileable = !(flags & ALLOC_NO_TILING) && pI8302->allowPageFlip &&
-		 IsTileable(pI830Ent->pScrn_2->displayWidth * pI8302->cpp);
-         if (tileable) {
-            if (IS_I9XX(pI830))
-               align = MB(1);
-            else
-	       align = KB(512);
-	    alignflags = ALIGN_BOTH_ENDS;
-         } else {
-	    align = KB(64);
-	    alignflags = 0;
-         }
-
-#if 1 /* ROTATION */
-         if (pI830Ent->pScrn_2->virtualX > pI830Ent->pScrn_2->virtualY)
-            size = lineSize * (pI830Ent->pScrn_2->virtualX + cacheLines);
-         else 
-            size = lineSize * (pI830Ent->pScrn_2->virtualY + cacheLines);
-         size = ROUND_TO_PAGE(size);
-#else
-         size = lineSize * (pI830Ent->pScrn_2->virtualY + cacheLines);
-         size = ROUND_TO_PAGE(size);
-#endif
-         xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-		     "%sSecondary framebuffer allocation size: %ld kByte\n", s,
-		     size / 1024);
-         alloced = I830AllocVidMem(pScrn, &(pI830->FrontBuffer2),
-				&(pI830->StolenPool), size, align,
-				flags | alignflags |
-				FROM_ANYWHERE | ALLOCATE_AT_BOTTOM);
-         if (alloced < size) {
-	    if (!dryrun) {
-	       xf86DrvMsg(pI830Ent->pScrn_2->scrnIndex, X_ERROR,
-		       "Failed to allocate secondary framebuffer.\n");
-	    }
-            return FALSE;
-         }
-      }
-
-      /* Clear everything first. */
-      memset(&(pI830->FbMemBox), 0, sizeof(pI830->FbMemBox));
-      memset(&(pI830->FrontBuffer), 0, sizeof(pI830->FrontBuffer));
-      pI830->FrontBuffer.Key = -1;
-
-#if 1 /* ROTATION */
-      pI830->FbMemBox.x1 = 0;
-      pI830->FbMemBox.x2 = pScrn->displayWidth;
-      pI830->FbMemBox.y1 = 0;
-      if (pScrn->virtualX > pScrn->virtualY)
-         pI830->FbMemBox.y2 = pScrn->virtualX;
-      else
-         pI830->FbMemBox.y2 = pScrn->virtualY;
-#else
-      pI830->FbMemBox.x1 = 0;
-      pI830->FbMemBox.x2 = pScrn->displayWidth;
-      pI830->FbMemBox.y1 = 0;
-      pI830->FbMemBox.y2 = pScrn->virtualY;
-#endif
-
-      /*
-       * Calculate how much framebuffer memory to allocate.  For the
-       * initial allocation, calculate a reasonable minimum.  This is
-       * enough for the virtual screen size, plus some pixmap cache
-       * space.
-       */
-
-      lineSize = pScrn->displayWidth * pI830->cpp;
-      minspace = lineSize * pScrn->virtualY;
-      avail = pScrn->videoRam * 1024;
-      maxCacheLines = (avail - minspace) / lineSize;
-      /* This shouldn't happen. */
-      if (maxCacheLines < 0) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		    "Internal Error: "
-		    "maxCacheLines < 0 in I830Allocate2DMemory()\n");
-	 maxCacheLines = 0;
-      }
-      if (maxCacheLines > (MAX_DISPLAY_HEIGHT - pScrn->virtualY))
-	 maxCacheLines = MAX_DISPLAY_HEIGHT - pScrn->virtualY;
-
-      if (pI830->CacheLines >= 0) {
-	 cacheLines = pI830->CacheLines;
-      } else {
-#if 1
-	 /* Make sure there is enough for two DVD sized YUV buffers */
-	 cacheLines = (pScrn->depth == 24) ? 256 : 384;
-	 if (pScrn->displayWidth <= 1024)
-	    cacheLines *= 2;
-#else
-	 /*
-	  * Make sure there is enough for two DVD sized YUV buffers.
-	  * Make that 1.5MB, which is around what was allocated with
-	  * the old algorithm
-	  */
-	 cacheLines = (MB(1) + KB(512)) / pI830->cpp / pScrn->displayWidth;
-#endif
-      }
-      if (cacheLines > maxCacheLines)
-	 cacheLines = maxCacheLines;
-
-      pI830->FbMemBox.y2 += cacheLines;
-
-      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-		     "%sAllocating at least %d scanlines for pixmap cache\n",
-		     s, cacheLines);
-
-      tileable = !(flags & ALLOC_NO_TILING) && pI830->allowPageFlip &&
-		 IsTileable(pScrn->displayWidth * pI830->cpp);
-      if (tileable) {
-         if (IS_I9XX(pI830))
-            align = MB(1);
-         else
-	    align = KB(512);
-	 alignflags = ALIGN_BOTH_ENDS;
-      } else {
-	 align = KB(64);
-	 alignflags = 0;
-      }
-
-#if 1 /* ROTATION */
-      if (pScrn->virtualX > pScrn->virtualY)
-         size = lineSize * (pScrn->virtualX + cacheLines);
-      else 
-         size = lineSize * (pScrn->virtualY + cacheLines);
-      size = ROUND_TO_PAGE(size);
-#else
-      size = lineSize * (pScrn->virtualY + cacheLines);
-      size = ROUND_TO_PAGE(size);
-#endif
-      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-		     "%sInitial framebuffer allocation size: %ld kByte\n", s,
-		     size / 1024);
-      alloced = I830AllocVidMem(pScrn, &(pI830->FrontBuffer),
-				&(pI830->StolenPool), size, align,
-				flags | alignflags |
-				FROM_ANYWHERE | ALLOCATE_AT_BOTTOM);
-      if (alloced < size) {
-	 if (!dryrun) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate "
-	    		"framebuffer. Is your VideoRAM set too low ??\n");
+	 if (!I830AllocateFramebuffer(pI830Ent->pScrn_2, pI8302,
+				      &pI830->FbMemBox2,
+				      &pI830->FrontBuffer2, &pI830->StolenPool,
+				      TRUE, flags))
+	 {
+	    return FALSE;
 	 }
-	 return FALSE;
       }
-#ifdef I830_USE_EXA
-      size = lineSize * pScrn->virtualY;
-      size = ROUND_TO_PAGE(size);
-
-      if (tileable) {
-	 align = KB(512);
-	 alignflags = ALIGN_BOTH_ENDS;
-      } else {
-	 align = KB(64);
-	 alignflags = 0;
+      if (!I830AllocateFramebuffer(pScrn, pI830, &pI830->FbMemBox,
+				   &pI830->FrontBuffer, &pI830->StolenPool,
+				   FALSE, flags))
+      {
+	 return FALSE;
       }
 
-      alloced = I830AllocVidMem(pScrn, &(pI830->Offscreen),
-				&(pI830->StolenPool), size, align,
-				flags | alignflags |
-				FROM_ANYWHERE | ALLOCATE_AT_BOTTOM);
-      if (alloced < size) {
-	 if (!dryrun) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate "
-		       "offscreen memory.  Not enough VRAM?\n");
+#ifdef I830_USE_EXA
+      if (pI830->useEXA) {
+	 /* Default EXA to having 3 screens worth of offscreen memory space
+	  * (for pixmaps), plus a double-buffered, 1920x1088 video's worth.
+	  */
+	 size = 3 * pScrn->displayWidth * pI830->cpp * pScrn->virtualY;
+	 size += 1920 * 1088 * 2 * 2;
+	 size = ROUND_TO_PAGE(size);
+
+	 alloced = I830AllocVidMem(pScrn, &(pI830->Offscreen),
+				   &(pI830->StolenPool), size, 1,
+				   flags |
+				   FROM_ANYWHERE | ALLOCATE_AT_BOTTOM);
+	 if (alloced < size) {
+	    if (!dryrun) {
+	       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate "
+			  "offscreen memory.  Not enough VRAM?\n");
+	    }
+	    return FALSE;
+	 } else {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Successful allocation of "
+		       "EXA offscreen memory at 0x%lx, size %ld KB\n",
+		       pI830->Offscreen.Start, pI830->Offscreen.Size/1024);
 	 }
-	 return FALSE;
-      } else {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Successful allocate "
-		       "offscreen memory at 0x%lx, size %ld KB\n", 
-			pI830->Offscreen.Start, pI830->Offscreen.Size/1024);
       }
 #endif
    } else {
diff --git a/src/i830_video.c b/src/i830_video.c
index d10fd16..946a447 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -120,8 +120,8 @@ static int I830QueryImageAttributesTextu
 
 static void I830BlockHandler(int, pointer, pointer, pointer);
 
-static FBLinearPtr
-I830AllocateMemory(ScrnInfoPtr pScrn, FBLinearPtr linear, int size);
+static void
+I830FreeMemory(ScrnInfoPtr pScrn, struct linear_alloc *linear);
 
 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
 
@@ -715,7 +715,7 @@ I830SetupImageVideoOverlay(ScreenPtr pSc
    pPriv->contrast = 64;
    pPriv->saturation = 128;
    pPriv->pipe = 0;  /* XXX must choose pipe wisely */
-   pPriv->linear = NULL;
+   memset(&pPriv->linear, 0, sizeof(pPriv->linear));
    pPriv->currentBuf = 0;
    pPriv->gamma5 = 0xc0c0c0;
    pPriv->gamma4 = 0x808080;
@@ -838,7 +838,7 @@ I830SetupImageVideoTextured(ScreenPtr pS
 
       pPriv->textured = TRUE;
       pPriv->videoStatus = 0;
-      pPriv->linear = NULL;
+      memset(&pPriv->linear, 0, sizeof(pPriv->linear));
       pPriv->currentBuf = 0;
       pPriv->doubleBuffer = 0;
 
@@ -902,10 +902,7 @@ I830StopVideo(ScrnInfoPtr pScrn, pointer
          if (pI830->entityPrivate)
             pI830->entityPrivate->XvInUse = -1;
       }
-      if (pPriv->linear) {
-	 xf86FreeOffscreenLinear(pPriv->linear);
-	 pPriv->linear = NULL;
-      }
+      I830FreeMemory(pScrn, &pPriv->linear);
       pPriv->videoStatus = 0;
    } else {
       if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
@@ -2224,9 +2221,7 @@ BroadwaterDisplayVideoTextured(ScrnInfoP
    /*
     * Use the extra space allocated at the end of the Xv buffer
     */
-   state_base_offset = (pPriv->YBuf0offset + 
-			pPriv->linear->size * pI830->cpp -
-			BRW_LINEAR_EXTRA);
+   state_base_offset = pPriv->extra_offset;
    state_base_offset = ALIGN(state_base_offset, 64);
 
    state_base = (char *)(pI830->FbBase + state_base_offset);
@@ -2798,44 +2793,119 @@ BroadwaterDisplayVideoTextured(ScrnInfoP
 #endif
 }
 
-static FBLinearPtr
-I830AllocateMemory(ScrnInfoPtr pScrn, FBLinearPtr linear, int size)
+#ifdef I830_USE_EXA
+static void
+I830VideoSave(ScreenPtr pScreen, ExaOffscreenArea *area)
+{
+   struct linear_alloc *linear = area->privData;
+
+   linear->exa = NULL;
+   linear->offset = 0;
+}
+#endif /* I830_USE_EXA */
+
+/**
+ * Allocates linear memory using the XFree86 (XAA) or EXA allocator.
+ *
+ * \param pPriv adaptor the memory is being allocated for.
+ * \param size size of the allocation, in bytes.
+ * \param alignment offset alignment of the allocation, in bytes.
+ * \return offset of the allocated memory.
+ */
+static void
+I830AllocateMemory(ScrnInfoPtr pScrn, struct linear_alloc *linear, int size,
+		   int align)
 {
-   ScreenPtr pScreen;
-   FBLinearPtr new_linear = NULL;
+   ScreenPtr pScreen = pScrn->pScreen;
+   I830Ptr pI830 = I830PTR(pScrn);
 
-   if (linear) {
-      if (linear->size >= size)
-	 return linear;
+#ifdef I830_USE_EXA
+   if (pI830->useEXA) {
+      if (linear->exa != NULL) {
+	 if (linear->exa->size >= size)
+	    return;
 
-      if (xf86ResizeOffscreenLinear(linear, size))
-	 return linear;
+	 exaOffscreenFree(pScreen, linear->exa);
+	 linear->offset = 0;
+      }
 
-      xf86FreeOffscreenLinear(linear);
+      linear->exa = exaOffscreenAlloc(pScreen, size, align, TRUE,
+				      I830VideoSave, linear);
+      if (linear->exa == NULL)
+	 return;
+      linear->offset = linear->exa->offset;
    }
+#endif /* I830_USE_EXA */
+#ifdef I830_USE_XAA
+   if (!pI830->useEXA) {
+      int max_size;
 
-   pScreen = screenInfo.screens[pScrn->scrnIndex];
+      /* The XFree86 linear allocator operates in units of screen pixels,
+       * sadly.
+       */
+      size = (size + pI830->cpp - 1) / pI830->cpp;
+      align = (align + pI830->cpp - 1) / pI830->cpp;
 
-   new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4,
-					    NULL, NULL, NULL);
+      if (linear->xaa != NULL) {
+	 if (linear->xaa->size >= size) {
+	    linear->offset = linear->xaa->offset * pI830->cpp;
+	    return;
+	 }
 
-   if (!new_linear) {
-      int max_size;
+	 if (xf86ResizeOffscreenLinear(linear->xaa, size)) {
+	    linear->offset = linear->xaa->offset * pI830->cpp;
+	    return;
+	 }
+
+	 xf86FreeOffscreenLinear(linear->xaa);
+      }
+
+      linear->xaa = xf86AllocateOffscreenLinear(pScreen, size, align,
+						NULL, NULL, NULL);
+      if (linear->xaa != NULL) {
+	 linear->offset = linear->xaa->offset * pI830->cpp;
+	 return;
+      }
 
-      xf86QueryLargestOffscreenLinear(pScreen, &max_size, 4,
+      xf86QueryLargestOffscreenLinear(pScreen, &max_size, align,
 				      PRIORITY_EXTREME);
 
       if (max_size < size) {
-         ErrorF("No memory available\n");
-	 return NULL;
+	 ErrorF("No memory available\n");
+	 linear->offset = 0;
+	 return;
       }
 
       xf86PurgeUnlockedOffscreenAreas(pScreen);
-      new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4,
-					       NULL, NULL, NULL);
+      linear->xaa = xf86AllocateOffscreenLinear(pScreen, size, 4,
+						NULL, NULL, NULL);
+      linear->offset = linear->xaa->offset * pI830->cpp;
    }
+#endif /* I830_USE_XAA */
+}
 
-   return new_linear;
+static void
+I830FreeMemory(ScrnInfoPtr pScrn, struct linear_alloc *linear)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+
+#ifdef I830_USE_EXA
+   if (pI830->useEXA) {
+      if (linear->exa != NULL) {
+	 exaOffscreenFree(pScrn->pScreen, linear->exa);
+	 linear->exa = NULL;
+      }
+   }
+#endif /* I830_USE_EXA */
+#ifdef I830_USE_XAA
+   if (!pI830->useEXA) {
+      if (linear->xaa != NULL) {
+	 xf86FreeOffscreenLinear(linear->xaa);
+	 linear->xaa = NULL;
+      }
+   }
+#endif /* I830_USE_XAA */
+   linear->offset = 0;
 }
 
 /*
@@ -2981,19 +3051,21 @@ I830PutImage(ScrnInfoPtr pScrn,
       extraLinear = 0;
 
    /* size is multiplied by 2 because we have two buffers that are flipping */
-   pPriv->linear = I830AllocateMemory(pScrn, pPriv->linear,
-				      (extraLinear +
-				       (pPriv->doubleBuffer ? size * 2 : size)) /
-				      pI830->cpp);
+   I830AllocateMemory(pScrn, &pPriv->linear,
+		      extraLinear + (pPriv->doubleBuffer ? size * 2 : size),
+		      16);
 
-   if(!pPriv->linear || pPriv->linear->offset < (pScrn->virtualX * pScrn->virtualY))
+   if (pPriv->linear.offset == 0)
       return BadAlloc;
 
+   pPriv->extra_offset = pPriv->linear.offset +
+      pPriv->doubleBuffer ? size * 2 : size;
+
    /* fixup pointers */
 #if 0
-   pPriv->YBuf0offset = pScrn->fbOffset + pPriv->linear->offset * pI830->cpp;
+   pPriv->YBuf0offset = pScrn->fbOffset + pPriv->linear.offset;
 #else
-   pPriv->YBuf0offset = pI830->FrontBuffer.Start + pPriv->linear->offset * pI830->cpp;
+   pPriv->YBuf0offset = pI830->FrontBuffer.Start + pPriv->linear.offset;
 #endif
    if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
       pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * width);
@@ -3236,10 +3308,7 @@ I830BlockHandler(int i,
 	 }
       } else {				/* FREE_TIMER */
 	 if (pPriv->freeTime < now) {
-	    if (pPriv->linear) {
-	       xf86FreeOffscreenLinear(pPriv->linear);
-	       pPriv->linear = NULL;
-	    }
+	    I830FreeMemory(pScrn, &pPriv->linear);
 	    pPriv->videoStatus = 0;
 	 }
       }
@@ -3251,7 +3320,7 @@ I830BlockHandler(int i,
  ***************************************************************************/
 
 typedef struct {
-   FBLinearPtr linear;
+   struct linear_alloc linear;
    Bool isOn;
 } OffscreenPrivRec, *OffscreenPrivPtr;
 
@@ -3261,8 +3330,7 @@ I830AllocateSurface(ScrnInfoPtr pScrn,
 		    unsigned short w,
 		    unsigned short h, XF86SurfacePtr surface)
 {
-   FBLinearPtr linear;
-   int pitch, fbpitch, size, bpp;
+   int pitch, fbpitch, size;
    OffscreenPrivPtr pPriv;
    I830Ptr pI830 = I830PTR(pScrn);
 
@@ -3280,41 +3348,40 @@ I830AllocateSurface(ScrnInfoPtr pScrn,
    if (pI830->rotation != RR_Rotate_0)
       return BadAlloc;
 
-   w = (w + 1) & ~1;
-   pitch = ((w << 1) + 15) & ~15;
-   bpp = pScrn->bitsPerPixel >> 3;
-   fbpitch = bpp * pScrn->displayWidth;
-   size = ((pitch * h) + bpp - 1) / bpp;
-
-   if (!(linear = I830AllocateMemory(pScrn, NULL, size)))
+   if (!(surface->pitches = xalloc(sizeof(int))))
       return BadAlloc;
-
-   surface->width = w;
-   surface->height = h;
-
-   if (!(surface->pitches = xalloc(sizeof(int)))) {
-      xf86FreeOffscreenLinear(linear);
-      return BadAlloc;
-   }
    if (!(surface->offsets = xalloc(sizeof(int)))) {
       xfree(surface->pitches);
-      xf86FreeOffscreenLinear(linear);
       return BadAlloc;
    }
    if (!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) {
       xfree(surface->pitches);
       xfree(surface->offsets);
-      xf86FreeOffscreenLinear(linear);
       return BadAlloc;
    }
 
-   pPriv->linear = linear;
+   w = (w + 1) & ~1;
+   pitch = ((w << 1) + 15) & ~15;
+   fbpitch = pI830->cpp * pScrn->displayWidth;
+   size = pitch * h;
+
+   I830AllocateMemory(pScrn, &pPriv->linear, size, 16);
+   if (pPriv->linear.offset == 0) {
+      xfree(surface->pitches);
+      xfree(surface->offsets);
+      xfree(pPriv);
+      return BadAlloc;
+   }
+
+   surface->width = w;
+   surface->height = h;
+
    pPriv->isOn = FALSE;
 
    surface->pScrn = pScrn;
    surface->id = id;
    surface->pitches[0] = pitch;
-   surface->offsets[0] = linear->offset * bpp;
+   surface->offsets[0] = pPriv->linear.offset;
    surface->devPrivate.ptr = (pointer) pPriv;
 
 #if 0
@@ -3358,7 +3425,7 @@ I830FreeSurface(XF86SurfacePtr surface)
    if (pPriv->isOn) {
       I830StopSurface(surface);
    }
-   xf86FreeOffscreenLinear(pPriv->linear);
+   I830FreeMemory(surface->pScrn, &pPriv->linear);
    xfree(surface->pitches);
    xfree(surface->offsets);
    xfree(surface->devPrivate.ptr);
diff --git a/src/i830_video.h b/src/i830_video.h
index 6a09a25..12a5bda 100644
--- a/src/i830_video.h
+++ b/src/i830_video.h
@@ -27,6 +27,18 @@ THE USE OR OTHER DEALINGS IN THE SOFTWAR
 #include "xf86.h"
 #include "xf86_OSproc.h"
 
+/* Ugly mess to support the old XF86 allocator or EXA using the same code.
+ */
+struct linear_alloc {
+#ifdef I830_USE_XAA
+   FBLinearPtr xaa;
+#endif
+#ifdef I830_USE_EXA
+   ExaOffscreenArea *exa;
+#endif
+   unsigned int offset;
+};
+
 typedef struct {
    CARD32 YBuf0offset;
    CARD32 UBuf0offset;
@@ -57,7 +69,8 @@ typedef struct {
    CARD32 videoStatus;
    Time offTime;
    Time freeTime;
-   FBLinearPtr linear;
+   struct linear_alloc linear;
+   unsigned int extra_offset;
 
    Bool overlayOK;
    int oneLineMode;
diff-tree 84915ac8afeb4bbc03df8f94ab3ba351788d6501 (from 1e9105395a7900521206b28bae4bb4f85669a0cd)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Thu Dec 21 23:42:53 2006 -0800

    If DDC detailed modes are missing physical size, pull from features.
    
    Monitors without detailed modes, or those which do not bother to set a
    physical size in their detailed modes may still have physical size in the
    global data.

diff --git a/src/i830_modes.c b/src/i830_modes.c
index 34f6cd5..42ee79d 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -140,5 +140,13 @@ i830_ddc_get_modes(xf86OutputPtr output)
 	}
     }
 
+    /* if no mm size is available from a detailed timing, check the max size field */
+    if ((!output->mm_width || !output->mm_height) &&
+	(ddc_mon->features.hsize && ddc_mon->features.vsize))
+    {
+	output->mm_width = ddc_mon->features.hsize * 10;
+	output->mm_height = ddc_mon->features.vsize * 10;
+    }
+
     return ddc_modes;
 }
diff-tree 1e9105395a7900521206b28bae4bb4f85669a0cd (from parents)
Merge: df9ecf8ab93f0aeffde11d438513d41220ba75cb c237e930615f1b048895efe988d28503f5d67c37
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Thu Dec 21 23:34:30 2006 -0800

    Merge branch 'modesetting-origin' into modesetting

diff-tree df9ecf8ab93f0aeffde11d438513d41220ba75cb (from d8c5dba4d797fc50d7b2b5855f34e2d2e2ad3e4f)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Thu Dec 21 23:32:35 2006 -0800

    Change belinea edid quirk to cover the 10 20 30W model as well.
    
    This larger model reported different (but still incorrect)
    sync polarities, so instead of flipping them, just set them to the right
    value.

diff --git a/src/i830_edid_modes.c b/src/i830_edid_modes.c
index 5357023..5cef46d 100644
--- a/src/i830_edid_modes.c
+++ b/src/i830_edid_modes.c
@@ -46,18 +46,21 @@
 
 typedef enum {
     DDC_QUIRK_NONE = 0,
-    /*
-     * Detailed timing sync polarity values are inverted
-     */
-    DDC_QUIRK_DT_SYNC_INVERT = 1 << 0,
+    /* Force detailed sync polarity to -h +v */
+    DDC_QUIRK_DT_SYNC_HM_VP = 1 << 0,
 } ddc_quirk_t;
 
-static Bool dt_sync_invert (int scrnIndex, xf86MonPtr DDC)
+static Bool quirk_dt_sync_hm_vp (int scrnIndex, xf86MonPtr DDC)
 {
     /* Belinea 1924S1W */
     if (memcmp (DDC->vendor.name, "MAX", 4) == 0 &&
 	DDC->vendor.prod_id == 1932)
 	return TRUE;
+    /* Belinea 10 20 30W */
+    if (memcmp (DDC->vendor.name, "MAX", 4) == 0 &&
+	DDC->vendor.prod_id == 2007)
+	return TRUE;
+    
     return FALSE;
 }
 
@@ -69,8 +72,8 @@ typedef struct {
 
 static const ddc_quirk_map_t ddc_quirks[] = {
     { 
-	dt_sync_invert,	DDC_QUIRK_DT_SYNC_INVERT,
-	"Detailed timing data contains inverted sync polarity"
+	quirk_dt_sync_hm_vp,	DDC_QUIRK_DT_SYNC_HM_VP,
+	"Set detailed timing sync polarity to -h +v"
     },
     { 
 	NULL,		DDC_QUIRK_NONE,
@@ -154,7 +157,6 @@ DDCModeFromDetailedTiming(int scrnIndex,
 			  int preferred, ddc_quirk_t quirks)
 {
     DisplayModePtr Mode;
-    unsigned int misc;
 
     /* We don't do stereo */
     if (timing->stereo) {
@@ -196,19 +198,20 @@ DDCModeFromDetailedTiming(int scrnIndex,
     if (timing->interlaced)
         Mode->Flags |= V_INTERLACE;
 
-    misc = timing->misc;
-    if (quirks & DDC_QUIRK_DT_SYNC_INVERT)
-	misc ^= 0x3;
-    
-    if (misc & 0x02)
-        Mode->Flags |= V_PHSYNC;
-    else
-        Mode->Flags |= V_NHSYNC;
-
-    if (misc & 0x01)
-        Mode->Flags |= V_PVSYNC;
+    if (quirks & DDC_QUIRK_DT_SYNC_HM_VP)
+	Mode->Flags |= V_NHSYNC | V_PVSYNC;
     else
-        Mode->Flags |= V_NVSYNC;
+    {
+	if (timing->misc & 0x02)
+	    Mode->Flags |= V_PHSYNC;
+	else
+	    Mode->Flags |= V_NHSYNC;
+    
+	if (timing->misc & 0x01)
+	    Mode->Flags |= V_PVSYNC;
+	else
+	    Mode->Flags |= V_NVSYNC;
+    }
 
     return Mode;
 }
diff-tree c237e930615f1b048895efe988d28503f5d67c37 (from d8c5dba4d797fc50d7b2b5855f34e2d2e2ad3e4f)
Author: Keith Packard <keithp at ukulele.keithp.com>
Date:   Thu Dec 21 23:30:37 2006 -0800

    Use Vesa DDC timeouts for all I2C busses.
    
    The default I2C timeouts are very short, and while most
    modern monitors have no trouble responding at that rate,
    some older ones cannot manage.

diff --git a/src/i830_i2c.c b/src/i830_i2c.c
index 8fd12ea..450f9de 100644
--- a/src/i830_i2c.c
+++ b/src/i830_i2c.c
@@ -365,6 +365,14 @@ I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr
 #endif
     pI2CBus->DriverPrivate.uval = i2c_reg;
 
+    /* Assume all busses are used for DDCish stuff */
+    
+    pI2CBus->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */
+    pI2CBus->StartTimeout = 550;
+    pI2CBus->BitTimeout = 40;
+    pI2CBus->ByteTimeout = 40;
+    pI2CBus->AcknTimeout = 40;
+
     if (!xf86I2CBusInit(pI2CBus))
 	return FALSE;
 
diff-tree d8c5dba4d797fc50d7b2b5855f34e2d2e2ad3e4f (from fab9a6b6210daea423b609208ef57fa26571f5d3)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Thu Dec 21 21:20:43 2006 -0800

    When cleaning duplicate modes, make sure ->Last is reset correctly.
    
    When removing the very last mode for a monitor, move the ->Last pointer to
    the previous list element.

diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index bb6c869..0c482a2 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -437,7 +437,11 @@ xf86PruneDuplicateMonitorModes (MonPtr M
 	{
 	    next = clone->next;
 	    if (xf86ModesEqual (master, clone))
+	    {
+		if (Monitor->Last == clone)
+		    Monitor->Last = clone->prev;
 		xf86DeleteMode (&Monitor->Modes, clone);
+	    }
 	}
     }
 }
diff-tree fab9a6b6210daea423b609208ef57fa26571f5d3 (from d9b27667e6cc6c7e171b0f513d40be7658cf4574)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Thu Dec 21 21:19:32 2006 -0800

    Add EDID quirk support for broken EDID data.
    
    For EDID with known errors, add a quirk mechanism to automatically
    compensate. The first quirk is for a Belinea 1440x900 monitor which
    incorrectly specifies sync polarities in the detailed mode.

diff --git a/src/i830_edid_modes.c b/src/i830_edid_modes.c
index 3becbb5..5357023 100644
--- a/src/i830_edid_modes.c
+++ b/src/i830_edid_modes.c
@@ -41,6 +41,44 @@
 #if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0)
 
 /*
+ * Quirks to work around broken EDID data from various monitors.
+ */
+
+typedef enum {
+    DDC_QUIRK_NONE = 0,
+    /*
+     * Detailed timing sync polarity values are inverted
+     */
+    DDC_QUIRK_DT_SYNC_INVERT = 1 << 0,
+} ddc_quirk_t;
+
+static Bool dt_sync_invert (int scrnIndex, xf86MonPtr DDC)
+{
+    /* Belinea 1924S1W */
+    if (memcmp (DDC->vendor.name, "MAX", 4) == 0 &&
+	DDC->vendor.prod_id == 1932)
+	return TRUE;
+    return FALSE;
+}
+
+typedef struct {
+    Bool	(*detect) (int scrnIndex, xf86MonPtr DDC);
+    ddc_quirk_t	quirk;
+    char	*description;
+} ddc_quirk_map_t;
+
+static const ddc_quirk_map_t ddc_quirks[] = {
+    { 
+	dt_sync_invert,	DDC_QUIRK_DT_SYNC_INVERT,
+	"Detailed timing data contains inverted sync polarity"
+    },
+    { 
+	NULL,		DDC_QUIRK_NONE,
+	"No known quirks"
+    },
+};
+
+/*
  * TODO:
  *  - for those with access to the VESA DMT standard; review please.
  */
@@ -68,7 +106,8 @@ DisplayModeRec DDCEstablishedModes[17] =
 };
 
 static DisplayModePtr
-DDCModesFromEstablished(int scrnIndex, struct established_timings *timing)
+DDCModesFromEstablished(int scrnIndex, struct established_timings *timing,
+			ddc_quirk_t quirks)
 {
     DisplayModePtr Modes = NULL, Mode = NULL;
     CARD32 bits = (timing->t1) | (timing->t2 << 8) |
@@ -89,7 +128,8 @@ DDCModesFromEstablished(int scrnIndex, s
  *
  */
 static DisplayModePtr
-DDCModesFromStandardTiming(int scrnIndex, struct std_timings *timing)
+DDCModesFromStandardTiming(int scrnIndex, struct std_timings *timing,
+			   ddc_quirk_t quirks)
 {
     DisplayModePtr Modes = NULL, Mode = NULL;
     int i;
@@ -111,9 +151,10 @@ DDCModesFromStandardTiming(int scrnIndex
  */
 static DisplayModePtr
 DDCModeFromDetailedTiming(int scrnIndex, struct detailed_timings *timing,
-			  int preferred)
+			  int preferred, ddc_quirk_t quirks)
 {
     DisplayModePtr Mode;
+    unsigned int misc;
 
     /* We don't do stereo */
     if (timing->stereo) {
@@ -155,12 +196,16 @@ DDCModeFromDetailedTiming(int scrnIndex,
     if (timing->interlaced)
         Mode->Flags |= V_INTERLACE;
 
-    if (timing->misc & 0x02)
+    misc = timing->misc;
+    if (quirks & DDC_QUIRK_DT_SYNC_INVERT)
+	misc ^= 0x3;
+    
+    if (misc & 0x02)
         Mode->Flags |= V_PHSYNC;
     else
         Mode->Flags |= V_NHSYNC;
 
-    if (timing->misc & 0x01)
+    if (misc & 0x01)
         Mode->Flags |= V_PVSYNC;
     else
         Mode->Flags |= V_NVSYNC;
@@ -172,17 +217,22 @@ DisplayModePtr
 xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC)
 {
     int preferred, i;
-    DisplayModePtr Modes = NULL, Mode;
-
-    preferred = PREFERRED_TIMING_MODE(DDC->features.msc);
+    DisplayModePtr  Modes = NULL, Mode;
+    ddc_quirk_t	    quirks;
 
-    /* Add established timings */
-    Mode = DDCModesFromEstablished(scrnIndex, &DDC->timings1);
-    Modes = xf86ModesAdd(Modes, Mode);
+    xf86DrvMsg (scrnIndex, X_INFO, "EDID vendor \"%s\", prod id %d\n",
+		DDC->vendor.name, DDC->vendor.prod_id);
+    quirks = DDC_QUIRK_NONE;
+    for (i = 0; ddc_quirks[i].detect; i++)
+	if (ddc_quirks[i].detect (scrnIndex, DDC))
+	{
+	    xf86DrvMsg (scrnIndex, X_INFO, "    EDID quirk: %s\n",
+			ddc_quirks[i].description);
+	    quirks |= ddc_quirks[i].quirk;
+	}
+    
 
-    /* Add standard timings */
-    Mode = DDCModesFromStandardTiming(scrnIndex, DDC->timings2);
-    Modes = xf86ModesAdd(Modes, Mode);
+    preferred = PREFERRED_TIMING_MODE(DDC->features.msc);
 
     for (i = 0; i < DET_TIMINGS; i++) {
 	struct detailed_monitor_section *det_mon = &DDC->det_mon[i];
@@ -191,13 +241,15 @@ xf86DDCGetModes(int scrnIndex, xf86MonPt
         case DT:
             Mode = DDCModeFromDetailedTiming(scrnIndex,
                                              &det_mon->section.d_timings,
-					     preferred);
+					     preferred,
+					     quirks);
 	    preferred = 0;
             Modes = xf86ModesAdd(Modes, Mode);
             break;
         case DS_STD_TIMINGS:
             Mode = DDCModesFromStandardTiming(scrnIndex,
-					      det_mon->section.std_t);
+					      det_mon->section.std_t,
+					      quirks);
             Modes = xf86ModesAdd(Modes, Mode);
             break;
         default:
@@ -205,6 +257,14 @@ xf86DDCGetModes(int scrnIndex, xf86MonPt
         }
     }
 
+    /* Add established timings */
+    Mode = DDCModesFromEstablished(scrnIndex, &DDC->timings1, quirks);
+    Modes = xf86ModesAdd(Modes, Mode);
+
+    /* Add standard timings */
+    Mode = DDCModesFromStandardTiming(scrnIndex, DDC->timings2, quirks);
+    Modes = xf86ModesAdd(Modes, Mode);
+
     return Modes;
 }
 
diff-tree d9b27667e6cc6c7e171b0f513d40be7658cf4574 (from 4c0c1aa882cfec77b2183baec93cbc4cfaf4abe0)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Thu Dec 21 21:17:03 2006 -0800

    PLL computations missed one possible 'm2' value.
    
    m2 was ranging from min <= m2 < max instead of <= max resulting in
    inaccurate PLL frequencies for some modes.

diff --git a/src/i830_display.c b/src/i830_display.c
index e3fdf6d..c5880d6 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -299,7 +299,7 @@ i830FindBestPLL(xf86CrtcPtr crtc, int ta
 
     for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) 
     {
-	for (clock.m2 = limit->m2.min; clock.m2 < clock.m1 && clock.m2 < limit->m2.max; clock.m2++) 
+	for (clock.m2 = limit->m2.min; clock.m2 < clock.m1 && clock.m2 <= limit->m2.max; clock.m2++) 
 	{
 	    for (clock.n = limit->n.min; clock.n <= limit->n.max; clock.n++) 
 	    {
diff-tree 4c0c1aa882cfec77b2183baec93cbc4cfaf4abe0 (from 98fd44d681220aa31200e4262f1a7ec952a09530)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Thu Dec 21 02:33:39 2006 -0800

    Computed corred color conversion values.
    
    Extract correct color conversion values for all video formats from
    documentation. Use those, with appropriate conversions, for the color
    conversion register values.

diff --git a/src/fix.5c b/src/fix.5c
new file mode 100644
index 0000000..b758a43
--- /dev/null
+++ b/src/fix.5c
@@ -0,0 +1,14 @@
+/*
+ * Convert CSC fix point values to floats
+ */
+
+real fixval (int fix)
+{
+    int exp = fix >> 9;
+    int mant = fix & ((1 << 9) - 1);
+    real ret;
+    if (exp == 0x7)
+	return 1.0;
+    ret = (2 ** -exp) * mant / (1 << 9);
+    return ret;
+}
diff --git a/src/i830_tv.c b/src/i830_tv.c
index 323f022..6231891 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -578,6 +578,43 @@ i830_tv_mode_fixup(xf86OutputPtr output,
     return TRUE;
 }
 
+static CARD32
+i830_float_to_csc (float fin)
+{
+    CARD32  exp;
+    CARD32  mant;
+    CARD32  ret;
+    float   f = fin;
+    
+    /* somehow the color conversion knows the signs of all the values */
+    if (f < 0) f = -f;
+    
+    if (f >= 1)
+    {
+	exp = 0x7;
+	mant = 1 << 8;
+    }
+    else
+    {
+	for (exp = 0; exp < 3 && f < 0.5; exp++)
+	    f *= 2.0;
+	mant = (f * (1 << 9) + 0.5);
+	if (mant >= (1 << 9))
+	    mant = (1 << 9) - 1;
+    }
+    ret = (exp << 9) | mant;
+    return ret;
+}
+
+static CARD16
+i830_float_to_luma (float f)
+{
+    CARD16  ret;
+
+    ret = (f * (1 << 9));
+    return ret;
+}
+
 static void
 i830_tv_mode_set(xf86OutputPtr output, DisplayModePtr mode,
 		 DisplayModePtr adjusted_mode)
@@ -716,18 +753,37 @@ i830_tv_mode_set(xf86OutputPtr output, D
     OUTREG(TV_SC_CTL_1, scctl1);
     OUTREG(TV_SC_CTL_2, scctl2);
     OUTREG(TV_SC_CTL_3, scctl3);
-    /* XXX match BIOS */
-    OUTREG(TV_CSC_Y, 0x0332012D);
-    OUTREG(TV_CSC_Y2, 0x07D30133);
-    OUTREG(TV_CSC_U, 0x076A0564);
-    OUTREG(TV_CSC_U2, 0x030D0200);
-    OUTREG(TV_CSC_V, 0x037A033D);
-    OUTREG(TV_CSC_V2, 0x06F60200);
+    
+    OUTREG(TV_CSC_Y,
+	   (i830_float_to_csc(color_conversion->ry) << 16) |
+	   (i830_float_to_csc(color_conversion->gy)));
+    OUTREG(TV_CSC_Y2,
+	    (i830_float_to_csc(color_conversion->by) << 16) |
+	    (i830_float_to_luma(color_conversion->ay)));
+	   
+    OUTREG(TV_CSC_U,
+	   (i830_float_to_csc(color_conversion->ru) << 16) |
+	   (i830_float_to_csc(color_conversion->gu)));
+
+    OUTREG(TV_CSC_U2,
+	    (i830_float_to_csc(color_conversion->bu) << 16) |
+	    (i830_float_to_luma(color_conversion->au)));
+	   
+    OUTREG(TV_CSC_V,
+	   (i830_float_to_csc(color_conversion->rv) << 16) |
+	   (i830_float_to_csc(color_conversion->gv)));
+
+    OUTREG(TV_CSC_V2,
+	    (i830_float_to_csc(color_conversion->bv) << 16) |
+	    (i830_float_to_luma(color_conversion->av)));
+	   
     OUTREG(TV_CLR_KNOBS, 0x00606000);
     OUTREG(TV_CLR_LEVEL, ((video_levels->black << TV_BLACK_LEVEL_SHIFT) |
 			  (video_levels->blank << TV_BLANK_LEVEL_SHIFT)));
+    
     OUTREG(TV_WIN_POS, 0x00360024);
     OUTREG(TV_WIN_SIZE, 0x02640198);
+    
     OUTREG(TV_FILTER_CTL_1, 0x8000085E);
     OUTREG(TV_FILTER_CTL_2, 0x00017878);
     OUTREG(TV_FILTER_CTL_3, 0x0000BC3C);
diff-tree 98fd44d681220aa31200e4262f1a7ec952a09530 (from 4ba72fc408e7fab7c384aff5e73f0cfb8fd86cf3)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Thu Dec 21 01:24:24 2006 -0800

    TV subcarrier was computed from wrong clock value.
    
    The constants provided in the documentation for the subcarrier DDA values
    assumed the clock was programmed to precisely 108MHz, but the PLL can't hit
    that value exactly (or our PLL computation can't, in any case). The
    result was an incorrect subcarrier frequency which resulted in synthetic
    subcarrier phase shift and a lovely rainbow effect on the screen.
    
    Unfortunately, the documentation didn't exactly describe the function
    performed by the subcarrier clock hardware, so a bit of detective work was
    needed. New constants were computed using the code in tv.5c and those, along
    with lots of other values from the documentation were inserted into the
    necessary tables.
    
    The result appears to generate stable NTSC video on the svideo connector.

diff --git a/src/i830_tv.c b/src/i830_tv.c
index 6852793..323f022 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -83,61 +83,20 @@ struct i830_tv_priv {
     CARD32 save_TV_CTL;
 };
 
-enum burst_modes {
-    TV_SC_NTSC_MJ,
-    TV_SC_PAL,
-    TV_SC_PAL_NC,
-    TV_SC_PAL_M,
-    TV_SC_NTSC_443
-};
+typedef struct {
+    int	blank, black, burst;
+} video_levels_t;
+
+typedef struct {
+    float   ry, gy, by, ay;
+    float   ru, gu, bu, au;
+    float   rv, gv, bv, av;
+} color_conversion_t;
 
-const struct tv_sc_mode {
-    char *name;
-    int dda2_size, dda3_size, dda1_inc, dda2_inc, dda3_inc;
-    CARD32 sc_reset;
-    Bool pal_burst;
-} tv_sc_modes[] = {
-    [TV_SC_NTSC_MJ] = {
-	"NTSC M/J",
-	27456, 0, 135, 20800, 0,
-	TV_SC_RESET_EVERY_4,
-	FALSE
-    },
-    [TV_SC_PAL] = {
-	"PAL",
-	27648, 625, 168, 4122, 67,
-	TV_SC_RESET_EVERY_8,
-	TRUE
-    },
-    [TV_SC_PAL_NC] = {
-	"PAL Nc",
-	27648, 625, 135, 23578, 134,
-	TV_SC_RESET_EVERY_8,
-	TRUE
-    },
-    [TV_SC_PAL_M] = {
-	"PAL M",
-	27456, 0, 135, 16704, 0,
-	TV_SC_RESET_EVERY_8,
-	TRUE
-    },
-    [TV_SC_NTSC_443] = {
-	"NTSC-4.43",
-	27456, 525, 168, 4093, 310,
-	TV_SC_RESET_NEVER,
-	FALSE
-    },
-};
-
-/**
- * Register programming values for TV modes.
- *
- * These values account for -1s required.
- */
-const struct tv_mode {
+typedef struct {
     char *name;
     CARD32 oversample;
-    int hsync_end, hblank_end, hblank_start, htotal;
+    int hsync_end, hblank_start, hblank_end, htotal;
     Bool progressive;
     int vsync_start_f1, vsync_start_f2, vsync_len;
     Bool veq_ena;
@@ -149,20 +108,264 @@ const struct tv_mode {
     int vburst_start_f2, vburst_end_f2;
     int vburst_start_f3, vburst_end_f3;
     int vburst_start_f4, vburst_end_f4;
-} tv_modes[] = {
+    /*
+     * subcarrier programming
+     */
+    int dda2_size, dda3_size, dda1_inc, dda2_inc, dda3_inc;
+    CARD32 sc_reset;
+    Bool pal_burst;
+    /*
+     * blank/black levels
+     */
+    video_levels_t	composite_levels, svideo_levels;
+    color_conversion_t	composite_color, svideo_color;
+} tv_mode_t;
+
+#define TV_PLL_CLOCK	107520
+
+/*
+ * Sub carrier DDA
+ *
+ *  I think this works as follows:
+ *
+ *  subcarrier freq = pixel_clock * (dda1_inc + dda2_inc / dda2_size) / 4096
+ *
+ * Presumably, when dda3 is added in, it gets to adjust the dda2_inc value
+ *
+ * So,
+ *  dda1_ideal = subcarrier/pixel * 4096
+ *  dda1_inc = floor (dda1_ideal)
+ *  dda2 = dda1_ideal - dda1_inc
+ *
+ *  then pick a ratio for dda2 that gives the closest approximation. If
+ *  you can't get close enough, you can play with dda3 as well. This
+ *  seems likely to happen when dda2 is small as the jumps would be larger
+ *
+ * To invert this,
+ *
+ *  pixel_clock = subcarrier * 4096 / (dda1_inc + dda2_inc / dda2_size)
+ *
+ * The constants below were all computed using a 107.520MHz clock
+ */
+ 
+/**
+ * Register programming values for TV modes.
+ *
+ * These values account for -1s required.
+ */
+
+const tv_mode_t tv_modes[] = {
     {
-	"480i",
-	TV_OVERSAMPLE_8X,
-	64, 124, 836, 857,
-	FALSE,
-	6, 7, 6,
-	TRUE, 0, 1, 18,
-	20, 21, 240,
-	TRUE,
-	72, 34, 9, 240, 10, 240, 9, 240, 10, 240
+	.name		= "NTSC 480i",
+	.oversample	= TV_OVERSAMPLE_8X,
+	
+	/* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */
+
+	.hsync_end	= 64,		    .hblank_end		= 124,
+	.hblank_start	= 836,		    .htotal		= 857,
+	
+	.progressive	= FALSE,
+	
+	.vsync_start_f1	= 6,		    .vsync_start_f2	= 7,
+	.vsync_len	= 6,
+	
+	.veq_ena	= TRUE,		    .veq_start_f1    	= 0,
+	.veq_start_f2	= 1,		    .veq_len		= 18,
+	
+	.vi_end_f1	= 20,		    .vi_end_f2		= 21,
+	.nbr_end	= 240,
+	
+	.burst_ena	= TRUE,
+	.hburst_start	= 72,		    .hburst_len		= 34,
+	.vburst_start_f1 = 9,		    .vburst_end_f1	= 240,
+	.vburst_start_f2 = 10,		    .vburst_end_f2	= 240,
+	.vburst_start_f3 = 9,		    .vburst_end_f3	= 240, 
+	.vburst_start_f4 = 10,		    .vburst_end_f4	= 240,
+
+	/* desired 3.5800000 actual 3.5800000 clock 107.52 */
+	.dda1_inc	=    136,
+	.dda2_inc	=   7624,	    .dda2_size		=  20013,
+	.dda3_inc	=      0,	    .dda3_size		=      0,
+	.sc_reset	= TV_SC_RESET_EVERY_4,
+	.pal_burst	= FALSE,
+
+	.composite_levels = { .blank = 225, .black = 267, .burst = 113 },
+	.composite_color = {
+	    .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.5082,
+	    .ru =-0.0749, .gu =-0.1471, .bu = 0.2220, .au = 1.0000,
+	    .rv = 0.3125, .gv =-0.2616, .bv =-0.0508, .av = 1.0000,
+	},
+
+	.svideo_levels    = { .blank = 266, .black = 316, .burst = 133 },
+	.svideo_color = {
+	    .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.6006,
+	    .ru =-0.0885, .gu =-0.1738, .bu = 0.2624, .au = 1.0000,
+	    .rv = 0.3693, .gv =-0.3092, .bv =-0.0601, .av = 1.0000,
+	},
+    },
+    {
+	.name		= "NTSC-Japan 480i",
+	.oversample	= TV_OVERSAMPLE_8X,
+	
+	/* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */
+	.hsync_end	= 64,		    .hblank_end		= 124,
+	.hblank_start	= 836,		    .htotal		= 857,
+	
+	.progressive	= FALSE,
+	
+	.vsync_start_f1	= 6,		    .vsync_start_f2	= 7,
+	.vsync_len	= 6,
+	
+	.veq_ena	= TRUE,		    .veq_start_f1    	= 0,
+	.veq_start_f2	= 1,		    .veq_len		= 18,
+	
+	.vi_end_f1	= 20,		    .vi_end_f2		= 21,
+	.nbr_end	= 240,
+	
+	.burst_ena	= TRUE,
+	.hburst_start	= 72,		    .hburst_len		= 34,
+	.vburst_start_f1 = 9,		    .vburst_end_f1	= 240,
+	.vburst_start_f2 = 10,		    .vburst_end_f2	= 240,
+	.vburst_start_f3 = 9,		    .vburst_end_f3	= 240, 
+	.vburst_start_f4 = 10,		    .vburst_end_f4	= 240,
+
+	/* desired 3.5800000 actual 3.5800000 clock 107.52 */
+	.dda1_inc	=    136,
+	.dda2_inc	=   7624,	    .dda2_size		=  20013,
+	.dda3_inc	=      0,	    .dda3_size		=      0,
+	.sc_reset	= TV_SC_RESET_EVERY_4,
+	.pal_burst	= FALSE,
+
+	.composite_levels = { .blank = 225, .black = 225, .burst = 113 },
+	.composite_color = {
+	    .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.5495,
+	    .ru =-0.0810, .gu =-0.1590, .bu = 0.2400, .au = 1.0000,
+	    .rv = 0.3378, .gv =-0.2829, .bv =-0.0549, .av = 1.0000,
+	},
+
+	.svideo_levels    = { .blank = 266, .black = 266, .burst = 133 },
+	.svideo_color = {
+	    .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.6494,
+	    .ru =-0.0957, .gu =-0.1879, .bu = 0.2836, .au = 1.0000,
+	    .rv = 0.3992, .gv =-0.3343, .bv =-0.0649, .av = 1.0000,
+	},
     }
+#if 0
+    {
+	/* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */
+	.name	    = "PAL",
+	/* desired 4.4336180 actual 4.4336180 clock 107.52 */
+	.dda1_inc	=    168,
+	.dda2_inc	=  18557,	.dda2_size	=  20625,
+	.dda3_inc	=      0,	.dda3_size	=      0,
+	.sc_reset   = TV_SC_RESET_EVERY_8,
+	.pal_burst  = TRUE
+	
+	.composite_levels = { .blank = 237, .black = 237, .burst = 118 },
+	.composite_color = {
+	    .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.5379,
+	    .ru =-0.0793, .gu =-0.1557, .bu = 0.2350, .au = 1.0000,
+	    .rv = 0.3307, .gv =-0.2769, .bv =-0.0538, .av = 1.0000,
+	},
+
+	.svideo_levels    = { .blank = 280, .black = 280, .burst = 139 },
+	.svideo_color = {
+	    .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.6357,
+	    .ru =-0.0937, .gu =-0.1840, .bu = 0.2777, .au = 1.0000,
+	    .rv = 0.3908, .gv =-0.3273, .bv =-0.0636, .av = 1.0000,
+	},
+    },
+    {
+	/* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.576MHz */
+	.name	    = "PAL M",
+	/* desired 3.5756110 actual 3.5756110 clock 107.52 */
+	.dda1_inc	=    136,
+	.dda2_inc	=   5611,	.dda2_size	=  26250,
+	.dda3_inc	=      0,	.dda3_size	=      0,
+	.sc_reset   = TV_SC_RESET_EVERY_8,
+	.pal_burst  = TRUE
+	
+	.composite_levels = { .blank = 225, .black = 267, .burst = 113 },
+	.composite_color = {
+	    .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.5082,
+	    .ru =-0.0749, .gu =-0.1471, .bu = 0.2220, .au = 1.0000,
+	    .rv = 0.3125, .gv =-0.2616, .bv =-0.0508, .av = 1.0000,
+	},
+
+	.svideo_levels    = { .blank = 266, .black = 316, .burst = 133 },
+	.svideo_color = {
+	    .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.6006,
+	    .ru =-0.0885, .gu =-0.1738, .bu = 0.2624, .au = 1.0000,
+	    .rv = 0.3693, .gv =-0.3092, .bv =-0.0601, .av = 1.0000,
+	},
+    },
+    {
+	/* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 3.582MHz */
+	.name	    = "PAL Nc",
+	/* desired 3.5820560 actual 3.5820560 clock 107.52 */
+	.dda1_inc	=    136,
+	.dda2_inc	=  12056,	.dda2_size	=  26250,
+	.dda3_inc	=      0,	.dda3_size	=      0,
+	.sc_reset   = TV_SC_RESET_EVERY_8,
+	.pal_burst  = TRUE
+	
+	.composite_levels = { .blank = 225, .black = 267, .burst = 113 },
+	.composite_color = {
+	    .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.5082,
+	    .ru =-0.0749, .gu =-0.1471, .bu = 0.2220, .au = 1.0000,
+	    .rv = 0.3125, .gv =-0.2616, .bv =-0.0508, .av = 1.0000,
+	},
+
+	.svideo_levels    = { .blank = 266, .black = 316, .burst = 133 },
+	.svideo_color = {
+	    .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.6006,
+	    .ru =-0.0885, .gu =-0.1738, .bu = 0.2624, .au = 1.0000,
+	    .rv = 0.3693, .gv =-0.3092, .bv =-0.0601, .av = 1.0000,
+	},
+    },
+    {
+	/* 525 lines, 60 fields, 15.734KHz line, Sub-Carrier 4.43MHz */
+	.name	    = "NTSC-4.43(nonstandard)",
+	/* desired 4.4336180 actual 4.4336180 clock 107.52 */
+	.dda1_inc	=    168,
+	.dda2_inc	=  18557,	.dda2_size	=  20625,
+	.dda3_inc	=      0,	.dda3_size	=      0,
+	.sc_reset   = TV_SC_RESET_NEVER,
+	.pal_burst  = FALSE
+
+	.composite_levels = { .blank = 225, .black = 267, .burst = 113 },
+	.composite_color = {
+	    .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.5082,
+	    .ru =-0.0749, .gu =-0.1471, .bu = 0.2220, .au = 1.0000,
+	    .rv = 0.3125, .gv =-0.2616, .bv =-0.0508, .av = 1.0000,
+	},
+
+	.svideo_levels    = { .blank = 266, .black = 316, .burst = 133 },
+	.svideo_color = {
+	    .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.6006,
+	    .ru =-0.0885, .gu =-0.1738, .bu = 0.2624, .au = 1.0000,
+	    .rv = 0.3693, .gv =-0.3092, .bv =-0.0601, .av = 1.0000,
+	},
+    },
+#endif
+};
+
+static const video_levels_t component_level = {
+    .blank = 279, .black = 279 
 };
 
+static const color_conversion_t sdtv_component_color = {
+    .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.6364,
+    .ru =-0.1687, .gu =-0.3313, .bu = 0.5000, .au = 1.0000,
+    .rv = 0.5000, .gv =-0.4187, .bv =-0.0813, .av = 1.0000,
+};
+    
+static const color_conversion_t hdtv_component_color = {
+    .ry = 0.2126, .gy = 0.7152, .by = 0.0722, .ay = 0.6364,
+    .ru =-0.1146, .gu =-0.3854, .bu = 0.5000, .au = 1.0000,
+    .rv = 0.5000, .gv =-0.4542, .bv =-0.0458, .av = 1.0000,
+};
+    
 static void
 i830_tv_dpms(xf86OutputPtr output, int mode)
 {
@@ -385,30 +588,55 @@ i830_tv_mode_set(xf86OutputPtr output, D
     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;
+    const tv_mode_t	    *tv_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;
+    const video_levels_t	*video_levels;
+    const color_conversion_t	*color_conversion;
+    Bool		    burst_ena;
 
     /* Need to actually choose or construct the appropriate
      * mode.  For now, just set the first one in the list, with
      * NTSC format.
      */
     tv_mode = &tv_modes[0];
-    sc_mode = &tv_sc_modes[TV_SC_NTSC_MJ];
-
-    type = dev_priv->type;
+    
+    tv_ctl = 0;
 
+    switch (dev_priv->type) {
+    default:
+    case TV_TYPE_UNKNOWN:
+    case TV_TYPE_COMPOSITE:
+	tv_ctl |= TV_ENC_OUTPUT_COMPOSITE;
+	video_levels = &tv_mode->composite_levels;
+	color_conversion = &tv_mode->composite_color;
+	burst_ena = tv_mode->burst_ena;
+	break;
+    case TV_TYPE_COMPONENT:
+	tv_ctl |= TV_ENC_OUTPUT_COMPONENT;
+	video_levels = &component_level;
+	if (tv_mode->burst_ena)
+	    color_conversion = &sdtv_component_color;
+	else
+	    color_conversion = &hdtv_component_color;
+	burst_ena = FALSE;
+	break;
+    case TV_TYPE_SVIDEO:
+	tv_ctl |= TV_ENC_OUTPUT_SVIDEO;
+	video_levels = &tv_mode->svideo_levels;
+	color_conversion = &tv_mode->svideo_color;
+	burst_ena = tv_mode->burst_ena;
+	break;
+    }
     hctl1 = (tv_mode->hsync_end << TV_HSYNC_END_SHIFT) |
 	(tv_mode->htotal << TV_HTOTAL_SHIFT);
 
     hctl2 = (tv_mode->hburst_start << 16) |
 	(tv_mode->hburst_len << TV_HBURST_LEN_SHIFT);
-    if (tv_mode->burst_ena)
+    if (burst_ena)
 	hctl2 |= TV_BURST_ENA;
 
     hctl3 = (tv_mode->hblank_start << TV_HBLANK_START_SHIFT) |
@@ -440,44 +668,32 @@ i830_tv_mode_set(xf86OutputPtr output, D
     vctl7 = (tv_mode->vburst_start_f4 << TV_VBURST_START_F4_SHIFT) |
 	(tv_mode->vburst_end_f4 << TV_VBURST_END_F4_SHIFT);
 
-    tv_ctl = 0;
     if (intel_crtc->pipe == 1)
 	tv_ctl |= TV_ENC_PIPEB_SELECT;
 
-    switch (type) {
-    case TV_TYPE_COMPOSITE:
-	tv_ctl |= TV_ENC_OUTPUT_COMPOSITE;
-	break;
-    case TV_TYPE_COMPONENT:
-	tv_ctl |= TV_ENC_OUTPUT_COMPONENT;
-	break;
-    case TV_TYPE_SVIDEO:
-	tv_ctl |= TV_ENC_OUTPUT_SVIDEO;
-	break;
-    default:
-    case TV_TYPE_UNKNOWN:
-	tv_ctl |= TV_ENC_OUTPUT_SVIDEO_COMPOSITE;
-	break;
-    }
     tv_ctl |= tv_mode->oversample;
     if (tv_mode->progressive)
 	tv_ctl |= TV_PROGRESSIVE;
-    if (sc_mode->pal_burst)
+    if (tv_mode->pal_burst)
 	tv_ctl |= TV_PAL_BURST;
 
-    scctl1 = TV_SC_DDA1_EN | TV_SC_DDA2_EN;
-    if (sc_mode->dda3_size != 0)
+    scctl1 = TV_SC_DDA1_EN;
+    
+    if (tv_mode->dda2_inc)
+	scctl1 |= TV_SC_DDA2_EN;
+    
+    if (tv_mode->dda3_inc)
 	scctl1 |= TV_SC_DDA3_EN;
-    scctl1 |= sc_mode->sc_reset;
-    /* XXX: set the burst level */
-    scctl1 |= 113 << TV_BURST_LEVEL_SHIFT;    /* from BIOS */
-    scctl1 |= sc_mode->dda1_inc << TV_SCDDA1_INC_SHIFT;
+    
+    scctl1 |= tv_mode->sc_reset;
+    scctl1 |= video_levels->burst << TV_BURST_LEVEL_SHIFT;
+    scctl1 |= tv_mode->dda1_inc << TV_SCDDA1_INC_SHIFT;
 
-    scctl2 = sc_mode->dda2_size << TV_SCDDA2_SIZE_SHIFT |
-	sc_mode->dda2_inc << TV_SCDDA2_INC_SHIFT;
+    scctl2 = tv_mode->dda2_size << TV_SCDDA2_SIZE_SHIFT |
+	tv_mode->dda2_inc << TV_SCDDA2_INC_SHIFT;
 
-    scctl3 = sc_mode->dda3_size << TV_SCDDA3_SIZE_SHIFT |
-	sc_mode->dda3_inc << TV_SCDDA3_INC_SHIFT;
+    scctl3 = tv_mode->dda3_size << TV_SCDDA3_SIZE_SHIFT |
+	tv_mode->dda3_inc << TV_SCDDA3_INC_SHIFT;
 
     /* Enable two fixes for the chips that need them. */
     if (pI830->PciInfo->chipType < PCI_CHIP_I945_G)
@@ -508,7 +724,8 @@ i830_tv_mode_set(xf86OutputPtr output, D
     OUTREG(TV_CSC_V, 0x037A033D);
     OUTREG(TV_CSC_V2, 0x06F60200);
     OUTREG(TV_CLR_KNOBS, 0x00606000);
-    OUTREG(TV_CLR_LEVEL, 0x013C010A);
+    OUTREG(TV_CLR_LEVEL, ((video_levels->black << TV_BLACK_LEVEL_SHIFT) |
+			  (video_levels->blank << TV_BLANK_LEVEL_SHIFT)));
     OUTREG(TV_WIN_POS, 0x00360024);
     OUTREG(TV_WIN_SIZE, 0x02640198);
     OUTREG(TV_FILTER_CTL_1, 0x8000085E);
@@ -527,10 +744,10 @@ i830_tv_mode_set(xf86OutputPtr output, D
     OUTREG(TV_CTL, tv_ctl);
 }
 
-static const DisplayModeRec tvModes[] = {
+static const DisplayModeRec reported_modes[] = {
     {
 	.name = "NTSC 480i",
-	.Clock = 108000,
+	.Clock = TV_PLL_CLOCK,
 	
 	.HDisplay   = 1024,
 	.HSyncStart = 1048,
@@ -542,7 +759,7 @@ static const DisplayModeRec tvModes[] = 
 	.VSyncEnd   = 777,
 	.VTotal     = 806,
 
-	.type       = M_T_DEFAULT
+	.type       = M_T_DRIVER
     }
 };
 
@@ -641,7 +858,8 @@ i830_tv_detect(xf86OutputPtr output)
     {
 	if (intel_output->load_detect_temp)
 	{
-	    mode = tvModes[0];
+	    /* we only need the pixel clock set correctly here */
+	    mode = reported_modes[0];
 	    xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
 	    i830PipeSetMode (crtc, &mode, FALSE);
 	}
@@ -668,43 +886,25 @@ i830_tv_detect(xf86OutputPtr output)
 static DisplayModePtr
 i830_tv_get_modes(xf86OutputPtr output)
 {
-    ScrnInfoPtr pScrn = output->scrn;
-    I830Ptr pI830 = I830PTR(pScrn);
-    DisplayModePtr new;
-    char stmp[32];
+    ScrnInfoPtr	    pScrn = output->scrn;
+    I830Ptr	    pI830 = I830PTR(pScrn);
+    DisplayModePtr  new, first = NULL, *tail = &first;;
+    int		    i;
 
     (void) pI830;
-    new             = xnfcalloc(1, sizeof (DisplayModeRec));
-    sprintf(stmp, "480i");
-    new->name       = xnfalloc(strlen(stmp) + 1);
-    strcpy(new->name, stmp);
-    
-    new->Clock      = 108000;
-    
-    /*
-    new->HDisplay   = 640;
-    new->HSyncStart = 664;
-    new->HSyncEnd   = 704;
-    new->HTotal     = 832;
-    
-    new->VDisplay   = 480;
-    new->VSyncStart = 489;
-    new->VSyncEnd   = 491;
-    new->VTotal     = 520;
-     */
-    new->HDisplay   = 1024;
-    new->HSyncStart = 1048;
-    new->HSyncEnd   = 1184;
-    new->HTotal     = 1344;
-    
-    new->VDisplay   = 768;
-    new->VSyncStart = 771;
-    new->VSyncEnd   = 777;
-    new->VTotal     = 806;
 
-    new->type       = M_T_DRIVER;
+    for (i = 0; i < sizeof (reported_modes) / sizeof (reported_modes[0]); i++)
+    {
+	new             = xnfcalloc(1, sizeof (DisplayModeRec));
+
+	*new = reported_modes[i];
+	new->name = xnfalloc(strlen(reported_modes[i].name) + 1);
+	strcpy(new->name, reported_modes[i].name);
+	*tail = new;
+	tail = &new->next;
+    }
 
-    return new;
+    return first;
 }
 
 static void
diff --git a/src/tv.5c b/src/tv.5c
new file mode 100644
index 0000000..b4a2ba6
--- /dev/null
+++ b/src/tv.5c
@@ -0,0 +1,128 @@
+/*
+ * tv.5c
+ *
+ * Compute tv encoder subcarrier dda constants
+ *
+ * The TV encoder subcarrier must be set precisely to the
+ * required frequency or the cumulative phase errors will be
+ * quite visible in the output. To accomplish this, the TV encoder
+ * has a complex circuit that takes a fixed clock, generated by the PLL
+ * and generates a precise subcarrier clock from that using the following
+ * formula:
+ *
+ *  subcarrier = pixel_clock * (S1 + (S2 + (S3/Z3)) / Z2) / 4096
+ *
+ * Careful selection of the constants will provide the necessarily
+ * precise clock.
+ *
+ * In the code below, S1 is represented by dda1, S2/Z2 by dda2 and S3/Z3
+ * by dda3.
+ */
+
+typedef struct {
+    int	step;
+    int	size;
+} term_t;
+
+/*
+ * Find the approximation closest, but no larger than 'v', where
+ * 0 <= v < 1, and the result denominator must be less than 30000.
+ */
+term_t approx (rational v)
+{
+    rational	best_dist = 1.0;
+    term_t	best;
+
+    for (int den = 20000; den < 30000; den++)
+    {
+	int num = floor (v * den);
+	term_t	    approx = { step = num, size = den };
+	rational    dist = v - approx.step/approx.size;
+	if (dist >= 0 && dist < best_dist)
+	{
+	    best_dist = dist;
+	    best = approx;
+	}
+    }
+    return best;
+}
+
+typedef struct {
+    rational	subcarrier;
+    rational	pixel;
+    rational	result;
+    term_t	dda1;
+    term_t	dda2;
+    term_t	dda3;
+} dda;
+
+/*
+ * Compute the dda constants for the given pixel clock and
+ * desired subcarrier frequency
+ */
+
+dda find_dda (rational pixel, rational subcarrier)
+{
+    dda	d;
+
+    d.subcarrier = subcarrier;
+    d.pixel = pixel;
+    
+    rational	dda1 = subcarrier / pixel * 4096;
+    d.dda1 = (term_t) { step = floor (dda1), size = 4096 };
+    
+    rational	dda2 = dda1 - d.dda1.step;
+    d.dda2 = approx (dda2);
+    
+    rational	dda3 = dda2 * d.dda2.size - d.dda2.step;
+    d.dda3 = approx (dda3);
+
+    /* Compute the resulting pixel clock to compare */
+    d.result = d.pixel * (d.dda1.step +
+			  (d.dda2.step + d.dda3.step/d.dda3.size) /
+			  d.dda2.size) / d.dda1.size;
+    return d;
+}
+
+/*
+ * Print out the computed constants
+ */
+void print_dda (dda d)
+{
+    printf ("\t/* desired %9.7f actual %9.7f clock %g */\n",
+	    d.subcarrier, d.result, d.pixel);
+    printf ("\t.dda1_inc\t= %6d,\n", d.dda1.step);
+    printf ("\t.dda2_inc\t= %6d,\t.dda2_size\t= %6d,\n",
+	    d.dda2.step, d.dda2.step != 0 ? d.dda2.size : 0);
+    printf ("\t.dda3_inc\t= %6d,\t.dda3_size\t= %6d,\n",
+	    d.dda3.step, d.dda3.step != 0 ? d.dda3.size : 0);
+}
+
+/*
+ * These are all of the required subcarrier frequencies
+ */
+rational[]    subcarriers = {
+    /* these are the values we use; for some reason, this generates
+     * a more stable image (at least for NTSC) */
+    3.580, 4.434, 3.582, 3.576, 4.430,
+    
+    /* these are the values pulled out of the various specs */
+    3.579545, 4.433618, 3.582056, 3.575611, 4.433618
+};
+
+/*
+ * We fix the pixel clock to a value which the hardware can
+ * generate exactly
+ */
+rational    pixel = 107.520;
+
+void main ()
+{
+    for (int i = 0; i < dim(subcarriers); i++)
+    {
+	dda d = find_dda (pixel, subcarriers[i]);
+	print_dda (d);
+    }
+}
+
+main ();
diff-tree 4ba72fc408e7fab7c384aff5e73f0cfb8fd86cf3 (from c28075e1d70c98b39fc9829a6a01da171a9b9426)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Tue Dec 19 22:39:57 2006 -0800

    Reinitialize DGA mode list whenever we update the global list.
    
    DGA has a copy of the current mode list (yes, this is broken).
    Regenerate it whenever the ddx mode list changes.

diff --git a/src/i830.h b/src/i830.h
index a92f557..fd9f9aa 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -508,6 +508,7 @@ extern void I830SelectBuffer(ScrnInfoPtr
 extern void I830RefreshRing(ScrnInfoPtr pScrn);
 extern void I830EmitFlush(ScrnInfoPtr pScrn);
 
+extern Bool I830DGAReInit(ScreenPtr pScreen);
 extern Bool I830DGAInit(ScreenPtr pScreen);
 
 #ifdef I830_XV
diff --git a/src/i830_dga.c b/src/i830_dga.c
index b53b667..c312c6d 100644
--- a/src/i830_dga.c
+++ b/src/i830_dga.c
@@ -83,8 +83,8 @@ DGAFunctionRec I830DGAFuncs = {
 #endif
 };
 
-Bool
-I830DGAInit(ScreenPtr pScreen)
+static DGAModePtr
+I830DGAModes (ScreenPtr pScreen, int *nump)
 {
    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
    I830Ptr pI830 = I830PTR(pScrn);
@@ -93,8 +93,6 @@ I830DGAInit(ScreenPtr pScreen)
    int Bpp = pScrn->bitsPerPixel >> 3;
    int num = 0;
 
-   MARKER();
-
    pMode = firstMode = pScrn->modes;
 
    while (pMode) {
@@ -103,7 +101,7 @@ I830DGAInit(ScreenPtr pScreen)
 
       if (!newmodes) {
 	 xfree(modes);
-	 return FALSE;
+	 return NULL;
       }
       modes = newmodes;
 
@@ -159,7 +157,42 @@ I830DGAInit(ScreenPtr pScreen)
       if (pMode == firstMode)
 	 break;
    }
+   *nump = num;
+   return modes;
+}
+
+Bool
+I830DGAReInit(ScreenPtr pScreen)
+{
+   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+   I830Ptr pI830 = I830PTR(pScrn);
+   int num;
+   DGAModePtr  modes;
+   
+   modes = I830DGAModes (pScreen, &num);
+   if (!modes)
+      return FALSE;
+   
+   if (pI830->DGAModes)
+      xfree (pI830->DGAModes);
+   
+   pI830->numDGAModes = num;
+   pI830->DGAModes = modes;
+   return DGAReInitModes (pScreen, modes, num);
+}
 
+Bool
+I830DGAInit(ScreenPtr pScreen)
+{
+   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+   I830Ptr pI830 = I830PTR(pScrn);
+   int num;
+   DGAModePtr  modes;
+   
+   modes = I830DGAModes (pScreen, &num);
+   if (!modes)
+      return FALSE;
+   
    pI830->numDGAModes = num;
    pI830->DGAModes = modes;
 
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 7309675..d30af07 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3600,6 +3600,7 @@ I830CheckDevicesTimer(OsTimerPtr timer, 
       
       xf86ProbeOutputModes (pScrn);
       xf86SetScrnInfoModes (pScrn);
+      I830DGAReInit (pScrn->pScreen);
       xf86SwitchMode(pScrn->pScreen, pScrn->currentMode);
 
       /* Clear the BIOS's hotkey press flags */
diff --git a/src/i830_randr.c b/src/i830_randr.c
index 0a10384..3d6febc 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -97,6 +97,7 @@ xf86RandR12GetInfo (ScreenPtr pScreen, R
     /* Re-probe the outputs for new monitors or modes */
     xf86ProbeOutputModes (scrp);
     xf86SetScrnInfoModes (scrp);
+    I830DGAReInit (pScreen);
 
     for (mode = scrp->modes; ; mode = mode->next)
     {
@@ -787,6 +788,7 @@ xf86RandR12GetInfo12 (ScreenPtr pScreen,
 
     xf86ProbeOutputModes (pScrn);
     xf86SetScrnInfoModes (pScrn);
+    I830DGAReInit (pScreen);
     return xf86RandR12SetInfo12 (pScreen);
 }
 
diff-tree c28075e1d70c98b39fc9829a6a01da171a9b9426 (from 2ef4c5e8f6444aad192304e5a2f7a0c77bfb917d)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Tue Dec 19 21:53:10 2006 -0800

    TV output I830OutputPrivate had wrong type (crashed in SetMode).
    
    TV output private type field was set to I830_OUTPUT_SDVO instead of
    I830_OUTPUT_TVOUT. When DGA mode setting occurred, the sdvo output debug
    code would be invoked and attempt to dereference sdvo-specific bits of the
    private structure leading to a segfault.

diff --git a/src/i830_tv.c b/src/i830_tv.c
index af9826b..6852793 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -774,7 +774,7 @@ i830_tv_init(ScrnInfoPtr pScrn)
 	return;
     }
     dev_priv = (struct i830_tv_priv *) (intel_output + 1);
-    intel_output->type = I830_OUTPUT_SDVO;
+    intel_output->type = I830_OUTPUT_TVOUT;
     intel_output->dev_priv = dev_priv;
     dev_priv->type = TV_TYPE_UNKNOWN;
     
diff-tree 2ef4c5e8f6444aad192304e5a2f7a0c77bfb917d (from b00951a5c87ca8c596ee9cc73d96d598eec60751)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Tue Dec 19 16:45:39 2006 -0800

    Re-initialize physical screen size only if -dpi was passed.
    
    Physical screen size from the config file or DDC will already
    be set correctly in the screen structure, unless it was computed from the
    virtual size using the -dpi command line option. Recompute physical size as
    we reset the screen size if the -dpi option was used.

diff --git a/src/i830_randr.c b/src/i830_randr.c
index 290cb10..0a10384 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -835,9 +835,10 @@ xf86RandR12CreateScreenResources12 (Scre
     XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
     int			c;
     int			width, height;
+    int			mmWidth, mmHeight;
 
     /*
-     * Compute width of screen
+     * Compute size of screen
      */
     width = 0; height = 0;
     for (c = 0; c < config->num_crtc; c++)
@@ -854,14 +855,19 @@ xf86RandR12CreateScreenResources12 (Scre
     
     if (width && height)
     {
-	int mmWidth, mmHeight;
-
-	mmWidth = pScreen->mmWidth;
-	mmHeight = pScreen->mmHeight;
-	if (width != pScreen->width)
-	    mmWidth = mmWidth * width / pScreen->width;
-	if (height != pScreen->height)
-	    mmHeight = mmHeight * height / pScreen->height;
+	/*
+	 * Compute physical size of screen
+	 */
+	if (monitorResolution) 
+	{
+	    mmWidth = width * 25.4 / monitorResolution;
+	    mmHeight = height * 25.4 / monitorResolution;
+	}
+	else
+	{
+	    mmWidth = pScreen->mmWidth;
+	    mmHeight = pScreen->mmHeight;
+	}
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		   "Setting screen physical size to %d x %d\n",
 		   mmWidth, mmHeight);
diff-tree b00951a5c87ca8c596ee9cc73d96d598eec60751 (from parents)
Merge: 05cd921140fae2746c3421715d7f18248a66735a c0a0ddc0ce69b60ac3a58d45cb32ccd0e0bfb0c9
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Tue Dec 19 16:22:04 2006 -0800

    Merge branch 'modesetting-origin' into modesetting

diff-tree 05cd921140fae2746c3421715d7f18248a66735a (from 3c86fdda1d09fd22d4c15a8e412611db4cea7dcf)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Tue Dec 19 16:21:46 2006 -0800

    Align textured video dither matrix to window

diff --git a/src/i915_video.c b/src/i915_video.c
index c2f0184..636b2cb 100644
--- a/src/i915_video.c
+++ b/src/i915_video.c
@@ -103,7 +103,7 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
 
    /* draw rect -- just clipping */
    OUT_RING(_3DSTATE_DRAW_RECT_CMD);
-   OUT_RING(DRAW_DITHER_OFS_X(x1 & 3)| DRAW_DITHER_OFS_Y(y1 & 3)); /* flags */
+   OUT_RING(DRAW_DITHER_OFS_X(pDraw->x & 3)| DRAW_DITHER_OFS_Y(pDraw->y & 3)); /* flags */
    OUT_RING(0x00000000);	/* ymin, xmin */
    OUT_RING((pScrn->virtualX - 1) |
 	    (pScrn->virtualY - 1) << 16); /* ymax, xmax */
diff-tree c0a0ddc0ce69b60ac3a58d45cb32ccd0e0bfb0c9 (from 3c86fdda1d09fd22d4c15a8e412611db4cea7dcf)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Dec 19 16:06:13 2006 -0800

    Bug #9382: Save the CRTC's desired mode in the old RandR 1.0 mode set path.

diff --git a/src/i830_display.c b/src/i830_display.c
index 88f6f16..e3fdf6d 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -1013,6 +1013,7 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
 			     TRUE);
 	if (!ok)
 	    goto done;
+	crtc->desiredMode = *pMode;
     }
 
     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Mode bandwidth is %d Mpixel/s\n",
diff-tree 3c86fdda1d09fd22d4c15a8e412611db4cea7dcf (from 293ad158ece941eeb9894f5af4d663464b9954e5)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Tue Dec 19 15:53:07 2006 -0800

    Turn on dithering for 915 textured video

diff --git a/src/i915_video.c b/src/i915_video.c
index fb3f4fc..c2f0184 100644
--- a/src/i915_video.c
+++ b/src/i915_video.c
@@ -60,7 +60,7 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
 			 DrawablePtr pDraw)
 {
    I830Ptr pI830 = I830PTR(pScrn);
-   CARD32 format, ms3, s2;
+   CARD32 format, ms3, s2, s5;
    BoxPtr pbox;
    int nbox, dxo, dyo;
    Bool planar;
@@ -103,7 +103,7 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
 
    /* draw rect -- just clipping */
    OUT_RING(_3DSTATE_DRAW_RECT_CMD);
-   OUT_RING(0x00000000);	/* flags */
+   OUT_RING(DRAW_DITHER_OFS_X(x1 & 3)| DRAW_DITHER_OFS_Y(y1 & 3)); /* flags */
    OUT_RING(0x00000000);	/* ymin, xmin */
    OUT_RING((pScrn->virtualX - 1) |
 	    (pScrn->virtualY - 1) << 16); /* ymax, xmax */
@@ -131,7 +131,10 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
    OUT_RING(s2);
    OUT_RING((1 << S4_POINT_WIDTH_SHIFT) | S4_LINE_WIDTH_ONE |
 	    S4_CULLMODE_NONE | S4_VFMT_XY);
-   OUT_RING(0x00000000); /* S5 - enable bits */
+   s5 = 0x0;
+   if (pI830->cpp == 2)
+      s5 |= S5_COLOR_DITHER_ENABLE;
+   OUT_RING(s5); /* S5 - enable bits */
    OUT_RING((2 << S6_DEPTH_TEST_FUNC_SHIFT) |
 	    (2 << S6_CBUF_SRC_BLEND_FACT_SHIFT) |
 	    (1 << S6_CBUF_DST_BLEND_FACT_SHIFT) | S6_COLOR_WRITE_ENABLE |
diff-tree 293ad158ece941eeb9894f5af4d663464b9954e5 (from ff1223142aedcf888665de6e4d7d5d03a55b2688)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Dec 19 14:35:51 2006 -0800

    Remove 8k framebuffer stride restriction on 965.
    
    Also, clean up the message if the limitation is hit.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 09488ab..7309675 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1840,8 +1840,9 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 #endif
       pI830->disableTiling = TRUE; /* no DRI - so disableTiling */
 
-   if (pScrn->displayWidth * pI830->cpp > 8192) {
-      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot support frame buffer stride > 8K >  DRI.\n");
+   if (!IS_I965G(pI830) && pScrn->displayWidth * pI830->cpp > 8192) {
+      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		 "Cannot support DRI with frame buffer stride > 8K.\n");
       pI830->disableTiling = TRUE;
       pI830->directRenderingDisabled = TRUE;
    }
diff-tree ff1223142aedcf888665de6e4d7d5d03a55b2688 (from 3b5703c7fa08e63f2a31be7496ded9c70015946d)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Dec 19 12:49:55 2006 -0800

    Only erase curMode in i830DisableUnusedFunctions when the CRTC is disabled.
    
    This bug resulted in broken xinerama, among other issues.

diff --git a/src/i830_display.c b/src/i830_display.c
index 4899763..88f6f16 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -987,9 +987,9 @@ i830DisableUnusedFunctions(ScrnInfoPtr p
 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling CRTC %s\n",
 		       pipe_name);
 	    crtc->funcs->dpms(crtc, DPMSModeOff);
-	}
 
-	memset(&crtc->curMode, 0, sizeof(crtc->curMode));
+	    memset(&crtc->curMode, 0, sizeof(crtc->curMode));
+	}
     }
 }
 
diff-tree 3b5703c7fa08e63f2a31be7496ded9c70015946d (from d89e211b12ff715d7475421af69157b102accaca)
Author: Daniel Stone <daniel at fooishbar.org>
Date:   Tue Dec 19 09:49:49 2006 -0800

    Respect the srcdir.

diff --git a/src/ch7xxx/Makefile.am b/src/ch7xxx/Makefile.am
index d63c7fc..7f3b1e1 100644
--- a/src/ch7xxx/Makefile.am
+++ b/src/ch7xxx/Makefile.am
@@ -3,7 +3,7 @@
 # -avoid-version prevents gratuitous .0.0.0 version numbers on the end
 # _ladir passes a dummy rpath to libtool so the thing will actually link
 # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
-AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ -I../
+AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ -I$(srcdir)/../
 
 ch7xxx_la_LTLIBRARIES = ch7xxx.la
 ch7xxx_la_LDFLAGS = -module -avoid-version
diff --git a/src/sil164/Makefile.am b/src/sil164/Makefile.am
index d4c0cbd..927f5a7 100644
--- a/src/sil164/Makefile.am
+++ b/src/sil164/Makefile.am
@@ -3,7 +3,7 @@
 # -avoid-version prevents gratuitous .0.0.0 version numbers on the end
 # _ladir passes a dummy rpath to libtool so the thing will actually link
 # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
-AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ -I../
+AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ -I$(srcdir)/../
 
 sil164_la_LTLIBRARIES = sil164.la
 sil164_la_LDFLAGS = -module -avoid-version
diff-tree d89e211b12ff715d7475421af69157b102accaca (from 3fc9feec7b29e0b908e3b90e0f6634117d66ba6d)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Dec 15 14:39:14 2006 -0800

    Disable configure-disabled outputs before mode setting.
    
    We're not supposed to turn off pipes/planes/dplls with outputs attached, which
    we could have done before this.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 7da4bf5..09488ab 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3173,6 +3173,8 @@ I830EnterVT(int scrnIndex, int flags)
    ResetState(pScrn, FALSE);
    SetHWOperatingState(pScrn);
 
+   i830DisableUnusedFunctions(pScrn);
+
    for (i = 0; i < xf86_config->num_crtc; i++)
    {
       xf86CrtcPtr	crtc = xf86_config->crtc[i];
@@ -3188,8 +3190,6 @@ I830EnterVT(int scrnIndex, int flags)
       i830PipeSetBase(crtc, crtc->x, crtc->y);
    }
 
-   i830DisableUnusedFunctions(pScrn);
-
    i830DumpRegs (pScrn);
    i830DescribeOutputConfiguration(pScrn);
 
diff-tree 3fc9feec7b29e0b908e3b90e0f6634117d66ba6d (from 7b8056e3e347b15b37be0116315d7d3a23aef99f)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Dec 15 14:38:23 2006 -0800

    Simplify i830DisableUnusedFunctions() by using the CRTC dpms routines.

diff --git a/src/i830_display.c b/src/i830_display.c
index f87aadc..4899763 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -962,7 +962,6 @@ void
 i830DisableUnusedFunctions(ScrnInfoPtr pScrn)
 {
     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-    I830Ptr pI830 = I830PTR(pScrn);
     int o, pipe;
 
     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling unused functions\n");
@@ -970,51 +969,24 @@ i830DisableUnusedFunctions(ScrnInfoPtr p
     for (o = 0; o < xf86_config->num_output; o++) 
     {
 	xf86OutputPtr  output = xf86_config->output[o];
-	if (!output->crtc)
+	if (!output->crtc) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling output %s\n",
+		       output->name);
 	    (*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 < xf86_config->num_crtc; pipe++) 
     {
 	xf86CrtcPtr crtc = xf86_config->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 (crtc->enabled)
-	    continue;
-	
-	dspcntr = INREG(dspcntr_reg);
-	if (dspcntr & DISPLAY_PLANE_ENABLE) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling plane %s\n",
-		       pipe_name);
-	    
-	    OUTREG(dspcntr_reg, dspcntr & ~DISPLAY_PLANE_ENABLE);
-
-	    /* Wait for vblank for the disable to take effect */
-	    i830WaitForVblank(pScrn);
-	}
-
-	pipeconf = INREG(pipeconf_reg);
-	if (pipeconf & PIPEACONF_ENABLE) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling pipe %s\n",
-		       pipe_name);
-	   OUTREG(pipeconf_reg, pipeconf & ~PIPEACONF_ENABLE);
-	}
-
-	dpll = INREG(dpll_reg);
-	if (dpll & DPLL_VCO_ENABLE) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling DPLL %s\n",
+	if (!crtc->enabled) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling CRTC %s\n",
 		       pipe_name);
-	    OUTREG(dpll_reg, dpll & ~DPLL_VCO_ENABLE);
+	    crtc->funcs->dpms(crtc, DPMSModeOff);
 	}
 
 	memset(&crtc->curMode, 0, sizeof(crtc->curMode));
diff-tree 7b8056e3e347b15b37be0116315d7d3a23aef99f (from eedef7adc53dd8337d27c02551c5778fb43bae05)
Author: Keith Packard <keithp at ukulele.keithp.com>
Date:   Tue Dec 19 01:32:54 2006 -0800

    Writing 1 to I2C line means to tristate the bus so others can manipulate it.
    
    We were forcing bus lines to 1 which was breaking DDC for some monitors.
    Instead, make the PutBits function just tristate when writing 1 bits.

diff --git a/src/i830_i2c.c b/src/i830_i2c.c
index d246c16..8fd12ea 100644
--- a/src/i830_i2c.c
+++ b/src/i830_i2c.c
@@ -272,31 +272,21 @@ i830I2CGetBits(I2CBusPtr b, int *clock, 
 {
     ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
     I830Ptr pI830 = I830PTR(pScrn);
-    CARD32 val, tristate = 0;
+    CARD32 val;
 
     val = INREG(b->DriverPrivate.uval);
 
-    /* If we've released either of the lines from holding low, tristate them
-     * so that we can successfully read.  Some hardware fails to read low
-     * values driven by slaves when our master is not tri-stated, while other
-     * chips succeed.
+    /*
+     * to read valid data, we must have written a 1 to
+     * the associated bit. Writing a 1 is done by
+     * tri-stating the bus in PutBits, so we needn't make
+     * sure that is true here
      */
-    if ((val & GPIO_DATA_DIR_OUT) && (val & GPIO_DATA_VAL_OUT))
-	tristate |= GPIO_DATA_DIR_IN | GPIO_DATA_DIR_MASK;
-    if ((val & GPIO_CLOCK_DIR_OUT) && (val & GPIO_CLOCK_VAL_OUT))
-	tristate |= GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK;
-
-    if (tristate) {
-	OUTREG(b->DriverPrivate.uval, tristate);
-
-	val = INREG(b->DriverPrivate.uval);
-    }
-
     *data = (val & GPIO_DATA_VAL_IN) != 0;
     *clock = (val & GPIO_CLOCK_VAL_IN) != 0;
 
 #if I2C_DEBUG
-    ErrorF("Getting I2C:                   %c %c\n",
+    ErrorF("Getting %s:                   %c %c\n", b->BusName,
 	   *clock ? '^' : 'v',
 	   *data ? '^' : 'v');
 #endif
@@ -306,6 +296,7 @@ static void
 i830I2CPutBits(I2CBusPtr b, int clock, int data)
 {
     CARD32 reserved = 0;
+    CARD32 data_bits, clock_bits;
 
 #if I2C_DEBUG
     int cur_clock, cur_data;
@@ -318,11 +309,11 @@ i830I2CPutBits(I2CBusPtr b, int clock, i
     i830I2CGetBits(b, &cur_clock, &cur_data);
 
     if (first) {
-	ErrorF("I2C Debug:        C D      C D\n");
+	ErrorF("%s Debug:        C D      C D\n", b->BusName);
 	first = FALSE;
     }
 
-    ErrorF("Setting I2C 0x%08x to: %c %c\n",
+    ErrorF("Setting %s 0x%08x to: %c %c\n", b->BusName,
 	   (int)b->DriverPrivate.uval,
 	   clock ? '^' : 'v',
 	   data ? '^' : 'v');
@@ -334,17 +325,19 @@ i830I2CPutBits(I2CBusPtr b, int clock, i
 	    (GPIO_DATA_PULLUP_DISABLE | GPIO_CLOCK_PULLUP_DISABLE);
     }
 
-    OUTREG(b->DriverPrivate.uval,
-	   reserved |
-	   (data ? GPIO_DATA_VAL_OUT : 0) |
-	   (clock ? GPIO_CLOCK_VAL_OUT : 0) |
-	   GPIO_CLOCK_DIR_OUT |
-	   GPIO_DATA_DIR_OUT |
-	   GPIO_CLOCK_DIR_MASK |
-	   GPIO_CLOCK_VAL_MASK |
-	   GPIO_DATA_DIR_MASK |
-	   GPIO_DATA_VAL_MASK);
+    /* data or clock == 1 means to tristate the bus. otherwise, drive it low */
+    if (data)
+	data_bits = GPIO_DATA_DIR_IN|GPIO_DATA_DIR_MASK;
+    else
+	data_bits = GPIO_DATA_DIR_OUT|GPIO_DATA_DIR_MASK|GPIO_DATA_VAL_MASK;
+    if (clock)
+	clock_bits = GPIO_CLOCK_DIR_IN|GPIO_CLOCK_DIR_MASK;
+    else
+	clock_bits = GPIO_CLOCK_DIR_OUT|GPIO_CLOCK_DIR_MASK|GPIO_CLOCK_VAL_MASK;
+    
+    OUTREG(b->DriverPrivate.uval, reserved | data_bits | clock_bits);
 }
+
 #endif
 
 /* the i830 has a number of I2C Buses */
diff-tree eedef7adc53dd8337d27c02551c5778fb43bae05 (from 8983845f91cacf8110c70121e0f5f293fe443e6d)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Dec 18 15:57:44 2006 -0800

    Add a detect() function for DVO chips, and implement it on sil164.

diff --git a/src/ch7xxx/Makefile.am b/src/ch7xxx/Makefile.am
index 645ac69..d63c7fc 100644
--- a/src/ch7xxx/Makefile.am
+++ b/src/ch7xxx/Makefile.am
@@ -3,7 +3,7 @@
 # -avoid-version prevents gratuitous .0.0.0 version numbers on the end
 # _ladir passes a dummy rpath to libtool so the thing will actually link
 # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
-AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@
+AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ -I../
 
 ch7xxx_la_LTLIBRARIES = ch7xxx.la
 ch7xxx_la_LDFLAGS = -module -avoid-version
diff --git a/src/ch7xxx/ch7xxx.c b/src/ch7xxx/ch7xxx.c
index b1e8cbd..5bfb7c5 100644
--- a/src/ch7xxx/ch7xxx.c
+++ b/src/ch7xxx/ch7xxx.c
@@ -25,6 +25,11 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF 
 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 **************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <string.h>
 #include "xf86.h"
 #include "xf86_OSproc.h"
@@ -32,6 +37,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "compiler.h"
 #include "miscstruct.h"
 #include "xf86i2c.h"
+#include "i830_xf86Crtc.h"
 #define DPMS_SERVER
 #include <X11/extensions/dpms.h>
 
@@ -173,6 +179,12 @@ out:
     return NULL;
 }
 
+static xf86OutputStatus
+ch7xxx_detect(I2CDevPtr d)
+{
+    return XF86OutputStatusUnknown;
+}
+
 static ModeStatus
 ch7xxx_mode_valid(I2CDevPtr d, DisplayModePtr mode)
 {
@@ -275,6 +287,7 @@ ch7xxx_restore(I2CDevPtr d)
 
 I830I2CVidOutputRec CH7xxxVidOutput = {
     .init = ch7xxx_init,
+    .detect = ch7xxx_detect,
     .mode_valid = ch7xxx_mode_valid,
     .mode_set = ch7xxx_mode_set,
     .dpms = ch7xxx_dpms,
diff --git a/src/i2c_vid.h b/src/i2c_vid.h
index 877122f..3be394d 100644
--- a/src/i2c_vid.h
+++ b/src/i2c_vid.h
@@ -4,6 +4,7 @@
 
 typedef struct _I830I2CVidOutputRec {
     void *(*init)(I2CBusPtr b, I2CSlaveAddr addr);
+    xf86OutputStatus (*detect)(I2CDevPtr d);
     ModeStatus (*mode_valid)(I2CDevPtr d, DisplayModePtr mode);
     void (*mode_set)(I2CDevPtr d, DisplayModePtr mode);
     void (*dpms)(I2CDevPtr d, int mode);
diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index c3ad4c0..97453de 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -177,7 +177,10 @@ i830_dvo_mode_set(xf86OutputPtr output, 
 static xf86OutputStatus
 i830_dvo_detect(xf86OutputPtr output)
 {
-    return XF86OutputStatusUnknown;
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    void *dev_priv = intel_output->i2c_drv->dev_priv;
+
+    return intel_output->i2c_drv->vid_rec->detect(dev_priv);
 }
 
 static Bool
diff --git a/src/sil164/Makefile.am b/src/sil164/Makefile.am
index bb84d03..d4c0cbd 100644
--- a/src/sil164/Makefile.am
+++ b/src/sil164/Makefile.am
@@ -3,7 +3,7 @@
 # -avoid-version prevents gratuitous .0.0.0 version numbers on the end
 # _ladir passes a dummy rpath to libtool so the thing will actually link
 # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
-AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@
+AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ -I../
 
 sil164_la_LTLIBRARIES = sil164.la
 sil164_la_LDFLAGS = -module -avoid-version
diff --git a/src/sil164/sil164.c b/src/sil164/sil164.c
index 497336c..453ed04 100644
--- a/src/sil164/sil164.c
+++ b/src/sil164/sil164.c
@@ -26,12 +26,18 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF 
 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 **************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include "xf86.h"
 #include "xf86_OSproc.h"
 #include "xf86Resources.h"
 #include "compiler.h"
 #include "miscstruct.h"
 #include "xf86i2c.h"
+#include "i830_xf86Crtc.h"
 #define DPMS_SERVER
 #include <X11/extensions/dpms.h>
 
@@ -117,6 +123,20 @@ out:
     return NULL;
 }
 
+static xf86OutputStatus
+sil164_detect(I2CDevPtr d)
+{
+    SIL164Ptr sil = SILPTR(d);
+    CARD8 reg9;
+
+    sil164ReadByte(sil, SIL164_REG9, &reg9);
+
+    if (reg9 & SIL164_9_HTPLG)
+	return XF86OutputStatusConnected;
+    else
+	return XF86OutputStatusDisconnected;
+}
+
 static ModeStatus
 sil164_mode_valid(I2CDevPtr d, DisplayModePtr mode)
 {
@@ -215,6 +235,7 @@ sil164_restore(I2CDevPtr d)
 
 I830I2CVidOutputRec SIL164VidOutput = {
     .init = sil164_init,
+    .detect = sil164_detect,
     .mode_valid = sil164_mode_valid,
     .mode_set = sil164_mode_set,
     .dpms = sil164_dpms,
diff-tree 8983845f91cacf8110c70121e0f5f293fe443e6d (from fa4642048b183134544fc5ee47558446d27f6194)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Dec 18 15:57:08 2006 -0800

    Fix crash in xf86SetScrnInfoModes when pScrn->modes ends up empty.

diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index 51e6f1c..bb6c869 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -555,16 +555,20 @@ xf86SetScrnInfoModes (ScrnInfoPtr pScrn)
     for (mode = pScrn->modes; mode; mode = mode->next)
 	if (xf86ModesEqual (mode, &crtc->desiredMode))
 	    break;
-    
-    /* For some reason, pScrn->modes is circular, unlike the other mode lists.
-     * How great is that?
-     */
-    for (last = pScrn->modes; last && last->next; last = last->next);
-    last->next = pScrn->modes;
-    pScrn->modes->prev = last;
-    if (mode)
-	while (pScrn->modes != mode)
-	    pScrn->modes = pScrn->modes->next;
+
+    if (pScrn->modes != NULL) {
+	/* For some reason, pScrn->modes is circular, unlike the other mode
+	 * lists.  How great is that?
+	 */
+	for (last = pScrn->modes; last && last->next; last = last->next)
+	    ;
+	last->next = pScrn->modes;
+	pScrn->modes->prev = last;
+	if (mode) {
+	    while (pScrn->modes != mode)
+		pScrn->modes = pScrn->modes->next;
+	}
+    }
     pScrn->currentMode = pScrn->modes;
 }
 
diff-tree fa4642048b183134544fc5ee47558446d27f6194 (from dcb069a1da6b3300b0772843dd9b67efdf319637)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Dec 18 15:32:35 2006 -0800

    Clean up i2c_vid interface, including de-StudlyCapsing and removing dead code.
    
    The old Init() function is removed and the previous Detect() function is now
    init().  This leaves us room in the namespace for a detect() like other
    outputs have ("is the monitor connected?").  Also, Power() became dpms(),
    taking a DPMSMode*.  In general, the mode setting path now matches the intel
    internal path, except for the lack of mode_fixup().

diff --git a/src/ch7xxx/ch7xxx.c b/src/ch7xxx/ch7xxx.c
index 61ab20d..b1e8cbd 100644
--- a/src/ch7xxx/ch7xxx.c
+++ b/src/ch7xxx/ch7xxx.c
@@ -32,6 +32,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "compiler.h"
 #include "miscstruct.h"
 #include "xf86i2c.h"
+#define DPMS_SERVER
+#include <X11/extensions/dpms.h>
 
 #include "../i2c_vid.h"
 #include "ch7xxx.h"
@@ -112,7 +114,7 @@ ch7xxx_write(struct ch7xxx_priv *dev_pri
 }
 
 static void *
-ch7xxx_probe(I2CBusPtr b, I2CSlaveAddr addr)
+ch7xxx_init(I2CBusPtr b, I2CSlaveAddr addr)
 {
     /* this will detect the CH7xxx chip on the specified i2c bus */
     struct ch7xxx_priv *dev_priv;
@@ -171,14 +173,6 @@ out:
     return NULL;
 }
 
-
-static Bool
-ch7xxx_init(I2CDevPtr d)
-{
-    /* not much to do */
-    return TRUE;
-}
-
 static ModeStatus
 ch7xxx_mode_valid(I2CDevPtr d, DisplayModePtr mode)
 {
@@ -228,11 +222,11 @@ ch7xxx_mode_set(I2CDevPtr d, DisplayMode
 
 /* set the CH7xxx power state */
 static void
-ch7xxx_power(I2CDevPtr d, Bool on)
+ch7xxx_dpms(I2CDevPtr d, int mode)
 {
     struct ch7xxx_priv *dev_priv = d->DriverPrivate.ptr;
 
-    if (on)
+    if (mode == DPMSModeOn)
 	ch7xxx_write(dev_priv, CH7xxx_PM, CH7xxx_PM_DVIL | CH7xxx_PM_DVIP);
     else
 	ch7xxx_write(dev_priv, CH7xxx_PM, CH7xxx_PM_FPD);
@@ -280,12 +274,11 @@ ch7xxx_restore(I2CDevPtr d)
 }
 
 I830I2CVidOutputRec CH7xxxVidOutput = {
-    ch7xxx_probe,
-    ch7xxx_init,
-    ch7xxx_mode_valid,
-    ch7xxx_mode_set,
-    ch7xxx_power,
-    ch7xxx_dump_regs,
-    ch7xxx_save,
-    ch7xxx_restore,
+    .init = ch7xxx_init,
+    .mode_valid = ch7xxx_mode_valid,
+    .mode_set = ch7xxx_mode_set,
+    .dpms = ch7xxx_dpms,
+    .dump_regs = ch7xxx_dump_regs,
+    .save = ch7xxx_save,
+    .restore = ch7xxx_restore,
 };
diff --git a/src/i2c_vid.h b/src/i2c_vid.h
index 5a743d2..877122f 100644
--- a/src/i2c_vid.h
+++ b/src/i2c_vid.h
@@ -3,14 +3,13 @@
 #define I2C_VID_H
 
 typedef struct _I830I2CVidOutputRec {
-  void *(*Detect)(I2CBusPtr b, I2CSlaveAddr addr);
-  Bool (*Init)(I2CDevPtr d);
-  ModeStatus (*ModeValid)(I2CDevPtr d, DisplayModePtr mode);
-  void (*Mode)(I2CDevPtr d, DisplayModePtr mode);
-  void (*Power)(I2CDevPtr d, Bool On);
-  void (*PrintRegs)(I2CDevPtr d);
-  void (*SaveRegs)(I2CDevPtr d);
-  void (*RestoreRegs)(I2CDevPtr d);
+    void *(*init)(I2CBusPtr b, I2CSlaveAddr addr);
+    ModeStatus (*mode_valid)(I2CDevPtr d, DisplayModePtr mode);
+    void (*mode_set)(I2CDevPtr d, DisplayModePtr mode);
+    void (*dpms)(I2CDevPtr d, int mode);
+    void (*dump_regs)(I2CDevPtr d);
+    void (*save)(I2CDevPtr d);
+    void (*restore)(I2CDevPtr d);
 } I830I2CVidOutputRec, *I830I2CVidOutputPtr;
 
 #endif
diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index 804f0fc..c3ad4c0 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -62,12 +62,13 @@ i830_dvo_dpms(xf86OutputPtr output, int 
     ScrnInfoPtr		    pScrn = output->scrn;
     I830Ptr		    pI830 = I830PTR(pScrn);
     I830OutputPrivatePtr    intel_output = output->driver_private;
+    void *		    dev_priv = intel_output->i2c_drv->dev_priv;
 
     if (mode == DPMSModeOn) {
 	OUTREG(DVOC, INREG(DVOC) | DVO_ENABLE);
-	(*intel_output->i2c_drv->vid_rec->Power)(intel_output->i2c_drv->dev_priv, TRUE);
+	(*intel_output->i2c_drv->vid_rec->dpms)(dev_priv, mode);
     } else {
-	(*intel_output->i2c_drv->vid_rec->Power)(intel_output->i2c_drv->dev_priv, FALSE);
+	(*intel_output->i2c_drv->vid_rec->dpms)(dev_priv, mode);
 	OUTREG(DVOC, INREG(DVOC) & ~DVO_ENABLE);
     }
 }
@@ -78,6 +79,7 @@ i830_dvo_save(xf86OutputPtr output)
     ScrnInfoPtr		    pScrn = output->scrn;
     I830Ptr		    pI830 = I830PTR(pScrn);
     I830OutputPrivatePtr    intel_output = output->driver_private;
+    void *		    dev_priv = intel_output->i2c_drv->dev_priv;
 
     /* Each output should probably just save the registers it touches, but for
      * now, use more overkill.
@@ -86,7 +88,7 @@ i830_dvo_save(xf86OutputPtr output)
     pI830->saveDVOB = INREG(DVOB);
     pI830->saveDVOC = INREG(DVOC);
 
-    (*intel_output->i2c_drv->vid_rec->SaveRegs)(intel_output->i2c_drv->dev_priv);
+    (*intel_output->i2c_drv->vid_rec->save)(dev_priv);
 }
 
 static void
@@ -95,12 +97,13 @@ i830_dvo_restore(xf86OutputPtr output)
     ScrnInfoPtr		    pScrn = output->scrn;
     I830Ptr		    pI830 = I830PTR(pScrn);
     I830OutputPrivatePtr    intel_output = output->driver_private;
+    void *		    dev_priv = intel_output->i2c_drv->dev_priv;
 
     OUTREG(DVOA, pI830->saveDVOA);
     OUTREG(DVOB, pI830->saveDVOB);
     OUTREG(DVOC, pI830->saveDVOC);
 
-    (*intel_output->i2c_drv->vid_rec->RestoreRegs)(intel_output->i2c_drv->dev_priv);
+    (*intel_output->i2c_drv->vid_rec->restore)(dev_priv);
 }
 
 static int
@@ -114,7 +117,7 @@ i830_dvo_mode_valid(xf86OutputPtr output
 
     /* XXX: Validate clock range */
 
-    return intel_output->i2c_drv->vid_rec->ModeValid(dev_priv, pMode);
+    return intel_output->i2c_drv->vid_rec->mode_valid(dev_priv, pMode);
 }
 
 static Bool
@@ -139,8 +142,8 @@ i830_dvo_mode_set(xf86OutputPtr output, 
     CARD32		    dvo;
     int			    dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
 
-    intel_output->i2c_drv->vid_rec->Mode(intel_output->i2c_drv->dev_priv,
-					 mode);
+    intel_output->i2c_drv->vid_rec->mode_set(intel_output->i2c_drv->dev_priv,
+					     mode);
 
     /* 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);
@@ -196,7 +199,7 @@ I830I2CDetectDVOControllers(ScrnInfoPtr 
 	ret_ptr = NULL;
 	drv->vid_rec = LoaderSymbol(drv->fntablename);
 	if (drv->vid_rec != NULL)
-	    ret_ptr = drv->vid_rec->Detect(pI2CBus, drv->address);
+	    ret_ptr = drv->vid_rec->init(pI2CBus, drv->address);
 
 	if (ret_ptr != NULL) {
 	    drv->dev_priv = ret_ptr;
diff --git a/src/sil164/sil164.c b/src/sil164/sil164.c
index 0a68d69..497336c 100644
--- a/src/sil164/sil164.c
+++ b/src/sil164/sil164.c
@@ -32,16 +32,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "compiler.h"
 #include "miscstruct.h"
 #include "xf86i2c.h"
+#define DPMS_SERVER
+#include <X11/extensions/dpms.h>
 
 #include "../i2c_vid.h"
 #include "sil164.h"
 #include "sil164_reg.h"
 
-static void
-sil164PrintRegs(I2CDevPtr d);
-static void
-sil164Power(I2CDevPtr d, Bool On);
-
 static Bool
 sil164ReadByte(SIL164Ptr sil, int addr, CARD8 *ch)
 {
@@ -68,7 +65,7 @@ sil164WriteByte(SIL164Ptr sil, int addr,
 
 /* Silicon Image 164 driver for chip on i2c bus */
 static void *
-sil164Detect(I2CBusPtr b, I2CSlaveAddr addr)
+sil164_init(I2CBusPtr b, I2CSlaveAddr addr)
 {
     /* this will detect the SIL164 chip on the specified i2c bus */
     SIL164Ptr sil;
@@ -120,26 +117,19 @@ out:
     return NULL;
 }
 
-
-static Bool
-sil164Init(I2CDevPtr d)
-{
-    /* not much to do */
-    return TRUE;
-}
-
 static ModeStatus
-sil164ModeValid(I2CDevPtr d, DisplayModePtr mode)
+sil164_mode_valid(I2CDevPtr d, DisplayModePtr mode)
 {
     return MODE_OK;
 }
 
 static void
-sil164Mode(I2CDevPtr d, DisplayModePtr mode)
+sil164_mode_set(I2CDevPtr d, DisplayModePtr mode)
 {
-    sil164Power(d, TRUE);
-    sil164PrintRegs(d);
-
+    /* As long as the basics are set up, since we don't have clock dependencies
+     * in the mode setup, we can just leave the registers alone and everything
+     * will work fine.
+     */
     /* recommended programming sequence from doc */
     /*sil164WriteByte(sil, 0x08, 0x30);
       sil164WriteByte(sil, 0x09, 0x00);
@@ -152,7 +142,7 @@ sil164Mode(I2CDevPtr d, DisplayModePtr m
 
 /* set the SIL164 power state */
 static void
-sil164Power(I2CDevPtr d, Bool On)
+sil164_dpms(I2CDevPtr d, int mode)
 {
     SIL164Ptr sil = SILPTR(d);
     int ret;
@@ -162,7 +152,7 @@ sil164Power(I2CDevPtr d, Bool On)
     if (ret == FALSE)
 	return;
 
-    if (On)
+    if (mode == DPMSModeOn)
 	ch |= SIL164_8_PD;
     else
 	ch &= ~SIL164_8_PD;
@@ -173,7 +163,7 @@ sil164Power(I2CDevPtr d, Bool On)
 }
 
 static void
-sil164PrintRegs(I2CDevPtr d)
+sil164_dump_regs(I2CDevPtr d)
 {
     SIL164Ptr sil = SILPTR(d);
     CARD8 val;
@@ -193,7 +183,7 @@ sil164PrintRegs(I2CDevPtr d)
 }
 
 static void
-sil164SaveRegs(I2CDevPtr d)
+sil164_save(I2CDevPtr d)
 {
     SIL164Ptr sil = SILPTR(d);
 
@@ -210,7 +200,7 @@ sil164SaveRegs(I2CDevPtr d)
 }
 
 static void
-sil164RestoreRegs(I2CDevPtr d)
+sil164_restore(I2CDevPtr d)
 {
     SIL164Ptr sil = SILPTR(d);
 
@@ -224,12 +214,11 @@ sil164RestoreRegs(I2CDevPtr d)
 
 
 I830I2CVidOutputRec SIL164VidOutput = {
-    sil164Detect,
-    sil164Init,
-    sil164ModeValid,
-    sil164Mode,
-    sil164Power,
-    sil164PrintRegs,
-    sil164SaveRegs,
-    sil164RestoreRegs,
+    .init = sil164_init,
+    .mode_valid = sil164_mode_valid,
+    .mode_set = sil164_mode_set,
+    .dpms = sil164_dpms,
+    .dump_regs = sil164_dump_regs,
+    .save = sil164_save,
+    .restore = sil164_restore,
 };
diff-tree dcb069a1da6b3300b0772843dd9b67efdf319637 (from 0305298405bd7018e5c520bdd5ea46a75be09f37)
Author: Dave Airlie <airlied at linux.ie>
Date:   Tue Dec 19 10:29:56 2006 +1100

    ch7xxx: add lookup table for name
    
    Don't load if we don't match name

diff --git a/src/ch7xxx/ch7xxx.c b/src/ch7xxx/ch7xxx.c
index d31a38c..61ab20d 100644
--- a/src/ch7xxx/ch7xxx.c
+++ b/src/ch7xxx/ch7xxx.c
@@ -41,6 +41,17 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * driver for the Chrontel 7xxx DVI chip over DVO.
  */
 
+static struct ch7xxx_id_struct {
+    int vid;
+    char *name;
+} ch7xxx_ids[] = { 
+	{ CH7011_VID, "CH7011" },
+	{ CH7009A_VID, "CH7009A" },
+	{ CH7009B_VID, "CH7009B" },
+};
+
+#define ID_ARRAY_SIZE (sizeof(ch7xxx_ids) / sizeof(ch7xxx_ids[0]))
+
 struct ch7xxx_reg_state {
     CARD8 regs[CH7xxx_NUM_REGS];
 };
@@ -60,6 +71,18 @@ static CARD8 ch7xxxFreqRegs[][7] =
     { 0, 0x23, 0x04, 0x26, 0x30, 0x60, 0x00 },
     { 0, 0x2D, 0x07, 0x26, 0x30, 0xE0, 0x00 } };
 
+static char *ch7xxx_get_id(int vid)
+{
+    int i;
+
+    for (i = 0; i < ID_ARRAY_SIZE; i++) {
+        if (ch7xxx_ids[i].vid == vid)
+		return ch7xxx_ids[i].name;
+    }
+
+    return NULL;
+}
+
 /** Reads an 8 bit register */
 static Bool
 ch7xxx_read(struct ch7xxx_priv *dev_priv, int addr, unsigned char *ch)
@@ -95,6 +118,7 @@ ch7xxx_probe(I2CBusPtr b, I2CSlaveAddr a
     struct ch7xxx_priv *dev_priv;
     CARD8 vendor, device;
     unsigned char ch;
+    char *name;
 
     dev_priv = xcalloc(1, sizeof(struct ch7xxx_priv));
     if (dev_priv == NULL)
@@ -112,7 +136,8 @@ ch7xxx_probe(I2CBusPtr b, I2CSlaveAddr a
     if (!ch7xxx_read(dev_priv, CH7xxx_REG_VID, &vendor))
 	goto out;
 
-    if (vendor != CH7xxx_VID) {
+    name = ch7xxx_get_id(vendor);
+    if (!name) {
 	xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex, X_INFO,
 		   "ch7xxx not detected; got 0x%02x from %s slave %d.\n",
 		   vendor, dev_priv->d.pI2CBus->BusName,
@@ -132,8 +157,8 @@ ch7xxx_probe(I2CBusPtr b, I2CSlaveAddr a
 	goto out;
     }
 	xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex, X_INFO,
-		   "Detected CH7xxx chipset, vendor/device ID 0x%02x/0x%02x\n",
-		   vendor, device);
+		   "Detected %s chipset, vendor/device ID 0x%02x/0x%02x\n",
+		   name, vendor, device);
 
     if (!xf86I2CDevInit(&dev_priv->d)) {
 	goto out;
diff-tree 0305298405bd7018e5c520bdd5ea46a75be09f37 (from 23114fbccad849249b4b7200e3d085a9ac0e2e99)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Dec 18 14:49:01 2006 -0800

    Limit modes to 165Mhz on CH7009, according to spec.

diff --git a/src/ch7xxx/ch7xxx.c b/src/ch7xxx/ch7xxx.c
index e4b21f2..d31a38c 100644
--- a/src/ch7xxx/ch7xxx.c
+++ b/src/ch7xxx/ch7xxx.c
@@ -157,6 +157,9 @@ ch7xxx_init(I2CDevPtr d)
 static ModeStatus
 ch7xxx_mode_valid(I2CDevPtr d, DisplayModePtr mode)
 {
+    if (mode->Clock > 165000)
+	return MODE_CLOCK_HIGH;
+
     return MODE_OK;
 }
 
diff-tree 23114fbccad849249b4b7200e3d085a9ac0e2e99 (from 633d718f6fb019844304228a81c84a8605da004f)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Dec 18 14:47:44 2006 -0800

    Align the driver to the CH7009[AB] spec.
    
    With this, the driver works at 640x480 and 1280x1024 on my panel.

diff --git a/src/ch7xxx/ch7xxx.c b/src/ch7xxx/ch7xxx.c
index 59722b8..e4b21f2 100644
--- a/src/ch7xxx/ch7xxx.c
+++ b/src/ch7xxx/ch7xxx.c
@@ -50,7 +50,7 @@ struct ch7xxx_priv {
     struct ch7xxx_reg_state SavedReg;
     struct ch7xxx_reg_state ModeReg;
     CARD8 save_TCTL, save_TPCP, save_TPD, save_TPVT;
-    CARD8 save_TPF, save_TCT, save_PM;
+    CARD8 save_TLPF, save_TCT, save_PM, save_IDF;
 };
 
 static void ch7xxx_save(I2CDevPtr d);
@@ -164,44 +164,30 @@ static void
 ch7xxx_mode_set(I2CDevPtr d, DisplayModePtr mode)
 {
     struct ch7xxx_priv *dev_priv = d->DriverPrivate.ptr;
-    int ret;
-    unsigned char pm, idf;
-    unsigned char tpcp, tpd, tpf, cm;
-    CARD8 *freq_regs;
-    int i;
-
-    ErrorF("Clock is %d\n", mode->Clock);
-
-    if (mode->Clock < 75000)
-	freq_regs = ch7xxxFreqRegs[0];
-    else if (mode->Clock < 125000)
-	freq_regs = ch7xxxFreqRegs[1];
-    else
-	freq_regs = ch7xxxFreqRegs[2];
-
-    for (i = 0x31; i < 0x37; i++) {
-	dev_priv->ModeReg.regs[i] = freq_regs[i - 0x31];
-	ch7xxx_write(dev_priv, i, dev_priv->ModeReg.regs[i]);
-    }
-
-#if 0
-    xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex, X_ERROR,
-	       "ch7xxx idf is 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
-	       idf, tpcp, tpd, tpf);
+    CARD8 tvco, tpcp, tpd, tlpf, idf;
 
-    xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex, X_ERROR,
-	       "ch7xxx pm is %02X\n", pm);
-
-    if (mode->Clock < 65000) {
+    if (mode->Clock <= 65000) {
+	tvco = 0x23;
 	tpcp = 0x08;
 	tpd = 0x16;
-	tpf = 0x60;
+	tlpf = 0x60;
     } else {
+	tvco = 0x2d;
 	tpcp = 0x06;
 	tpd = 0x26;
-	tpf = 0xa0;
+	tlpf = 0xa0;
     }
 
+    ch7xxx_write(dev_priv, CH7xxx_TCTL, 0x00);
+    ch7xxx_write(dev_priv, CH7xxx_TVCO, tvco);
+    ch7xxx_write(dev_priv, CH7xxx_TPCP, tpcp);
+    ch7xxx_write(dev_priv, CH7xxx_TPD, tpd);
+    ch7xxx_write(dev_priv, CH7xxx_TPVT, 0x30);
+    ch7xxx_write(dev_priv, CH7xxx_TLPF, tlpf);
+    ch7xxx_write(dev_priv, CH7xxx_TCT, 0x00);
+
+    ch7xxx_read(dev_priv, CH7xxx_IDF, &idf);
+
     idf &= ~(CH7xxx_IDF_HSP | CH7xxx_IDF_VSP);
     if (mode->Flags & V_PHSYNC)
 	idf |= CH7xxx_IDF_HSP;
@@ -209,45 +195,19 @@ ch7xxx_mode_set(I2CDevPtr d, DisplayMode
     if (mode->Flags & V_PVSYNC)
 	idf |= CH7xxx_IDF_HSP;
 
-    /* setup PM Registers */
-    pm &= ~CH7xxx_PM_FPD;
-    pm |= CH7xxx_PM_DVIL | CH7xxx_PM_DVIP;
-
-    /* cm |= 1; */
-
-    ch7xxx_write(dev_priv, CH7xxx_CM, cm);
-    ch7xxx_write(dev_priv, CH7xxx_TPCP, tpcp);
-    ch7xxx_write(dev_priv, CH7xxx_TPD, tpd);
-    ch7xxx_write(dev_priv, CH7xxx_TPF, tpf);
-    ch7xxx_write(dev_priv, CH7xxx_TPF, idf);
-    ch7xxx_write(dev_priv, CH7xxx_PM, pm);
-#endif
+    ch7xxx_write(dev_priv, CH7xxx_IDF, idf);
 }
 
 /* set the CH7xxx power state */
 static void
-ch7xxx_power(I2CDevPtr d, Bool On)
+ch7xxx_power(I2CDevPtr d, Bool on)
 {
     struct ch7xxx_priv *dev_priv = d->DriverPrivate.ptr;
-    int ret;
-    unsigned char ch;
-
-    ret = ch7xxx_read(dev_priv, CH7xxx_PM, &ch);
-    if (ret == FALSE)
-	return;
-
-#if 0
-    ret = ch7xxx_read(dev_priv, CH7xxx_REG8, &ch);
-    if (ret)
-	return;
 
-    if (On)
-	ch |= CH7xxx_8_PD;
+    if (on)
+	ch7xxx_write(dev_priv, CH7xxx_PM, CH7xxx_PM_DVIL | CH7xxx_PM_DVIP);
     else
-	ch &= ~CH7xxx_8_PD;
-
-    ch7xxx_write(dev_priv, CH7xxx_REG8, ch);
-#endif
+	ch7xxx_write(dev_priv, CH7xxx_PM, CH7xxx_PM_FPD);
 }
 
 static void
@@ -267,34 +227,28 @@ static void
 ch7xxx_save(I2CDevPtr d)
 {
     struct ch7xxx_priv *dev_priv = d->DriverPrivate.ptr;
-    int ret;
-    int i;
 
-    ch7xxx_read(dev_priv, CH7xxx_PM, &dev_priv->save_PM);
     ch7xxx_read(dev_priv, CH7xxx_TCTL, &dev_priv->save_TCTL);
     ch7xxx_read(dev_priv, CH7xxx_TPCP, &dev_priv->save_TPCP);
     ch7xxx_read(dev_priv, CH7xxx_TPD, &dev_priv->save_TPD);
     ch7xxx_read(dev_priv, CH7xxx_TPVT, &dev_priv->save_TPVT);
-    ch7xxx_read(dev_priv, CH7xxx_TPF, &dev_priv->save_TPF);
-
-    return;
+    ch7xxx_read(dev_priv, CH7xxx_TLPF, &dev_priv->save_TLPF);
+    ch7xxx_read(dev_priv, CH7xxx_PM, &dev_priv->save_PM);
+    ch7xxx_read(dev_priv, CH7xxx_IDF, &dev_priv->save_IDF);
 }
 
 static void
 ch7xxx_restore(I2CDevPtr d)
 {
     struct ch7xxx_priv *dev_priv = d->DriverPrivate.ptr;
-    int ret;
-    int i;
 
     ch7xxx_write(dev_priv, CH7xxx_TCTL, dev_priv->save_TCTL);
     ch7xxx_write(dev_priv, CH7xxx_TPCP, dev_priv->save_TPCP);
     ch7xxx_write(dev_priv, CH7xxx_TPD, dev_priv->save_TPD);
     ch7xxx_write(dev_priv, CH7xxx_TPVT, dev_priv->save_TPVT);
-    ch7xxx_write(dev_priv, CH7xxx_TPF, dev_priv->save_TPF);
+    ch7xxx_write(dev_priv, CH7xxx_TLPF, dev_priv->save_TLPF);
+    ch7xxx_write(dev_priv, CH7xxx_IDF, dev_priv->save_IDF);
     ch7xxx_write(dev_priv, CH7xxx_PM, dev_priv->save_PM);
-
-    return;
 }
 
 I830I2CVidOutputRec CH7xxxVidOutput = {
diff --git a/src/ch7xxx/ch7xxx_reg.h b/src/ch7xxx/ch7xxx_reg.h
index 0a5f188..c626e1f 100644
--- a/src/ch7xxx/ch7xxx_reg.h
+++ b/src/ch7xxx/ch7xxx_reg.h
@@ -53,11 +53,12 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define CH7301_DAC_CNTL 0x21
 #define CH7301_HOTPLUG 0x23
 #define CH7xxx_TCTL 0x31
+#define CH7xxx_TVCO 0x32
 #define CH7xxx_TPCP 0x33
 #define CH7xxx_TPD 0x34
 #define CH7xxx_TPVT 0x35
-#define CH7xxx_TPF 0x36
-#define CH7301_TCT 0x37
+#define CH7xxx_TLPF 0x36
+#define CH7xxx_TCT 0x37
 #define CH7301_TEST_PATTERN 0x48
 #define CH7xxx_PM 0x49
 
diff-tree 633d718f6fb019844304228a81c84a8605da004f (from 3167bc6b24bd74c50ca4c4d361b14aa24d77cfa3)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Dec 18 13:59:17 2006 -0800

    Clean up a bunch of log noise from ch7xxx startup.

diff --git a/src/ch7xxx/ch7xxx.c b/src/ch7xxx/ch7xxx.c
index 5213646..59722b8 100644
--- a/src/ch7xxx/ch7xxx.c
+++ b/src/ch7xxx/ch7xxx.c
@@ -93,10 +93,9 @@ ch7xxx_probe(I2CBusPtr b, I2CSlaveAddr a
 {
     /* this will detect the CH7xxx chip on the specified i2c bus */
     struct ch7xxx_priv *dev_priv;
+    CARD8 vendor, device;
     unsigned char ch;
 
-    xf86DrvMsg(b->scrnIndex, X_INFO, "detecting ch7xxx\n");
-
     dev_priv = xcalloc(1, sizeof(struct ch7xxx_priv));
     if (dev_priv == NULL)
 	return NULL;
@@ -110,29 +109,31 @@ ch7xxx_probe(I2CBusPtr b, I2CSlaveAddr a
     dev_priv->d.ByteTimeout = b->ByteTimeout;
     dev_priv->d.DriverPrivate.ptr = dev_priv;
 
-    if (!ch7xxx_read(dev_priv, CH7xxx_REG_VID, &ch))
+    if (!ch7xxx_read(dev_priv, CH7xxx_REG_VID, &vendor))
 	goto out;
 
-    ErrorF("VID is %02X", ch);
-    if (ch!=(CH7xxx_VID & 0xFF)) {
-	xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex, X_ERROR,
-		   "ch7xxx not detected got %d: from %s Slave %d.\n",
-		   ch, dev_priv->d.pI2CBus->BusName, dev_priv->d.SlaveAddr);
+    if (vendor != CH7xxx_VID) {
+	xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex, X_INFO,
+		   "ch7xxx not detected; got 0x%02x from %s slave %d.\n",
+		   vendor, dev_priv->d.pI2CBus->BusName,
+		   dev_priv->d.SlaveAddr);
 	goto out;
     }
 
 
-    if (!ch7xxx_read(dev_priv, CH7xxx_REG_DID, &ch))
+    if (!ch7xxx_read(dev_priv, CH7xxx_REG_DID, &device))
 	goto out;
 
-    ErrorF("DID is %02X", ch);
-    if (ch!=(CH7xxx_DID & 0xFF)) {
-	xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex, X_ERROR,
-		   "ch7xxx not detected got %d: from %s Slave %d.\n",
-		   ch, dev_priv->d.pI2CBus->BusName, dev_priv->d.SlaveAddr);
+    if (device != CH7xxx_DID) {
+	xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex, X_INFO,
+		   "ch7xxx not detected; got 0x%02x from %s slave %d.\n",
+		   device, dev_priv->d.pI2CBus->BusName,
+		   dev_priv->d.SlaveAddr);
 	goto out;
     }
-
+	xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex, X_INFO,
+		   "Detected CH7xxx chipset, vendor/device ID 0x%02x/0x%02x\n",
+		   vendor, device);
 
     if (!xf86I2CDevInit(&dev_priv->d)) {
 	goto out;
@@ -235,9 +236,6 @@ ch7xxx_power(I2CDevPtr d, Bool On)
     if (ret == FALSE)
 	return;
 
-    xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex, X_ERROR,
-	       "ch7xxx pm is %02X\n", ch);
-
 #if 0
     ret = ch7xxx_read(dev_priv, CH7xxx_REG8, &ch);
     if (ret)
diff --git a/src/ch7xxx/ch7xxx_reg.h b/src/ch7xxx/ch7xxx_reg.h
index 891fde8..0a5f188 100644
--- a/src/ch7xxx/ch7xxx_reg.h
+++ b/src/ch7xxx/ch7xxx_reg.h
@@ -29,7 +29,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define CH7xxx_REG_VID 0x4a
 #define CH7xxx_REG_DID 0x4b
 
-#define CH7011_VID 0x83
+#define CH7011_VID 0x83 /* 7010 as well */
 #define CH7009A_VID 0x84
 #define CH7009B_VID 0x85
 #define CH7301_VID 0x95
diff-tree 3167bc6b24bd74c50ca4c4d361b14aa24d77cfa3 (from 4ca92da5b93b07f0bff51843f8fb5d04a2a29443)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Dec 18 13:45:55 2006 -0800

    Fix DVO mode valid function to not throw out all modes.

diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index ed8d1c7..804f0fc 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -107,16 +107,14 @@ static int
 i830_dvo_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
 {
     I830OutputPrivatePtr    intel_output = output->driver_private;
-    
+    void *dev_priv = intel_output->i2c_drv->dev_priv;
+
     if (pMode->Flags & V_DBLSCAN)
 	return MODE_NO_DBLESCAN;
 
     /* XXX: Validate clock range */
 
-    if ((*intel_output->i2c_drv->vid_rec->ModeValid)(intel_output->i2c_drv->dev_priv, pMode))
-	return MODE_OK;
-    else
-	return MODE_BAD;
+    return intel_output->i2c_drv->vid_rec->ModeValid(dev_priv, pMode);
 }
 
 static Bool
diff-tree 4ca92da5b93b07f0bff51843f8fb5d04a2a29443 (from 31849edb3b503ade659981dfa36babf5ad8757c5)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Dec 18 13:45:34 2006 -0800

    Add save/restore to ch7xxx to avoid segfaults on server start.

diff --git a/src/ch7xxx/ch7xxx.c b/src/ch7xxx/ch7xxx.c
index bf70d8e..5213646 100644
--- a/src/ch7xxx/ch7xxx.c
+++ b/src/ch7xxx/ch7xxx.c
@@ -49,6 +49,8 @@ struct ch7xxx_priv {
     I2CDevRec d;
     struct ch7xxx_reg_state SavedReg;
     struct ch7xxx_reg_state ModeReg;
+    CARD8 save_TCTL, save_TPCP, save_TPD, save_TPVT;
+    CARD8 save_TPF, save_TCT, save_PM;
 };
 
 static void ch7xxx_save(I2CDevPtr d);
@@ -270,13 +272,29 @@ ch7xxx_save(I2CDevPtr d)
     int ret;
     int i;
 
-    for (i = 0; i < CH7xxx_NUM_REGS; i++) {
-	ret = ch7xxx_read(dev_priv, i, &dev_priv->SavedReg.regs[i]);
-	if (ret == FALSE)
-	    break;
-    }
+    ch7xxx_read(dev_priv, CH7xxx_PM, &dev_priv->save_PM);
+    ch7xxx_read(dev_priv, CH7xxx_TCTL, &dev_priv->save_TCTL);
+    ch7xxx_read(dev_priv, CH7xxx_TPCP, &dev_priv->save_TPCP);
+    ch7xxx_read(dev_priv, CH7xxx_TPD, &dev_priv->save_TPD);
+    ch7xxx_read(dev_priv, CH7xxx_TPVT, &dev_priv->save_TPVT);
+    ch7xxx_read(dev_priv, CH7xxx_TPF, &dev_priv->save_TPF);
+
+    return;
+}
+
+static void
+ch7xxx_restore(I2CDevPtr d)
+{
+    struct ch7xxx_priv *dev_priv = d->DriverPrivate.ptr;
+    int ret;
+    int i;
 
-    memcpy(dev_priv->ModeReg.regs, dev_priv->SavedReg.regs, CH7xxx_NUM_REGS);
+    ch7xxx_write(dev_priv, CH7xxx_TCTL, dev_priv->save_TCTL);
+    ch7xxx_write(dev_priv, CH7xxx_TPCP, dev_priv->save_TPCP);
+    ch7xxx_write(dev_priv, CH7xxx_TPD, dev_priv->save_TPD);
+    ch7xxx_write(dev_priv, CH7xxx_TPVT, dev_priv->save_TPVT);
+    ch7xxx_write(dev_priv, CH7xxx_TPF, dev_priv->save_TPF);
+    ch7xxx_write(dev_priv, CH7xxx_PM, dev_priv->save_PM);
 
     return;
 }
@@ -289,5 +307,5 @@ I830I2CVidOutputRec CH7xxxVidOutput = {
     ch7xxx_power,
     ch7xxx_dump_regs,
     ch7xxx_save,
-    NULL,
+    ch7xxx_restore,
 };
diff-tree 31849edb3b503ade659981dfa36babf5ad8757c5 (from 2d0ca2202cb0d780bb4387bbe04e5caa6512e3b1)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Dec 18 13:32:21 2006 -0800

    Move the ch7xxx code to the style I've been settling on for output code.

diff --git a/src/ch7xxx/ch7xxx.c b/src/ch7xxx/ch7xxx.c
index df66d03..bf70d8e 100644
--- a/src/ch7xxx/ch7xxx.c
+++ b/src/ch7xxx/ch7xxx.c
@@ -41,113 +41,126 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * driver for the Chrontel 7xxx DVI chip over DVO.
  */
 
-static void ch7xxxSaveRegs(I2CDevPtr d);
+struct ch7xxx_reg_state {
+    CARD8 regs[CH7xxx_NUM_REGS];
+};
+
+struct ch7xxx_priv {
+    I2CDevRec d;
+    struct ch7xxx_reg_state SavedReg;
+    struct ch7xxx_reg_state ModeReg;
+};
+
+static void ch7xxx_save(I2CDevPtr d);
 
 static CARD8 ch7xxxFreqRegs[][7] =
   { { 0, 0x23, 0x08, 0x16, 0x30, 0x60, 0x00 },
     { 0, 0x23, 0x04, 0x26, 0x30, 0x60, 0x00 },
     { 0, 0x2D, 0x07, 0x26, 0x30, 0xE0, 0x00 } };
 
-
-static Bool ch7xxxReadByte(CH7xxxPtr ch7xxx, int addr, unsigned char *ch)
+/** Reads an 8 bit register */
+static Bool
+ch7xxx_read(struct ch7xxx_priv *dev_priv, int addr, unsigned char *ch)
 {
-    if (!xf86I2CReadByte(&(ch7xxx->d), addr, ch)) {
-	xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex,
+    if (!xf86I2CReadByte(&dev_priv->d, addr, ch)) {
+	xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex,
 		   X_ERROR, "Unable to read from %s Slave %d.\n",
-		   ch7xxx->d.pI2CBus->BusName, ch7xxx->d.SlaveAddr);
+		   dev_priv->d.pI2CBus->BusName, dev_priv->d.SlaveAddr);
 	return FALSE;
     }
 
     return TRUE;
 }
 
-static Bool ch7xxxWriteByte(CH7xxxPtr ch7xxx, int addr, unsigned char ch)
+/** Writes an 8 bit register */
+static Bool
+ch7xxx_write(struct ch7xxx_priv *dev_priv, int addr, unsigned char ch)
 {
-    if (!xf86I2CWriteByte(&(ch7xxx->d), addr, ch)) {
-	xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR,
+    if (!xf86I2CWriteByte(&dev_priv->d, addr, ch)) {
+	xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex, X_ERROR,
 		   "Unable to write to %s Slave %d.\n",
-		   ch7xxx->d.pI2CBus->BusName, ch7xxx->d.SlaveAddr);
+		   dev_priv->d.pI2CBus->BusName, dev_priv->d.SlaveAddr);
 	return FALSE;
     }
 
     return TRUE;
 }
 
-static void *ch7xxxDetect(I2CBusPtr b, I2CSlaveAddr addr)
+static void *
+ch7xxx_probe(I2CBusPtr b, I2CSlaveAddr addr)
 {
     /* this will detect the CH7xxx chip on the specified i2c bus */
-    CH7xxxPtr ch7xxx;
+    struct ch7xxx_priv *dev_priv;
     unsigned char ch;
 
-    xf86DrvMsg(b->scrnIndex, X_ERROR, "detecting ch7xxx\n");
+    xf86DrvMsg(b->scrnIndex, X_INFO, "detecting ch7xxx\n");
 
-    ch7xxx = xcalloc(1, sizeof(CH7xxxRec));
-    if (ch7xxx == NULL)
+    dev_priv = xcalloc(1, sizeof(struct ch7xxx_priv));
+    if (dev_priv == NULL)
 	return NULL;
 
-    ch7xxx->d.DevName = "CH7xxx TMDS Controller";
-    ch7xxx->d.SlaveAddr = addr;
-    ch7xxx->d.pI2CBus = b;
-    ch7xxx->d.StartTimeout = b->StartTimeout;
-    ch7xxx->d.BitTimeout = b->BitTimeout;
-    ch7xxx->d.AcknTimeout = b->AcknTimeout;
-    ch7xxx->d.ByteTimeout = b->ByteTimeout;
-    ch7xxx->d.DriverPrivate.ptr = ch7xxx;
+    dev_priv->d.DevName = "CH7xxx TMDS Controller";
+    dev_priv->d.SlaveAddr = addr;
+    dev_priv->d.pI2CBus = b;
+    dev_priv->d.StartTimeout = b->StartTimeout;
+    dev_priv->d.BitTimeout = b->BitTimeout;
+    dev_priv->d.AcknTimeout = b->AcknTimeout;
+    dev_priv->d.ByteTimeout = b->ByteTimeout;
+    dev_priv->d.DriverPrivate.ptr = dev_priv;
 
-    if (!ch7xxxReadByte(ch7xxx, CH7xxx_REG_VID, &ch))
+    if (!ch7xxx_read(dev_priv, CH7xxx_REG_VID, &ch))
 	goto out;
 
     ErrorF("VID is %02X", ch);
     if (ch!=(CH7xxx_VID & 0xFF)) {
-	xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR,
+	xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex, X_ERROR,
 		   "ch7xxx not detected got %d: from %s Slave %d.\n",
-		   ch, ch7xxx->d.pI2CBus->BusName, ch7xxx->d.SlaveAddr);
+		   ch, dev_priv->d.pI2CBus->BusName, dev_priv->d.SlaveAddr);
 	goto out;
     }
 
 
-    if (!ch7xxxReadByte(ch7xxx, CH7xxx_REG_DID, &ch))
+    if (!ch7xxx_read(dev_priv, CH7xxx_REG_DID, &ch))
 	goto out;
 
     ErrorF("DID is %02X", ch);
     if (ch!=(CH7xxx_DID & 0xFF)) {
-	xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR,
+	xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex, X_ERROR,
 		   "ch7xxx not detected got %d: from %s Slave %d.\n",
-		   ch, ch7xxx->d.pI2CBus->BusName, ch7xxx->d.SlaveAddr);
+		   ch, dev_priv->d.pI2CBus->BusName, dev_priv->d.SlaveAddr);
 	goto out;
     }
 
 
-    if (!xf86I2CDevInit(&(ch7xxx->d))) {
+    if (!xf86I2CDevInit(&dev_priv->d)) {
 	goto out;
     }
 
-    return ch7xxx;
+    return dev_priv;
 
 out:
-    xfree(ch7xxx);
+    xfree(dev_priv);
     return NULL;
 }
 
 
-static Bool ch7xxxInit(I2CDevPtr d)
+static Bool
+ch7xxx_init(I2CDevPtr d)
 {
-    CH7xxxPtr ch7xxx = CH7PTR(d);
-
     /* not much to do */
     return TRUE;
 }
 
-static ModeStatus ch7xxxModeValid(I2CDevPtr d, DisplayModePtr mode)
+static ModeStatus
+ch7xxx_mode_valid(I2CDevPtr d, DisplayModePtr mode)
 {
-    CH7xxxPtr ch7xxx = CH7PTR(d);
-
     return MODE_OK;
 }
 
-static void ch7xxxMode(I2CDevPtr d, DisplayModePtr mode)
+static void
+ch7xxx_mode_set(I2CDevPtr d, DisplayModePtr mode)
 {
-    CH7xxxPtr ch7xxx = CH7PTR(d);
+    struct ch7xxx_priv *dev_priv = d->DriverPrivate.ptr;
     int ret;
     unsigned char pm, idf;
     unsigned char tpcp, tpd, tpf, cm;
@@ -164,16 +177,16 @@ static void ch7xxxMode(I2CDevPtr d, Disp
 	freq_regs = ch7xxxFreqRegs[2];
 
     for (i = 0x31; i < 0x37; i++) {
-	ch7xxx->ModeReg.regs[i] = freq_regs[i - 0x31];
-	ch7xxxWriteByte(ch7xxx, i, ch7xxx->ModeReg.regs[i]);
+	dev_priv->ModeReg.regs[i] = freq_regs[i - 0x31];
+	ch7xxx_write(dev_priv, i, dev_priv->ModeReg.regs[i]);
     }
 
 #if 0
-    xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR,
+    xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex, X_ERROR,
 	       "ch7xxx idf is 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
 	       idf, tpcp, tpd, tpf);
 
-    xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR,
+    xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex, X_ERROR,
 	       "ch7xxx pm is %02X\n", pm);
 
     if (mode->Clock < 65000) {
@@ -199,31 +212,32 @@ static void ch7xxxMode(I2CDevPtr d, Disp
 
     /* cm |= 1; */
 
-    ch7xxxWriteByte(ch7xxx, CH7xxx_CM, cm);
-    ch7xxxWriteByte(ch7xxx, CH7xxx_TPCP, tpcp);
-    ch7xxxWriteByte(ch7xxx, CH7xxx_TPD, tpd);
-    ch7xxxWriteByte(ch7xxx, CH7xxx_TPF, tpf);
-    ch7xxxWriteByte(ch7xxx, CH7xxx_TPF, idf);
-    ch7xxxWriteByte(ch7xxx, CH7xxx_PM, pm);
+    ch7xxx_write(dev_priv, CH7xxx_CM, cm);
+    ch7xxx_write(dev_priv, CH7xxx_TPCP, tpcp);
+    ch7xxx_write(dev_priv, CH7xxx_TPD, tpd);
+    ch7xxx_write(dev_priv, CH7xxx_TPF, tpf);
+    ch7xxx_write(dev_priv, CH7xxx_TPF, idf);
+    ch7xxx_write(dev_priv, CH7xxx_PM, pm);
 #endif
 }
 
 /* set the CH7xxx power state */
-static void ch7xxxPower(I2CDevPtr d, Bool On)
+static void
+ch7xxx_power(I2CDevPtr d, Bool On)
 {
-    CH7xxxPtr ch7xxx = CH7PTR(d);
+    struct ch7xxx_priv *dev_priv = d->DriverPrivate.ptr;
     int ret;
     unsigned char ch;
 
-    ret = ch7xxxReadByte(ch7xxx, CH7xxx_PM, &ch);
+    ret = ch7xxx_read(dev_priv, CH7xxx_PM, &ch);
     if (ret == FALSE)
 	return;
 
-    xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR,
+    xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex, X_ERROR,
 	       "ch7xxx pm is %02X\n", ch);
 
 #if 0
-    ret = ch7xxxReadByte(ch7xxx, CH7xxx_REG8, &ch);
+    ret = ch7xxx_read(dev_priv, CH7xxx_REG8, &ch);
     if (ret)
 	return;
 
@@ -232,48 +246,48 @@ static void ch7xxxPower(I2CDevPtr d, Boo
     else
 	ch &= ~CH7xxx_8_PD;
 
-    ch7xxxWriteByte(ch7xxx, CH7xxx_REG8, ch);
+    ch7xxx_write(dev_priv, CH7xxx_REG8, ch);
 #endif
 }
 
-static void ch7xxxPrintRegs(I2CDevPtr d)
+static void
+ch7xxx_dump_regs(I2CDevPtr d)
 {
-    CH7xxxPtr ch7xxx = CH7PTR(d);
+    struct ch7xxx_priv *dev_priv = d->DriverPrivate.ptr;
     int i;
 
-    ch7xxxSaveRegs(d);
-
     for (i = 0; i < CH7xxx_NUM_REGS; i++) {
 	if (( i % 8 ) == 0 )
 	    ErrorF("\n %02X: ", i);
-	ErrorF("%02X ", ch7xxx->ModeReg.regs[i]);
+	ErrorF("%02X ", dev_priv->ModeReg.regs[i]);
     }
 }
 
-static void ch7xxxSaveRegs(I2CDevPtr d)
+static void
+ch7xxx_save(I2CDevPtr d)
 {
-    CH7xxxPtr ch7xxx = CH7PTR(d);
+    struct ch7xxx_priv *dev_priv = d->DriverPrivate.ptr;
     int ret;
     int i;
 
     for (i = 0; i < CH7xxx_NUM_REGS; i++) {
-	ret = ch7xxxReadByte(ch7xxx, i, &ch7xxx->SavedReg.regs[i]);
+	ret = ch7xxx_read(dev_priv, i, &dev_priv->SavedReg.regs[i]);
 	if (ret == FALSE)
 	    break;
     }
 
-    memcpy(ch7xxx->ModeReg.regs, ch7xxx->SavedReg.regs, CH7xxx_NUM_REGS);
+    memcpy(dev_priv->ModeReg.regs, dev_priv->SavedReg.regs, CH7xxx_NUM_REGS);
 
     return;
 }
 
 I830I2CVidOutputRec CH7xxxVidOutput = {
-    ch7xxxDetect,
-    ch7xxxInit,
-    ch7xxxModeValid,
-    ch7xxxMode,
-    ch7xxxPower,
-    ch7xxxPrintRegs,
-    ch7xxxSaveRegs,
+    ch7xxx_probe,
+    ch7xxx_init,
+    ch7xxx_mode_valid,
+    ch7xxx_mode_set,
+    ch7xxx_power,
+    ch7xxx_dump_regs,
+    ch7xxx_save,
     NULL,
 };
diff --git a/src/ch7xxx/ch7xxx_reg.h b/src/ch7xxx/ch7xxx_reg.h
index e24e9a6..891fde8 100644
--- a/src/ch7xxx/ch7xxx_reg.h
+++ b/src/ch7xxx/ch7xxx_reg.h
@@ -39,18 +39,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #define CH7xxx_NUM_REGS 0x4c
 
-typedef struct _CH7xxxSaveRec {
-    CARD8 regs[CH7xxx_NUM_REGS];
-} CH7xxxSaveRec;
-
-typedef struct {
-    I2CDevRec d;
-    CH7xxxSaveRec SavedReg;
-    CH7xxxSaveRec ModeReg;
-} CH7xxxRec, *CH7xxxPtr;
-
-#define CH7PTR(d) ((CH7xxxPtr)(d->DriverPrivate.ptr))
-
 #define CH7xxx_CM 0x1C
 #define CH7xxx_CM_XCM (1<<0)
 #define CH7xxx_CM_MCP (1<<2)
diff-tree 2d0ca2202cb0d780bb4387bbe04e5caa6512e3b1 (from 6823ca87f3b1ef3b28ed167254dcfce2a80467df)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Dec 18 10:37:33 2006 -0800

    Bug #8786: Treat pictures with no color data as non-component alpha.
    
    This is an un(der?)-documented part of the render protocol: If the mask is
    alpha only, then the component alpha flag is ignored on it.

diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
index daffa0c..cefa15c 100644
--- a/src/i915_exa_render.c
+++ b/src/i915_exa_render.c
@@ -142,7 +142,9 @@ static CARD32 I915GetBlendCntl(int op, P
      * the source blend factor is 0, and the source blend value is the mask
      * channels multiplied by the source picture's alpha.
      */
-    if (pMask && pMask->componentAlpha && I915BlendOp[op].src_alpha) {
+    if (pMask && pMask->componentAlpha && PICT_FORMAT_RGB(pMask->format) &&
+	I915BlendOp[op].src_alpha)
+    {
         if (dblend == BLENDFACT_SRC_ALPHA) {
 	    dblend = BLENDFACT_SRC_COLR;
         } else if (dblend == BLENDFACT_INV_SRC_ALPHA) {
@@ -228,7 +230,9 @@ I915EXACheckComposite(int op, PicturePtr
     /* Check for unsupported compositing operations. */
     if (op >= sizeof(I915BlendOp) / sizeof(I915BlendOp[0]))
         I830FALLBACK("Unsupported Composite op 0x%x\n", op);
-    if (pMaskPicture != NULL && pMaskPicture->componentAlpha) {
+    if (pMaskPicture != NULL && pMaskPicture->componentAlpha &&
+	PICT_FORMAT_RGB(pMaskPicture->format))
+    {
         /* Check if it's component alpha that relies on a source alpha and on
          * the source value.  We can only get one of those into the single
          * source value that we get to blend with.
@@ -463,7 +467,7 @@ I915EXAPrepareComposite(int op, PictureP
 	if (PICT_FORMAT_A(pMaskPicture->format) == 0)
 	    i915_fs_mov_masked(FS_R1, MASK_W, i915_fs_operand_one());
 
-	/* If component alpha is set in the mask and the blend operation
+	/* If component alpha is active in the mask and the blend operation
 	 * uses the source alpha, then we know we don't need the source
 	 * value (otherwise we would have hit a fallback earlier), so we
 	 * provide the source alpha (src.A * mask.X) as output color.
@@ -472,7 +476,9 @@ I915EXAPrepareComposite(int op, PictureP
 	 * is unused..  Otherwise, we provide the non-CA source value
 	 * (src.X * mask.A).
 	 */
-	if (pMaskPicture->componentAlpha) {
+	if (pMaskPicture->componentAlpha &&
+	    PICT_FORMAT_RGB(pMaskPicture->format))
+	{
 	    if (I915BlendOp[op].src_alpha) {
 		i915_fs_mul(FS_OC, i915_fs_operand(FS_R0, W, W, W, W),
 			    i915_fs_operand_reg(FS_R1));
diff-tree 6823ca87f3b1ef3b28ed167254dcfce2a80467df (from 86558cc622b516b568cc26efdf9b64d4b660f50f)
Author: Keith Packard <keithp at mandolin.keithp.com>
Date:   Sat Dec 16 21:12:47 2006 -0800

    Follow mode setting order in RestoreHWState.
    
    Add delays after output and CRTC disable. Restore panel fit register before
    PLLs are restarted. Move all VGA restore code last. Shuffle various register
    writes around and add delays to match PipeSetMode code.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 998b36f..7da4bf5 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2210,18 +2210,22 @@ RestoreHWState(ScrnInfoPtr pScrn)
 #ifdef XF86DRI
    I830DRISetVBlankInterrupt (pScrn, FALSE);
 #endif
-
    /* Disable outputs */
    for (i = 0; i < xf86_config->num_output; i++) {
       xf86OutputPtr   output = xf86_config->output[i];
       output->funcs->dpms(output, DPMSModeOff);
    }
-
+   i830WaitForVblank(pScrn);
+   
    /* Disable pipes */
    for (i = 0; i < xf86_config->num_crtc; i++) {
       xf86CrtcPtr crtc = xf86_config->crtc[i];
       crtc->funcs->dpms(crtc, DPMSModeOff);
    }
+   i830WaitForVblank(pScrn);
+
+   if (!IS_I830(pI830) && !IS_845G(pI830))
+     OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL);
 
    if (pI830->saveDPLL_A & DPLL_VCO_ENABLE)
    {
@@ -2248,32 +2252,31 @@ RestoreHWState(ScrnInfoPtr pScrn)
    OUTREG(DSPASTRIDE, pI830->saveDSPASTRIDE);
    OUTREG(DSPASIZE, pI830->saveDSPASIZE);
    OUTREG(DSPAPOS, pI830->saveDSPAPOS);
-   OUTREG(DSPACNTR, pI830->saveDSPACNTR);
+   OUTREG(PIPEASRC, pI830->savePIPEASRC);
    OUTREG(DSPABASE, pI830->saveDSPABASE);
-   if (IS_I965G(pI830)) {
+   if (IS_I965G(pI830))
       OUTREG(DSPASURF, pI830->saveDSPASURF);
-   }
-   
-   OUTREG(PIPEASRC, pI830->savePIPEASRC);
    OUTREG(PIPEACONF, pI830->savePIPEACONF);
+   i830WaitForVblank(pScrn);
+   OUTREG(DSPACNTR, pI830->saveDSPACNTR);
+   OUTREG(DSPABASE, INREG(DSPABASE));
+   i830WaitForVblank(pScrn);
    
-   for(i = 0; i < 256; i++) {
-         OUTREG(PALETTE_A + (i << 2), pI830->savePaletteA[i]);
-   }
-
-   if(xf86_config->num_crtc == 2) {
-      OUTREG(FPB0, pI830->saveFPB0);
-      OUTREG(FPB1, pI830->saveFPB1);
-      if (IS_I965G(pI830))
-	 OUTREG(DPLL_B_MD, pI830->saveDPLL_B_MD);
+   if(xf86_config->num_crtc == 2) 
+   {
       if (pI830->saveDPLL_B & DPLL_VCO_ENABLE)
       {
 	 OUTREG(DPLL_B, pI830->saveDPLL_B & ~DPLL_VCO_ENABLE);
 	 usleep(150);
       }
+      OUTREG(FPB0, pI830->saveFPB0);
+      OUTREG(FPB1, pI830->saveFPB1);
       OUTREG(DPLL_B, pI830->saveDPLL_B);
       usleep(150);
-      OUTREG(DPLL_B, pI830->saveDPLL_B);
+      if (IS_I965G(pI830))
+	 OUTREG(DPLL_B_MD, pI830->saveDPLL_B_MD);
+      else
+	 OUTREG(DPLL_B, pI830->saveDPLL_B);
       usleep(150);
    
       OUTREG(HTOTAL_B, pI830->saveHTOTAL_B);
@@ -2286,43 +2289,48 @@ RestoreHWState(ScrnInfoPtr pScrn)
       OUTREG(DSPBSIZE, pI830->saveDSPBSIZE);
       OUTREG(DSPBPOS, pI830->saveDSPBPOS);
       OUTREG(PIPEBSRC, pI830->savePIPEBSRC);
-      OUTREG(PIPEBCONF, pI830->savePIPEBCONF);
-      OUTREG(DSPBCNTR, pI830->saveDSPBCNTR);
       OUTREG(DSPBBASE, pI830->saveDSPBBASE);
-      if (IS_I965G(pI830)) {
+      if (IS_I965G(pI830))
 	 OUTREG(DSPBSURF, pI830->saveDSPBSURF);
-      }
-      for(i= 0; i < 256; i++) {
-         OUTREG(PALETTE_B + (i << 2), pI830->savePaletteB[i]);
-      }
+      OUTREG(PIPEBCONF, pI830->savePIPEBCONF);
+      i830WaitForVblank(pScrn);
+      OUTREG(DSPBCNTR, pI830->saveDSPBCNTR);
+      OUTREG(DSPBBASE, INREG(DSPBBASE));
+      i830WaitForVblank(pScrn);
    }
 
-   if (!IS_I830(pI830) && !IS_845G(pI830))
-     OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL);
-
+   /* Restore outputs */
+   for (i = 0; i < xf86_config->num_output; i++) {
+      xf86OutputPtr   output = xf86_config->output[i];
+      if (output->funcs->restore)
+	 output->funcs->restore(output);
+   }
+    
    OUTREG(VGACNTRL, pI830->saveVGACNTRL);
 
    OUTREG(VCLK_DIVISOR_VGA0, pI830->saveVCLK_DIVISOR_VGA0);
    OUTREG(VCLK_DIVISOR_VGA1, pI830->saveVCLK_DIVISOR_VGA1);
    OUTREG(VCLK_POST_DIV, pI830->saveVCLK_POST_DIV);
 
-   for (i = 0; i < xf86_config->num_output; i++) {
-      xf86OutputPtr   output = xf86_config->output[i];
-      (*output->funcs->restore) (output);
+   for(i = 0; i < 256; i++) {
+      OUTREG(PALETTE_A + (i << 2), pI830->savePaletteA[i]);
+   }
+   
+   if(xf86_config->num_crtc == 2) {
+      for(i= 0; i < 256; i++) {
+         OUTREG(PALETTE_B + (i << 2), pI830->savePaletteB[i]);
+      }
    }
 
    for(i = 0; i < 7; i++) {
-	   OUTREG(SWF0 + (i << 2), pI830->saveSWF[i]);
-	   OUTREG(SWF00 + (i << 2), pI830->saveSWF[i+7]);
+      OUTREG(SWF0 + (i << 2), pI830->saveSWF[i]);
+      OUTREG(SWF00 + (i << 2), pI830->saveSWF[i+7]);
    }
 
    OUTREG(SWF30, pI830->saveSWF[14]);
    OUTREG(SWF31, pI830->saveSWF[15]);
    OUTREG(SWF32, pI830->saveSWF[16]);
 
-   for (i = 0; i < 2; i++)
-      i830WaitForVblank(pScrn);
-
    vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS);
    vgaHWLock(hwp);
 
diff-tree 86558cc622b516b568cc26efdf9b64d4b660f50f (from 8e6ab99b3195325f9fe5432725fe328591c0c7e2)
Author: Keith Packard <keithp at mandolin.keithp.com>
Date:   Sat Dec 16 21:09:31 2006 -0800

    Prefer earliest CRTC when mapping to outputs.
    
    For some reason, the code was preferring the last possible output when
    mapping outputs to crtcs. Use the earlier CRTC instead to make the i830
    driver consistent with BIOS usage.

diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index 76d6d03..51e6f1c 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -359,7 +359,7 @@ xf86PickCrtcs (ScrnInfoPtr	pScrn,
 	crtcs[n] = crtc;
 	memcpy (crtcs, best_crtcs, n * sizeof (xf86CrtcPtr));
 	score = my_score + xf86PickCrtcs (pScrn, crtcs, modes, n+1, width, height);
-	if (score >= best_score)
+	if (score > best_score)
 	{
 	    best_crtc = crtc;
 	    best_score = score;
diff-tree 8e6ab99b3195325f9fe5432725fe328591c0c7e2 (from bffd611b0a1cb05868e0f93e6ff9357a3116eaa6)
Author: Keith Packard <keithp at mandolin.keithp.com>
Date:   Sat Dec 16 21:06:36 2006 -0800

    Not restoring active outputs. Wait for input sync before enabling outputs.
    
    Oops--looks like a typo to me; the code was callint set_target_output
    instead of set_active_outputs.
    
    BIOS loops waiting for the SDVO input to sync before enabling outputs, this
    makes sense to me.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index d19b8b0..cb68802 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -693,18 +693,16 @@ i830_sdvo_dpms(xf86OutputPtr output, int
 
 	temp = INREG(dev_priv->output_device);
 	if ((temp & SDVO_ENABLE) == 0)
+	{
 	    OUTREG(dev_priv->output_device, temp | SDVO_ENABLE);
-
-	i830_sdvo_set_active_outputs(output, dev_priv->active_outputs);
-
 #if 0
-	/* Do it again!  If we remove this below register write, or the exact
-	 * same one 2 lines up, the mac mini SDVO output doesn't turn on.
-	 */
-	OUTREG(dev_priv->output_device,
-	       INREG(dev_priv->output_device) | SDVO_ENABLE);
+	    /* Do it again!  If we remove this below register write, or the exact
+	     * same one 2 lines up, the mac mini SDVO output doesn't turn on.
+	     */
+	    OUTREG(dev_priv->output_device,
+		   INREG(dev_priv->output_device) | SDVO_ENABLE);
 #endif
-
+	}
 	for (i = 0; i < 2; i++)
 	    i830WaitForVblank(pScrn);
 
@@ -716,6 +714,8 @@ i830_sdvo_dpms(xf86OutputPtr output, int
 		       "First %s output reported failure to sync\n",
 		       SDVO_NAME(dev_priv));
 	}
+
+	i830_sdvo_set_active_outputs(output, dev_priv->active_outputs);
     }
 }
 
@@ -764,16 +764,11 @@ i830_sdvo_restore(xf86OutputPtr output)
     struct i830_sdvo_priv   *dev_priv = intel_output->dev_priv;
     I830Ptr		    pI830 = I830PTR(pScrn);
     int			    o;
+    int			    i;
+    Bool		    input1, input2;
+    CARD8		    status;
 
-    if (dev_priv->caps.sdvo_inputs_mask & 0x1) {
-       i830_sdvo_set_target_input(output, TRUE, FALSE);
-       i830_sdvo_set_input_timing(output, &dev_priv->save_input_dtd_1);
-    }
-
-    if (dev_priv->caps.sdvo_inputs_mask & 0x2) {
-       i830_sdvo_set_target_input(output, FALSE, TRUE);
-       i830_sdvo_set_input_timing(output, &dev_priv->save_input_dtd_2);
-    }
+    i830_sdvo_set_active_outputs(output, 0);
 
     for (o = SDVO_OUTPUT_FIRST; o <= SDVO_OUTPUT_LAST; o++)
     {
@@ -784,11 +779,33 @@ i830_sdvo_restore(xf86OutputPtr output)
 	    i830_sdvo_set_output_timing(output, &dev_priv->save_output_dtd[o]);
 	}
     }
-    i830_sdvo_set_target_output(output, dev_priv->save_active_outputs);
+
+    if (dev_priv->caps.sdvo_inputs_mask & 0x1) {
+       i830_sdvo_set_target_input(output, TRUE, FALSE);
+       i830_sdvo_set_input_timing(output, &dev_priv->save_input_dtd_1);
+    }
+
+    if (dev_priv->caps.sdvo_inputs_mask & 0x2) {
+       i830_sdvo_set_target_input(output, FALSE, TRUE);
+       i830_sdvo_set_input_timing(output, &dev_priv->save_input_dtd_2);
+    }
 
     i830_sdvo_set_clock_rate_mult(output, dev_priv->save_sdvo_mult);
 
     OUTREG(dev_priv->output_device, dev_priv->save_SDVOX);
+
+    if (dev_priv->save_SDVOX & SDVO_ENABLE)
+    {
+	for (i = 0; i < 2; i++)
+	    i830WaitForVblank(pScrn);
+	status = i830_sdvo_get_trained_inputs(output, &input1, &input2);
+	if (status == SDVO_CMD_STATUS_SUCCESS && !input1)
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "First %s output reported failure to sync\n",
+		       SDVO_NAME(dev_priv));
+    }
+    
+    i830_sdvo_set_active_outputs(output, dev_priv->save_active_outputs);
 }
 
 static int
diff-tree bffd611b0a1cb05868e0f93e6ff9357a3116eaa6 (from 9b1a1b170befae2e705c23ce295837d0d13b60c0)
Author: Keith Packard <keithp at mandolin.keithp.com>
Date:   Sat Dec 16 21:03:15 2006 -0800

    Follow BIOS order in writing DPLL/DPLL_MD registers.
    
    965 BIOS writes DPLL and then DPLL_MD.
    945 BIOS writes DPLL twice.

diff --git a/src/i830_display.c b/src/i830_display.c
index 6971e28..f87aadc 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -787,12 +787,6 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
     i830PrintPll("chosen", &clock);
     ErrorF("clock regs: 0x%08x, 0x%08x\n", (int)dpll, (int)fp);
 
-    if (IS_I965G(pI830)) {
-	int sdvo_pixel_multiply = adjusted_mode->Clock / mode->Clock;
-	OUTREG(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) |
-	       ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT));
-    }
-
     if (dpll & DPLL_VCO_ENABLE)
     {
 	OUTREG(fp_reg, fp);
@@ -804,21 +798,17 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
     /* Wait for the clocks to stabilize. */
     usleep(150);
     
-    /* write it again -- the BIOS does, after all */
-    OUTREG(dpll_reg, dpll);
+    if (IS_I965G(pI830)) {
+	int sdvo_pixel_multiply = adjusted_mode->Clock / mode->Clock;
+	OUTREG(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) |
+	       ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT));
+    } else {
+       /* write it again -- the BIOS does, after all */
+       OUTREG(dpll_reg, dpll);
+    }
     /* Wait for the clocks to stabilize. */
     usleep(150);
 
-#if 0
-    /* Magic re-write of the register for the Mac Mini.  Without this, the
-     * first X invocation after a cold boot will stick in 4x pixel multiply
-     * mode.  Alternatives that don't work include sleeping and doing an
-     * INREG for presumable pci write posting magic before and after the dpll
-     * write above.
-     */
-    OUTREG(dpll_reg, dpll);
-#endif
-
     OUTREG(htot_reg, (adjusted_mode->CrtcHDisplay - 1) |
 	((adjusted_mode->CrtcHTotal - 1) << 16));
     OUTREG(hblank_reg, (adjusted_mode->CrtcHBlankStart - 1) |
diff-tree 9b1a1b170befae2e705c23ce295837d0d13b60c0 (from 60411bc4d0b3c53850c73b7246d5f7ed5c2d4084)
Author: Keith Packard <keithp at mandolin.keithp.com>
Date:   Sat Dec 16 16:53:49 2006 -0800

    reorder restore writes for 965 VGA

diff --git a/src/i830_display.c b/src/i830_display.c
index f7f250d..6971e28 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -765,9 +765,11 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
 	else
 	    pipeconf &= ~PIPEACONF_DOUBLE_WIDE;
     }
+#if 1
     dspcntr |= DISPLAY_PLANE_ENABLE;
     pipeconf |= PIPEACONF_ENABLE;
     dpll |= DPLL_VCO_ENABLE;
+#endif
 
     if (is_lvds)
     {
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 373bc21..998b36f 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2223,18 +2223,19 @@ RestoreHWState(ScrnInfoPtr pScrn)
       crtc->funcs->dpms(crtc, DPMSModeOff);
    }
 
-   OUTREG(FPA0, pI830->saveFPA0);
-   OUTREG(FPA1, pI830->saveFPA1);
-   if (IS_I965G(pI830))
-      OUTREG(DPLL_A_MD, pI830->saveDPLL_A_MD);
    if (pI830->saveDPLL_A & DPLL_VCO_ENABLE)
    {
       OUTREG(DPLL_A, pI830->saveDPLL_A & ~DPLL_VCO_ENABLE);
       usleep(150);
    }
+   OUTREG(FPA0, pI830->saveFPA0);
+   OUTREG(FPA1, pI830->saveFPA1);
    OUTREG(DPLL_A, pI830->saveDPLL_A);
    usleep(150);
-   OUTREG(DPLL_A, pI830->saveDPLL_A);
+   if (IS_I965G(pI830))
+      OUTREG(DPLL_A_MD, pI830->saveDPLL_A_MD);
+   else
+      OUTREG(DPLL_A, pI830->saveDPLL_A);
    usleep(150);
 
    OUTREG(HTOTAL_A, pI830->saveHTOTAL_A);
@@ -2243,16 +2244,19 @@ RestoreHWState(ScrnInfoPtr pScrn)
    OUTREG(VTOTAL_A, pI830->saveVTOTAL_A);
    OUTREG(VBLANK_A, pI830->saveVBLANK_A);
    OUTREG(VSYNC_A, pI830->saveVSYNC_A);
+   
    OUTREG(DSPASTRIDE, pI830->saveDSPASTRIDE);
    OUTREG(DSPASIZE, pI830->saveDSPASIZE);
    OUTREG(DSPAPOS, pI830->saveDSPAPOS);
-   OUTREG(PIPEACONF, pI830->savePIPEACONF);
-   OUTREG(PIPEASRC, pI830->savePIPEASRC);
    OUTREG(DSPACNTR, pI830->saveDSPACNTR);
    OUTREG(DSPABASE, pI830->saveDSPABASE);
    if (IS_I965G(pI830)) {
       OUTREG(DSPASURF, pI830->saveDSPASURF);
    }
+   
+   OUTREG(PIPEASRC, pI830->savePIPEASRC);
+   OUTREG(PIPEACONF, pI830->savePIPEACONF);
+   
    for(i = 0; i < 256; i++) {
          OUTREG(PALETTE_A + (i << 2), pI830->savePaletteA[i]);
    }
@@ -2296,6 +2300,8 @@ RestoreHWState(ScrnInfoPtr pScrn)
    if (!IS_I830(pI830) && !IS_845G(pI830))
      OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL);
 
+   OUTREG(VGACNTRL, pI830->saveVGACNTRL);
+
    OUTREG(VCLK_DIVISOR_VGA0, pI830->saveVCLK_DIVISOR_VGA0);
    OUTREG(VCLK_DIVISOR_VGA1, pI830->saveVCLK_DIVISOR_VGA1);
    OUTREG(VCLK_POST_DIV, pI830->saveVCLK_POST_DIV);
@@ -2305,8 +2311,6 @@ RestoreHWState(ScrnInfoPtr pScrn)
       (*output->funcs->restore) (output);
    }
 
-   OUTREG(VGACNTRL, pI830->saveVGACNTRL);
-
    for(i = 0; i < 7; i++) {
 	   OUTREG(SWF0 + (i << 2), pI830->saveSWF[i]);
 	   OUTREG(SWF00 + (i << 2), pI830->saveSWF[i+7]);
diff-tree 60411bc4d0b3c53850c73b7246d5f7ed5c2d4084 (from 082519f34b468d0c5aa08db74ff2b51cf411d743)
Author: Keith Packard <keithp at bouzouki.jf.intel.com>
Date:   Thu Dec 14 18:36:44 2006 -0800

    Follow BIOS PLL write protocol (disable,enable,enable).
    
    This gets VGA output and text restore working, but SDVO is still not working.

diff --git a/src/i830_display.c b/src/i830_display.c
index 897a4ee..f7f250d 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -507,10 +507,17 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mod
 	/* Enable the DPLL */
 	temp = INREG(dpll_reg);
 	if ((temp & DPLL_VCO_ENABLE) == 0)
+	{
+	    OUTREG(dpll_reg, temp);
+	    /* Wait for the clocks to stabilize. */
+	    usleep(150);
 	    OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE);
-
-	/* Wait for the clocks to stabilize. */
-	usleep(150);
+	    /* Wait for the clocks to stabilize. */
+	    usleep(150);
+	    OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE);
+	    /* Wait for the clocks to stabilize. */
+	    usleep(150);
+	}
 
 	/* Enable the pipe */
 	temp = INREG(pipeconf_reg);
@@ -794,6 +801,11 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
     OUTREG(dpll_reg, dpll);
     /* Wait for the clocks to stabilize. */
     usleep(150);
+    
+    /* write it again -- the BIOS does, after all */
+    OUTREG(dpll_reg, dpll);
+    /* Wait for the clocks to stabilize. */
+    usleep(150);
 
 #if 0
     /* Magic re-write of the register for the Mac Mini.  Without this, the
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 97f5285..373bc21 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2233,19 +2233,8 @@ RestoreHWState(ScrnInfoPtr pScrn)
       usleep(150);
    }
    OUTREG(DPLL_A, pI830->saveDPLL_A);
-   if(xf86_config->num_crtc == 2) {
-      OUTREG(FPB0, pI830->saveFPB0);
-      OUTREG(FPB1, pI830->saveFPB1);
-      if (IS_I965G(pI830))
-	 OUTREG(DPLL_B_MD, pI830->saveDPLL_B_MD);
-      if (pI830->saveDPLL_B & DPLL_VCO_ENABLE)
-      {
-	 OUTREG(DPLL_A, pI830->saveDPLL_B & ~DPLL_VCO_ENABLE);
-	 usleep(150);
-      }
-      OUTREG(DPLL_B, pI830->saveDPLL_B);
-   }
-   /* Wait for clocks to stabilize */
+   usleep(150);
+   OUTREG(DPLL_A, pI830->saveDPLL_A);
    usleep(150);
 
    OUTREG(HTOTAL_A, pI830->saveHTOTAL_A);
@@ -2257,13 +2246,32 @@ RestoreHWState(ScrnInfoPtr pScrn)
    OUTREG(DSPASTRIDE, pI830->saveDSPASTRIDE);
    OUTREG(DSPASIZE, pI830->saveDSPASIZE);
    OUTREG(DSPAPOS, pI830->saveDSPAPOS);
-   OUTREG(DSPABASE, pI830->saveDSPABASE);
+   OUTREG(PIPEACONF, pI830->savePIPEACONF);
    OUTREG(PIPEASRC, pI830->savePIPEASRC);
+   OUTREG(DSPACNTR, pI830->saveDSPACNTR);
+   OUTREG(DSPABASE, pI830->saveDSPABASE);
+   if (IS_I965G(pI830)) {
+      OUTREG(DSPASURF, pI830->saveDSPASURF);
+   }
    for(i = 0; i < 256; i++) {
          OUTREG(PALETTE_A + (i << 2), pI830->savePaletteA[i]);
    }
 
    if(xf86_config->num_crtc == 2) {
+      OUTREG(FPB0, pI830->saveFPB0);
+      OUTREG(FPB1, pI830->saveFPB1);
+      if (IS_I965G(pI830))
+	 OUTREG(DPLL_B_MD, pI830->saveDPLL_B_MD);
+      if (pI830->saveDPLL_B & DPLL_VCO_ENABLE)
+      {
+	 OUTREG(DPLL_B, pI830->saveDPLL_B & ~DPLL_VCO_ENABLE);
+	 usleep(150);
+      }
+      OUTREG(DPLL_B, pI830->saveDPLL_B);
+      usleep(150);
+      OUTREG(DPLL_B, pI830->saveDPLL_B);
+      usleep(150);
+   
       OUTREG(HTOTAL_B, pI830->saveHTOTAL_B);
       OUTREG(HBLANK_B, pI830->saveHBLANK_B);
       OUTREG(HSYNC_B, pI830->saveHSYNC_B);
@@ -2273,8 +2281,13 @@ RestoreHWState(ScrnInfoPtr pScrn)
       OUTREG(DSPBSTRIDE, pI830->saveDSPBSTRIDE);
       OUTREG(DSPBSIZE, pI830->saveDSPBSIZE);
       OUTREG(DSPBPOS, pI830->saveDSPBPOS);
-      OUTREG(DSPBBASE, pI830->saveDSPBBASE);
       OUTREG(PIPEBSRC, pI830->savePIPEBSRC);
+      OUTREG(PIPEBCONF, pI830->savePIPEBCONF);
+      OUTREG(DSPBCNTR, pI830->saveDSPBCNTR);
+      OUTREG(DSPBBASE, pI830->saveDSPBBASE);
+      if (IS_I965G(pI830)) {
+	 OUTREG(DSPBSURF, pI830->saveDSPBSURF);
+      }
       for(i= 0; i < 256; i++) {
          OUTREG(PALETTE_B + (i << 2), pI830->savePaletteB[i]);
       }
@@ -2283,27 +2296,17 @@ RestoreHWState(ScrnInfoPtr pScrn)
    if (!IS_I830(pI830) && !IS_845G(pI830))
      OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL);
 
-   if (IS_I965G(pI830)) {
-      OUTREG(DSPASURF, pI830->saveDSPASURF);
-      OUTREG(DSPBSURF, pI830->saveDSPBSURF);
-   }
-
    OUTREG(VCLK_DIVISOR_VGA0, pI830->saveVCLK_DIVISOR_VGA0);
    OUTREG(VCLK_DIVISOR_VGA1, pI830->saveVCLK_DIVISOR_VGA1);
    OUTREG(VCLK_POST_DIV, pI830->saveVCLK_POST_DIV);
 
-   OUTREG(PIPEACONF, pI830->savePIPEACONF);
-   OUTREG(PIPEBCONF, pI830->savePIPEBCONF);
-
-   OUTREG(VGACNTRL, pI830->saveVGACNTRL);
-   OUTREG(DSPACNTR, pI830->saveDSPACNTR);
-   OUTREG(DSPBCNTR, pI830->saveDSPBCNTR);
-
    for (i = 0; i < xf86_config->num_output; i++) {
       xf86OutputPtr   output = xf86_config->output[i];
       (*output->funcs->restore) (output);
    }
 
+   OUTREG(VGACNTRL, pI830->saveVGACNTRL);
+
    for(i = 0; i < 7; i++) {
 	   OUTREG(SWF0 + (i << 2), pI830->saveSWF[i]);
 	   OUTREG(SWF00 + (i << 2), pI830->saveSWF[i+7]);
diff-tree 082519f34b468d0c5aa08db74ff2b51cf411d743 (from 55e7a32096a58f7bb2380b04df6b3dd9dc8e5b6a)
Author: Keith Packard <keithp at bouzouki.jf.intel.com>
Date:   Thu Dec 14 16:51:48 2006 -0800

    Turn pll/pipe/plane on in crtc_set_mode
    
    Instead of delaying pll/pipe/plane enables to the dpms function, turn them
    on right away in the crtc_set_mode function. To avoid rewriting these
    registers in the subsequent dpms function, check each register written there
    to see if the enable bit is already on and don't rewrite.

diff --git a/src/i830_display.c b/src/i830_display.c
index 4a429fc..897a4ee 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -506,22 +506,25 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mod
     case DPMSModeSuspend:
 	/* Enable the DPLL */
 	temp = INREG(dpll_reg);
-	OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE);
-	(void)INREG(dpll_reg); /* write posting */
+	if ((temp & DPLL_VCO_ENABLE) == 0)
+	    OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE);
 
 	/* Wait for the clocks to stabilize. */
 	usleep(150);
 
 	/* Enable the pipe */
 	temp = INREG(pipeconf_reg);
-	OUTREG(pipeconf_reg, temp | PIPEACONF_ENABLE);
+	if ((temp & PIPEACONF_ENABLE) == 0)
+	    OUTREG(pipeconf_reg, temp | PIPEACONF_ENABLE);
 
 	/* Enable the plane */
 	temp = INREG(dspcntr_reg);
-	OUTREG(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE);
-
-	/* Flush the plane changes */
-	OUTREG(dspbase_reg, INREG(dspbase_reg));
+	if ((temp & DISPLAY_PLANE_ENABLE) == 0)
+	{
+	    OUTREG(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE);
+	    /* Flush the plane changes */
+	    OUTREG(dspbase_reg, INREG(dspbase_reg));
+	}
 
 	/* Give the overlay scaler a chance to enable if it's on this pipe */
 	i830_crtc_dpms_video(crtc, TRUE);
@@ -530,16 +533,17 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mod
 	/* Give the overlay scaler a chance to disable if it's on this pipe */
 	i830_crtc_dpms_video(crtc, FALSE);
 
-	/* Disable display plane */
-	temp = INREG(dspcntr_reg);
-	OUTREG(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
-
 	/* Disable the VGA plane that we never use */
 	OUTREG(VGACNTRL, VGA_DISP_DISABLE);
 
-	/* Flush the plane changes */
-	OUTREG(dspbase_reg, INREG(dspbase_reg));
-	(void)INREG(dspbase_reg); /* write posting */
+	/* Disable display plane */
+	temp = INREG(dspcntr_reg);
+	if ((temp & DISPLAY_PLANE_ENABLE) != 0)
+	{
+	    OUTREG(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
+	    /* Flush the plane changes */
+	    OUTREG(dspbase_reg, INREG(dspbase_reg));
+	}
 
 	if (!IS_I9XX(pI830)) {
 	    /* Wait for vblank for the disable to take effect */
@@ -548,15 +552,15 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mod
 
 	/* Next, disable display pipes */
 	temp = INREG(pipeconf_reg);
-	OUTREG(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
-	(void)INREG(pipeconf_reg); /* write posting */
+	if ((temp & PIPEACONF_ENABLE) != 0)
+	    OUTREG(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
 
 	/* Wait for vblank for the disable to take effect. */
 	i830WaitForVblank(pScrn);
 
 	temp = INREG(dpll_reg);
-	OUTREG(dpll_reg, temp & ~DPLL_VCO_ENABLE);
-	(void)INREG(dpll_reg); /* write posting */
+	if ((temp & DPLL_VCO_ENABLE) != 0)
+	    OUTREG(dpll_reg, temp & ~DPLL_VCO_ENABLE);
 
 	/* Wait for the clocks to turn off. */
 	usleep(150);
@@ -592,6 +596,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
     int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
     int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD;
     int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
+    int dspbase_reg = (pipe == 0) ? DSPABASE : DSPBBASE;
     int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
     int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
     int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
@@ -753,13 +758,44 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
 	else
 	    pipeconf &= ~PIPEACONF_DOUBLE_WIDE;
     }
+    dspcntr |= DISPLAY_PLANE_ENABLE;
+    pipeconf |= PIPEACONF_ENABLE;
+    dpll |= DPLL_VCO_ENABLE;
+
+    if (is_lvds)
+    {
+	/* The LVDS pin pair needs to be on before the DPLLs are enabled.
+	 * This is an exception to the general rule that mode_set doesn't turn
+	 * things on.
+	 */
+	OUTREG(LVDS, INREG(LVDS) | LVDS_PORT_EN | LVDS_PIPEB_SELECT);
+    }
+    
+    /* Disable the panel fitter if it was on our pipe */
+    if (!IS_I830(pI830) && ((INREG(PFIT_CONTROL) >> 29) & 0x3) == pipe)
+	OUTREG(PFIT_CONTROL, 0);
 
     i830PrintPll("chosen", &clock);
     ErrorF("clock regs: 0x%08x, 0x%08x\n", (int)dpll, (int)fp);
 
+    if (IS_I965G(pI830)) {
+	int sdvo_pixel_multiply = adjusted_mode->Clock / mode->Clock;
+	OUTREG(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) |
+	       ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT));
+    }
+
+    if (dpll & DPLL_VCO_ENABLE)
+    {
+	OUTREG(fp_reg, fp);
+	OUTREG(dpll_reg, dpll & ~DPLL_VCO_ENABLE);
+	usleep(150);
+    }
     OUTREG(fp_reg, fp);
     OUTREG(dpll_reg, dpll);
+    /* Wait for the clocks to stabilize. */
+    usleep(150);
 
+#if 0
     /* Magic re-write of the register for the Mac Mini.  Without this, the
      * first X invocation after a cold boot will stick in 4x pixel multiply
      * mode.  Alternatives that don't work include sleeping and doing an
@@ -767,12 +803,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
      * write above.
      */
     OUTREG(dpll_reg, dpll);
-
-    if (IS_I965G(pI830)) {
-	int sdvo_pixel_multiply = adjusted_mode->Clock / mode->Clock;
-	OUTREG(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) |
-	       ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT));
-    }
+#endif
 
     OUTREG(htot_reg, (adjusted_mode->CrtcHDisplay - 1) |
 	((adjusted_mode->CrtcHTotal - 1) << 16));
@@ -792,14 +823,16 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
      */
     OUTREG(dspsize_reg, ((mode->VDisplay - 1) << 16) | (mode->HDisplay - 1));
     OUTREG(dsppos_reg, 0);
-    i830PipeSetBase(crtc, crtc->x, crtc->y);
     OUTREG(pipesrc_reg, ((mode->HDisplay - 1) << 16) | (mode->VDisplay - 1));
+    i830PipeSetBase(crtc, crtc->x, crtc->y);
     OUTREG(pipeconf_reg, pipeconf);
+    i830WaitForVblank(pScrn);
+    
     OUTREG(dspcntr_reg, dspcntr);
-
-    /* Disable the panel fitter if it was on our pipe */
-    if (!IS_I830(pI830) && ((INREG(PFIT_CONTROL) >> 29) & 0x3) == pipe)
-	OUTREG(PFIT_CONTROL, 0);
+    /* Flush the plane changes */
+    OUTREG(dspbase_reg, INREG(dspbase_reg));
+    
+    i830WaitForVblank(pScrn);
 }
 
 /**
diff --git a/src/i830_driver.c b/src/i830_driver.c
index a210b63..97f5285 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2225,15 +2225,25 @@ RestoreHWState(ScrnInfoPtr pScrn)
 
    OUTREG(FPA0, pI830->saveFPA0);
    OUTREG(FPA1, pI830->saveFPA1);
-   OUTREG(DPLL_A, pI830->saveDPLL_A);
    if (IS_I965G(pI830))
       OUTREG(DPLL_A_MD, pI830->saveDPLL_A_MD);
+   if (pI830->saveDPLL_A & DPLL_VCO_ENABLE)
+   {
+      OUTREG(DPLL_A, pI830->saveDPLL_A & ~DPLL_VCO_ENABLE);
+      usleep(150);
+   }
+   OUTREG(DPLL_A, pI830->saveDPLL_A);
    if(xf86_config->num_crtc == 2) {
       OUTREG(FPB0, pI830->saveFPB0);
       OUTREG(FPB1, pI830->saveFPB1);
-      OUTREG(DPLL_B, pI830->saveDPLL_B);
       if (IS_I965G(pI830))
 	 OUTREG(DPLL_B_MD, pI830->saveDPLL_B_MD);
+      if (pI830->saveDPLL_B & DPLL_VCO_ENABLE)
+      {
+	 OUTREG(DPLL_A, pI830->saveDPLL_B & ~DPLL_VCO_ENABLE);
+	 usleep(150);
+      }
+      OUTREG(DPLL_B, pI830->saveDPLL_B);
    }
    /* Wait for clocks to stabilize */
    usleep(150);
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index 4307025..b682b27 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -196,11 +196,13 @@ i830_lvds_mode_set(xf86OutputPtr output,
     I830Ptr pI830 = I830PTR(pScrn);
     CARD32 pfit_control;
 
+#if 0
     /* The LVDS pin pair needs to be on before the DPLLs are enabled.
      * This is an exception to the general rule that mode_set doesn't turn
      * things on.
      */
     OUTREG(LVDS, INREG(LVDS) | LVDS_PORT_EN | LVDS_PIPEB_SELECT);
+#endif
 
     /* Enable automatic panel scaling so that non-native modes fill the
      * screen.  Should be enabled before the pipe is enabled, according to
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index fc17efd..d19b8b0 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -679,26 +679,31 @@ i830_sdvo_dpms(xf86OutputPtr output, int
     I830OutputPrivatePtr    intel_output = output->driver_private;
     struct i830_sdvo_priv   *dev_priv = intel_output->dev_priv;
     I830Ptr pI830 = I830PTR(pScrn);
+    CARD32  temp;
 
     if (mode != DPMSModeOn) {
 	i830_sdvo_set_active_outputs(output, 0);
-	OUTREG(dev_priv->output_device,
-	       INREG(dev_priv->output_device) & ~SDVO_ENABLE);
+	temp = INREG(dev_priv->output_device);
+	if ((temp & SDVO_ENABLE) != 0)
+	    OUTREG(dev_priv->output_device, temp & ~SDVO_ENABLE);
     } else {
 	Bool input1, input2;
 	int i;
 	CARD8 status;
 
-	OUTREG(dev_priv->output_device,
-	       INREG(dev_priv->output_device) | SDVO_ENABLE);
+	temp = INREG(dev_priv->output_device);
+	if ((temp & SDVO_ENABLE) == 0)
+	    OUTREG(dev_priv->output_device, temp | SDVO_ENABLE);
 
 	i830_sdvo_set_active_outputs(output, dev_priv->active_outputs);
 
+#if 0
 	/* Do it again!  If we remove this below register write, or the exact
 	 * same one 2 lines up, the mac mini SDVO output doesn't turn on.
 	 */
 	OUTREG(dev_priv->output_device,
 	       INREG(dev_priv->output_device) | SDVO_ENABLE);
+#endif
 
 	for (i = 0; i < 2; i++)
 	    i830WaitForVblank(pScrn);
diff-tree 55e7a32096a58f7bb2380b04df6b3dd9dc8e5b6a (from d4142abc68888178a8f6c54fdcece91e898bc9f5)
Author: Keith Packard <keithp at bouzouki.jf.intel.com>
Date:   Thu Dec 14 16:50:26 2006 -0800

    Respect Virtual in xorg.conf
    
    Instead of growing virtual to fit our desired sizes, if it is set in the
    config file, use the value as the virtual size and make the default
    configuration fit within that size (if possible).

diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index 6b73264..76d6d03 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -196,7 +196,7 @@ xf86OutputDestroy (xf86OutputPtr output)
 }
 
 static DisplayModePtr
-xf86DefaultMode (xf86OutputPtr output)
+xf86DefaultMode (xf86OutputPtr output, int width, int height)
 {
     DisplayModePtr  target_mode = NULL;
     DisplayModePtr  mode;
@@ -216,6 +216,7 @@ xf86DefaultMode (xf86OutputPtr output)
 	int	    preferred = (mode->type & M_T_PREFERRED) != 0;
 	int	    diff;
 
+	if (mode->HDisplay > width || mode->VDisplay > height) continue;
 	dpi = (mode->HDisplay * 254) / (mm_height * 10);
 	diff = dpi - 96;
 	diff = diff < 0 ? -diff : diff;
@@ -231,7 +232,8 @@ xf86DefaultMode (xf86OutputPtr output)
 }
 
 static DisplayModePtr
-xf86ClosestMode (xf86OutputPtr output, DisplayModePtr match)
+xf86ClosestMode (xf86OutputPtr output, DisplayModePtr match,
+		 int width, int height)
 {
     DisplayModePtr  target_mode = NULL;
     DisplayModePtr  mode;
@@ -245,6 +247,8 @@ xf86ClosestMode (xf86OutputPtr output, D
 	int	    dx, dy;
 	int	    diff;
 
+	if (mode->HDisplay > width || mode->VDisplay > height) continue;
+	
 	/* exact matches are preferred */
 	if (xf86ModesEqual (mode, match))
 	    return mode;
@@ -262,13 +266,16 @@ xf86ClosestMode (xf86OutputPtr output, D
 }
 
 static Bool
-xf86OutputHasPreferredMode (xf86OutputPtr output)
+xf86OutputHasPreferredMode (xf86OutputPtr output, int width, int height)
 {
     DisplayModePtr  mode;
 
     for (mode = output->probed_modes; mode; mode = mode->next)
+    {
+	if (mode->HDisplay > width || mode->VDisplay > height) continue;
 	if (mode->type & M_T_PREFERRED)
 	    return TRUE;
+    }
     return FALSE;
 }
 
@@ -276,7 +283,9 @@ static int
 xf86PickCrtcs (ScrnInfoPtr	pScrn,
 	       xf86CrtcPtr	*best_crtcs,
 	       DisplayModePtr	*modes,
-	       int		n)
+	       int		n,
+	       int		width,
+	       int		height)
 {
     xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
     int		    c, o, l;
@@ -297,7 +306,7 @@ xf86PickCrtcs (ScrnInfoPtr	pScrn,
      */
     best_crtcs[n] = NULL;
     best_crtc = NULL;
-    best_score = xf86PickCrtcs (pScrn, best_crtcs, modes, n+1);
+    best_score = xf86PickCrtcs (pScrn, best_crtcs, modes, n+1, width, height);
     if (modes[n] == NULL)
 	return best_score;
     
@@ -310,7 +319,7 @@ xf86PickCrtcs (ScrnInfoPtr	pScrn,
     if (output->status == XF86OutputStatusConnected)
 	my_score++;
     /* Score outputs with preferred modes higher */
-    if (xf86OutputHasPreferredMode (output))
+    if (xf86OutputHasPreferredMode (output, width, height))
 	my_score++;
     /*
      * Select a crtc for this output and
@@ -349,7 +358,7 @@ xf86PickCrtcs (ScrnInfoPtr	pScrn,
 	}
 	crtcs[n] = crtc;
 	memcpy (crtcs, best_crtcs, n * sizeof (xf86CrtcPtr));
-	score = my_score + xf86PickCrtcs (pScrn, crtcs, modes, n+1);
+	score = my_score + xf86PickCrtcs (pScrn, crtcs, modes, n+1, width, height);
 	if (score >= best_score)
 	{
 	    best_crtc = crtc;
@@ -378,7 +387,7 @@ xf86DefaultScreenLimits (ScrnInfoPtr pSc
 
     for (c = 0; c < config->num_crtc; c++)
     {
-	int	    crtc_width = 1600, crtc_height = 1200;
+	int	    crtc_width = 0, crtc_height = 0;
 
 	for (o = 0; o < config->num_output; o++) 
 	{
@@ -392,16 +401,19 @@ xf86DefaultScreenLimits (ScrnInfoPtr pSc
 		    {
 			if (mode->HDisplay > crtc_width)
 			    crtc_width = mode->HDisplay;
-			if (mode->VDisplay > crtc_width)
+			if (mode->VDisplay > crtc_height)
 			    crtc_height = mode->VDisplay;
 		    }
 		}
 	}
-	if (crtc_width > width)
-	    width = crtc_width;
+	width += crtc_width;
 	if (crtc_height > height)
 	    height = crtc_height;
     }
+    if (config->maxWidth && width > config->maxWidth) width = config->maxWidth;
+    if (config->maxHeight && height > config->maxHeight) height = config->maxHeight;
+    if (config->minWidth && width < config->minWidth) width = config->minWidth;
+    if (config->minHeight && height < config->minHeight) height = config->minHeight;
     *widthp = width;
     *heightp = height;
 }
@@ -575,6 +587,26 @@ xf86InitialConfiguration (ScrnInfoPtr	  
 
     xf86ProbeOutputModes (pScrn);
 
+    if (pScrn->display->virtualX == 0)
+    {
+	/*
+	 * Expand virtual size to cover potential mode switches
+	 */
+	xf86DefaultScreenLimits (pScrn, &width, &height);
+    
+	pScrn->display->virtualX = width;
+	pScrn->display->virtualY = height;
+    }
+    else
+    {
+	width = pScrn->display->virtualX;
+	height = pScrn->display->virtualY;
+    }
+    if (width > pScrn->virtualX)
+	pScrn->virtualX = width;
+    if (height > pScrn->virtualY)
+	pScrn->virtualY = height;
+    
     crtcs = xnfcalloc (config->num_output, sizeof (xf86CrtcPtr));
     modes = xnfcalloc (config->num_output, sizeof (DisplayModePtr));
     
@@ -589,9 +621,9 @@ xf86InitialConfiguration (ScrnInfoPtr	  
 	xf86OutputPtr output = config->output[o];
 
 	if (output->status != XF86OutputStatusDisconnected &&
-	    xf86OutputHasPreferredMode (output))
+	    xf86OutputHasPreferredMode (output, width, height))
 	{
-	    target_mode = xf86DefaultMode (output);
+	    target_mode = xf86DefaultMode (output, width, height);
 	    if (target_mode)
 	    {
 		modes[o] = target_mode;
@@ -607,7 +639,7 @@ xf86InitialConfiguration (ScrnInfoPtr	  
 	    xf86OutputPtr output = config->output[o];
 	    if (output->status != XF86OutputStatusDisconnected)
 	    {
-		target_mode = xf86DefaultMode (output);
+		target_mode = xf86DefaultMode (output, width, height);
 		if (target_mode)
 		{
 		    modes[o] = target_mode;
@@ -622,30 +654,16 @@ xf86InitialConfiguration (ScrnInfoPtr	  
 	xf86OutputPtr output = config->output[o];
 	
 	if (output->status != XF86OutputStatusDisconnected && !modes[o])
-	    modes[o] = xf86ClosestMode (output, target_mode);
+	    modes[o] = xf86ClosestMode (output, target_mode, width, height);
     }
 
-    if (!xf86PickCrtcs (pScrn, crtcs, modes, 0))
+    if (!xf86PickCrtcs (pScrn, crtcs, modes, 0, width, height))
     {
 	xfree (crtcs);
 	xfree (modes);
 	return FALSE;
     }
     
-    xf86DefaultScreenLimits (pScrn, &width, &height);
-    
-    /*
-     * Expand virtual size to cover potential mode switches
-     */
-    if (width > pScrn->virtualX)
-	pScrn->virtualX = width;
-    if (width > pScrn->display->virtualX)
-	pScrn->display->virtualX = width;
-    if (height > pScrn->virtualY)
-	pScrn->virtualY = height;
-    if (height > pScrn->display->virtualY)
-	pScrn->display->virtualY = height;
-    
     /* XXX override xf86 common frame computation code */
     
     pScrn->display->frameX0 = 0;
diff-tree d4142abc68888178a8f6c54fdcece91e898bc9f5 (from 2b5a5542ad7d1c558d1684a0a69b66bab6e9d001)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Dec 14 13:49:08 2006 -0800

    Set frame buffer size ranges in xf86_config.
    
    Initialization and default configuration code needs to know the range of
    legitimate sizes for the frame buffer.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index d4f2aa3..a210b63 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -912,6 +912,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    Bool enable;
    const char *chipname;
    int num_pipe;
+   int max_width;
 #ifdef XF86DRI
    unsigned long savedMMSize;
 #endif
@@ -970,10 +971,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
     } else 
         pI830->entityPrivate = NULL;
 
-   /* Allocate an xf86CrtcConfig */
-   xf86CrtcConfigInit (pScrn);
-   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-
    if (xf86RegisterResources(pI830->pEnt->index, 0, ResNone)) {
       PreInitCleanup(pScrn);
       return FALSE;
@@ -1181,6 +1178,16 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    xf86DrvMsg(pScrn->scrnIndex, from, "IO registers at addr 0x%lX\n",
 	      (unsigned long)pI830->MMIOAddr);
 
+   /* Allocate an xf86CrtcConfig */
+   xf86CrtcConfigInit (pScrn);
+   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+   
+   if (IS_I965G(pI830))
+      max_width = 16384;
+   else
+      max_width = 8192 / pI830->cpp;
+   xf86CrtcSetSizeRange (pScrn, 320, 200, max_width, 2048);
+
    /* Some of the probing needs MMIO access, so map it here. */
    I830MapMMIO(pScrn);
 
@@ -1836,6 +1843,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    if (pScrn->displayWidth * pI830->cpp > 8192) {
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot support frame buffer stride > 8K >  DRI.\n");
       pI830->disableTiling = TRUE;
+      pI830->directRenderingDisabled = TRUE;
    }
 
    if (pScrn->virtualY > 2048) {
diff-tree 2b5a5542ad7d1c558d1684a0a69b66bab6e9d001 (from 3fe802453a85183a69c36a098639895f49b17df1)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Dec 14 13:43:50 2006 -0800

    Change TV modes from Preferred to Driver.
    
    This avoids having the artificial TV mode size drive overall screen size.

diff --git a/src/i830_tv.c b/src/i830_tv.c
index ccb6aac..af9826b 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -702,7 +702,7 @@ i830_tv_get_modes(xf86OutputPtr output)
     new->VSyncEnd   = 777;
     new->VTotal     = 806;
 
-    new->type       = M_T_PREFERRED;
+    new->type       = M_T_DRIVER;
 
     return new;
 }
diff-tree 3fe802453a85183a69c36a098639895f49b17df1 (from 0f6addc8a6aeb9bd041d0f8e8e5850e76764ba51)
Author: Keith Packard <keithp at bouzouki.jf.intel.com>
Date:   Wed Dec 13 13:15:14 2006 -0800

    Move xf86CrtcConfig to ScrnInfo private.
    
    Pull xf86CrtcConfig out of the driver private structure and allocate a
    ScrnInfo private index for it. Also, make the arrays of outputs and crtcs
    dynamic instead of fixed.

diff --git a/src/i830.h b/src/i830.h
index 292374c..a92f557 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -234,9 +234,6 @@ typedef struct _I830PipeRec {
 } I830PipeRec, *I830PipePtr;
 
 typedef struct _I830Rec {
-   /* Must be first */
-   xf86CrtcConfigRec	xf86_config;
-    
    unsigned char *MMIOBase;
    unsigned char *FbBase;
    int cpp;
diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index e9ca8f1..cb1585f 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -86,10 +86,11 @@ I830SetPipeCursorBase (xf86CrtcPtr crtc)
     I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
     int			pipe = intel_crtc->pipe;
     I830Ptr		pI830 = I830PTR(pScrn);
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     int			cursor_base = (pipe == 0 ? CURSOR_A_BASE : CURSOR_B_BASE);
     I830MemRange	*cursor_mem;
 
-    if (pipe >= pI830->xf86_config.num_crtc)
+    if (pipe >= xf86_config->num_crtc)
 	FatalError("Bad pipe number for cursor base setting\n");
 
     if (pI830->CursorIsARGB)
@@ -180,17 +181,18 @@ I830SetPipeCursor (xf86CrtcPtr crtc, Boo
 void
 I830InitHWCursor(ScrnInfoPtr pScrn)
 {
+   xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
    I830Ptr pI830 = I830PTR(pScrn);
    CARD32 temp;
    int i;
 
    DPRINTF(PFX, "I830InitHWCursor\n");
-   for (i = 0; i < pI830->xf86_config.num_crtc; i++) 
-      pI830->xf86_config.crtc[i]->cursorShown = FALSE;
+   for (i = 0; i < xf86_config->num_crtc; i++) 
+      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->xf86_config.num_crtc; i++)
+      for (i = 0; i < xf86_config->num_crtc; i++)
       {
 	 int   cursor_control = i == 0 ? CURSOR_A_CONTROL : CURSOR_B_CONTROL;
 	 temp = INREG(cursor_control);
@@ -204,7 +206,7 @@ I830InitHWCursor(ScrnInfoPtr pScrn)
 	    temp |= CURSOR_MODE_64_4C_AX;
 	 /* Need to set control, then address. */
 	 OUTREG(cursor_control, temp);
-	 I830SetPipeCursorBase(pI830->xf86_config.crtc[i]);
+	 I830SetPipeCursorBase(xf86_config->crtc[i]);
       }
    } else {
       temp = INREG(CURSOR_CONTROL);
@@ -217,7 +219,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_config.crtc[0]);
+      I830SetPipeCursorBase(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);
@@ -454,6 +456,7 @@ static void I830LoadCursorARGB (ScrnInfo
 static void
 I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
 {
+   xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     I830Ptr pI830 = I830PTR(pScrn);
     CARD32 temp;
     Bool inrange;
@@ -490,9 +493,9 @@ I830SetCursorPosition(ScrnInfoPtr pScrn,
     x -= hotspotx;
     y -= hotspoty;
 
-    for (pipe = 0; pipe < pI830->xf86_config.num_crtc; pipe++)
+    for (pipe = 0; pipe < xf86_config->num_crtc; pipe++)
     {
-	xf86CrtcPtr    crtc = pI830->xf86_config.crtc[pipe];
+	xf86CrtcPtr    crtc = xf86_config->crtc[pipe];
 	DisplayModePtr	    mode = &crtc->curMode;
 	int		    thisx = x - crtc->x;
 	int		    thisy = y - crtc->y;
@@ -542,6 +545,7 @@ I830SetCursorPosition(ScrnInfoPtr pScrn,
 static void
 I830ShowCursor(ScrnInfoPtr pScrn)
 {
+   xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
    I830Ptr pI830 = I830PTR(pScrn);
     int pipe;
 
@@ -556,26 +560,28 @@ I830ShowCursor(ScrnInfoPtr pScrn)
 	   pI830->CursorMemARGB->Physical, pI830->CursorMemARGB->Start);
 
     pI830->cursorOn = TRUE;
-    for (pipe = 0; pipe < pI830->xf86_config.num_crtc; pipe++)
-	I830SetPipeCursor (pI830->xf86_config.crtc[pipe], TRUE);
+    for (pipe = 0; pipe < xf86_config->num_crtc; pipe++)
+	I830SetPipeCursor (xf86_config->crtc[pipe], TRUE);
 }
 
 static void
 I830HideCursor(ScrnInfoPtr pScrn)
 {
+   xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
    I830Ptr pI830 = I830PTR(pScrn);
     int pipe;
 
    DPRINTF(PFX, "I830HideCursor\n");
 
    pI830->cursorOn = FALSE;
-    for (pipe = 0; pipe < pI830->xf86_config.num_crtc; pipe++)
-	I830SetPipeCursor (pI830->xf86_config.crtc[pipe], TRUE);
+    for (pipe = 0; pipe < xf86_config->num_crtc; pipe++)
+	I830SetPipeCursor (xf86_config->crtc[pipe], TRUE);
 }
 
 static void
 I830SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
 {
+   xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
    I830Ptr pI830 = I830PTR(pScrn);
    int pipe; 
 
@@ -587,9 +593,9 @@ I830SetCursorColors(ScrnInfoPtr pScrn, i
 
    DPRINTF(PFX, "I830SetCursorColors\n");
 
-   for (pipe = 0; pipe < pI830->xf86_config.num_crtc; pipe++)
+   for (pipe = 0; pipe < xf86_config->num_crtc; pipe++)
    {
-      xf86CrtcPtr	crtc = pI830->xf86_config.crtc[pipe];
+      xf86CrtcPtr	crtc = 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 37a6e32..4a429fc 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -225,12 +225,12 @@ Bool
 i830PipeHasType (xf86CrtcPtr crtc, int type)
 {
     ScrnInfoPtr	pScrn = crtc->scrn;
-    I830Ptr	pI830 = I830PTR(pScrn);
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     int		i;
 
-    for (i = 0; i < pI830->xf86_config.num_output; i++)
+    for (i = 0; i < xf86_config->num_output; i++)
     {
-	xf86OutputPtr  output = pI830->xf86_config.output[i];
+	xf86OutputPtr  output = xf86_config->output[i];
 	if (output->crtc == crtc)
 	{
 	    I830OutputPrivatePtr    intel_output = output->driver_private;
@@ -373,14 +373,14 @@ DisplayModePtr
 i830PipeFindClosestMode(xf86CrtcPtr crtc, DisplayModePtr pMode)
 {
     ScrnInfoPtr	pScrn = crtc->scrn;
-    I830Ptr pI830 = I830PTR(pScrn);
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(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->xf86_config.num_output; i++) 
+    for (i = 0; i < xf86_config->num_output; i++) 
     {
-	xf86OutputPtr  output = pI830->xf86_config.output[i];
+	xf86OutputPtr  output = xf86_config->output[i];
 	if (output->crtc == crtc && output->probed_modes != NULL)
 	{
 	    pScan = output->probed_modes;
@@ -469,11 +469,11 @@ Bool
 i830PipeInUse (xf86CrtcPtr crtc)
 {
     ScrnInfoPtr pScrn = crtc->scrn;
-    I830Ptr pI830 = I830PTR(pScrn);
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     int	i;
     
-    for (i = 0; i < pI830->xf86_config.num_output; i++)
-	if (pI830->xf86_config.output[i]->crtc == crtc)
+    for (i = 0; i < xf86_config->num_output; i++)
+	if (xf86_config->output[i]->crtc == crtc)
 	    return TRUE;
     return FALSE;
 }
@@ -584,6 +584,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
 		   DisplayModePtr adjusted_mode)
 {
     ScrnInfoPtr pScrn = crtc->scrn;
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     I830Ptr pI830 = I830PTR(pScrn);
     I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
     int pipe = intel_crtc->pipe;
@@ -612,8 +613,8 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
     /* Set up some convenient bools for what outputs are connected to
      * our pipe, used in DPLL setup.
      */
-    for (i = 0; i < pI830->xf86_config.num_output; i++) {
-	xf86OutputPtr  output = pI830->xf86_config.output[i];
+    for (i = 0; i < xf86_config->num_output; i++) {
+	xf86OutputPtr  output = xf86_config->output[i];
 	I830OutputPrivatePtr intel_output = output->driver_private;
 
 	if (output->crtc != crtc)
@@ -814,7 +815,7 @@ i830PipeSetMode(xf86CrtcPtr crtc, Displa
 		Bool plane_enable)
 {
     ScrnInfoPtr pScrn = crtc->scrn;
-    I830Ptr pI830 = I830PTR(pScrn);
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     int i;
     Bool ret = FALSE;
 #ifdef XF86DRI
@@ -842,8 +843,8 @@ i830PipeSetMode(xf86CrtcPtr crtc, Displa
      * adjust it according to limitations or output properties, and also
      * a chance to reject the mode entirely.
      */
-    for (i = 0; i < pI830->xf86_config.num_output; i++) {
-	xf86OutputPtr output = pI830->xf86_config.output[i];
+    for (i = 0; i < xf86_config->num_output; i++) {
+	xf86OutputPtr output = xf86_config->output[i];
 
 	if (output->crtc != crtc)
 	    continue;
@@ -860,8 +861,8 @@ i830PipeSetMode(xf86CrtcPtr crtc, Displa
     }
 
     /* Disable the outputs and CRTCs before setting the mode. */
-    for (i = 0; i < pI830->xf86_config.num_output; i++) {
-	xf86OutputPtr output = pI830->xf86_config.output[i];
+    for (i = 0; i < xf86_config->num_output; i++) {
+	xf86OutputPtr output = xf86_config->output[i];
 
 	if (output->crtc != crtc)
 	    continue;
@@ -876,16 +877,16 @@ i830PipeSetMode(xf86CrtcPtr crtc, Displa
      * on the DPLL.
      */
     crtc->funcs->mode_set(crtc, pMode, adjusted_mode);
-    for (i = 0; i < pI830->xf86_config.num_output; i++) {
-	xf86OutputPtr output = pI830->xf86_config.output[i];
+    for (i = 0; i < xf86_config->num_output; i++) {
+	xf86OutputPtr output = xf86_config->output[i];
 	if (output->crtc == crtc)
 	    output->funcs->mode_set(output, pMode, adjusted_mode);
     }
 
     /* Now, enable the clocks, plane, pipe, and outputs that we set up. */
     crtc->funcs->dpms(crtc, DPMSModeOn);
-    for (i = 0; i < pI830->xf86_config.num_output; i++) {
-	xf86OutputPtr output = pI830->xf86_config.output[i];
+    for (i = 0; i < xf86_config->num_output; i++) {
+	xf86OutputPtr output = xf86_config->output[i];
 	if (output->crtc == crtc)
 	    output->funcs->dpms(output, DPMSModeOn);
     }
@@ -923,14 +924,15 @@ done:
 void
 i830DisableUnusedFunctions(ScrnInfoPtr pScrn)
 {
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     I830Ptr pI830 = I830PTR(pScrn);
     int o, pipe;
 
     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling unused functions\n");
 
-    for (o = 0; o < pI830->xf86_config.num_output; o++) 
+    for (o = 0; o < xf86_config->num_output; o++) 
     {
-	xf86OutputPtr  output = pI830->xf86_config.output[o];
+	xf86OutputPtr  output = xf86_config->output[o];
 	if (!output->crtc)
 	    (*output->funcs->dpms)(output, DPMSModeOff);
     }
@@ -939,9 +941,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->xf86_config.num_crtc; pipe++) 
+    for (pipe = 0; pipe < xf86_config->num_crtc; pipe++) 
     {
-	xf86CrtcPtr crtc = pI830->xf86_config.crtc[pipe];
+	xf86CrtcPtr crtc = xf86_config->crtc[pipe];
 	I830CrtcPrivatePtr  intel_crtc = crtc->driver_private;
 	int		    pipe = intel_crtc->pipe;
 	int	    dspcntr_reg = pipe == 0 ? DSPACNTR : DSPBCNTR;
@@ -990,7 +992,6 @@ Bool
 i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
 {
     xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
-    I830Ptr pI830 = I830PTR(pScrn);
     Bool ok = TRUE;
     xf86CrtcPtr crtc = config->output[config->compat_output]->crtc;
 
@@ -1025,13 +1026,14 @@ done:
 void
 i830DescribeOutputConfiguration(ScrnInfoPtr pScrn)
 {
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     I830Ptr pI830 = I830PTR(pScrn);
     int i;
 
     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output configuration:\n");
 
-    for (i = 0; i < pI830->xf86_config.num_crtc; i++) {
-	xf86CrtcPtr crtc = pI830->xf86_config.crtc[i];
+    for (i = 0; i < xf86_config->num_crtc; i++) {
+	xf86CrtcPtr crtc = 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;
@@ -1061,8 +1063,8 @@ i830DescribeOutputConfiguration(ScrnInfo
 	}
     }
 
-    for (i = 0; i < pI830->xf86_config.num_output; i++) {
-	xf86OutputPtr	output = pI830->xf86_config.output[i];
+    for (i = 0; i < xf86_config->num_output; i++) {
+	xf86OutputPtr	output = xf86_config->output[i];
 	xf86CrtcPtr	crtc = output->crtc;
 	I830CrtcPrivatePtr	intel_crtc = crtc ? crtc->driver_private : NULL;
 	
@@ -1091,7 +1093,7 @@ xf86CrtcPtr
 i830GetLoadDetectPipe(xf86OutputPtr output)
 {
     ScrnInfoPtr		    pScrn = output->scrn;
-    I830Ptr		    pI830 = I830PTR(pScrn);
+    xf86CrtcConfigPtr	    xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     I830OutputPrivatePtr    intel_output = output->driver_private;
     xf86CrtcPtr	    crtc;
     int			    i;
@@ -1099,14 +1101,14 @@ i830GetLoadDetectPipe(xf86OutputPtr outp
     if (output->crtc) 
 	return output->crtc;
 
-    for (i = 0; i < pI830->xf86_config.num_crtc; i++)
-	if (!i830PipeInUse(pI830->xf86_config.crtc[i]))
+    for (i = 0; i < xf86_config->num_crtc; i++)
+	if (!i830PipeInUse(xf86_config->crtc[i]))
 	    break;
 
-    if (i == pI830->xf86_config.num_crtc)
+    if (i == xf86_config->num_crtc)
 	return NULL;
 
-    crtc = pI830->xf86_config.crtc[i];
+    crtc = xf86_config->crtc[i];
 
     output->crtc = crtc;
     intel_output->load_detect_temp = TRUE;
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 0f6145b..c5d7a94 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1518,11 +1518,12 @@ Bool
 I830DRISetVBlankInterrupt (ScrnInfoPtr pScrn, Bool on)
 {
     I830Ptr pI830 = I830PTR(pScrn);
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     drmI830VBlankPipe pipe;
 
     if (pI830->directRenderingEnabled && pI830->drmMinor >= 5) {
 	if (on) {
-	    if (pI830->xf86_config.num_crtc > 1 && pI830->xf86_config.crtc[1]->enabled)
+	    if (xf86_config->num_crtc > 1 && 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 7ec5559..d4f2aa3 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -578,6 +578,7 @@ static void
 I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
 		LOCO * colors, VisualPtr pVisual)
 {
+   xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
    I830Ptr pI830;
    int i,j, index;
    unsigned char r, g, b;
@@ -589,9 +590,9 @@ I830LoadPalette(ScrnInfoPtr pScrn, int n
    DPRINTF(PFX, "I830LoadPalette: numColors: %d\n", numColors);
    pI830 = I830PTR(pScrn);
 
-   for(p=0; p < pI830->xf86_config.num_crtc; p++) 
+   for(p=0; p < xf86_config->num_crtc; p++) 
    {
-      xf86CrtcPtr	   crtc = pI830->xf86_config.crtc[p];
+      xf86CrtcPtr	   crtc = xf86_config->crtc[p];
       I830CrtcPrivatePtr   intel_crtc = crtc->driver_private;
 
       if (p == 0) {
@@ -896,6 +897,7 @@ I830ReduceMMSize(ScrnInfoPtr pScrn, unsi
 static Bool
 I830PreInit(ScrnInfoPtr pScrn, int flags)
 {
+   xf86CrtcConfigPtr   xf86_config;
    vgaHWPtr hwp;
    I830Ptr pI830;
    MessageType from = X_PROBED;
@@ -968,6 +970,10 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
     } else 
         pI830->entityPrivate = NULL;
 
+   /* Allocate an xf86CrtcConfig */
+   xf86CrtcConfigInit (pScrn);
+   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+
    if (xf86RegisterResources(pI830->pEnt->index, 0, ResNone)) {
       PreInitCleanup(pScrn);
       return FALSE;
@@ -1386,9 +1392,9 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
     * This will give us some likely legitimate response for later if both
     * pipes are already allocated and we're asked to do a detect.
     */
-   for (i = 0; i < pI830->xf86_config.num_output; i++) 
+   for (i = 0; i < xf86_config->num_output; i++) 
    {
-      xf86OutputPtr	      output = pI830->xf86_config.output[i];
+      xf86OutputPtr	      output = xf86_config->output[i];
 
       output->status = (*output->funcs->detect) (output);
    }
@@ -2096,6 +2102,7 @@ SetHWOperatingState(ScrnInfoPtr pScrn)
 static Bool
 SaveHWState(ScrnInfoPtr pScrn)
 {
+   xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
    I830Ptr pI830 = I830PTR(pScrn);
    vgaHWPtr hwp = VGAHWPTR(pScrn);
    vgaRegPtr vgaReg = &hwp->SavedReg;
@@ -2125,7 +2132,7 @@ SaveHWState(ScrnInfoPtr pScrn)
       pI830->savePaletteA[i] = INREG(PALETTE_A + (i << 2));
    }
 
-   if(pI830->xf86_config.num_crtc == 2) {
+   if(xf86_config->num_crtc == 2) {
       pI830->savePIPEBCONF = INREG(PIPEBCONF);
       pI830->savePIPEBSRC = INREG(PIPEBSRC);
       pI830->saveDSPBCNTR = INREG(DSPBCNTR);
@@ -2169,8 +2176,8 @@ SaveHWState(ScrnInfoPtr pScrn)
 
    pI830->savePFIT_CONTROL = INREG(PFIT_CONTROL);
 
-   for (i = 0; i < pI830->xf86_config.num_output; i++) {
-      xf86OutputPtr   output = pI830->xf86_config.output[i];
+   for (i = 0; i < xf86_config->num_output; i++) {
+      xf86OutputPtr   output = xf86_config->output[i];
       if (output->funcs->save)
 	 (*output->funcs->save) (output);
    }
@@ -2184,6 +2191,7 @@ SaveHWState(ScrnInfoPtr pScrn)
 static Bool
 RestoreHWState(ScrnInfoPtr pScrn)
 {
+   xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
    I830Ptr pI830 = I830PTR(pScrn);
    vgaHWPtr hwp = VGAHWPTR(pScrn);
    vgaRegPtr vgaReg = &hwp->SavedReg;
@@ -2196,14 +2204,14 @@ RestoreHWState(ScrnInfoPtr pScrn)
 #endif
 
    /* Disable outputs */
-   for (i = 0; i < pI830->xf86_config.num_output; i++) {
-      xf86OutputPtr   output = pI830->xf86_config.output[i];
+   for (i = 0; i < xf86_config->num_output; i++) {
+      xf86OutputPtr   output = xf86_config->output[i];
       output->funcs->dpms(output, DPMSModeOff);
    }
 
    /* Disable pipes */
-   for (i = 0; i < pI830->xf86_config.num_crtc; i++) {
-      xf86CrtcPtr crtc = pI830->xf86_config.crtc[i];
+   for (i = 0; i < xf86_config->num_crtc; i++) {
+      xf86CrtcPtr crtc = xf86_config->crtc[i];
       crtc->funcs->dpms(crtc, DPMSModeOff);
    }
 
@@ -2212,7 +2220,7 @@ RestoreHWState(ScrnInfoPtr pScrn)
    OUTREG(DPLL_A, pI830->saveDPLL_A);
    if (IS_I965G(pI830))
       OUTREG(DPLL_A_MD, pI830->saveDPLL_A_MD);
-   if(pI830->xf86_config.num_crtc == 2) {
+   if(xf86_config->num_crtc == 2) {
       OUTREG(FPB0, pI830->saveFPB0);
       OUTREG(FPB1, pI830->saveFPB1);
       OUTREG(DPLL_B, pI830->saveDPLL_B);
@@ -2237,7 +2245,7 @@ RestoreHWState(ScrnInfoPtr pScrn)
          OUTREG(PALETTE_A + (i << 2), pI830->savePaletteA[i]);
    }
 
-   if(pI830->xf86_config.num_crtc == 2) {
+   if(xf86_config->num_crtc == 2) {
       OUTREG(HTOTAL_B, pI830->saveHTOTAL_B);
       OUTREG(HBLANK_B, pI830->saveHBLANK_B);
       OUTREG(HSYNC_B, pI830->saveHSYNC_B);
@@ -2273,8 +2281,8 @@ RestoreHWState(ScrnInfoPtr pScrn)
    OUTREG(DSPACNTR, pI830->saveDSPACNTR);
    OUTREG(DSPBCNTR, pI830->saveDSPBCNTR);
 
-   for (i = 0; i < pI830->xf86_config.num_output; i++) {
-      xf86OutputPtr   output = pI830->xf86_config.output[i];
+   for (i = 0; i < xf86_config->num_output; i++) {
+      xf86OutputPtr   output = xf86_config->output[i];
       (*output->funcs->restore) (output);
    }
 
@@ -3097,6 +3105,7 @@ static Bool
 I830EnterVT(int scrnIndex, int flags)
 {
    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+   xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
    I830Ptr  pI830 = I830PTR(pScrn);
    int	    i;
 
@@ -3131,9 +3140,9 @@ I830EnterVT(int scrnIndex, int flags)
    ResetState(pScrn, FALSE);
    SetHWOperatingState(pScrn);
 
-   for (i = 0; i < pI830->xf86_config.num_crtc; i++)
+   for (i = 0; i < xf86_config->num_crtc; i++)
    {
-      xf86CrtcPtr	crtc = pI830->xf86_config.crtc[i];
+      xf86CrtcPtr	crtc = xf86_config->crtc[i];
 
       /* Mark that we'll need to re-set the mode for sure */
       memset(&crtc->curMode, 0, sizeof(crtc->curMode));
@@ -3271,6 +3280,7 @@ static Bool
 I830SaveScreen(ScreenPtr pScreen, int mode)
 {
    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+   xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
    I830Ptr pI830 = I830PTR(pScrn);
    Bool on = xf86IsUnblank(mode);
    CARD32 temp, ctrl, base, surf;
@@ -3279,7 +3289,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->xf86_config.num_crtc; i++) {
+      for (i = 0; i < xf86_config->num_crtc; i++) {
         if (i == 0) {
 	    ctrl = DSPACNTR;
 	    base = DSPABASE;
@@ -3289,7 +3299,7 @@ I830SaveScreen(ScreenPtr pScreen, int mo
 	    base = DSPBADDR;
 	    surf = DSPBSURF;
         }
-        if (pI830->xf86_config.crtc[i]->enabled) {
+        if (xf86_config->crtc[i]->enabled) {
 	   temp = INREG(ctrl);
 	   if (on)
 	      temp |= DISPLAY_PLANE_ENABLE;
@@ -3508,7 +3518,7 @@ i830MonitorDetectDebugger(ScrnInfoPtr pS
    if (!pScrn->vtSema)
       return 1000;
 
-   for (i = 0; i < pI830->xf86_config.num_output; i++) {
+   for (i = 0; i < xf86_config->num_output; i++) {
       enum output_status ret;
       char *result;
 
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index 4027a25..4307025 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -135,12 +135,13 @@ i830_lvds_mode_fixup(xf86OutputPtr outpu
 		     DisplayModePtr adjusted_mode)
 {
     ScrnInfoPtr pScrn = output->scrn;
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     I830Ptr pI830 = I830PTR(pScrn);
     I830CrtcPrivatePtr intel_crtc = output->crtc->driver_private;
     int i;
 
-    for (i = 0; i < pI830->xf86_config.num_output; i++) {
-	xf86OutputPtr other_output = pI830->xf86_config.output[i];
+    for (i = 0; i < xf86_config->num_output; i++) {
+	xf86OutputPtr other_output = xf86_config->output[i];
 
 	if (other_output != output && other_output->crtc == output->crtc) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
diff --git a/src/i830_randr.c b/src/i830_randr.c
index 2d986df..290cb10 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -495,13 +495,17 @@ xf86RandR12CrtcNotify (RRCrtcPtr	randr_c
     int			y;
     Rotation		rotation;
     int			numOutputs;
-    RROutputPtr		randr_outputs[XF86_MAX_OUTPUT];
+    RROutputPtr		*randr_outputs;
     RROutputPtr		randr_output;
     xf86CrtcPtr		crtc = randr_crtc->devPrivate;
     xf86OutputPtr	output;
     int			i, j;
     DisplayModePtr	curMode = &crtc->curMode;
+    Bool		ret;
 
+    randr_outputs = ALLOCATE_LOCAL(config->num_output * sizeof (RROutputPtr));
+    if (!randr_outputs)
+	return FALSE;
     x = crtc->x;
     y = crtc->y;
     rotation = RR_Rotate_0;
@@ -529,8 +533,10 @@ xf86RandR12CrtcNotify (RRCrtcPtr	randr_c
 	    }
 	}
     }
-    return RRCrtcNotify (randr_crtc, randr_mode, x, y,
-			 rotation, numOutputs, randr_outputs);
+    ret = RRCrtcNotify (randr_crtc, randr_mode, x, y,
+			rotation, numOutputs, randr_outputs);
+    DEALLOCATE_LOCAL(randr_outputs);
+    return ret;
 }
 
 static Bool
@@ -550,9 +556,10 @@ xf86RandR12CrtcSet (ScreenPtr	pScreen,
     Bool		changed = FALSE;
     Bool		pos_changed;
     int			o, ro;
-    xf86CrtcPtr		save_crtcs[XF86_MAX_OUTPUT];
+    xf86CrtcPtr		*save_crtcs;
     Bool		save_enabled = crtc->enabled;
 
+    save_crtcs = ALLOCATE_LOCAL(config->num_crtc * sizeof (xf86CrtcPtr));
     if ((mode != NULL) != crtc->enabled)
 	changed = TRUE;
     else if (mode && !xf86ModesEqual (&crtc->curMode, mode))
@@ -606,6 +613,7 @@ xf86RandR12CrtcSet (ScreenPtr	pScreen,
 		    xf86OutputPtr	output = config->output[o];
 		    output->crtc = save_crtcs[o];
 		}
+		DEALLOCATE_LOCAL(save_crtcs);
 		return FALSE;
 	    }
 	    crtc->desiredMode = *mode;
@@ -616,6 +624,7 @@ xf86RandR12CrtcSet (ScreenPtr	pScreen,
     }
     if (pos_changed && mode)
 	i830PipeSetBase(crtc, x, y);
+    DEALLOCATE_LOCAL(save_crtcs);
     return xf86RandR12CrtcNotify (randr_crtc);
 }
 
@@ -694,13 +703,15 @@ xf86RandR12SetInfo12 (ScreenPtr pScreen)
 {
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
     xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
-    RROutputPtr		clones[XF86_MAX_OUTPUT];
-    RRCrtcPtr		crtcs[XF86_MAX_CRTC];
+    RROutputPtr		*clones;
+    RRCrtcPtr		*crtcs;
     int			ncrtc;
     int			o, c, l;
     RRCrtcPtr		randr_crtc;
     int			nclone;
     
+    clones = ALLOCATE_LOCAL(config->num_output * sizeof (RROutputPtr));
+    crtcs = ALLOCATE_LOCAL (config->num_crtc * sizeof (RRCrtcPtr));
     for (o = 0; o < config->num_output; o++)
     {
 	xf86OutputPtr	output = config->output[o];
@@ -716,7 +727,11 @@ xf86RandR12SetInfo12 (ScreenPtr pScreen)
 	    randr_crtc = NULL;
 
 	if (!RROutputSetCrtcs (output->randr_output, crtcs, ncrtc))
+	{
+	    DEALLOCATE_LOCAL (crtcs);
+	    DEALLOCATE_LOCAL (clones);
 	    return FALSE;
+	}
 
 	RROutputSetCrtc (output->randr_output, randr_crtc);
 	RROutputSetPhysicalSize(output->randr_output, 
@@ -750,8 +765,14 @@ xf86RandR12SetInfo12 (ScreenPtr pScreen)
 		clones[nclone++] = clone->randr_output;
 	}
 	if (!RROutputSetClones (output->randr_output, clones, nclone))
+	{
+	    DEALLOCATE_LOCAL (crtcs);
+	    DEALLOCATE_LOCAL (clones);
 	    return FALSE;
+	}
     }
+    DEALLOCATE_LOCAL (crtcs);
+    DEALLOCATE_LOCAL (clones);
     return TRUE;
 }
 
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 90a62c0..fc17efd 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -951,12 +951,12 @@ i830_sdvo_dump_device(xf86OutputPtr outp
 void
 i830_sdvo_dump(ScrnInfoPtr pScrn)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     int	i;
 
-    for (i = 0; i < pI830->xf86_config.num_output; i++) 
+    for (i = 0; i < xf86_config->num_output; i++) 
     {
-	xf86OutputPtr	output = pI830->xf86_config.output[i];
+	xf86OutputPtr	output = xf86_config->output[i];
 	I830OutputPrivatePtr	intel_output = output->driver_private;
 	
 	if (intel_output->type == I830_OUTPUT_SDVO)
@@ -995,7 +995,7 @@ static DisplayModePtr
 i830_sdvo_get_modes(xf86OutputPtr output)
 {
     ScrnInfoPtr pScrn = output->scrn;
-    I830Ptr pI830 = I830PTR(pScrn);
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     DisplayModePtr modes;
     xf86OutputPtr crt;
 
@@ -1008,7 +1008,7 @@ i830_sdvo_get_modes(xf86OutputPtr output
      * but it does load-detect as connected.  So, just steal the DDC bits from
      * analog when we fail at finding it the right way.
      */
-    crt = pI830->xf86_config.output[0];
+    crt = xf86_config->output[0];
     if (crt->funcs->detect(crt) == XF86OutputStatusDisconnected) {
 	return crt->funcs->get_modes(crt);
     }
diff --git a/src/i830_tv.c b/src/i830_tv.c
index 42c2aad..ccb6aac 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -356,11 +356,11 @@ i830_tv_mode_fixup(xf86OutputPtr output,
 		 DisplayModePtr adjusted_mode)
 {
     ScrnInfoPtr pScrn = output->scrn;
-    I830Ptr pI830 = I830PTR(pScrn);
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     int i;
 
-    for (i = 0; i < pI830->xf86_config.num_output; i++) {
-	xf86OutputPtr other_output = pI830->xf86_config.output[i];
+    for (i = 0; i < xf86_config->num_output; i++) {
+	xf86OutputPtr other_output = xf86_config->output[i];
 
 	if (other_output != output && other_output->crtc == output->crtc) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
diff --git a/src/i830_video.c b/src/i830_video.c
index 5979415..d10fd16 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -3514,6 +3514,7 @@ void
 i830_crtc_dpms_video(xf86CrtcPtr crtc, Bool on)
 {
    ScrnInfoPtr pScrn = crtc->scrn;
+   xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
    I830Ptr pI830 = I830PTR(pScrn);
    I830PortPrivPtr pPriv;
    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
@@ -3551,7 +3552,7 @@ i830_crtc_dpms_video(xf86CrtcPtr crtc, B
       }
 
       /* Check we have an LFP connected */
-      if (i830PipeHasType(pI830->xf86_config.crtc[pPriv->pipe],
+      if (i830PipeHasType(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 25657e6..6b73264 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -37,6 +37,36 @@
 #include "X11/extensions/render.h"
 
 /*
+ * Initialize xf86CrtcConfig structure
+ */
+
+int xf86CrtcConfigPrivateIndex = -1;
+
+void
+xf86CrtcConfigInit (ScrnInfoPtr scrn)
+{
+    xf86CrtcConfigPtr	config;
+    
+    if (xf86CrtcConfigPrivateIndex == -1)
+	xf86CrtcConfigPrivateIndex = xf86AllocateScrnInfoPrivateIndex();
+    config = xnfcalloc (1, sizeof (xf86CrtcConfigRec));
+    scrn->privates[xf86CrtcConfigPrivateIndex].ptr = config;
+}
+ 
+void
+xf86CrtcSetSizeRange (ScrnInfoPtr scrn,
+		      int minWidth, int minHeight,
+		      int maxWidth, int maxHeight)
+{
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
+
+    config->minWidth = minWidth;
+    config->minHeight = minHeight;
+    config->maxWidth = maxWidth;
+    config->maxHeight = maxHeight;
+}
+
+/*
  * Crtc functions
  */
 xf86CrtcPtr
@@ -44,7 +74,7 @@ xf86CrtcCreate (ScrnInfoPtr		scrn,
 		const xf86CrtcFuncsRec	*funcs)
 {
     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
-    xf86CrtcPtr		crtc;
+    xf86CrtcPtr		crtc, *crtcs;
 
     crtc = xcalloc (sizeof (xf86CrtcRec), 1);
     if (!crtc)
@@ -54,6 +84,17 @@ xf86CrtcCreate (ScrnInfoPtr		scrn,
 #ifdef RANDR_12_INTERFACE
     crtc->randr_crtc = NULL;
 #endif
+    if (xf86_config->crtc)
+	crtcs = xrealloc (xf86_config->crtc,
+			  (xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr));
+    else
+	crtcs = xalloc ((xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr));
+    if (!crtcs)
+    {
+	xfree (crtc);
+	return NULL;
+    }
+    xf86_config->crtc = crtcs;
     xf86_config->crtc[xf86_config->num_crtc++] = crtc;
     return crtc;
 }
@@ -85,7 +126,7 @@ xf86OutputCreate (ScrnInfoPtr		    scrn,
 		  const xf86OutputFuncsRec *funcs,
 		  const char		    *name)
 {
-    xf86OutputPtr	output;
+    xf86OutputPtr	output, *outputs;
     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
     int			len = strlen (name);
 
@@ -100,6 +141,17 @@ xf86OutputCreate (ScrnInfoPtr		    scrn,
 #ifdef RANDR_12_INTERFACE
     output->randr_output = NULL;
 #endif
+    if (xf86_config->output)
+	outputs = xrealloc (xf86_config->output,
+			  (xf86_config->num_output + 1) * sizeof (xf86OutputPtr));
+    else
+	outputs = xalloc ((xf86_config->num_output + 1) * sizeof (xf86OutputPtr));
+    if (!outputs)
+    {
+	xfree (output);
+	return NULL;
+    }
+    xf86_config->output = outputs;
     xf86_config->output[xf86_config->num_output++] = output;
     return output;
 }
diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h
index f2c2429..9294ccc 100644
--- a/src/i830_xf86Crtc.h
+++ b/src/i830_xf86Crtc.h
@@ -307,26 +307,39 @@ struct _xf86Output {
 #endif
 };
 
-/* XXX yes, static allocation is a kludge */
-#define XF86_MAX_CRTC	4
-#define XF86_MAX_OUTPUT	16
-
 typedef struct _xf86CrtcConfig {
-   int			num_output;
-   xf86OutputPtr	output[XF86_MAX_OUTPUT];
-   /**
-    * compat_output is used whenever we deal
-    * with legacy code that only understands a single
-    * output. pScrn->modes will be loaded from this output,
-    * adjust frame will whack this output, etc.
-    */
-   int			compat_output;
-    
-   int			num_crtc;
-   xf86CrtcPtr		crtc[XF86_MAX_CRTC];
+    int			num_output;
+    xf86OutputPtr	*output;
+    /**
+     * compat_output is used whenever we deal
+     * with legacy code that only understands a single
+     * output. pScrn->modes will be loaded from this output,
+     * adjust frame will whack this output, etc.
+     */
+    int			compat_output;
+
+    int			num_crtc;
+    xf86CrtcPtr		*crtc;
+
+    int			minWidth, minHeight;
+    int			maxWidth, maxHeight;
 } xf86CrtcConfigRec, *xf86CrtcConfigPtr;
 
-#define XF86_CRTC_CONFIG_PTR(p)	((xf86CrtcConfigPtr) ((p)->driverPrivate))
+extern int xf86CrtcConfigPrivateIndex;
+
+#define XF86_CRTC_CONFIG_PTR(p)	((xf86CrtcConfigPtr) ((p)->privates[xf86CrtcConfigPrivateIndex].ptr))
+
+/*
+ * Initialize xf86CrtcConfig structure
+ */
+
+void
+xf86CrtcConfigInit (ScrnInfoPtr		scrn);
+
+void
+xf86CrtcSetSizeRange (ScrnInfoPtr scrn,
+		      int minWidth, int minHeight,
+		      int maxWidth, int maxHeight);
 
 /*
  * Crtc functions
diff-tree 0f6addc8a6aeb9bd041d0f8e8e5850e76764ba51 (from parents)
Merge: 001e272437a0247ffbc4b9ff8a3f2b437cf4c533 3fa5b3998353518c40e2fb0c28b425ee22c8d625
Author: Keith Packard <keithp at bouzouki.jf.intel.com>
Date:   Wed Dec 13 12:10:31 2006 -0800

    Merge branch 'modesetting-origin' into modesetting

diff-tree 001e272437a0247ffbc4b9ff8a3f2b437cf4c533 (from df0a5a25aa72563a33731f8063602dd7faad8459)
Author: Keith Packard <keithp at bouzouki.jf.intel.com>
Date:   Wed Dec 13 12:08:58 2006 -0800

    Auto-detect working TV output by checking TV regs functionality.
    
    We can't figure out which chips are supposed to have TV out, so instead we
    prod the TV_DAC register to see if it will hold the value written to it, if
    not, we assume the chip doesn't have TV out.

diff --git a/src/i830_tv.c b/src/i830_tv.c
index b6cc2c9..42c2aad 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -583,8 +583,11 @@ i830_tv_detect_type (xf86CrtcPtr    crtc
 	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;
+		   TVDAC_C_SENSE_CTL |
+		   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);
@@ -612,7 +615,7 @@ i830_tv_detect_type (xf86CrtcPtr    crtc
 	type = TV_TYPE_COMPONENT;
     } else {
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		   "Couldn't detect TV connection\n");
+		   "No TV connection detected\n");
 	type = TV_TYPE_NONE;
     }
     
@@ -730,10 +733,34 @@ i830_tv_init(ScrnInfoPtr pScrn)
     xf86OutputPtr	    output;
     I830OutputPrivatePtr    intel_output;
     struct i830_tv_priv	    *dev_priv;
+    CARD32		    tv_dac_on, tv_dac_off, save_tv_dac;
  
     if ((INREG(TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED)
 	return;
 
+    /*
+     * Sanity check the TV output by checking to see if the
+     * DAC register holds a value
+     */
+    save_tv_dac = INREG(TV_DAC);
+    
+    OUTREG(TV_DAC, save_tv_dac | TVDAC_STATE_CHG_EN);
+    tv_dac_on = INREG(TV_DAC);
+    
+    OUTREG(TV_DAC, save_tv_dac & ~TVDAC_STATE_CHG_EN);
+    tv_dac_off = INREG(TV_DAC);
+    
+    OUTREG(TV_DAC, save_tv_dac);
+    
+    /*
+     * If the register does not hold the state change enable
+     * bit, (either as a 0 or a 1), assume it doesn't really
+     * exist
+     */
+    if ((tv_dac_on & TVDAC_STATE_CHG_EN) == 0 || 
+	(tv_dac_off & TVDAC_STATE_CHG_EN) != 0)
+	return;
+    
     output = xf86OutputCreate (pScrn, &i830_tv_output_funcs, "TV");
     
     if (!output)
diff-tree 3fa5b3998353518c40e2fb0c28b425ee22c8d625 (from e27372e85a007d8a7e31678dbdb62755c22918bf)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Dec 13 11:54:36 2006 -0800

    Add magic double-write of the dpll register to fix mac mini cold boot.

diff --git a/src/i830_display.c b/src/i830_display.c
index c111145..37a6e32 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -758,6 +758,15 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
 
     OUTREG(fp_reg, fp);
     OUTREG(dpll_reg, dpll);
+
+    /* Magic re-write of the register for the Mac Mini.  Without this, the
+     * first X invocation after a cold boot will stick in 4x pixel multiply
+     * mode.  Alternatives that don't work include sleeping and doing an
+     * INREG for presumable pci write posting magic before and after the dpll
+     * write above.
+     */
+    OUTREG(dpll_reg, dpll);
+
     if (IS_I965G(pI830)) {
 	int sdvo_pixel_multiply = adjusted_mode->Clock / mode->Clock;
 	OUTREG(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) |
diff-tree e27372e85a007d8a7e31678dbdb62755c22918bf (from df0a5a25aa72563a33731f8063602dd7faad8459)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Dec 13 00:26:27 2006 -0800

    Add some caution with PCI write posting and DPLL delays to i830_crtc_dpms.
    
    While it doesn't specifically help/hurt my test case, we've seen enough
    mysterious behavior that caution is probably warranted.

diff --git a/src/i830_display.c b/src/i830_display.c
index e4d8e9f..c111145 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -507,6 +507,7 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mod
 	/* Enable the DPLL */
 	temp = INREG(dpll_reg);
 	OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE);
+	(void)INREG(dpll_reg); /* write posting */
 
 	/* Wait for the clocks to stabilize. */
 	usleep(150);
@@ -538,6 +539,7 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mod
 
 	/* Flush the plane changes */
 	OUTREG(dspbase_reg, INREG(dspbase_reg));
+	(void)INREG(dspbase_reg); /* write posting */
 
 	if (!IS_I9XX(pI830)) {
 	    /* Wait for vblank for the disable to take effect */
@@ -547,12 +549,17 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mod
 	/* Next, disable display pipes */
 	temp = INREG(pipeconf_reg);
 	OUTREG(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
+	(void)INREG(pipeconf_reg); /* write posting */
 
 	/* Wait for vblank for the disable to take effect. */
 	i830WaitForVblank(pScrn);
 
 	temp = INREG(dpll_reg);
 	OUTREG(dpll_reg, temp & ~DPLL_VCO_ENABLE);
+	(void)INREG(dpll_reg); /* write posting */
+
+	/* Wait for the clocks to turn off. */
+	usleep(150);
 	break;
     }
 }
diff-tree df0a5a25aa72563a33731f8063602dd7faad8459 (from 4cdcaac26b3f425ec8fcc2fd3eaa9bfb7a137422)
Author: Keith Packard <keithp at bouzouki.jf.intel.com>
Date:   Wed Dec 13 11:38:18 2006 -0800

    Rename outputs to TMDS-1/TMDS-2, LVDS, TV and VGA.
    
    These names are reasonably short and describe the connector rather than the
    target media, but we don't appear to have any way to determine what is on
    the other end of the wire. More importantly, they're all unique now.

diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index 25ced63..ed8d1c7 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -246,7 +246,7 @@ i830_dvo_init(ScrnInfoPtr pScrn)
     int			    ret;
 
     output = xf86OutputCreate (pScrn, &i830_dvo_output_funcs,
-				   "ADD AGP card");
+				   "TMDS");
     if (!output)
 	return;
     intel_output = xnfcalloc (sizeof (I830OutputPrivateRec), 1);
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index 90f785e..4027a25 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -311,7 +311,7 @@ i830_lvds_init(ScrnInfoPtr pScrn)
 	}
    }
 
-    output = xf86OutputCreate (pScrn, &i830_lvds_output_funcs, "Built-in LCD panel");
+    output = xf86OutputCreate (pScrn, &i830_lvds_output_funcs, "LVDS");
     if (!output)
 	return;
     intel_output = xnfcalloc (sizeof (I830OutputPrivateRec), 1);
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index da4df92..90a62c0 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -1053,6 +1053,9 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
     int			    i;
     unsigned char	    ch[0x40];
     I2CBusPtr		    i2cbus = NULL, ddcbus;
+    char		    name[60];
+    char		    *name_prefix;
+    char		    *name_suffix;
 
     output = xf86OutputCreate (pScrn, &i830_sdvo_output_funcs,
 			       "ADD2 PCIE card");
@@ -1087,9 +1090,11 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
     if (output_device == SDVOB) {
 	dev_priv->d.DevName = "SDVO Controller B";
 	dev_priv->d.SlaveAddr = 0x70;
+	name_suffix="-1";
     } else {
 	dev_priv->d.DevName = "SDVO Controller C";
 	dev_priv->d.SlaveAddr = 0x72;
+	name_suffix="-2";
     }
     dev_priv->d.pI2CBus = i2cbus;
     dev_priv->d.DriverPrivate.ptr = output;
@@ -1158,11 +1163,13 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
     {
 	dev_priv->active_outputs = SDVO_OUTPUT_TMDS0;
         output->subpixel_order = SubPixelHorizontalRGB;
+	name_prefix="TMDS";
     }
     else if (dev_priv->caps.output_flags & SDVO_OUTPUT_TMDS1)
     {
 	dev_priv->active_outputs = SDVO_OUTPUT_TMDS1;
         output->subpixel_order = SubPixelHorizontalRGB;
+	name_prefix="TMDS";
     }
     else
     {
@@ -1174,6 +1181,9 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
 		   SDVO_NAME(dev_priv),
 		   bytes[0], bytes[1]);
     }
+    strcpy (name, name_prefix);
+    strcat (name, name_suffix);
+    xf86OutputRename (output, name);
     
     /* Set the input timing to the screen. Assume always input 0. */
     i830_sdvo_set_target_input(output, TRUE, FALSE);
diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index 6f96d44..25657e6 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -105,6 +105,21 @@ xf86OutputCreate (ScrnInfoPtr		    scrn,
 }
 
 void
+xf86OutputRename (xf86OutputPtr output, const char *name)
+{
+    int	    len = strlen(name);
+    char    *newname = xalloc (len + 1);
+    
+    if (!newname)
+	return;	/* so sorry... */
+    
+    strcpy (newname, name);
+    if (output->name != (char *) (output + 1))
+	xfree (output->name);
+    output->name = newname;
+}
+
+void
 xf86OutputDestroy (xf86OutputPtr output)
 {
     ScrnInfoPtr		scrn = output->scrn;
@@ -123,6 +138,8 @@ xf86OutputDestroy (xf86OutputPtr output)
 	    xf86_config->num_output--;
 	    break;
 	}
+    if (output->name != (char *) (output + 1))
+	xfree (output->name);
     xfree (output);
 }
 
diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h
index 042cb2f..f2c2429 100644
--- a/src/i830_xf86Crtc.h
+++ b/src/i830_xf86Crtc.h
@@ -367,6 +367,9 @@ xf86OutputCreate (ScrnInfoPtr		scrn,
 		      const char	*name);
 
 void
+xf86OutputRename (xf86OutputPtr output, const char *name);
+
+void
 xf86OutputDestroy (xf86OutputPtr	output);
 
 void
diff-tree 4cdcaac26b3f425ec8fcc2fd3eaa9bfb7a137422 (from 9dd1520421dcb8c7f36a684f3d2ffb6b42a6671a)
Author: Keith Packard <keithp at mandolin.keithp.com>
Date:   Tue Dec 12 23:26:00 2006 -0800

    Write dpll_md register while updating dpll as that appears to be required.
    
    SDVO multiplier on 965 is in the dpll_md register; for some reason, that
    needs to be written along with the dpll value or the multiplier doesn't get
    set correctly.

diff --git a/src/i830_display.c b/src/i830_display.c
index 8da5131..e4d8e9f 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -752,11 +752,9 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
     OUTREG(fp_reg, fp);
     OUTREG(dpll_reg, dpll);
     if (IS_I965G(pI830)) {
-	/* Set the SDVO multiplier/divider to 1x for the sake of analog output.
-	 * It will be updated by the SDVO code if SDVO had fixed up the clock
-	 * for a higher multiplier.
-	 */
-	OUTREG(dpll_md_reg, 0);
+	int sdvo_pixel_multiply = adjusted_mode->Clock / mode->Clock;
+	OUTREG(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) |
+	       ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT));
     }
 
     OUTREG(htot_reg, (adjusted_mode->CrtcHDisplay - 1) |
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 68ee941..da4df92 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -557,7 +557,6 @@ i830_sdvo_mode_set(xf86OutputPtr output,
     xf86CrtcPtr	    crtc = output->crtc;
     I830CrtcPrivatePtr	    intel_crtc = crtc->driver_private;
     CARD32 sdvox;
-    int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD;
     int sdvo_pixel_multiply;
     CARD16 width, height;
     CARD16 h_blank_len, h_sync_len, v_blank_len, v_sync_len;
@@ -663,8 +662,7 @@ i830_sdvo_mode_set(xf86OutputPtr output,
 
     sdvo_pixel_multiply = i830_sdvo_get_pixel_multiplier(mode);
     if (IS_I965G(pI830)) {
-	OUTREG(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) |
-	       ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT));
+	/* done in crtc_mode_set as the dpll_md reg must be written early */
     } else if (IS_I945G(pI830) || IS_I945GM(pI830)) {
 	/* done in crtc_mode_set as it lives inside the dpll register */
     } else {
diff-tree 9dd1520421dcb8c7f36a684f3d2ffb6b42a6671a (from parents)
Merge: d57a25815398ae83eae8bdcb3a1b607760aa30b6 63bf48481d4e5e285fdfe7037ea4150283163a54
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Tue Dec 12 22:52:59 2006 -0800

    Merge branch 'modesetting-origin' into modesetting

diff-tree d57a25815398ae83eae8bdcb3a1b607760aa30b6 (from 41444183b59ed84c09749ca89afbef036d42ec5f)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Tue Dec 12 22:48:21 2006 -0800

    Elide duplicate modes in pScrn->monitor.
    
    xf86DDCMonitorSet dumps all of the DDC-discovered modes
    into the monitor mode list without checking to see if they
    are already present. This provides an ever-changing list of
    modes for outputs which have no DDC and which simply duplicate the monitor
    mode list.

diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index a222382..6f96d44 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -337,6 +337,30 @@ xf86DefaultScreenLimits (ScrnInfoPtr pSc
     *heightp = height;
 }
 
+/*
+ * XXX walk the monitor mode list and prune out duplicates that
+ * are inserted by xf86DDCMonitorSet. In an ideal world, that
+ * function would do this work by itself.
+ */
+
+static void
+xf86PruneDuplicateMonitorModes (MonPtr Monitor)
+{
+    DisplayModePtr  master, clone, next;
+
+    for (master = Monitor->Modes; 
+	 master && master != Monitor->Last; 
+	 master = master->next)
+    {
+	for (clone = master->next; clone && clone != Monitor->Modes; clone = next)
+	{
+	    next = clone->next;
+	    if (xf86ModesEqual (master, clone))
+		xf86DeleteMode (&Monitor->Modes, clone);
+	}
+    }
+}
+
 void
 xf86ProbeOutputModes (ScrnInfoPtr pScrn)
 {
@@ -344,6 +368,9 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn)
     Bool		properties_set = FALSE;
     int			o;
 
+    /* Elide duplicate modes before defaulting code uses them */
+    xf86PruneDuplicateMonitorModes (pScrn->monitor);
+    
     /* Probe the list of modes for each output. */
     for (o = 0; o < config->num_output; o++) 
     {
diff-tree 63bf48481d4e5e285fdfe7037ea4150283163a54 (from 41444183b59ed84c09749ca89afbef036d42ec5f)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Dec 12 22:42:41 2006 -0800

    Correct typo in mac mini hack, and return modes when the hack is unnecessary.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 895639e..68ee941 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -1003,7 +1003,7 @@ i830_sdvo_get_modes(xf86OutputPtr output
 
     modes = i830_ddc_get_modes(output);
     if (modes != NULL)
-	return NULL;
+	return modes;
 
     /* Mac mini hack.  On this device, I get DDC through the analog, which
      * load-detects as disconnected.  I fail to DDC through the SDVO DDC,
diff-tree 41444183b59ed84c09749ca89afbef036d42ec5f (from 7ed1b05922c07ff45a5794a992fd3d59ab55aa73)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Dec 12 18:08:57 2006 -0800

    Replace custom, partially broken DPMS implementation with a generic one.

diff --git a/src/i830_display.c b/src/i830_display.c
index f0aac15..8da5131 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -478,6 +478,12 @@ i830PipeInUse (xf86CrtcPtr crtc)
     return FALSE;
 }
 
+/**
+ * Sets the power management mode of the pipe and plane.
+ *
+ * This code should probably grow support for turning the cursor off and back
+ * on appropriately at the same time as we're turning the pipe off/on.
+ */
 static void
 i830_crtc_dpms(xf86CrtcPtr crtc, int mode)
 {
diff --git a/src/i830_driver.c b/src/i830_driver.c
index d8a9c9b..7ec5559 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -314,8 +314,6 @@ const char *i830_output_type_names[] = {
    "TVOUT",
 };
 
-static void I830DisplayPowerManagementSet(ScrnInfoPtr pScrn,
-					  int PowerManagementMode, int flags);
 static void i830AdjustFrame(int scrnIndex, int x, int y, int flags);
 static Bool I830CloseScreen(int scrnIndex, ScreenPtr pScreen);
 static Bool I830SaveScreen(ScreenPtr pScreen, int unblack);
@@ -2863,7 +2861,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       return FALSE;
    }
 
-   xf86DPMSInit(pScreen, I830DisplayPowerManagementSet, 0);
+   xf86DPMSInit(pScreen, xf86DPMSSet, 0);
 
 #ifdef I830_XV
    /* Init video */
@@ -3319,55 +3317,6 @@ I830SaveScreen(ScreenPtr pScreen, int mo
    return TRUE;
 }
 
-/* Use the VBE version when available. */
-static void
-I830DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
-			      int flags)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   int i;
-   CARD32 temp, ctrl, base;
-
-   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->xf86_config.num_crtc; i++) 
-   {
-      xf86CrtcPtr	   crtc = pI830->xf86_config.crtc[i];
-      
-      if (i == 0) {
-         ctrl = DSPACNTR;
-         base = DSPABASE;
-      } else {
-         ctrl = DSPBCNTR;
-         base = DSPBADDR;
-      }
-      /* XXX pipe disable too? */
-      if (crtc->enabled) {
-	   temp = INREG(ctrl);
-	   if (PowerManagementMode == DPMSModeOn)
-	      temp |= DISPLAY_PLANE_ENABLE;
-	   else
-	      temp &= ~DISPLAY_PLANE_ENABLE;
-	   OUTREG(ctrl, temp);
-	   /* Flush changes */
-	   temp = INREG(base);
-	   OUTREG(base, temp);
-      }
-   }
-
-   if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn) {
-      if (PowerManagementMode == DPMSModeOn)
-         pI830->CursorInfoRec->ShowCursor(pScrn);
-      else
-         pI830->CursorInfoRec->HideCursor(pScrn);
-      pI830->cursorOn = TRUE;
-   }
-}
-
 static Bool
 I830CloseScreen(int scrnIndex, ScreenPtr pScreen)
 {
diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index 448d4f9..a222382 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -590,3 +590,38 @@ xf86InitialConfiguration (ScrnInfoPtr	  
     xfree (modes);
     return TRUE;
 }
+
+/**
+ * Set the DPMS power mode of all outputs and CRTCs.
+ *
+ * If the new mode is off, it will turn off outputs and then CRTCs.
+ * Otherwise, it will affect CRTCs before outputs.
+ */
+void
+xf86DPMSSet(ScrnInfoPtr pScrn, int mode, int flags)
+{
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int			i;
+
+    if (mode == DPMSModeOff) {
+	for (i = 0; i < config->num_output; i++) {
+	    xf86OutputPtr output = config->output[i];
+	    if (output->crtc != NULL)
+		(*output->funcs->dpms) (output, mode);
+	}
+    }
+
+    for (i = 0; i < config->num_crtc; i++) {
+	xf86CrtcPtr crtc = config->crtc[i];
+	if (crtc->enabled)
+	    (*crtc->funcs->dpms) (crtc, mode);
+    }
+
+    if (mode != DPMSModeOff) {
+	for (i = 0; i < config->num_output; i++) {
+	    xf86OutputPtr output = config->output[i];
+	    if (output->crtc != NULL)
+		(*output->funcs->dpms) (output, mode);
+	}
+    }
+}
diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h
index 21fc244..042cb2f 100644
--- a/src/i830_xf86Crtc.h
+++ b/src/i830_xf86Crtc.h
@@ -378,4 +378,7 @@ xf86SetScrnInfoModes (ScrnInfoPtr pScrn)
 Bool
 xf86InitialConfiguration (ScrnInfoPtr pScrn);
 
+void
+xf86DPMSSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags);
+
 #endif /* _XF86CRTC_H_ */
diff-tree 7ed1b05922c07ff45a5794a992fd3d59ab55aa73 (from 9776f6c68b3cdd5585e58e677c1b1318d9aedaf4)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Dec 12 16:03:52 2006 -0800

    Fix mac mini SDVO output: write the SDVO[BC] enabled register state twice.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 7936abd..895639e 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -696,6 +696,12 @@ i830_sdvo_dpms(xf86OutputPtr output, int
 
 	i830_sdvo_set_active_outputs(output, dev_priv->active_outputs);
 
+	/* Do it again!  If we remove this below register write, or the exact
+	 * same one 2 lines up, the mac mini SDVO output doesn't turn on.
+	 */
+	OUTREG(dev_priv->output_device,
+	       INREG(dev_priv->output_device) | SDVO_ENABLE);
+
 	for (i = 0; i < 2; i++)
 	    i830WaitForVblank(pScrn);
 
diff-tree 9776f6c68b3cdd5585e58e677c1b1318d9aedaf4 (from 54823ac39ce9666099d69196694643f04123cb4d)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Dec 12 16:02:47 2006 -0800

    Flush the plane changes in i830_crtc_dpms()
    
    Otherwise, the changes may not have taken effect.

diff --git a/src/i830_display.c b/src/i830_display.c
index f05b5c7..f0aac15 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -487,6 +487,7 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mod
     int pipe = intel_crtc->pipe;
     int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
     int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
+    int dspbase_reg = (pipe == 0) ? DSPABASE : DSPBBASE;
     int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
     CARD32 temp;
 
@@ -512,6 +513,9 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mod
 	temp = INREG(dspcntr_reg);
 	OUTREG(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE);
 
+	/* Flush the plane changes */
+	OUTREG(dspbase_reg, INREG(dspbase_reg));
+
 	/* Give the overlay scaler a chance to enable if it's on this pipe */
 	i830_crtc_dpms_video(crtc, TRUE);
 	break;
@@ -526,6 +530,9 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mod
 	/* Disable the VGA plane that we never use */
 	OUTREG(VGACNTRL, VGA_DISP_DISABLE);
 
+	/* Flush the plane changes */
+	OUTREG(dspbase_reg, INREG(dspbase_reg));
+
 	if (!IS_I9XX(pI830)) {
 	    /* Wait for vblank for the disable to take effect */
 	    i830WaitForVblank(pScrn);
diff-tree 54823ac39ce9666099d69196694643f04123cb4d (from ec45d7274333cccd20ad080facc8e995ad7b26b0)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Dec 12 14:38:08 2006 -0800

    Move the SDVO sync detection to after we've turned the port on.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 8619d02..7936abd 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -556,12 +556,9 @@ i830_sdvo_mode_set(xf86OutputPtr output,
     struct i830_sdvo_priv   *dev_priv = intel_output->dev_priv;
     xf86CrtcPtr	    crtc = output->crtc;
     I830CrtcPrivatePtr	    intel_crtc = crtc->driver_private;
-    Bool input1, input2;
     CARD32 sdvox;
     int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD;
     int sdvo_pixel_multiply;
-    int i;
-    CARD8 status;
     CARD16 width, height;
     CARD16 h_blank_len, h_sync_len, v_blank_len, v_sync_len;
     CARD16 h_sync_offset, v_sync_offset;
@@ -675,18 +672,6 @@ i830_sdvo_mode_set(xf86OutputPtr output,
     }
 
     OUTREG(dev_priv->output_device, sdvox);
-
-    for (i = 0; i < 2; i++)
-	i830WaitForVblank(pScrn);
-
-    status = i830_sdvo_get_trained_inputs(output, &input1, &input2);
-
-    /* Warn if the device reported failure to sync. */
-    if (status == SDVO_CMD_STATUS_SUCCESS && !input1) {
-	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		   "First %s output reported failure to sync\n",
-		   SDVO_NAME(dev_priv));
-    }
 }
 
 static void
@@ -699,10 +684,29 @@ i830_sdvo_dpms(xf86OutputPtr output, int
 
     if (mode != DPMSModeOn) {
 	i830_sdvo_set_active_outputs(output, 0);
-	OUTREG(dev_priv->output_device, INREG(dev_priv->output_device) & ~SDVO_ENABLE);
+	OUTREG(dev_priv->output_device,
+	       INREG(dev_priv->output_device) & ~SDVO_ENABLE);
     } else {
-	OUTREG(dev_priv->output_device, INREG(dev_priv->output_device) | SDVO_ENABLE);
+	Bool input1, input2;
+	int i;
+	CARD8 status;
+
+	OUTREG(dev_priv->output_device,
+	       INREG(dev_priv->output_device) | SDVO_ENABLE);
+
 	i830_sdvo_set_active_outputs(output, dev_priv->active_outputs);
+
+	for (i = 0; i < 2; i++)
+	    i830WaitForVblank(pScrn);
+
+	status = i830_sdvo_get_trained_inputs(output, &input1, &input2);
+
+	/* Warn if the device reported failure to sync. */
+	if (status == SDVO_CMD_STATUS_SUCCESS && !input1) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "First %s output reported failure to sync\n",
+		       SDVO_NAME(dev_priv));
+	}
     }
 }
 
diff-tree ec45d7274333cccd20ad080facc8e995ad7b26b0 (from 838af10b85ee8c085c6d2c4fbe18fd90b2be9d3f)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Dec 12 13:54:49 2006 -0800

    Extend the error state reporting to cover ESR and decode PGTBL_ERR for 945.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index ce8407d..7c85cff 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -398,8 +398,11 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define EIR               0x20B0
 #define EMR               0x20B4
 #define ESR               0x20B8
-#define IP_ERR                    0x0001
-#define ERROR_RESERVED            0xffc6
+# define ERR_VERTEX_MAX				(1 << 5) /* lpt/cst */
+# define ERR_PGTBL_ERROR			(1 << 4)
+# define ERR_DISPLAY_OVERLAY_UNDERRUN		(1 << 3)
+# define ERR_MAIN_MEMORY_REFRESH		(1 << 2)
+# define ERR_INSTRUCTION_ERROR			(1 << 0)
 
 
 /* Interrupt Control Registers 
@@ -507,8 +510,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define PGETBL_SIZE_256KB   (1 << 1)
 #define PGETBL_SIZE_128KB   (2 << 1)
 
-/* Register containing pge table error results, p276
+/** @defgroup PGE_ERR
+ * @{
  */
+/** Page table debug register for i845 */
 #define PGE_ERR          0x2024
 #define PGE_ERR_ADDR_MASK   0xFFFFF000
 #define PGE_ERR_ID_MASK     0x00000038
@@ -528,8 +533,33 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define PGE_ERR_ILLEGAL_TRX 0x00000004
 #define PGE_ERR_LOCAL_MEM   0x00000005
 #define PGE_ERR_TILED       0x00000006
+/** @} */
 
-
+/** @defgroup PGTBL_ER
+ * @{
+ */
+/** Page table debug register for i945 */
+# define PGTBL_ER	0x2024
+# define PGTBL_ERR_MT_TILING			(1 << 27)
+# define PGTBL_ERR_MT_GTT_PTE			(1 << 26)
+# define PGTBL_ERR_LC_TILING			(1 << 25)
+# define PGTBL_ERR_LC_GTT_PTE			(1 << 24)
+# define PGTBL_ERR_BIN_VERTEXDATA_GTT_PTE	(1 << 23)
+# define PGTBL_ERR_BIN_INSTRUCTION_GTT_PTE	(1 << 22)
+# define PGTBL_ERR_CS_VERTEXDATA_GTT_PTE	(1 << 21)
+# define PGTBL_ERR_CS_INSTRUCTION_GTT_PTE	(1 << 20)
+# define PGTBL_ERR_CS_GTT		(1 << 19)
+# define PGTBL_ERR_OVERLAY_TILING		(1 << 18)
+# define PGTBL_ERR_OVERLAY_GTT_PTE		(1 << 16)
+# define PGTBL_ERR_DISPC_TILING			(1 << 14)
+# define PGTBL_ERR_DISPC_GTT_PTE		(1 << 12)
+# define PGTBL_ERR_DISPB_TILING			(1 << 10)
+# define PGTBL_ERR_DISPB_GTT_PTE		(1 << 8)
+# define PGTBL_ERR_DISPA_TILING			(1 << 6)
+# define PGTBL_ERR_DISPA_GTT_PTE		(1 << 4)
+# define PGTBL_ERR_HOST_PTE_DATA		(1 << 1)
+# define PGTBL_ERR_HOST_GTT_PTE			(1 << 0)
+/** @} */
 
 /* Page table entries loaded via mmio region, p323
  */
diff --git a/src/i830_debug.c b/src/i830_debug.c
index 7446a22..25245fb 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -637,17 +637,67 @@ Bool
 i830_check_error_state(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    int errors = 0, fatal = 0;
+    int errors = 0;
     unsigned long temp, head, tail;
 
     if (!I830IsPrimary(pScrn)) return TRUE;
 
-    /* Check first for page table errors */
-    temp = INREG(PGE_ERR);
+    temp = INREG16(ESR);
     if (temp != 0) {
-	xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "PGTBL_ER is 0x%08lx\n", temp);
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		   "ESR is 0x%08lx%s%s%s%s\n", temp,
+		   temp & ERR_VERTEX_MAX ? ", max vertices exceeded" : "",
+		   temp & ERR_PGTBL_ERROR ? ", page table error" : "",
+		   temp & ERR_DISPLAY_OVERLAY_UNDERRUN ?
+		   ", display/overlay underrun" : "",
+		   temp & ERR_INSTRUCTION_ERROR ? ", instruction error" : "");
 	errors++;
     }
+    /* Check first for page table errors */
+    if (!IS_I9XX(pI830)) {
+	temp = INREG(PGE_ERR);
+	if (temp != 0) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		       "PGTBL_ER is 0x%08lx\n", temp);
+	    errors++;
+	}
+    } else {
+	temp = INREG(PGTBL_ER);
+	if (temp != 0) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "PGTBL_ER is 0x%08lx"
+		       "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", temp,
+		       temp & PGTBL_ERR_HOST_GTT_PTE ? ", host gtt pte" : "",
+		       temp & PGTBL_ERR_HOST_PTE_DATA ? ", host pte data" : "",
+		       temp & PGTBL_ERR_DISPA_GTT_PTE ? ", display A pte" : "",
+		       temp & PGTBL_ERR_DISPA_TILING ?
+		       ", display A tiling" : "",
+		       temp & PGTBL_ERR_DISPB_GTT_PTE ? ", display B pte" : "",
+		       temp & PGTBL_ERR_DISPB_TILING ?
+		       ", display B tiling" : "",
+		       temp & PGTBL_ERR_DISPC_GTT_PTE ? ", display C pte" : "",
+		       temp & PGTBL_ERR_DISPC_TILING ?
+		       ", display C tiling" : "",
+		       temp & PGTBL_ERR_OVERLAY_GTT_PTE ?
+		       ", overlay GTT PTE" : "",
+		       temp & PGTBL_ERR_OVERLAY_TILING ?
+		       ", overlay tiling" : "",
+		       temp & PGTBL_ERR_CS_GTT ? ", CS GTT" : "",
+		       temp & PGTBL_ERR_CS_INSTRUCTION_GTT_PTE ?
+		       ", CS instruction GTT PTE" : "",
+		       temp & PGTBL_ERR_CS_VERTEXDATA_GTT_PTE ?
+		       ", CS vertex data GTT PTE" : "",
+		       temp & PGTBL_ERR_BIN_INSTRUCTION_GTT_PTE ?
+		       ", BIN instruction GTT PTE" : "",
+		       temp & PGTBL_ERR_BIN_VERTEXDATA_GTT_PTE ?
+		       ", BIN vertex data GTT PTE" : "",
+		       temp & PGTBL_ERR_LC_GTT_PTE ? ", LC pte" : "",
+		       temp & PGTBL_ERR_LC_TILING ? ", LC tiling" : "",
+		       temp & PGTBL_ERR_MT_GTT_PTE ? ", MT pte" : "",
+		       temp & PGTBL_ERR_MT_TILING ? ", MT tiling" : "");
+	    errors++;
+	}
+    }
     temp = INREG(PGETBL_CTL);
     if (!(temp & 1)) {
 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
@@ -678,8 +728,5 @@ i830_check_error_state(ScrnInfoPtr pScrn
     }
 #endif
 
-    if (fatal)
-	FatalError("i830_check_error_state: can't recover from the above\n");
-
     return (errors != 0);
 }
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 78804de..d8a9c9b 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3125,7 +3125,10 @@ I830EnterVT(int scrnIndex, int flags)
       if (!I830BindAGPMemory(pScrn))
          return FALSE;
 
-   i830_check_error_state(pScrn);
+   if (i830_check_error_state(pScrn)) {
+      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		 "Existing errors found in hardware state\n");
+   }
 
    ResetState(pScrn, FALSE);
    SetHWOperatingState(pScrn);
diff-tree 838af10b85ee8c085c6d2c4fbe18fd90b2be9d3f (from 668ae6ce3c3c4b93a58749fd44ef32451adb6f9c)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Dec 12 13:45:41 2006 -0800

    Move PrintErrorState and CheckInheritedErrors code to i830_debug.c.

diff --git a/src/common.h b/src/common.h
index dd3fed6..540983b 100644
--- a/src/common.h
+++ b/src/common.h
@@ -96,7 +96,7 @@ extern void I830DPRINTF_stub(const char 
 			     const char *function, const char *fmt, ...);
 
 #ifdef _I830_H_
-#define PrintErrorState I830PrintErrorState
+#define PrintErrorState i830_dump_error_state
 #define WaitRingFunc I830WaitLpRing
 #define RecPtr pI830
 #else
diff --git a/src/i830.h b/src/i830.h
index 64a32dc..292374c 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -499,8 +499,6 @@ typedef struct _I830Rec {
 extern int I830WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis);
 extern void I830SetPIOAccess(I830Ptr pI830);
 extern void I830SetMMIOAccess(I830Ptr pI830);
-extern void I830PrintErrorState(ScrnInfoPtr pScrn);
-extern void I965PrintErrorState(ScrnInfoPtr pScrn);
 extern void I830Sync(ScrnInfoPtr pScrn);
 extern void I830InitHWCursor(ScrnInfoPtr pScrn);
 extern void I830SetPipeCursor (xf86CrtcPtr crtc, Bool force);
diff --git a/src/i830_accel.c b/src/i830_accel.c
index 6ad62d1..2260b71 100644
--- a/src/i830_accel.c
+++ b/src/i830_accel.c
@@ -58,6 +58,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "xaarop.h"
 #include "i830.h"
 #include "i810_reg.h"
+#include "i830_debug.h"
 
 int
 I830WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis)
@@ -99,7 +100,7 @@ I830WaitLpRing(ScrnInfoPtr pScrn, int n,
       } else if (now - start > timeout_millis) {
 	 ErrorF("Error in I830WaitLpRing(), now is %d, start is %d\n", now,
 		start);
-	 I830PrintErrorState(pScrn);
+	 i830_dump_error_state(pScrn);
 	 ErrorF("space: %d wanted %d\n", ring->space, n);
 #ifdef XF86DRI
 	 if (pI830->directRenderingEnabled) {
diff --git a/src/i830_debug.c b/src/i830_debug.c
index c2096a5..7446a22 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -522,3 +522,164 @@ void i830DumpRegs (ScrnInfoPtr pScrn)
     }
     xf86DrvMsg (pScrn->scrnIndex, X_INFO, "DumpRegsEnd\n");
 }
+
+/* Famous last words
+ */
+void
+i830_dump_error_state(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    ErrorF("pgetbl_ctl: 0x%lx pgetbl_err: 0x%lx\n",
+	   (unsigned long)INREG(PGETBL_CTL), (unsigned long)INREG(PGE_ERR));
+
+    ErrorF("ipeir: %lx iphdr: %lx\n", (unsigned long)INREG(IPEIR),
+	   (unsigned long)INREG(IPEHR));
+
+    ErrorF("LP ring tail: %lx head: %lx len: %lx start %lx\n",
+	   (unsigned long)INREG(LP_RING + RING_TAIL),
+	   (unsigned long)INREG(LP_RING + RING_HEAD) & HEAD_ADDR,
+	   (unsigned long)INREG(LP_RING + RING_LEN),
+	   (unsigned long)INREG(LP_RING + RING_START));
+
+    ErrorF("eir: %x esr: %x emr: %x\n",
+	   INREG16(EIR), INREG16(ESR), INREG16(EMR));
+
+    ErrorF("instdone: %x instpm: %x\n", INREG16(INST_DONE), INREG8(INST_PM));
+
+    ErrorF("memmode: %lx instps: %lx\n", (unsigned long)INREG(MEMMODE),
+	   (unsigned long)INREG(INST_PS));
+
+    ErrorF("hwstam: %x ier: %x imr: %x iir: %x\n",
+	   INREG16(HWSTAM), INREG16(IER), INREG16(IMR), INREG16(IIR));
+}
+
+void
+i965_dump_error_state(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    ErrorF("pgetbl_ctl: 0x%lx pgetbl_err: 0x%lx\n",
+	   INREG(PGETBL_CTL), INREG(PGE_ERR));
+
+    ErrorF("ipeir: %lx iphdr: %lx\n", INREG(IPEIR_I965), INREG(IPEHR_I965));
+
+    ErrorF("LP ring tail: %lx head: %lx len: %lx start %lx\n",
+	   INREG(LP_RING + RING_TAIL),
+	   INREG(LP_RING + RING_HEAD) & HEAD_ADDR,
+	   INREG(LP_RING + RING_LEN), INREG(LP_RING + RING_START));
+
+    ErrorF("Err ID (eir): %x Err Status (esr): %x Err Mask (emr): %x\n",
+	   (int)INREG(EIR), (int)INREG(ESR), (int)INREG(EMR));
+
+    ErrorF("instdone: %x instdone_1: %x\n", (int)INREG(INST_DONE_I965),
+	   (int)INREG(INST_DONE_1));
+    ErrorF("instpm: %x\n", (int)INREG(INST_PM));
+
+    ErrorF("memmode: %lx instps: %lx\n", INREG(MEMMODE), INREG(INST_PS_I965));
+
+    ErrorF("HW Status mask (hwstam): %x\nIRQ enable (ier): %x "
+	   "imr: %x iir: %x\n",
+	   (int)INREG(HWSTAM), (int)INREG(IER), (int)INREG(IMR),
+	   (int)INREG(IIR));
+
+    ErrorF("acthd: %lx dma_fadd_p: %lx\n", INREG(ACTHD), INREG(DMA_FADD_P));
+    ErrorF("ecoskpd: %lx excc: %lx\n", INREG(ECOSKPD), INREG(EXCC));
+
+    ErrorF("cache_mode: %x/%x\n", (int)INREG(CACHE_MODE_0),
+	   (int)INREG(CACHE_MODE_1));
+    ErrorF("mi_arb_state: %x\n", (int)INREG(MI_ARB_STATE));
+
+    ErrorF("IA_VERTICES_COUNT_QW %x/%x\n",
+	   (int)INREG(IA_VERTICES_COUNT_QW),
+	   (int)INREG(IA_VERTICES_COUNT_QW+4));
+    ErrorF("IA_PRIMITIVES_COUNT_QW %x/%x\n",
+	   (int)INREG(IA_PRIMITIVES_COUNT_QW),
+	   (int)INREG(IA_PRIMITIVES_COUNT_QW+4));
+
+    ErrorF("VS_INVOCATION_COUNT_QW %x/%x\n",
+	   (int)INREG(VS_INVOCATION_COUNT_QW),
+	   (int)INREG(VS_INVOCATION_COUNT_QW+4));
+
+    ErrorF("GS_INVOCATION_COUNT_QW %x/%x\n",
+	   (int)INREG(GS_INVOCATION_COUNT_QW),
+	   (int)INREG(GS_INVOCATION_COUNT_QW+4));
+    ErrorF("GS_PRIMITIVES_COUNT_QW %x/%x\n",
+	   (int)INREG(GS_PRIMITIVES_COUNT_QW),
+	   (int)INREG(GS_PRIMITIVES_COUNT_QW+4));
+
+    ErrorF("CL_INVOCATION_COUNT_QW %x/%x\n",
+	   (int)INREG(CL_INVOCATION_COUNT_QW),
+	   (int)INREG(CL_INVOCATION_COUNT_QW+4));
+    ErrorF("CL_PRIMITIVES_COUNT_QW %x/%x\n",
+	   (int)INREG(CL_PRIMITIVES_COUNT_QW),
+	   (int)INREG(CL_PRIMITIVES_COUNT_QW+4));
+
+    ErrorF("PS_INVOCATION_COUNT_QW %x/%x\n",
+	   (int)INREG(PS_INVOCATION_COUNT_QW),
+	   (int)INREG(PS_INVOCATION_COUNT_QW+4));
+    ErrorF("PS_DEPTH_COUNT_QW %x/%x\n",
+	   (int)INREG(PS_DEPTH_COUNT_QW),
+	   (int)INREG(PS_DEPTH_COUNT_QW+4));
+
+    ErrorF("WIZ_CTL %x\n", (int)INREG(WIZ_CTL));
+    ErrorF("TS_CTL %x  TS_DEBUG_DATA %x\n", (int)INREG(TS_CTL),
+	   (int)INREG(TS_DEBUG_DATA));
+    ErrorF("TD_CTL %x / %x\n", (int)INREG(TD_CTL), (int)INREG(TD_CTL2));
+}
+
+/**
+ * Checks the hardware error state bits.
+ *
+ * \return TRUE if any errors were found.
+ */
+Bool
+i830_check_error_state(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    int errors = 0, fatal = 0;
+    unsigned long temp, head, tail;
+
+    if (!I830IsPrimary(pScrn)) return TRUE;
+
+    /* Check first for page table errors */
+    temp = INREG(PGE_ERR);
+    if (temp != 0) {
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "PGTBL_ER is 0x%08lx\n", temp);
+	errors++;
+    }
+    temp = INREG(PGETBL_CTL);
+    if (!(temp & 1)) {
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		   "PGTBL_CTL (0x%08lx) indicates GTT is disabled\n", temp);
+	errors++;
+    }
+    temp = INREG(LP_RING + RING_LEN);
+    if (temp & 1) {
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		   "PRB0_CTL (0x%08lx) indicates ring buffer enabled\n", temp);
+	errors++;
+    }
+    head = INREG(LP_RING + RING_HEAD);
+    tail = INREG(LP_RING + RING_TAIL);
+    if ((tail & I830_TAIL_MASK) != (head & I830_HEAD_MASK)) {
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		   "PRB0_HEAD (0x%08lx) and PRB0_TAIL (0x%08lx) indicate "
+		   "ring buffer not flushed\n", head, tail);
+	errors++;
+    }
+
+#if 0
+    if (errors) {
+	if (IS_I965G(pI830))
+	    i965_dump_error_state(pScrn);
+	else
+	    i830_dump_error_state(pScrn);
+    }
+#endif
+
+    if (fatal)
+	FatalError("i830_check_error_state: can't recover from the above\n");
+
+    return (errors != 0);
+}
diff --git a/src/i830_debug.h b/src/i830_debug.h
index a365085..2d2e72b 100644
--- a/src/i830_debug.h
+++ b/src/i830_debug.h
@@ -28,3 +28,7 @@
 void i830TakeRegSnapshot(ScrnInfoPtr pScrn);
 void i830CompareRegsToSnapshot(ScrnInfoPtr pScrn, char *where);
 void i830DumpRegs (ScrnInfoPtr pScrn);
+void i830_dump_error_state(ScrnInfoPtr pScrn);
+void i965_dump_error_state(ScrnInfoPtr pScrn);
+Bool i830_check_error_state(ScrnInfoPtr pScrn);
+
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 46973e7..78804de 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1948,61 +1948,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 }
 
 /*
- * As the name says.  Check that the initial state is reasonable.
- * If any unrecoverable problems are found, bail out here.
- */
-static Bool
-CheckInheritedState(ScrnInfoPtr pScrn)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   int errors = 0, fatal = 0;
-   unsigned long temp, head, tail;
-
-   if (!I830IsPrimary(pScrn)) return TRUE;
-
-   /* Check first for page table errors */
-   temp = INREG(PGE_ERR);
-   if (temp != 0) {
-      xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "PGTBL_ER is 0x%08lx\n", temp);
-      errors++;
-   }
-   temp = INREG(PGETBL_CTL);
-   if (!(temp & 1)) {
-      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		 "PGTBL_CTL (0x%08lx) indicates GTT is disabled\n", temp);
-      errors++;
-   }
-   temp = INREG(LP_RING + RING_LEN);
-   if (temp & 1) {
-      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		 "PRB0_CTL (0x%08lx) indicates ring buffer enabled\n", temp);
-      errors++;
-   }
-   head = INREG(LP_RING + RING_HEAD);
-   tail = INREG(LP_RING + RING_TAIL);
-   if ((tail & I830_TAIL_MASK) != (head & I830_HEAD_MASK)) {
-      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		 "PRB0_HEAD (0x%08lx) and PRB0_TAIL (0x%08lx) indicate "
-		 "ring buffer not flushed\n", head, tail);
-      errors++;
-   }
-
-#if 0
-   if (errors) {
-      if (IS_I965G(pI830))
-         I965PrintErrorState(pScrn);
-      else
-         I830PrintErrorState(pScrn);
-   }
-#endif
-
-   if (fatal)
-      FatalError("CheckInheritedState: can't recover from the above\n");
-
-   return (errors != 0);
-}
-
-/*
  * Reset registers that it doesn't make sense to save/restore to a sane state.
  * This is basically the ring buffer and fence registers.  Restoring these
  * doesn't make sense without restoring GTT mappings.  This is something that
@@ -2366,103 +2311,6 @@ InitRegisterRec(ScrnInfoPtr pScrn)
       i830Reg->Fence[i] = 0;
 }
 
-/* Famous last words
- */
-void
-I830PrintErrorState(ScrnInfoPtr pScrn)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-
-   ErrorF("pgetbl_ctl: 0x%lx pgetbl_err: 0x%lx\n",
-	  (unsigned long)INREG(PGETBL_CTL), (unsigned long)INREG(PGE_ERR));
-
-   ErrorF("ipeir: %lx iphdr: %lx\n", (unsigned long)INREG(IPEIR), 
-	  (unsigned long)INREG(IPEHR));
-
-   ErrorF("LP ring tail: %lx head: %lx len: %lx start %lx\n",
-	  (unsigned long)INREG(LP_RING + RING_TAIL),
-	  (unsigned long)INREG(LP_RING + RING_HEAD) & HEAD_ADDR,
-	  (unsigned long)INREG(LP_RING + RING_LEN), 
-	  (unsigned long)INREG(LP_RING + RING_START));
-
-   ErrorF("eir: %x esr: %x emr: %x\n",
-	  INREG16(EIR), INREG16(ESR), INREG16(EMR));
-
-   ErrorF("instdone: %x instpm: %x\n", INREG16(INST_DONE), INREG8(INST_PM));
-
-   ErrorF("memmode: %lx instps: %lx\n", (unsigned long)INREG(MEMMODE), 
-	  (unsigned long)INREG(INST_PS));
-
-   ErrorF("hwstam: %x ier: %x imr: %x iir: %x\n",
-	  INREG16(HWSTAM), INREG16(IER), INREG16(IMR), INREG16(IIR));
-}
-
-void
-I965PrintErrorState(ScrnInfoPtr pScrn)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-
-   ErrorF("pgetbl_ctl: 0x%lx pgetbl_err: 0x%lx\n",
-	  INREG(PGETBL_CTL), INREG(PGE_ERR));
-
-   ErrorF("ipeir: %lx iphdr: %lx\n", INREG(IPEIR_I965), INREG(IPEHR_I965));
-
-   ErrorF("LP ring tail: %lx head: %lx len: %lx start %lx\n",
-	  INREG(LP_RING + RING_TAIL),
-	  INREG(LP_RING + RING_HEAD) & HEAD_ADDR,
-	  INREG(LP_RING + RING_LEN), INREG(LP_RING + RING_START));
-
-   ErrorF("Err ID (eir): %x Err Status (esr): %x Err Mask (emr): %x\n",
-	  (int)INREG(EIR), (int)INREG(ESR), (int)INREG(EMR));
-
-   ErrorF("instdone: %x instdone_1: %x\n", (int)INREG(INST_DONE_I965),
-	  (int)INREG(INST_DONE_1));
-   ErrorF("instpm: %x\n", (int)INREG(INST_PM));
-
-   ErrorF("memmode: %lx instps: %lx\n", INREG(MEMMODE), INREG(INST_PS_I965));
-
-   ErrorF("HW Status mask (hwstam): %x\nIRQ enable (ier): %x imr: %x iir: %x\n",
-	  (int)INREG(HWSTAM), (int)INREG(IER), (int)INREG(IMR),
-	  (int)INREG(IIR));
-
-   ErrorF("acthd: %lx dma_fadd_p: %lx\n", INREG(ACTHD), INREG(DMA_FADD_P));
-   ErrorF("ecoskpd: %lx excc: %lx\n", INREG(ECOSKPD), INREG(EXCC));
-
-   ErrorF("cache_mode: %x/%x\n", (int)INREG(CACHE_MODE_0),
-	  (int)INREG(CACHE_MODE_1));
-   ErrorF("mi_arb_state: %x\n", (int)INREG(MI_ARB_STATE));
-
-   ErrorF("IA_VERTICES_COUNT_QW %x/%x\n", (int)INREG(IA_VERTICES_COUNT_QW),
-	  (int)INREG(IA_VERTICES_COUNT_QW+4));
-   ErrorF("IA_PRIMITIVES_COUNT_QW %x/%x\n", (int)INREG(IA_PRIMITIVES_COUNT_QW),
-	  (int)INREG(IA_PRIMITIVES_COUNT_QW+4));
-
-   ErrorF("VS_INVOCATION_COUNT_QW %x/%x\n", (int)INREG(VS_INVOCATION_COUNT_QW),
-	  (int)INREG(VS_INVOCATION_COUNT_QW+4));
-
-   ErrorF("GS_INVOCATION_COUNT_QW %x/%x\n", (int)INREG(GS_INVOCATION_COUNT_QW),
-	  (int)INREG(GS_INVOCATION_COUNT_QW+4));
-   ErrorF("GS_PRIMITIVES_COUNT_QW %x/%x\n", (int)INREG(GS_PRIMITIVES_COUNT_QW),
-	  (int)INREG(GS_PRIMITIVES_COUNT_QW+4));
-
-   ErrorF("CL_INVOCATION_COUNT_QW %x/%x\n", (int)INREG(CL_INVOCATION_COUNT_QW),
-	  (int)INREG(CL_INVOCATION_COUNT_QW+4));
-   ErrorF("CL_PRIMITIVES_COUNT_QW %x/%x\n", (int)INREG(CL_PRIMITIVES_COUNT_QW),
-	  (int)INREG(CL_PRIMITIVES_COUNT_QW+4));
-
-   ErrorF("PS_INVOCATION_COUNT_QW %x/%x\n", (int)INREG(PS_INVOCATION_COUNT_QW),
-	  (int)INREG(PS_INVOCATION_COUNT_QW+4));
-   ErrorF("PS_DEPTH_COUNT_QW %x/%x\n", (int)INREG(PS_DEPTH_COUNT_QW),
-	  (int)INREG(PS_DEPTH_COUNT_QW+4));
-
-   ErrorF("WIZ_CTL %x\n", (int)INREG(WIZ_CTL));
-   ErrorF("TS_CTL %x  TS_DEBUG_DATA %x\n", (int)INREG(TS_CTL),
-	  (int)INREG(TS_DEBUG_DATA));
-   ErrorF("TD_CTL %x / %x\n", (int)INREG(TD_CTL), (int)INREG(TD_CTL2));
-
-   
-}
-
 static void
 I830PointerMoved(int index, int x, int y)
 {
@@ -3277,7 +3125,7 @@ I830EnterVT(int scrnIndex, int flags)
       if (!I830BindAGPMemory(pScrn))
          return FALSE;
 
-   CheckInheritedState(pScrn);
+   i830_check_error_state(pScrn);
 
    ResetState(pScrn, FALSE);
    SetHWOperatingState(pScrn);
diff --git a/src/i830_video.c b/src/i830_video.c
index 986d36a..5979415 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -2794,7 +2794,7 @@ BroadwaterDisplayVideoTextured(ScrnInfoP
    if (pI830->AccelInfoRec)
       (*pI830->AccelInfoRec->Sync)(pScrn);
 #if WATCH_STATS
-   I830PrintErrorState (pScrn);
+   i830_dump_error_state (pScrn);
 #endif
 }
 
diff-tree 668ae6ce3c3c4b93a58749fd44ef32451adb6f9c (from 91a538beadc17155be395ea2c8109a0958a969bd)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Dec 12 11:39:40 2006 -0800

    Set the SDVO port to on before sending the SDVO output on command.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 077e6c1..8619d02 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -701,8 +701,8 @@ i830_sdvo_dpms(xf86OutputPtr output, int
 	i830_sdvo_set_active_outputs(output, 0);
 	OUTREG(dev_priv->output_device, INREG(dev_priv->output_device) & ~SDVO_ENABLE);
     } else {
-	i830_sdvo_set_active_outputs(output, dev_priv->active_outputs);
 	OUTREG(dev_priv->output_device, INREG(dev_priv->output_device) | SDVO_ENABLE);
+	i830_sdvo_set_active_outputs(output, dev_priv->active_outputs);
     }
 }
 
diff-tree 91a538beadc17155be395ea2c8109a0958a969bd (from ce54538b905eb329f45c1b9b15e95ddce4a7927f)
Author: Eric Anholt <eric at anholt.net>
Date:   Sat Dec 9 15:58:47 2006 -0800

    More debugging output for SDVO.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index d525024..ce8407d 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -888,6 +888,16 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 /** @} */
 
 #define DPLL_TEST		0x606c
+# define DPLLB_TEST_SDVO_DIV_1			(0 << 22)
+# define DPLLB_TEST_SDVO_DIV_2			(1 << 22)
+# define DPLLB_TEST_SDVO_DIV_4			(2 << 22)
+# define DPLLB_TEST_SDVO_DIV_MASK		(3 << 22)
+# define DPLLB_TEST_N_BYPASS			(1 << 19)
+# define DPLLB_TEST_M_BYPASS			(1 << 18)
+# define DPLLB_INPUT_BUFFER_ENABLE		(1 << 16)
+# define DPLLA_TEST_N_BYPASS			(1 << 3)
+# define DPLLA_TEST_M_BYPASS			(1 << 2)
+# define DPLLA_INPUT_BUFFER_ENABLE		(1 << 0)
 
 #define D_STATE			0x6104
 #define DSPCLK_GATE_D		0x6200
diff --git a/src/i830_debug.c b/src/i830_debug.c
index 8c8b95e..c2096a5 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -160,8 +160,8 @@ DEBUGSTRING(i830_debug_dpll)
     }
     if (IS_I945G(pI830) || IS_I945GM(pI830)) {
 	sprintf(sdvoextra, ", SDVO mult %d",
-		(int)(val & SDVO_MULTIPLIER_MASK) >>
-		SDVO_MULTIPLIER_SHIFT_HIRES);
+		(int)((val & SDVO_MULTIPLIER_MASK) >>
+		SDVO_MULTIPLIER_SHIFT_HIRES) + 1);
     } else {
 	sdvoextra[0] = '\0';
     }
@@ -172,6 +172,22 @@ DEBUGSTRING(i830_debug_dpll)
 		     fpextra, sdvoextra);
 }
 
+DEBUGSTRING(i830_debug_dpll_test)
+{
+    char *dpllandiv = val & DPLLA_TEST_N_BYPASS ? ", DPLLA N bypassed" : "";
+    char *dpllamdiv = val & DPLLA_TEST_M_BYPASS ? ", DPLLA M bypassed" : "";
+    char *dpllainput = val & DPLLA_INPUT_BUFFER_ENABLE ?
+	"" : ", DPLLA input buffer disabled";
+    char *dpllbndiv = val & DPLLB_TEST_N_BYPASS ? ", DPLLB N bypassed" : "";
+    char *dpllbmdiv = val & DPLLB_TEST_M_BYPASS ? ", DPLLB M bypassed" : "";
+    char *dpllbinput = val & DPLLB_INPUT_BUFFER_ENABLE ?
+	"" : ", DPLLB input buffer disabled";
+
+    return XNFprintf("%s%s%s%s%s%s",
+		     dpllandiv, dpllamdiv, dpllainput,
+		     dpllbndiv, dpllbmdiv, dpllbinput);
+}
+
 DEBUGSTRING(i830_debug_lvds)
 {
     char pipe = val & LVDS_PIPEB_SELECT ? 'B' : 'A';
@@ -180,6 +196,27 @@ DEBUGSTRING(i830_debug_lvds)
     return XNFprintf("%s, pipe %c", enable, pipe);
 }
 
+DEBUGSTRING(i830_debug_sdvo)
+{
+    char *enable = val & SDVO_ENABLE ? "enabled" : "disabled";
+    char pipe = val & SDVO_PIPE_B_SELECT ? 'B' : 'A';
+    char *stall = val & SDVO_STALL_SELECT ? "enabled" : "disabled";
+    char *detected = val & SDVO_DETECTED ? "" : "not ";
+    char *gang = val & SDVOC_GANG_MODE ? ", gang mode" : "";
+    char sdvoextra[20];
+
+    if (IS_I915G(pI830) || IS_I915GM(pI830)) {
+	sprintf(sdvoextra, ", SDVO mult %d",
+		(int)((val & SDVO_PORT_MULTIPLY_MASK) >>
+		SDVO_PORT_MULTIPLY_SHIFT) + 1);
+    } else {
+	sdvoextra[0] = '\0';
+    }
+
+    return XNFprintf("%s, pipe %c, stall %s, %sdetected%s%s",
+		     enable, pipe, stall, detected, sdvoextra, gang);
+}
+
 #define DEFINEREG(reg) \
 	{ reg, #reg, NULL, 0 }
 #define DEFINEREG2(reg, func) \
@@ -194,14 +231,14 @@ static struct i830SnapshotRec {
     DEFINEREG(VCLK_DIVISOR_VGA0),
     DEFINEREG(VCLK_DIVISOR_VGA1),
     DEFINEREG(VCLK_POST_DIV),
-    DEFINEREG(DPLL_TEST),
+    DEFINEREG2(DPLL_TEST, i830_debug_dpll_test),
     DEFINEREG(D_STATE),
     DEFINEREG(DSPCLK_GATE_D),
     DEFINEREG(RENCLK_GATE_D1),
     DEFINEREG(RENCLK_GATE_D2),
 /*  DEFINEREG(RAMCLK_GATE_D),	CRL only */
-    DEFINEREG(SDVOB),
-    DEFINEREG(SDVOC),
+    DEFINEREG2(SDVOB, i830_debug_sdvo),
+    DEFINEREG2(SDVOC, i830_debug_sdvo),
 /*    DEFINEREG(UDIB_SVB_SHB_CODES), CRL only */
 /*    DEFINEREG(UDIB_SHA_BLANK_CODES), CRL only */
     DEFINEREG(SDVOUDI),
diff-tree ce54538b905eb329f45c1b9b15e95ddce4a7927f (from c8c1fb64ccecfb88f9923ad65c9898aa44692260)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Dec 8 08:26:30 2006 -0800

    Add a hack for DDC on my Mac Mini.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 87dc9d9..077e6c1 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -983,6 +983,31 @@ i830_sdvo_detect(xf86OutputPtr output)
 	return XF86OutputStatusDisconnected;
 }
 
+static DisplayModePtr
+i830_sdvo_get_modes(xf86OutputPtr output)
+{
+    ScrnInfoPtr pScrn = output->scrn;
+    I830Ptr pI830 = I830PTR(pScrn);
+    DisplayModePtr modes;
+    xf86OutputPtr crt;
+
+    modes = i830_ddc_get_modes(output);
+    if (modes != NULL)
+	return NULL;
+
+    /* Mac mini hack.  On this device, I get DDC through the analog, which
+     * load-detects as disconnected.  I fail to DDC through the SDVO DDC,
+     * but it does load-detect as connected.  So, just steal the DDC bits from
+     * analog when we fail at finding it the right way.
+     */
+    crt = pI830->xf86_config.output[0];
+    if (crt->funcs->detect(crt) == XF86OutputStatusDisconnected) {
+	return crt->funcs->get_modes(crt);
+    }
+
+    return NULL;
+}
+
 static void
 i830_sdvo_destroy (xf86OutputPtr output)
 {
@@ -1007,7 +1032,7 @@ static const xf86OutputFuncsRec i830_sdv
     .mode_fixup = i830_sdvo_mode_fixup,
     .mode_set = i830_sdvo_mode_set,
     .detect = i830_sdvo_detect,
-    .get_modes = i830_ddc_get_modes,
+    .get_modes = i830_sdvo_get_modes,
     .destroy = i830_sdvo_destroy
 };
 
diff-tree c8c1fb64ccecfb88f9923ad65c9898aa44692260 (from 3f3791ba2ece8e8a7aa3a5676f5f6361862a292c)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Dec 11 16:02:29 2006 -0800

    Move the overlay mode switch status updates to when we enable/disable crtcs.
    
    This should help if we mode switch with randr during video playback, and also
    simplifies the code by moving the protection all to one place.

diff --git a/src/i830.h b/src/i830.h
index 9809f35..64a32dc 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -517,8 +517,7 @@ extern Bool I830DGAInit(ScreenPtr pScree
 
 #ifdef I830_XV
 extern void I830InitVideo(ScreenPtr pScreen);
-extern void I830VideoSwitchModeBefore(ScrnInfoPtr pScrn, DisplayModePtr mode);
-extern void I830VideoSwitchModeAfter(ScrnInfoPtr pScrn, DisplayModePtr mode);
+extern void i830_crtc_dpms_video(xf86CrtcPtr crtc, Bool on);
 #endif
 
 extern Bool I830AllocateRotatedBuffer(ScrnInfoPtr pScrn, const int flags);
diff --git a/src/i830_display.c b/src/i830_display.c
index b2d9e35..f05b5c7 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -511,8 +511,14 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mod
 	/* Enable the plane */
 	temp = INREG(dspcntr_reg);
 	OUTREG(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE);
+
+	/* Give the overlay scaler a chance to enable if it's on this pipe */
+	i830_crtc_dpms_video(crtc, TRUE);
 	break;
     case DPMSModeOff:
+	/* Give the overlay scaler a chance to disable if it's on this pipe */
+	i830_crtc_dpms_video(crtc, FALSE);
+
 	/* Disable display plane */
 	temp = INREG(dspcntr_reg);
 	OUTREG(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 19f9426..46973e7 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2244,7 +2244,6 @@ RestoreHWState(ScrnInfoPtr pScrn)
    I830Ptr pI830 = I830PTR(pScrn);
    vgaHWPtr hwp = VGAHWPTR(pScrn);
    vgaRegPtr vgaReg = &hwp->SavedReg;
-   CARD32 temp;
    int i;
 
    DPRINTF(PFX, "RestoreHWState\n");
@@ -2259,19 +2258,11 @@ RestoreHWState(ScrnInfoPtr pScrn)
       output->funcs->dpms(output, DPMSModeOff);
    }
 
-   /* Disable display planes */
-   temp = INREG(DSPACNTR);
-   OUTREG(DSPACNTR, temp & ~DISPLAY_PLANE_ENABLE);
-   temp = INREG(DSPBCNTR);
-   OUTREG(DSPBCNTR, temp & ~DISPLAY_PLANE_ENABLE);
-
-   /* Next, disable display pipes */
-   temp = INREG(PIPEACONF);
-   OUTREG(PIPEACONF, temp & ~PIPEACONF_ENABLE);
-   temp = INREG(PIPEBCONF);
-   OUTREG(PIPEBCONF, temp & ~PIPEBCONF_ENABLE);
-
-   i830WaitForVblank(pScrn);
+   /* Disable pipes */
+   for (i = 0; i < pI830->xf86_config.num_crtc; i++) {
+      xf86CrtcPtr crtc = pI830->xf86_config.crtc[i];
+      crtc->funcs->dpms(crtc, DPMSModeOff);
+   }
 
    OUTREG(FPA0, pI830->saveFPA0);
    OUTREG(FPA1, pI830->saveFPA1);
@@ -3214,11 +3205,6 @@ I830LeaveVT(int scrnIndex, int flags)
 
    i830SetHotkeyControl(pScrn, HOTKEY_BIOS_SWITCH);
 
-#ifdef I830_XV
-   /* Give the video overlay code a chance to shutdown. */
-   I830VideoSwitchModeBefore(pScrn, NULL);
-#endif
-
    if (!I830IsPrimary(pScrn)) {
    	I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
 	if (!pI8301->GttBound) {
@@ -3319,10 +3305,6 @@ I830EnterVT(int scrnIndex, int flags)
 #ifdef XF86DRI
    I830DRISetVBlankInterrupt (pScrn, TRUE);
 #endif
-   
-#ifdef I830_XV
-   I830VideoSwitchModeAfter(pScrn, pScrn->currentMode);
-#endif
 
    ResetState(pScrn, TRUE);
    SetHWOperatingState(pScrn);
@@ -3396,11 +3378,6 @@ I830SwitchMode(int scrnIndex, DisplayMod
 
    DPRINTF(PFX, "I830SwitchMode: mode == %p\n", mode);
 
-#ifdef I830_XV
-   /* Give the video overlay code a chance to see the new mode. */
-   I830VideoSwitchModeBefore(pScrn, mode);
-#endif
-
    /* Sync the engine before mode switch */
    i830WaitSync(pScrn);
 
@@ -3434,18 +3411,8 @@ I830SwitchMode(int scrnIndex, DisplayMod
 	 xf86DrvMsg(scrnIndex, X_INFO,
 		    "Failed to restore previous mode (SwitchMode)\n");
       }
-
-#ifdef I830_XV
-      /* Give the video overlay code a chance to see the new mode. */
-      I830VideoSwitchModeAfter(pScrn, pI830->currentMode);
-#endif
    } else {
       pI830->currentMode = mode;
-
-#ifdef I830_XV
-      /* Give the video overlay code a chance to see the new mode. */
-      I830VideoSwitchModeAfter(pScrn, mode);
-#endif
    }
 
    return ret;
diff --git a/src/i830_video.c b/src/i830_video.c
index 3aad1aa..986d36a 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -738,10 +738,10 @@ I830SetupImageVideoOverlay(ScreenPtr pSc
 
    /*
     * Initialise pPriv->overlayOK.  Set it to TRUE here so that a warning will
-    * be generated if I830VideoSwitchModeAfter() sets it to FALSE.
+    * be generated if i830_crtc_dpms_video() sets it to FALSE during mode
+    * setup.
     */
    pPriv->overlayOK = TRUE;
-   I830VideoSwitchModeAfter(pScrn, pScrn->currentMode);
 
    pI830->BlockHandler = pScreen->BlockHandler;
    pScreen->BlockHandler = I830BlockHandler;
@@ -3511,95 +3511,77 @@ I830InitOffscreenImages(ScreenPtr pScree
 }
 
 void
-I830VideoSwitchModeBefore(ScrnInfoPtr pScrn, DisplayModePtr mode)
+i830_crtc_dpms_video(xf86CrtcPtr crtc, Bool on)
 {
+   ScrnInfoPtr pScrn = crtc->scrn;
    I830Ptr pI830 = I830PTR(pScrn);
    I830PortPrivPtr pPriv;
+   I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
 
-   if (!pI830->adaptor) {
+   if (pI830->adaptor == NULL)
       return;
-   }
-
-   pPriv = GET_PORT_PRIVATE(pScrn);
 
-   if (!pPriv) {
-      xf86ErrorF("pPriv isn't set\n");
+   /* No overlay scaler on the 965. */
+   if (IS_I965G(pI830))
       return;
-   }
 
-   /* We stop the video when mode switching, just so we don't lockup
-    * the engine. The overlayOK will determine whether we can re-enable
-    * with the current video on completion of the mode switch.
-    */
-   I830StopVideo(pScrn, pPriv, TRUE);
-
-   pPriv->overlayOK = FALSE;
-
-   pPriv->oneLineMode = FALSE;
-}
-
-void
-I830VideoSwitchModeAfter(ScrnInfoPtr pScrn, DisplayModePtr mode)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   I830PortPrivPtr pPriv;
-   int size, hsize, vsize, active;
-
-   if (!pI830->adaptor) {
-      return;
-   }
    pPriv = GET_PORT_PRIVATE(pScrn);
-   if (!pPriv)
-      return;
-
-   pPriv->overlayOK = TRUE;
 
-   if (!IS_I965G(pI830)) {
-      if (pPriv->pipe == 0) {
-         if (INREG(PIPEACONF) & PIPEACONF_DOUBLE_WIDE) {
-            xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-	    "Disabling XVideo output because Pipe A is in double-wide mode.\n");
-            pPriv->overlayOK = FALSE;
-         } else if (!pPriv->overlayOK) {
-            xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-	    "Re-enabling XVideo output because Pipe A is now in single-wide mode.\n");
-            pPriv->overlayOK = TRUE;
-         }
-      }
-
-      if (pPriv->pipe == 1) {
-         if (INREG(PIPEBCONF) & PIPEBCONF_DOUBLE_WIDE) {
-            xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-   	    "Disabling XVideo output because Pipe B is in double-wide mode.\n");
-            pPriv->overlayOK = FALSE;
-         } else if (!pPriv->overlayOK) {
-            xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-	    "Re-enabling XVideo output because Pipe B is now in single-wide mode.\n");
-            pPriv->overlayOK = TRUE;
-         }
-      }
-   }
+   /* Check if it's the pipe the overlay is on */
+   if (intel_crtc->pipe != pPriv->pipe)
+      return;
 
-   /* Check we have an LFP connected */
-   if (i830PipeHasType (pI830->xf86_config.crtc[pPriv->pipe], I830_OUTPUT_LVDS)) 
-   {
-      size = pPriv->pipe ? INREG(PIPEBSRC) : INREG(PIPEASRC);
-      hsize = (size >> 16) & 0x7FF;
-      vsize = size & 0x7FF;
-      active = pPriv->pipe ? (INREG(VTOTAL_B) & 0x7FF) : (INREG(VTOTAL_A) & 0x7FF);
+   if (on) {
+      int size, hsize, vsize, active;
+      int pipeconf_reg = pPriv->pipe == 0 ? PIPEACONF : PIPEBCONF;
+      char pipename = pPriv->pipe == 0 ? 'A' : 'B';
+
+      pPriv->overlayOK = TRUE;
+
+      if (INREG(pipeconf_reg) & PIPEACONF_DOUBLE_WIDE) {
+	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		    "Disabling XVideo output because Pipe %c is in "
+		    "double-wide mode.\n", pipename);
+	 pPriv->overlayOK = FALSE;
+      } else if (!pPriv->overlayOK) {
+	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		    "Re-enabling XVideo output because Pipe %c is now in "
+		    "single-wide mode.\n", pipename);
+	 pPriv->overlayOK = TRUE;
+      }
+
+      /* Check we have an LFP connected */
+      if (i830PipeHasType(pI830->xf86_config.crtc[pPriv->pipe],
+			  I830_OUTPUT_LVDS)) {
+	 size = pPriv->pipe ? INREG(PIPEBSRC) : INREG(PIPEASRC);
+	 hsize = (size >> 16) & 0x7FF;
+	 vsize = size & 0x7FF;
+	 int vtotal_reg = pPriv->pipe ? VTOTAL_A : VTOTAL_B;
+	 active = INREG(vtotal_reg) & 0x7FF;
+
+	 if (vsize < active && hsize > 1024)
+	    I830SetOneLineModeRatio(pScrn);
+
+	 if (pPriv->scaleRatio & 0xFFFE0000) {
+	    /* Possible bogus ratio, using in-accurate fallback */
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		       "Bogus panel fit register, Xvideo positioning may not "
+		       "be accurate.\n");
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		       "Using fallback ratio - was 0x%x, now 0x%x\n",
+		       pPriv->scaleRatio,
+		       (int)(((float)active * 65536)/(float)vsize));
 
-      if (vsize < active && hsize > 1024)
-         I830SetOneLineModeRatio(pScrn);
-   
-      if (pPriv->scaleRatio & 0xFFFE0000) {
-         /* Possible bogus ratio, using in-accurate fallback */
-         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-	    "Bogus panel fit register, Xvideo positioning may not be accurate.\n");
-         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-	    "Using fallback ratio - was 0x%x, now 0x%x\n", pPriv->scaleRatio, (int)(((float)active * 65536)/(float)vsize));
-   
-   
-         pPriv->scaleRatio = (int)(((float)active * 65536) / (float)vsize);
+	    pPriv->scaleRatio = (int)(((float)active * 65536) / (float)vsize);
+	 }
       }
+   } else {
+      /* We stop the video when mode switching, so we don't lock up
+       * the engine. The overlayOK will determine whether we can re-enable
+       * with the current video on completion of the mode switch.
+       */
+      I830StopVideo(pScrn, pPriv, TRUE);
+      pPriv->overlayOK = FALSE;
+      pPriv->oneLineMode = FALSE;
    }
 }
diff-tree 3f3791ba2ece8e8a7aa3a5676f5f6361862a292c (from c21baa5a3044eb66f2518b018dae07eadb989aa1)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Dec 11 15:20:15 2006 -0800

    Remove remnants of old savedCurrentMode hack.  Man, that was gross.

diff --git a/src/i830.h b/src/i830.h
index 2a7a1d8..9809f35 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -242,10 +242,6 @@ typedef struct _I830Rec {
    int cpp;
 
    DisplayModePtr currentMode;
-   /* Mode saved during randr reprobe, which will need to be freed at the point
-    * of the next SwitchMode, when we lose this last reference to it.
-    */
-   DisplayModePtr savedCurrentMode;
 
    I830EntPtr entityPrivate;	
    int init;
diff --git a/src/i830_display.c b/src/i830_display.c
index 6206243..b2d9e35 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -976,19 +976,6 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
 	       (int)(pMode->HDisplay * pMode->VDisplay *
 		     pMode->VRefresh / 1000000));
 
-    if (pI830->savedCurrentMode) {
-	/* We're done with the currentMode that the last randr probe had left
-	 * behind, so free it.
-	 */
-	xfree(pI830->savedCurrentMode->name);
-	xfree(pI830->savedCurrentMode);
-	pI830->savedCurrentMode = NULL;
-
-	/* If HW cursor currently showing, reset cursor state */
-	if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn)
-	    pI830->CursorInfoRec->ShowCursor(pScrn);
-    }
-
     i830DisableUnusedFunctions(pScrn);
 
     i830DescribeOutputConfiguration(pScrn);
diff-tree c21baa5a3044eb66f2518b018dae07eadb989aa1 (from b3865f34669319f449f2da8f87a4eef6ec8e7804)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Dec 11 15:15:01 2006 -0800

    Remove dead remnants of old clone mode support.

diff --git a/src/i830.h b/src/i830.h
index ce9b461..2a7a1d8 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -247,11 +247,6 @@ typedef struct _I830Rec {
     */
    DisplayModePtr savedCurrentMode;
 
-   Bool Clone;
-   int CloneRefresh;
-   int CloneHDisplay;
-   int CloneVDisplay;
-
    I830EntPtr entityPrivate;	
    int init;
 
diff --git a/src/i830_display.c b/src/i830_display.c
index 439c298..6206243 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -983,16 +983,6 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
 	xfree(pI830->savedCurrentMode->name);
 	xfree(pI830->savedCurrentMode);
 	pI830->savedCurrentMode = NULL;
-	    
-	/* If we might have enabled/disabled some pipes, we need to reset
-	 * cloning mode support.
-	 */
-	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;
 
 	/* If HW cursor currently showing, reset cursor state */
 	if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn)
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 61ce8ad..19f9426 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -274,8 +274,6 @@ typedef enum {
    OPTION_DISPLAY_INFO,
    OPTION_DEVICE_PRESENCE,
    OPTION_MONITOR_LAYOUT,
-   OPTION_CLONE,
-   OPTION_CLONE_REFRESH,
    OPTION_CHECKDEVICES,
    OPTION_FIXEDPIPE,
    OPTION_ROTATE,
@@ -297,8 +295,6 @@ static OptionInfoRec I830Options[] = {
    {OPTION_COLOR_KEY,	"ColorKey",	OPTV_INTEGER,	{0},	FALSE},
    {OPTION_VIDEO_KEY,	"VideoKey",	OPTV_INTEGER,	{0},	FALSE},
    {OPTION_MONITOR_LAYOUT, "MonitorLayout", OPTV_ANYSTR,{0},	FALSE},
-   {OPTION_CLONE,	"Clone",	OPTV_BOOLEAN,	{0},	FALSE},
-   {OPTION_CLONE_REFRESH,"CloneRefresh",OPTV_INTEGER,	{0},	FALSE},
    {OPTION_CHECKDEVICES, "CheckDevices",OPTV_BOOLEAN,	{0},	FALSE},
    {OPTION_FIXEDPIPE,   "FixedPipe",    OPTV_ANYSTR, 	{0},	FALSE},
    {OPTION_ROTATE,      "Rotate",       OPTV_ANYSTR,    {0},    FALSE},
@@ -1387,23 +1383,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
        i830_crtc_init(pScrn, i);
    }
 
-   if (xf86ReturnOptValBool(pI830->Options, OPTION_CLONE, FALSE)) {
-      if (num_pipe == 1) {
-         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 
- 		 "Can't enable Clone Mode because this is a single pipe device\n");
-         PreInitCleanup(pScrn);
-         return FALSE;
-      }
-      if (pI830->entityPrivate) {
-         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 
- 		 "Can't enable Clone Mode because second head is configured\n");
-         PreInitCleanup(pScrn);
-         return FALSE;
-      }
-      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabling Clone Mode\n");
-      pI830->Clone = TRUE;
-   }
-
    SaveHWState(pScrn);
    /* Do an initial detection of the outputs while none are configured on yet.
     * This will give us some likely legitimate response for later if both
@@ -3240,12 +3219,6 @@ I830LeaveVT(int scrnIndex, int flags)
    I830VideoSwitchModeBefore(pScrn, NULL);
 #endif
 
-   if (pI830->Clone) {
-      /* Ensure we don't try and setup modes on a clone head */
-      pI830->CloneHDisplay = 0;
-      pI830->CloneVDisplay = 0;
-   }
-
    if (!I830IsPrimary(pScrn)) {
    	I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
 	if (!pI8301->GttBound) {
diff --git a/src/i830_video.c b/src/i830_video.c
index a3bfda8..3aad1aa 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -954,7 +954,7 @@ I830SetPortAttribute(ScrnInfoPtr pScrn,
       overlay->OCLRC1 = pPriv->saturation;
       overlay->OCMD &= ~OVERLAY_ENABLE;
       OVERLAY_UPDATE;
-   } else if (pI830->Clone && attribute == xvPipe) {
+   } else if (attribute == xvPipe) {
       if ((value < 0) || (value > 1))
          return BadValue;
       pPriv->pipe = value;
@@ -3554,18 +3554,6 @@ I830VideoSwitchModeAfter(ScrnInfoPtr pSc
 
    pPriv->overlayOK = TRUE;
 
-#if 0
-   /* XXX Must choose pipe wisely */
-   /* ensure pipe is updated on mode switch */
-   if (!pI830->Clone) {
-      if (pPriv->pipe != pI830->pipe) {
-         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-	   "Changing XVideo pipe (%d to %d).\n", pPriv->pipe, pI830->pipe);
-         pPriv->pipe = pI830->pipe;
-      }
-   }
-#endif
-
    if (!IS_I965G(pI830)) {
       if (pPriv->pipe == 0) {
          if (INREG(PIPEACONF) & PIPEACONF_DOUBLE_WIDE) {
diff-tree b3865f34669319f449f2da8f87a4eef6ec8e7804 (from 24d9521c7ae72e146025f10ea85b07ebd7041716)
Author: Joshua J. Berry <des at condordes.net>
Date:   Mon Dec 11 14:46:20 2006 -0800

    Include i830.h to get M_T_* compat defines for older X Servers.
    
    Not duplicating the defines ensures that we won't let the compat bits slip
    into the X Server when we move this code over there.

diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index 3a592e5..448d4f9 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -32,6 +32,7 @@
 
 #include "xf86.h"
 #include "xf86DDC.h"
+#include "i830.h"
 #include "i830_xf86Crtc.h"
 #include "X11/extensions/render.h"
 
diff-tree 24d9521c7ae72e146025f10ea85b07ebd7041716 (from fde52de870c84821ab457e17634c334a10cf71ab)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Dec 11 09:34:50 2006 -0800

    Add error messages for previous silent DRI initialization failures.

diff --git a/src/i830_dri.c b/src/i830_dri.c
index b320633..0f6145b 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -426,15 +426,24 @@ I830CheckDRIAvailable(ScrnInfoPtr pScrn)
 
    /* Check that the GLX, DRI, and DRM modules have been loaded by testing
     * for known symbols in each module. */
-   if (!xf86LoaderCheckSymbol("GlxSetVisualConfigs"))
+   if (!xf86LoaderCheckSymbol("GlxSetVisualConfigs")) {
+      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		 "[dri] %s failed: glx not loaded\n", __FUNCTION__);
       return FALSE;
-   if (!xf86LoaderCheckSymbol("DRIScreenInit"))
+   }
+   if (!xf86LoaderCheckSymbol("DRIScreenInit")) {
+      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		 "[dri] %s failed: dri not loaded\n", __FUNCTION__);
       return FALSE;
-   if (!xf86LoaderCheckSymbol("drmAvailable"))
+   }
+   if (!xf86LoaderCheckSymbol("drmAvailable")) {
+      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		 "[dri] %s failed: libdrm not loaded\n", __FUNCTION__);
       return FALSE;
+   }
    if (!xf86LoaderCheckSymbol("DRIQueryVersion")) {
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		 "[dri] %s failed (libdri.a too old)\n", "I830CheckDRIAvailable");
+		 "[dri] %s failed (libdri.a too old)\n", __FUNCTION__);
       return FALSE;
    }
 
diff-tree fde52de870c84821ab457e17634c334a10cf71ab (from parents)
Merge: 7dbe6c378d1bc0c06ed6be4c1f9ca38ac31a5571 85de8a05804eaebcd61430793ef5406f196f9a95
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Wed Dec 6 23:40:13 2006 -0800

    Merge branch 'modesetting-origin' into modesetting

diff-tree 7dbe6c378d1bc0c06ed6be4c1f9ca38ac31a5571 (from 28c7002b1cf81e286a083384575d53021d3ce906)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Wed Dec 6 23:39:14 2006 -0800

    Move vga restore to end of RestoreHWState.
    
    I was having consistent system lockups when the vga restore
    was first. Moving it to the end has reduced them to an infrequent
    occurrence (but, alas, it has happened once since). This does not
    make me happy.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 915107f..61ce8ad 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2273,8 +2273,6 @@ RestoreHWState(ScrnInfoPtr pScrn)
 #ifdef XF86DRI
    I830DRISetVBlankInterrupt (pScrn, FALSE);
 #endif
-   vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS);
-   vgaHWLock(hwp);
 
    /* Disable outputs */
    for (i = 0; i < pI830->xf86_config.num_output; i++) {
@@ -2376,6 +2374,12 @@ RestoreHWState(ScrnInfoPtr pScrn)
    OUTREG(SWF31, pI830->saveSWF[15]);
    OUTREG(SWF32, pI830->saveSWF[16]);
 
+   for (i = 0; i < 2; i++)
+      i830WaitForVblank(pScrn);
+
+   vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS);
+   vgaHWLock(hwp);
+
    return TRUE;
 }
 
diff-tree 28c7002b1cf81e286a083384575d53021d3ce906 (from 182d2f503a7a1be90d93a4a15059585a564fd3ce)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Wed Dec 6 23:35:15 2006 -0800

    Use DOUBLE_WIDE mode on all hardware.
    
    DOUBLE_WIDE mode is needed when the pixel clock is > 90% of the core
    clock rate. The code guesses what the core clock rate is based on
    the bus (AGP -> 133MHz, PCI-E -> 200MHz).

diff --git a/src/i830_display.c b/src/i830_display.c
index 0e5a09a..439c298 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -705,22 +705,23 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
 	dspcntr |= DISPPLANE_SEL_PIPE_B;
 
     pipeconf = INREG(pipeconf_reg);
-    if (!IS_I9XX(pI830) && pipe == 0) {
+    if (pipe == 0) 
+    {
 	/*
 	 * The docs say this is needed when the dot clock is > 90% of the
 	 * core speed. Core speeds are indicated by bits in the PCI
-	 * config space and don't seem to ever be less than 200MHz,
-	 * which is a bit confusing.
-	 *
-	 * However, For one little 855/852 card I have, 135000 requires
-	 * double wide mode, but 108000 does not. That makes no sense
-	 * but we're used to that. It may be affected by pixel size,
-	 * but the BIOS mode setting code doesn't appear to use that.
-	 *
-	 * It doesn't seem to cause any harm, although it
-	 * does restrict some output options.
+	 * config space, but that's a pain to go read, so we just guess
+	 * based on the hardware age. AGP hardware is assumed to run
+	 * at 133MHz while PCI-E hardware is assumed to run at 200MHz
 	 */
-	if (adjusted_mode->Clock > 108000)
+	int core_clock;
+	
+	if (IS_I9XX(pI830))
+	    core_clock = 200000;
+	else
+	    core_clock = 133000;
+	
+	if (mode->Clock > core_clock * 9 / 10)
 	    pipeconf |= PIPEACONF_DOUBLE_WIDE;
 	else
 	    pipeconf &= ~PIPEACONF_DOUBLE_WIDE;
diff-tree 85de8a05804eaebcd61430793ef5406f196f9a95 (from 182d2f503a7a1be90d93a4a15059585a564fd3ce)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Dec 6 20:26:53 2006 -0800

    Include render.h to get SubPixelUnknown define.

diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index 5378b34..3a592e5 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -33,6 +33,7 @@
 #include "xf86.h"
 #include "xf86DDC.h"
 #include "i830_xf86Crtc.h"
+#include "X11/extensions/render.h"
 
 /*
  * Crtc functions
diff-tree 182d2f503a7a1be90d93a4a15059585a564fd3ce (from parents)
Merge: 677c454469a6223460778033758e384e989cea47 6777d8044d5cc063698e05afb7a93a58a7a3b64a
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Wed Dec 6 17:18:58 2006 -0800

    Merge branch 'modesetting-origin' into modesetting

diff --cc src/i830_driver.c
index e04a44c,2f515ed..915107f
@@@ -707,8 -729,46 +729,46 @@@
     } else {
        i830_dvo_init(pScrn);
     }
 -   if (IS_I915GM(pI830) || IS_I945GM(pI830))
 +   if (IS_I9XX(pI830) && !IS_I915G(pI830))
        i830_tv_init(pScrn);
+    
+    for (o = 0; o < config->num_output; o++)
+    {
+       xf86OutputPtr	   output = config->output[o];
+       I830OutputPrivatePtr intel_output = output->driver_private;
+       int		   crtc_mask = 0, clone_mask = 0;
+       
+       /*
+        * Valid crtcs
+        */
+       switch (intel_output->type) {
+       case I830_OUTPUT_DVO:
+       case I830_OUTPUT_SDVO:
+ 	 crtc_mask = ((1 << 0)|
+ 		      (1 << 1));
+ 	 clone_mask = ((1 << I830_OUTPUT_ANALOG) |
+ 		       (1 << I830_OUTPUT_DVO) |
+ 		       (1 << I830_OUTPUT_SDVO));
+ 	 break;
+       case I830_OUTPUT_ANALOG:
+ 	 crtc_mask = ((1 << 0));
+ 	 clone_mask = ((1 << I830_OUTPUT_ANALOG) |
+ 		       (1 << I830_OUTPUT_DVO) |
+ 		       (1 << I830_OUTPUT_SDVO));
+ 	 break;
+       case I830_OUTPUT_LVDS:
+ 	 crtc_mask = (1 << 1);
+ 	 clone_mask = (1 << I830_OUTPUT_LVDS);
+ 	 break;
+       case I830_OUTPUT_TVOUT:
+ 	 crtc_mask = ((1 << 0) |
+ 		      (1 << 1));
+ 	 clone_mask = (1 << I830_OUTPUT_TVOUT);
+ 	 break;
+       }
+       output->possible_crtcs = crtc_mask;
+       output->possible_clones = i830_output_clones (pScrn, clone_mask);
+    }
  }
  
  /**
diff-tree 6777d8044d5cc063698e05afb7a93a58a7a3b64a (from c6ce8a3c3355e8a56e86856caa56baf1cd3c0231)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Dec 6 17:10:06 2006 -0800

    Harmless warning fix.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 53c0ab8..2f515ed 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2177,7 +2177,6 @@ SaveHWState(ScrnInfoPtr pScrn)
    I830Ptr pI830 = I830PTR(pScrn);
    vgaHWPtr hwp = VGAHWPTR(pScrn);
    vgaRegPtr vgaReg = &hwp->SavedReg;
-   CARD32 temp;
    int i;
 
    /* Save video mode information for native mode-setting. */
diff-tree c6ce8a3c3355e8a56e86856caa56baf1cd3c0231 (from b23dec37b28a76433ad5d537ab508294e843cabe)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Dec 6 17:07:48 2006 -0800

    Reduce dumpregs to X startup, after a mode set, and LeaveVT.
    
    While here, remove some other register dumping that is better done by
    i830DumpRegs().

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 9428476..53c0ab8 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1184,6 +1184,9 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    /* Some of the probing needs MMIO access, so map it here. */
    I830MapMMIO(pScrn);
 
+   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Hardware state on X startup:\n");
+   i830DumpRegs (pScrn);
+
    i830TakeRegSnapshot(pScrn);
 
 #if 1
@@ -2177,18 +2180,6 @@ SaveHWState(ScrnInfoPtr pScrn)
    CARD32 temp;
    int i;
 
-   /*
-    * Print out the PIPEACONF and PIPEBCONF registers.
-    */
-   temp = INREG(PIPEACONF);
-   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEACONF is 0x%08lx\n", 
-	      (unsigned long) temp);
-   if (pI830->xf86_config.num_crtc == 2) {
-      temp = INREG(PIPEBCONF);
-      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEBCONF is 0x%08lx\n", 
-		 (unsigned long) temp);
-   }
-
    /* Save video mode information for native mode-setting. */
    pI830->saveDSPACNTR = INREG(DSPACNTR);
    pI830->savePIPEACONF = INREG(PIPEACONF);
@@ -2386,9 +2377,6 @@ RestoreHWState(ScrnInfoPtr pScrn)
    OUTREG(SWF31, pI830->saveSWF[15]);
    OUTREG(SWF32, pI830->saveSWF[16]);
 
-   i830CompareRegsToSnapshot(pScrn, "After RestoreHWState");
-   i830DumpRegs (pScrn);
-
    return TRUE;
 }
 
@@ -2502,195 +2490,6 @@ I965PrintErrorState(ScrnInfoPtr pScrn)
    
 }
 
-#ifdef I830DEBUG
-static void
-dump_DSPACNTR(ScrnInfoPtr pScrn)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   unsigned int tmp;
-
-   /* Display A Control */
-   tmp = INREG(0x70180);
-   ErrorF("Display A Plane Control Register (0x%.8x)\n", tmp);
-
-   if (tmp & BIT(31))
-      ErrorF("   Display Plane A (Primary) Enable\n");
-   else
-      ErrorF("   Display Plane A (Primary) Disabled\n");
-
-   if (tmp & BIT(30))
-      ErrorF("   Display A pixel data is gamma corrected\n");
-   else
-      ErrorF("   Display A pixel data bypasses gamma correction logic (default)\n");
-
-   switch ((tmp & 0x3c000000) >> 26) {	/* bit 29:26 */
-   case 0x00:
-   case 0x01:
-   case 0x03:
-      ErrorF("   Reserved\n");
-      break;
-   case 0x02:
-      ErrorF("   8-bpp Indexed\n");
-      break;
-   case 0x04:
-      ErrorF("   15-bit (5-5-5) pixel format (Targa compatible)\n");
-      break;
-   case 0x05:
-      ErrorF("   16-bit (5-6-5) pixel format (XGA compatible)\n");
-      break;
-   case 0x06:
-      ErrorF("   32-bit format (X:8:8:8)\n");
-      break;
-   case 0x07:
-      ErrorF("   32-bit format (8:8:8:8)\n");
-      break;
-   default:
-      ErrorF("   Unknown - Invalid register value maybe?\n");
-   }
-
-   if (tmp & BIT(25))
-      ErrorF("   Stereo Enable\n");
-   else
-      ErrorF("   Stereo Disable\n");
-
-   if (tmp & BIT(24))
-      ErrorF("   Display A, Pipe B Select\n");
-   else
-      ErrorF("   Display A, Pipe A Select\n");
-
-   if (tmp & BIT(22))
-      ErrorF("   Source key is enabled\n");
-   else
-      ErrorF("   Source key is disabled\n");
-
-   switch ((tmp & 0x00300000) >> 20) {	/* bit 21:20 */
-   case 0x00:
-      ErrorF("   No line duplication\n");
-      break;
-   case 0x01:
-      ErrorF("   Line/pixel Doubling\n");
-      break;
-   case 0x02:
-   case 0x03:
-      ErrorF("   Reserved\n");
-      break;
-   }
-
-   if (tmp & BIT(18))
-      ErrorF("   Stereo output is high during second image\n");
-   else
-      ErrorF("   Stereo output is high during first image\n");
-}
-
-static void
-dump_DSPBCNTR(ScrnInfoPtr pScrn)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   unsigned int tmp;
-
-   /* Display B/Sprite Control */
-   tmp = INREG(0x71180);
-   ErrorF("Display B/Sprite Plane Control Register (0x%.8x)\n", tmp);
-
-   if (tmp & BIT(31))
-      ErrorF("   Display B/Sprite Enable\n");
-   else
-      ErrorF("   Display B/Sprite Disable\n");
-
-   if (tmp & BIT(30))
-      ErrorF("   Display B pixel data is gamma corrected\n");
-   else
-      ErrorF("   Display B pixel data bypasses gamma correction logic (default)\n");
-
-   switch ((tmp & 0x3c000000) >> 26) {	/* bit 29:26 */
-   case 0x00:
-   case 0x01:
-   case 0x03:
-      ErrorF("   Reserved\n");
-      break;
-   case 0x02:
-      ErrorF("   8-bpp Indexed\n");
-      break;
-   case 0x04:
-      ErrorF("   15-bit (5-5-5) pixel format (Targa compatible)\n");
-      break;
-   case 0x05:
-      ErrorF("   16-bit (5-6-5) pixel format (XGA compatible)\n");
-      break;
-   case 0x06:
-      ErrorF("   32-bit format (X:8:8:8)\n");
-      break;
-   case 0x07:
-      ErrorF("   32-bit format (8:8:8:8)\n");
-      break;
-   default:
-      ErrorF("   Unknown - Invalid register value maybe?\n");
-   }
-
-   if (tmp & BIT(25))
-      ErrorF("   Stereo is enabled and both start addresses are used in a two frame sequence\n");
-   else
-      ErrorF("   Stereo disable and only a single start address is used\n");
-
-   if (tmp & BIT(24))
-      ErrorF("   Display B/Sprite, Pipe B Select\n");
-   else
-      ErrorF("   Display B/Sprite, Pipe A Select\n");
-
-   if (tmp & BIT(22))
-      ErrorF("   Sprite source key is enabled\n");
-   else
-      ErrorF("   Sprite source key is disabled (default)\n");
-
-   switch ((tmp & 0x00300000) >> 20) {	/* bit 21:20 */
-   case 0x00:
-      ErrorF("   No line duplication\n");
-      break;
-   case 0x01:
-      ErrorF("   Line/pixel Doubling\n");
-      break;
-   case 0x02:
-   case 0x03:
-      ErrorF("   Reserved\n");
-      break;
-   }
-
-   if (tmp & BIT(18))
-      ErrorF("   Stereo output is high during second image\n");
-   else
-      ErrorF("   Stereo output is high during first image\n");
-
-   if (tmp & BIT(15))
-      ErrorF("   Alpha transfer mode enabled\n");
-   else
-      ErrorF("   Alpha transfer mode disabled\n");
-
-   if (tmp & BIT(0))
-      ErrorF("   Sprite is above overlay\n");
-   else
-      ErrorF("   Sprite is above display A (default)\n");
-}
-
-void
-I830_dump_registers(ScrnInfoPtr pScrn)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   unsigned int i;
-
-   ErrorF("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n");
-
-   dump_DSPACNTR(pScrn);
-   dump_DSPBCNTR(pScrn);
-
-   ErrorF("0x71400 == 0x%.8x\n", INREG(0x71400));
-   ErrorF("0x70008 == 0x%.8x\n", INREG(0x70008));
-   for (i = 0x71410; i <= 0x71428; i += 4)
-      ErrorF("0x%x == 0x%.8x\n", i, INREG(i));
-
-   ErrorF("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n");
-}
-#endif
-
 static void
 I830PointerMoved(int index, int x, int y)
 {
@@ -3302,10 +3101,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    if (serverGeneration == 1)
       xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
 
-#ifdef I830DEBUG
-   I830_dump_registers(pScrn);
-#endif
-
    if (IS_I965G(pI830)) {
       /* turn off clock gating */
 #if 0
@@ -3477,6 +3272,10 @@ I830LeaveVT(int scrnIndex, int flags)
    ResetState(pScrn, TRUE);
 
    RestoreHWState(pScrn);
+
+   i830CompareRegsToSnapshot(pScrn, "After LeaveVT");
+   i830DumpRegs (pScrn);
+
    if (I830IsPrimary(pScrn))
       I830UnbindAGPMemory(pScrn);
    if (pI830->AccelInfoRec)
diff-tree b23dec37b28a76433ad5d537ab508294e843cabe (from d3c21c09e3904b3d32aca7563044194b061ac2fa)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Dec 6 16:58:24 2006 -0800

    Save/restore registers around calls in PreInit with register side-effects.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index ec41a56..9428476 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1401,12 +1401,10 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       pI830->Clone = TRUE;
    }
 
-
-#if 0
-   SaveHWState (pScrn);
-#endif
-   /* Perform the pipe assignment of outputs. This is a kludge until
-    * we have better configuration support in the generic RandR code
+   SaveHWState(pScrn);
+   /* Do an initial detection of the outputs while none are configured on yet.
+    * This will give us some likely legitimate response for later if both
+    * pipes are already allocated and we're asked to do a detect.
     */
    for (i = 0; i < pI830->xf86_config.num_output; i++) 
    {
@@ -1414,16 +1412,16 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 
       output->status = (*output->funcs->detect) (output);
    }
-#if 0
-   RestoreHWState (pScrn);
-#endif
-   
+
    if (!xf86InitialConfiguration (pScrn))
    {
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
+      RestoreHWState(pScrn);
       PreInitCleanup(pScrn);
       return FALSE;
    }
+   RestoreHWState(pScrn);
+
    pScrn->displayWidth = (pScrn->virtualX + 63) & ~63;
     
    pI830->rotation = RR_Rotate_0;
diff-tree d3c21c09e3904b3d32aca7563044194b061ac2fa (from 9c3e733aaa2068fcb0164577237ed70d177e9b5a)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Dec 6 16:50:52 2006 -0800

    Remove stale i830_tv_pre_set_mode. Replaced by generic dpms hook call.
    
    Also replaced by not spamming unrelated ADPA register.  At least, it had sure
    better not be related.

diff --git a/src/i830_tv.c b/src/i830_tv.c
index 9f92ce0..b6cc2c9 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -287,18 +287,6 @@ i830_tv_mode_valid(xf86OutputPtr output,
     return MODE_OK;
 }
 
-static void
-i830_tv_pre_set_mode(xf86OutputPtr output, DisplayModePtr pMode)
-{
-    ScrnInfoPtr pScrn = output->scrn;
-    I830Ptr pI830 = I830PTR(pScrn);
-
-    /* Disable the encoder while we set up the pipe. */
-    OUTREG(TV_CTL, INREG(TV_CTL) & ~TV_ENC_ENABLE);
-    /* XXX match BIOS for now */
-    OUTREG(ADPA, 0x40008C18);
-}
-
 static const CARD32 h_luma[60] = {
     0xB1403000, 0x2E203500, 0x35002E20, 0x3000B140,
     0x35A0B160, 0x2DC02E80, 0xB1403480, 0xB1603000,
diff-tree 9c3e733aaa2068fcb0164577237ed70d177e9b5a (from d5ec9d2160f47f21a6015c1cc05b57274cbb0471)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Dec 6 16:36:42 2006 -0800

    Save/restore more TV registers.

diff --git a/src/i830_tv.c b/src/i830_tv.c
index d44d58e..9f92ce0 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -59,6 +59,26 @@ struct i830_tv_priv {
     CARD32 save_TV_V_CTL_6;
     CARD32 save_TV_V_CTL_7;
     CARD32 save_TV_SC_CTL_1, save_TV_SC_CTL_2, save_TV_SC_CTL_3;
+
+    CARD32 save_TV_CSC_Y;
+    CARD32 save_TV_CSC_Y2;
+    CARD32 save_TV_CSC_U;
+    CARD32 save_TV_CSC_U2;
+    CARD32 save_TV_CSC_V;
+    CARD32 save_TV_CSC_V2;
+    CARD32 save_TV_CLR_KNOBS;
+    CARD32 save_TV_CLR_LEVEL;
+    CARD32 save_TV_WIN_POS;
+    CARD32 save_TV_WIN_SIZE;
+    CARD32 save_TV_FILTER_CTL_1;
+    CARD32 save_TV_FILTER_CTL_2;
+    CARD32 save_TV_FILTER_CTL_3;
+
+    CARD32 save_TV_H_LUMA[60];
+    CARD32 save_TV_H_CHROMA[60];
+    CARD32 save_TV_V_LUMA[43];
+    CARD32 save_TV_V_CHROMA[43];
+
     CARD32 save_TV_DAC;
     CARD32 save_TV_CTL;
 };
@@ -168,6 +188,7 @@ i830_tv_save(xf86OutputPtr output)
     I830Ptr		    pI830 = I830PTR(pScrn);
     I830OutputPrivatePtr    intel_output = output->driver_private;
     struct i830_tv_priv	    *dev_priv = intel_output->dev_priv;
+    int			    i;
 
     dev_priv->save_TV_H_CTL_1 = INREG(TV_H_CTL_1);
     dev_priv->save_TV_H_CTL_2 = INREG(TV_H_CTL_2);
@@ -183,6 +204,29 @@ i830_tv_save(xf86OutputPtr output)
     dev_priv->save_TV_SC_CTL_2 = INREG(TV_SC_CTL_2);
     dev_priv->save_TV_SC_CTL_3 = INREG(TV_SC_CTL_3);
 
+    dev_priv->save_TV_CSC_Y = INREG(TV_CSC_Y);
+    dev_priv->save_TV_CSC_Y2 = INREG(TV_CSC_Y2);
+    dev_priv->save_TV_CSC_U = INREG(TV_CSC_U);
+    dev_priv->save_TV_CSC_U2 = INREG(TV_CSC_U2);
+    dev_priv->save_TV_CSC_V = INREG(TV_CSC_V);
+    dev_priv->save_TV_CSC_V2 = INREG(TV_CSC_V2);
+    dev_priv->save_TV_CLR_KNOBS = INREG(TV_CLR_KNOBS);
+    dev_priv->save_TV_CLR_LEVEL = INREG(TV_CLR_LEVEL);
+    dev_priv->save_TV_WIN_POS = INREG(TV_WIN_POS);
+    dev_priv->save_TV_WIN_SIZE = INREG(TV_WIN_SIZE);
+    dev_priv->save_TV_FILTER_CTL_1 = INREG(TV_FILTER_CTL_1);
+    dev_priv->save_TV_FILTER_CTL_2 = INREG(TV_FILTER_CTL_2);
+    dev_priv->save_TV_FILTER_CTL_3 = INREG(TV_FILTER_CTL_3);
+
+    for (i = 0; i < 60; i++)
+	dev_priv->save_TV_H_LUMA[i] = INREG(TV_H_LUMA_0 + (i <<2));
+    for (i = 0; i < 60; i++)
+	dev_priv->save_TV_H_CHROMA[i] = INREG(TV_H_CHROMA_0 + (i <<2));
+    for (i = 0; i < 43; i++)
+	dev_priv->save_TV_V_LUMA[i] = INREG(TV_V_LUMA_0 + (i <<2));
+    for (i = 0; i < 43; i++)
+	dev_priv->save_TV_V_CHROMA[i] = INREG(TV_V_CHROMA_0 + (i <<2));
+
     dev_priv->save_TV_DAC = INREG(TV_DAC);
     dev_priv->save_TV_CTL = INREG(TV_CTL);
 }
@@ -194,6 +238,7 @@ i830_tv_restore(xf86OutputPtr output)
     I830Ptr		    pI830 = I830PTR(pScrn);
     I830OutputPrivatePtr    intel_output = output->driver_private;
     struct i830_tv_priv	    *dev_priv = intel_output->dev_priv;
+    int			    i;
 
     OUTREG(TV_H_CTL_1, dev_priv->save_TV_H_CTL_1);
     OUTREG(TV_H_CTL_2, dev_priv->save_TV_H_CTL_2);
@@ -209,6 +254,29 @@ i830_tv_restore(xf86OutputPtr output)
     OUTREG(TV_SC_CTL_2, dev_priv->save_TV_SC_CTL_2);
     OUTREG(TV_SC_CTL_3, dev_priv->save_TV_SC_CTL_3);
 
+    OUTREG(TV_CSC_Y, dev_priv->save_TV_CSC_Y);
+    OUTREG(TV_CSC_Y2, dev_priv->save_TV_CSC_Y2);
+    OUTREG(TV_CSC_U, dev_priv->save_TV_CSC_U);
+    OUTREG(TV_CSC_U2, dev_priv->save_TV_CSC_U2);
+    OUTREG(TV_CSC_V, dev_priv->save_TV_CSC_V);
+    OUTREG(TV_CSC_V2, dev_priv->save_TV_CSC_V2);
+    OUTREG(TV_CLR_KNOBS, dev_priv->save_TV_CLR_KNOBS);
+    OUTREG(TV_CLR_LEVEL, dev_priv->save_TV_CLR_LEVEL);
+    OUTREG(TV_WIN_POS, dev_priv->save_TV_WIN_POS);
+    OUTREG(TV_WIN_SIZE, dev_priv->save_TV_WIN_SIZE);
+    OUTREG(TV_FILTER_CTL_1, dev_priv->save_TV_FILTER_CTL_1);
+    OUTREG(TV_FILTER_CTL_2, dev_priv->save_TV_FILTER_CTL_2);
+    OUTREG(TV_FILTER_CTL_3, dev_priv->save_TV_FILTER_CTL_3);
+
+    for (i = 0; i < 60; i++)
+	OUTREG(TV_H_LUMA_0 + (i <<2), dev_priv->save_TV_H_LUMA[i]);
+    for (i = 0; i < 60; i++)
+	OUTREG(TV_H_CHROMA_0 + (i <<2), dev_priv->save_TV_H_CHROMA[i]);
+    for (i = 0; i < 43; i++)
+	OUTREG(TV_V_LUMA_0 + (i <<2), dev_priv->save_TV_V_LUMA[i]);
+    for (i = 0; i < 43; i++)
+	OUTREG(TV_V_CHROMA_0 + (i <<2), dev_priv->save_TV_V_CHROMA[i]);
+
     OUTREG(TV_DAC, dev_priv->save_TV_DAC);
     OUTREG(TV_CTL, dev_priv->save_TV_CTL);
 }
diff-tree d5ec9d2160f47f21a6015c1cc05b57274cbb0471 (from 5d345c13a949caef384a63769d7185885de6d26d)
Author: Keith Packard <keithp at bouzouki.jf.intel.com>
Date:   Wed Dec 6 14:44:40 2006 -0800

    Cannot modify DPLL register in output mode_set function.
    
    DPLL register contains clock setup, so it cannot be written
    from the output mode_set function or 'bad things' happen.

diff --git a/src/i830_display.c b/src/i830_display.c
index 3d0c3af..0e5a09a 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -624,15 +624,22 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
 
     fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
 
-    i830PrintPll("chosen", &clock);
-    ErrorF("clock regs: 0x%08x, 0x%08x\n", (int)dpll, (int)fp);
-
     dpll = DPLL_VGA_MODE_DIS;
     if (IS_I9XX(pI830)) {
 	if (is_lvds)
 	    dpll |= DPLLB_MODE_LVDS;
 	else
 	    dpll |= DPLLB_MODE_DAC_SERIAL;
+	if (is_sdvo)
+	{
+	    dpll |= DPLL_DVO_HIGH_SPEED;
+	    if (IS_I945G(pI830) || IS_I945GM(pI830))
+	    {
+		int sdvo_pixel_multiply = adjusted_mode->Clock / mode->Clock;
+		dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
+	    }
+	}
+	
 	/* compute bitmask from p1 value */
 	dpll |= (1 << (clock.p1 - 1)) << 16;
 	switch (clock.p2) {
@@ -719,6 +726,9 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
 	    pipeconf &= ~PIPEACONF_DOUBLE_WIDE;
     }
 
+    i830PrintPll("chosen", &clock);
+    ErrorF("clock regs: 0x%08x, 0x%08x\n", (int)dpll, (int)fp);
+
     OUTREG(fp_reg, fp);
     OUTREG(dpll_reg, dpll);
     if (IS_I965G(pI830)) {
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 331a519..87dc9d9 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -557,8 +557,7 @@ i830_sdvo_mode_set(xf86OutputPtr output,
     xf86CrtcPtr	    crtc = output->crtc;
     I830CrtcPrivatePtr	    intel_crtc = crtc->driver_private;
     Bool input1, input2;
-    CARD32 dpll, sdvox;
-    int dpll_reg = (intel_crtc->pipe == 0) ? DPLL_A : DPLL_B;
+    CARD32 sdvox;
     int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD;
     int sdvo_pixel_multiply;
     int i;
@@ -614,9 +613,6 @@ i830_sdvo_mode_set(xf86OutputPtr output,
     output_dtd.part2.v_sync_off_high = v_sync_offset & 0xc0;
     output_dtd.part2.reserved = 0;
 
-    /* Turn off the screens before adjusting timings */
-    i830_sdvo_set_active_outputs(output, 0);
-
     /* Set the output timing to the screen */
     i830_sdvo_set_target_output(output, dev_priv->active_outputs);
     i830_sdvo_set_output_timing(output, &output_dtd);
@@ -668,20 +664,16 @@ i830_sdvo_mode_set(xf86OutputPtr output,
     if (intel_crtc->pipe == 1)
 	sdvox |= SDVO_PIPE_B_SELECT;
 
-    dpll = INREG(dpll_reg);
-
     sdvo_pixel_multiply = i830_sdvo_get_pixel_multiplier(mode);
     if (IS_I965G(pI830)) {
 	OUTREG(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) |
 	       ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT));
     } else if (IS_I945G(pI830) || IS_I945GM(pI830)) {
-	dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
+	/* done in crtc_mode_set as it lives inside the dpll register */
     } else {
 	sdvox |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT;
     }
 
-    OUTREG(dpll_reg, dpll | DPLL_DVO_HIGH_SPEED);
-
     OUTREG(dev_priv->output_device, sdvox);
 
     for (i = 0; i < 2; i++)
@@ -695,9 +687,6 @@ i830_sdvo_mode_set(xf86OutputPtr output,
 		   "First %s output reported failure to sync\n",
 		   SDVO_NAME(dev_priv));
     }
-
-    i830_sdvo_set_active_outputs(output, dev_priv->active_outputs);
-    i830_sdvo_set_target_input(output, TRUE, FALSE);
 }
 
 static void
diff-tree 5d345c13a949caef384a63769d7185885de6d26d (from 6ee63364f5fabbc5578bcc9ded38c778595f5a6d)
Author: Keith Packard <keithp at bouzouki.jf.intel.com>
Date:   Wed Dec 6 13:19:58 2006 -0800

    Clean up SDVO multiplier debug output

diff --git a/src/i830_debug.c b/src/i830_debug.c
index 9f4dd29..8c8b95e 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -159,7 +159,7 @@ DEBUGSTRING(i830_debug_dpll)
 	break;
     }
     if (IS_I945G(pI830) || IS_I945GM(pI830)) {
-	sprintf(sdvoextra, "SDVO mult %d",
+	sprintf(sdvoextra, ", SDVO mult %d",
 		(int)(val & SDVO_MULTIPLIER_MASK) >>
 		SDVO_MULTIPLIER_SHIFT_HIRES);
     } else {
diff-tree 6ee63364f5fabbc5578bcc9ded38c778595f5a6d (from parents)
Merge: 56f71194157ef929b62fe34a89c840bd59e56301 b75ecdb48309a15eb7c52b279c7f8523a95bcd48
Author: Keith Packard <keithp at bouzouki.jf.intel.com>
Date:   Wed Dec 6 12:53:22 2006 -0800

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

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

    Merge branch 'generic-mode-set' into modesetting

diff --cc src/i830_debug.c
index f732389,b14f981..b1902ff
@@@ -181,14 -331,31 +331,31 @@@
      int i;
  
      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 -	       "Comparing regs before/after X's VT usage\n");
 +	       "Comparing regs from server start up to %s\n", where);
      for (i = 0; i < NUM_I830_SNAPSHOTREGS; i++) {
  	CARD32 val = INREG(i830_snapshot[i].reg);
- 	if (i830_snapshot[i].regval != val) {
+ 	if (i830_snapshot[i].val == val)
+ 	    continue;
+ 
+ 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ 		   "Register 0x%x (%s) changed from 0x%08x to 0x%08x\n",
+ 		   i830_snapshot[i].reg, i830_snapshot[i].name,
+ 		   (int)i830_snapshot[i].val, (int)val);
+ 
+ 	if (i830_snapshot[i].debug_output != NULL) {
+ 	    char *before, *after;
+ 
+ 	    before = i830_snapshot[i].debug_output(pI830,
+ 						   i830_snapshot[i].reg,
+ 						   i830_snapshot[i].val);
+ 	    after = i830_snapshot[i].debug_output(pI830,
+ 						  i830_snapshot[i].reg,
+ 						  val);
  	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- 		       "Register 0x%x (%s) changed from 0x%08x to 0x%08x\n",
- 		       i830_snapshot[i].reg, i830_snapshot[i].name,
- 		       (int)i830_snapshot[i].regval, (int)val);
+ 		       "%s before: %s\n", i830_snapshot[i].name, before);
+ 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ 		       "%s after: %s\n", i830_snapshot[i].name, after);
+ 
  	}
      }
  }
diff-tree b3bb10e33e44c78f132d239e30931f97065a9fd6 (from 47d07b1073c162ec00a8b173b8b6389dc4adbe88)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Dec 6 11:53:40 2006 -0800

    Fix LVDS: Don't change bits in LVDS other than port enable/pipe select.
    
    This behavior matches what we did before when LVDS worked.

diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index 2c044e9..97f3852 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -199,7 +199,7 @@ i830_lvds_mode_set(xf86OutputPtr output,
      * This is an exception to the general rule that mode_set doesn't turn
      * things on.
      */
-    OUTREG(LVDS, LVDS_PORT_EN | LVDS_PIPEB_SELECT);
+    OUTREG(LVDS, INREG(LVDS) | LVDS_PORT_EN | LVDS_PIPEB_SELECT);
 
     /* Enable automatic panel scaling so that non-native modes fill the
      * screen.  Should be enabled before the pipe is enabled, according to
diff-tree 47d07b1073c162ec00a8b173b8b6389dc4adbe88 (from 727bf1cbf72362edcbdd68001a3558fd2b2b4eca)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Dec 6 10:56:38 2006 -0800

    More LVDS fixed mode fixing: use the EDID DTD's blank length.

diff --git a/src/i830_bios.c b/src/i830_bios.c
index 4a1bdb1..a9ef474 100644
--- a/src/i830_bios.c
+++ b/src/i830_bios.c
@@ -210,13 +210,14 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScr
 		_H_SYNC_OFF(timing_ptr);
 	    fixed_mode->HSyncEnd   = fixed_mode->HSyncStart +
 		_H_SYNC_WIDTH(timing_ptr);
-	    fixed_mode->HTotal     = fixed_mode->HSyncEnd +
-		1;
+	    fixed_mode->HTotal     = fixed_mode->HDisplay +
+	        _H_BLANK(timing_ptr);
 	    fixed_mode->VSyncStart = fixed_mode->VDisplay +
 		_V_SYNC_OFF(timing_ptr);
 	    fixed_mode->VSyncEnd   = fixed_mode->VSyncStart +
 		_V_SYNC_WIDTH(timing_ptr);
-	    fixed_mode->VTotal     = fixed_mode->VSyncEnd + 1;
+	    fixed_mode->VTotal     = fixed_mode->VDisplay +
+	        _V_BLANK(timing_ptr);
 	    fixed_mode->Clock      = _PIXEL_CLOCK(timing_ptr) / 1000;
 	    fixed_mode->type       = M_T_PREFERRED;
 
diff-tree 727bf1cbf72362edcbdd68001a3558fd2b2b4eca (from 236c53be5d94798d55219651a6885fee32ce175b)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Dec 6 10:12:49 2006 -0800

    Add missing newlines to new debug output.

diff --git a/src/i830_debug.c b/src/i830_debug.c
index 68c4b5d..b14f981 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -352,9 +352,9 @@ void i830CompareRegsToSnapshot(ScrnInfoP
 						  i830_snapshot[i].reg,
 						  val);
 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		       "%s before: %s", i830_snapshot[i].name, before);
+		       "%s before: %s\n", i830_snapshot[i].name, before);
 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		       "%s after: %s", i830_snapshot[i].name, after);
+		       "%s after: %s\n", i830_snapshot[i].name, after);
 
 	}
     }
diff-tree 236c53be5d94798d55219651a6885fee32ce175b (from 1d94ec7de3387b70815679977cfc5d88200efa99)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Dec 6 10:10:27 2006 -0800

    Fix LVDS fixed mode code after generic-mode-set.

diff --git a/src/i830.h b/src/i830.h
index 4cfed4b..ae6b536 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -438,19 +438,8 @@ typedef struct _I830Rec {
 
    int ddc2;
 
-   /* Panel size pulled from the BIOS */
-   int PanelXRes, PanelYRes;
-
    /* The BIOS's fixed timings for the LVDS */
-   int panel_fixed_clock;
-   int panel_fixed_hactive;
-   int panel_fixed_hblank;
-   int panel_fixed_hsyncoff;
-   int panel_fixed_hsyncwidth;
-   int panel_fixed_vactive;
-   int panel_fixed_vblank;
-   int panel_fixed_vsyncoff;
-   int panel_fixed_vsyncwidth;
+   DisplayModePtr panel_fixed_mode;
 
    int backlight_duty_cycle;  /* restore backlight to this value */
    
diff --git a/src/i830_bios.c b/src/i830_bios.c
index 0821845..4a1bdb1 100644
--- a/src/i830_bios.c
+++ b/src/i830_bios.c
@@ -158,6 +158,7 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScr
 	struct lvds_bdb_2 *lvds2;
 	struct lvds_bdb_2_fp_params *fpparam;
 	struct lvds_bdb_2_fp_edid_dtd *fptiming;
+	DisplayModePtr fixed_mode;
 	CARD8 *timing_ptr;
 
 	id = INTEL_BIOS_8(start);
@@ -197,32 +198,36 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScr
 		    continue;
 	    }
 
-	    pI830->PanelXRes = fpparam->x_res;
-	    pI830->PanelYRes = fpparam->y_res;
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		       "Found panel of size %dx%d in BIOS VBT tables\n",
-		       pI830->PanelXRes, pI830->PanelYRes);
+	    fixed_mode = xnfalloc(sizeof(DisplayModeRec));
+	    memset(fixed_mode, 0, sizeof(*fixed_mode));
 
 	    /* Since lvds_bdb_2_fp_edid_dtd is just an EDID detailed timing
 	     * block, pull the contents out using EDID macros.
 	     */
-	    pI830->panel_fixed_clock = _PIXEL_CLOCK(timing_ptr) / 1000;
-	    pI830->panel_fixed_hactive = _H_ACTIVE(timing_ptr);
-	    pI830->panel_fixed_hblank = _H_BLANK(timing_ptr);
-	    pI830->panel_fixed_hsyncoff = _H_SYNC_OFF(timing_ptr);
-	    pI830->panel_fixed_hsyncwidth = _H_SYNC_WIDTH(timing_ptr);
-
-	    pI830->panel_fixed_vactive = _V_ACTIVE(timing_ptr);
-	    pI830->panel_fixed_vblank = _V_BLANK(timing_ptr);
-	    pI830->panel_fixed_vsyncoff = _V_SYNC_OFF(timing_ptr);
-	    pI830->panel_fixed_vsyncwidth = _V_SYNC_WIDTH(timing_ptr);
+	    fixed_mode->HDisplay   = _H_ACTIVE(timing_ptr);
+	    fixed_mode->VDisplay   = _V_ACTIVE(timing_ptr);
+	    fixed_mode->HSyncStart = fixed_mode->HDisplay +
+		_H_SYNC_OFF(timing_ptr);
+	    fixed_mode->HSyncEnd   = fixed_mode->HSyncStart +
+		_H_SYNC_WIDTH(timing_ptr);
+	    fixed_mode->HTotal     = fixed_mode->HSyncEnd +
+		1;
+	    fixed_mode->VSyncStart = fixed_mode->VDisplay +
+		_V_SYNC_OFF(timing_ptr);
+	    fixed_mode->VSyncEnd   = fixed_mode->VSyncStart +
+		_V_SYNC_WIDTH(timing_ptr);
+	    fixed_mode->VTotal     = fixed_mode->VSyncEnd + 1;
+	    fixed_mode->Clock      = _PIXEL_CLOCK(timing_ptr) / 1000;
+	    fixed_mode->type       = M_T_PREFERRED;
+
+	    xf86SetModeDefaultName(fixed_mode);
+
 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		       "Panel mode h active %d blank %d rate %f v active %d blank %d rate %f\n",
-		       pI830->panel_fixed_hactive, pI830->panel_fixed_hblank,
-		       (double) pI830->panel_fixed_clock / (pI830->panel_fixed_hactive + pI830->panel_fixed_hblank),
-		       pI830->panel_fixed_vactive, pI830->panel_fixed_vblank,
-		       (double) pI830->panel_fixed_clock / 
-		       ((pI830->panel_fixed_hactive + pI830->panel_fixed_hblank) * (pI830->panel_fixed_vactive + pI830->panel_fixed_vblank)));
+		       "Found panel mode in BIOS VBT tables:\n");
+	    xf86PrintModeline(pScrn->scrnIndex, fixed_mode);
+
+	    pI830->panel_fixed_mode = fixed_mode;
+
 	    found_panel_info = TRUE;
 	    break;
 	}
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index a9c0e20..2c044e9 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -161,22 +161,16 @@ i830_lvds_mode_fixup(xf86OutputPtr outpu
      * with the panel scaling set up to source from the H/VDisplay
      * of the original mode.
      */
-    if (pI830->panel_fixed_hactive != 0) {
-	adjusted_mode->HDisplay = pI830->panel_fixed_hactive;
-	adjusted_mode->HTotal = adjusted_mode->HDisplay +
-	    pI830->panel_fixed_hblank;
-	adjusted_mode->HSyncStart = adjusted_mode->HDisplay +
-	    pI830->panel_fixed_hsyncoff;
-	adjusted_mode->HSyncStart = adjusted_mode->HSyncStart +
-	    pI830->panel_fixed_hsyncwidth;
-	adjusted_mode->VDisplay = pI830->panel_fixed_vactive;
-	adjusted_mode->VTotal = adjusted_mode->VDisplay +
-	    pI830->panel_fixed_hblank;
-	adjusted_mode->VSyncStart = adjusted_mode->VDisplay +
-	    pI830->panel_fixed_hsyncoff;
-	adjusted_mode->VSyncStart = adjusted_mode->VSyncStart +
-	    pI830->panel_fixed_hsyncwidth;
-	adjusted_mode->Clock = pI830->panel_fixed_clock;
+    if (pI830->panel_fixed_mode != NULL) {
+	adjusted_mode->HDisplay = pI830->panel_fixed_mode->HDisplay;
+	adjusted_mode->HSyncStart = pI830->panel_fixed_mode->HSyncStart;
+	adjusted_mode->HSyncEnd = pI830->panel_fixed_mode->HSyncEnd;
+	adjusted_mode->HTotal = pI830->panel_fixed_mode->HTotal;
+	adjusted_mode->VDisplay = pI830->panel_fixed_mode->VDisplay;
+	adjusted_mode->VSyncStart = pI830->panel_fixed_mode->VSyncStart;
+	adjusted_mode->VSyncEnd = pI830->panel_fixed_mode->VSyncEnd;
+	adjusted_mode->VTotal = pI830->panel_fixed_mode->VTotal;
+	adjusted_mode->Clock = pI830->panel_fixed_mode->Clock;
 	xf86SetModeCrtc(adjusted_mode, INTERLACE_HALVE_V);
     }
 
@@ -241,30 +235,16 @@ i830_lvds_get_modes(xf86OutputPtr output
 {
     ScrnInfoPtr	    pScrn = output->scrn;
     I830Ptr	    pI830 = I830PTR(pScrn);
-    DisplayModePtr  modes, new;
-    char	    stmp[32];
+    DisplayModePtr  modes;
 
     modes = i830_ddc_get_modes(output);
     if (modes != NULL)
 	return modes;
 
-    new             = xnfcalloc(1, sizeof (DisplayModeRec));
-    sprintf(stmp, "%dx%d", pI830->PanelXRes, pI830->PanelYRes);
-    new->name       = xnfalloc(strlen(stmp) + 1);
-    strcpy(new->name, stmp);
-    new->HDisplay   = pI830->PanelXRes;
-    new->VDisplay   = pI830->PanelYRes;
-    new->HSyncStart = pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff;
-    new->HSyncEnd   = new->HSyncStart + pI830->panel_fixed_hsyncwidth;
-    new->HTotal     = new->HSyncEnd + 1;
-    new->VSyncStart = pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff;
-    new->VSyncEnd   = new->VSyncStart + pI830->panel_fixed_vsyncwidth;
-    new->VTotal     = new->VSyncEnd + 1;
-    new->Clock      = pI830->panel_fixed_clock;
+    if (pI830->panel_fixed_mode != NULL)
+	return xf86DuplicateMode(pI830->panel_fixed_mode);
 
-    new->type       = M_T_PREFERRED;
-
-    return new;
+    return NULL;
 }
 
 static void
@@ -321,7 +301,9 @@ i830_lvds_init(ScrnInfoPtr pScrn)
 	     * display.
 	     */
 
-	    if (pI830->PanelXRes == 800 && pI830->PanelYRes == 600) {
+	    if (pI830->panel_fixed_mode != NULL &&
+		pI830->panel_fixed_mode->HDisplay == 800 &&
+		pI830->panel_fixed_mode->VDisplay == 600) {
 		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 			   "Suspected Mac Mini, ignoring the LVDS\n");
 		return;
diff-tree 1cb6311c1182fe98d2b8d237cef42509c3178f9a (from ffd8aacbe7c72b696ff7257609e3c1d45c057609)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Dec 6 16:31:00 2006 +0800

    fix typo in checking xf86CrtcScreenInit return

diff --git a/src/i830_randr.c b/src/i830_randr.c
index 0077020..a6d71f2 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -900,7 +900,7 @@ xf86RandR12Init12 (ScreenPtr pScreen)
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
     rrScrPrivPtr	rp = rrGetScrPriv(pScreen);
 
-    if (xf86CrtcScreenInit (pScreen))
+    if (!xf86CrtcScreenInit (pScreen))
 	return FALSE;
 
     rp->rrGetInfo = xf86RandR12GetInfo12;
diff-tree 56f71194157ef929b62fe34a89c840bd59e56301 (from ffd8aacbe7c72b696ff7257609e3c1d45c057609)
Author: Keith Packard <keithp at mandolin.keithp.com>
Date:   Wed Dec 6 00:13:57 2006 -0800

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

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

    new server APIs are not in server-1.2 (version 7.1.99.2)

diff --git a/src/i830_display.h b/src/i830_display.h
index c80c3f7..d140e09 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -44,11 +44,11 @@ Bool i830PipeInUse(xf86CrtcPtr crtc);
 
 /** @{
  */
-#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,1,99,2,0)
+#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,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) */
+#endif /* XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2) */
 /** @} */
diff --git a/src/i830_edid_modes.c b/src/i830_edid_modes.c
index fcb71d2..3becbb5 100644
--- a/src/i830_edid_modes.c
+++ b/src/i830_edid_modes.c
@@ -38,7 +38,7 @@
 #include "i830.h"
 #include "i830_display.h"
 
-#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,1,99,2,0)
+#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0)
 
 /*
  * TODO:
@@ -208,4 +208,4 @@ xf86DDCGetModes(int scrnIndex, xf86MonPt
     return Modes;
 }
 
-#endif /* XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,1,99,2,0) */
+#endif /* XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0) */
diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c
index c091aef..1afda95 100644
--- a/src/i830_xf86Modes.c
+++ b/src/i830_xf86Modes.c
@@ -45,7 +45,7 @@
  * there but we still want to use.  We need to come up with better API here.
  */
 
-#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,1,99,2,0)
+#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0)
 /**
  * Calculates the horizontal sync rate of a mode.
  *
@@ -321,7 +321,7 @@ xf86PrintModeline(int scrnIndex,DisplayM
 		   mode->VTotal, flags, xf86ModeHSync(mode));
     xfree(flags);
 }
-#endif /* XORG_VERSION_CURRENT <= 7.1.99.2 */
+#endif /* XORG_VERSION_CURRENT <= 7.2.99.2 */
 
 /**
  * Marks as bad any modes with unsupported flags.
diff --git a/src/i830_xf86Modes.h b/src/i830_xf86Modes.h
index 3bd8557..9830003 100644
--- a/src/i830_xf86Modes.h
+++ b/src/i830_xf86Modes.h
@@ -29,7 +29,7 @@
 #define _I830_XF86MODES_H_
 #include "xorgVersion.h"
 
-#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,1,99,2,0)
+#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0)
 double i830_xf86ModeHSync(DisplayModePtr mode);
 double i830_xf86ModeVRefresh(DisplayModePtr mode);
 DisplayModePtr i830_xf86DuplicateMode(DisplayModePtr pMode);
@@ -50,7 +50,7 @@ DisplayModePtr i830_xf86ModesAdd(Display
 #define xf86ModesEqual i830_xf86ModesEqual
 #define xf86PrintModeline i830_xf86PrintModeline
 #define xf86ModesAdd i830_xf86ModesAdd
-#endif /* XORG_VERSION_CURRENT <= 7.1.99.2 */
+#endif /* XORG_VERSION_CURRENT <= 7.2.99.2 */
 
 void
 i830xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,
diff --git a/src/i830_xf86cvt.c b/src/i830_xf86cvt.c
index 0014056..dba57c8 100644
--- a/src/i830_xf86cvt.c
+++ b/src/i830_xf86cvt.c
@@ -40,7 +40,7 @@
 #include "i830.h"
 #include "i830_display.h"
 
-#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,1,99,2,0)
+#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0)
 /*
  * Generate a CVT standard mode from HDisplay, VDisplay and VRefresh.
  *
@@ -303,4 +303,4 @@ xf86CVTMode(int HDisplay, int VDisplay, 
 
     return Mode;
 }
-#endif /* XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,1,99,2,0) */
+#endif /* XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0) */
diff-tree a73649611414cb92697575efa90addfc3cf91cf9 (from 62fba80d3ea9c185ec8ae1e06c099c02bf844d8b)
Author: Keith Packard <keithp at mandolin.keithp.com>
Date:   Tue Dec 5 19:47:04 2006 -0800

    Capture VGA registers sooner so checks are more informative

diff --git a/src/i830_debug.c b/src/i830_debug.c
index d74d092..f732389 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -175,13 +175,13 @@ void i830TakeRegSnapshot(ScrnInfoPtr pSc
     }
 }
 
-void i830CompareRegsToSnapshot(ScrnInfoPtr pScrn)
+void i830CompareRegsToSnapshot(ScrnInfoPtr pScrn, char *where)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     int i;
 
     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-	       "Comparing regs before/after X's VT usage\n");
+	       "Comparing regs from server start up to %s\n", where);
     for (i = 0; i < NUM_I830_SNAPSHOTREGS; i++) {
 	CARD32 val = INREG(i830_snapshot[i].reg);
 	if (i830_snapshot[i].regval != val) {
diff --git a/src/i830_debug.h b/src/i830_debug.h
index a8e3839..a365085 100644
--- a/src/i830_debug.h
+++ b/src/i830_debug.h
@@ -26,5 +26,5 @@
  */
 
 void i830TakeRegSnapshot(ScrnInfoPtr pScrn);
-void i830CompareRegsToSnapshot(ScrnInfoPtr pScrn);
+void i830CompareRegsToSnapshot(ScrnInfoPtr pScrn, char *where);
 void i830DumpRegs (ScrnInfoPtr pScrn);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index c85fe4e..73af147 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -325,6 +325,9 @@ static Bool I830CloseScreen(int scrnInde
 static Bool I830SaveScreen(ScreenPtr pScreen, int unblack);
 static Bool I830EnterVT(int scrnIndex, int flags);
 static CARD32 I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg);
+static Bool SaveHWState(ScrnInfoPtr pScrn);
+static Bool RestoreHWState(ScrnInfoPtr pScrn);
+
 
 extern int I830EntityIndex;
 
@@ -1146,6 +1149,8 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    /* Some of the probing needs MMIO access, so map it here. */
    I830MapMMIO(pScrn);
 
+   i830TakeRegSnapshot(pScrn);
+
 #if 1
    pI830->saveSWF0 = INREG(SWF0);
    pI830->saveSWF4 = INREG(SWF4);
@@ -1360,18 +1365,22 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    }
 
 
+#if 0
+   SaveHWState (pScrn);
+#endif
    /* 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->xf86_config.num_output; i++) 
    {
       xf86OutputPtr	      output = pI830->xf86_config.output[i];
-      I830OutputPrivatePtr    intel_output = output->driver_private;
-      xf86CrtcPtr	      crtc;
-      int		      p;
 
       output_status[i] = (*output->funcs->detect) (output);
    }
+#if 0
+   RestoreHWState (pScrn);
+#endif
+   
    
    for (i = 0; i < pI830->xf86_config.num_output; i++) 
    {
@@ -1911,6 +1920,8 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       xf86LoaderReqSymLists(I810ramdacSymbols, NULL);
    }
 
+   i830CompareRegsToSnapshot(pScrn, "After PreInit");
+
    I830UnmapMMIO(pScrn);
 
    /*  We won't be using the VGA access after the probe. */
@@ -2187,8 +2198,6 @@ SaveHWState(ScrnInfoPtr pScrn)
 		 (unsigned long) temp);
    }
 
-   i830TakeRegSnapshot(pScrn);
-
    /* Save video mode information for native mode-setting. */
    pI830->saveDSPACNTR = INREG(DSPACNTR);
    pI830->savePIPEACONF = INREG(PIPEACONF);
@@ -2380,7 +2389,8 @@ RestoreHWState(ScrnInfoPtr pScrn)
    OUTREG(SWF31, pI830->saveSWF[15]);
    OUTREG(SWF32, pI830->saveSWF[16]);
 
-   i830CompareRegsToSnapshot(pScrn);
+   i830CompareRegsToSnapshot(pScrn, "After RestoreHWState");
+   i830DumpRegs (pScrn);
 
    return TRUE;
 }
diff-tree 62fba80d3ea9c185ec8ae1e06c099c02bf844d8b (from 2e8c927f9308069a82f25b65bb0c62bc5a156832)
Author: Keith Packard <keithp at mandolin.keithp.com>
Date:   Tue Dec 5 19:43:41 2006 -0800

    fix up misleading comment in i830_crt.c about border register

diff --git a/src/i830_crt.c b/src/i830_crt.c
index 7a706d1..bf23f9e 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -221,9 +221,7 @@ i830_crt_detect_load (xf86CrtcPtr	    cr
     adpa |= ADPA_VSYNC_CNTL_ENABLE | ADPA_HSYNC_CNTL_ENABLE;
     OUTREG(ADPA, adpa);
 
-    /* Set the border color to purple.  Maybe we should save/restore this
-     * reg.
-     */
+    /* Set the border color to purple. */
     bclrpat = INREG(bclrpat_reg);
     OUTREG(bclrpat_reg, 0x00500050);
 
diff-tree 1d94ec7de3387b70815679977cfc5d88200efa99 (from eee23fdd0dadd38a2b80525ec886120150f91077)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Dec 5 18:22:59 2006 -0800

    Fix ordering of PIPE[AB]SRC debug output to be (x, y).

diff --git a/src/i830_debug.c b/src/i830_debug.c
index 97b0983..68c4b5d 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -41,6 +41,12 @@ DEBUGSTRING(i830_debug_xyminus1)
 		     ((val & 0xffff0000) >> 16) + 1);
 }
 
+DEBUGSTRING(i830_debug_yxminus1)
+{
+    return XNFprintf("%d, %d", ((val & 0xffff0000) >> 16) + 1,
+		     (val & 0xffff) + 1);
+}
+
 DEBUGSTRING(i830_debug_xy)
 {
     return XNFprintf("%d, %d", (val & 0xffff),
@@ -228,7 +234,7 @@ static struct i830SnapshotRec {
     DEFINEREG(DSPASURF),
     DEFINEREG(DSPATILEOFF),
     DEFINEREG2(PIPEACONF, i830_debug_pipeconf),
-    DEFINEREG2(PIPEASRC, i830_debug_xyminus1),
+    DEFINEREG2(PIPEASRC, i830_debug_yxminus1),
 
     DEFINEREG2(FPA0, i830_debug_fp),
     DEFINEREG2(FPA1, i830_debug_fp),
@@ -251,7 +257,7 @@ static struct i830SnapshotRec {
     DEFINEREG(DSPBSURF),
     DEFINEREG(DSPBTILEOFF),
     DEFINEREG2(PIPEBCONF, i830_debug_pipeconf),
-    DEFINEREG2(PIPEBSRC, i830_debug_xyminus1),
+    DEFINEREG2(PIPEBSRC, i830_debug_yxminus1),
 
     DEFINEREG2(FPB0, i830_debug_fp),
     DEFINEREG2(FPB1, i830_debug_fp),
diff-tree eee23fdd0dadd38a2b80525ec886120150f91077 (from 58c247c6de56508b00eadf77b4c145c94134270d)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Dec 5 18:19:49 2006 -0800

    Fix copy'n'paste-o of the ordering of h/v fields in DSP[AB]SIZE.

diff --git a/src/i830_display.c b/src/i830_display.c
index 03a7765..d822083 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -745,7 +745,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
     /* pipesrc and dspsize control the size that is scaled from, which should
      * always be the user's requested size.
      */
-    OUTREG(dspsize_reg, ((mode->HDisplay - 1) << 16) | (mode->VDisplay - 1));
+    OUTREG(dspsize_reg, ((mode->VDisplay - 1) << 16) | (mode->HDisplay - 1));
     OUTREG(dsppos_reg, 0);
     i830PipeSetBase(crtc, crtc->x, crtc->y);
     OUTREG(pipesrc_reg, ((mode->HDisplay - 1) << 16) | (mode->VDisplay - 1));
diff-tree 58c247c6de56508b00eadf77b4c145c94134270d (from parents)
Merge: 0b4c3e7bff790e1e99ace5036a41e96046335b04 2e8c927f9308069a82f25b65bb0c62bc5a156832
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Dec 5 15:28:21 2006 -0800

    Merge branch 'modesetting-origin' into modesetting
    
    Conflicts:
    
    	src/i830_display.c

diff --cc src/i830_display.c
index d7d7417,ac56528..03a7765
@@@ -506,20 -516,34 +576,20 @@@
      int dspstride_reg = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
      int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
      int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
-     int m1 = 0, m2 = 0, n = 0, p1 = 0, p2 = 0;
 -    int pipestat_reg = (pipe == 0) ? PIPEASTAT : PIPEBSTAT;
 -    Bool ret = FALSE;
 -#ifdef XF86DRI
 -    Bool didLock = FALSE;
 -#endif
 -
 -    if (xf86ModesEqual(&crtc->curMode, pMode))
 -	return TRUE;
 -
 -    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested pix clock: %d\n",
 -	       pMode->Clock);
 -
 -    crtc->enabled = i830PipeInUse (crtc);
 -    
 -    if (!crtc->enabled)
 -    {
 -	/* XXX disable crtc? */
 -	return TRUE;
 -    }
 +    int i;
 +    int refclk;
-     CARD32 dpll = 0, fp = 0, temp, dspcntr;
++    intel_clock_t clock;
++    CARD32 dpll = 0, fp = 0, dspcntr, pipeconf;
 +    Bool ok, is_sdvo = FALSE, is_dvo = FALSE;
 +    Bool is_crt = FALSE, is_lvds = FALSE, is_tv = FALSE;
  
 -#ifdef XF86DRI
 -    didLock = I830DRILock(pScrn);
 -#endif
 -    
 -    for (i = 0; i < pI830->xf86_config.num_output; i++) 
 -    {
 +    /* Set up some convenient bools for what outputs are connected to
 +     * our pipe, used in DPLL setup.
 +     */
 +    for (i = 0; i < pI830->xf86_config.num_output; i++) {
  	xf86OutputPtr  output = pI830->xf86_config.output[i];
 -	I830OutputPrivatePtr	intel_output = output->driver_private;
 +	I830OutputPrivatePtr intel_output = output->driver_private;
 +
  	if (output->crtc != crtc)
  	    continue;
  
@@@ -547,18 -643,15 +617,17 @@@
      } else {
  	refclk = 48000;
      }
 -    
 -    ok = i830FindBestPLL(crtc, pixel_clock, refclk, &clock);
 -    if (!ok) {
 -	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 -		   "Couldn't find PLL settings for mode!\n");
 -	goto done;
 -    }
  
-     ok = i830FindBestPLL(crtc, adjusted_mode->Clock, refclk, &m1, &m2, &n,
- 			 &p1, &p2);
 -    dpll = DPLL_VCO_ENABLE | DPLL_VGA_MODE_DIS;
++    ok = i830FindBestPLL(crtc, adjusted_mode->Clock, refclk, &clock);
 +    if (!ok)
 +	FatalError("Couldn't find PLL settings for mode!\n");
 +
-     fp = ((n - 2) << 16) | ((m1 - 2) << 8) | (m2 - 2);
++    fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
 +
-     i830PrintPll("chosen", refclk, m1, m2, n, p1, p2);
++    i830PrintPll("chosen", &clock);
 +    ErrorF("clock regs: 0x%08x, 0x%08x\n", (int)dpll, (int)fp);
 +
 +    dpll = DPLL_VGA_MODE_DIS;
      if (IS_I9XX(pI830)) {
  	if (is_lvds)
  	    dpll |= DPLLB_MODE_LVDS;
@@@ -628,137 -739,101 +697,176 @@@
      else
  	dspcntr |= DISPPLANE_SEL_PIPE_B;
  
 -    OUTREG(VGACNTRL, VGA_DISP_DISABLE);
 -
 -    /* Finally, set the mode. */
 -    /* First, disable display planes */
 -    temp = INREG(dspcntr_reg);
 -    OUTREG(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
 -
 -    /* Wait for vblank for the disable to take effect */
 -    i830WaitForVblank(pScrn);
 -
 -    /* Next, disable display pipes */
 -    temp = INREG(pipeconf_reg);
 -    OUTREG(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
 -
 -    OUTREG(fp_reg, fp);
 -    OUTREG(dpll_reg, dpll);
 -
 -    /*
 -     * If the panel fitter is stuck on our pipe, turn it off.
 -     * The LVDS output will set it as necessary in post_set_mode.
 -     */
 -    if (!IS_I830(pI830)) {
 -	if (((INREG(PFIT_CONTROL) >> 29) & 0x3) == pipe)
 -	    OUTREG(PFIT_CONTROL, 0);
 -    }
 -
 -    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);
 -    }
 -
 -    OUTREG(htot_reg, htot);
 -    OUTREG(hblank_reg, hblank);
 -    OUTREG(hsync_reg, hsync);
 -    OUTREG(vtot_reg, vtot);
 -    OUTREG(vblank_reg, vblank);
 -    OUTREG(vsync_reg, vsync);
 -    OUTREG(dspstride_reg, pScrn->displayWidth * pI830->cpp);
 -    OUTREG(dspsize_reg, dspsize);
 -    OUTREG(dsppos_reg, 0);
 -    i830PipeSetBase(crtc, crtc->x, crtc->y);
 -    OUTREG(pipesrc_reg, pipesrc);
 -
 -    /* Then, turn the pipe on first */
 -    temp = INREG(pipeconf_reg);
 -    temp |= PIPEACONF_ENABLE;
 -    if (!IS_I9XX(pI830) && pipe == 0)
 -    {
++    pipeconf = INREG(pipeconf_reg);
++    if (!IS_I9XX(pI830) && pipe == 0) {
+ 	/*
+ 	 * The docs say this is needed when the dot clock is > 90% of the
+ 	 * core speed. Core speeds are indicated by bits in the PCI
+ 	 * config space and don't seem to ever be less than 200MHz,
+ 	 * which is a bit confusing.
+ 	 *
+ 	 * However, For one little 855/852 card I have, 135000 requires
+ 	 * double wide mode, but 108000 does not. That makes no sense
+ 	 * but we're used to that. It may be affected by pixel size,
+ 	 * but the BIOS mode setting code doesn't appear to use that.
+ 	 *
+ 	 * It doesn't seem to cause any harm, although it
+ 	 * does restrict some output options.
+ 	 */
 -	if (pixel_clock > 108000)
 -	    temp |= PIPEACONF_DOUBLE_WIDE;
++	if (adjusted_mode->Clock > 108000)
++	    pipeconf |= PIPEACONF_DOUBLE_WIDE;
+ 	else
 -	    temp &= ~PIPEACONF_DOUBLE_WIDE;
++	    pipeconf &= ~PIPEACONF_DOUBLE_WIDE;
++    }
++
 +    OUTREG(fp_reg, fp);
 +    OUTREG(dpll_reg, dpll);
 +    if (IS_I965G(pI830)) {
 +	/* Set the SDVO multiplier/divider to 1x for the sake of analog output.
 +	 * It will be updated by the SDVO code if SDVO had fixed up the clock
 +	 * for a higher multiplier.
 +	 */
 +	OUTREG(dpll_md_reg, 0);
 +    }
 +
 +    OUTREG(htot_reg, (adjusted_mode->CrtcHDisplay - 1) |
 +	((adjusted_mode->CrtcHTotal - 1) << 16));
 +    OUTREG(hblank_reg, (adjusted_mode->CrtcHBlankStart - 1) |
 +	((adjusted_mode->CrtcHBlankEnd - 1) << 16));
 +    OUTREG(hsync_reg, (adjusted_mode->CrtcHSyncStart - 1) |
 +	((adjusted_mode->CrtcHSyncEnd - 1) << 16));
 +    OUTREG(vtot_reg, (adjusted_mode->CrtcVDisplay - 1) |
 +	((adjusted_mode->CrtcVTotal - 1) << 16));
 +    OUTREG(vblank_reg, (adjusted_mode->CrtcVBlankStart - 1) |
 +	((adjusted_mode->CrtcVBlankEnd - 1) << 16));
 +    OUTREG(vsync_reg, (adjusted_mode->CrtcVSyncStart - 1) |
 +	((adjusted_mode->CrtcVSyncEnd - 1) << 16));
 +    OUTREG(dspstride_reg, pScrn->displayWidth * pI830->cpp);
 +    /* pipesrc and dspsize control the size that is scaled from, which should
 +     * always be the user's requested size.
 +     */
 +    OUTREG(dspsize_reg, ((mode->HDisplay - 1) << 16) | (mode->VDisplay - 1));
 +    OUTREG(dsppos_reg, 0);
 +    i830PipeSetBase(crtc, crtc->x, crtc->y);
 +    OUTREG(pipesrc_reg, ((mode->HDisplay - 1) << 16) | (mode->VDisplay - 1));
-     temp = INREG(pipeconf_reg);
-     OUTREG(pipeconf_reg, temp);
++    OUTREG(pipeconf_reg, pipeconf);
 +    OUTREG(dspcntr_reg, dspcntr);
 +
 +    /* Disable the panel fitter if it was on our pipe */
 +    if (!IS_I830(pI830) && ((INREG(PFIT_CONTROL) >> 29) & 0x3) == pipe)
 +	OUTREG(PFIT_CONTROL, 0);
 +}
 +
 +/**
 + * Sets the given video mode on the given pipe.
 + *
 + * Plane A is always output to pipe A, and plane B to pipe B.  The plane
 + * will not be enabled if plane_enable is FALSE, which is used for
 + * load detection, when something else will be output to the pipe other than
 + * display data.
 + */
 +Bool
 +i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode,
 +		Bool plane_enable)
 +{
 +    ScrnInfoPtr pScrn = crtc->scrn;
 +    I830Ptr pI830 = I830PTR(pScrn);
 +    int i;
 +    Bool ret = FALSE;
 +#ifdef XF86DRI
 +    Bool didLock = FALSE;
 +#endif
 +    DisplayModePtr adjusted_mode;
 +
 +    /* XXX: curMode */
 +
 +    adjusted_mode = xf86DuplicateMode(pMode);
 +
 +    crtc->enabled = i830PipeInUse (crtc);
 +    
 +    if (!crtc->enabled)
 +    {
 +	/* XXX disable crtc? */
 +	return TRUE;
 +    }
 +
 +#ifdef XF86DRI
 +    didLock = I830DRILock(pScrn);
 +#endif
 +
 +    /* Pass our mode to the outputs and the CRTC to give them a chance to
 +     * adjust it according to limitations or output properties, and also
 +     * a chance to reject the mode entirely.
 +     */
 +    for (i = 0; i < pI830->xf86_config.num_output; i++) {
 +	xf86OutputPtr output = pI830->xf86_config.output[i];
 +
 +	if (output->crtc != crtc)
 +	    continue;
 +
 +	if (!output->funcs->mode_fixup(output, pMode, adjusted_mode)) {
 +	    ret = FALSE;
 +	    goto done;
 +	}
      }
 -    OUTREG(pipeconf_reg, temp);
  
 -    if (plane_enable) {
 -	/* And then turn the plane on */
 -	OUTREG(dspcntr_reg, dspcntr);
 +    if (!crtc->funcs->mode_fixup(crtc, pMode, adjusted_mode)) {
 +	ret = FALSE;
 +	goto done;
 +    }
 +
 +    /* Disable the outputs and CRTCs before setting the mode. */
 +    for (i = 0; i < pI830->xf86_config.num_output; i++) {
 +	xf86OutputPtr output = pI830->xf86_config.output[i];
 +
 +	if (output->crtc != crtc)
 +	    continue;
 +
 +	/* Disable the output as the first thing we do. */
 +	output->funcs->dpms(output, DPMSModeOff);
 +    }
 +
 +    crtc->funcs->dpms(crtc, DPMSModeOff);
 +
 +    /* Set up the DPLL and any output state that needs to adjust or depend
 +     * on the DPLL.
 +     */
 +    crtc->funcs->mode_set(crtc, pMode, adjusted_mode);
 +    for (i = 0; i < pI830->xf86_config.num_output; i++) {
 +	xf86OutputPtr output = pI830->xf86_config.output[i];
 +	if (output->crtc == crtc)
 +	    output->funcs->mode_set(output, pMode, adjusted_mode);
 +    }
 +
 +    /* Now, enable the clocks, plane, pipe, and outputs that we set up. */
 +    crtc->funcs->dpms(crtc, DPMSModeOn);
 +    for (i = 0; i < pI830->xf86_config.num_output; i++) {
 +	xf86OutputPtr output = pI830->xf86_config.output[i];
 +	if (output->crtc == crtc)
 +	    output->funcs->dpms(output, DPMSModeOn);
      }
  
+ #if 0
+     /*
+      * If the display isn't solid, it may be running out
+      * of memory bandwidth. This code will dump out the
+      * pipe status, if bit 31 is on, the fifo underran
+      */
+     for (i = 0; i < 4; i++) {
+ 	i830WaitForVblank(pScrn);
+     
+ 	OUTREG(pipestat_reg, INREG(pipestat_reg) | 0x80000000);
+     
+ 	i830WaitForVblank(pScrn);
+     
+ 	temp = INREG(pipestat_reg);
+ 	ErrorF ("pipe status 0x%x\n", temp);
+     }
+ #endif
+     
      crtc->curMode = *pMode;
  
 +    /* XXX free adjustedmode */
      ret = TRUE;
  done:
  #ifdef XF86DRI
diff-tree 0b4c3e7bff790e1e99ace5036a41e96046335b04 (from 7844e576e71c004ed495bbc31f7bbe890d18b8d9)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Dec 5 14:39:47 2006 -0800

    Add a bunch of per-register debug code to i830DumpRegs().

diff --git a/src/i810_reg.h b/src/i810_reg.h
index 7312f8a..d525024 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -762,6 +762,18 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 #define PP_STATUS	0x61200
 # define PP_ON					(1 << 31)
+/**
+ * Indicates that all dependencies of the panel are on:
+ *
+ * - PLL enabled
+ * - pipe enabled
+ * - LVDS/DVOB/DVOC on
+ */
+# define PP_READY				(1 << 30)
+# define PP_SEQUENCE_NONE			(0 << 28)
+# define PP_SEQUENCE_ON				(1 << 28)
+# define PP_SEQUENCE_OFF			(2 << 28)
+# define PP_SEQUENCE_MASK			0x30000000
 
 #define PP_CONTROL	0x61204
 # define POWER_TARGET_ON			(1 << 0)
@@ -796,12 +808,14 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 # define DPLL_VGA_MODE_DIS			(1 << 28)
 # define DPLLB_MODE_DAC_SERIAL			(1 << 26) /* i915 */
 # define DPLLB_MODE_LVDS			(2 << 26) /* i915 */
+# define DPLL_MODE_MASK				(3 << 26)
 # define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10	(0 << 24) /* i915 */
 # define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5		(1 << 24) /* i915 */
 # define DPLLB_LVDS_P2_CLOCK_DIV_14		(0 << 24) /* i915 */
 # define DPLLB_LVDS_P2_CLOCK_DIV_7		(1 << 24) /* i915 */
 # define DPLL_P2_CLOCK_DIV_MASK			0x03000000 /* i915 */
 # define DPLL_FPA01_P1_POST_DIV_MASK		0x00ff0000 /* i915 */
+# define DPLL_FPA01_P1_POST_DIV_SHIFT		16
 # define PLL_P2_DIVIDE_BY_4			(1 << 23) /* i830, required in DVO non-gang */
 # define DPLL_FPA01_P1_POS_DIV_MASK_I830	0x001f0000 /* i830 */
 # define PLL_P1_DIVIDE_BY_TWO			(1 << 21) /* i830 */
@@ -809,6 +823,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 # define PLL_REF_INPUT_TVCLKINA			(1 << 13) /* i830 */
 # define PLL_REF_INPUT_TVCLKINBC		(2 << 13) /* SDVO TVCLKIN */
 # define PLLB_REF_INPUT_SPREADSPECTRUMIN	(3 << 13)
+# define PLL_REF_INPUT_MASK			(3 << 13)
 # define PLL_LOAD_PULSE_PHASE_SHIFT		9
 /*
  * Parallel to Serial Load Pulse phase selection.
@@ -818,6 +833,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
  */
 # define PLL_LOAD_PULSE_PHASE_MASK		(0xf << PLL_LOAD_PULSE_PHASE_SHIFT)
 # define DISPLAY_RATE_SELECT_FPA1		(1 << 8)
+
 /**
  * SDVO multiplier for 945G/GM. Not used on 965.
  *
@@ -906,8 +922,11 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define FPB0		0x06048
 #define FPB1		0x0604c
 # define FP_N_DIV_MASK				0x003f0000
+# define FP_N_DIV_SHIFT				16
 # define FP_M1_DIV_MASK				0x00003f00
+# define FP_M1_DIV_SHIFT			8
 # define FP_M2_DIV_MASK				0x0000003f
+# define FP_M2_DIV_SHIFT			0
 
 #define PORT_HOTPLUG_EN		0x61110
 # define SDVOB_HOTPLUG_INT_EN			(1 << 26)
diff --git a/src/i830_debug.c b/src/i830_debug.c
index d74d092..97b0983 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -33,13 +33,157 @@
 #include "i830.h"
 #include "i830_debug.h"
 
+#define DEBUGSTRING(func) static char *func(I830Ptr pI830, int reg, CARD32 val)
+
+DEBUGSTRING(i830_debug_xyminus1)
+{
+    return XNFprintf("%d, %d", (val & 0xffff) + 1,
+		     ((val & 0xffff0000) >> 16) + 1);
+}
+
+DEBUGSTRING(i830_debug_xy)
+{
+    return XNFprintf("%d, %d", (val & 0xffff),
+		     ((val & 0xffff0000) >> 16));
+}
+
+DEBUGSTRING(i830_debug_dspstride)
+{
+    return XNFprintf("%d bytes", val);
+}
+
+DEBUGSTRING(i830_debug_dspcntr)
+{
+    char *enabled = val & DISPLAY_PLANE_ENABLE ? "enabled" : "disabled";
+    char plane = val & DISPPLANE_SEL_PIPE_B ? 'B' : 'A';
+    return XNFprintf("%s, pipe %c", enabled, plane);
+}
+
+DEBUGSTRING(i830_debug_pipeconf)
+{
+    char *enabled = val & PIPEACONF_ENABLE ? "enabled" : "disabled";
+    char *wide = val & PIPEACONF_DOUBLE_WIDE ? "double-wide" : "single-wide";
+    return XNFprintf("%s, %s", enabled, wide);
+}
+
+DEBUGSTRING(i830_debug_hvtotal)
+{
+    return XNFprintf("%d active, %d total", (val & 0xffff) + 1,
+		     ((val & 0xffff0000) >> 16) + 1);
+}
+
+DEBUGSTRING(i830_debug_hvsyncblank)
+{
+    return XNFprintf("%d start, %d end", (val & 0xffff) + 1,
+		     ((val & 0xffff0000) >> 16) + 1);
+}
+
+DEBUGSTRING(i830_debug_vgacntrl)
+{
+    return XNFprintf("%s", val & VGA_DISP_DISABLE ? "disabled" : "enabled");
+}
+
+DEBUGSTRING(i830_debug_fp)
+{
+    return XNFprintf("n = %d, m1 = %d, m2 = %d",
+		     ((val & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT),
+		     ((val & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT),
+		     ((val & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT));
+}
+
+DEBUGSTRING(i830_debug_pp_status)
+{
+    char *status = val & PP_ON ? "on" : "off";
+    char *ready = val & PP_READY ? "ready" : "not ready";
+    char *seq = "unknown";
+
+    switch (val & PP_SEQUENCE_MASK) {
+    case PP_SEQUENCE_NONE:
+	seq = "idle";
+	break;
+    case PP_SEQUENCE_ON:
+	seq = "on";
+	break;
+    case PP_SEQUENCE_OFF:
+	seq = "off";
+	break;
+    }
+
+    return XNFprintf("%s, %s, sequencing %s", status, ready, seq);
+}
+
+DEBUGSTRING(i830_debug_pp_control)
+{
+    return XNFprintf("power target: %s",
+		     val & POWER_TARGET_ON ? "on" : "off");
+}
+
+DEBUGSTRING(i830_debug_dpll)
+{
+    char *enabled = val & DPLL_VCO_ENABLE ? "enabled" : "disabled";
+    char *dvomode = val & DPLL_DVO_HIGH_SPEED ? "dvo" : "non-dvo";
+    char *vgamode = val & DPLL_VGA_MODE_DIS ? "" : ", VGA";
+    char *mode = "unknown";
+    char *clock = "unknown";
+    char *fpextra = val & DISPLAY_RATE_SELECT_FPA1 ? ", using FPx1!" : "";
+    char sdvoextra[3];
+    int p1, p2 = 0;
+
+    p1 = ffs((val & DPLL_FPA01_P1_POST_DIV_MASK) >>
+	     DPLL_FPA01_P1_POST_DIV_SHIFT);
+    switch (val & DPLL_MODE_MASK) {
+    case DPLLB_MODE_DAC_SERIAL:
+	mode = "dac/serial";
+	p2 = val & DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 ? 5 : 10;
+	break;
+    case DPLLB_MODE_LVDS:
+	mode = "LVDS";
+	p2 = val & DPLLB_LVDS_P2_CLOCK_DIV_7 ? 7 : 14;
+	break;
+    }
+    switch (val & PLL_REF_INPUT_MASK) {
+    case PLL_REF_INPUT_DREFCLK:
+	clock = "default";
+	break;
+    case PLL_REF_INPUT_TVCLKINA:
+	clock = "TV A";
+	break;
+    case PLL_REF_INPUT_TVCLKINBC:
+	clock = "TV B/C";
+	break;
+    }
+    if (IS_I945G(pI830) || IS_I945GM(pI830)) {
+	sprintf(sdvoextra, "SDVO mult %d",
+		(int)(val & SDVO_MULTIPLIER_MASK) >>
+		SDVO_MULTIPLIER_SHIFT_HIRES);
+    } else {
+	sdvoextra[0] = '\0';
+    }
+
+    return XNFprintf("%s, %s%s, %s mode, %s clock, p1 = %d, "
+		     "p2 = %d%s%s",
+		     enabled, dvomode, vgamode, mode, clock, p1, p2,
+		     fpextra, sdvoextra);
+}
+
+DEBUGSTRING(i830_debug_lvds)
+{
+    char pipe = val & LVDS_PIPEB_SELECT ? 'B' : 'A';
+    char *enable = val & LVDS_PORT_EN ? "enabled" : "disabled";
+
+    return XNFprintf("%s, pipe %c", enable, pipe);
+}
+
 #define DEFINEREG(reg) \
-	{ reg, #reg, 0 }
+	{ reg, #reg, NULL, 0 }
+#define DEFINEREG2(reg, func) \
+	{ reg, #reg, func, 0 }
 
 static struct i830SnapshotRec {
     int reg;
     char *name;
-    CARD32 regval;
+    char *(*debug_output)(I830Ptr pI830, int reg, CARD32 val);
+    CARD32 val;
 } i830_snapshot[] = {
     DEFINEREG(VCLK_DIVISOR_VGA0),
     DEFINEREG(VCLK_DIVISOR_VGA1),
@@ -61,7 +205,7 @@ static struct i830SnapshotRec {
     DEFINEREG(DSPFW3),
 
     DEFINEREG(ADPA),
-    DEFINEREG(LVDS),
+    DEFINEREG2(LVDS, i830_debug_lvds),
     DEFINEREG(DVOA),
     DEFINEREG(DVOB),
     DEFINEREG(DVOC),
@@ -69,63 +213,63 @@ static struct i830SnapshotRec {
     DEFINEREG(DVOB_SRCDIM),
     DEFINEREG(DVOC_SRCDIM),
 
-    DEFINEREG(PP_CONTROL),
-    DEFINEREG(PP_STATUS),
+    DEFINEREG2(PP_CONTROL, i830_debug_pp_control),
+    DEFINEREG2(PP_STATUS, i830_debug_pp_status),
     DEFINEREG(PFIT_CONTROL),
     DEFINEREG(PFIT_PGM_RATIOS),
     DEFINEREG(PORT_HOTPLUG_EN),
     DEFINEREG(PORT_HOTPLUG_STAT),
 
-    DEFINEREG(DSPACNTR),
-    DEFINEREG(DSPASTRIDE),
-    DEFINEREG(DSPAPOS),
-    DEFINEREG(DSPASIZE),
+    DEFINEREG2(DSPACNTR, i830_debug_dspcntr),
+    DEFINEREG2(DSPASTRIDE, i830_debug_dspstride),
+    DEFINEREG2(DSPAPOS, i830_debug_xy),
+    DEFINEREG2(DSPASIZE, i830_debug_xyminus1),
     DEFINEREG(DSPABASE),
     DEFINEREG(DSPASURF),
     DEFINEREG(DSPATILEOFF),
-    DEFINEREG(PIPEACONF),
-    DEFINEREG(PIPEASRC),
+    DEFINEREG2(PIPEACONF, i830_debug_pipeconf),
+    DEFINEREG2(PIPEASRC, i830_debug_xyminus1),
 
-    DEFINEREG(FPA0),
-    DEFINEREG(FPA1),
-    DEFINEREG(DPLL_A),
+    DEFINEREG2(FPA0, i830_debug_fp),
+    DEFINEREG2(FPA1, i830_debug_fp),
+    DEFINEREG2(DPLL_A, i830_debug_dpll),
     DEFINEREG(DPLL_A_MD),
-    DEFINEREG(HTOTAL_A),
-    DEFINEREG(HBLANK_A),
-    DEFINEREG(HSYNC_A),
-    DEFINEREG(VTOTAL_A),
-    DEFINEREG(VBLANK_A),
-    DEFINEREG(VSYNC_A),
+    DEFINEREG2(HTOTAL_A, i830_debug_hvtotal),
+    DEFINEREG2(HBLANK_A, i830_debug_hvsyncblank),
+    DEFINEREG2(HSYNC_A, i830_debug_hvsyncblank),
+    DEFINEREG2(VTOTAL_A, i830_debug_hvtotal),
+    DEFINEREG2(VBLANK_A, i830_debug_hvsyncblank),
+    DEFINEREG2(VSYNC_A, i830_debug_hvsyncblank),
     DEFINEREG(BCLRPAT_A),
     DEFINEREG(VSYNCSHIFT_A),
 
-    DEFINEREG(DSPBCNTR),
-    DEFINEREG(DSPBSTRIDE),
-    DEFINEREG(DSPBPOS),
-    DEFINEREG(DSPBSIZE),
+    DEFINEREG2(DSPBCNTR, i830_debug_dspcntr),
+    DEFINEREG2(DSPBSTRIDE, i830_debug_dspstride),
+    DEFINEREG2(DSPBPOS, i830_debug_xy),
+    DEFINEREG2(DSPBSIZE, i830_debug_xyminus1),
     DEFINEREG(DSPBBASE),
     DEFINEREG(DSPBSURF),
     DEFINEREG(DSPBTILEOFF),
-    DEFINEREG(PIPEBCONF),
-    DEFINEREG(PIPEBSRC),
+    DEFINEREG2(PIPEBCONF, i830_debug_pipeconf),
+    DEFINEREG2(PIPEBSRC, i830_debug_xyminus1),
 
-    DEFINEREG(FPB0),
-    DEFINEREG(FPB1),
-    DEFINEREG(DPLL_B),
+    DEFINEREG2(FPB0, i830_debug_fp),
+    DEFINEREG2(FPB1, i830_debug_fp),
+    DEFINEREG2(DPLL_B, i830_debug_dpll),
     DEFINEREG(DPLL_B_MD),
-    DEFINEREG(HTOTAL_B),
-    DEFINEREG(HBLANK_B),
-    DEFINEREG(HSYNC_B),
-    DEFINEREG(VTOTAL_B),
-    DEFINEREG(VBLANK_B),
-    DEFINEREG(VSYNC_B),
+    DEFINEREG2(HTOTAL_B, i830_debug_hvtotal),
+    DEFINEREG2(HBLANK_B, i830_debug_hvsyncblank),
+    DEFINEREG2(HSYNC_B, i830_debug_hvsyncblank),
+    DEFINEREG2(VTOTAL_B, i830_debug_hvtotal),
+    DEFINEREG2(VBLANK_B, i830_debug_hvsyncblank),
+    DEFINEREG2(VSYNC_B, i830_debug_hvsyncblank),
     DEFINEREG(BCLRPAT_B),
     DEFINEREG(VSYNCSHIFT_B),
 
     DEFINEREG(VCLK_DIVISOR_VGA0),
     DEFINEREG(VCLK_DIVISOR_VGA1),
     DEFINEREG(VCLK_POST_DIV),
-    DEFINEREG(VGACNTRL),
+    DEFINEREG2(VGACNTRL, i830_debug_vgacntrl),
 
     DEFINEREG(TV_CTL),
     DEFINEREG(TV_DAC),
@@ -171,7 +315,7 @@ void i830TakeRegSnapshot(ScrnInfoPtr pSc
     int i;
 
     for (i = 0; i < NUM_I830_SNAPSHOTREGS; i++) {
-	i830_snapshot[i].regval = INREG(i830_snapshot[i].reg);
+	i830_snapshot[i].val = INREG(i830_snapshot[i].reg);
     }
 }
 
@@ -184,11 +328,28 @@ void i830CompareRegsToSnapshot(ScrnInfoP
 	       "Comparing regs before/after X's VT usage\n");
     for (i = 0; i < NUM_I830_SNAPSHOTREGS; i++) {
 	CARD32 val = INREG(i830_snapshot[i].reg);
-	if (i830_snapshot[i].regval != val) {
+	if (i830_snapshot[i].val == val)
+	    continue;
+
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		   "Register 0x%x (%s) changed from 0x%08x to 0x%08x\n",
+		   i830_snapshot[i].reg, i830_snapshot[i].name,
+		   (int)i830_snapshot[i].val, (int)val);
+
+	if (i830_snapshot[i].debug_output != NULL) {
+	    char *before, *after;
+
+	    before = i830_snapshot[i].debug_output(pI830,
+						   i830_snapshot[i].reg,
+						   i830_snapshot[i].val);
+	    after = i830_snapshot[i].debug_output(pI830,
+						  i830_snapshot[i].reg,
+						  val);
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		       "%s before: %s", i830_snapshot[i].name, before);
 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		       "Register 0x%x (%s) changed from 0x%08x to 0x%08x\n",
-		       i830_snapshot[i].reg, i830_snapshot[i].name,
-		       (int)i830_snapshot[i].regval, (int)val);
+		       "%s after: %s", i830_snapshot[i].name, after);
+
 	}
     }
 }
@@ -220,8 +381,19 @@ void i830DumpRegs (ScrnInfoPtr pScrn)
 
     xf86DrvMsg (pScrn->scrnIndex, X_INFO, "DumpRegsBegin\n");
     for (i = 0; i < NUM_I830_SNAPSHOTREGS; i++) {
-	xf86DrvMsg (pScrn->scrnIndex, X_INFO, "%20.20s: 0x%08x\n",
-		    i830_snapshot[i].name, (unsigned int) INREG(i830_snapshot[i].reg));
+	CARD32 val = INREG(i830_snapshot[i].reg);
+
+	if (i830_snapshot[i].debug_output != NULL) {
+	    char *debug = i830_snapshot[i].debug_output(pI830,
+							i830_snapshot[i].reg,
+							val);
+	    xf86DrvMsg (pScrn->scrnIndex, X_INFO, "%20.20s: 0x%08x (%s)\n",
+			i830_snapshot[i].name, (unsigned int)val, debug);
+	    xfree(debug);
+	} else {
+	    xf86DrvMsg (pScrn->scrnIndex, X_INFO, "%20.20s: 0x%08x\n",
+			i830_snapshot[i].name, (unsigned int)val);
+	}
     }
     i830DumpIndexed (pScrn, "SR", 0x3c4, 0x3c5, 0, 7);
     msr = INREG8(0x3cc);
diff-tree 7844e576e71c004ed495bbc31f7bbe890d18b8d9 (from e777d38ce98d7220621b049b09df1deca5a5df42)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Dec 5 14:39:09 2006 -0800

    Move reg dump from i830PipeSetMode to after we set up the modes with RandR.

diff --git a/src/i830_display.c b/src/i830_display.c
index eab82f6..d7d7417 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -758,8 +758,6 @@ i830PipeSetMode(xf86CrtcPtr crtc, Displa
 
     crtc->curMode = *pMode;
 
-    i830DumpRegs(pScrn);
-
     /* XXX free adjustedmode */
     ret = TRUE;
 done:
diff --git a/src/i830_randr.c b/src/i830_randr.c
index 373403f..dd70bba 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -41,6 +41,7 @@
 
 #include "i830_xf86Crtc.h"
 #include "i830_randr.h"
+#include "i830_debug.h"
 #include "i830_display.h"
 #include "i830.h"
 
@@ -604,6 +605,8 @@ xf86RandR12CrtcSet (ScreenPtr	pScreen,
 	    i830PipeSetBase(crtc, x, y);
 	}
 	i830DisableUnusedFunctions (pScrn);
+
+	i830DumpRegs(pScrn);
     }
     return xf86RandR12CrtcNotify (randr_crtc);
 }
diff-tree e777d38ce98d7220621b049b09df1deca5a5df42 (from 81dde11d419c8f9198ab3502d9813d66d0bc6d6d)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Dec 5 10:01:31 2006 -0800

    WIP code to move mode set sequencing to XFree86 handlers.
    
    It compiles.  It definitely doesn't run.

diff --git a/src/i830_crt.c b/src/i830_crt.c
index 7a706d1..ebd83bc 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -93,13 +93,16 @@ i830_crt_mode_valid(xf86OutputPtr output
     return MODE_OK;
 }
 
-static void
-i830_crt_pre_set_mode (xf86OutputPtr output, DisplayModePtr pMode)
+static Bool
+i830_crt_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
+		    DisplayModePtr adjusted_mode)
 {
+    return TRUE;
 }
 
 static void
-i830_crt_post_set_mode (xf86OutputPtr output, DisplayModePtr pMode)
+i830_crt_mode_set(xf86OutputPtr output, DisplayModePtr mode,
+		  DisplayModePtr adjusted_mode)
 {
     ScrnInfoPtr		    pScrn = output->scrn;
     I830Ptr		    pI830 = I830PTR(pScrn);
@@ -122,11 +125,10 @@ i830_crt_post_set_mode (xf86OutputPtr ou
 	OUTREG(dpll_md_reg, dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK);
     }
 
-    adpa = ADPA_DAC_ENABLE;
-
-    if (pMode->Flags & V_PHSYNC)
+    adpa = 0;
+    if (adjusted_mode->Flags & V_PHSYNC)
 	adpa |= ADPA_HSYNC_ACTIVE_HIGH;
-    if (pMode->Flags & V_PVSYNC)
+    if (adjusted_mode->Flags & V_PVSYNC)
 	adpa |= ADPA_VSYNC_ACTIVE_HIGH;
 
     if (i830_crtc->pipe == 0)
@@ -372,8 +374,8 @@ static const xf86OutputFuncsRec i830_crt
     .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,
+    .mode_fixup = i830_crt_mode_fixup,
+    .mode_set = i830_crt_mode_set,
     .detect = i830_crt_detect,
     .get_modes = i830_crt_get_modes,
     .destroy = i830_crt_destroy
diff --git a/src/i830_display.c b/src/i830_display.c
index 29b783b..eab82f6 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -408,34 +408,94 @@ i830PipeInUse (xf86CrtcPtr crtc)
     return FALSE;
 }
 
+static void
+i830_crtc_dpms(xf86CrtcPtr crtc, int mode)
+{
+    ScrnInfoPtr pScrn = crtc->scrn;
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+    int pipe = intel_crtc->pipe;
+    int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
+    int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
+    int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
+    CARD32 temp;
+
+    /* XXX: When our outputs are all unaware of DPMS modes other than off and
+     * on, we should map those modes to DPMSModeOff in the CRTC.
+     */
+    switch (mode) {
+    case DPMSModeOn:
+    case DPMSModeStandby:
+    case DPMSModeSuspend:
+	/* Enable the DPLL */
+	temp = INREG(dpll_reg);
+	OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE);
+
+	/* Wait for the clocks to stabilize. */
+	usleep(150);
+
+	/* Enable the pipe */
+	temp = INREG(pipeconf_reg);
+	OUTREG(pipeconf_reg, temp | PIPEACONF_ENABLE);
+
+	/* Enable the plane */
+	temp = INREG(dspcntr_reg);
+	OUTREG(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE);
+	break;
+    case DPMSModeOff:
+	/* Disable display plane */
+	temp = INREG(dspcntr_reg);
+	OUTREG(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
+
+	/* Disable the VGA plane that we never use */
+	OUTREG(VGACNTRL, VGA_DISP_DISABLE);
+
+	if (!IS_I9XX(pI830)) {
+	    /* Wait for vblank for the disable to take effect */
+	    i830WaitForVblank(pScrn);
+	}
+
+	/* Next, disable display pipes */
+	temp = INREG(pipeconf_reg);
+	OUTREG(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
+
+	/* Wait for vblank for the disable to take effect. */
+	i830WaitForVblank(pScrn);
+
+	temp = INREG(dpll_reg);
+	OUTREG(dpll_reg, temp & ~DPLL_VCO_ENABLE);
+	break;
+    }
+}
+
+static Bool
+i830_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode,
+		     DisplayModePtr adjusted_mode)
+{
+    return TRUE;
+}
+
 /**
- * Sets the given video mode on the given pipe.
+ * Sets up registers for the given mode/adjusted_mode pair.
  *
- * Plane A is always output to pipe A, and plane B to pipe B.  The plane
- * will not be enabled if plane_enable is FALSE, which is used for
- * load detection, when something else will be output to the pipe other than
- * display data.
+ * The clocks, CRTCs and outputs attached to this CRTC must be off.
+ *
+ * This shouldn't enable any clocks, CRTCs, or outputs, but they should
+ * be easily turned on/off after this.
  */
-Bool
-i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode,
-		Bool plane_enable)
+static void
+i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
+		   DisplayModePtr adjusted_mode)
 {
     ScrnInfoPtr pScrn = crtc->scrn;
     I830Ptr pI830 = I830PTR(pScrn);
     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;
-    CARD32 pipesrc, dspsize;
-    Bool ok, is_sdvo = FALSE, is_dvo = FALSE;
-    Bool is_crt = FALSE, is_lvds = FALSE, is_tv = FALSE;
-    int refclk, pixel_clock;
-    int i;
-    int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
-    int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
     int fp_reg = (pipe == 0) ? FPA0 : FPB0;
     int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
+    int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD;
+    int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
+    int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
     int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
     int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
     int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
@@ -446,38 +506,23 @@ i830PipeSetMode(xf86CrtcPtr crtc, Displa
     int dspstride_reg = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
     int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
     int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
-    Bool ret = FALSE;
-#ifdef XF86DRI
-    Bool didLock = FALSE;
-#endif
-
-    if (xf86ModesEqual(&crtc->curMode, pMode))
-	return TRUE;
-
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested pix clock: %d\n",
-	       pMode->Clock);
-
-    crtc->enabled = i830PipeInUse (crtc);
-    
-    if (!crtc->enabled)
-    {
-	/* XXX disable crtc? */
-	return TRUE;
-    }
+    int m1 = 0, m2 = 0, n = 0, p1 = 0, p2 = 0;
+    int i;
+    int refclk;
+    CARD32 dpll = 0, fp = 0, temp, dspcntr;
+    Bool ok, is_sdvo = FALSE, is_dvo = FALSE;
+    Bool is_crt = FALSE, is_lvds = FALSE, is_tv = FALSE;
 
-#ifdef XF86DRI
-    didLock = I830DRILock(pScrn);
-#endif
-    
-    for (i = 0; i < pI830->xf86_config.num_output; i++) 
-    {
+    /* Set up some convenient bools for what outputs are connected to
+     * our pipe, used in DPLL setup.
+     */
+    for (i = 0; i < pI830->xf86_config.num_output; i++) {
 	xf86OutputPtr  output = pI830->xf86_config.output[i];
-	I830OutputPrivatePtr	intel_output = output->driver_private;
+	I830OutputPrivatePtr intel_output = output->driver_private;
+
 	if (output->crtc != crtc)
 	    continue;
 
-	(*output->funcs->pre_set_mode)(output, pMode);
-	
 	switch (intel_output->type) {
 	case I830_OUTPUT_LVDS:
 	    is_lvds = TRUE;
@@ -497,90 +542,23 @@ i830PipeSetMode(xf86CrtcPtr crtc, Displa
 	}
     }
 
-    if (is_lvds && (is_sdvo || is_dvo || is_tv || is_crt)) {
-	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		   "Can't enable LVDS and non-LVDS on the same pipe\n");
-	goto done;
-    }
-    if (is_tv && (is_sdvo || is_dvo || is_crt || is_lvds)) {
-	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		   "Can't enable a TV and any other output on the same "
-		   "pipe\n");
-	goto done;
-    }
-    if (pipe == 0 && is_lvds) {
-	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		   "Can't support LVDS on pipe A\n");
-	goto done;
-    }
-
-    htot = (pMode->CrtcHDisplay - 1) | ((pMode->CrtcHTotal - 1) << 16);
-    hblank = (pMode->CrtcHBlankStart - 1) | ((pMode->CrtcHBlankEnd - 1) << 16);
-    hsync = (pMode->CrtcHSyncStart - 1) | ((pMode->CrtcHSyncEnd - 1) << 16);
-    vtot = (pMode->CrtcVDisplay - 1) | ((pMode->CrtcVTotal - 1) << 16);
-    vblank = (pMode->CrtcVBlankStart - 1) | ((pMode->CrtcVBlankEnd - 1) << 16);
-    vsync = (pMode->CrtcVSyncStart - 1) | ((pMode->CrtcVSyncEnd - 1) << 16);
-    pipesrc = ((pMode->HDisplay - 1) << 16) | (pMode->VDisplay - 1);
-    dspsize = ((pMode->VDisplay - 1) << 16) | (pMode->HDisplay - 1);
-    pixel_clock = pMode->Clock;
-
-    if (is_lvds && pI830->panel_fixed_hactive != 0) {
-	/* To enable panel fitting, we need to set the pipe timings to that of
-	 * the screen at its full resolution.  So, drop the timings from the
-	 * BIOS VBT tables here.
-	 */
-	htot = (pI830->panel_fixed_hactive - 1) |
-		((pI830->panel_fixed_hactive + pI830->panel_fixed_hblank - 1)
-		 << 16);
-	hblank = (pI830->panel_fixed_hactive - 1) |
-		((pI830->panel_fixed_hactive + pI830->panel_fixed_hblank - 1)
-		 << 16);
-	hsync = (pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff - 1) |
-		((pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff +
-		  pI830->panel_fixed_hsyncwidth - 1) << 16);
-
-	vtot = (pI830->panel_fixed_vactive - 1) |
-		((pI830->panel_fixed_vactive + pI830->panel_fixed_vblank - 1)
-		 << 16);
-	vblank = (pI830->panel_fixed_vactive - 1) |
-		((pI830->panel_fixed_vactive + pI830->panel_fixed_vblank - 1)
-		 << 16);
-	vsync = (pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff - 1) |
-		((pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff +
-		  pI830->panel_fixed_vsyncwidth - 1) << 16);
-	pixel_clock = pI830->panel_fixed_clock;
-
-	if (pMode->HDisplay <= pI830->panel_fixed_hactive &&
-	    pMode->HDisplay <= pI830->panel_fixed_vactive)
-	{
-	    pipesrc = ((pMode->HDisplay - 1) << 16) |
-		       (pMode->VDisplay - 1);
-	    dspsize = ((pMode->VDisplay - 1) << 16) |
-		       (pMode->HDisplay - 1);
-	}
-    }
-
-    /* Adjust the clock for pixel multiplication.
-     * See DPLL_MD_UDI_MULTIPLIER_MASK.
-     */
-    if (is_sdvo) {
-	pixel_clock *= i830_sdvo_get_pixel_multiplier(pMode);
-    }
-
     if (IS_I9XX(pI830)) {
 	refclk = 96000;
     } else {
 	refclk = 48000;
     }
-    ok = i830FindBestPLL(crtc, pixel_clock, refclk, &m1, &m2, &n,
+
+    ok = i830FindBestPLL(crtc, adjusted_mode->Clock, refclk, &m1, &m2, &n,
 			 &p1, &p2);
-    if (!ok) {
-	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		   "Couldn't find PLL settings for mode!\n");
-	goto done;
-    }
+    if (!ok)
+	FatalError("Couldn't find PLL settings for mode!\n");
+
+    fp = ((n - 2) << 16) | ((m1 - 2) << 8) | (m2 - 2);
+
+    i830PrintPll("chosen", refclk, m1, m2, n, p1, p2);
+    ErrorF("clock regs: 0x%08x, 0x%08x\n", (int)dpll, (int)fp);
 
-    dpll = DPLL_VCO_ENABLE | DPLL_VGA_MODE_DIS;
+    dpll = DPLL_VGA_MODE_DIS;
     if (IS_I9XX(pI830)) {
 	if (is_lvds)
 	    dpll |= DPLLB_MODE_LVDS;
@@ -615,33 +593,15 @@ i830PipeSetMode(xf86CrtcPtr crtc, Displa
 /*	dpll |= PLL_REF_INPUT_TVCLKINBC; */
 	dpll |= 3;
     }
-#if 0    
+#if 0
     else if (is_lvds)
 	dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
 #endif
-    else	
+    else
 	dpll |= PLL_REF_INPUT_DREFCLK;
 
-    fp = ((n - 2) << 16) | ((m1 - 2) << 8) | (m2 - 2);
-
-#if 1
-    ErrorF("hact: %d htot: %d hbstart: %d hbend: %d hsyncstart: %d hsyncend: %d\n",
-	(int)(htot & 0xffff) + 1, (int)(htot >> 16) + 1,
-	(int)(hblank & 0xffff) + 1, (int)(hblank >> 16) + 1,
-	(int)(hsync & 0xffff) + 1, (int)(hsync >> 16) + 1);
-    ErrorF("vact: %d vtot: %d vbstart: %d vbend: %d vsyncstart: %d vsyncend: %d\n",
-	(int)(vtot & 0xffff) + 1, (int)(vtot >> 16) + 1,
-	(int)(vblank & 0xffff) + 1, (int)(vblank >> 16) + 1,
-	(int)(vsync & 0xffff) + 1, (int)(vsync >> 16) + 1);
-    ErrorF("pipesrc: %dx%d, dspsize: %dx%d\n",
-	(int)(pipesrc >> 16) + 1, (int)(pipesrc & 0xffff) + 1,
-	(int)(dspsize & 0xffff) + 1, (int)(dspsize >> 16) + 1);
-#endif
-
-    i830PrintPll("chosen", refclk, m1, m2, n, p1, p2);
-    ErrorF("clock regs: 0x%08x, 0x%08x\n", (int)dpll, (int)fp);
-
-    dspcntr = DISPLAY_PLANE_ENABLE;
+    /* Set up the display plane register */
+    dspcntr = 0;
     switch (pScrn->bitsPerPixel) {
     case 8:
 	dspcntr |= DISPPLANE_8BPP | DISPPLANE_GAMMA_ENABLE;
@@ -668,61 +628,139 @@ i830PipeSetMode(xf86CrtcPtr crtc, Displa
     else
 	dspcntr |= DISPPLANE_SEL_PIPE_B;
 
-    OUTREG(VGACNTRL, VGA_DISP_DISABLE);
+    OUTREG(fp_reg, fp);
+    OUTREG(dpll_reg, dpll);
+    if (IS_I965G(pI830)) {
+	/* Set the SDVO multiplier/divider to 1x for the sake of analog output.
+	 * It will be updated by the SDVO code if SDVO had fixed up the clock
+	 * for a higher multiplier.
+	 */
+	OUTREG(dpll_md_reg, 0);
+    }
 
-    /* Finally, set the mode. */
-    /* First, disable display planes */
-    temp = INREG(dspcntr_reg);
-    OUTREG(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
+    OUTREG(htot_reg, (adjusted_mode->CrtcHDisplay - 1) |
+	((adjusted_mode->CrtcHTotal - 1) << 16));
+    OUTREG(hblank_reg, (adjusted_mode->CrtcHBlankStart - 1) |
+	((adjusted_mode->CrtcHBlankEnd - 1) << 16));
+    OUTREG(hsync_reg, (adjusted_mode->CrtcHSyncStart - 1) |
+	((adjusted_mode->CrtcHSyncEnd - 1) << 16));
+    OUTREG(vtot_reg, (adjusted_mode->CrtcVDisplay - 1) |
+	((adjusted_mode->CrtcVTotal - 1) << 16));
+    OUTREG(vblank_reg, (adjusted_mode->CrtcVBlankStart - 1) |
+	((adjusted_mode->CrtcVBlankEnd - 1) << 16));
+    OUTREG(vsync_reg, (adjusted_mode->CrtcVSyncStart - 1) |
+	((adjusted_mode->CrtcVSyncEnd - 1) << 16));
+    OUTREG(dspstride_reg, pScrn->displayWidth * pI830->cpp);
+    /* pipesrc and dspsize control the size that is scaled from, which should
+     * always be the user's requested size.
+     */
+    OUTREG(dspsize_reg, ((mode->HDisplay - 1) << 16) | (mode->VDisplay - 1));
+    OUTREG(dsppos_reg, 0);
+    i830PipeSetBase(crtc, crtc->x, crtc->y);
+    OUTREG(pipesrc_reg, ((mode->HDisplay - 1) << 16) | (mode->VDisplay - 1));
+    temp = INREG(pipeconf_reg);
+    OUTREG(pipeconf_reg, temp);
+    OUTREG(dspcntr_reg, dspcntr);
 
-    /* Wait for vblank for the disable to take effect */
-    i830WaitForVblank(pScrn);
+    /* Disable the panel fitter if it was on our pipe */
+    if (!IS_I830(pI830) && ((INREG(PFIT_CONTROL) >> 29) & 0x3) == pipe)
+	OUTREG(PFIT_CONTROL, 0);
+}
 
-    /* Next, disable display pipes */
-    temp = INREG(pipeconf_reg);
-    OUTREG(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
+/**
+ * Sets the given video mode on the given pipe.
+ *
+ * Plane A is always output to pipe A, and plane B to pipe B.  The plane
+ * will not be enabled if plane_enable is FALSE, which is used for
+ * load detection, when something else will be output to the pipe other than
+ * display data.
+ */
+Bool
+i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode,
+		Bool plane_enable)
+{
+    ScrnInfoPtr pScrn = crtc->scrn;
+    I830Ptr pI830 = I830PTR(pScrn);
+    int i;
+    Bool ret = FALSE;
+#ifdef XF86DRI
+    Bool didLock = FALSE;
+#endif
+    DisplayModePtr adjusted_mode;
 
-    OUTREG(fp_reg, fp);
-    OUTREG(dpll_reg, dpll);
+    /* XXX: curMode */
+
+    adjusted_mode = xf86DuplicateMode(pMode);
 
-    /*
-     * If the panel fitter is stuck on our pipe, turn it off.
-     * The LVDS output will set it as necessary in post_set_mode.
+    crtc->enabled = i830PipeInUse (crtc);
+    
+    if (!crtc->enabled)
+    {
+	/* XXX disable crtc? */
+	return TRUE;
+    }
+
+#ifdef XF86DRI
+    didLock = I830DRILock(pScrn);
+#endif
+
+    /* Pass our mode to the outputs and the CRTC to give them a chance to
+     * adjust it according to limitations or output properties, and also
+     * a chance to reject the mode entirely.
      */
-    if (!IS_I830(pI830)) {
-	if (((INREG(PFIT_CONTROL) >> 29) & 0x3) == pipe)
-	    OUTREG(PFIT_CONTROL, 0);
+    for (i = 0; i < pI830->xf86_config.num_output; i++) {
+	xf86OutputPtr output = pI830->xf86_config.output[i];
+
+	if (output->crtc != crtc)
+	    continue;
+
+	if (!output->funcs->mode_fixup(output, pMode, adjusted_mode)) {
+	    ret = FALSE;
+	    goto done;
+	}
     }
 
+    if (!crtc->funcs->mode_fixup(crtc, pMode, adjusted_mode)) {
+	ret = FALSE;
+	goto done;
+    }
+
+    /* Disable the outputs and CRTCs before setting the mode. */
     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);
+	xf86OutputPtr output = pI830->xf86_config.output[i];
+
+	if (output->crtc != crtc)
+	    continue;
+
+	/* Disable the output as the first thing we do. */
+	output->funcs->dpms(output, DPMSModeOff);
     }
 
-    OUTREG(htot_reg, htot);
-    OUTREG(hblank_reg, hblank);
-    OUTREG(hsync_reg, hsync);
-    OUTREG(vtot_reg, vtot);
-    OUTREG(vblank_reg, vblank);
-    OUTREG(vsync_reg, vsync);
-    OUTREG(dspstride_reg, pScrn->displayWidth * pI830->cpp);
-    OUTREG(dspsize_reg, dspsize);
-    OUTREG(dsppos_reg, 0);
-    i830PipeSetBase(crtc, crtc->x, crtc->y);
-    OUTREG(pipesrc_reg, pipesrc);
+    crtc->funcs->dpms(crtc, DPMSModeOff);
 
-    /* Then, turn the pipe on first */
-    temp = INREG(pipeconf_reg);
-    OUTREG(pipeconf_reg, temp | PIPEACONF_ENABLE);
+    /* Set up the DPLL and any output state that needs to adjust or depend
+     * on the DPLL.
+     */
+    crtc->funcs->mode_set(crtc, pMode, adjusted_mode);
+    for (i = 0; i < pI830->xf86_config.num_output; i++) {
+	xf86OutputPtr output = pI830->xf86_config.output[i];
+	if (output->crtc == crtc)
+	    output->funcs->mode_set(output, pMode, adjusted_mode);
+    }
 
-    if (plane_enable) {
-	/* And then turn the plane on */
-	OUTREG(dspcntr_reg, dspcntr);
+    /* Now, enable the clocks, plane, pipe, and outputs that we set up. */
+    crtc->funcs->dpms(crtc, DPMSModeOn);
+    for (i = 0; i < pI830->xf86_config.num_output; i++) {
+	xf86OutputPtr output = pI830->xf86_config.output[i];
+	if (output->crtc == crtc)
+	    output->funcs->dpms(output, DPMSModeOn);
     }
 
     crtc->curMode = *pMode;
 
+    i830DumpRegs(pScrn);
+
+    /* XXX free adjustedmode */
     ret = TRUE;
 done:
 #ifdef XF86DRI
@@ -962,3 +1000,29 @@ i830ReleaseLoadDetectPipe(xf86OutputPtr 
 	i830DisableUnusedFunctions(pScrn);
     }
 }
+
+static const xf86CrtcFuncsRec i830_crtc_funcs = {
+    .dpms = i830_crtc_dpms,
+    .save = NULL, /* XXX */
+    .restore = NULL, /* XXX */
+    .mode_fixup = i830_crtc_mode_fixup,
+    .mode_set = i830_crtc_mode_set,
+    .destroy = NULL, /* XXX */
+};
+
+void
+i830_crtc_init(ScrnInfoPtr pScrn, int pipe)
+{
+    xf86CrtcPtr crtc;
+    I830CrtcPrivatePtr intel_crtc;
+
+    crtc = xf86CrtcCreate (pScrn, &i830_crtc_funcs);
+    if (crtc == NULL)
+	return;
+
+    intel_crtc = xnfcalloc (sizeof (I830CrtcPrivateRec), 1);
+    intel_crtc->pipe = pipe;
+
+    crtc->driver_private = intel_crtc;
+}
+
diff --git a/src/i830_display.h b/src/i830_display.h
index c80c3f7..c1725ab 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -41,6 +41,7 @@ void i830DescribeOutputConfiguration(Scr
 xf86CrtcPtr i830GetLoadDetectPipe(xf86OutputPtr output);
 void i830ReleaseLoadDetectPipe(xf86OutputPtr output);
 Bool i830PipeInUse(xf86CrtcPtr crtc);
+void i830_crtc_init(ScrnInfoPtr pScrn, int pipe);
 
 /** @{
  */
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 3aafe3a..8f017ab 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -715,28 +715,7 @@ I830SetupOutputs(ScrnInfoPtr pScrn)
  * Setup the CRTCs
  */
 
-static const xf86CrtcFuncsRec i830_crtc_funcs = {
-};
 
-static void
-I830SetupCrtcs(ScrnInfoPtr pScrn, int num_pipe)
-{
-    int	    p;
-
-    for (p = 0; p < num_pipe; p++)
-    {
-	xf86CrtcPtr    crtc = xf86CrtcCreate (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;
-    }
-}
-    
 static void 
 I830PreInitDDC(ScrnInfoPtr pScrn)
 {
@@ -1340,7 +1319,9 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 
    I830PreInitDDC(pScrn);
    I830SetupOutputs(pScrn);
-   I830SetupCrtcs(pScrn, num_pipe);
+   for (i = 0; i < num_pipe; i++) {
+       i830_crtc_init(pScrn, i);
+   }
 
    if (xf86ReturnOptValBool(pI830->Options, OPTION_CLONE, FALSE)) {
       if (num_pipe == 1) {
@@ -2286,7 +2267,13 @@ RestoreHWState(ScrnInfoPtr pScrn)
    vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS);
    vgaHWLock(hwp);
 
-   /* First, disable display planes */
+   /* Disable outputs */
+   for (i = 0; i < pI830->xf86_config.num_output; i++) {
+      xf86OutputPtr   output = pI830->xf86_config.output[i];
+      output->funcs->dpms(output, DPMSModeOff);
+   }
+
+   /* Disable display planes */
    temp = INREG(DSPACNTR);
    OUTREG(DSPACNTR, temp & ~DISPLAY_PLANE_ENABLE);
    temp = INREG(DSPBCNTR);
@@ -2298,12 +2285,6 @@ RestoreHWState(ScrnInfoPtr pScrn)
    temp = INREG(PIPEBCONF);
    OUTREG(PIPEBCONF, temp & ~PIPEBCONF_ENABLE);
 
-   /* Disable outputs if necessary */
-   for (i = 0; i < pI830->xf86_config.num_output; i++) {
-      xf86OutputPtr   output = pI830->xf86_config.output[i];
-      (*output->funcs->pre_set_mode) (output, NULL);
-   }
-
    i830WaitForVblank(pScrn);
 
    OUTREG(FPA0, pI830->saveFPA0);
@@ -2311,6 +2292,16 @@ RestoreHWState(ScrnInfoPtr pScrn)
    OUTREG(DPLL_A, pI830->saveDPLL_A);
    if (IS_I965G(pI830))
       OUTREG(DPLL_A_MD, pI830->saveDPLL_A_MD);
+   if(pI830->xf86_config.num_crtc == 2) {
+      OUTREG(FPB0, pI830->saveFPB0);
+      OUTREG(FPB1, pI830->saveFPB1);
+      OUTREG(DPLL_B, pI830->saveDPLL_B);
+      if (IS_I965G(pI830))
+	 OUTREG(DPLL_B_MD, pI830->saveDPLL_B_MD);
+   }
+   /* Wait for clocks to stabilize */
+   usleep(150);
+
    OUTREG(HTOTAL_A, pI830->saveHTOTAL_A);
    OUTREG(HBLANK_A, pI830->saveHBLANK_A);
    OUTREG(HSYNC_A, pI830->saveHSYNC_A);
@@ -2327,11 +2318,6 @@ RestoreHWState(ScrnInfoPtr pScrn)
    }
 
    if(pI830->xf86_config.num_crtc == 2) {
-      OUTREG(FPB0, pI830->saveFPB0);
-      OUTREG(FPB1, pI830->saveFPB1);
-      OUTREG(DPLL_B, pI830->saveDPLL_B);
-      if (IS_I965G(pI830))
-	 OUTREG(DPLL_B_MD, pI830->saveDPLL_B_MD);
       OUTREG(HTOTAL_B, pI830->saveHTOTAL_B);
       OUTREG(HBLANK_B, pI830->saveHBLANK_B);
       OUTREG(HSYNC_B, pI830->saveHSYNC_B);
@@ -2348,12 +2334,8 @@ RestoreHWState(ScrnInfoPtr pScrn)
       }
    }
 
-   OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL);
-
-   for (i = 0; i < pI830->xf86_config.num_output; i++) {
-      xf86OutputPtr   output = pI830->xf86_config.output[i];
-      (*output->funcs->restore) (output);
-   }
+   if (!IS_I830(pI830) && !IS_845G(pI830))
+     OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL);
 
    if (IS_I965G(pI830)) {
       OUTREG(DSPASURF, pI830->saveDSPASURF);
@@ -2371,6 +2353,11 @@ RestoreHWState(ScrnInfoPtr pScrn)
    OUTREG(DSPACNTR, pI830->saveDSPACNTR);
    OUTREG(DSPBCNTR, pI830->saveDSPBCNTR);
 
+   for (i = 0; i < pI830->xf86_config.num_output; i++) {
+      xf86OutputPtr   output = pI830->xf86_config.output[i];
+      (*output->funcs->restore) (output);
+   }
+
    for(i = 0; i < 7; i++) {
 	   OUTREG(SWF0 + (i << 2), pI830->saveSWF[i]);
 	   OUTREG(SWF00 + (i << 2), pI830->saveSWF[i+7]);
diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index 6fe3157..04d2038 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -59,11 +59,17 @@ struct _I830DVODriver i830_dvo_drivers[]
 static void
 i830_dvo_dpms(xf86OutputPtr output, int mode)
 {
+    ScrnInfoPtr		    pScrn = output->scrn;
+    I830Ptr		    pI830 = I830PTR(pScrn);
     I830OutputPrivatePtr    intel_output = output->driver_private;
-    if (mode == DPMSModeOn)
+
+    if (mode == DPMSModeOn) {
+	OUTREG(DVOC, INREG(DVOC) | DVO_ENABLE);
 	(*intel_output->i2c_drv->vid_rec->Power)(intel_output->i2c_drv->dev_priv, TRUE);
-    else
+    } else {
 	(*intel_output->i2c_drv->vid_rec->Power)(intel_output->i2c_drv->dev_priv, FALSE);
+	OUTREG(DVOC, INREG(DVOC) & ~DVO_ENABLE);
+    }
 }
 
 static void
@@ -113,48 +119,51 @@ i830_dvo_mode_valid(xf86OutputPtr output
 	return MODE_BAD;
 }
 
-static void
-i830_dvo_pre_set_mode(xf86OutputPtr output, DisplayModePtr pMode)
+static Bool
+i830_dvo_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
+		    DisplayModePtr adjusted_mode)
 {
-    ScrnInfoPtr		    pScrn = output->scrn;
-    I830Ptr		    pI830 = I830PTR(pScrn);
-    I830OutputPrivatePtr    intel_output = output->driver_private;
+    /* XXX: Hook this up to a DVO driver function */
 
-    (*intel_output->i2c_drv->vid_rec->Mode)(intel_output->i2c_drv->dev_priv, pMode);
-
-    OUTREG(DVOC, INREG(DVOC) & ~DVO_ENABLE);
+    return TRUE;
 }
 
 static void
-i830_dvo_post_set_mode(xf86OutputPtr output, DisplayModePtr pMode)
+i830_dvo_mode_set(xf86OutputPtr output, DisplayModePtr mode,
+		  DisplayModePtr adjusted_mode)
 {
     ScrnInfoPtr		    pScrn = output->scrn;
     I830Ptr		    pI830 = I830PTR(pScrn);
     xf86CrtcPtr	    crtc = output->crtc;
     I830CrtcPrivatePtr	    intel_crtc = crtc->driver_private;
+    I830OutputPrivatePtr    intel_output = output->driver_private;
     int			    pipe = intel_crtc->pipe;
     CARD32		    dvo;
     int			    dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
 
+    intel_output->i2c_drv->vid_rec->Mode(intel_output->i2c_drv->dev_priv,
+					 mode);
+
     /* 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 (pipe == 1)
 	dvo |= DVO_PIPE_B_SELECT;
 
-    if (pMode->Flags & V_PHSYNC)
+    if (adjusted_mode->Flags & V_PHSYNC)
 	dvo |= DVO_HSYNC_ACTIVE_HIGH;
-    if (pMode->Flags & V_PVSYNC)
+    if (adjusted_mode->Flags & V_PVSYNC)
 	dvo |= DVO_VSYNC_ACTIVE_HIGH;
 
     OUTREG(dpll_reg, INREG(dpll_reg) | DPLL_DVO_HIGH_SPEED);
 
-    /*OUTREG(DVOB_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
-      (pMode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));*/
-    OUTREG(DVOC_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
-	   (pMode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));
+    /*OUTREG(DVOB_SRCDIM,
+      (adjusted_mode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
+      (adjusted_mode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));*/
+    OUTREG(DVOC_SRCDIM,
+	   (adjusted_mode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
+	   (adjusted_mode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));
     /*OUTREG(DVOB, dvo);*/
     OUTREG(DVOC, dvo);
 }
@@ -222,8 +231,8 @@ static const xf86OutputFuncsRec i830_dvo
     .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,
+    .mode_fixup = i830_dvo_mode_fixup,
+    .mode_set = i830_dvo_mode_set,
     .detect = i830_dvo_detect,
     .get_modes = i830_ddc_get_modes,
     .destroy = i830_dvo_destroy
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index cf70956..a9c0e20 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -40,7 +40,7 @@ static void
 i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    CARD32 pp_status, pp_control;
+    CARD32 pp_status;
     CARD32 blc_pwm_ctl;
     int backlight_duty_cycle;
 
@@ -77,6 +77,8 @@ i830_lvds_dpms (xf86OutputPtr output, in
 	i830SetLVDSPanelPower(pScrn, TRUE);
     else
 	i830SetLVDSPanelPower(pScrn, FALSE);
+
+    /* XXX: We never power down the LVDS pair. */
 }
 
 static void
@@ -128,28 +130,86 @@ i830_lvds_mode_valid(xf86OutputPtr outpu
    return MODE_OK;
 }
 
-static void
-i830_lvds_pre_set_mode(xf86OutputPtr output, DisplayModePtr pMode)
+static Bool
+i830_lvds_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
+		     DisplayModePtr adjusted_mode)
 {
-    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
-     * conservative for now.
+    ScrnInfoPtr pScrn = output->scrn;
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830CrtcPrivatePtr intel_crtc = output->crtc->driver_private;
+    int i;
+
+    for (i = 0; i < pI830->xf86_config.num_output; i++) {
+	xf86OutputPtr other_output = pI830->xf86_config.output[i];
+
+	if (other_output != output && other_output->crtc == output->crtc) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Can't enable LVDS and another output on the same "
+		       "pipe\n");
+	    return FALSE;
+	}
+    }
+
+    if (intel_crtc->pipe == 0) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "Can't support LVDS on pipe A\n");
+	return FALSE;
+    }
+
+    /* If we have timings from the BIOS for the panel, put them in
+     * to the adjusted mode.  The CRTC will be set up for this mode,
+     * with the panel scaling set up to source from the H/VDisplay
+     * of the original mode.
+     */
+    if (pI830->panel_fixed_hactive != 0) {
+	adjusted_mode->HDisplay = pI830->panel_fixed_hactive;
+	adjusted_mode->HTotal = adjusted_mode->HDisplay +
+	    pI830->panel_fixed_hblank;
+	adjusted_mode->HSyncStart = adjusted_mode->HDisplay +
+	    pI830->panel_fixed_hsyncoff;
+	adjusted_mode->HSyncStart = adjusted_mode->HSyncStart +
+	    pI830->panel_fixed_hsyncwidth;
+	adjusted_mode->VDisplay = pI830->panel_fixed_vactive;
+	adjusted_mode->VTotal = adjusted_mode->VDisplay +
+	    pI830->panel_fixed_hblank;
+	adjusted_mode->VSyncStart = adjusted_mode->VDisplay +
+	    pI830->panel_fixed_hsyncoff;
+	adjusted_mode->VSyncStart = adjusted_mode->VSyncStart +
+	    pI830->panel_fixed_hsyncwidth;
+	adjusted_mode->Clock = pI830->panel_fixed_clock;
+	xf86SetModeCrtc(adjusted_mode, INTERLACE_HALVE_V);
+    }
+
+    /* XXX: if we don't have BIOS fixed timings (or we have
+     * a preferred mode from DDC, probably), we should use the
+     * DDC mode as the fixed timing.
      */
-    i830SetLVDSPanelPower(pScrn, FALSE);
+
+    /* XXX: It would be nice to support lower refresh rates on the
+     * panels to reduce power consumption, and perhaps match the
+     * user's requested refresh rate.
+     */
+
+    return TRUE;
 }
 
 static void
-i830_lvds_post_set_mode(xf86OutputPtr output, DisplayModePtr pMode)
+i830_lvds_mode_set(xf86OutputPtr output, DisplayModePtr mode,
+		   DisplayModePtr adjusted_mode)
 {
-    ScrnInfoPtr	pScrn = output->scrn;
-    I830Ptr	pI830 = I830PTR(pScrn);
-    CARD32	pfit_control;
+    ScrnInfoPtr pScrn = output->scrn;
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD32 pfit_control;
+
+    /* The LVDS pin pair needs to be on before the DPLLs are enabled.
+     * This is an exception to the general rule that mode_set doesn't turn
+     * things on.
+     */
+    OUTREG(LVDS, LVDS_PORT_EN | LVDS_PIPEB_SELECT);
 
     /* Enable automatic panel scaling so that non-native modes fill the
      * screen.  Should be enabled before the pipe is enabled, according to
-     * register description.
+     * register description and PRM.
      */
     pfit_control = (PFIT_ENABLE |
 		    VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
@@ -159,19 +219,6 @@ i830_lvds_post_set_mode(xf86OutputPtr ou
 	pfit_control |= PANEL_8TO6_DITHER_ENABLE;
 
     OUTREG(PFIT_CONTROL, pfit_control);
-
-    /* Disable the PLL before messing with LVDS enable */
-    OUTREG(FPB0, INREG(FPB0) & ~DPLL_VCO_ENABLE);
-
-    /* LVDS must be powered on before PLL is enabled and before power
-     * sequencing the panel.
-     */
-    OUTREG(LVDS, INREG(LVDS) | LVDS_PORT_EN | LVDS_PIPEB_SELECT);
-
-    /* Re-enable the PLL */
-    OUTREG(FPB0, INREG(FPB0) | DPLL_VCO_ENABLE);
-
-    i830SetLVDSPanelPower(pScrn, TRUE);
 }
 
 /**
@@ -234,8 +281,8 @@ static const xf86OutputFuncsRec i830_lvd
     .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,
+    .mode_fixup = i830_lvds_mode_fixup,
+    .mode_set = i830_lvds_mode_set,
     .detect = i830_lvds_detect,
     .get_modes = i830_lvds_get_modes,
     .destroy = i830_lvds_destroy
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index c75800d..7755252 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -534,15 +534,36 @@ i830_sdvo_set_clock_rate_mult(xf86Output
     return TRUE;
 }
 
+static Bool
+i830_sdvo_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
+		     DisplayModePtr adjusted_mode)
+{
+    /* Make the CRTC code factor in the SDVO pixel multiplier.  The SDVO
+     * device will be told of the multiplier during mode_set.
+     */
+    adjusted_mode->Clock *= i830_sdvo_get_pixel_multiplier(mode);
+
+    return TRUE;
+}
+
 static void
-i830_sdvo_pre_set_mode(xf86OutputPtr output, DisplayModePtr mode)
+i830_sdvo_mode_set(xf86OutputPtr output, DisplayModePtr mode,
+		   DisplayModePtr adjusted_mode)
 {
     ScrnInfoPtr pScrn = output->scrn;
     I830Ptr pI830 = I830PTR(pScrn);
     I830OutputPrivatePtr    intel_output = output->driver_private;
     struct i830_sdvo_priv   *dev_priv = intel_output->dev_priv;
-    CARD16 width;
-    CARD16 height;
+    xf86CrtcPtr	    crtc = output->crtc;
+    I830CrtcPrivatePtr	    intel_crtc = crtc->driver_private;
+    Bool input1, input2;
+    CARD32 dpll, sdvox;
+    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;
+    CARD16 width, height;
     CARD16 h_blank_len, h_sync_len, v_blank_len, v_sync_len;
     CARD16 h_sync_offset, v_sync_offset;
     struct i830_sdvo_dtd output_dtd;
@@ -633,26 +654,6 @@ i830_sdvo_pre_set_mode(xf86OutputPtr out
 	break;
     }
 
-    OUTREG(dev_priv->output_device, INREG(dev_priv->output_device) & ~SDVO_ENABLE);
-}
-
-static void
-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;
-    xf86CrtcPtr	    crtc = output->crtc;
-    I830CrtcPrivatePtr	    intel_crtc = crtc->driver_private;
-    I830Ptr pI830 = I830PTR(pScrn);
-    Bool input1, input2;
-    CARD32 dpll, sdvox;
-    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;
-
     /* Set the SDVO control regs. */
     sdvox = INREG(dev_priv->output_device);
     switch (dev_priv->output_device) {
@@ -663,7 +664,7 @@ i830_sdvo_post_set_mode(xf86OutputPtr ou
 	sdvox &= SDVOC_PRESERVE_MASK;
 	break;
     }
-    sdvox |= SDVO_ENABLE | (9 << 19) | SDVO_BORDER_ENABLE;
+    sdvox |= (9 << 19) | SDVO_BORDER_ENABLE;
     if (intel_crtc->pipe == 1)
 	sdvox |= SDVO_PIPE_B_SELECT;
 
@@ -1014,8 +1015,8 @@ static const xf86OutputFuncsRec i830_sdv
     .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,
+    .mode_fixup = i830_sdvo_mode_fixup,
+    .mode_set = i830_sdvo_mode_set,
     .detect = i830_sdvo_detect,
     .get_modes = i830_ddc_get_modes,
     .destroy = i830_sdvo_destroy
diff --git a/src/i830_tv.c b/src/i830_tv.c
index f5716f8..87aecda 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -295,8 +295,33 @@ static const CARD32 v_chroma[43] = {
     0x28003100, 0x28002F00, 0x00003100,
 };
 
+static Bool
+i830_tv_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
+		 DisplayModePtr adjusted_mode)
+{
+    ScrnInfoPtr pScrn = output->scrn;
+    I830Ptr pI830 = I830PTR(pScrn);
+    int i;
+
+    for (i = 0; i < pI830->xf86_config.num_output; i++) {
+	xf86OutputPtr other_output = pI830->xf86_config.output[i];
+
+	if (other_output != output && other_output->crtc == output->crtc) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Can't enable TV and another output on the same "
+		       "pipe\n");
+	    return FALSE;
+	}
+    }
+
+    /* XXX: fill me in */
+
+    return TRUE;
+}
+
 static void
-i830_tv_post_set_mode(xf86OutputPtr output, DisplayModePtr pMode)
+i830_tv_mode_set(xf86OutputPtr output, DisplayModePtr mode,
+		 DisplayModePtr adjusted_mode)
 {
     ScrnInfoPtr		    pScrn = output->scrn;
     I830Ptr		    pI830 = I830PTR(pScrn);
@@ -359,7 +384,7 @@ i830_tv_post_set_mode(xf86OutputPtr outp
     vctl7 = (tv_mode->vburst_start_f4 << TV_VBURST_START_F4_SHIFT) |
 	(tv_mode->vburst_end_f4 << TV_VBURST_END_F4_SHIFT);
 
-    tv_ctl = TV_ENC_ENABLE;
+    tv_ctl = 0;
     if (intel_crtc->pipe == 1)
 	tv_ctl |= TV_ENC_PIPEB_SELECT;
 
@@ -403,7 +428,7 @@ i830_tv_post_set_mode(xf86OutputPtr outp
 	tv_ctl |= TV_ENC_C0_FIX | TV_ENC_SDP_FIX;
 
     tv_filter_ctl = TV_AUTO_SCALE;
-    if (pMode->HDisplay > 1024)
+    if (mode->HDisplay > 1024)
 	tv_ctl |= TV_V_FILTER_BYPASS;
 
     OUTREG(TV_H_CTL_1, hctl1);
@@ -635,8 +660,8 @@ static const xf86OutputFuncsRec i830_tv_
     .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,
+    .mode_fixup = i830_tv_mode_fixup,
+    .mode_set = i830_tv_mode_set,
     .detect = i830_tv_detect,
     .get_modes = i830_tv_get_modes,
     .destroy = i830_tv_destroy
diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h
index 2952c8d..b5dbe51 100644
--- a/src/i830_xf86Crtc.h
+++ b/src/i830_xf86Crtc.h
@@ -27,14 +27,15 @@
 #include "i830_xf86Modes.h"
 
 typedef struct _xf86Crtc xf86CrtcRec, *xf86CrtcPtr;
+typedef struct _xf86Output xf86OutputRec, *xf86OutputPtr;
 
 typedef struct _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.
+    * mode is DPMSModeOff, the crtc must be disabled sufficiently for it to
+    * be safe to call mode_set.
     */
    void
     (*dpms)(xf86CrtcPtr		crtc,
@@ -52,6 +53,27 @@ typedef struct _xf86CrtcFuncs {
    void
     (*restore)(xf86CrtcPtr	crtc);
 
+
+    /**
+     * Callback to adjust the mode to be set in the CRTC.
+     *
+     * This allows a CRTC to adjust the clock or even the entire set of
+     * timings, which is used for panels with fixed timings or for
+     * buses with clock limitations.
+     */
+    Bool
+    (*mode_fixup)(xf86CrtcPtr crtc,
+		  DisplayModePtr mode,
+		  DisplayModePtr adjusted_mode);
+
+    /**
+     * Callback for setting up a video mode after fixups have been made.
+     */
+    void
+    (*mode_set)(xf86CrtcPtr crtc,
+		DisplayModePtr mode,
+		DisplayModePtr adjusted_mode);
+
     /**
      * Clean up driver-specific bits of the crtc
      */
@@ -127,8 +149,6 @@ struct _xf86Crtc {
 #endif
 };
 
-typedef struct _xf86Output xf86OutputRec, *xf86OutputPtr;
-
 typedef struct _xf86OutputFuncs {
     /**
      * Turns the output on/off, or sets intermediate power levels if available.
@@ -157,7 +177,7 @@ typedef struct _xf86OutputFuncs {
      * 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.
+     * on the output specifically, and not represent generic CRTC limitations.
      *
      * \return MODE_OK if the mode is valid, or another MODE_* otherwise.
      */
@@ -166,22 +186,28 @@ typedef struct _xf86OutputFuncs {
 		  DisplayModePtr    pMode);
 
     /**
-     * Callback for setting up a video mode before any crtc/dpll changes.
+     * Callback to adjust the mode to be set in the CRTC.
      *
-     * \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).
+     * This allows an output to adjust the clock or even the entire set of
+     * timings, which is used for panels with fixed timings or for
+     * buses with clock limitations.
      */
-    void
-    (*pre_set_mode)(xf86OutputPtr   output,
-		    DisplayModePtr  pMode);
+    Bool
+    (*mode_fixup)(xf86OutputPtr output,
+		  DisplayModePtr mode,
+		  DisplayModePtr adjusted_mode);
 
     /**
-     * Callback for setting up a video mode after the DPLL update but before
-     * the plane is enabled.
+     * Callback for setting up a video mode after fixups have been made.
+     *
+     * This is only called while the output is disabled.  The dpms callback
+     * must be all that's necessary for the output, to turn the output on
+     * after this function is called.
      */
     void
-    (*post_set_mode)(xf86OutputPtr  output,
-		     DisplayModePtr pMode);
+    (*mode_set)(xf86OutputPtr  output,
+		DisplayModePtr mode,
+		DisplayModePtr adjusted_mode);
 
     /**
      * Probe for a connected output, and return detect_status.
diff-tree 2e8c927f9308069a82f25b65bb0c62bc5a156832 (from 8fcf9a81179ee8577ddab5e904c58fbfd14cf59c)
Author: Keith Packard <keithp at bouzouki.jf.intel.com>
Date:   Mon Dec 4 14:02:30 2006 -0800

    Re-create RandR Crtc/output structures on server regen.
    
    RandR structures must be re-created when the server reinitializes,
    but the driver PreInit function is not re-invoked. Recreate them
    manually in this case during ScreenInit.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 3aafe3a..c85fe4e 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3805,6 +3805,7 @@ I830CloseScreen(int scrnIndex, ScreenPtr
    DPRINTF(PFX, "\nUnmapping memory\n");
    I830UnmapMem(pScrn);
    vgaHWUnmapMem(pScrn);
+   xf86CrtcCloseScreen (pScreen);
 
    if (pI830->ScanlineColorExpandBuffers) {
       xfree(pI830->ScanlineColorExpandBuffers);
diff --git a/src/i830_randr.c b/src/i830_randr.c
index da8d746..0077020 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -900,6 +900,9 @@ xf86RandR12Init12 (ScreenPtr pScreen)
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
     rrScrPrivPtr	rp = rrGetScrPriv(pScreen);
 
+    if (xf86CrtcScreenInit (pScreen))
+	return FALSE;
+
     rp->rrGetInfo = xf86RandR12GetInfo12;
     rp->rrScreenSetSize = xf86RandR12ScreenSetSize;
     rp->rrCrtcSet = xf86RandR12CrtcSet;
diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index 2eb775b..7eb581c 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -68,7 +68,8 @@ xf86CrtcDestroy (xf86CrtcPtr crtc)
     
     (*crtc->funcs->destroy) (crtc);
 #ifdef RANDR_12_INTERFACE
-    RRCrtcDestroy (crtc->randr_crtc);
+    if (crtc->randr_crtc)
+	RRCrtcDestroy (crtc->randr_crtc);
 #endif
     for (c = 0; c < xf86_config->num_crtc; c++)
 	if (xf86_config->crtc[c] == crtc)
@@ -122,7 +123,8 @@ xf86OutputDestroy (xf86OutputPtr output)
     
     (*output->funcs->destroy) (output);
 #ifdef RANDR_12_INTERFACE
-    RROutputDestroy (output->randr_output);
+    if (output->randr_output)
+	RROutputDestroy (output->randr_output);
 #endif
     while (output->probed_modes)
 	xf86DeleteMode (&output->probed_modes, output->probed_modes);
@@ -138,3 +140,55 @@ xf86OutputDestroy (xf86OutputPtr output)
     xfree (output);
 }
 
+Bool
+xf86CrtcScreenInit (ScreenPtr pScreen)
+{
+#ifdef RANDR_12_INTERFACE
+    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int			i;
+
+    for (i = 0; i < xf86_config->num_crtc; i++)
+    {
+	xf86CrtcPtr crtc = xf86_config->crtc[i];
+
+	if (!crtc->randr_crtc)
+	    crtc->randr_crtc = RRCrtcCreate (crtc);
+	if (!crtc->randr_crtc)
+	    return FALSE;
+    }
+    for (i = 0; i < xf86_config->num_output; i++)
+    {
+	xf86OutputPtr output = xf86_config->output[i];
+	
+	if (!output->randr_output)
+	    output->randr_output = RROutputCreate (output->name,
+						   strlen (output->name),
+						   output);
+	if (!output->randr_output)
+	    return FALSE;
+    }
+#endif
+    return TRUE;
+}
+
+void
+xf86CrtcCloseScreen (ScreenPtr pScreen)
+{
+#ifdef RANDR_12_INTERFACE
+    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int			i;
+
+    for (i = 0; i < xf86_config->num_crtc; i++)
+    {
+	xf86CrtcPtr crtc = xf86_config->crtc[i];
+	crtc->randr_crtc = NULL;
+    }
+    for (i = 0; i < xf86_config->num_output; i++)
+    {
+	xf86OutputPtr output = xf86_config->output[i];
+	output->randr_output = NULL;
+    }
+#endif
+}
diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h
index 2952c8d..21ba1fc 100644
--- a/src/i830_xf86Crtc.h
+++ b/src/i830_xf86Crtc.h
@@ -307,4 +307,10 @@ xf86OutputCreate (ScrnInfoPtr		scrn,
 void
 xf86OutputDestroy (xf86OutputPtr	output);
 
+Bool
+xf86CrtcScreenInit (ScreenPtr pScreen);
+
+void
+xf86CrtcCloseScreen (ScreenPtr pScreen);
+
 #endif /* _XF86CRTC_H_ */
diff-tree 677c454469a6223460778033758e384e989cea47 (from parents)
Merge: 16f9a56070a01c7ada8e566d9b73fcf7900136e0 8fcf9a81179ee8577ddab5e904c58fbfd14cf59c
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Sat Dec 2 23:28:38 2006 -0800

    Merge branch 'modesetting-origin' into modesetting

diff-tree 8fcf9a81179ee8577ddab5e904c58fbfd14cf59c (from 81dde11d419c8f9198ab3502d9813d66d0bc6d6d)
Author: Keith Packard <keithp at ukulele.keithp.com>
Date:   Sat Dec 2 22:58:31 2006 -0800

    DOUBLE_WIDE mode for high pixel clock 8xx. Rewrite PLL search.
    
    High pixel clock modes on pipe A of an 8xx chip require
    DOUBLE_WIDE mode. It's supposed to be modes > 180MHz or so,
    but the board I have requires DOUBLE_WIDE mode for clocks > 108MHz
    or so. The limit is related to the core clock speed of the chip, which
    can be found indirectly through PCI config space. None of the possible
    values explain why this board needs this mode for these relatively low
    clock rates though.
    
    Also, create tables of data for the PLL computation and use them
    instead of code. I think it's cleaner looking. It is also untested on
    9xx. It'll work. Really.

diff --git a/src/i830_display.c b/src/i830_display.c
index 29b783b..ac56528 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -43,21 +43,179 @@
 #include "i830_debug.h"
 #include "i830_xf86Modes.h"
 
-/** Returns the pixel clock for the given refclk and divisors. */
-static int i830_clock(int refclk, int m1, int m2, int n, int p1, int p2)
+typedef struct {
+    /* given values */    
+    int n;
+    int m1, m2;
+    int p1, p2;
+    /* derived values */
+    int	dot;
+    int	vco;
+    int	m;
+    int	p;
+} intel_clock_t;
+
+typedef struct {
+    int	min, max;
+} intel_range_t;
+
+typedef struct {
+    int	dot_limit;
+    int	p2_slow, p2_fast;
+} intel_p2_t;
+
+#define INTEL_P2_NUM		      2
+
+typedef struct {
+    intel_range_t   dot, vco, n, m, m1, m2, p, p1;
+    intel_p2_t	    p2;
+} intel_limit_t;
+
+#define I8XX_DOT_MIN		  25000
+#define I8XX_DOT_MAX		 350000
+#define I8XX_VCO_MIN		 930000
+#define I8XX_VCO_MAX		1400000
+#define I8XX_N_MIN		      3
+#define I8XX_N_MAX		     16
+#define I8XX_M_MIN		     96
+#define I8XX_M_MAX		    140
+#define I8XX_M1_MIN		     18
+#define I8XX_M1_MAX		     26
+#define I8XX_M2_MIN		      6
+#define I8XX_M2_MAX		     16
+#define I8XX_P_MIN		      4
+#define I8XX_P_MAX		    128
+#define I8XX_P1_MIN		      0
+#define I8XX_P1_MAX		     30
+#define I8XX_P2_SLOW		      1
+#define I8XX_P2_FAST		      0
+#define I8XX_P2_SLOW_LIMIT	 165000
+
+#define I9XX_DOT_MIN		  20000
+#define I9XX_DOT_MAX		 400000
+#define I9XX_VCO_MIN		1400000
+#define I9XX_VCO_MAX		2800000
+#define I9XX_N_MIN		      3
+#define I9XX_N_MAX		      8
+#define I9XX_M_MIN		     70
+#define I9XX_M_MAX		    120
+#define I9XX_M1_MIN		     10
+#define I9XX_M1_MAX		     20
+#define I9XX_M2_MIN		      5
+#define I9XX_M2_MAX		      9
+#define I9XX_P_SDVO_DAC_MIN	      5
+#define I9XX_P_SDVO_DAC_MAX	     80
+#define I9XX_P_LVDS_MIN		      7
+#define I9XX_P_LVDS_MAX		     98
+#define I9XX_P1_MIN		      1
+#define I9XX_P1_MAX		      8
+#define I9XX_P2_SDVO_DAC_SLOW		     10
+#define I9XX_P2_SDVO_DAC_FAST		      5
+#define I9XX_P2_SDVO_DAC_SLOW_LIMIT	 200000
+#define I9XX_P2_LVDS_SLOW		     14
+#define I9XX_P2_LVDS_FAST		      7
+#define I9XX_P2_LVDS_SLOW_LIMIT		 112000
+
+#define INTEL_LIMIT_I8XX	    0
+#define INTEL_LIMIT_I9XX_SDVO_DAC   1
+#define INTEL_LIMIT_I9XX_LVDS	    2
+
+static const intel_limit_t intel_limits[] = {
+    {
+        .dot = { .min = I8XX_DOT_MIN,		.max = I8XX_DOT_MAX },
+        .vco = { .min = I8XX_VCO_MIN,		.max = I8XX_VCO_MAX },
+        .n   = { .min = I8XX_N_MIN,		.max = I8XX_N_MAX },
+        .m   = { .min = I8XX_M_MIN,		.max = I8XX_M_MAX },
+        .m1  = { .min = I8XX_M1_MIN,		.max = I8XX_M1_MAX },
+        .m2  = { .min = I8XX_M2_MIN,		.max = I8XX_M2_MAX },
+        .p   = { .min = I8XX_P_MIN,		.max = I8XX_P_MAX },
+        .p1  = { .min = I8XX_P1_MIN,		.max = I8XX_P1_MAX },
+	.p2  = { .dot_limit = I8XX_P2_SLOW_LIMIT,
+		 .p2_slow = I8XX_P2_SLOW,	.p2_fast = I8XX_P2_FAST },
+    },
+    {
+        .dot = { .min = I9XX_DOT_MIN,		.max = I9XX_DOT_MAX },
+        .vco = { .min = I9XX_VCO_MIN,		.max = I9XX_VCO_MAX },
+        .n   = { .min = I9XX_N_MIN,		.max = I9XX_N_MAX },
+        .m   = { .min = I9XX_M_MIN,		.max = I9XX_M_MAX },
+        .m1  = { .min = I9XX_M1_MIN,		.max = I9XX_M1_MAX },
+        .m2  = { .min = I9XX_M2_MIN,		.max = I9XX_M2_MAX },
+        .p   = { .min = I9XX_P_SDVO_DAC_MIN,	.max = I9XX_P_SDVO_DAC_MAX },
+        .p1  = { .min = I9XX_P1_MIN,		.max = I9XX_P1_MAX },
+	.p2  = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT,
+		 .p2_slow = I9XX_P2_SDVO_DAC_SLOW,	.p2_fast = I9XX_P2_SDVO_DAC_FAST },
+    },
+    {
+        .dot = { .min = I9XX_DOT_MIN,		.max = I9XX_DOT_MAX },
+        .vco = { .min = I9XX_VCO_MIN,		.max = I9XX_VCO_MAX },
+        .n   = { .min = I9XX_N_MIN,		.max = I9XX_N_MAX },
+        .m   = { .min = I9XX_M_MIN,		.max = I9XX_M_MAX },
+        .m1  = { .min = I9XX_M1_MIN,		.max = I9XX_M1_MAX },
+        .m2  = { .min = I9XX_M2_MIN,		.max = I9XX_M2_MAX },
+        .p   = { .min = I9XX_P_LVDS_MIN,	.max = I9XX_P_LVDS_MAX },
+        .p1  = { .min = I9XX_P1_MIN,		.max = I9XX_P1_MAX },
+	/* The single-channel range is 25-112Mhz, and dual-channel
+	 * is 80-224Mhz.  Prefer single channel as much as possible.
+	 */
+	.p2  = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
+		 .p2_slow = I9XX_P2_LVDS_SLOW,	.p2_fast = I9XX_P2_LVDS_FAST },
+    },
+};
+
+static const intel_limit_t *intel_limit (xf86CrtcPtr crtc)
 {
-    return refclk * (5 * m1 + m2) / n / (p1 * p2);
+    ScrnInfoPtr	pScrn = crtc->scrn;
+    I830Ptr	pI830 = I830PTR(pScrn);
+    const intel_limit_t *limit;
+
+    if (IS_I9XX(pI830)) 
+    {
+	if (i830PipeHasType (crtc, I830_OUTPUT_LVDS))
+	    limit = &intel_limits[INTEL_LIMIT_I9XX_LVDS];
+	else
+	    limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC];
+    }
+    else
+        limit = &intel_limits[INTEL_LIMIT_I8XX];
+    return limit;
 }
 
-static void
-i830PrintPll(char *prefix, int refclk, int m1, int m2, int n, int p1, int p2)
+/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */
+
+static void i8xx_clock(int refclk, intel_clock_t *clock)
 {
-    int dotclock;
+    clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
+    clock->p = (clock->p1 + 2) << (clock->p2 + 1);
+    clock->vco = refclk * clock->m / (clock->n + 2);
+    clock->dot = clock->vco / clock->p;
+}
 
-    dotclock = i830_clock(refclk, m1, m2, n, p1, p2);
+/** Derive the pixel clock for the given refclk and divisors for 9xx chips. */
+
+static void i9xx_clock(int refclk, intel_clock_t *clock)
+{
+    clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
+    clock->p = clock->p1 * clock->p2;
+    clock->vco = refclk * clock->m / (clock->n + 2);
+    clock->dot = clock->vco / clock->p;
+}
+
+static void intel_clock(I830Ptr pI830, int refclk, intel_clock_t *clock)
+{
+    if (IS_I9XX(pI830))
+	return i9xx_clock (refclk, clock);
+    else
+	return i8xx_clock (refclk, clock);
+}
 
-    ErrorF("%s: dotclock %d ((%d, %d), %d, (%d, %d))\n", prefix, dotclock,
-	   m1, m2, n, p1, p2);
+static void
+i830PrintPll(char *prefix, intel_clock_t *clock)
+{
+    ErrorF("%s: dotclock %d vco %d ((m %d, m1 %d, m2 %d), n %d, (p %d, p1 %d, p2 %d))\n",
+	   prefix, clock->dot, clock->vco,
+	   clock->m, clock->m1, clock->m2,
+	   clock->n, 
+	   clock->p, clock->p1, clock->p2);
 }
 
 /**
@@ -83,90 +241,38 @@ i830PipeHasType (xf86CrtcPtr crtc, int t
     return FALSE;
 }
 
+#define i830PllInvalid(s)   { /* ErrorF (s) */; return FALSE; }
 /**
  * Returns whether the given set of divisors are valid for a given refclk with
  * the given outputs.
- *
- * The equation for these divisors would be:
- * clk = refclk * (5 * m1 + m2) / n / (p1 * p2)
  */
+
 static Bool
-i830PllIsValid(xf86CrtcPtr crtc, int refclk, int m1, int m2,
-	       int n, int p1, int p2)
+i830PllIsValid(xf86CrtcPtr crtc, intel_clock_t *clock)
 {
-    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;
-    int min_p1, max_p1, min_p, max_p, min_vco, max_vco, min_dot, max_dot;
+    const intel_limit_t *limit = intel_limit (crtc);
 
-    if (IS_I9XX(pI830)) {
-	min_m1 = 10;
-	max_m1 = 20;
-	min_m2 = 5;
-	max_m2 = 9;
-	min_m = 70;
-	max_m = 120;
-	min_n = 3;
-	max_n = 8;
-	min_p1 = 1;
-	max_p1 = 8;
-	if (i830PipeHasType (crtc, I830_OUTPUT_LVDS)) {
-	    min_p = 7;
-	    max_p = 98;
-	} else {
-	    min_p = 5;
-	    max_p = 80;
-	}
-	min_vco = 1400000;
-	max_vco = 2800000;
-	min_dot = 20000;
-	max_dot = 400000;
-    } else {
-	min_m1 = 18;
-	max_m1 = 26;
-	min_m2 = 6;
-	max_m2 = 16;
-	min_m = 96;
-	max_m = 140;
-	min_n = 3;
-	max_n = 16;
-	min_p1 = 2;
-	max_p1 = 18;
-	min_vco = 930000;
-	max_vco = 1400000;
-	min_dot = 20000;
-	max_dot = 350000;
-	min_p = 4;
-	max_p = 128;
-    }
-
-    p = p1 * p2;
-    m = 5 * m1 + m2;
-    vco = refclk * m / n;
-    dotclock = i830_clock(refclk, m1, m2, n, p1, p2);
-
-    if (p1 < min_p1 || p1 > max_p1)
-	return FALSE;
-    if (p < min_p || p > max_p)
-	return FALSE;
-    if (m2 < min_m2 || m2 > max_m2)
-	return FALSE;
-    if (m1 < min_m1 || m1 > max_m1)
-	return FALSE;
-    if (m1 <= m2)
-	return FALSE;
-    if (m < min_m || m > max_m)
-	return FALSE;
-    if (n < min_n || n > max_n)
-	return FALSE;
-    if (vco < min_vco || vco > max_vco)
-	return FALSE;
+    if (clock->p1  < limit->p1.min  || limit->p1.max  < clock->p1)
+	i830PllInvalid ("p1 out of range\n");
+    if (clock->p   < limit->p.min   || limit->p.max   < clock->p)
+	i830PllInvalid ("p out of range\n");
+    if (clock->m2  < limit->m2.min  || limit->m2.max  < clock->m2)
+	i830PllInvalid ("m2 out of range\n");
+    if (clock->m1  < limit->m1.min  || limit->m1.max  < clock->m1)
+	i830PllInvalid ("m1 out of range\n");
+    if (clock->m1 <= clock->m2)
+	i830PllInvalid ("m1 <= m2\n");
+    if (clock->m   < limit->m.min   || limit->m.max   < clock->m)
+	i830PllInvalid ("m out of range\n");
+    if (clock->n   < limit->n.min   || limit->n.max   < clock->n)
+	i830PllInvalid ("n out of range\n");
+    if (clock->vco < limit->vco.min || limit->vco.max < clock->vco)
+	i830PllInvalid ("vco out of range\n");
     /* XXX: We may need to be checking "Dot clock" depending on the multiplier,
      * output, etc., rather than just a single range.
      */
-    if (dotclock < min_dot || dotclock > max_dot)
-	return FALSE;
+    if (clock->dot < limit->dot.min || limit->dot.max < clock->dot)
+	i830PllInvalid ("dot out of range\n");
 
     return TRUE;
 }
@@ -174,83 +280,47 @@ i830PllIsValid(xf86CrtcPtr crtc, int ref
 /**
  * Returns a set of divisors for the desired target clock with the given refclk,
  * or FALSE.  Divisor values are the actual divisors for
- * clk = refclk * (5 * m1 + m2) / n / (p1 * p2)
  */
 static Bool
-i830FindBestPLL(xf86CrtcPtr crtc, int target, int refclk,
-		int *outm1, int *outm2, int *outn, int *outp1, int *outp2)
+i830FindBestPLL(xf86CrtcPtr crtc, int target, int refclk, intel_clock_t *best_clock)
 {
     ScrnInfoPtr pScrn = crtc->scrn;
     I830Ptr pI830 = I830PTR(pScrn);
-    int m1, m2, n, p1, p2;
+    intel_clock_t   clock;
+    const intel_limit_t   *limit = intel_limit (crtc);
     int err = target;
-    int min_m1, max_m1, min_m2, max_m2, min_n, max_n, min_p1, max_p1;
-
-    if (IS_I9XX(pI830)) {
-	min_m1 = 10;
-	max_m1 = 20;
-	min_m2 = 5;
-	max_m2 = 9;
-	min_n = 3;
-	max_n = 8;
-	min_p1 = 1;
-	max_p1 = 8;
-	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.
-	     */
-	    if (target < 112000)
-		p2 = 14;
-	    else
-		p2 = 7;
-	} else {
-	    if (target < 200000)
-		p2 = 10;
-	    else
-		p2 = 5;
-	}
-    } else {
-	min_m1 = 18;
-	max_m1 = 26;
-	min_m2 = 6;
-	max_m2 = 16;
-	min_n = 3;
-	max_n = 16;
-	min_p1 = 2;
-	max_p1 = 18;
-	if (target < 165000)
-	    p2 = 4;
-	else
-	    p2 = 2;
-    }
 
+    if (target < limit->p2.dot_limit)
+	clock.p2 = limit->p2.p2_slow;
+    else
+	clock.p2 = limit->p2.p2_fast;
 
-    for (m1 = min_m1; m1 <= max_m1; m1++) {
-	for (m2 = min_m2; m2 < max_m2; m2++) {
-	    for (n = min_n; n <= max_n; n++) {
-		for (p1 = min_p1; p1 <= max_p1; p1++) {
-		    int clock, this_err;
+    memset (best_clock, 0, sizeof (*best_clock));
 
-		    if (!i830PllIsValid(crtc, refclk, m1, m2, n,
-					p1, p2)) {
+    for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) 
+    {
+	for (clock.m2 = limit->m2.min; clock.m2 < clock.m1 && clock.m2 < limit->m2.max; clock.m2++) 
+	{
+	    for (clock.n = limit->n.min; clock.n <= limit->n.max; clock.n++) 
+	    {
+		for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max; clock.p1++) 
+		{
+		    int this_err;
+
+		    intel_clock (pI830, refclk, &clock);
+		    
+		    if (!i830PllIsValid(crtc, &clock))
 			continue;
-		    }
 
-		    clock = i830_clock(refclk, m1, m2, n, p1, p2);
-		    this_err = abs(clock - target);
+		    this_err = abs(clock.dot - target);
 		    if (this_err < err) {
-			*outm1 = m1;
-			*outm2 = m2;
-			*outn = n;
-			*outp1 = p1;
-			*outp2 = p2;
+			*best_clock = clock;
 			err = this_err;
 		    }
 		}
 	    }
 	}
     }
-
     return (err != target);
 }
 
@@ -424,7 +494,7 @@ i830PipeSetMode(xf86CrtcPtr crtc, Displa
     I830Ptr pI830 = I830PTR(pScrn);
     I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
     int pipe = intel_crtc->pipe;
-    int m1 = 0, m2 = 0, n = 0, p1 = 0, p2 = 0;
+    intel_clock_t clock;
     CARD32 dpll = 0, fp = 0, temp;
     CARD32 htot, hblank, hsync, vtot, vblank, vsync, dspcntr;
     CARD32 pipesrc, dspsize;
@@ -446,6 +516,7 @@ i830PipeSetMode(xf86CrtcPtr crtc, Displa
     int dspstride_reg = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
     int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
     int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
+    int pipestat_reg = (pipe == 0) ? PIPEASTAT : PIPEBSTAT;
     Bool ret = FALSE;
 #ifdef XF86DRI
     Bool didLock = FALSE;
@@ -572,8 +643,8 @@ i830PipeSetMode(xf86CrtcPtr crtc, Displa
     } else {
 	refclk = 48000;
     }
-    ok = i830FindBestPLL(crtc, pixel_clock, refclk, &m1, &m2, &n,
-			 &p1, &p2);
+    
+    ok = i830FindBestPLL(crtc, pixel_clock, refclk, &clock);
     if (!ok) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		   "Couldn't find PLL settings for mode!\n");
@@ -586,8 +657,9 @@ i830PipeSetMode(xf86CrtcPtr crtc, Displa
 	    dpll |= DPLLB_MODE_LVDS;
 	else
 	    dpll |= DPLLB_MODE_DAC_SERIAL;
-	dpll |= (1 << (p1 - 1)) << 16;
-	switch (p2) {
+	/* compute bitmask from p1 value */
+	dpll |= (1 << (clock.p1 - 1)) << 16;
+	switch (clock.p2) {
 	case 5:
 	    dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5;
 	    break;
@@ -604,9 +676,8 @@ i830PipeSetMode(xf86CrtcPtr crtc, Displa
 	if (IS_I965G(pI830))
 	    dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT);
     } else {
-	dpll |= (p1 - 2) << 16;
-	if (p2 == 4)
-	    dpll |= PLL_P2_DIVIDE_BY_4;
+	dpll |= clock.p1 << 16;
+	dpll |= clock.p2 << 23;
     }
 
     if (is_tv)
@@ -622,7 +693,7 @@ i830PipeSetMode(xf86CrtcPtr crtc, Displa
     else	
 	dpll |= PLL_REF_INPUT_DREFCLK;
 
-    fp = ((n - 2) << 16) | ((m1 - 2) << 8) | (m2 - 2);
+    fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
 
 #if 1
     ErrorF("hact: %d htot: %d hbstart: %d hbend: %d hsyncstart: %d hsyncend: %d\n",
@@ -638,7 +709,7 @@ i830PipeSetMode(xf86CrtcPtr crtc, Displa
 	(int)(dspsize & 0xffff) + 1, (int)(dspsize >> 16) + 1);
 #endif
 
-    i830PrintPll("chosen", refclk, m1, m2, n, p1, p2);
+    i830PrintPll("chosen", &clock);
     ErrorF("clock regs: 0x%08x, 0x%08x\n", (int)dpll, (int)fp);
 
     dspcntr = DISPLAY_PLANE_ENABLE;
@@ -714,13 +785,53 @@ i830PipeSetMode(xf86CrtcPtr crtc, Displa
 
     /* Then, turn the pipe on first */
     temp = INREG(pipeconf_reg);
-    OUTREG(pipeconf_reg, temp | PIPEACONF_ENABLE);
+    temp |= PIPEACONF_ENABLE;
+    if (!IS_I9XX(pI830) && pipe == 0)
+    {
+	/*
+	 * The docs say this is needed when the dot clock is > 90% of the
+	 * core speed. Core speeds are indicated by bits in the PCI
+	 * config space and don't seem to ever be less than 200MHz,
+	 * which is a bit confusing.
+	 *
+	 * However, For one little 855/852 card I have, 135000 requires
+	 * double wide mode, but 108000 does not. That makes no sense
+	 * but we're used to that. It may be affected by pixel size,
+	 * but the BIOS mode setting code doesn't appear to use that.
+	 *
+	 * It doesn't seem to cause any harm, although it
+	 * does restrict some output options.
+	 */
+	if (pixel_clock > 108000)
+	    temp |= PIPEACONF_DOUBLE_WIDE;
+	else
+	    temp &= ~PIPEACONF_DOUBLE_WIDE;
+    }
+    OUTREG(pipeconf_reg, temp);
 
     if (plane_enable) {
 	/* And then turn the plane on */
 	OUTREG(dspcntr_reg, dspcntr);
     }
 
+#if 0
+    /*
+     * If the display isn't solid, it may be running out
+     * of memory bandwidth. This code will dump out the
+     * pipe status, if bit 31 is on, the fifo underran
+     */
+    for (i = 0; i < 4; i++) {
+	i830WaitForVblank(pScrn);
+    
+	OUTREG(pipestat_reg, INREG(pipestat_reg) | 0x80000000);
+    
+	i830WaitForVblank(pScrn);
+    
+	temp = INREG(pipestat_reg);
+	ErrorF ("pipe status 0x%x\n", temp);
+    }
+#endif
+    
     crtc->curMode = *pMode;
 
     ret = TRUE;
diff --git a/src/i830_randr.c b/src/i830_randr.c
index 373403f..da8d746 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -710,7 +710,7 @@ xf86RandR12SetInfo12 (ScrnInfoPtr pScrn)
 	    subpixel = SubPixelHorizontalRGB;
 	    break;
 	case I830_OUTPUT_ANALOG:
-	    crtc_types = ((1 << 0) | (1 << 1));
+	    crtc_types = ((1 << 0));
 	    clone_types = ((1 << I830_OUTPUT_ANALOG) |
 			   (1 << I830_OUTPUT_DVO) |
 			   (1 << I830_OUTPUT_SDVO));
diff-tree 81dde11d419c8f9198ab3502d9813d66d0bc6d6d (from a504e31f0fefdec802ae403573f52fac3d577b65)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Dec 1 10:37:19 2006 -0800

    Fix copy'n'paste-o from restructure-outputs that resulted in crashes.
    
    Our driver private is stored in the bus that we set up, not the DDC device
    that xf86 code does.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index aa06182..c75800d 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -823,7 +823,7 @@ i830_sdvo_get_capabilities(xf86OutputPtr
 static Bool
 i830_sdvo_ddc_i2c_get_byte(I2CDevPtr d, I2CByte *data, Bool last)
 {
-    xf86OutputPtr	    output = d->DriverPrivate.ptr;
+    xf86OutputPtr	    output = d->pI2CBus->DriverPrivate.ptr;
     I830OutputPrivatePtr    intel_output = output->driver_private;
     I2CBusPtr		    i2cbus = intel_output->pI2CBus, savebus;
     Bool		    ret;
@@ -840,7 +840,7 @@ i830_sdvo_ddc_i2c_get_byte(I2CDevPtr d, 
 static Bool
 i830_sdvo_ddc_i2c_put_byte(I2CDevPtr d, I2CByte c)
 {
-    xf86OutputPtr	    output = d->DriverPrivate.ptr;
+    xf86OutputPtr	    output = d->pI2CBus->DriverPrivate.ptr;
     I830OutputPrivatePtr    intel_output = output->driver_private;
     I2CBusPtr		    i2cbus = intel_output->pI2CBus, savebus;
     Bool		    ret;
@@ -875,7 +875,7 @@ i830_sdvo_ddc_i2c_start(I2CBusPtr b, int
 static void
 i830_sdvo_ddc_i2c_stop(I2CDevPtr d)
 {
-    xf86OutputPtr	    output = d->DriverPrivate.ptr;
+    xf86OutputPtr	    output = d->pI2CBus->DriverPrivate.ptr;
     I830OutputPrivatePtr    intel_output = output->driver_private;
     I2CBusPtr		    i2cbus = intel_output->pI2CBus, savebus;
 
diff-tree a504e31f0fefdec802ae403573f52fac3d577b65 (from f21230d3e1cc5470e8f88404b5d9f1702bec44bb)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Dec 1 12:49:43 2006 -0800

    Don't try to write the read-only PP_STATUS register.
    
    Also, don't bother reading the PP_CONTROL register to try to get LVDS status --
    that's what PP_STATUS is for.

diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index bfb4e14..cf70956 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -50,12 +50,10 @@ i830SetLVDSPanelPower(ScrnInfoPtr pScrn,
         pI830->backlight_duty_cycle = backlight_duty_cycle;
 
     if (on) {
-	OUTREG(PP_STATUS, INREG(PP_STATUS) | PP_ON);
 	OUTREG(PP_CONTROL, INREG(PP_CONTROL) | POWER_TARGET_ON);
 	do {
 	    pp_status = INREG(PP_STATUS);
-	    pp_control = INREG(PP_CONTROL);
-	} while (!(pp_status & PP_ON) && !(pp_control & POWER_TARGET_ON));
+	} while ((pp_status & PP_ON) == 0);
 	OUTREG(BLC_PWM_CTL,
 	       (blc_pwm_ctl & ~BACKLIGHT_DUTY_CYCLE_MASK) |
 	       pI830->backlight_duty_cycle);
@@ -63,12 +61,10 @@ i830SetLVDSPanelPower(ScrnInfoPtr pScrn,
 	OUTREG(BLC_PWM_CTL,
 	       (blc_pwm_ctl & ~BACKLIGHT_DUTY_CYCLE_MASK));
 
-	OUTREG(PP_STATUS, INREG(PP_STATUS) & ~PP_ON);
 	OUTREG(PP_CONTROL, INREG(PP_CONTROL) & ~POWER_TARGET_ON);
 	do {
 	    pp_status = INREG(PP_STATUS);
-	    pp_control = INREG(PP_CONTROL);
-	} while ((pp_status & PP_ON) || (pp_control & POWER_TARGET_ON));
+	} while (pp_status & PP_ON);
     }
 }
 
diff-tree f21230d3e1cc5470e8f88404b5d9f1702bec44bb (from e603cd0c73344ef137d3276b5cfcbcf4df340778)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Dec 1 12:48:57 2006 -0800

    Add the [ax]4r4g4b4 source picture formats.

diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
index eae8171..daffa0c 100644
--- a/src/i915_exa_render.c
+++ b/src/i915_exa_render.c
@@ -116,6 +116,8 @@ static struct formatinfo I915TexFormats[
         {PICT_r5g6b5,   MAPSURF_16BIT | MT_16BIT_RGB565   },
         {PICT_a1r5g5b5, MAPSURF_16BIT | MT_16BIT_ARGB1555 },
         {PICT_x1r5g5b5, MAPSURF_16BIT | MT_16BIT_ARGB1555 },
+        {PICT_a4r4g4b4, MAPSURF_16BIT | MT_16BIT_ARGB4444 },
+        {PICT_x4r4g4b4, MAPSURF_16BIT | MT_16BIT_ARGB4444 },
         {PICT_a8,       MAPSURF_8BIT | MT_8BIT_A8 	  },
 };
 
diff-tree 16f9a56070a01c7ada8e566d9b73fcf7900136e0 (from e603cd0c73344ef137d3276b5cfcbcf4df340778)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Fri Dec 1 10:50:27 2006 -0800

    TV output exists on all 9xx chips except for 915G

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 3aafe3a..e04a44c 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -707,7 +707,7 @@ I830SetupOutputs(ScrnInfoPtr pScrn)
    } else {
       i830_dvo_init(pScrn);
    }
-   if (IS_I915GM(pI830) || IS_I945GM(pI830))
+   if (IS_I9XX(pI830) && !IS_I915G(pI830))
       i830_tv_init(pScrn);
 }
 
diff-tree e603cd0c73344ef137d3276b5cfcbcf4df340778 (from ec30356d950199903978265076b8a4e3960cf84f)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Fri Dec 1 10:08:36 2006 -0800

    Leave detected TV status alone when no free CRTC is available.
    
    Yes, this means not detecting TV hotplug when two outputs are
    already running. An alternative would be to turn off one of the other
    outputs temporarily, but that would cause flashing. Something to consider.

diff --git a/src/i830_tv.c b/src/i830_tv.c
index f7d9207..f5716f8 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -473,7 +473,7 @@ static const DisplayModeRec tvModes[] = 
  * \return TRUE if TV is connected.
  * \return FALSE if TV is disconnected.
  */
-static int
+static void
 i830_tv_detect_type (xf86CrtcPtr    crtc,
 		     xf86OutputPtr  output)
 {
@@ -536,7 +536,6 @@ i830_tv_detect_type (xf86CrtcPtr    crtc
     }
     
     dev_priv->type = type;
-    return type;
 }
 
 /**
@@ -548,25 +547,25 @@ i830_tv_detect_type (xf86CrtcPtr    crtc
 static enum detect_status
 i830_tv_detect(xf86OutputPtr output)
 {
-    xf86CrtcPtr	    crtc;
+    xf86CrtcPtr		    crtc;
     DisplayModeRec	    mode;
     I830OutputPrivatePtr    intel_output = output->driver_private;
-    int			    type;
+    struct i830_tv_priv	    *dev_priv = intel_output->dev_priv;
 
     crtc = i830GetLoadDetectPipe (output);
-    if (!crtc)
-	return OUTPUT_STATUS_UNKNOWN;
-    
-    if (intel_output->load_detect_temp)
+    if (crtc)
     {
-	mode = tvModes[0];
-	xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
-	i830PipeSetMode (crtc, &mode, FALSE);
+	if (intel_output->load_detect_temp)
+	{
+	    mode = tvModes[0];
+	    xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
+	    i830PipeSetMode (crtc, &mode, FALSE);
+	}
+	i830_tv_detect_type (crtc, output);
+	i830ReleaseLoadDetectPipe (output);
     }
-    type = i830_tv_detect_type (crtc, output);
-    i830ReleaseLoadDetectPipe (output);
     
-    switch (type) {
+    switch (dev_priv->type) {
     case TV_TYPE_NONE:
 	return OUTPUT_STATUS_DISCONNECTED;
     case TV_TYPE_UNKNOWN:
diff-tree ec30356d950199903978265076b8a4e3960cf84f (from 7642da82781826cb3b45078750cc54d8f592893a)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Fri Dec 1 10:06:29 2006 -0800

    Do output detection before any crtc allocation.
    
    Some output detection requires a crtc for load detection, perform all of the
    output detection before allocating any crtcs so that there will be a free
    crtc for any load detection. Avoids losing TV detection when two monitors
    are connected.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index c5e56e5..3aafe3a 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -880,6 +880,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 #ifdef XF86DRI
    unsigned long savedMMSize;
 #endif
+   enum detect_status output_status[MAX_OUTPUTS];
 
    if (pScrn->numEntities != 1)
       return FALSE;
@@ -1369,8 +1370,21 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       xf86CrtcPtr	      crtc;
       int		      p;
 
+      output_status[i] = (*output->funcs->detect) (output);
+   }
+   
+   for (i = 0; i < pI830->xf86_config.num_output; i++) 
+   {
+      xf86OutputPtr	      output = pI830->xf86_config.output[i];
+      I830OutputPrivatePtr    intel_output = output->driver_private;
+      xf86CrtcPtr	      crtc;
+      int		      p;
+
       output->crtc = NULL;
 
+      if (output_status[i] == OUTPUT_STATUS_DISCONNECTED)
+	 continue;
+      
       switch (intel_output->type) {
       case I830_OUTPUT_LVDS:
 	 /* LVDS must live on pipe B for two-pipe devices */
@@ -1381,23 +1395,19 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       case I830_OUTPUT_ANALOG:
       case I830_OUTPUT_DVO:
       case I830_OUTPUT_SDVO:
-	 if ((*output->funcs->detect)(output) != OUTPUT_STATUS_DISCONNECTED) 
+	 for (p = 0; p < pI830->xf86_config.num_crtc; p++)
 	 {
-	    for (p = 0; p < pI830->xf86_config.num_crtc; p++)
+	    crtc = pI830->xf86_config.crtc[p];
+	    if (!i830PipeInUse(crtc))
 	    {
-	       crtc = pI830->xf86_config.crtc[p];
-	       if (!i830PipeInUse(crtc))
-	       {
-		  output->crtc = crtc;
-		  break;
-	       }
+	       output->crtc = crtc;
+	       break;
 	    }
 	 }
 	 break;
       case I830_OUTPUT_TVOUT:
 	 crtc = pI830->xf86_config.crtc[0];
-	 if ((*output->funcs->detect)(output) != OUTPUT_STATUS_DISCONNECTED &&
-	     !i830PipeInUse(crtc))
+	 if (!i830PipeInUse(crtc))
 	 {
 	    output->crtc = crtc;
 	 }
diff-tree 7642da82781826cb3b45078750cc54d8f592893a (from de50ca9ed9e78c17be1badec62e35ed5e4d62b05)
Author: Keith Packard <keithp at ukulele.keithp.com>
Date:   Thu Nov 30 23:21:39 2006 -0800

    When CRTC is disable through RandR, the mode is NULL. Don't dereference it.
    
    Correctly interpret mode == NULL as CRTC disable, make sure the CRTC is
    disabled in this case.

diff --git a/src/i830_randr.c b/src/i830_randr.c
index 9ac54b5..373403f 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -550,7 +550,9 @@ xf86RandR12CrtcSet (ScreenPtr	pScreen,
     xf86CrtcPtr	save_crtcs[MAX_OUTPUTS];
     Bool		save_enabled = crtc->enabled;
 
-    if (!xf86ModesEqual (&crtc->curMode, mode))
+    if ((mode != NULL) != crtc->enabled)
+	changed = TRUE;
+    else if (mode && !xf86ModesEqual (&crtc->curMode, mode))
 	changed = TRUE;
     
     for (o = 0; o < pI830->xf86_config.num_output; o++) 
diff-tree de50ca9ed9e78c17be1badec62e35ed5e4d62b05 (from 8c44556408601db2be799b5ac5c4da1d92886d31)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Nov 30 17:56:47 2006 -0800

    Tristate the clock/data pins during GPIO when released while getting values.
    
    While the register is laid out suggesting that you can read a low value while
    driving the output high, and the I2C spec seems to indicate that you should be
    able to as well, and on some hardware this works successfully, on the i865 and
    perhaps some other chips it doesn't.  So, if we're not holding the clock or
    data pin low during GetBits, tristate the pin so that we can successfully read.
    
    This fixes i865 analog (VGA) DDC so it successfully sees slave acks.
    
    Also, improve the I2C bit-banging debugging.

diff --git a/src/i830_i2c.c b/src/i830_i2c.c
index 973ca61..d246c16 100644
--- a/src/i830_i2c.c
+++ b/src/i830_i2c.c
@@ -261,24 +261,46 @@ I830I2CAddress(I2CDevPtr d, I2CSlaveAddr
 
 #else
 
+#define I2C_DEBUG 0
+
+#if I2C_DEBUG
+static Bool first = TRUE;
+#endif
+
 static void
 i830I2CGetBits(I2CBusPtr b, int *clock, int *data)
 {
     ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
     I830Ptr pI830 = I830PTR(pScrn);
-    CARD32 val;
+    CARD32 val, tristate = 0;
 
     val = INREG(b->DriverPrivate.uval);
+
+    /* If we've released either of the lines from holding low, tristate them
+     * so that we can successfully read.  Some hardware fails to read low
+     * values driven by slaves when our master is not tri-stated, while other
+     * chips succeed.
+     */
+    if ((val & GPIO_DATA_DIR_OUT) && (val & GPIO_DATA_VAL_OUT))
+	tristate |= GPIO_DATA_DIR_IN | GPIO_DATA_DIR_MASK;
+    if ((val & GPIO_CLOCK_DIR_OUT) && (val & GPIO_CLOCK_VAL_OUT))
+	tristate |= GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK;
+
+    if (tristate) {
+	OUTREG(b->DriverPrivate.uval, tristate);
+
+	val = INREG(b->DriverPrivate.uval);
+    }
+
     *data = (val & GPIO_DATA_VAL_IN) != 0;
     *clock = (val & GPIO_CLOCK_VAL_IN) != 0;
-}
-
-#define I2C_DEBUG 0
 
 #if I2C_DEBUG
-static int last_clock = 0, last_data = 0;
-static Bool first = TRUE;
+    ErrorF("Getting I2C:                   %c %c\n",
+	   *clock ? '^' : 'v',
+	   *data ? '^' : 'v');
 #endif
+}
 
 static void
 i830I2CPutBits(I2CBusPtr b, int clock, int data)
@@ -287,23 +309,12 @@ i830I2CPutBits(I2CBusPtr b, int clock, i
 
 #if I2C_DEBUG
     int cur_clock, cur_data;
-    char *debug = "";
 #endif
 
     ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
     I830Ptr pI830 = I830PTR(pScrn);
 
 #if I2C_DEBUG
-    if (!first && cur_clock != last_clock && cur_data != last_data) {
-	/* If we change the clock and data simultaneously, that would be bad.
-	 * I thought we did sometimes, but maybe not.
-	 */
-	debug = " <--";
-    }
-
-    last_clock = cur_clock;
-    last_data = cur_data;
-
     i830I2CGetBits(b, &cur_clock, &cur_data);
 
     if (first) {
@@ -311,13 +322,10 @@ i830I2CPutBits(I2CBusPtr b, int clock, i
 	first = FALSE;
     }
 
-    ErrorF("Setting I2C 0x%08x to: %c %c (at: %c %c)%s\n",
+    ErrorF("Setting I2C 0x%08x to: %c %c\n",
 	   (int)b->DriverPrivate.uval,
 	   clock ? '^' : 'v',
-	   data ? '^' : 'v',
-	   cur_clock ? '^' : 'v',
-	   cur_data ? '^' : 'v',
-	   debug);
+	   data ? '^' : 'v');
 #endif
 
     if (!IS_I830(pI830) && !IS_845G(pI830)) {
diff-tree 8c44556408601db2be799b5ac5c4da1d92886d31 (from 28401b25cc5c1afb272e506cef196ba3a1258bd3)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Nov 30 15:56:52 2006 -0800

    Preserve some GPIO bits that the docs tell us to.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index e931934..7312f8a 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -281,12 +281,14 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 # define GPIO_CLOCK_VAL_MASK		(1 << 2)
 # define GPIO_CLOCK_VAL_OUT		(1 << 3)
 # define GPIO_CLOCK_VAL_IN		(1 << 4)
+# define GPIO_CLOCK_PULLUP_DISABLE	(1 << 5)
 # define GPIO_DATA_DIR_MASK		(1 << 8)
 # define GPIO_DATA_DIR_IN		(0 << 9)
 # define GPIO_DATA_DIR_OUT		(1 << 9)
 # define GPIO_DATA_VAL_MASK		(1 << 10)
 # define GPIO_DATA_VAL_OUT		(1 << 11)
 # define GPIO_DATA_VAL_IN		(1 << 12)
+# define GPIO_DATA_PULLUP_DISABLE	(1 << 13)
 
 /* p317, 319
  */
diff --git a/src/i830_i2c.c b/src/i830_i2c.c
index ea828ff..973ca61 100644
--- a/src/i830_i2c.c
+++ b/src/i830_i2c.c
@@ -283,6 +283,8 @@ static Bool first = TRUE;
 static void
 i830I2CPutBits(I2CBusPtr b, int clock, int data)
 {
+    CARD32 reserved = 0;
+
 #if I2C_DEBUG
     int cur_clock, cur_data;
     char *debug = "";
@@ -310,7 +312,7 @@ i830I2CPutBits(I2CBusPtr b, int clock, i
     }
 
     ErrorF("Setting I2C 0x%08x to: %c %c (at: %c %c)%s\n",
-	   b->DriverPrivate.uval,
+	   (int)b->DriverPrivate.uval,
 	   clock ? '^' : 'v',
 	   data ? '^' : 'v',
 	   cur_clock ? '^' : 'v',
@@ -318,15 +320,22 @@ i830I2CPutBits(I2CBusPtr b, int clock, i
 	   debug);
 #endif
 
+    if (!IS_I830(pI830) && !IS_845G(pI830)) {
+	/* On most chips, these bits must be preserved in software. */
+	reserved = INREG(b->DriverPrivate.uval) &
+	    (GPIO_DATA_PULLUP_DISABLE | GPIO_CLOCK_PULLUP_DISABLE);
+    }
+
     OUTREG(b->DriverPrivate.uval,
-	(data ? GPIO_DATA_VAL_OUT : 0) |
-	(clock ? GPIO_CLOCK_VAL_OUT : 0) |
-	GPIO_CLOCK_DIR_OUT |
-	GPIO_DATA_DIR_OUT |
-	GPIO_CLOCK_DIR_MASK |
-	GPIO_CLOCK_VAL_MASK |
-	GPIO_DATA_DIR_MASK |
-	GPIO_DATA_VAL_MASK);
+	   reserved |
+	   (data ? GPIO_DATA_VAL_OUT : 0) |
+	   (clock ? GPIO_CLOCK_VAL_OUT : 0) |
+	   GPIO_CLOCK_DIR_OUT |
+	   GPIO_DATA_DIR_OUT |
+	   GPIO_CLOCK_DIR_MASK |
+	   GPIO_CLOCK_VAL_MASK |
+	   GPIO_DATA_DIR_MASK |
+	   GPIO_DATA_VAL_MASK);
 }
 #endif
 
diff-tree 28401b25cc5c1afb272e506cef196ba3a1258bd3 (from ff64bc7397cafbec94e388e1625b3a1999f1aca7)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Nov 30 15:45:13 2006 -0800

    Add debug code for the bit-banging I2C implementation.

diff --git a/src/i830_i2c.c b/src/i830_i2c.c
index 8b93c8e..ea828ff 100644
--- a/src/i830_i2c.c
+++ b/src/i830_i2c.c
@@ -273,12 +273,51 @@ i830I2CGetBits(I2CBusPtr b, int *clock, 
     *clock = (val & GPIO_CLOCK_VAL_IN) != 0;
 }
 
+#define I2C_DEBUG 0
+
+#if I2C_DEBUG
+static int last_clock = 0, last_data = 0;
+static Bool first = TRUE;
+#endif
+
 static void
 i830I2CPutBits(I2CBusPtr b, int clock, int data)
 {
+#if I2C_DEBUG
+    int cur_clock, cur_data;
+    char *debug = "";
+#endif
+
     ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
     I830Ptr pI830 = I830PTR(pScrn);
 
+#if I2C_DEBUG
+    if (!first && cur_clock != last_clock && cur_data != last_data) {
+	/* If we change the clock and data simultaneously, that would be bad.
+	 * I thought we did sometimes, but maybe not.
+	 */
+	debug = " <--";
+    }
+
+    last_clock = cur_clock;
+    last_data = cur_data;
+
+    i830I2CGetBits(b, &cur_clock, &cur_data);
+
+    if (first) {
+	ErrorF("I2C Debug:        C D      C D\n");
+	first = FALSE;
+    }
+
+    ErrorF("Setting I2C 0x%08x to: %c %c (at: %c %c)%s\n",
+	   b->DriverPrivate.uval,
+	   clock ? '^' : 'v',
+	   data ? '^' : 'v',
+	   cur_clock ? '^' : 'v',
+	   cur_data ? '^' : 'v',
+	   debug);
+#endif
+
     OUTREG(b->DriverPrivate.uval,
 	(data ? GPIO_DATA_VAL_OUT : 0) |
 	(clock ? GPIO_CLOCK_VAL_OUT : 0) |
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 b94b7c4bcfdb7ba59ed818f72309b5060a2ab7ee (from parents)
Merge: b6fc8df9a52f5fe1b4d26ae06bc4d48235b44a67 25e6e497824a23eb231fc6fd6e483f601d612cee
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Nov 30 09:15:30 2006 -0800

    Merge branch 'exa' of ../xf86-video-intel into modesetting
    
    Conflicts:
    
    	man/i810.man
    	src/Makefile.am
    	src/i830.h
    	src/i830_driver.c
    	src/i830_rotate.c
    	src/i830_video.c

diff --cc man/i810.man
index fa588fb,509ffbc..ff45809
@@@ -181,32 -201,14 +181,37 @@@
  .BI "Option \*qLinearAlloc\*q \*q" integer \*q
  Allows more memory for the offscreen allocator. This usually helps in
  situations where HDTV movies are required to play but not enough offscreen
 -memory is usually available. Set this to 6144 for upto 1920x1080 HDTV support.
 +memory is usually available. Set this to 8160 for upto 1920x1080 HDTV support.
  Default 0KB (off).
  .TP
 +.BI "Option \*qLegacy3D\*q \*q" boolean \*q
 +Enable support for the legacy i915_dri.so 3D driver.
 +This will, among other things, make the 2D driver tell libGL to
 +load the 3D driver i915_dri.so instead of the newer i915tex_dri.so.
 +This option is only used for chipsets in the range i830-i945. 
 +Default for i830-i945 series: Enabled for i915 drm versions < 1.7.0. Otherwise
 +disabled. 
 +Default for i810: The option is not used.
 +Default for i965: The option is always true.
 +.TP
 +.BI "Option \*qAperTexSize\*q \*q" integer \*q
 +Give the size in kiB of the AGP aperture area that is reserved for the
 +DRM memory manager present in i915 drm from version 1.7.0 and upwards,
 +and that is used with the 3D driver in Mesa from version 6.5.2 and
 +upwards. If the size is set too high to make room for pre-allocated
 +VideoRam, the driver will try to reduce it automatically. If you use only
 +older Mesa or DRM versions, you may set this value to zero, and
 +atctivate the legacy texture pool (see 
 +.B "Option \*qLegacy3D\*q"
 +). If you run 3D programs with large texture memory requirements, you might
 +gain some performance by increasing this value.
 +Default: 32768.
-  
++.TP
+ .BI "Option \*qAccelMethod\*q \*q" string \*q
+ Choose acceleration architecture, either "XAA" or "EXA".  XAA is the old
+ (but stable) XFree86 based acceleration architecture.  EXA is a newer and
+ simpler acceleration architecture designed to better accelerate the X Render
+ extension.  Default: "XAA".
  
  .SH "SEE ALSO"
  __xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), xorgconfig(__appmansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__)
diff --cc src/Makefile.am
index 583925f,163cc3f..5246270
@@@ -24,7 -24,7 +24,8 @@@
  # -avoid-version prevents gratuitous .0.0.0 version numbers on the end
  # _ladir passes a dummy rpath to libtool so the thing will actually link
  # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
- AM_CFLAGS = @WARN_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@ -DI830_XV
 -AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ -DI830_XV -DI830_USE_XAA -DI830_USE_EXA
++AM_CFLAGS = @WARN_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@ \
++	-DI830_XV -DI830_USE_XAA -DI830_USE_EXA
  
  i810_drv_la_LTLIBRARIES = i810_drv.la
  i810_drv_la_LDFLAGS = -module -avoid-version
diff --cc src/i830.h
index 1534f61,9c37068..422fdb7
@@@ -69,13 -70,17 +69,22 @@@
  #include "i830_dri.h"
  #endif
  
+ #ifdef I830_USE_EXA
+ #include "exa.h"
+ Bool I830EXAInit(ScreenPtr pScreen);
+ #endif
+ 
+ #ifdef I830_USE_XAA
+ Bool I830XAAInit(ScreenPtr pScreen);
+ #endif
+ 
 +typedef struct _I830OutputRec I830OutputRec, *I830OutputPtr;
 +
  #include "common.h"
 +#include "i830_sdvo.h"
 +#include "i2c_vid.h"
  
 +/* I830 Video support */
  #define NEED_REPLIES				/* ? */
  #define EXTENSION_PROC_ARGS void *
  #include "extnsionst.h" 			/* required */
@@@ -147,155 -170,36 +156,163 @@@
  #endif
  } I830EntRec, *I830EntPtr;
  
 -typedef struct _MergedDisplayModeRec {
 -    DisplayModePtr First;
 -    DisplayModePtr Second;
 -    int    SecondPosition;
 -} I830MergedDisplayModeRec, *I830MergedDisplayModePtr;
 -
 -typedef struct _I830XineramaData {
 -    int x;
 -    int y;
 -    int width;
 -    int height;
 -} I830XineramaData;
 -
 -typedef struct _ModePrivateRec {
 -    I830MergedDisplayModeRec merged;
 -    VbeModeInfoData vbeData;
 -} I830ModePrivateRec, *I830ModePrivatePtr;
 -
 -typedef struct _region {
 -    int x0,x1,y0,y1;
 -} region;
 +/* store information about an Ixxx DVO */
 +/* The i830->i865 use multiple DVOs with multiple i2cs */
 +/* the i915, i945 have a single sDVO i2c bus - which is different */
 +#define MAX_OUTPUTS 6
 +
 +#define I830_I2C_BUS_DVO 1
 +#define I830_I2C_BUS_SDVO 2
 +
 +/* these are outputs from the chip - integrated only 
 +   external chips are via DVO or SDVO output */
 +#define I830_OUTPUT_UNUSED 0
 +#define I830_OUTPUT_ANALOG 1
 +#define I830_OUTPUT_DVO 2
 +#define I830_OUTPUT_SDVO 3
 +#define I830_OUTPUT_LVDS 4
 +#define I830_OUTPUT_TVOUT 5
 +
 +#define I830_DVO_CHIP_NONE 0
 +#define I830_DVO_CHIP_LVDS 1
 +#define I830_DVO_CHIP_TMDS 2
 +#define I830_DVO_CHIP_TVOUT 4
 +
 +struct _I830DVODriver {
 +   int type;
 +   char *modulename;
 +   char *fntablename;
 +   int address;
 +   const char **symbols;
 +   I830I2CVidOutputRec *vid_rec;
 +   void *dev_priv;
 +   pointer modhandle;
 +};
 +
 +extern const char *i830_output_type_names[];
 +
 +enum detect_status {
 +   OUTPUT_STATUS_CONNECTED,
 +   OUTPUT_STATUS_DISCONNECTED,
 +   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;
 +   /** Output-private structure.  Should replace i2c_drv */
 +   void *dev_priv;
 +#ifdef RANDR_12_INTERFACE
 +   RROutputPtr randr_output;
 +#endif
 +};
  
+ /** 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;
 +   int		  x;
 +   int		  y;
 +   Bool		  cursorInRange;
 +   Bool		  cursorShown;
 +   DisplayModeRec curMode;
 +   DisplayModeRec desiredMode;
 +#ifdef RANDR_12_INTERFACE
 +   RRCrtcPtr	  randr_crtc;
 +#endif
 +} I830PipeRec, *I830PipePtr;
 +
  typedef struct _I830Rec {
     unsigned char *MMIOBase;
     unsigned char *FbBase;
@@@ -416,8 -347,10 +435,9 @@@
     int NumScanlineColorExpandBuffers;
     int nextColorExpandBuf;
  
 -   I830RegRec SavedReg;
     I830RegRec ModeReg;
  
+    Bool useEXA;
     Bool noAccel;
     Bool SWCursor;
     Bool cursorOn;
@@@ -487,82 -455,13 +515,84 @@@
 -   Bool vbeRestoreWorkaround;
 -   Bool displayInfo;
 -   Bool devicePresence;
  
     OsTimerPtr devicesTimer;
  
 -   CARD32 savedAsurf;
 -   CARD32 savedBsurf;
 +   int ddc2;
 +   int num_outputs;
 +   struct _I830OutputRec output[MAX_OUTPUTS];
 +
 +   /* Panel size pulled from the BIOS */
 +   int PanelXRes, PanelYRes;
 +
 +   /* The BIOS's fixed timings for the LVDS */
 +   int panel_fixed_clock;
 +   int panel_fixed_hactive;
 +   int panel_fixed_hblank;
 +   int panel_fixed_hsyncoff;
 +   int panel_fixed_hsyncwidth;
 +   int panel_fixed_vactive;
 +   int panel_fixed_vblank;
 +   int panel_fixed_vsyncoff;
 +   int panel_fixed_vsyncwidth;
  
 -    enum last_3d last_3d;
 +   int backlight_duty_cycle;  /* restore backlight to this value */
 +   
 +   Bool panel_wants_dither;
 +
 +   CARD32 saveDSPACNTR;
 +   CARD32 saveDSPBCNTR;
 +   CARD32 savePIPEACONF;
 +   CARD32 savePIPEBCONF;
 +   CARD32 savePIPEASRC;
 +   CARD32 savePIPEBSRC;
 +   CARD32 saveFPA0;
 +   CARD32 saveFPA1;
 +   CARD32 saveDPLL_A;
 +   CARD32 saveDPLL_A_MD;
 +   CARD32 saveHTOTAL_A;
 +   CARD32 saveHBLANK_A;
 +   CARD32 saveHSYNC_A;
 +   CARD32 saveVTOTAL_A;
 +   CARD32 saveVBLANK_A;
 +   CARD32 saveVSYNC_A;
 +   CARD32 saveDSPASTRIDE;
 +   CARD32 saveDSPASIZE;
 +   CARD32 saveDSPAPOS;
 +   CARD32 saveDSPABASE;
 +   CARD32 saveDSPASURF;
 +   CARD32 saveFPB0;
 +   CARD32 saveFPB1;
 +   CARD32 saveDPLL_B;
 +   CARD32 saveDPLL_B_MD;
 +   CARD32 saveHTOTAL_B;
 +   CARD32 saveHBLANK_B;
 +   CARD32 saveHSYNC_B;
 +   CARD32 saveVTOTAL_B;
 +   CARD32 saveVBLANK_B;
 +   CARD32 saveVSYNC_B;
 +   CARD32 saveDSPBSTRIDE;
 +   CARD32 saveDSPBSIZE;
 +   CARD32 saveDSPBPOS;
 +   CARD32 saveDSPBBASE;
 +   CARD32 saveDSPBSURF;
 +   CARD32 saveVCLK_DIVISOR_VGA0;
 +   CARD32 saveVCLK_DIVISOR_VGA1;
 +   CARD32 saveVCLK_POST_DIV;
 +   CARD32 saveVGACNTRL;
 +   CARD32 saveADPA;
 +   CARD32 saveLVDS;
 +   CARD32 saveDVOA;
 +   CARD32 saveDVOB;
 +   CARD32 saveDVOC;
 +   CARD32 savePP_ON;
 +   CARD32 savePP_OFF;
 +   CARD32 savePP_CONTROL;
 +   CARD32 savePP_CYCLE;
 +   CARD32 savePFIT_CONTROL;
 +   CARD32 savePaletteA[256];
 +   CARD32 savePaletteB[256];
 +   CARD32 saveSWF[17];
 +   CARD32 saveBLC_PWM_CTL;
++
++   enum last_3d last_3d;
  } I830Rec;
  
  #define I830PTR(p) ((I830Ptr)((p)->driverPrivate))
@@@ -652,24 -550,19 +682,27 @@@
  extern void I830ChangeFrontbuffer(ScrnInfoPtr pScrn,int buffer);
  extern Bool I830IsPrimary(ScrnInfoPtr pScrn);
  
 -extern DisplayModePtr I830GetModePool(ScrnInfoPtr pScrn, vbeInfoPtr pVbe,
 -					VbeInfoBlock *vbe);
 -extern void I830SetModeParameters(ScrnInfoPtr pScrn, vbeInfoPtr pVbe);
 -extern void I830UnsetModeParameters(ScrnInfoPtr pScrn, vbeInfoPtr pVbe);
 -extern void I830PrintModes(ScrnInfoPtr pScrn);
 -extern int I830GetBestRefresh(ScrnInfoPtr pScrn, int refresh);
 -extern Bool I830CheckModeSupport(ScrnInfoPtr pScrn, int x, int y, int mode);
  extern Bool I830Rotate(ScrnInfoPtr pScrn, DisplayModePtr mode);
  extern Bool I830FixOffset(ScrnInfoPtr pScrn, I830MemRange *mem);
 +extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg,
 +			char *name);
 +
 +/* i830_display.c */
 +Bool
 +i830PipeHasType (ScrnInfoPtr pScrn, int pipe, int type);
 +
 +/* i830_crt.c */
 +void i830_crt_init(ScrnInfoPtr pScrn);
 +
 +/* i830_dvo.c */
 +void i830_dvo_init(ScrnInfoPtr pScrn);
 +
 +/* i830_lvds.c */
 +void i830_lvds_init(ScrnInfoPtr pScrn);
  
+ extern void i830MarkSync(ScrnInfoPtr pScrn);
+ extern void i830WaitSync(ScrnInfoPtr pScrn);
+ 
  /* i830_memory.c */
  Bool I830BindAGPMemory(ScrnInfoPtr pScrn);
  Bool I830UnbindAGPMemory(ScrnInfoPtr pScrn);
diff --cc src/i830_driver.c
index 55610f5,12fc524..61dbeea
@@@ -197,10 -197,20 +197,22 @@@
  
  #ifdef XF86DRI
  #include "dri.h"
 +#include <sys/ioctl.h>
 +#include <errno.h>
  #endif
  
+ #ifdef I830_USE_EXA
+ const char *I830exaSymbols[] = {
+     "exaGetVersion",
+     "exaDriverInit",
+     "exaDriverFini",
+     "exaOffscreenAlloc",
+     "exaOffscreenFree",
+     "exaWaitSync",
+     NULL
+ };
+ #endif
+ 
  #define BIT(x) (1 << (x))
  #define MAX(a,b) ((a) > (b) ? (a) : (b))
  #define NB_OF(x) (sizeof (x) / sizeof (*x))
@@@ -265,11 -278,18 +280,14 @@@
     OPTION_FIXEDPIPE,
     OPTION_ROTATE,
     OPTION_LINEARALLOC,
 -   OPTION_MERGEDFB,
 -   OPTION_METAMODES,
 -   OPTION_SECONDHSYNC,
 -   OPTION_SECONDVREFRESH,
 -   OPTION_SECONDPOSITION,
 -   OPTION_INTELXINERAMA
 +   OPTION_INTELTEXPOOL,
 +   OPTION_INTELMMSIZE
  } I830Opts;
  
 -static OptionInfoRec I830BIOSOptions[] = {
 +static OptionInfoRec I830Options[] = {
+ #if defined(I830_USE_XAA) && defined(I830_USE_EXA)
+    {OPTION_ACCELMETHOD,	"AccelMethod",	OPTV_ANYSTR,	{0},	FALSE},
+ #endif
     {OPTION_NOACCEL,	"NoAccel",	OPTV_BOOLEAN,	{0},	FALSE},
     {OPTION_SW_CURSOR,	"SWcursor",	OPTV_BOOLEAN,	{0},	FALSE},
     {OPTION_CACHE_LINES,	"CacheLines",	OPTV_INTEGER,	{0},	FALSE},
@@@ -3189,70 -7584,110 +3284,69 @@@
           break;
     }
  
- 
 -   return TRUE;
 -}
 -
 -static void
 -I830AdjustFrame(int scrnIndex, int x, int y, int flags)
 -{
 -   ScrnInfoPtr pScrn;
 -   I830Ptr pI830;
 -   vbeInfoPtr pVbe;
 -   unsigned long Start;
 -
 -   pScrn = xf86Screens[scrnIndex];
 -   pI830 = I830PTR(pScrn);
 -   pVbe = pI830->pVbe;
 -
 -   DPRINTF(PFX, "I830AdjustFrame: y = %d (+ %d), x = %d (+ %d)\n",
 -	   x, pI830->xoffset, y, pI830->yoffset);
 -
 -   /* Sync the engine before adjust frame */
 -   i830WaitSync(pScrn);
 -
 -   if (pI830->MergedFB) {
 -      I830AdjustFrameMerged(scrnIndex, x, y, flags);
 -
 -      if (pI830->pipe == 0) {
 -         OUTREG(DSPABASE, pI830->FrontBuffer.Start + ((pI830->FirstframeY0 * pScrn->displayWidth + pI830->FirstframeX0) * pI830->cpp));
 -         OUTREG(DSPBBASE, pI830->FrontBuffer.Start + ((pI830->pScrn_2->frameY0 * pScrn->displayWidth + pI830->pScrn_2->frameX0) * pI830->cpp));
 -      } else {
 -         OUTREG(DSPBBASE, pI830->FrontBuffer.Start + ((pI830->FirstframeY0 * pScrn->displayWidth + pI830->FirstframeX0) * pI830->cpp));
 -         OUTREG(DSPABASE, pI830->FrontBuffer.Start + ((pI830->pScrn_2->frameY0 * pScrn->displayWidth + pI830->pScrn_2->frameX0) * pI830->cpp));
 -      }
 -
 -      return;
 -   }
 -
 -   if (I830IsPrimary(pScrn))
 -      Start = pI830->FrontBuffer.Start;
 -   else {
 -      I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
 -      Start = pI8301->FrontBuffer2.Start;
 -   }
 -
 -   /* Sigh...
 -    * It seems that there are quite a few Video BIOS' that get this wrong.
 -    * So, we'll bypass the VBE call and hit the hardware directly.
 -    */
 -
 -   if (pI830->Clone) {
 -      if (!pI830->pipe == 0) {
 -         if (!IS_I965G(pI830)) {
 -            OUTREG(DSPABASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
 -         } else {
 -            OUTREG(DSPABASE, 0);
 -            OUTREG(DSPASURF, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
 -         }
 -      } else {
 -         if (!IS_I965G(pI830)) {
 -            OUTREG(DSPBBASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
 -         } else {
 -            OUTREG(DSPBBASE, 0);
 -            OUTREG(DSPBSURF, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
 -         }
 -      }
 -   }
 -
 -   if (pI830->pipe == 0) {
 -      if (!IS_I965G(pI830)) {
 -         OUTREG(DSPABASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
 -      } else {
 -         OUTREG(DSPABASE, 0);
 -         OUTREG(DSPASURF, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
 -      }
 -   } else {
 -      if (!IS_I965G(pI830)) {
 -         OUTREG(DSPBBASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
 +#ifdef XF86DRI
 +   if (pI830->directRenderingEnabled && (pI830->mmModeFlags & I830_KERNEL_MM)) {
 +      unsigned long aperEnd = ROUND_DOWN_TO(pI830->FbMapSize, GTT_PAGE_SIZE) 
 +	 / GTT_PAGE_SIZE;
 +      unsigned long aperStart = ROUND_TO(pI830->FbMapSize - KB(pI830->mmSize), GTT_PAGE_SIZE) 
 +	 / GTT_PAGE_SIZE;
 +
 +      if (aperEnd < aperStart || aperEnd - aperStart < I830_MM_MINPAGES) {
 +	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 
 +		    "Too little AGP aperture space for DRM memory manager.\n"
 +		    "\tPlease increase AGP aperture size from BIOS configuration screen\n"
 +		    "\tor decrease the amount of video RAM using option \"VideoRam\".\n"
 +		    "\tDisabling DRI.\n");
 +	 pI830->directRenderingOpen = FALSE;
 +	 I830DRICloseScreen(pScreen);
 +	 pI830->directRenderingEnabled = FALSE;
        } else {
 -         OUTREG(DSPBBASE, 0);
 -         OUTREG(DSPBSURF, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
 +#ifndef XSERVER_LIBDRM_MM
 +	 if (I830DrmMMInit(pI830->drmSubFD, aperStart, aperEnd - aperStart,
 +			   DRM_BO_MEM_TT)) {
 +#else
 +	 if (drmMMInit(pI830->drmSubFD, aperStart, aperEnd - aperStart,
 +		       DRM_BO_MEM_TT)) {
 +#endif	   
 +	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 
 +		       "Could not initialize the DRM memory manager.\n");
 +	    
 +	    pI830->directRenderingOpen = FALSE;
 +	    I830DRICloseScreen(pScreen);
 +	    pI830->directRenderingEnabled = FALSE;
 +	 } else {
 +	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
 +		       "Initialized DRM memory manager, %ld AGP pages\n"
 +		       "\tat AGP offset 0x%lx\n", 
 +		       aperEnd - aperStart,
 +		       aperStart);
 +	 }
        }
     }
 -}
 -
 -static void
 -I830BIOSFreeScreen(int scrnIndex, int flags)
 -{
 -   I830BIOSFreeRec(xf86Screens[scrnIndex]);
 -   if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
 -      vgaHWFreeHWRec(xf86Screens[scrnIndex]);
 -}
 -
 -#ifndef SAVERESTORE_HWSTATE
 -#define SAVERESTORE_HWSTATE 0
  #endif
  
 -#if SAVERESTORE_HWSTATE
 +   return TRUE;
 +}
 +
  static void
 -SaveHWOperatingState(ScrnInfoPtr pScrn)
 +i830AdjustFrame(int scrnIndex, int x, int y, int flags)
  {
 +   ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
     I830Ptr pI830 = I830PTR(pScrn);
 -   I830RegPtr save = &pI830->SavedReg;
 +   int i;
 +
 +   DPRINTF(PFX, "i830AdjustFrame: y = %d (+ %d), x = %d (+ %d)\n",
 +	   x, pI830->xoffset, y, pI830->yoffset);
  
 -   DPRINTF(PFX, "SaveHWOperatingState\n");
 +   /* Sync the engine before adjust frame */
 +   if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
 +      (*pI830->AccelInfoRec->Sync)(pScrn);
 +      pI830->AccelInfoRec->NeedToSync = FALSE;
 +   }
  
 -   return;
 +   for (i = 0; i < pI830->num_pipes; i++)
 +      if (pI830->pipes[i].enabled)
 +	 i830PipeSetBase(pScrn, i, x, y);
  }
  
  static void
@@@ -3853,15 -8888,52 +3953,52 @@@
  }
  
  void
+ i830WaitSync(ScrnInfoPtr pScrn)
+ {
+    I830Ptr pI830 = I830PTR(pScrn);
+ 
+ #ifdef I830_USE_XAA
+    if (!pI830->noAccel && !pI830->useEXA && pI830->AccelInfoRec 
+ 	&& pI830->AccelInfoRec->NeedToSync) {
+       (*pI830->AccelInfoRec->Sync)(pScrn);
+       pI830->AccelInfoRec->NeedToSync = FALSE;
+    }
+ #endif
+ #ifdef I830_USE_EXA
+    if (!pI830->noAccel && pI830->useEXA && pI830->EXADriverPtr) {
+ 	ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
+ 	exaWaitSync(pScreen);
+    }
+ #endif
+ }
+ 
+ void
+ i830MarkSync(ScrnInfoPtr pScrn)
+ {
+    I830Ptr pI830 = I830PTR(pScrn);
+ 
+ #ifdef I830_USE_XAA
+    if (!pI830->useEXA && pI830->AccelInfoRec)
+       pI830->AccelInfoRec->NeedToSync = TRUE;
+ #endif
+ #ifdef I830_USE_EXA
+    if (pI830->useEXA && pI830->EXADriverPtr) {
+       ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
+       exaMarkSync(pScreen);
+    }
+ #endif
+ }
+ 
+ void
  I830InitpScrn(ScrnInfoPtr pScrn)
  {
 -   pScrn->PreInit = I830BIOSPreInit;
 -   pScrn->ScreenInit = I830BIOSScreenInit;
 -   pScrn->SwitchMode = I830BIOSSwitchMode;
 -   pScrn->AdjustFrame = I830AdjustFrame;
 -   pScrn->EnterVT = I830BIOSEnterVT;
 -   pScrn->LeaveVT = I830BIOSLeaveVT;
 -   pScrn->FreeScreen = I830BIOSFreeScreen;
 +   pScrn->PreInit = I830PreInit;
 +   pScrn->ScreenInit = I830ScreenInit;
 +   pScrn->SwitchMode = I830SwitchMode;
 +   pScrn->AdjustFrame = i830AdjustFrame;
 +   pScrn->EnterVT = I830EnterVT;
 +   pScrn->LeaveVT = I830LeaveVT;
 +   pScrn->FreeScreen = I830FreeScreen;
     pScrn->ValidMode = I830ValidMode;
     pScrn->PMEvent = I830PMEvent;
  }
diff-tree b6fc8df9a52f5fe1b4d26ae06bc4d48235b44a67 (from 359dc81c07901665da0f86c573c096fa1661cdd2)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Nov 29 15:06:32 2006 -0800

    Properly detect the GTT size on the G965.
    
    In the past, the GTT has always been sized just large enough to map the whole
    graphics aperture.  However, apparently on the G965 that isn't the case, and
    it is actually 512KB on hardware with a 256MB aperture.  This resulted in X
    not bothering to allocate memory for 256KB that it thought was already mapped
    into stolen memory, and thus garbage rendering (particularly visible in large
    video modes that displayed this unallocated memory).  The kernel happens to
    get the right answer by hardwiring a 512KB GTT size already, but that may not
    be true on future hardware.
    
    Instead, we use a convenient field in PGETBL_CTL that's specifically for the
    GTT size rather than the aperture size, which gets us the answer we want.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index 53a063f..9c6e0dd 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -499,6 +499,11 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define PGETBL_ADDR_MASK    0xFFFFF000
 #define PGETBL_ENABLE_MASK  0x00000001
 #define PGETBL_ENABLED      0x00000001
+/** Added in 965G, this field has the actual size of the global GTT */
+#define PGETBL_SIZE_MASK    0x0000000e
+#define PGETBL_SIZE_512KB   (0 << 1)
+#define PGETBL_SIZE_256KB   (1 << 1)
+#define PGETBL_SIZE_128KB   (2 << 1)
 
 /* Register containing pge table error results, p276
  */
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 39ffa54..55610f5 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -394,7 +394,7 @@ I830DetectMemory(ScrnInfoPtr pScrn)
    I830Ptr pI830 = I830PTR(pScrn);
    PCITAG bridge;
    CARD16 gmch_ctrl;
-   int memsize = 0;
+   int memsize = 0, gtt_size;
    int range;
 #if 0
    VbeInfoBlock *vbeInfo;
@@ -403,9 +403,35 @@ I830DetectMemory(ScrnInfoPtr pScrn)
    bridge = pciTag(0, 0, 0);		/* This is always the host bridge */
    gmch_ctrl = pciReadWord(bridge, I830_GMCH_CTRL);
 
-   /* We need to reduce the stolen size, by the GTT and the popup.
-    * The GTT varying according the the FbMapSize and the popup is 4KB */
-   range = (pI830->FbMapSize / (1024*1024)) + 4;
+   if (IS_I965G(pI830)) {
+      /* The 965 may have a GTT that is actually larger than is necessary
+       * to cover the aperture, so check the hardware's reporting of the
+       * GTT size.
+       */
+      switch (INREG(PGETBL_CTL) & PGETBL_SIZE_MASK) {
+      case PGETBL_SIZE_512KB:
+	 gtt_size = 512;
+	 break;
+      case PGETBL_SIZE_256KB:
+	 gtt_size = 256;
+	 break;
+      case PGETBL_SIZE_128KB:
+	 gtt_size = 128;
+	 break;
+      default:
+	 FatalError("Unknown GTT size value: %08x\n", (int)INREG(PGETBL_CTL));
+      }
+   } else {
+      /* Older chipsets only had GTT appropriately sized for the aperture. */
+      gtt_size = pI830->FbMapSize / (1024*1024);
+   }
+
+   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "detected %d kB GTT.\n", gtt_size);
+
+   /* The stolen memory has the GTT at the top, and the 4KB popup below that.
+    * Everything else can be freely used by the graphics driver.
+    */
+   range = gtt_size + 4;
 
    if (IS_I85X(pI830) || IS_I865G(pI830) || IS_I9XX(pI830)) {
       switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
diff-tree 359dc81c07901665da0f86c573c096fa1661cdd2 (from 9e4e7d4fa25a64a2494e7531967599142e60e716)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Nov 29 15:01:39 2006 -0800

    Revert "Don't allocate stuff in the first 256K of video memory (GATT?)"
    
    This reverts commit 997e8c9bb4235cab1fff4738387df9afcbea0a03.
    
    The GTT is definitely located at the end of stolen memory.  This commit
    apparently worked around mis-estimation of the GTT size.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 1e619e4..39ffa54 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -806,7 +806,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    pointer pVBEModule = NULL;
    Bool enable;
    const char *chipname;
-   int mem_skip;
 #ifdef XF86DRI
    unsigned long savedMMSize;
 #endif
@@ -1126,15 +1125,8 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    /*
     * Get the pre-allocated (stolen) memory size.
     */
-    
-   mem_skip = 0;
-   
-   /* On 965, it looks like the GATT table is inside the aperture? */
-   if (IS_I965G(pI830))
-      mem_skip = pI830->FbMapSize >> 10;
-    
-   pI830->StolenMemory.Size = I830DetectMemory(pScrn) - mem_skip;
-   pI830->StolenMemory.Start = mem_skip;
+   pI830->StolenMemory.Size = I830DetectMemory(pScrn);
+   pI830->StolenMemory.Start = 0;
    pI830->StolenMemory.End = pI830->StolenMemory.Size;
 
    /* Find the maximum amount of agpgart memory available. */
diff-tree 9e4e7d4fa25a64a2494e7531967599142e60e716 (from 8d9ba2405d1f1e58a0cfb570e83e9206af8525b5)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Nov 28 16:36:09 2006 -0800

    Conditionally compile old-server compatibility code in.
    
    This also replaces calls to compat code with the real names of the functions,
    and slips #defines to an i830-namespaced version in when doing compat.
    The current server version (7.1.99.2) is still left as requiring compat code,
    since the version hasn't been bumped yet.
    
    This also fixes some failures to call the compat code, and some failures to
    actually compile the compat code.  Oops.

diff --git a/src/Makefile.am b/src/Makefile.am
index 52def8b..583925f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -62,6 +62,7 @@ i810_drv_la_SOURCES = \
 	 i830_display.h \
          i830_driver.c \
 	 i830_dvo.c \
+         i830_edid_modes.c \
          i830.h \
          i830_i2c.c \
          i830_io.c \
@@ -79,6 +80,7 @@ i810_drv_la_SOURCES = \
 	 i830_tv.c \
 	 i830_xf86Modes.h \
 	 i830_xf86Modes.c \
+	 i830_xf86cvt.c \
 	 i915_3d.c \
 	 i915_3d.h \
 	 i915_reg.h \
diff --git a/src/i830_crt.c b/src/i830_crt.c
index f067260..76a8007 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -316,7 +316,7 @@ i830_crt_get_modes(ScrnInfoPtr pScrn, I8
     fixed_mon.vrefresh[0].lo = 50.0;
     fixed_mon.vrefresh[0].hi = 70.0;
 
-    modes = i830xf86DuplicateModes(pScrn, pScrn->monitor->Modes);
+    modes = xf86DuplicateModes(pScrn, pScrn->monitor->Modes);
     i830xf86ValidateModesSync(pScrn, modes, &fixed_mon);
     i830xf86PruneInvalidModes(pScrn, &modes, TRUE);
 
diff --git a/src/i830_display.c b/src/i830_display.c
index 04f85cc..e2e4b6e 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -321,7 +321,7 @@ i830PipeFindClosestMode(ScrnInfoPtr pScr
 	assert(pScan->VRefresh != 0.0);
 
 	/* If there's an exact match, we're done. */
-	if (I830ModesEqual(pScan, pMode)) {
+	if (xf86ModesEqual(pScan, pMode)) {
 	    pBest = pMode;
 	    break;
 	}
@@ -366,7 +366,7 @@ i830PipeFindClosestMode(ScrnInfoPtr pScr
 		   "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)) {
 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		   "Choosing pipe %d's mode %dx%d@%.1f instead of xf86 "
 		   "mode %dx%d@%.1f\n", pipe,
@@ -434,7 +434,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     Bool didLock = FALSE;
 #endif
 
-    if (I830ModesEqual(&pI830Pipe->curMode, pMode))
+    if (xf86ModesEqual(&pI830Pipe->curMode, pMode))
 	return TRUE;
 
     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested pix clock: %d\n",
@@ -957,7 +957,7 @@ i830GetLoadDetectPipe(ScrnInfoPtr pScrn,
     output->pipe = i;
     output->enabled = TRUE;
 
-    I830xf86SetModeCrtc(&mode, INTERLACE_HALVE_V);
+    xf86SetModeCrtc(&mode, INTERLACE_HALVE_V);
 
     i830PipeSetMode(pScrn, &mode, i, FALSE);
 
diff --git a/src/i830_display.h b/src/i830_display.h
index 322f635..266d0b2 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -25,6 +25,8 @@
  *
  */
 
+#include "xorgVersion.h"
+
 /* i830_display.c */
 DisplayModePtr
 i830PipeFindClosestMode(ScrnInfoPtr pScrn, int pipe, DisplayModePtr pMode);
@@ -41,8 +43,12 @@ Bool i830PipeInUse(ScrnInfoPtr pScrn, in
 
 /** @{
  */
-DisplayModePtr i830xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC);
-DisplayModePtr i830xf86CVTMode(int HDisplay, int VDisplay, float VRefresh,
-			       Bool Reduced, Bool Interlaced);
+#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 --git a/src/i830_edid_modes.c b/src/i830_edid_modes.c
index 05df60c..fcb71d2 100644
--- a/src/i830_edid_modes.c
+++ b/src/i830_edid_modes.c
@@ -25,8 +25,8 @@
  * @file This is a copy of edid_modes.c from the X Server, for compatibility
  * with old X Servers.
  */
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
+#ifdef HAVE_CONFIG_H
+#include <config.h>
 #endif
 
 #include "xf86.h"
@@ -35,6 +35,10 @@
 #include "property.h"
 #include "propertyst.h"
 #include "xf86DDC.h"
+#include "i830.h"
+#include "i830_display.h"
+
+#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,1,99,2,0)
 
 /*
  * TODO:
@@ -92,7 +96,7 @@ DDCModesFromStandardTiming(int scrnIndex
 
     for (i = 0; i < STD_TIMINGS; i++) {
         if (timing[i].hsize && timing[i].vsize && timing[i].refresh) {
-            Mode =  i830xf86CVTMode(timing[i].hsize, timing[i].vsize,
+            Mode =  xf86CVTMode(timing[i].hsize, timing[i].vsize,
                                 timing[i].refresh, FALSE, FALSE);
 	    Mode->type = M_T_DRIVER;
             Modes = xf86ModesAdd(Modes, Mode);
@@ -164,52 +168,8 @@ DDCModeFromDetailedTiming(int scrnIndex,
     return Mode;
 }
 
-/*
- *
- */
-static void
-DDCGuessRangesFromModes(int scrnIndex, MonPtr Monitor, DisplayModePtr Modes)
-{
-    DisplayModePtr Mode = Modes;
-
-    if (!Monitor || !Modes)
-        return;
-
-    /* set up the ranges for scanning through the modes */
-    Monitor->nHsync = 1;
-    Monitor->hsync[0].lo = 1024.0;
-    Monitor->hsync[0].hi = 0.0;
-
-    Monitor->nVrefresh = 1;
-    Monitor->vrefresh[0].lo = 1024.0;
-    Monitor->vrefresh[0].hi = 0.0;
-
-    while (Mode) {
-        if (!Mode->HSync)
-            Mode->HSync = ((float) Mode->Clock ) / ((float) Mode->HTotal);
-
-        if (!Mode->VRefresh)
-            Mode->VRefresh = (1000.0 * ((float) Mode->Clock)) / 
-                ((float) (Mode->HTotal * Mode->VTotal));
-
-        if (Mode->HSync < Monitor->hsync[0].lo)
-            Monitor->hsync[0].lo = Mode->HSync;
-
-        if (Mode->HSync > Monitor->hsync[0].hi)
-            Monitor->hsync[0].hi = Mode->HSync;
-
-        if (Mode->VRefresh < Monitor->vrefresh[0].lo)
-            Monitor->vrefresh[0].lo = Mode->VRefresh;
-
-        if (Mode->VRefresh > Monitor->vrefresh[0].hi)
-            Monitor->vrefresh[0].hi = Mode->VRefresh;
-
-        Mode = Mode->next;
-    }
-}
-
 DisplayModePtr
-i830xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC)
+xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC)
 {
     int preferred, i;
     DisplayModePtr Modes = NULL, Mode;
@@ -247,3 +207,5 @@ i830xf86DDCGetModes(int scrnIndex, xf86M
 
     return Modes;
 }
+
+#endif /* XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,1,99,2,0) */
diff --git a/src/i830_modes.c b/src/i830_modes.c
index 9e952c8..60bedad 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -158,11 +158,11 @@ i830_reprobe_output_modes(ScrnInfoPtr pS
 	    /* The code to choose the best mode per pipe later on will require
 	     * VRefresh to be set.
 	     */
-	    mode->VRefresh = i830xf86ModeVRefresh(mode);
-	    I830xf86SetModeCrtc(mode, INTERLACE_HALVE_V);
+	    mode->VRefresh = xf86ModeVRefresh(mode);
+	    xf86SetModeCrtc(mode, INTERLACE_HALVE_V);
 
 #ifdef DEBUG_REPROBE
-	    PrintModeline(pScrn->scrnIndex, mode);
+	    xf86PrintModeline(pScrn->scrnIndex, mode);
 #endif
 	}
     }
@@ -203,7 +203,7 @@ i830_set_xf86_modes_from_outputs(ScrnInf
     for (i = 0; i < pI830->num_outputs; i++) {
 	if (pI830->output[i].probed_modes != NULL) {
 	    pScrn->modes =
-		i830xf86DuplicateModes(pScrn, pI830->output[i].probed_modes);
+		xf86DuplicateModes(pScrn, pI830->output[i].probed_modes);
 	    break;
 	}
     }
diff --git a/src/i830_randr.c b/src/i830_randr.c
index 389805a..9def4d8 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -117,7 +117,7 @@ I830RandRGetInfo (ScreenPtr pScreen, Rot
 	    return FALSE;
 	RRRegisterRate (pScreen, pSize, refresh);
 
-	if (I830ModesEqual(mode, scrp->currentMode) &&
+	if (xf86ModesEqual(mode, scrp->currentMode) &&
 	    mode->HDisplay == scrp->virtualX &&
 	    mode->VDisplay == scrp->virtualY)
 	{
@@ -509,7 +509,7 @@ I830RandRCrtcNotify (RRCrtcPtr	crtc)
 	    for (j = 0; j < rrout->numModes; j++)
 	    {
 		DisplayModePtr	outMode = rrout->modes[j]->devPrivate;
-		if (I830ModesEqual(pipeMode, outMode))
+		if (xf86ModesEqual(pipeMode, outMode))
 		{
 		    mode = rrout->modes[j];
 		    break;
diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c
index 24cc23b..809acf5 100644
--- a/src/i830_xf86Modes.c
+++ b/src/i830_xf86Modes.c
@@ -45,13 +45,14 @@
  * there but we still want to use.  We need to come up with better API here.
  */
 
+#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,1,99,2,0)
 /**
  * Calculates the horizontal sync rate of a mode.
  *
  * Exact copy of xf86Mode.c's.
  */
 double
-i830xf86ModeHSync(DisplayModePtr mode)
+xf86ModeHSync(DisplayModePtr mode)
 {
     double hsync = 0.0;
     
@@ -69,7 +70,7 @@ i830xf86ModeHSync(DisplayModePtr mode)
  * Exact copy of xf86Mode.c's.
  */
 double
-i830xf86ModeVRefresh(DisplayModePtr mode)
+xf86ModeVRefresh(DisplayModePtr mode)
 {
     double refresh = 0.0;
 
@@ -89,7 +90,7 @@ i830xf86ModeVRefresh(DisplayModePtr mode
 
 /** Sets a default mode name of <width>x<height> on a mode. */
 void
-i830xf86SetModeDefaultName(DisplayModePtr mode)
+xf86SetModeDefaultName(DisplayModePtr mode)
 {
     if (mode->name != NULL)
 	xfree(mode->name);
@@ -98,7 +99,7 @@ i830xf86SetModeDefaultName(DisplayModePt
 }
 
 /*
- * I830xf86SetModeCrtc
+ * xf86SetModeCrtc
  *
  * Initialises the Crtc parameters for a mode.  The initialisation includes
  * adjustments for interlaced and double scan modes.
@@ -106,7 +107,7 @@ i830xf86SetModeDefaultName(DisplayModePt
  * Exact copy of xf86Mode.c's.
  */
 void
-I830xf86SetModeCrtc(DisplayModePtr p, int adjustFlags)
+xf86SetModeCrtc(DisplayModePtr p, int adjustFlags)
 {
     if ((p == NULL) || ((p->type & M_T_CRTC_C) == M_T_BUILTIN))
 	return;
@@ -191,7 +192,7 @@ I830xf86SetModeCrtc(DisplayModePtr p, in
  * Allocates and returns a copy of pMode, including pointers within pMode.
  */
 DisplayModePtr
-i830xf86DuplicateMode(DisplayModePtr pMode)
+xf86DuplicateMode(DisplayModePtr pMode)
 {
     DisplayModePtr pNew;
 
@@ -200,7 +201,7 @@ i830xf86DuplicateMode(DisplayModePtr pMo
     pNew->next = NULL;
     pNew->prev = NULL;
     if (pNew->name == NULL) {
-	i830xf86SetModeDefaultName(pMode);
+	xf86SetModeDefaultName(pMode);
     } else {
 	pNew->name = xnfstrdup(pMode->name);
     }
@@ -215,7 +216,7 @@ i830xf86DuplicateMode(DisplayModePtr pMo
  * \param modeList doubly-linked mode list
  */
 DisplayModePtr
-i830xf86DuplicateModes(ScrnInfoPtr pScrn, DisplayModePtr modeList)
+xf86DuplicateModes(ScrnInfoPtr pScrn, DisplayModePtr modeList)
 {
     DisplayModePtr first = NULL, last = NULL;
     DisplayModePtr mode;
@@ -223,7 +224,7 @@ i830xf86DuplicateModes(ScrnInfoPtr pScrn
     for (mode = modeList; mode != NULL; mode = mode->next) {
 	DisplayModePtr new;
 
-	new = i830xf86DuplicateMode(mode);
+	new = xf86DuplicateMode(mode);
 
 	/* Insert pNew into modeList */
 	if (last) {
@@ -249,7 +250,7 @@ i830xf86DuplicateModes(ScrnInfoPtr pScrn
  * This isn't in xf86Modes.c, but it might deserve to be there.
  */
 Bool
-I830ModesEqual(DisplayModePtr pMode1, DisplayModePtr pMode2)
+xf86ModesEqual(DisplayModePtr pMode1, DisplayModePtr pMode2)
 {
      if (pMode1->Clock == pMode2->Clock &&
 	 pMode1->HDisplay == pMode2->HDisplay &&
@@ -285,7 +286,7 @@ add(char **p, char *new)
  * Convenient VRefresh printing was added, though, compared to xf86Mode.c
  */
 void
-PrintModeline(int scrnIndex,DisplayModePtr mode)
+xf86PrintModeline(int scrnIndex,DisplayModePtr mode)
 {
     char tmp[256];
     char *flags = xnfcalloc(1, 1);
@@ -317,9 +318,10 @@ PrintModeline(int scrnIndex,DisplayModeP
 		   mode->name, mode->VRefresh, mode->Clock/1000., mode->HDisplay,
 		   mode->HSyncStart, mode->HSyncEnd, mode->HTotal,
 		   mode->VDisplay, mode->VSyncStart, mode->VSyncEnd,
-		   mode->VTotal, flags, i830xf86ModeHSync(mode));
+		   mode->VTotal, flags, xf86ModeHSync(mode));
     xfree(flags);
 }
+#endif /* XORG_VERSION_CURRENT <= 7.1.99.2 */
 
 /**
  * Marks as bad any modes with unsupported flags.
@@ -393,8 +395,8 @@ i830xf86ValidateModesSync(ScrnInfoPtr pS
 
 	bad = TRUE;
 	for (i = 0; i < mon->nHsync; i++) {
-	    if (i830xf86ModeHSync(mode) >= mon->hsync[i].lo &&
-		i830xf86ModeHSync(mode) <= mon->hsync[i].hi)
+	    if (xf86ModeHSync(mode) >= mon->hsync[i].lo &&
+		xf86ModeHSync(mode) <= mon->hsync[i].hi)
 	    {
 		bad = FALSE;
 	    }
@@ -404,8 +406,8 @@ i830xf86ValidateModesSync(ScrnInfoPtr pS
 
 	bad = TRUE;
 	for (i = 0; i < mon->nVrefresh; i++) {
-	    if (i830xf86ModeVRefresh(mode) >= mon->vrefresh[i].lo &&
-		i830xf86ModeVRefresh(mode) <= mon->vrefresh[i].hi)
+	    if (xf86ModeVRefresh(mode) >= mon->vrefresh[i].lo &&
+		xf86ModeVRefresh(mode) <= mon->vrefresh[i].hi)
 	    {
 		bad = FALSE;
 	    }
diff --git a/src/i830_xf86Modes.h b/src/i830_xf86Modes.h
index 262a45c..d057ef5 100644
--- a/src/i830_xf86Modes.h
+++ b/src/i830_xf86Modes.h
@@ -25,26 +25,27 @@
  *
  */
 
-double
-i830xf86ModeHSync(DisplayModePtr mode);
+#include "xorgVersion.h"
 
-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);
+#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
+#endif /* XORG_VERSION_CURRENT <= 7.1.99.2 */
 
 void
 i830xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,
@@ -72,6 +73,3 @@ i830xf86ValidateModesFlags(ScrnInfoPtr p
 
 void
 i830xf86ValidateModesUserConfig(ScrnInfoPtr pScrn, DisplayModePtr modeList);
-
-void
-PrintModeline(int scrnIndex,DisplayModePtr mode);
diff --git a/src/i830_xf86cvt.c b/src/i830_xf86cvt.c
index b0f9727..0014056 100644
--- a/src/i830_xf86cvt.c
+++ b/src/i830_xf86cvt.c
@@ -31,8 +31,16 @@
  * code is shared directly.
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include "xf86.h"
 
+#include "i830.h"
+#include "i830_display.h"
+
+#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,1,99,2,0)
 /*
  * Generate a CVT standard mode from HDisplay, VDisplay and VRefresh.
  *
@@ -58,8 +66,8 @@
  *
  */
 _X_EXPORT DisplayModePtr
-i830xf86CVTMode(int HDisplay, int VDisplay, float VRefresh, Bool Reduced,
-		Bool Interlaced)
+xf86CVTMode(int HDisplay, int VDisplay, float VRefresh, Bool Reduced,
+	    Bool Interlaced)
 {
     DisplayModeRec  *Mode = xnfalloc(sizeof(DisplayModeRec));
 
@@ -295,3 +303,4 @@ i830xf86CVTMode(int HDisplay, int VDispl
 
     return Mode;
 }
+#endif /* XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,1,99,2,0) */
diff-tree 8d9ba2405d1f1e58a0cfb570e83e9206af8525b5 (from dbb8135e10e943a4d4e65f95853eeccc764ccf24)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Nov 28 15:44:06 2006 -0800

    sparse cleanups (use NULL instead of 0 for pointers)

diff --git a/src/i810_dri.c b/src/i810_dri.c
index a8c10ff..3e32283 100644
--- a/src/i810_dri.c
+++ b/src/i810_dri.c
@@ -171,9 +171,9 @@ I810InitVisualConfigs(ScreenPtr pScreen)
    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
    I810Ptr pI810 = I810PTR(pScrn);
    int numConfigs = 0;
-   __GLXvisualConfig *pConfigs = 0;
-   I810ConfigPrivPtr pI810Configs = 0;
-   I810ConfigPrivPtr *pI810ConfigPtrs = 0;
+   __GLXvisualConfig *pConfigs = NULL;
+   I810ConfigPrivPtr pI810Configs = NULL;
+   I810ConfigPrivPtr *pI810ConfigPtrs = NULL;
    int accum, stencil, db, depth;
    int i;
 
@@ -385,7 +385,7 @@ I810DRIScreenInit(ScreenPtr pScreen)
 
    if (!(pI810DRI = (I810DRIPtr) xcalloc(sizeof(I810DRIRec), 1))) {
       DRIDestroyInfoRec(pI810->pDRIInfo);
-      pI810->pDRIInfo = 0;
+      pI810->pDRIInfo = NULL;
       return FALSE;
    }
    pDRIInfo->devPrivate = pI810DRI;
@@ -413,9 +413,9 @@ I810DRIScreenInit(ScreenPtr pScreen)
       xf86DrvMsg(pScreen->myNum, X_ERROR,
 		 "[dri] DRIScreenInit failed.  Disabling DRI.\n");
       xfree(pDRIInfo->devPrivate);
-      pDRIInfo->devPrivate = 0;
+      pDRIInfo->devPrivate = NULL;
       DRIDestroyInfoRec(pI810->pDRIInfo);
-      pI810->pDRIInfo = 0;
+      pI810->pDRIInfo = NULL;
       return FALSE;
    }
 
@@ -1070,10 +1070,10 @@ I810DRICloseScreen(ScreenPtr pScreen)
    if (pI810->pDRIInfo) {
       if (pI810->pDRIInfo->devPrivate) {
 	 xfree(pI810->pDRIInfo->devPrivate);
-	 pI810->pDRIInfo->devPrivate = 0;
+	 pI810->pDRIInfo->devPrivate = NULL;
       }
       DRIDestroyInfoRec(pI810->pDRIInfo);
-      pI810->pDRIInfo = 0;
+      pI810->pDRIInfo = NULL;
    }
    if (pI810->pVisualConfigs)
       xfree(pI810->pVisualConfigs);
@@ -1200,9 +1200,9 @@ I810DRIMoveBuffers(WindowPtr pParent, DD
    BoxPtr pbox = REGION_RECTS(prgnSrc);
    int nbox = REGION_NUM_RECTS(prgnSrc);
 
-   BoxPtr pboxNew1 = 0;
-   BoxPtr pboxNew2 = 0;
-   DDXPointPtr pptNew1 = 0;
+   BoxPtr pboxNew1 = NULL;
+   BoxPtr pboxNew2 = NULL;
+   DDXPointPtr pptNew1 = NULL;
    DDXPointPtr pptSrc = &ptOldOrg;
 
    int dx = pParent->drawable.x - ptOldOrg.x;
diff-tree dbb8135e10e943a4d4e65f95853eeccc764ccf24 (from e8fb40ab1063b18372be2b5996257eb69d3f15c4)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Nov 28 13:21:31 2006 -0800

    Remove printing of the XFree86 screen mode list, and some other detritus.

diff --git a/src/i830.h b/src/i830.h
index 96ac7a4..1534f61 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -652,8 +652,6 @@ extern void I830ReadAllRegisters(I830Ptr
 extern void I830ChangeFrontbuffer(ScrnInfoPtr pScrn,int buffer);
 extern Bool I830IsPrimary(ScrnInfoPtr pScrn);
 
-extern void I830PrintModes(ScrnInfoPtr pScrn);
-extern Bool I830CheckModeSupport(ScrnInfoPtr pScrn, int x, int y, int mode);
 extern Bool I830Rotate(ScrnInfoPtr pScrn, DisplayModePtr mode);
 extern Bool I830FixOffset(ScrnInfoPtr pScrn, I830MemRange *mem);
 extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg,
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 0ae1ee6..1e619e4 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1735,8 +1735,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 
    pI830->displayWidth = pScrn->displayWidth;
 
-   I830PrintModes(pScrn);
-
    /* Don't need MMIO access anymore. */
    if (pI830->swfSaved) {
       OUTREG(SWF0, pI830->saveSWF0);
diff --git a/src/i830_modes.c b/src/i830_modes.c
index a0428a0..9e952c8 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -55,96 +55,8 @@
 #include "i830_xf86Modes.h"
 #include <randrstr.h>
 
-/* Established timings from EDID standard */
-static struct
-{
-    int hsize;
-    int vsize;
-    int refresh;
-} est_timings[] = {
-    {1280, 1024, 75},
-    {1024, 768, 75},
-    {1024, 768, 70},
-    {1024, 768, 60},
-    {1024, 768, 87},
-    {832, 624, 75},
-    {800, 600, 75},
-    {800, 600, 72},
-    {800, 600, 60},
-    {800, 600, 56},
-    {640, 480, 75},
-    {640, 480, 72},
-    {640, 480, 67},
-    {640, 480, 60},
-    {720, 400, 88},
-    {720, 400, 70},
-};
-
 #define DEBUG_REPROBE 1
 
-void
-I830PrintModes(ScrnInfoPtr scrp)
-{
-    DisplayModePtr p;
-    float hsync, refresh = 0;
-    char *desc, *desc2, *prefix, *uprefix;
-
-    if (scrp == NULL)
-	return;
-
-    xf86DrvMsg(scrp->scrnIndex, scrp->virtualFrom, "Virtual size is %dx%d "
-	       "(pitch %d)\n", scrp->virtualX, scrp->virtualY,
-	       scrp->displayWidth);
-    
-    p = scrp->modes;
-    if (p == NULL)
-	return;
-
-    do {
-	desc = desc2 = "";
-	if (p->HSync > 0.0)
-	    hsync = p->HSync;
-	else if (p->HTotal > 0)
-	    hsync = (float)p->Clock / (float)p->HTotal;
-	else
-	    hsync = 0.0;
-	if (p->VTotal > 0)
-	    refresh = hsync * 1000.0 / p->VTotal;
-	if (p->Flags & V_INTERLACE) {
-	    refresh *= 2.0;
-	    desc = " (I)";
-	}
-	if (p->Flags & V_DBLSCAN) {
-	    refresh /= 2.0;
-	    desc = " (D)";
-	}
-	if (p->VScan > 1) {
-	    refresh /= p->VScan;
-	    desc2 = " (VScan)";
-	}
-	if (p->VRefresh > 0.0)
-	    refresh = p->VRefresh;
-	if (p->type & M_T_BUILTIN)
-	    prefix = "Built-in mode";
-	else if (p->type & M_T_DEFAULT)
-	    prefix = "Default mode";
-	else
-	    prefix = "Mode";
-	if (p->type & M_T_USERDEF)
-	    uprefix = "*";
-	else
-	    uprefix = " ";
-	if (p->name)
-	    xf86DrvMsg(scrp->scrnIndex, X_CONFIG,
-			   "%s%s \"%s\"\n", uprefix, prefix, p->name);
-	else
-	    xf86DrvMsg(scrp->scrnIndex, X_PROBED,
-			   "%s%s %dx%d (unnamed)\n",
-			   uprefix, prefix, p->HDisplay, p->VDisplay);
-	p = p->next;
-    } while (p != NULL && p != scrp->modes);
-}
-
 static DisplayModePtr
 i830GetModeListTail(DisplayModePtr pModeList)
 {
diff-tree e8fb40ab1063b18372be2b5996257eb69d3f15c4 (from 72692ba2e0254460c4f5a8cd476f5748383390ae)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Nov 28 11:17:21 2006 -0800

    Replace custom DDC mode list code with a copy of the X Server's.
    
    The X Server now has most of the mode helper functions we want, and we can
    start removing compilation of our copies when the server is new enough.

diff --git a/src/Makefile.am b/src/Makefile.am
index 0fce5e4..52def8b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -63,7 +63,6 @@ i810_drv_la_SOURCES = \
          i830_driver.c \
 	 i830_dvo.c \
          i830.h \
-         i830_gtf.c \
          i830_i2c.c \
          i830_io.c \
 	 i830_lvds.c \
diff --git a/src/i830.h b/src/i830.h
index 32a540e..96ac7a4 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -676,10 +676,6 @@ void i830_lvds_init(ScrnInfoPtr pScrn);
 Bool I830BindAGPMemory(ScrnInfoPtr pScrn);
 Bool I830UnbindAGPMemory(ScrnInfoPtr pScrn);
 
-/* i830_gtf.c */
-DisplayModePtr i830GetGTF(int h_pixels, int v_lines, float freq,
-			  int interlaced, int margins);
-
 /* i830_modes.c */
 int I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time);
 void i830_reprobe_output_modes(ScrnInfoPtr pScrn);
diff --git a/src/i830_display.h b/src/i830_display.h
index 361a3c6..322f635 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -38,3 +38,11 @@ void i830DescribeOutputConfiguration(Scr
 int i830GetLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output);
 void i830ReleaseLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output);
 Bool i830PipeInUse(ScrnInfoPtr pScrn, int pipe);
+
+/** @{
+ */
+DisplayModePtr i830xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC);
+DisplayModePtr i830xf86CVTMode(int HDisplay, int VDisplay, float VRefresh,
+			       Bool Reduced, Bool Interlaced);
+/** @} */
+
diff --git a/src/i830_edid_modes.c b/src/i830_edid_modes.c
new file mode 100644
index 0000000..05df60c
--- /dev/null
+++ b/src/i830_edid_modes.c
@@ -0,0 +1,249 @@
+/*
+ * Copyright 2006 Luc Verhaegen.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @file This is a copy of edid_modes.c from the X Server, for compatibility
+ * with old X Servers.
+ */
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include "xf86.h"
+#include "xf86DDC.h"
+#include <X11/Xatom.h>
+#include "property.h"
+#include "propertyst.h"
+#include "xf86DDC.h"
+
+/*
+ * TODO:
+ *  - for those with access to the VESA DMT standard; review please.
+ */
+#define MODEPREFIX(name) NULL, NULL, name, 0,M_T_DRIVER
+#define MODESUFFIX   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,FALSE,FALSE,0,NULL,0,0.0,0.0
+
+DisplayModeRec DDCEstablishedModes[17] = {
+    { MODEPREFIX("800x600"),    40000,  800,  840,  968, 1056, 0,  600,  601,  605,  628, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600 at 60Hz */
+    { MODEPREFIX("800x600"),    36000,  800,  824,  896, 1024, 0,  600,  601,  603,  625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600 at 56Hz */
+    { MODEPREFIX("640x480"),    31500,  640,  656,  720,  840, 0,  480,  481,  484,  500, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480 at 75Hz */
+    { MODEPREFIX("640x480"),    31500,  640,  664,  704,  832, 0,  480,  489,  491,  520, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480 at 72Hz */
+    { MODEPREFIX("640x480"),    30240,  640,  704,  768,  864, 0,  480,  483,  486,  525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480 at 67Hz */
+    { MODEPREFIX("640x480"),    25200,  640,  656,  752,  800, 0,  480,  490,  492,  525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480 at 60Hz */
+    { MODEPREFIX("720x400"),    35500,  720,  738,  846,  900, 0,  400,  421,  423,  449, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 720x400 at 88Hz */
+    { MODEPREFIX("720x400"),    28320,  720,  738,  846,  900, 0,  400,  412,  414,  449, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 720x400 at 70Hz */
+    { MODEPREFIX("1280x1024"), 135000, 1280, 1296, 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x1024 at 75Hz */
+    { MODEPREFIX("1024x768"),   78800, 1024, 1040, 1136, 1312, 0,  768,  769,  772,  800, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1024x768 at 75Hz */
+    { MODEPREFIX("1024x768"),   75000, 1024, 1048, 1184, 1328, 0,  768,  771,  777,  806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768 at 70Hz */
+    { MODEPREFIX("1024x768"),   65000, 1024, 1048, 1184, 1344, 0,  768,  771,  777,  806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768 at 60Hz */
+    { MODEPREFIX("1024x768"),   44900, 1024, 1032, 1208, 1264, 0,  768,  768,  776,  817, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* 1024x768 at 43Hz */
+    { MODEPREFIX("832x624"),    57284,  832,  864,  928, 1152, 0,  624,  625,  628,  667, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 832x624 at 75Hz */
+    { MODEPREFIX("800x600"),    49500,  800,  816,  896, 1056, 0,  600,  601,  604,  625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600 at 75Hz */
+    { MODEPREFIX("800x600"),    50000,  800,  856,  976, 1040, 0,  600,  637,  643,  666, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600 at 72Hz */
+    { MODEPREFIX("1152x864"),  108000, 1152, 1216, 1344, 1600, 0,  864,  865,  868,  900, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1152x864 at 75Hz */
+};
+
+static DisplayModePtr
+DDCModesFromEstablished(int scrnIndex, struct established_timings *timing)
+{
+    DisplayModePtr Modes = NULL, Mode = NULL;
+    CARD32 bits = (timing->t1) | (timing->t2 << 8) |
+        ((timing->t_manu & 0x80) << 9);
+    int i;
+
+    for (i = 0; i < 17; i++) {
+        if (bits & (0x01 << i)) {
+            Mode = xf86DuplicateMode(&DDCEstablishedModes[i]);
+            Modes = xf86ModesAdd(Modes, Mode);
+        }
+    }
+
+    return Modes;
+}
+
+/*
+ *
+ */
+static DisplayModePtr
+DDCModesFromStandardTiming(int scrnIndex, struct std_timings *timing)
+{
+    DisplayModePtr Modes = NULL, Mode = NULL;
+    int i;
+
+    for (i = 0; i < STD_TIMINGS; i++) {
+        if (timing[i].hsize && timing[i].vsize && timing[i].refresh) {
+            Mode =  i830xf86CVTMode(timing[i].hsize, timing[i].vsize,
+                                timing[i].refresh, FALSE, FALSE);
+	    Mode->type = M_T_DRIVER;
+            Modes = xf86ModesAdd(Modes, Mode);
+        }
+    }
+
+    return Modes;
+}
+
+/*
+ *
+ */
+static DisplayModePtr
+DDCModeFromDetailedTiming(int scrnIndex, struct detailed_timings *timing,
+			  int preferred)
+{
+    DisplayModePtr Mode;
+
+    /* We don't do stereo */
+    if (timing->stereo) {
+        xf86DrvMsg(scrnIndex, X_INFO,
+		   "%s: Ignoring: We don't handle stereo.\n", __func__);
+        return NULL;
+    }
+
+    /* We only do seperate sync currently */
+    if (timing->sync != 0x03) {
+         xf86DrvMsg(scrnIndex, X_INFO,
+		    "%s: %dx%d Warning: We only handle seperate"
+                    " sync.\n", __func__, timing->h_active, timing->v_active);
+    }
+
+    Mode = xnfalloc(sizeof(DisplayModeRec));
+    memset(Mode, 0, sizeof(DisplayModeRec));
+
+    Mode->type = M_T_DRIVER;
+    if (preferred)
+	Mode->type |= M_T_PREFERRED;
+
+    Mode->Clock = timing->clock / 1000.0;
+
+    Mode->HDisplay = timing->h_active;
+    Mode->HSyncStart = timing->h_active + timing->h_sync_off;
+    Mode->HSyncEnd = Mode->HSyncStart + timing->h_sync_width;
+    Mode->HTotal = timing->h_active + timing->h_blanking;
+
+    Mode->VDisplay = timing->v_active;
+    Mode->VSyncStart = timing->v_active + timing->v_sync_off;
+    Mode->VSyncEnd = Mode->VSyncStart + timing->v_sync_width;
+    Mode->VTotal = timing->v_active + timing->v_blanking;
+
+    xf86SetModeDefaultName(Mode);
+
+    /* We ignore h/v_size and h/v_border for now. */
+
+    if (timing->interlaced)
+        Mode->Flags |= V_INTERLACE;
+
+    if (timing->misc & 0x02)
+        Mode->Flags |= V_PHSYNC;
+    else
+        Mode->Flags |= V_NHSYNC;
+
+    if (timing->misc & 0x01)
+        Mode->Flags |= V_PVSYNC;
+    else
+        Mode->Flags |= V_NVSYNC;
+
+    return Mode;
+}
+
+/*
+ *
+ */
+static void
+DDCGuessRangesFromModes(int scrnIndex, MonPtr Monitor, DisplayModePtr Modes)
+{
+    DisplayModePtr Mode = Modes;
+
+    if (!Monitor || !Modes)
+        return;
+
+    /* set up the ranges for scanning through the modes */
+    Monitor->nHsync = 1;
+    Monitor->hsync[0].lo = 1024.0;
+    Monitor->hsync[0].hi = 0.0;
+
+    Monitor->nVrefresh = 1;
+    Monitor->vrefresh[0].lo = 1024.0;
+    Monitor->vrefresh[0].hi = 0.0;
+
+    while (Mode) {
+        if (!Mode->HSync)
+            Mode->HSync = ((float) Mode->Clock ) / ((float) Mode->HTotal);
+
+        if (!Mode->VRefresh)
+            Mode->VRefresh = (1000.0 * ((float) Mode->Clock)) / 
+                ((float) (Mode->HTotal * Mode->VTotal));
+
+        if (Mode->HSync < Monitor->hsync[0].lo)
+            Monitor->hsync[0].lo = Mode->HSync;
+
+        if (Mode->HSync > Monitor->hsync[0].hi)
+            Monitor->hsync[0].hi = Mode->HSync;
+
+        if (Mode->VRefresh < Monitor->vrefresh[0].lo)
+            Monitor->vrefresh[0].lo = Mode->VRefresh;
+
+        if (Mode->VRefresh > Monitor->vrefresh[0].hi)
+            Monitor->vrefresh[0].hi = Mode->VRefresh;
+
+        Mode = Mode->next;
+    }
+}
+
+DisplayModePtr
+i830xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC)
+{
+    int preferred, i;
+    DisplayModePtr Modes = NULL, Mode;
+
+    preferred = PREFERRED_TIMING_MODE(DDC->features.msc);
+
+    /* Add established timings */
+    Mode = DDCModesFromEstablished(scrnIndex, &DDC->timings1);
+    Modes = xf86ModesAdd(Modes, Mode);
+
+    /* Add standard timings */
+    Mode = DDCModesFromStandardTiming(scrnIndex, DDC->timings2);
+    Modes = xf86ModesAdd(Modes, Mode);
+
+    for (i = 0; i < DET_TIMINGS; i++) {
+	struct detailed_monitor_section *det_mon = &DDC->det_mon[i];
+
+        switch (det_mon->type) {
+        case DT:
+            Mode = DDCModeFromDetailedTiming(scrnIndex,
+                                             &det_mon->section.d_timings,
+					     preferred);
+	    preferred = 0;
+            Modes = xf86ModesAdd(Modes, Mode);
+            break;
+        case DS_STD_TIMINGS:
+            Mode = DDCModesFromStandardTiming(scrnIndex,
+					      det_mon->section.std_t);
+            Modes = xf86ModesAdd(Modes, Mode);
+            break;
+        default:
+            break;
+        }
+    }
+
+    return Modes;
+}
diff --git a/src/i830_gtf.c b/src/i830_gtf.c
deleted file mode 100644
index 523e167..0000000
--- a/src/i830_gtf.c
+++ /dev/null
@@ -1,353 +0,0 @@
-#define DEBUG_VERB 2
-/*
- * Copyright © 2002 David Dawes
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of the author(s) shall
- * not be used in advertising or otherwise to promote the sale, use or other
- * dealings in this Software without prior written authorization from
- * the author(s).
- *
- * Authors: David Dawes <dawes at xfree86.org>
- *
- * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/vbe/vbeModes.c,v 1.6 2002/11/02 01:38:25 dawes Exp $
- */
-/*
- * Modified by Alan Hourihane <alanh at tungstengraphics.com>
- * to support extended BIOS modes for the Intel chipsets
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdio.h>
-#include <string.h>
-
-#include "xf86.h"
-#include "vbe.h"
-#include "vbeModes.h"
-#include "i830.h"
-#include "i830_xf86Modes.h"
-
-#include <math.h>
-
-#define rint(x) floor(x)
-
-#define MARGIN_PERCENT    1.8   /* % of active vertical image                */
-#define CELL_GRAN         8.0   /* assumed character cell granularity        */
-#define MIN_PORCH         1     /* minimum front porch                       */
-#define V_SYNC_RQD        3     /* width of vsync in lines                   */
-#define H_SYNC_PERCENT    8.0   /* width of hsync as % of total line         */
-#define MIN_VSYNC_PLUS_BP 550.0 /* min time of vsync + back porch (microsec) */
-#define M                 600.0 /* blanking formula gradient                 */
-#define C                 40.0  /* blanking formula offset                   */
-#define K                 128.0 /* blanking formula scaling factor           */
-#define J                 20.0  /* blanking formula scaling factor           */
-
-/* C' and M' are part of the Blanking Duty Cycle computation */
-
-#define C_PRIME           (((C - J) * K/256.0) + J)
-#define M_PRIME           (K/256.0 * M)
-
-DisplayModePtr
-i830GetGTF(int h_pixels, int v_lines, float freq, int interlaced, int margins)
-{
-    float h_pixels_rnd;
-    float v_lines_rnd;
-    float v_field_rate_rqd;
-    float top_margin;
-    float bottom_margin;
-    float interlace;
-    float h_period_est;
-    float vsync_plus_bp;
-    float v_back_porch;
-    float total_v_lines;
-    float v_field_rate_est;
-    float h_period;
-    float v_field_rate;
-    float v_frame_rate;
-    float left_margin;
-    float right_margin;
-    float total_active_pixels;
-    float ideal_duty_cycle;
-    float h_blank;
-    float total_pixels;
-    float pixel_freq;
-    float h_freq;
-
-    float h_sync;
-    float h_front_porch;
-    float v_odd_front_porch_lines;
-    DisplayModePtr m;
-
-    m = xnfcalloc(sizeof(DisplayModeRec), 1);
-    
-    
-    /*  1. In order to give correct results, the number of horizontal
-     *  pixels requested is first processed to ensure that it is divisible
-     *  by the character size, by rounding it to the nearest character
-     *  cell boundary:
-     *
-     *  [H PIXELS RND] = ((ROUND([H PIXELS]/[CELL GRAN RND],0))*[CELLGRAN RND])
-     */
-    
-    h_pixels_rnd = rint((float) h_pixels / CELL_GRAN) * CELL_GRAN;
-    
-    
-    /*  2. If interlace is requested, the number of vertical lines assumed
-     *  by the calculation must be halved, as the computation calculates
-     *  the number of vertical lines per field. In either case, the
-     *  number of lines is rounded to the nearest integer.
-     *   
-     *  [V LINES RND] = IF([INT RQD?]="y", ROUND([V LINES]/2,0),
-     *                                     ROUND([V LINES],0))
-     */
-
-    v_lines_rnd = interlaced ?
-            rint((float) v_lines) / 2.0 :
-            rint((float) v_lines);
-    
-    /*  3. Find the frame rate required:
-     *
-     *  [V FIELD RATE RQD] = IF([INT RQD?]="y", [I/P FREQ RQD]*2,
-     *                                          [I/P FREQ RQD])
-     */
-
-    v_field_rate_rqd = interlaced ? (freq * 2.0) : (freq);
-
-    /*  4. Find number of lines in Top margin:
-     *
-     *  [TOP MARGIN (LINES)] = IF([MARGINS RQD?]="Y",
-     *          ROUND(([MARGIN%]/100*[V LINES RND]),0),
-     *          0)
-     */
-
-    top_margin = margins ? rint(MARGIN_PERCENT / 100.0 * v_lines_rnd) : (0.0);
-
-    /*  5. Find number of lines in Bottom margin:
-     *
-     *  [BOT MARGIN (LINES)] = IF([MARGINS RQD?]="Y",
-     *          ROUND(([MARGIN%]/100*[V LINES RND]),0),
-     *          0)
-     */
-
-    bottom_margin = margins ? rint(MARGIN_PERCENT/100.0 * v_lines_rnd) : (0.0);
-
-    /*  6. If interlace is required, then set variable [INTERLACE]=0.5:
-     *   
-     *  [INTERLACE]=(IF([INT RQD?]="y",0.5,0))
-     */
-
-    interlace = interlaced ? 0.5 : 0.0;
-
-    /*  7. Estimate the Horizontal period
-     *
-     *  [H PERIOD EST] = ((1/[V FIELD RATE RQD]) - [MIN VSYNC+BP]/1000000) /
-     *                    ([V LINES RND] + (2*[TOP MARGIN (LINES)]) +
-     *                     [MIN PORCH RND]+[INTERLACE]) * 1000000
-     */
-
-    h_period_est = (((1.0/v_field_rate_rqd) - (MIN_VSYNC_PLUS_BP/1000000.0))
-                    / (v_lines_rnd + (2*top_margin) + MIN_PORCH + interlace)
-                    * 1000000.0);
-
-    /*  8. Find the number of lines in V sync + back porch:
-     *
-     *  [V SYNC+BP] = ROUND(([MIN VSYNC+BP]/[H PERIOD EST]),0)
-     */
-
-    vsync_plus_bp = rint(MIN_VSYNC_PLUS_BP/h_period_est);
-
-    /*  9. Find the number of lines in V back porch alone:
-     *
-     *  [V BACK PORCH] = [V SYNC+BP] - [V SYNC RND]
-     *
-     *  XXX is "[V SYNC RND]" a typo? should be [V SYNC RQD]?
-     */
-    
-    v_back_porch = vsync_plus_bp - V_SYNC_RQD;
-    
-    /*  10. Find the total number of lines in Vertical field period:
-     *
-     *  [TOTAL V LINES] = [V LINES RND] + [TOP MARGIN (LINES)] +
-     *                    [BOT MARGIN (LINES)] + [V SYNC+BP] + [INTERLACE] +
-     *                    [MIN PORCH RND]
-     */
-
-    total_v_lines = v_lines_rnd + top_margin + bottom_margin + vsync_plus_bp +
-        interlace + MIN_PORCH;
-    
-    /*  11. Estimate the Vertical field frequency:
-     *
-     *  [V FIELD RATE EST] = 1 / [H PERIOD EST] / [TOTAL V LINES] * 1000000
-     */
-
-    v_field_rate_est = 1.0 / h_period_est / total_v_lines * 1000000.0;
-    
-    /*  12. Find the actual horizontal period:
-     *
-     *  [H PERIOD] = [H PERIOD EST] / ([V FIELD RATE RQD] / [V FIELD RATE EST])
-     */
-
-    h_period = h_period_est / (v_field_rate_rqd / v_field_rate_est);
-    
-    /*  13. Find the actual Vertical field frequency:
-     *
-     *  [V FIELD RATE] = 1 / [H PERIOD] / [TOTAL V LINES] * 1000000
-     */
-
-    v_field_rate = 1.0 / h_period / total_v_lines * 1000000.0;
-
-    /*  14. Find the Vertical frame frequency:
-     *
-     *  [V FRAME RATE] = (IF([INT RQD?]="y", [V FIELD RATE]/2, [V FIELD RATE]))
-     */
-
-    v_frame_rate = interlaced ? v_field_rate / 2.0 : v_field_rate;
-
-    /*  15. Find number of pixels in left margin:
-     *
-     *  [LEFT MARGIN (PIXELS)] = (IF( [MARGINS RQD?]="Y",
-     *          (ROUND( ([H PIXELS RND] * [MARGIN%] / 100 /
-     *                   [CELL GRAN RND]),0)) * [CELL GRAN RND],
-     *          0))
-     */
-
-    left_margin = margins ?
-        rint(h_pixels_rnd * MARGIN_PERCENT / 100.0 / CELL_GRAN) * CELL_GRAN :
-        0.0;
-    
-    /*  16. Find number of pixels in right margin:
-     *
-     *  [RIGHT MARGIN (PIXELS)] = (IF( [MARGINS RQD?]="Y",
-     *          (ROUND( ([H PIXELS RND] * [MARGIN%] / 100 /
-     *                   [CELL GRAN RND]),0)) * [CELL GRAN RND],
-     *          0))
-     */
-    
-    right_margin = margins ?
-        rint(h_pixels_rnd * MARGIN_PERCENT / 100.0 / CELL_GRAN) * CELL_GRAN :
-        0.0;
-    
-    /*  17. Find total number of active pixels in image and left and right
-     *  margins:
-     *
-     *  [TOTAL ACTIVE PIXELS] = [H PIXELS RND] + [LEFT MARGIN (PIXELS)] +
-     *                          [RIGHT MARGIN (PIXELS)]
-     */
-
-    total_active_pixels = h_pixels_rnd + left_margin + right_margin;
-    
-    /*  18. Find the ideal blanking duty cycle from the blanking duty cycle
-     *  equation:
-     *
-     *  [IDEAL DUTY CYCLE] = [C'] - ([M']*[H PERIOD]/1000)
-     */
-
-    ideal_duty_cycle = C_PRIME - (M_PRIME * h_period / 1000.0);
-    
-    /*  19. Find the number of pixels in the blanking time to the nearest
-     *  double character cell:
-     *
-     *  [H BLANK (PIXELS)] = (ROUND(([TOTAL ACTIVE PIXELS] *
-     *                               [IDEAL DUTY CYCLE] /
-     *                               (100-[IDEAL DUTY CYCLE]) /
-     *                               (2*[CELL GRAN RND])), 0))
-     *                       * (2*[CELL GRAN RND])
-     */
-
-    h_blank = rint(total_active_pixels *
-                   ideal_duty_cycle /
-                   (100.0 - ideal_duty_cycle) /
-                   (2.0 * CELL_GRAN)) * (2.0 * CELL_GRAN);
-    
-    /*  20. Find total number of pixels:
-     *
-     *  [TOTAL PIXELS] = [TOTAL ACTIVE PIXELS] + [H BLANK (PIXELS)]
-     */
-
-    total_pixels = total_active_pixels + h_blank;
-    
-    /*  21. Find pixel clock frequency:
-     *
-     *  [PIXEL FREQ] = [TOTAL PIXELS] / [H PERIOD]
-     */
-    
-    pixel_freq = total_pixels / h_period;
-    
-    /*  22. Find horizontal frequency:
-     *
-     *  [H FREQ] = 1000 / [H PERIOD]
-     */
-
-    h_freq = 1000.0 / h_period;
-    
-
-    /* Stage 1 computations are now complete; I should really pass
-       the results to another function and do the Stage 2
-       computations, but I only need a few more values so I'll just
-       append the computations here for now */
-
-    
-
-    /*  17. Find the number of pixels in the horizontal sync period:
-     *
-     *  [H SYNC (PIXELS)] =(ROUND(([H SYNC%] / 100 * [TOTAL PIXELS] /
-     *                             [CELL GRAN RND]),0))*[CELL GRAN RND]
-     */
-
-    h_sync = rint(H_SYNC_PERCENT/100.0 * total_pixels / CELL_GRAN) * CELL_GRAN;
-
-    /*  18. Find the number of pixels in the horizontal front porch period:
-     *
-     *  [H FRONT PORCH (PIXELS)] = ([H BLANK (PIXELS)]/2)-[H SYNC (PIXELS)]
-     */
-
-    h_front_porch = (h_blank / 2.0) - h_sync;
-
-    /*  36. Find the number of lines in the odd front porch period:
-     *
-     *  [V ODD FRONT PORCH(LINES)]=([MIN PORCH RND]+[INTERLACE])
-     */
-    
-    v_odd_front_porch_lines = MIN_PORCH + interlace;
-    
-    /* finally, pack the results in the DisplayMode struct */
-    
-    m->HDisplay  = (int) (h_pixels_rnd);
-    m->HSyncStart = (int) (h_pixels_rnd + h_front_porch);
-    m->HSyncEnd = (int) (h_pixels_rnd + h_front_porch + h_sync);
-    m->HTotal = (int) (total_pixels);
-
-    m->VDisplay  = (int) (v_lines_rnd);
-    m->VSyncStart = (int) (v_lines_rnd + v_odd_front_porch_lines);
-    m->VSyncEnd = (int) (int) (v_lines_rnd + v_odd_front_porch_lines + V_SYNC_RQD);
-    m->VTotal = (int) (total_v_lines);
-
-    m->Clock   = (int)(pixel_freq * 1000);
-    m->SynthClock   = m->Clock;
-    m->HSync = h_freq;
-    m->VRefresh = v_frame_rate /* freq */;
-
-    i830xf86SetModeDefaultName(m);
-
-    return (m);
-}
diff --git a/src/i830_modes.c b/src/i830_modes.c
index 7fdd40e..a0428a0 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -48,31 +48,13 @@
 #include <math.h>
 
 #include "xf86.h"
+#include "xf86DDC.h"
 #include "X11/Xatom.h"
 #include "i830.h"
 #include "i830_display.h"
 #include "i830_xf86Modes.h"
 #include <randrstr.h>
 
-#define rint(x) floor(x)
-
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
-#define MARGIN_PERCENT    1.8   /* % of active vertical image                */
-#define CELL_GRAN         8.0   /* assumed character cell granularity        */
-#define MIN_PORCH         1     /* minimum front porch                       */
-#define V_SYNC_RQD        3     /* width of vsync in lines                   */
-#define H_SYNC_PERCENT    8.0   /* width of hsync as % of total line         */
-#define MIN_VSYNC_PLUS_BP 550.0 /* min time of vsync + back porch (microsec) */
-#define M                 600.0 /* blanking formula gradient                 */
-#define C                 40.0  /* blanking formula offset                   */
-#define K                 128.0 /* blanking formula scaling factor           */
-#define J                 20.0  /* blanking formula scaling factor           */
-
-/* C' and M' are part of the Blanking Duty Cycle computation */
-
-#define C_PRIME           (((C - J) * K/256.0) + J)
-#define M_PRIME           (K/256.0 * M)
 /* Established timings from EDID standard */
 static struct
 {
@@ -163,214 +145,6 @@ I830PrintModes(ScrnInfoPtr scrp)
     } while (p != NULL && p != scrp->modes);
 }
 
-/* This function will sort all modes according to their resolution.
- * Highest resolution first.
- */
-static void
-I830xf86SortModes(DisplayModePtr new, DisplayModePtr *first,
-	      DisplayModePtr *last)
-{
-    DisplayModePtr  p;
-
-    p = *last;
-    while (p) {
-	if (((new->HDisplay < p->HDisplay) &&
-	     (new->VDisplay < p->VDisplay)) ||
-	    ((new->HDisplay * new->VDisplay) < (p->HDisplay * p->VDisplay)) ||
-	    ((new->HDisplay == p->HDisplay) &&
-	     (new->VDisplay == p->VDisplay) &&
-	     (new->Clock < p->Clock))) {
-
-	    if (p->next) 
-		p->next->prev = new;
-	    new->prev = p;
-	    new->next = p->next;
-	    p->next = new;
-	    if (!(new->next))
-		*last = new;
-	    break;
-	}
-	if (!p->prev) {
-	    new->prev = NULL;
-	    new->next = p;
-	    p->prev = new;
-	    *first = new;
-	    break;
-	}
-	p = p->prev;
-    }
-
-    if (!*first) {
-	*first = new;
-	new->prev = NULL;
-	new->next = NULL;
-	*last = new;
-    }
-}
-
-/**
- * Gets a new pointer to a VESA established mode.
- *
- * \param i index into the VESA established modes table.
- */
-static DisplayModePtr
-I830GetVESAEstablishedMode(ScrnInfoPtr pScrn, int i)
-{
-    DisplayModePtr pMode;
-
-    for (pMode = I830xf86DefaultModes; pMode->name != NULL; pMode++)
-    {
-	if (pMode->HDisplay == est_timings[i].hsize &&
-	    pMode->VDisplay == est_timings[i].vsize &&
-	    fabs(i830xf86ModeVRefresh(pMode) - est_timings[i].refresh) < 1.0)
-	{
-	    DisplayModePtr pNew = i830xf86DuplicateMode(pMode);
-	    i830xf86SetModeDefaultName(pNew);
-	    pNew->VRefresh = i830xf86ModeVRefresh(pMode);
-	    return pNew;
-	}
-    }
-    return NULL;
-}
-
-static DisplayModePtr
-i830GetDDCModes(ScrnInfoPtr pScrn, xf86MonPtr ddc)
-{
-    DisplayModePtr  last  = NULL;
-    DisplayModePtr  new   = NULL;
-    DisplayModePtr  first = NULL;
-    int             count = 0;
-    int             j, tmp;
-
-    if (ddc == NULL)
-	return NULL;
-
-    /* Go thru detailed timing table first */
-    for (j = 0; j < 4; j++) {
-	if (ddc->det_mon[j].type == 0) {
-	    struct detailed_timings *d_timings =
-		&ddc->det_mon[j].section.d_timings;
-
-	    if (d_timings->h_active == 0 || d_timings->v_active == 0) break;
-
-	    new = xnfcalloc(1, sizeof (DisplayModeRec));
-	    memset(new, 0, sizeof (DisplayModeRec));
-
-	    new->HDisplay   = d_timings->h_active;
-	    new->VDisplay   = d_timings->v_active;
-
-	    new->HTotal     = new->HDisplay + d_timings->h_blanking;
-	    new->HSyncStart = new->HDisplay + d_timings->h_sync_off;
-	    new->HSyncEnd   = new->HSyncStart + d_timings->h_sync_width;
-	    new->VTotal     = new->VDisplay + d_timings->v_blanking;
-	    new->VSyncStart = new->VDisplay + d_timings->v_sync_off;
-	    new->VSyncEnd   = new->VSyncStart + d_timings->v_sync_width;
-	    new->Clock      = d_timings->clock / 1000;
-	    new->Flags      = (d_timings->interlaced ? V_INTERLACE : 0);
-	    new->status     = MODE_OK;
-	    if (PREFERRED_TIMING_MODE(ddc->features.msc))
-		new->type   = M_T_PREFERRED;
-	    else
-		new->type   = M_T_DRIVER;
-
-	    i830xf86SetModeDefaultName(new);
-
-	    if (d_timings->sync == 3) {
-		switch (d_timings->misc) {
-		case 0: new->Flags |= V_NHSYNC | V_NVSYNC; break;
-		case 1: new->Flags |= V_PHSYNC | V_NVSYNC; break;
-		case 2: new->Flags |= V_NHSYNC | V_PVSYNC; break;
-		case 3: new->Flags |= V_PHSYNC | V_PVSYNC; break;
-		}
-	    }
-	    count++;
-
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		       "Valid Mode from Detailed timing table: %s (ht %d hss %d hse %d vt %d vss %d vse %d)\n",
-		       new->name,
-		       new->HTotal, new->HSyncStart, new->HSyncEnd,
-		       new->VTotal, new->VSyncStart, new->VSyncEnd);
-
-	    I830xf86SortModes(new, &first, &last);
-	}
-    }
-
-    /* Search thru standard VESA modes from EDID */
-    for (j = 0; j < 8; j++) {
-        if (ddc->timings2[j].hsize == 0 || ddc->timings2[j].vsize == 0)
-               continue;
-#if 1
-	new = i830GetGTF(ddc->timings2[j].hsize, ddc->timings2[j].vsize,
-			 ddc->timings2[j].refresh, FALSE, FALSE);
-	new->status = MODE_OK;
-	new->type |= M_T_DEFAULT;
-
-	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		   "Valid Mode from standard timing table: %s\n",
-		   new->name);
-
-	I830xf86SortModes(new, &first, &last);
-#else
-	for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) {
-
-	    /* Ignore all double scan modes */
-	    if ((ddc->timings2[j].hsize == p->HDisplay) &&
-		(ddc->timings2[j].vsize == p->VDisplay)) {
-		float  refresh =
-		    (float)p->Clock * 1000.0 / p->HTotal / p->VTotal;
-		float err = (float)ddc->timings2[j].refresh - refresh;
-
-		if (err < 0) err = -err;
-		if (err < 1.0) {
-		    /* Is this good enough? */
-		    new = xnfcalloc(1, sizeof (DisplayModeRec));
-		    memcpy(new, p, sizeof(DisplayModeRec));
-		    new->name = xnfalloc(strlen(p->name) + 1);
-		    strcpy(new->name, p->name);
-		    new->status = MODE_OK;
-		    new->type   = M_T_DEFAULT;
-
-		    count++;
-
-		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-			       "Valid Mode from standard timing table: %s\n",
-			       new->name);
-
-		    I830xf86SortModes(new, &first, &last);
-		    break;
-		}
-	    }
-	}
-#endif
-    }
-
-    /* Search thru established modes from EDID */
-    tmp = (ddc->timings1.t1 << 8) | ddc->timings1.t2;
-    for (j = 0; j < 16; j++) {
-	if (tmp & (1 << j)) {
-	    new = I830GetVESAEstablishedMode(pScrn, j);
-	    if (new == NULL) {
-		ErrorF("Couldn't get established mode %d\n", j);
-		continue;
-	    }
-	    new->status = MODE_OK;
-	    new->type = M_T_DEFAULT;
-
-	    count++;
-
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Valid Mode from established "
-		       "timing table: %s\n", new->name);
-
-	    I830xf86SortModes(new, &first, &last);
-	}
-    }
-
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-	       "Total of %d DDC mode(s) found.\n", count);
-
-    return first;
-}
-
 static DisplayModePtr
 i830GetModeListTail(DisplayModePtr pModeList)
 {
@@ -673,7 +447,7 @@ i830_ddc_get_modes(ScrnInfoPtr pScrn, I8
 	       i830_output_type_names[output->type]);
     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 --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c
index ca92e4d..24cc23b 100644
--- a/src/i830_xf86Modes.c
+++ b/src/i830_xf86Modes.c
@@ -45,7 +45,6 @@
  * there but we still want to use.  We need to come up with better API here.
  */
 
-
 /**
  * Calculates the horizontal sync rate of a mode.
  *
@@ -88,12 +87,7 @@ i830xf86ModeVRefresh(DisplayModePtr mode
     return refresh;
 }
 
-/**
- * Sets a default mode name of <width>x<height>x<refresh> on a mode.
- *
- * The refresh rate doesn't contain decimals, as that's expected to be
- * unimportant from the user's perspective for non-custom modelines.
- */
+/** Sets a default mode name of <width>x<height> on a mode. */
 void
 i830xf86SetModeDefaultName(DisplayModePtr mode)
 {
@@ -530,112 +524,3 @@ i830xf86PruneInvalidModes(ScrnInfoPtr pS
 	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).
- */
-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}
-};
diff --git a/src/i830_xf86Modes.h b/src/i830_xf86Modes.h
index 5a26c0e..262a45c 100644
--- a/src/i830_xf86Modes.h
+++ b/src/i830_xf86Modes.h
@@ -75,5 +75,3 @@ i830xf86ValidateModesUserConfig(ScrnInfo
 
 void
 PrintModeline(int scrnIndex,DisplayModePtr mode);
-
-extern DisplayModeRec I830xf86DefaultModes[];
diff --git a/src/i830_xf86cvt.c b/src/i830_xf86cvt.c
new file mode 100644
index 0000000..b0f9727
--- /dev/null
+++ b/src/i830_xf86cvt.c
@@ -0,0 +1,297 @@
+/*
+ * Copyright 2005-2006 Luc Verhaegen.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @file This is a copy of xf86cvt.c from the X Server, for compatibility with
+ * old servers (pre-1.2).
+ */
+
+/*
+ * The reason for having this function in a file of its own is
+ * so that ../utils/cvt/cvt can link to it, and that xf86CVTMode
+ * code is shared directly.
+ */
+
+#include "xf86.h"
+
+/*
+ * Generate a CVT standard mode from HDisplay, VDisplay and VRefresh.
+ *
+ * These calculations are stolen from the CVT calculation spreadsheet written
+ * by Graham Loveridge. He seems to be claiming no copyright and there seems to
+ * be no license attached to this. He apparently just wants to see his name
+ * mentioned.
+ *
+ * This file can be found at http://www.vesa.org/Public/CVT/CVTd6r1.xls
+ *
+ * Comments and structure corresponds to the comments and structure of the xls.
+ * This should ease importing of future changes to the standard (not very
+ * likely though).
+ *
+ * About margins; i'm sure that they are to be the bit between HDisplay and
+ * HBlankStart, HBlankEnd and HTotal, VDisplay and VBlankStart, VBlankEnd and 
+ * VTotal, where the overscan colour is shown. FB seems to call _all_ blanking
+ * outside sync "margin" for some reason. Since we prefer seeing proper
+ * blanking instead of the overscan colour, and since the Crtc* values will
+ * probably get altered after us, we will disable margins altogether. With
+ * these calculations, Margins will plainly expand H/VDisplay, and we don't
+ * want that. -- libv
+ *
+ */
+_X_EXPORT DisplayModePtr
+i830xf86CVTMode(int HDisplay, int VDisplay, float VRefresh, Bool Reduced,
+		Bool Interlaced)
+{
+    DisplayModeRec  *Mode = xnfalloc(sizeof(DisplayModeRec));
+
+    /* 1) top/bottom margin size (% of height) - default: 1.8 */
+#define CVT_MARGIN_PERCENTAGE 1.8    
+
+    /* 2) character cell horizontal granularity (pixels) - default 8 */
+#define CVT_H_GRANULARITY 8
+
+    /* 4) Minimum vertical porch (lines) - default 3 */
+#define CVT_MIN_V_PORCH 3
+
+    /* 4) Minimum number of vertical back porch lines - default 6 */
+#define CVT_MIN_V_BPORCH 6
+
+    /* Pixel Clock step (kHz) */
+#define CVT_CLOCK_STEP 250
+
+    Bool Margins = FALSE;
+    float  VFieldRate, HPeriod;
+    int  HDisplayRnd, HMargin;
+    int  VDisplayRnd, VMargin, VSync;
+    float  Interlace; /* Please rename this */
+
+    memset(Mode, 0, sizeof(DisplayModeRec));
+
+    /* CVT default is 60.0Hz */
+    if (!VRefresh)
+        VRefresh = 60.0;
+
+    /* 1. Required field rate */
+    if (Interlaced)
+        VFieldRate = VRefresh * 2;
+    else
+        VFieldRate = VRefresh;
+
+    /* 2. Horizontal pixels */
+    HDisplayRnd = HDisplay - (HDisplay % CVT_H_GRANULARITY);
+
+    /* 3. Determine left and right borders */
+    if (Margins) {
+        /* right margin is actually exactly the same as left */
+        HMargin = (((float) HDisplayRnd) * CVT_MARGIN_PERCENTAGE / 100.0);
+        HMargin -= HMargin % CVT_H_GRANULARITY;
+    } else
+        HMargin = 0;
+
+    /* 4. Find total active pixels */
+    Mode->HDisplay = HDisplayRnd + 2*HMargin;
+
+    /* 5. Find number of lines per field */
+    if (Interlaced)
+        VDisplayRnd = VDisplay / 2;
+    else
+        VDisplayRnd = VDisplay;
+
+    /* 6. Find top and bottom margins */
+    /* nope. */
+    if (Margins)
+        /* top and bottom margins are equal again. */
+        VMargin = (((float) VDisplayRnd) * CVT_MARGIN_PERCENTAGE / 100.0);
+    else
+        VMargin = 0;
+
+    Mode->VDisplay = VDisplay + 2*VMargin;
+
+    /* 7. Interlace */
+    if (Interlaced)
+        Interlace = 0.5;
+    else
+        Interlace = 0.0;
+
+    /* Determine VSync Width from aspect ratio */
+    if (!(VDisplay % 3) && ((VDisplay * 4 / 3) == HDisplay))
+        VSync = 4;
+    else if (!(VDisplay % 9) && ((VDisplay * 16 / 9) == HDisplay))
+        VSync = 5;
+    else if (!(VDisplay % 10) && ((VDisplay * 16 / 10) == HDisplay))
+        VSync = 6;
+    else if (!(VDisplay % 4) && ((VDisplay * 5 / 4) == HDisplay))
+        VSync = 7;
+    else if (!(VDisplay % 9) && ((VDisplay * 15 / 9) == HDisplay))
+        VSync = 7;
+    else /* Custom */
+        VSync = 10;
+
+    if (!Reduced) { /* simplified GTF calculation */
+
+        /* 4) Minimum time of vertical sync + back porch interval (µs) 
+         * default 550.0 */
+#define CVT_MIN_VSYNC_BP 550.0
+
+        /* 3) Nominal HSync width (% of line period) - default 8 */
+#define CVT_HSYNC_PERCENTAGE 8
+
+        float  HBlankPercentage;
+        int  VSyncAndBackPorch, VBackPorch;
+        int  HBlank;
+
+        /* 8. Estimated Horizontal period */
+        HPeriod = ((float) (1000000.0 / VFieldRate - CVT_MIN_VSYNC_BP)) / 
+            (VDisplayRnd + 2 * VMargin + CVT_MIN_V_PORCH + Interlace);
+
+        /* 9. Find number of lines in sync + backporch */
+        if (((int)(CVT_MIN_VSYNC_BP / HPeriod) + 1) < (VSync + CVT_MIN_V_PORCH))
+            VSyncAndBackPorch = VSync + CVT_MIN_V_PORCH;
+        else
+            VSyncAndBackPorch = (int)(CVT_MIN_VSYNC_BP / HPeriod) + 1;
+
+        /* 10. Find number of lines in back porch */
+        VBackPorch = VSyncAndBackPorch - VSync;
+
+        /* 11. Find total number of lines in vertical field */
+        Mode->VTotal = VDisplayRnd + 2 * VMargin + VSyncAndBackPorch + Interlace
+            + CVT_MIN_V_PORCH;
+
+        /* 5) Definition of Horizontal blanking time limitation */
+        /* Gradient (%/kHz) - default 600 */
+#define CVT_M_FACTOR 600
+
+        /* Offset (%) - default 40 */
+#define CVT_C_FACTOR 40
+
+        /* Blanking time scaling factor - default 128 */
+#define CVT_K_FACTOR 128
+
+        /* Scaling factor weighting - default 20 */
+#define CVT_J_FACTOR 20
+
+#define CVT_M_PRIME CVT_M_FACTOR * CVT_K_FACTOR / 256
+#define CVT_C_PRIME (CVT_C_FACTOR - CVT_J_FACTOR) * CVT_K_FACTOR / 256 + \
+        CVT_J_FACTOR
+
+        /* 12. Find ideal blanking duty cycle from formula */
+        HBlankPercentage = CVT_C_PRIME - CVT_M_PRIME * HPeriod/1000.0;
+
+        /* 13. Blanking time */
+        if (HBlankPercentage < 20)
+            HBlankPercentage = 20;
+
+        HBlank = Mode->HDisplay * HBlankPercentage/(100.0 - HBlankPercentage);
+        HBlank -= HBlank % (2*CVT_H_GRANULARITY);
+        
+        /* 14. Find total number of pixels in a line. */
+        Mode->HTotal = Mode->HDisplay + HBlank;
+
+        /* Fill in HSync values */
+        Mode->HSyncEnd = Mode->HDisplay + HBlank / 2;
+
+        Mode->HSyncStart = Mode->HSyncEnd - 
+            (Mode->HTotal * CVT_HSYNC_PERCENTAGE) / 100;
+        Mode->HSyncStart += CVT_H_GRANULARITY - 
+            Mode->HSyncStart % CVT_H_GRANULARITY;
+
+        /* Fill in VSync values */
+        Mode->VSyncStart = Mode->VDisplay + CVT_MIN_V_PORCH;
+        Mode->VSyncEnd = Mode->VSyncStart + VSync;
+
+    } else { /* Reduced blanking */
+        /* Minimum vertical blanking interval time (µs) - default 460 */
+#define CVT_RB_MIN_VBLANK 460.0
+
+        /* Fixed number of clocks for horizontal sync */
+#define CVT_RB_H_SYNC 32.0
+
+        /* Fixed number of clocks for horizontal blanking */
+#define CVT_RB_H_BLANK 160.0
+
+        /* Fixed number of lines for vertical front porch - default 3 */
+#define CVT_RB_VFPORCH 3
+
+        int  VBILines;
+
+        /* 8. Estimate Horizontal period. */
+        HPeriod = ((float) (1000000.0 / VFieldRate - CVT_RB_MIN_VBLANK)) / 
+            (VDisplayRnd + 2*VMargin);
+
+        /* 9. Find number of lines in vertical blanking */
+        VBILines = ((float) CVT_RB_MIN_VBLANK) / HPeriod + 1;
+
+        /* 10. Check if vertical blanking is sufficient */
+        if (VBILines < (CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH))
+            VBILines = CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH;
+        
+        /* 11. Find total number of lines in vertical field */
+        Mode->VTotal = VDisplayRnd + 2 * VMargin + Interlace + VBILines;
+
+        /* 12. Find total number of pixels in a line */
+        Mode->HTotal = Mode->HDisplay + CVT_RB_H_BLANK;
+
+        /* Fill in HSync values */
+        Mode->HSyncEnd = Mode->HDisplay + CVT_RB_H_BLANK / 2;
+        Mode->HSyncStart = Mode->HSyncEnd - CVT_RB_H_SYNC;
+
+        /* Fill in VSync values */
+        Mode->VSyncStart = Mode->VDisplay + CVT_RB_VFPORCH;
+        Mode->VSyncEnd = Mode->VSyncStart + VSync;
+    }
+
+    /* 15/13. Find pixel clock frequency (kHz for xf86) */
+    Mode->Clock = Mode->HTotal * 1000.0 / HPeriod;
+    Mode->Clock -= Mode->Clock % CVT_CLOCK_STEP;
+
+    /* 16/14. Find actual Horizontal Frequency (kHz) */
+    Mode->HSync = ((float) Mode->Clock) / ((float) Mode->HTotal);
+
+    /* 17/15. Find actual Field rate */
+    Mode->VRefresh = (1000.0 * ((float) Mode->Clock)) / 
+        ((float) (Mode->HTotal * Mode->VTotal));
+
+    /* 18/16. Find actual vertical frame frequency */
+    /* ignore - just set the mode flag for interlaced */
+    if (Interlaced)
+        Mode->VTotal *= 2;
+
+    {
+        char  Name[256];
+        Name[0] = 0;
+
+        snprintf(Name, 256, "%dx%d", HDisplay, VDisplay);
+
+        Mode->name = xnfalloc(strlen(Name) + 1);
+        memcpy(Mode->name, Name, strlen(Name) + 1);
+    }
+
+    if (Reduced)
+        Mode->Flags |= V_PHSYNC | V_NVSYNC;
+    else
+        Mode->Flags |= V_NHSYNC | V_PVSYNC;
+
+    if (Interlaced)
+        Mode->Flags |= V_INTERLACE;
+
+    return 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 72692ba2e0254460c4f5a8cd476f5748383390ae (from 5f38bc3e2a685da5c03efa8103a353f79c842aa7)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Nov 27 11:23:55 2006 -0800

    Postpone SDVO DDC bus creation until we've detected the SDVO device.
    
    This reduces log noise for those of us with no SDVO devices.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 71bccc7..ebf5868 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -1026,6 +1026,22 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
 	return;
     }
 
+    output->pI2CBus = i2cbus;
+    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);
+	    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
@@ -1055,24 +1071,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
 	xfree(dev_priv);
 	return;
     }
-
-    output->pI2CBus = i2cbus;
     output->pDDCBus = ddcbus;
-    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');
-	    xf86DestroyI2CBusRec(output->pDDCBus, FALSE, FALSE);
-	    xf86DestroyI2CDevRec(&dev_priv->d, FALSE);
-	    xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE);
-	    xfree(dev_priv);
-	    return;
-	}
-    }
 
     i830_sdvo_get_capabilities(output, &dev_priv->caps);
 
diff-tree 5f38bc3e2a685da5c03efa8103a353f79c842aa7 (from 85f404bc67d5ab54175c19e75aad406abfcf2133)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Nov 27 11:06:50 2006 -0800

    Reduce the severity of many informational log messages.

diff --git a/src/i830_debug.c b/src/i830_debug.c
index 185988e..d74d092 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -200,7 +200,7 @@ static void i830DumpIndexed (ScrnInfoPtr
 
     for (i = min; i <= max; i++) {
 	OUTREG8 (id, i);
-	xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "%18.18s%02x: 0x%02x\n",
+	xf86DrvMsg (pScrn->scrnIndex, X_INFO, "%18.18s%02x: 0x%02x\n",
 		    name, i, INREG8(val));
     }
 }
@@ -218,14 +218,14 @@ void i830DumpRegs (ScrnInfoPtr pScrn)
     int msr;
     int crt;
 
-    xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "DumpRegsBegin\n");
+    xf86DrvMsg (pScrn->scrnIndex, X_INFO, "DumpRegsBegin\n");
     for (i = 0; i < NUM_I830_SNAPSHOTREGS; i++) {
-	xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "%20.20s: 0x%08x\n",
+	xf86DrvMsg (pScrn->scrnIndex, X_INFO, "%20.20s: 0x%08x\n",
 		    i830_snapshot[i].name, (unsigned int) INREG(i830_snapshot[i].reg));
     }
     i830DumpIndexed (pScrn, "SR", 0x3c4, 0x3c5, 0, 7);
     msr = INREG8(0x3cc);
-    xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "%20.20s: 0x%02x\n",
+    xf86DrvMsg (pScrn->scrnIndex, X_INFO, "%20.20s: 0x%02x\n",
 		    "MSR", (unsigned int) msr);
 
     if (msr & 1)
@@ -285,7 +285,9 @@ void i830DumpRegs (ScrnInfoPtr pScrn)
 	case 6:
 	    break;
 	default:
-	    xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "phase %d out of range\n", phase);
+	    xf86DrvMsg (pScrn->scrnIndex, X_INFO,
+			"SDVO phase shift %d out of range -- probobly not "
+			"an issue.\n", phase);
 	    break;
 	}
 	switch ((dpll >> 8) & 1) {
@@ -300,8 +302,8 @@ void i830DumpRegs (ScrnInfoPtr pScrn)
 	m2 = ((fp >> 0) & 0x3f);
 	m = 5 * (m1 + 2) + (m2 + 2);
 	dot = (ref * (5 * (m1 + 2) + (m2 + 2)) / (n + 2)) / (p1 * p2);
-	xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "pipe %s dot %d n %d m1 %d m2 %d p1 %d p2 %d\n",
+	xf86DrvMsg (pScrn->scrnIndex, X_INFO, "pipe %s dot %d n %d m1 %d m2 %d p1 %d p2 %d\n",
 		    pipe == 0 ? "A" : "B", dot, n, m1, m2, p1, p2);
     }
-    xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "DumpRegsEnd\n");
+    xf86DrvMsg (pScrn->scrnIndex, X_INFO, "DumpRegsEnd\n");
 }
diff --git a/src/i830_randr.c b/src/i830_randr.c
index a530ffb..389805a 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -889,7 +889,7 @@ I830RandRCreateScreenResources12 (Screen
 	    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,
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index fedb8a6..71bccc7 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -87,13 +87,22 @@ static Bool i830_sdvo_read_byte(I830Outp
 
     if (!xf86I2CReadByte(&dev_priv->d, addr, ch)) {
 	xf86DrvMsg(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);
 	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,
+				      unsigned char *ch)
+{
+    struct i830_sdvo_priv *dev_priv = 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,
 				 int addr, unsigned char ch)
@@ -102,7 +111,7 @@ static Bool i830_sdvo_write_byte(I830Out
 
     if (!xf86I2CWriteByte(&dev_priv->d, addr, ch)) {
 	xf86DrvMsg(output->pI2CBus->scrnIndex, X_ERROR,
-		   "Unable to write to %s Slave %d.\n",
+		   "Unable to write to %s Slave %02x.\n",
 		   output->pI2CBus->BusName, dev_priv->d.SlaveAddr);
 	return FALSE;
     }
@@ -1053,7 +1062,10 @@ 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])) {
+	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');
 	    xf86DestroyI2CBusRec(output->pDDCBus, FALSE, FALSE);
 	    xf86DestroyI2CDevRec(&dev_priv->d, FALSE);
 	    xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE);
diff-tree 85f404bc67d5ab54175c19e75aad406abfcf2133 (from 9aca4e207440119f4280b78199a221f85d50c511)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Nov 20 09:32:26 2006 -0800

    Re-indent ch7xxx driver.

diff --git a/src/ch7xxx/ch7xxx.c b/src/ch7xxx/ch7xxx.c
index d11c355..df66d03 100644
--- a/src/ch7xxx/ch7xxx.c
+++ b/src/ch7xxx/ch7xxx.c
@@ -33,11 +33,14 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "miscstruct.h"
 #include "xf86i2c.h"
 
-
 #include "../i2c_vid.h"
 #include "ch7xxx.h"
 #include "ch7xxx_reg.h"
 
+/** @file
+ * driver for the Chrontel 7xxx DVI chip over DVO.
+ */
+
 static void ch7xxxSaveRegs(I2CDevPtr d);
 
 static CARD8 ch7xxxFreqRegs[][7] =
@@ -48,225 +51,229 @@ static CARD8 ch7xxxFreqRegs[][7] =
 
 static Bool ch7xxxReadByte(CH7xxxPtr ch7xxx, int addr, unsigned char *ch)
 {
-  if (!xf86I2CReadByte(&(ch7xxx->d), addr, ch)) {
-    xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "Unable to read from %s Slave %d.\n", ch7xxx->d.pI2CBus->BusName, ch7xxx->d.SlaveAddr);
-    return FALSE;
-  }
-  return TRUE;
+    if (!xf86I2CReadByte(&(ch7xxx->d), addr, ch)) {
+	xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex,
+		   X_ERROR, "Unable to read from %s Slave %d.\n",
+		   ch7xxx->d.pI2CBus->BusName, ch7xxx->d.SlaveAddr);
+	return FALSE;
+    }
+
+    return TRUE;
 }
 
 static Bool ch7xxxWriteByte(CH7xxxPtr ch7xxx, int addr, unsigned char ch)
 {
-  if (!xf86I2CWriteByte(&(ch7xxx->d), addr, ch)) {
-    xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "Unable to write to %s Slave %d.\n", ch7xxx->d.pI2CBus->BusName, ch7xxx->d.SlaveAddr);
-    return FALSE;
-  }
-  return TRUE;
+    if (!xf86I2CWriteByte(&(ch7xxx->d), addr, ch)) {
+	xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR,
+		   "Unable to write to %s Slave %d.\n",
+		   ch7xxx->d.pI2CBus->BusName, ch7xxx->d.SlaveAddr);
+	return FALSE;
+    }
+
+    return TRUE;
 }
 
-/* Ch7xxxicon Image 164 driver for chip on i2c bus */
 static void *ch7xxxDetect(I2CBusPtr b, I2CSlaveAddr addr)
 {
-  /* this will detect the CH7xxx chip on the specified i2c bus */
-  CH7xxxPtr ch7xxx;
-  unsigned char ch;
-
-  xf86DrvMsg(b->scrnIndex, X_ERROR, "detecting ch7xxx\n");
-  
-  ch7xxx = xcalloc(1, sizeof(CH7xxxRec));
-  if (ch7xxx == NULL)
-    return NULL;
+    /* this will detect the CH7xxx chip on the specified i2c bus */
+    CH7xxxPtr ch7xxx;
+    unsigned char ch;
+
+    xf86DrvMsg(b->scrnIndex, X_ERROR, "detecting ch7xxx\n");
+
+    ch7xxx = xcalloc(1, sizeof(CH7xxxRec));
+    if (ch7xxx == NULL)
+	return NULL;
+
+    ch7xxx->d.DevName = "CH7xxx TMDS Controller";
+    ch7xxx->d.SlaveAddr = addr;
+    ch7xxx->d.pI2CBus = b;
+    ch7xxx->d.StartTimeout = b->StartTimeout;
+    ch7xxx->d.BitTimeout = b->BitTimeout;
+    ch7xxx->d.AcknTimeout = b->AcknTimeout;
+    ch7xxx->d.ByteTimeout = b->ByteTimeout;
+    ch7xxx->d.DriverPrivate.ptr = ch7xxx;
+
+    if (!ch7xxxReadByte(ch7xxx, CH7xxx_REG_VID, &ch))
+	goto out;
+
+    ErrorF("VID is %02X", ch);
+    if (ch!=(CH7xxx_VID & 0xFF)) {
+	xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR,
+		   "ch7xxx not detected got %d: from %s Slave %d.\n",
+		   ch, ch7xxx->d.pI2CBus->BusName, ch7xxx->d.SlaveAddr);
+	goto out;
+    }
+
+
+    if (!ch7xxxReadByte(ch7xxx, CH7xxx_REG_DID, &ch))
+	goto out;
+
+    ErrorF("DID is %02X", ch);
+    if (ch!=(CH7xxx_DID & 0xFF)) {
+	xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR,
+		   "ch7xxx not detected got %d: from %s Slave %d.\n",
+		   ch, ch7xxx->d.pI2CBus->BusName, ch7xxx->d.SlaveAddr);
+	goto out;
+    }
+
+
+    if (!xf86I2CDevInit(&(ch7xxx->d))) {
+	goto out;
+    }
+
+    return ch7xxx;
 
-  ch7xxx->d.DevName = "CH7xxx TMDS Controller";
-  ch7xxx->d.SlaveAddr = addr;
-  ch7xxx->d.pI2CBus = b;
-  ch7xxx->d.StartTimeout = b->StartTimeout;
-  ch7xxx->d.BitTimeout = b->BitTimeout;
-  ch7xxx->d.AcknTimeout = b->AcknTimeout;
-  ch7xxx->d.ByteTimeout = b->ByteTimeout;
-  ch7xxx->d.DriverPrivate.ptr = ch7xxx;
-
-  if (!ch7xxxReadByte(ch7xxx, CH7xxx_REG_VID, &ch))
-    goto out;
-
-  ErrorF("VID is %02X", ch);
-  if (ch!=(CH7xxx_VID & 0xFF))
-  {
-    xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "ch7xxx not detected got %d: from %s Slave %d.\n", ch, ch7xxx->d.pI2CBus->BusName, ch7xxx->d.SlaveAddr);
-    goto out;
-  }
-
-
-  if (!ch7xxxReadByte(ch7xxx, CH7xxx_REG_DID, &ch))
-    goto out;
-
-  ErrorF("DID is %02X", ch);
-  if (ch!=(CH7xxx_DID & 0xFF))
-  {
-    xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "ch7xxx not detected got %d: from %s Slave %d.\n", ch, ch7xxx->d.pI2CBus->BusName, ch7xxx->d.SlaveAddr);
-    goto out;
-  }
-
-
-  if (!xf86I2CDevInit(&(ch7xxx->d)))
-  {
-    goto out;
-  }
-
-  return ch7xxx;
-  
- out:
-  xfree(ch7xxx);
-  return NULL;
+out:
+    xfree(ch7xxx);
+    return NULL;
 }
 
 
 static Bool ch7xxxInit(I2CDevPtr d)
 {
-  CH7xxxPtr ch7xxx = CH7PTR(d);
+    CH7xxxPtr ch7xxx = CH7PTR(d);
 
-  /* not much to do */
-  return TRUE;
+    /* not much to do */
+    return TRUE;
 }
 
 static ModeStatus ch7xxxModeValid(I2CDevPtr d, DisplayModePtr mode)
 {
-  CH7xxxPtr ch7xxx = CH7PTR(d);
-  
-  return MODE_OK;
+    CH7xxxPtr ch7xxx = CH7PTR(d);
+
+    return MODE_OK;
 }
 
 static void ch7xxxMode(I2CDevPtr d, DisplayModePtr mode)
 {
-  CH7xxxPtr ch7xxx = CH7PTR(d);
-  int ret;
-  unsigned char pm, idf;
-  unsigned char tpcp, tpd, tpf, cm;
-  CARD8 *freq_regs;
-  int i;
-  ErrorF("Clock is %d\n", mode->Clock);
-
-  if (mode->Clock < 75000)
-    freq_regs = ch7xxxFreqRegs[0];
-  else if (mode->Clock < 125000)
-    freq_regs = ch7xxxFreqRegs[1];
-  else
-    freq_regs = ch7xxxFreqRegs[2];
-
-  for (i = 0x31; i < 0x37; i++) {
-    ch7xxx->ModeReg.regs[i] = freq_regs[i - 0x31];
-    ch7xxxWriteByte(ch7xxx, i, ch7xxx->ModeReg.regs[i]);
-  }
-    
-#if 0
-
-  xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "ch7xxx idf is 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", idf, tpcp, tpd, tpf);
-
-  xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "ch7xxx pm is %02X\n", pm);
-
-  if (mode->Clock < 65000) {
-    tpcp = 0x08;
-    tpd = 0x16;
-    tpf = 0x60;
-  } else {
-    tpcp = 0x06;
-    tpd = 0x26;
-    tpf = 0xa0;
-  }
-
-  idf &= ~(CH7xxx_IDF_HSP | CH7xxx_IDF_VSP);
-  if (mode->Flags & V_PHSYNC)
-    idf |= CH7xxx_IDF_HSP;
-
-  if (mode->Flags & V_PVSYNC)
-    idf |= CH7xxx_IDF_HSP;
-  
-  /* setup PM Registers */
-  pm &= ~CH7xxx_PM_FPD;
-  pm |= CH7xxx_PM_DVIL | CH7xxx_PM_DVIP;
-
-  //  cm |= 1;
-
-  ch7xxxWriteByte(ch7xxx, CH7xxx_CM, cm);
-  ch7xxxWriteByte(ch7xxx, CH7xxx_TPCP, tpcp);
-  ch7xxxWriteByte(ch7xxx, CH7xxx_TPD, tpd);
-  ch7xxxWriteByte(ch7xxx, CH7xxx_TPF, tpf);
-  ch7xxxWriteByte(ch7xxx, CH7xxx_TPF, idf);
-  ch7xxxWriteByte(ch7xxx, CH7xxx_PM, pm);
+    CH7xxxPtr ch7xxx = CH7PTR(d);
+    int ret;
+    unsigned char pm, idf;
+    unsigned char tpcp, tpd, tpf, cm;
+    CARD8 *freq_regs;
+    int i;
+
+    ErrorF("Clock is %d\n", mode->Clock);
+
+    if (mode->Clock < 75000)
+	freq_regs = ch7xxxFreqRegs[0];
+    else if (mode->Clock < 125000)
+	freq_regs = ch7xxxFreqRegs[1];
+    else
+	freq_regs = ch7xxxFreqRegs[2];
+
+    for (i = 0x31; i < 0x37; i++) {
+	ch7xxx->ModeReg.regs[i] = freq_regs[i - 0x31];
+	ch7xxxWriteByte(ch7xxx, i, ch7xxx->ModeReg.regs[i]);
+    }
 
+#if 0
+    xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR,
+	       "ch7xxx idf is 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
+	       idf, tpcp, tpd, tpf);
+
+    xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR,
+	       "ch7xxx pm is %02X\n", pm);
+
+    if (mode->Clock < 65000) {
+	tpcp = 0x08;
+	tpd = 0x16;
+	tpf = 0x60;
+    } else {
+	tpcp = 0x06;
+	tpd = 0x26;
+	tpf = 0xa0;
+    }
+
+    idf &= ~(CH7xxx_IDF_HSP | CH7xxx_IDF_VSP);
+    if (mode->Flags & V_PHSYNC)
+	idf |= CH7xxx_IDF_HSP;
+
+    if (mode->Flags & V_PVSYNC)
+	idf |= CH7xxx_IDF_HSP;
+
+    /* setup PM Registers */
+    pm &= ~CH7xxx_PM_FPD;
+    pm |= CH7xxx_PM_DVIL | CH7xxx_PM_DVIP;
+
+    /* cm |= 1; */
+
+    ch7xxxWriteByte(ch7xxx, CH7xxx_CM, cm);
+    ch7xxxWriteByte(ch7xxx, CH7xxx_TPCP, tpcp);
+    ch7xxxWriteByte(ch7xxx, CH7xxx_TPD, tpd);
+    ch7xxxWriteByte(ch7xxx, CH7xxx_TPF, tpf);
+    ch7xxxWriteByte(ch7xxx, CH7xxx_TPF, idf);
+    ch7xxxWriteByte(ch7xxx, CH7xxx_PM, pm);
 #endif
-  /* don't do much */
-  return;
 }
 
 /* set the CH7xxx power state */
 static void ch7xxxPower(I2CDevPtr d, Bool On)
 {
-  CH7xxxPtr ch7xxx = CH7PTR(d);
-  int ret;
-  unsigned char ch;
+    CH7xxxPtr ch7xxx = CH7PTR(d);
+    int ret;
+    unsigned char ch;
 
+    ret = ch7xxxReadByte(ch7xxx, CH7xxx_PM, &ch);
+    if (ret == FALSE)
+	return;
 
-  ret = ch7xxxReadByte(ch7xxx, CH7xxx_PM, &ch);
-  if (ret == FALSE)
-    return;
-  
-  xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "ch7xxx pm is %02X\n", ch);
-  
-#if 0  
-  ret = ch7xxxReadByte(ch7xxx, CH7xxx_REG8, &ch);
-  if (ret)
-    return;
+    xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR,
+	       "ch7xxx pm is %02X\n", ch);
 
-  if (On)
-    ch |= CH7xxx_8_PD;
-  else
-    ch &= ~CH7xxx_8_PD;
+#if 0
+    ret = ch7xxxReadByte(ch7xxx, CH7xxx_REG8, &ch);
+    if (ret)
+	return;
+
+    if (On)
+	ch |= CH7xxx_8_PD;
+    else
+	ch &= ~CH7xxx_8_PD;
 
-  ch7xxxWriteByte(ch7xxx, CH7xxx_REG8, ch);
+    ch7xxxWriteByte(ch7xxx, CH7xxx_REG8, ch);
 #endif
-  return;
 }
 
 static void ch7xxxPrintRegs(I2CDevPtr d)
 {
-  CH7xxxPtr ch7xxx = CH7PTR(d);
-  int i;
-
-  ch7xxxSaveRegs(d);
+    CH7xxxPtr ch7xxx = CH7PTR(d);
+    int i;
 
-  for (i = 0; i < CH7xxx_NUM_REGS; i++) {
-    if (( i % 8 ) == 0 )
-      ErrorF("\n %02X: ", i);
-    ErrorF("%02X ", ch7xxx->ModeReg.regs[i]);
+    ch7xxxSaveRegs(d);
 
-  }
+    for (i = 0; i < CH7xxx_NUM_REGS; i++) {
+	if (( i % 8 ) == 0 )
+	    ErrorF("\n %02X: ", i);
+	ErrorF("%02X ", ch7xxx->ModeReg.regs[i]);
+    }
 }
 
 static void ch7xxxSaveRegs(I2CDevPtr d)
 {
-  CH7xxxPtr ch7xxx = CH7PTR(d);
-  int ret;
-  int i;
+    CH7xxxPtr ch7xxx = CH7PTR(d);
+    int ret;
+    int i;
+
+    for (i = 0; i < CH7xxx_NUM_REGS; i++) {
+	ret = ch7xxxReadByte(ch7xxx, i, &ch7xxx->SavedReg.regs[i]);
+	if (ret == FALSE)
+	    break;
+    }
 
-  for (i = 0; i < CH7xxx_NUM_REGS; i++) {
-    ret = ch7xxxReadByte(ch7xxx, i, &ch7xxx->SavedReg.regs[i]);
-    if (ret == FALSE)
-      break;
-  }
+    memcpy(ch7xxx->ModeReg.regs, ch7xxx->SavedReg.regs, CH7xxx_NUM_REGS);
 
-  memcpy(ch7xxx->ModeReg.regs, ch7xxx->SavedReg.regs, CH7xxx_NUM_REGS);
-
-  return;
+    return;
 }
 
 I830I2CVidOutputRec CH7xxxVidOutput = {
-  ch7xxxDetect,
-  ch7xxxInit,
-  ch7xxxModeValid,
-  ch7xxxMode,
-  ch7xxxPower,
-  ch7xxxPrintRegs,
-  ch7xxxSaveRegs,
-  NULL,
+    ch7xxxDetect,
+    ch7xxxInit,
+    ch7xxxModeValid,
+    ch7xxxMode,
+    ch7xxxPower,
+    ch7xxxPrintRegs,
+    ch7xxxSaveRegs,
+    NULL,
 };
diff --git a/src/ch7xxx/ch7xxx_module.c b/src/ch7xxx/ch7xxx_module.c
index 19dc6cd..2613d9e 100644
--- a/src/ch7xxx/ch7xxx_module.c
+++ b/src/ch7xxx/ch7xxx_module.c
@@ -10,8 +10,7 @@
 
 static MODULESETUPPROTO(ch7xxxSetup);
 
-static XF86ModuleVersionInfo ch7xxxVersRec = 
-  {
+static XF86ModuleVersionInfo ch7xxxVersRec =  {
     "ch7xxx",
     MODULEVENDORSTRING,
     MODINFOSTRING1,
@@ -22,15 +21,15 @@ static XF86ModuleVersionInfo ch7xxxVersR
     ABI_VIDEODRV_VERSION,
     MOD_CLASS_NONE,
     { 0,0,0,0 }
-  };
+};
 
 _X_EXPORT XF86ModuleData ch7xxxModuleData = {
-  &ch7xxxVersRec,
-  ch7xxxSetup,
-  NULL
+    &ch7xxxVersRec,
+    ch7xxxSetup,
+    NULL
 };
 
 static pointer
 ch7xxxSetup(pointer module, pointer opts, int *errmaj, int *errmin) {
-  return (pointer)1;
+    return (pointer)1;
 }
diff --git a/src/ch7xxx/ch7xxx_reg.h b/src/ch7xxx/ch7xxx_reg.h
index 59de13b..e24e9a6 100644
--- a/src/ch7xxx/ch7xxx_reg.h
+++ b/src/ch7xxx/ch7xxx_reg.h
@@ -29,7 +29,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define CH7xxx_REG_VID 0x4a
 #define CH7xxx_REG_DID 0x4b
 
-
 #define CH7011_VID 0x83
 #define CH7009A_VID 0x84
 #define CH7009B_VID 0x85
@@ -41,13 +40,13 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define CH7xxx_NUM_REGS 0x4c
 
 typedef struct _CH7xxxSaveRec {
-  CARD8 regs[CH7xxx_NUM_REGS];
+    CARD8 regs[CH7xxx_NUM_REGS];
 } CH7xxxSaveRec;
 
 typedef struct {
-  I2CDevRec d;
-  CH7xxxSaveRec SavedReg;
-  CH7xxxSaveRec ModeReg;
+    I2CDevRec d;
+    CH7xxxSaveRec SavedReg;
+    CH7xxxSaveRec ModeReg;
 } CH7xxxRec, *CH7xxxPtr;
 
 #define CH7PTR(d) ((CH7xxxPtr)(d->DriverPrivate.ptr))
@@ -86,6 +85,4 @@ typedef struct {
 #define CH7301_SYNC_RGB_YUV (1<<0)
 #define CH7301_SYNC_POL_DVI (1<<5)
 
-
-
 #endif
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_ */
diff-tree 9aca4e207440119f4280b78199a221f85d50c511 (from 850e3652f4d5bb57f3c4ccb9cf29e2c75fecba9d)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Wed Nov 22 15:52:32 2006 -0800

    Remove custom configuration code (which was #ifdef'd out).
    
    Multi-screen configuration is moving to generic code.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index aaac83e..0ae1ee6 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1240,153 +1240,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 
    I830PreInitDDC(pScrn);
 
-#if 0
-   /*
-    * This moves to generic RandR-based configuration code
-    */
-   if ((s = xf86GetOptValString(pI830->Options, OPTION_MONITOR_LAYOUT)) &&
-      I830IsPrimary(pScrn)) {
-      char *Mon1;
-      char *Mon2;
-      char *sub;
-        
-      Mon1 = strtok(s, ",");
-      Mon2 = strtok(NULL, ",");
-
-      if (Mon1) {
-         sub = strtok(Mon1, "+");
-         do {
-            if (strcmp(sub, "NONE") == 0)
-               pI830->MonType1 |= PIPE_NONE;
-            else if (strcmp(sub, "CRT") == 0)
-               pI830->MonType1 |= PIPE_CRT;
-            else if (strcmp(sub, "TV") == 0)
-               pI830->MonType1 |= PIPE_TV;
-            else if (strcmp(sub, "DFP") == 0)
-               pI830->MonType1 |= PIPE_DFP;
-            else if (strcmp(sub, "LFP") == 0)
-               pI830->MonType1 |= PIPE_LFP;
-            else if (strcmp(sub, "Second") == 0)
-               pI830->MonType1 |= PIPE_CRT2;
-            else if (strcmp(sub, "TV2") == 0)
-               pI830->MonType1 |= PIPE_TV2;
-            else if (strcmp(sub, "DFP2") == 0)
-               pI830->MonType1 |= PIPE_DFP2;
-            else if (strcmp(sub, "LFP2") == 0)
-               pI830->MonType1 |= PIPE_LFP2;
-            else 
-               xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 
-			       "Invalid Monitor type specified for Pipe A\n"); 
-
-            sub = strtok(NULL, "+");
-         } while (sub);
-      }
-
-      if (Mon2) {
-         sub = strtok(Mon2, "+");
-         do {
-            if (strcmp(sub, "NONE") == 0)
-               pI830->MonType2 |= PIPE_NONE;
-            else if (strcmp(sub, "CRT") == 0)
-               pI830->MonType2 |= PIPE_CRT;
-            else if (strcmp(sub, "TV") == 0)
-               pI830->MonType2 |= PIPE_TV;
-            else if (strcmp(sub, "DFP") == 0)
-               pI830->MonType2 |= PIPE_DFP;
-            else if (strcmp(sub, "LFP") == 0)
-               pI830->MonType2 |= PIPE_LFP;
-            else if (strcmp(sub, "Second") == 0)
-               pI830->MonType2 |= PIPE_CRT2;
-            else if (strcmp(sub, "TV2") == 0)
-               pI830->MonType2 |= PIPE_TV2;
-            else if (strcmp(sub, "DFP2") == 0)
-               pI830->MonType2 |= PIPE_DFP2;
-            else if (strcmp(sub, "LFP2") == 0)
-               pI830->MonType2 |= PIPE_LFP2;
-            else 
-               xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 
-			       "Invalid Monitor type specified for Pipe B\n"); 
-
-               sub = strtok(NULL, "+");
-            } while (sub);
-         }
-    
-         if (pI830->num_pipes == 1 && pI830->MonType2 != PIPE_NONE) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		    "Monitor 2 cannot be specified on single pipe devices\n");
-            return FALSE;
-         }
-
-         if (pI830->MonType1 == PIPE_NONE && pI830->MonType2 == PIPE_NONE) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		    "Monitor 1 and 2 cannot be type NONE\n");
-            return FALSE;
-      }
-
-      if (pI830->MonType1 != PIPE_NONE)
-	 pI830->pipe = 0;
-      else
-	 pI830->pipe = 1;
-
-   } else if (I830IsPrimary(pScrn)) {
-      /* Choose a default set of outputs to use based on what we've detected.
-       *
-       * Assume that SDVO outputs are flat panels for now.  It's just a name
-       * at the moment, since we don't treat different SDVO outputs
-       * differently.
-       */
-      for (i = 0; i < pI830->num_outputs; i++) {
-	 if (pI830->output[i].type == I830_OUTPUT_LVDS)
-	    pI830->MonType2 = PIPE_LFP;
-
-	 if (pI830->output[i].type == I830_OUTPUT_SDVO ||
-	     pI830->output[i].type == I830_OUTPUT_ANALOG)
-	 {
-	    int pipetype;
-
-	    if (pI830->output[i].detect(pScrn, &pI830->output[i]) ==
-		OUTPUT_STATUS_DISCONNECTED)
-	    {
-	       continue;
-	    }
-
-	    if (pI830->output[i].type == I830_OUTPUT_SDVO)
-	       pipetype = PIPE_DFP;
-	    else
-	       pipetype = PIPE_CRT;
-
-	    if (pI830->MonType1 == PIPE_NONE)
-	       pI830->MonType1 |= pipetype;
-	    else if (pI830->MonType2 == PIPE_NONE)
-	       pI830->MonType2 |= pipetype;
-	 }
-      }
-
-      /* And, if we haven't found anything (including CRT through DDC), assume
-       * that there's a CRT and that the user has set up some appropriate modes
-       * or something.
-       */
-      if (pI830->MonType1 == PIPE_NONE && pI830->MonType2 == PIPE_NONE)
-	 pI830->MonType1 |= PIPE_CRT;
-
-      if (pI830->MonType1 != PIPE_NONE)
-	 pI830->pipe = 0;
-      else
-	 pI830->pipe = 1;
-
-      if (pI830->MonType1 != 0 && pI830->MonType2 != 0) {
-         xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
- 		    "Enabling clone mode by default\n");
-	 pI830->Clone = TRUE;
-      }
-   } else {
-      I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
-      pI830->pipe = !pI8301->pipe;
-      pI830->MonType1 = pI8301->MonType1;
-      pI830->MonType2 = pI8301->MonType2;
-   }
-#endif
-
    if (xf86ReturnOptValBool(pI830->Options, OPTION_CLONE, FALSE)) {
       if (pI830->num_pipes == 1) {
          xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 
@@ -1447,31 +1300,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       pI830->pipes[i].enabled = i830PipeInUse(pScrn, i);
    }
 
-#if 0
-   pI830->CloneRefresh = 60; /* default to 60Hz */
-   if (xf86GetOptValInteger(pI830->Options, OPTION_CLONE_REFRESH,
-			    &(pI830->CloneRefresh))) {
-      xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Clone Monitor Refresh Rate %d\n",
-		 pI830->CloneRefresh);
-   }
-
-   /* See above i830refreshes on why 120Hz is commented out */
-   if (pI830->CloneRefresh < 60 || pI830->CloneRefresh > 85 /* 120 */) {
-      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Bad Clone Refresh Rate\n");
-      PreInitCleanup(pScrn);
-      return FALSE;
-   }
-
-   if ((pI830->entityPrivate && I830IsPrimary(pScrn)) || pI830->Clone) {
-      if (pI830->MonType1 == PIPE_NONE || pI830->MonType2 == PIPE_NONE) {
-         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Monitor 1 or Monitor 2 "
-	 		"cannot be type NONE in DualHead or Clone setup.\n");
-         PreInitCleanup(pScrn);
-         return FALSE;
-      }
-   }
-#endif
-
    pI830->rotation = RR_Rotate_0;
    if ((s = xf86GetOptValString(pI830->Options, OPTION_ROTATE))) {
       pI830->InitialRotation = 0;
@@ -1646,24 +1474,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       }
    }
 
-#if 0
-   if (xf86IsEntityShared(pScrn->entityList[0])) {
-      if (!I830IsPrimary(pScrn)) {
-	 /* This could be made to work with a little more fiddling */
-	 pI830->directRenderingDisabled = TRUE;
-
-         xf86DrvMsg(pScrn->scrnIndex, from, "Secondary head is using Pipe %s\n",
-		pI830->pipe ? "B" : "A");
-      } else {
-         xf86DrvMsg(pScrn->scrnIndex, from, "Primary head is using Pipe %s\n",
-		pI830->pipe ? "B" : "A");
-      }
-   } else {
-      xf86DrvMsg(pScrn->scrnIndex, from, "Display is using Pipe %s\n",
-		pI830->pipe ? "B" : "A");
-   }
-#endif
-
    /* Alloc our pointers for the primary head */
    if (I830IsPrimary(pScrn)) {
       pI830->LpRing = xalloc(sizeof(I830RingBuffer));
@@ -3561,11 +3371,6 @@ I830EnterVT(int scrnIndex, int flags)
    I830DRISetVBlankInterrupt (pScrn, TRUE);
 #endif
    
-#if 0
-   if (!i830SetMode(pScrn, pScrn->currentMode))
-      return FALSE;
-#endif
-   
 #ifdef I830_XV
    I830VideoSwitchModeAfter(pScrn, pScrn->currentMode);
 #endif
diff-tree 850e3652f4d5bb57f3c4ccb9cf29e2c75fecba9d (from 659e3db925de91954421f7f33c072576dfefcc4a)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Wed Nov 22 15:36:43 2006 -0800

    Note which pipe has failed to be configured for VBlank interrupt

diff --git a/src/i830_dri.c b/src/i830_dri.c
index 6b17f46..3b02918 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1526,7 +1526,7 @@ I830DRISetVBlankInterrupt (ScrnInfoPtr p
 	}
 	if (drmCommandWrite(pI830->drmSubFD, DRM_I830_SET_VBLANK_PIPE,
 			    &pipe, sizeof (pipe))) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "I830 Vblank Pipe Setup Failed\n");
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "I830 Vblank Pipe Setup Failed %d\n", pipe.pipe);
 	    return FALSE;
 	}
     }
diff-tree 659e3db925de91954421f7f33c072576dfefcc4a (from 03c12f866529230df7a1503de61954cd5ade242e)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Wed Nov 22 15:35:59 2006 -0800

    Set up maximum screen size for clone instead of panorama.
    
    This avoids heading past the 8Kbyte stride limit of DRI so
    that 3D will be available by default.

diff --git a/src/i830_randr.c b/src/i830_randr.c
index d8e2261..a530ffb 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -1183,7 +1183,8 @@ I830RRDefaultScreenLimits (RROutputPtr *
 		    }
 		}
 	}
-	width += crtc_width;
+	if (crtc_width > width)
+	    width = crtc_width;
 	if (crtc_height > height)
 	    height = crtc_height;
     }
diff-tree 03c12f866529230df7a1503de61954cd5ade242e (from a0a9d1ea2ac9a0c665e5a1de5b8b8358dee3b9b4)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Wed Nov 22 15:34:03 2006 -0800

    Limit DRI use to cases when pitch < 8Kbytes, not 4096 pixels.
    
    3D rendering pipeline is limited to pitch of 8Kbytes and not 4096
    pixels, which rather makes a difference at 32bpp.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 5dcd596..aaac83e 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -661,10 +661,8 @@ I830SetupOutputs(ScrnInfoPtr pScrn)
    } else {
       i830_dvo_init(pScrn);
    }
-#if 1
    if (IS_I915GM(pI830) || IS_I945GM(pI830))
       i830_tv_init(pScrn);
-#endif
 }
 
 static void 
@@ -1915,9 +1913,9 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 #endif
       pI830->disableTiling = TRUE; /* no DRI - so disableTiling */
 
-   if (pScrn->displayWidth >= 4096) {
-      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot support > 1024x768 in leftof/rightof configurations. disabling DRI.\n");
-      pI830->directRenderingDisabled = TRUE;
+   if (pScrn->displayWidth * pI830->cpp > 8192) {
+      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot support frame buffer stride > 8K >  DRI.\n");
+      pI830->disableTiling = TRUE;
    }
 
    if (pScrn->virtualY > 2048) {
diff-tree a0a9d1ea2ac9a0c665e5a1de5b8b8358dee3b9b4 (from d6a0f917e601ea36643c6ad857756e19d24ecd73)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Mon Nov 20 17:25:00 2006 -0800

    Set configured values for screen virtual size and initial frame.
    
    Computation for virtual size and initial frame origin is quite
    broken in xf86 common code.

diff --git a/src/i830_randr.c b/src/i830_randr.c
index d27125f..d8e2261 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -1172,17 +1172,16 @@ I830RRDefaultScreenLimits (RROutputPtr *
 
 	    for (s = 0; s < output->numCrtcs; s++)
 		if (output->crtcs[s] == crtc)
-		    break;
-	    if (s == output->numCrtcs)
-		continue;
-	    for (m = 0; m < output->numModes; m++)
-	    {
-		RRModePtr   mode = output->modes[m];
-		if (mode->mode.width > crtc_width)
-		    crtc_width = mode->mode.width;
-		if (mode->mode.height > crtc_width)
-		    crtc_height = mode->mode.height;
-	    }
+		{
+		    for (m = 0; m < output->numModes; m++)
+		    {
+			RRModePtr   mode = output->modes[m];
+			if (mode->mode.width > crtc_width)
+			    crtc_width = mode->mode.width;
+			if (mode->mode.height > crtc_width)
+			    crtc_height = mode->mode.height;
+		    }
+		}
 	}
 	width += crtc_width;
 	if (crtc_height > height)
@@ -1241,9 +1240,16 @@ I830RandRPreInit (ScrnInfoPtr pScrn)
     
     if (width > pScrn->virtualX)
 	pScrn->virtualX = width;
+    if (width > pScrn->display->virtualX)
+	pScrn->display->virtualX = width;
     if (height > pScrn->virtualY)
 	pScrn->virtualY = height;
+    if (height > pScrn->display->virtualY)
+	pScrn->display->virtualY = height;
     
+    /* XXX override xf86 common frame computation code */
+    pScrn->display->frameX0 = 0;
+    pScrn->display->frameY0 = 0;
     for (o = 0; o < pI830->num_outputs; o++)
     {
 	RRModePtr	randr_mode = output_modes[o];
diff-tree d6a0f917e601ea36643c6ad857756e19d24ecd73 (from b945a650e952f98c2d101b71bd3ec0f390478da5)
Author: Keith Packard <keithp at bouzouki.jf.intel.com>
Date:   Mon Nov 20 15:17:32 2006 -0800

    Enable second SDVO channel.
    
    Rework SDVO support so that it can deal with two channels correctly,
    also save/restore all connected output timings.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index aaa2628..5dcd596 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -657,13 +657,7 @@ I830SetupOutputs(ScrnInfoPtr pScrn)
 
    if (IS_I9XX(pI830)) {
       i830_sdvo_init(pScrn, SDVOB);
-
-      /* Don't initialize the second SDVO port for now.  We have issues with
-       * dealing with two ports, where we stomp both SDVO channels' registers
-       * when interacting with each, channel, and commands to one SDVO
-       * device appear to be affecting the other.
-       */
-      /* i830_sdvo_init(pScrn, SDVOC); */
+      i830_sdvo_init(pScrn, SDVOC);
    } else {
       i830_dvo_init(pScrn);
    }
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 8d1f296..fedb8a6 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -59,7 +59,7 @@ struct i830_sdvo_priv {
     int output_device;
 
     /** Active outputs controlled by this SDVO output */
-    struct i830_sdvo_output_flags active_outputs;
+    CARD16 active_outputs;
 
     /**
      * Capabilities of the SDVO device returned by i830_sdvo_get_capabilities()
@@ -72,9 +72,9 @@ struct i830_sdvo_priv {
     /** State for save/restore */
     /** @{ */
     int save_sdvo_mult;
-    struct i830_sdvo_output_flags save_active_outputs;
+    CARD16 save_active_outputs;
     struct i830_sdvo_dtd save_input_dtd_1, save_input_dtd_2;
-    struct i830_sdvo_dtd save_output_dtd;
+    struct i830_sdvo_dtd save_output_dtd[16];
     CARD32 save_SDVOX;
     /** @} */
 };
@@ -155,6 +155,11 @@ const struct _sdvo_cmd_name {
     SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTROL_BUS_SWITCH),
 };
 
+static I2CSlaveAddr slaveAddr;
+
+#define SDVO_NAME(dev_priv) ((dev_priv)->output_device == SDVOB ? "SDVO" : "SDVO")
+#define SDVO_PRIV(output)   ((struct i830_sdvo_priv *) (output)->dev_priv)
+
 /**
  * Writes out the data given in args (up to 8 bytes), followed by the opcode.
  */
@@ -162,9 +167,13 @@ static void
 i830_sdvo_write_cmd(I830OutputPtr output, CARD8 cmd, void *args, int args_len)
 {
     int i;
+    struct i830_sdvo_priv *dev_priv = output->dev_priv;
+
+    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, "SDVO: W: %02X ", cmd);
+    xf86DrvMsg(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++)
@@ -217,7 +226,7 @@ i830_sdvo_read_response(I830OutputPtr ou
 
     /* Write the SDVO command logging */
     xf86DrvMsg(output->pI2CBus->scrnIndex, X_INFO,
-	       "SDVO: R: ");
+	       "%s: R: ", SDVO_NAME(SDVO_PRIV(output)));
     for (i = 0; i < response_len; i++)
 	LogWrite(1, "%02X ", ((CARD8 *)response)[i]);
     for (; i < 8; i++)
@@ -300,7 +309,7 @@ i830_sdvo_get_trained_inputs(I830OutputP
 
 static Bool
 i830_sdvo_get_active_outputs(I830OutputPtr output,
-			     struct i830_sdvo_output_flags *outputs)
+			     CARD16 *outputs)
 {
     CARD8 status;
 
@@ -312,12 +321,12 @@ i830_sdvo_get_active_outputs(I830OutputP
 
 static Bool
 i830_sdvo_set_active_outputs(I830OutputPtr output,
-			     struct i830_sdvo_output_flags *outputs)
+			     CARD16 outputs)
 {
     CARD8 status;
 
-    i830_sdvo_write_cmd(output, SDVO_CMD_SET_ACTIVE_OUTPUTS, outputs,
-			sizeof(*outputs));
+    i830_sdvo_write_cmd(output, SDVO_CMD_SET_ACTIVE_OUTPUTS, &outputs,
+			sizeof(outputs));
     status = i830_sdvo_read_response(output, NULL, 0);
 
     return (status == SDVO_CMD_STATUS_SUCCESS);
@@ -348,13 +357,12 @@ i830_sdvo_get_input_pixel_clock_range(I8
 }
 
 static Bool
-i830_sdvo_set_target_output(I830OutputPtr output,
-			    struct i830_sdvo_output_flags *outputs)
+i830_sdvo_set_target_output(I830OutputPtr output, CARD16 outputs)
 {
     CARD8 status;
 
-    i830_sdvo_write_cmd(output, SDVO_CMD_SET_TARGET_OUTPUT, outputs,
-			sizeof(*outputs));
+    i830_sdvo_write_cmd(output, SDVO_CMD_SET_TARGET_OUTPUT, &outputs,
+			sizeof(outputs));
 
     status = i830_sdvo_read_response(output, NULL, 0);
 
@@ -522,9 +530,9 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn
     CARD16 h_blank_len, h_sync_len, v_blank_len, v_sync_len;
     CARD16 h_sync_offset, v_sync_offset;
     struct i830_sdvo_dtd output_dtd;
-    struct i830_sdvo_output_flags no_outputs;
+    CARD16 no_outputs;
 
-    memset(&no_outputs, 0, sizeof(no_outputs));
+    no_outputs = 0;
 
     if (!mode)
 	return;
@@ -570,10 +578,10 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn
     output_dtd.part2.reserved = 0;
 
     /* Turn off the screens before adjusting timings */
-    i830_sdvo_set_active_outputs(output, &no_outputs);
+    i830_sdvo_set_active_outputs(output, 0);
 
     /* Set the output timing to the screen */
-    i830_sdvo_set_target_output(output, &dev_priv->active_outputs);
+    i830_sdvo_set_target_output(output, dev_priv->active_outputs);
     i830_sdvo_set_output_timing(output, &output_dtd);
 
     /* Set the input timing to the screen. Assume always input 0. */
@@ -609,8 +617,7 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn
 	break;
     }
 
-    OUTREG(SDVOC, INREG(SDVOC) & ~SDVO_ENABLE);
-    OUTREG(SDVOB, INREG(SDVOB) & ~SDVO_ENABLE);
+    OUTREG(dev_priv->output_device, INREG(dev_priv->output_device) & ~SDVO_ENABLE);
 }
 
 static void
@@ -620,7 +627,7 @@ i830_sdvo_post_set_mode(ScrnInfoPtr pScr
     I830Ptr pI830 = I830PTR(pScrn);
     struct i830_sdvo_priv *dev_priv = output->dev_priv;
     Bool input1, input2;
-    CARD32 dpll, sdvob, sdvoc;
+    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 sdvo_pixel_multiply;
@@ -628,12 +635,18 @@ i830_sdvo_post_set_mode(ScrnInfoPtr pScr
     CARD8 status;
 
     /* Set the SDVO control regs. */
-    sdvob = INREG(SDVOB) & SDVOB_PRESERVE_MASK;
-    sdvoc = INREG(SDVOC) & SDVOC_PRESERVE_MASK;
-    sdvob |= SDVO_ENABLE | (9 << 19) | SDVO_BORDER_ENABLE;
-    sdvoc |= 9 << 19;
+    sdvox = INREG(dev_priv->output_device);
+    switch (dev_priv->output_device) {
+    case SDVOB:
+	sdvox &= SDVOB_PRESERVE_MASK;
+	break;
+    case SDVOC:
+	sdvox &= SDVOC_PRESERVE_MASK;
+	break;
+    }
+    sdvox |= SDVO_ENABLE | (9 << 19) | SDVO_BORDER_ENABLE;
     if (output->pipe == 1)
-	sdvob |= SDVO_PIPE_B_SELECT;
+	sdvox |= SDVO_PIPE_B_SELECT;
 
     dpll = INREG(dpll_reg);
 
@@ -644,13 +657,12 @@ i830_sdvo_post_set_mode(ScrnInfoPtr pScr
     } else if (IS_I945G(pI830) || IS_I945GM(pI830)) {
 	dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
     } else {
-	sdvob |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT;
+	sdvox |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT;
     }
 
     OUTREG(dpll_reg, dpll | DPLL_DVO_HIGH_SPEED);
 
-    OUTREG(SDVOB, sdvob);
-    OUTREG(SDVOC, sdvoc);
+    OUTREG(dev_priv->output_device, sdvox);
 
     for (i = 0; i < 2; i++)
 	i830WaitForVblank(pScrn);
@@ -660,10 +672,11 @@ i830_sdvo_post_set_mode(ScrnInfoPtr pScr
     /* Warn if the device reported failure to sync. */
     if (status == SDVO_CMD_STATUS_SUCCESS && !input1) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		   "First SDVO output reported failure to sync\n");
+		   "First %s output reported failure to sync\n",
+		   SDVO_NAME(dev_priv));
     }
 
-    i830_sdvo_set_active_outputs(output, &dev_priv->active_outputs);
+    i830_sdvo_set_active_outputs(output, dev_priv->active_outputs);
     i830_sdvo_set_target_input(output, TRUE, FALSE);
 }
 
@@ -674,15 +687,11 @@ i830_sdvo_dpms(ScrnInfoPtr pScrn, I830Ou
     struct i830_sdvo_priv *dev_priv = output->dev_priv;
 
     if (mode != DPMSModeOn) {
-	struct i830_sdvo_output_flags no_outputs;
-
-	memset(&no_outputs, 0, sizeof(no_outputs));
-
-	i830_sdvo_set_active_outputs(output, &no_outputs);
-	OUTREG(SDVOB, INREG(SDVOB) & ~SDVO_ENABLE);
+	i830_sdvo_set_active_outputs(output, 0);
+	OUTREG(dev_priv->output_device, INREG(dev_priv->output_device) & ~SDVO_ENABLE);
     } else {
-	i830_sdvo_set_active_outputs(output, &dev_priv->active_outputs);
-	OUTREG(SDVOB, INREG(SDVOB) | SDVO_ENABLE);
+	i830_sdvo_set_active_outputs(output, dev_priv->active_outputs);
+	OUTREG(dev_priv->output_device, INREG(dev_priv->output_device) | SDVO_ENABLE);
     }
 }
 
@@ -691,6 +700,7 @@ i830_sdvo_save(ScrnInfoPtr pScrn, I830Ou
 {
     I830Ptr pI830 = I830PTR(pScrn);
     struct i830_sdvo_priv *dev_priv = output->dev_priv;
+    int o;
 
     /* XXX: We should save the in/out mapping. */
 
@@ -707,11 +717,15 @@ i830_sdvo_save(ScrnInfoPtr pScrn, I830Ou
        i830_sdvo_get_input_timing(output, &dev_priv->save_input_dtd_2);
     }
 
-    /* XXX: We should really iterate over the enabled outputs and save each
-     * one's state.
-     */
-    i830_sdvo_set_target_output(output, &dev_priv->save_active_outputs);
-    i830_sdvo_get_output_timing(output, &dev_priv->save_output_dtd);
+    for (o = SDVO_OUTPUT_FIRST; o <= SDVO_OUTPUT_LAST; o++)
+    {
+	CARD16  this_output = (1 << o);
+	if (dev_priv->caps.output_flags & this_output)
+	{
+	    i830_sdvo_set_target_output(output, this_output);
+	    i830_sdvo_get_output_timing(output, &dev_priv->save_output_dtd[o]);
+	}
+    }
 
     dev_priv->save_SDVOX = INREG(dev_priv->output_device);
 }
@@ -721,6 +735,7 @@ i830_sdvo_restore(ScrnInfoPtr pScrn, I83
 {
     I830Ptr pI830 = I830PTR(pScrn);
     struct i830_sdvo_priv *dev_priv = output->dev_priv;
+    int o;
 
     if (dev_priv->caps.sdvo_inputs_mask & 0x1) {
        i830_sdvo_set_target_input(output, TRUE, FALSE);
@@ -732,14 +747,20 @@ i830_sdvo_restore(ScrnInfoPtr pScrn, I83
        i830_sdvo_set_input_timing(output, &dev_priv->save_input_dtd_2);
     }
 
-    i830_sdvo_set_target_output(output, &dev_priv->save_active_outputs);
-    i830_sdvo_set_output_timing(output, &dev_priv->save_output_dtd);
+    for (o = SDVO_OUTPUT_FIRST; o <= SDVO_OUTPUT_LAST; o++)
+    {
+	CARD16  this_output = (1 << o);
+	if (dev_priv->caps.output_flags & this_output)
+	{
+	    i830_sdvo_set_target_output(output, this_output);
+	    i830_sdvo_set_output_timing(output, &dev_priv->save_output_dtd[o]);
+	}
+    }
+    i830_sdvo_set_target_output(output, dev_priv->save_active_outputs);
 
     i830_sdvo_set_clock_rate_mult(output, dev_priv->save_sdvo_mult);
 
     OUTREG(dev_priv->output_device, dev_priv->save_SDVOX);
-
-    i830_sdvo_set_active_outputs(output, &dev_priv->save_active_outputs);
 }
 
 static int
@@ -989,8 +1010,8 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
 
     if (!xf86I2CDevInit(&dev_priv->d)) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		   "Failed to initialize SDVO I2C device %s\n",
-		   output_device == SDVOB ? "SDVOB" : "SDVOC");
+		   "Failed to initialize %s I2C device\n",
+		   SDVO_NAME(dev_priv));
 	xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE);
 	xfree(dev_priv);
 	return;
@@ -1043,25 +1064,42 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
 
     i830_sdvo_get_capabilities(output, &dev_priv->caps);
 
+    memset(&dev_priv->active_outputs, 0, sizeof(dev_priv->active_outputs));
+    if (dev_priv->caps.output_flags & SDVO_OUTPUT_TMDS0)
+	dev_priv->active_outputs = SDVO_OUTPUT_TMDS0;
+    else if (dev_priv->caps.output_flags & SDVO_OUTPUT_TMDS1)
+	dev_priv->active_outputs = SDVO_OUTPUT_TMDS1;
+    else
+    {
+	unsigned char	bytes[2];
+
+	memcpy (bytes, &dev_priv->caps.output_flags, 2);
+	xf86DrvMsg(output->pI2CBus->scrnIndex, X_ERROR,
+		   "%s: No active TMDS outputs (0x%02x%02x)\n",
+		   SDVO_NAME(dev_priv),
+		   bytes[0], bytes[1]);
+    }
+    
+    /* Set the input timing to the screen. Assume always input 0. */
+    i830_sdvo_set_target_input(output, TRUE, FALSE);
+
     i830_sdvo_get_input_pixel_clock_range(output, &dev_priv->pixel_clock_min,
 					  &dev_priv->pixel_clock_max);
 
-    memset(&dev_priv->active_outputs, 0, sizeof(dev_priv->active_outputs));
-    dev_priv->active_outputs.tmds0 = 1;
-
     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-	       "SDVO device VID/DID: %02X:%02X.%02X, "
+	       "%s device VID/DID: %02X:%02X.%02X, "
 	       "clock range %.1fMHz - %.1fMHz, "
 	       "input 1: %c, input 2: %c, "
 	       "output 1: %c, output 2: %c\n",
+	       SDVO_NAME(dev_priv),
 	       dev_priv->caps.vendor_id, dev_priv->caps.device_id,
 	       dev_priv->caps.device_rev_id,
 	       dev_priv->pixel_clock_min / 1000.0,
 	       dev_priv->pixel_clock_max / 1000.0,
 	       (dev_priv->caps.sdvo_inputs_mask & 0x1) ? 'Y' : 'N',
 	       (dev_priv->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N',
-	       dev_priv->caps.output_flags.tmds0 ? 'Y' : 'N',
-	       dev_priv->caps.output_flags.tmds1 ? '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_sdvo_regs.h b/src/i830_sdvo_regs.h
index 98aa7a6..59b2aa8 100644
--- a/src/i830_sdvo_regs.h
+++ b/src/i830_sdvo_regs.h
@@ -29,21 +29,18 @@
  * @file SDVO command definitions and structures.
  */
 
-struct i830_sdvo_output_flags {
-    unsigned int tmds0:1;
-    unsigned int rgb0:1;
-    unsigned int cvbs0:1;
-    unsigned int svid0:1;
-    unsigned int yprpb0:1;
-    unsigned int scart0:1;
-    unsigned int lvds0:1;
-    unsigned int pad0:1;
-    unsigned int tmds1:1;
-    unsigned int pad1:4;
-    unsigned int rgb1:1;
-    unsigned int lvds1:1;
-    unsigned int pad2:1;
-} __attribute__((packed));
+#define SDVO_OUTPUT_FIRST   (0)
+#define SDVO_OUTPUT_TMDS0   (1 << 0)
+#define SDVO_OUTPUT_RGB0    (1 << 1)
+#define SDVO_OUTPUT_CVBS0   (1 << 2)
+#define SDVO_OUTPUT_SVID0   (1 << 3)
+#define SDVO_OUTPUT_YPRPB0  (1 << 4)
+#define SDVO_OUTPUT_SCART0  (1 << 5)
+#define SDVO_OUTPUT_LVDS0   (1 << 6)
+#define SDVO_OUTPUT_TMDS1   (1 << 8)
+#define SDVO_OUTPUT_RGB1    (1 << 13)
+#define SDVO_OUTPUT_LVDS1   (1 << 14)
+#define SDVO_OUTPUT_LAST    (14)
 
 struct i830_sdvo_caps {
     CARD8 vendor_id;
@@ -58,7 +55,7 @@ struct i830_sdvo_caps {
     unsigned int down_scaling:1;
     unsigned int stall_support:1;
     unsigned int pad:1;
-    struct i830_sdvo_output_flags output_flags;
+    CARD16 output_flags;
 } __attribute__((packed));
 
 /** This matches the EDID DTD structure, more or less */
@@ -204,7 +201,7 @@ struct i830_sdvo_get_trained_inputs_resp
 
 #define SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE		0x0f
 struct i830_sdvo_get_interrupt_event_source_response {
-    struct i830_sdvo_output_flags interrupt_status;
+    CARD16 interrupt_status;
     unsigned int ambient_light_interrupt:1;
     unsigned int pad:7;
 } __attribute__((packed));
diff-tree b945a650e952f98c2d101b71bd3ec0f390478da5 (from 28224af3d90a1a08d54a865dfaf20184330fe8a4)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Sun Nov 19 00:54:30 2006 -0800

    Fix TV color key.
    
    Subcarrier defines were incorrect in header file leaving one of the
    DDA phases disabled.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index a61bc6b..53a063f 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -1409,9 +1409,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 /** Turns on the first subcarrier phase generation DDA */
 # define TV_SC_DDA1_EN			(1 << 31)
 /** Turns on the first subcarrier phase generation DDA */
-# define TV_SC_DDA2_EN			(2 << 31)
+# define TV_SC_DDA2_EN			(1 << 30)
 /** Turns on the first subcarrier phase generation DDA */
-# define TV_SC_DDA3_EN			(3 << 31)
+# define TV_SC_DDA3_EN			(1 << 29)
 /** Sets the subcarrier DDA to reset frequency every other field */
 # define TV_SC_RESET_EVERY_2		(0 << 24)
 /** Sets the subcarrier DDA to reset frequency every fourth field */
diff-tree 28224af3d90a1a08d54a865dfaf20184330fe8a4 (from 816fc1a76a5ac738e41b172ba8f43137c1521328)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Sun Nov 19 00:40:46 2006 -0800

    Preliminary 945 TV output. Color key is broken. Fixed mode.
    
    TV output is generating video with this patch, but the color burst
    signal is incorrect somehow.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index 0ece7ee..a61bc6b 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -1044,6 +1044,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 # define TV_ENC_OUTPUT_SVIDEO		(1 << 28)
 /** Outputs Component video (DAC A/B/C) */
 # define TV_ENC_OUTPUT_COMPONENT	(2 << 28)
+/** Outputs Composite and SVideo (DAC A/B/C) */
+# define TV_ENC_OUTPUT_SVIDEO_COMPOSITE	(3 << 28)
 # define TV_TRILEVEL_SYNC		(1 << 21)
 /** Enables slow sync generation (945GM only) */
 # define TV_SLOW_SYNC			(1 << 20)
@@ -1078,6 +1080,18 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 # define TV_FUSE_STATE_NO_MACROVISION	(1 << 4)
 /** Read-only state that reports that TV-out is disabled in hardware. */
 # define TV_FUSE_STATE_DISABLED		(2 << 4)
+/** Normal operation */
+# define TV_TEST_MODE_NORMAL		(0 << 0)
+/** Encoder test pattern 1 - combo pattern */
+# define TV_TEST_MODE_PATTERN_1		(1 << 0)
+/** Encoder test pattern 2 - full screen vertical 75% color bars */
+# define TV_TEST_MODE_PATTERN_2		(2 << 0)
+/** Encoder test pattern 3 - full screen horizontal 75% color bars */
+# define TV_TEST_MODE_PATTERN_3		(3 << 0)
+/** Encoder test pattern 4 - random noise */
+# define TV_TEST_MODE_PATTERN_4		(4 << 0)
+/** Encoder test pattern 5 - linear color ramps */
+# define TV_TEST_MODE_PATTERN_5		(5 << 0)
 /**
  * This test mode forces the DACs to 50% of full output.
  *
@@ -1417,7 +1431,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 /** @defgroup TV_SC_CTL_2
  * @{
  */
-#define TV_SC_CTL_2		0x68068
+#define TV_SC_CTL_2		0x68064
 /** Sets the rollover for the second subcarrier phase generation DDA */
 # define TV_SCDDA2_SIZE_MASK		0x7fff0000
 # define TV_SCDDA2_SIZE_SHIFT		16
@@ -1586,6 +1600,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define TV_H_LUMA_59		0x681ec
 #define TV_H_CHROMA_0		0x68200
 #define TV_H_CHROMA_59		0x682ec
+#define TV_V_LUMA_0		0x68300
+#define TV_V_LUMA_42		0x683a8
+#define TV_V_CHROMA_0		0x68400
+#define TV_V_CHROMA_42		0x684a8
 /** @} */
 
 #define PIPEACONF 0x70008
diff --git a/src/i830_debug.c b/src/i830_debug.c
index 7922af0..185988e 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -126,6 +126,41 @@ static struct i830SnapshotRec {
     DEFINEREG(VCLK_DIVISOR_VGA1),
     DEFINEREG(VCLK_POST_DIV),
     DEFINEREG(VGACNTRL),
+
+    DEFINEREG(TV_CTL),
+    DEFINEREG(TV_DAC),
+    DEFINEREG(TV_CSC_Y),
+    DEFINEREG(TV_CSC_Y2),
+    DEFINEREG(TV_CSC_U),
+    DEFINEREG(TV_CSC_U2),
+    DEFINEREG(TV_CSC_V),
+    DEFINEREG(TV_CSC_V2),
+    DEFINEREG(TV_CLR_KNOBS),
+    DEFINEREG(TV_CLR_LEVEL),
+    DEFINEREG(TV_H_CTL_1),
+    DEFINEREG(TV_H_CTL_2),
+    DEFINEREG(TV_H_CTL_3),
+    DEFINEREG(TV_V_CTL_1),
+    DEFINEREG(TV_V_CTL_2),
+    DEFINEREG(TV_V_CTL_3),
+    DEFINEREG(TV_V_CTL_4),
+    DEFINEREG(TV_V_CTL_5),
+    DEFINEREG(TV_V_CTL_6),
+    DEFINEREG(TV_V_CTL_7),
+    DEFINEREG(TV_SC_CTL_1),
+    DEFINEREG(TV_SC_CTL_2),
+    DEFINEREG(TV_SC_CTL_3),
+    DEFINEREG(TV_WIN_POS),
+    DEFINEREG(TV_WIN_SIZE),
+    DEFINEREG(TV_FILTER_CTL_1),
+    DEFINEREG(TV_FILTER_CTL_2),
+    DEFINEREG(TV_FILTER_CTL_3),
+    DEFINEREG(TV_CC_CONTROL),
+    DEFINEREG(TV_CC_DATA),
+    DEFINEREG(TV_H_LUMA_0),
+    DEFINEREG(TV_H_LUMA_59),
+    DEFINEREG(TV_H_CHROMA_0),
+    DEFINEREG(TV_H_CHROMA_59),
 };
 #undef DEFINEREG
 #define NUM_I830_SNAPSHOTREGS (sizeof(i830_snapshot) / sizeof(i830_snapshot[0]))
diff --git a/src/i830_display.c b/src/i830_display.c
index bd40e4e..04f85cc 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -587,7 +587,11 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     }
 
     if (is_tv)
-	dpll |= PLL_REF_INPUT_TVCLKINBC;
+    {
+	/* XXX: just matching BIOS for now */
+/*	dpll |= PLL_REF_INPUT_TVCLKINBC; */
+	dpll |= 3;
+    }
 #if 0    
     else if (is_lvds)
 	dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index c9e06a6..aaa2628 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -667,6 +667,10 @@ I830SetupOutputs(ScrnInfoPtr pScrn)
    } else {
       i830_dvo_init(pScrn);
    }
+#if 1
+   if (IS_I915GM(pI830) || IS_I945GM(pI830))
+      i830_tv_init(pScrn);
+#endif
 }
 
 static void 
@@ -702,7 +706,8 @@ PreInitCleanup(ScrnInfoPtr pScrn)
    I830Ptr pI830 = I830PTR(pScrn);
 
    if (I830IsPrimary(pScrn)) {
-      pI830->entityPrivate->pScrn_1 = NULL;
+      if (pI830->entityPrivate)
+	 pI830->entityPrivate->pScrn_1 = NULL;
       if (pI830->LpRing)
          xfree(pI830->LpRing);
       pI830->LpRing = NULL;
@@ -1434,6 +1439,12 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 	    }
 	 }
 	 break;
+      case I830_OUTPUT_TVOUT:
+         if (!i830PipeInUse(pScrn, 0)) {
+	    pI830->output[i].pipe = 0;
+	    pI830->output[i].enabled = TRUE;
+	 }
+	 break;
       default:
 	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unhandled output type\n");
 	 break;
@@ -3551,6 +3562,7 @@ I830EnterVT(int scrnIndex, int flags)
 
    i830DisableUnusedFunctions(pScrn);
 
+   i830DumpRegs (pScrn);
    i830DescribeOutputConfiguration(pScrn);
 
 #ifdef XF86DRI
diff --git a/src/i830_tv.c b/src/i830_tv.c
index c597db5..f938d5c 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -279,8 +279,74 @@ i830_tv_pre_set_mode(ScrnInfoPtr pScrn, 
 
     /* Disable the encoder while we set up the pipe. */
     OUTREG(TV_CTL, INREG(TV_CTL) & ~TV_ENC_ENABLE);
+    /* XXX match BIOS for now */
+    OUTREG(ADPA, 0x40008C18);
 }
 
+static const CARD32 h_luma[60] = {
+    0xB1403000, 0x2E203500, 0x35002E20, 0x3000B140,
+    0x35A0B160, 0x2DC02E80, 0xB1403480, 0xB1603000,
+    0x2EA03640, 0x34002D80, 0x3000B120, 0x36E0B160,
+    0x2D202EF0, 0xB1203380, 0xB1603000, 0x2F303780,
+    0x33002CC0, 0x3000B100, 0x3820B160, 0x2C802F50,
+    0xB10032A0, 0xB1603000, 0x2F9038C0, 0x32202C20,
+    0x3000B0E0, 0x3980B160, 0x2BC02FC0, 0xB0E031C0,
+    0xB1603000, 0x2FF03A20, 0x31602B60, 0xB020B0C0,
+    0x3AE0B160, 0x2B001810, 0xB0C03120, 0xB140B020,
+    0x18283BA0, 0x30C02A80, 0xB020B0A0, 0x3C60B140,
+    0x2A201838, 0xB0A03080, 0xB120B020, 0x18383D20,
+    0x304029C0, 0xB040B080, 0x3DE0B100, 0x29601848,
+    0xB0803000, 0xB100B040, 0x18483EC0, 0xB0402900,
+    0xB040B060, 0x3F80B0C0, 0x28801858, 0xB060B080,
+    0xB0A0B060, 0x18602820, 0xB0A02820, 0x0000B060,
+};
+
+static const CARD32 h_chroma[60] = {
+    0xB1403000, 0x2E203500, 0x35002E20, 0x3000B140,
+    0x35A0B160, 0x2DC02E80, 0xB1403480, 0xB1603000,
+    0x2EA03640, 0x34002D80, 0x3000B120, 0x36E0B160,
+    0x2D202EF0, 0xB1203380, 0xB1603000, 0x2F303780,
+    0x33002CC0, 0x3000B100, 0x3820B160, 0x2C802F50,
+    0xB10032A0, 0xB1603000, 0x2F9038C0, 0x32202C20,
+    0x3000B0E0, 0x3980B160, 0x2BC02FC0, 0xB0E031C0,
+    0xB1603000, 0x2FF03A20, 0x31602B60, 0xB020B0C0,
+    0x3AE0B160, 0x2B001810, 0xB0C03120, 0xB140B020,
+    0x18283BA0, 0x30C02A80, 0xB020B0A0, 0x3C60B140,
+    0x2A201838, 0xB0A03080, 0xB120B020, 0x18383D20,
+    0x304029C0, 0xB040B080, 0x3DE0B100, 0x29601848,
+    0xB0803000, 0xB100B040, 0x18483EC0, 0xB0402900,
+    0xB040B060, 0x3F80B0C0, 0x28801858, 0xB060B080,
+    0xB0A0B060, 0x18602820, 0xB0A02820, 0x0000B060,
+};
+
+static const CARD32 v_luma[43] = {
+    0x36403000, 0x2D002CC0, 0x30003640, 0x2D0036C0,
+    0x35C02CC0, 0x37403000, 0x2C802D40, 0x30003540,
+    0x2D8037C0, 0x34C02C40, 0x38403000, 0x2BC02E00,
+    0x30003440, 0x2E2038C0, 0x34002B80, 0x39803000,
+    0x2B402E40, 0x30003380, 0x2E603A00, 0x33402B00,
+    0x3A803040, 0x2A802EA0, 0x30403300, 0x2EC03B40,
+    0x32802A40, 0x3C003040, 0x2A002EC0, 0x30803240,
+    0x2EC03C80, 0x320029C0, 0x3D403080, 0x29402F00,
+    0x308031C0, 0x2F203DC0, 0x31802900, 0x3E8030C0,
+    0x28802F40, 0x30C03140, 0x2F203F40, 0x31402840,
+    0x28003100, 0x28002F00, 0x00003100,
+};
+
+static const CARD32 v_chroma[43] = {
+    0x36403000, 0x2D002CC0, 0x30003640, 0x2D0036C0,
+    0x35C02CC0, 0x37403000, 0x2C802D40, 0x30003540,
+    0x2D8037C0, 0x34C02C40, 0x38403000, 0x2BC02E00,
+    0x30003440, 0x2E2038C0, 0x34002B80, 0x39803000,
+    0x2B402E40, 0x30003380, 0x2E603A00, 0x33402B00,
+    0x3A803040, 0x2A802EA0, 0x30403300, 0x2EC03B40,
+    0x32802A40, 0x3C003040, 0x2A002EC0, 0x30803240,
+    0x2EC03C80, 0x320029C0, 0x3D403080, 0x29402F00,
+    0x308031C0, 0x2F203DC0, 0x31802900, 0x3E8030C0,
+    0x28802F40, 0x30C03140, 0x2F203F40, 0x31402840,
+    0x28003100, 0x28002F00, 0x00003100,
+};
+
 static void
 i830_tv_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
 		      DisplayModePtr pMode)
@@ -293,6 +359,7 @@ i830_tv_post_set_mode(ScrnInfoPtr pScrn,
     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
@@ -302,10 +369,6 @@ i830_tv_post_set_mode(ScrnInfoPtr pScrn,
     sc_mode = &tv_sc_modes[TV_SC_NTSC_MJ];
 
     type = i830_tv_detect_type(pScrn, output);
-    if (type == TV_TYPE_UNKNOWN) {
-	xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Defaulting TV to SVIDEO\n");
-	type = TV_TYPE_SVIDEO;
-    }
 
     hctl1 = (tv_mode->hsync_end << TV_HSYNC_END_SHIFT) |
 	(tv_mode->htotal << TV_HTOTAL_SHIFT);
@@ -355,10 +418,13 @@ i830_tv_post_set_mode(ScrnInfoPtr pScrn,
     case TV_TYPE_COMPONENT:
 	tv_ctl |= TV_ENC_OUTPUT_COMPONENT;
 	break;
-    default:
     case TV_TYPE_SVIDEO:
 	tv_ctl |= TV_ENC_OUTPUT_SVIDEO;
 	break;
+    default:
+    case TV_TYPE_UNKNOWN:
+	tv_ctl |= TV_ENC_OUTPUT_SVIDEO_COMPOSITE;
+	break;
     }
     tv_ctl |= tv_mode->oversample;
     if (tv_mode->progressive)
@@ -366,11 +432,12 @@ i830_tv_post_set_mode(ScrnInfoPtr pScrn,
     if (sc_mode->pal_burst)
 	tv_ctl |= TV_PAL_BURST;
 
-    scctl1 = TV_SC_DDA1_EN | TV_SC_DDA1_EN;
+    scctl1 = TV_SC_DDA1_EN | TV_SC_DDA2_EN;
     if (sc_mode->dda3_size != 0)
 	scctl1 |= TV_SC_DDA3_EN;
     scctl1 |= sc_mode->sc_reset;
     /* XXX: set the burst level */
+    scctl1 |= 113 << TV_BURST_LEVEL_SHIFT;    /* from BIOS */
     scctl1 |= sc_mode->dda1_inc << TV_SCDDA1_INC_SHIFT;
 
     scctl2 = sc_mode->dda2_size << TV_SCDDA2_SIZE_SHIFT |
@@ -400,6 +467,28 @@ i830_tv_post_set_mode(ScrnInfoPtr pScrn,
     OUTREG(TV_SC_CTL_1, scctl1);
     OUTREG(TV_SC_CTL_2, scctl2);
     OUTREG(TV_SC_CTL_3, scctl3);
+    /* XXX match BIOS */
+    OUTREG(TV_CSC_Y, 0x0332012D);
+    OUTREG(TV_CSC_Y2, 0x07D30133);
+    OUTREG(TV_CSC_U, 0x076A0564);
+    OUTREG(TV_CSC_U2, 0x030D0200);
+    OUTREG(TV_CSC_V, 0x037A033D);
+    OUTREG(TV_CSC_V2, 0x06F60200);
+    OUTREG(TV_CLR_KNOBS, 0x00606000);
+    OUTREG(TV_CLR_LEVEL, 0x013C010A);
+    OUTREG(TV_WIN_POS, 0x00360024);
+    OUTREG(TV_WIN_SIZE, 0x02640198);
+    OUTREG(TV_FILTER_CTL_1, 0x8000085E);
+    OUTREG(TV_FILTER_CTL_2, 0x00017878);
+    OUTREG(TV_FILTER_CTL_3, 0x0000BC3C);
+    for (i = 0; i < 60; i++)
+	OUTREG(TV_H_LUMA_0 + (i <<2), h_luma[i]);
+    for (i = 0; i < 60; i++)
+	OUTREG(TV_H_CHROMA_0 + (i <<2), h_chroma[i]);
+    for (i = 0; i < 43; i++)
+	OUTREG(TV_V_LUMA_0 + (i <<2), v_luma[i]);
+    for (i = 0; i < 43; i++)
+	OUTREG(TV_V_CHROMA_0 + (i <<2), v_chroma[i]);
 
     OUTREG(TV_DAC, 0);
     OUTREG(TV_CTL, tv_ctl);
@@ -414,7 +503,7 @@ i830_tv_post_set_mode(ScrnInfoPtr pScrn,
 static enum detect_status
 i830_tv_detect(ScrnInfoPtr pScrn, I830OutputPtr output)
 {
-    return OUTPUT_STATUS_UNKNOWN;
+    return OUTPUT_STATUS_CONNECTED;
 }
 
 /**
@@ -426,31 +515,74 @@ i830_tv_detect(ScrnInfoPtr pScrn, I830Ou
 static DisplayModePtr
 i830_tv_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output)
 {
-    return NULL;
+    I830Ptr pI830 = I830PTR(pScrn);
+    DisplayModePtr new;
+    char stmp[32];
+
+    (void) pI830;
+    new             = xnfcalloc(1, sizeof (DisplayModeRec));
+    sprintf(stmp, "480i");
+    new->name       = xnfalloc(strlen(stmp) + 1);
+    strcpy(new->name, stmp);
+    
+    new->Clock      = 108000;
+    
+    /*
+    new->HDisplay   = 640;
+    new->HSyncStart = 664;
+    new->HSyncEnd   = 704;
+    new->HTotal     = 832;
+    
+    new->VDisplay   = 480;
+    new->VSyncStart = 489;
+    new->VSyncEnd   = 491;
+    new->VTotal     = 520;
+     */
+    new->HDisplay   = 1024;
+    new->HSyncStart = 1048;
+    new->HSyncEnd   = 1184;
+    new->HTotal     = 1344;
+    
+    new->VDisplay   = 768;
+    new->VSyncStart = 771;
+    new->VSyncEnd   = 777;
+    new->VTotal     = 806;
+
+    new->type       = M_T_PREFERRED;
+
+    return new;
 }
 
 void
 i830_tv_init(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-
+    I830OutputPtr output = &pI830->output[pI830->num_outputs];
+    struct i830_tv_priv *dev_priv;
+ 
     if ((INREG(TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED)
 	return;
 
-    pI830->output[pI830->num_outputs].dev_priv =
-	malloc(sizeof(struct i830_tv_priv));
-    if (pI830->output[pI830->num_outputs].dev_priv == NULL)
+    output->type = I830_OUTPUT_TVOUT;
+    output->pipe = 0;
+    output->enabled = FALSE;
+    output->load_detect_temp = FALSE;
+    
+    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 (dev_priv == NULL)
 	return;
 
-    pI830->output[pI830->num_outputs].type = I830_OUTPUT_ANALOG;
-    pI830->output[pI830->num_outputs].dpms = i830_tv_dpms;
-    pI830->output[pI830->num_outputs].save = i830_tv_save;
-    pI830->output[pI830->num_outputs].restore = i830_tv_restore;
-    pI830->output[pI830->num_outputs].mode_valid = i830_tv_mode_valid;
-    pI830->output[pI830->num_outputs].pre_set_mode = i830_tv_pre_set_mode;
-    pI830->output[pI830->num_outputs].post_set_mode = i830_tv_post_set_mode;
-    pI830->output[pI830->num_outputs].detect = i830_tv_detect;
-    pI830->output[pI830->num_outputs].get_modes = i830_tv_get_modes;
-
+    output->dev_priv = dev_priv;
+    ErrorF ("TV out is output %d\n", pI830->num_outputs);
     pI830->num_outputs++;
 }
diff-tree 816fc1a76a5ac738e41b172ba8f43137c1521328 (from parents)
Merge: 9948d8377d70e898260c12210151b952b3fb8bf1 7a7bb331e10498e5b8ccec58130bb23334d36562
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Nov 17 00:05:53 2006 -0800

    Merge branch 'modesetting-origin' into modesetting

diff-tree 7a7bb331e10498e5b8ccec58130bb23334d36562 (from c4508c1cadf323e9ef1d0e69dd77d5e841a6a978)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Nov 16 21:19:20 2006 -0800

    Don't dereference null DisplayModePtr on disabled output.
    
    During initial configuration, outputs which are disabled have null
    modes.

diff --git a/src/i830_randr.c b/src/i830_randr.c
index e01ac1e..d27125f 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -1266,7 +1266,8 @@ I830RandRPreInit (ScrnInfoPtr pScrn)
 	    pipe = 0;
 	    enabled = FALSE;
 	}
-	pI830->pipes[pipe].desiredMode = *mode;
+	if (mode)
+	    pI830->pipes[pipe].desiredMode = *mode;
 	pI830->output[o].pipe = pipe;
 	pI830->output[o].enabled = enabled;
     }
diff-tree c4508c1cadf323e9ef1d0e69dd77d5e841a6a978 (from 45a27f80e1c783627f570c309e7a853dcc9af0c1)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Nov 16 21:09:23 2006 -0800

    RandR-based initial output configuration.
    
    Using pre-init computed RandR information, make reasonable
    default choices for the output configuration at startup time.
    Either some preferred size or a size which yields 96dpi is chosen,
    from which other monitors are set to a similar size. The largest
    size sets the screen size.
    
    This needs to be extended to respect config file settings, but
    those have not been defined yet.

diff --git a/src/i830.h b/src/i830.h
index 96f0c29..f22be40 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -283,6 +283,7 @@ typedef struct _I830PipeRec {
    Bool		  cursorInRange;
    Bool		  cursorShown;
    DisplayModeRec curMode;
+   DisplayModeRec desiredMode;
 #ifdef RANDR_12_INTERFACE
    RRCrtcPtr	  randr_crtc;
 #endif
@@ -673,6 +674,8 @@ DisplayModePtr i830GetGTF(int h_pixels, 
 /* i830_modes.c */
 int I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time);
 void i830_reprobe_output_modes(ScrnInfoPtr pScrn);
+void i830_set_xf86_modes_from_outputs(ScrnInfoPtr pScrn);
+void i830_set_default_screen_size(ScrnInfoPtr pScrn);
 DisplayModePtr i830_ddc_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output);
 
 /* i830_randr.c */
diff --git a/src/i830_display.c b/src/i830_display.c
index a0809eb..bd40e4e 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -290,7 +290,7 @@ i830PipeSetBase(ScrnInfoPtr pScrn, int p
  * - Closer in size to the requested mode, but no larger
  * - Closer in refresh rate to the requested mode.
  */
-static DisplayModePtr
+DisplayModePtr
 i830PipeFindClosestMode(ScrnInfoPtr pScrn, int pipe, DisplayModePtr pMode)
 {
     I830Ptr pI830 = I830PTR(pScrn);
diff --git a/src/i830_display.h b/src/i830_display.h
index 67f3c7b..361a3c6 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -26,6 +26,8 @@
  */
 
 /* i830_display.c */
+DisplayModePtr
+i830PipeFindClosestMode(ScrnInfoPtr pScrn, int pipe, DisplayModePtr pMode);
 Bool i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe,
 		     Bool plane_enable);
 void i830DisableUnusedFunctions(ScrnInfoPtr pScrn);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 0ea20e4..5da4742 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3304,12 +3304,33 @@ I830EnterVT(int scrnIndex, int flags)
    ResetState(pScrn, FALSE);
    SetHWOperatingState(pScrn);
 
-   /* Mark that we'll need to re-set the mode for sure */
    for (i = 0; i < pI830->num_pipes; i++)
-      memset(&pI830->pipes[i].curMode, 0, sizeof(pI830->pipes[i].curMode));
+   {
+      I830PipePtr pipe = &pI830->pipes[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))
+	 return FALSE;
+      i830PipeSetBase(pScrn, i, pipe->x, pipe->y);
+   }
+
+   i830DisableUnusedFunctions(pScrn);
 
+   i830DescribeOutputConfiguration(pScrn);
+
+#ifdef XF86DRI
+   I830DRISetVBlankInterrupt (pScrn, TRUE);
+#endif
+   
+#if 0
    if (!i830SetMode(pScrn, pScrn->currentMode))
       return FALSE;
+#endif
    
 #ifdef I830_XV
    I830VideoSwitchModeAfter(pScrn, pScrn->currentMode);
diff --git a/src/i830_modes.c b/src/i830_modes.c
index 77db66c..7fdd40e 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -490,7 +490,7 @@ i830_reprobe_output_modes(ScrnInfoPtr pS
  *
  * This should be obsoleted by RandR 1.2 hopefully.
  */
-static void
+void
 i830_set_xf86_modes_from_outputs(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
@@ -557,7 +557,7 @@ i830_set_xf86_modes_from_outputs(ScrnInf
  * Takes the output mode lists and decides the default root window size
  * and framebuffer pitch.
  */
-static void
+void
 i830_set_default_screen_size(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
diff --git a/src/i830_randr.c b/src/i830_randr.c
index f579f41..e01ac1e 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -609,6 +609,7 @@ I830RandRCrtcSet (ScreenPtr	pScreen,
 		}
 		return FALSE;
 	    }
+	    pI830Pipe->desiredMode = *display_mode;
 	    i830PipeSetBase(pScrn, pipe, x, y);
 	}
 	randrp->modes[pipe] = display_mode;
@@ -840,11 +841,6 @@ I830RandRCreateObjects12 (ScrnInfoPtr pS
 	    return FALSE;
 	output->randr_output = randr_output;
     }
-    /*
-     * Configure output modes
-     */
-    if (!I830RandRSetInfo12 (pScrn))
-	return FALSE;
     return TRUE;
 }
 
@@ -855,7 +851,7 @@ I830RandRCreateScreenResources12 (Screen
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
     I830Ptr		pI830 = I830PTR(pScrn);
     int			p, o;
-    DisplayModePtr	mode;
+    int			width, height;
 
     /*
      * Attach RandR objects to screen
@@ -868,33 +864,43 @@ I830RandRCreateScreenResources12 (Screen
 	if (!RROutputAttachScreen (pI830->output[o].randr_output, pScreen))
 	    return FALSE;
 
-    mode = pScrn->currentMode;
-    if (mode)
+    /*
+     * Compute width of 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;
+    }
+    
+    if (width && height)
     {
 	int mmWidth, mmHeight;
 
 	mmWidth = pScreen->mmWidth;
 	mmHeight = pScreen->mmHeight;
-	if (mode->HDisplay != pScreen->width)
-	    mmWidth = mmWidth * mode->HDisplay / pScreen->width;
-	if (mode->VDisplay != pScreen->height)
-	    mmHeight = mmHeight * mode->VDisplay / pScreen->height;
+	if (width != pScreen->width)
+	    mmWidth = mmWidth * width / pScreen->width;
+	if (height != pScreen->height)
+	    mmHeight = mmHeight * height / pScreen->height;
 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		   "Setting screen physical size to %d x %d\n",
 		   mmWidth, mmHeight);
 	I830RandRScreenSetSize (pScreen,
-				mode->HDisplay,
-				mode->VDisplay,
+				width,
+				height,
 				mmWidth,
 				mmHeight);
     }
 
     for (p = 0; p < pI830->num_pipes; p++)
-    {
-	i830PipeSetBase(pScrn, p, 0, 0);
 	I830RandRCrtcNotify (pI830->pipes[p].randr_crtc);
-    }
-
     
     if (randrp->virtualX == -1 || randrp->virtualY == -1)
     {
@@ -926,19 +932,348 @@ I830RandRInit12 (ScreenPtr pScreen)
     pScrn->PointerMoved = I830RandRPointerMoved;
     return TRUE;
 }
+
+static RRModePtr
+I830RRDefaultMode (RROutputPtr output)
+{
+    RRModePtr   target_mode = NULL;
+    int		target_diff = 0;
+    int		mmHeight;
+    int		num_modes;
+    int		m;
+    
+    num_modes = output->numPreferred ? output->numPreferred : output->numModes;
+    mmHeight = output->mmHeight;
+    if (!mmHeight)
+	mmHeight = 203;	/* 768 pixels at 96dpi */
+    /*
+     * Pick a mode closest to 96dpi 
+     */
+    for (m = 0; m < num_modes; m++)
+    {
+	RRModePtr   mode = output->modes[m];
+	int	    dpi;
+	int	    diff;
+
+	dpi = (mode->mode.height * 254) / (mmHeight * 10);
+	diff = dpi - 96;
+	diff = diff < 0 ? -diff : diff;
+	if (target_mode == NULL || diff < target_diff)
+	{
+	    target_mode = mode;
+	    target_diff = diff;
+	}
+    }
+    return target_mode;
+}
+
+static RRModePtr
+I830ClosestMode (RROutputPtr output, RRModePtr match)
+{
+    RRModePtr   target_mode = NULL;
+    int		target_diff = 0;
+    int		m;
+    
+    /*
+     * Pick a mode closest to the specified mode
+     */
+    for (m = 0; m < output->numModes; m++)
+    {
+	RRModePtr   mode = output->modes[m];
+	int	    dx, dy;
+	int	    diff;
+
+	/* exact matches are preferred */
+	if (mode == match)
+	    return mode;
+	
+	dx = match->mode.width - mode->mode.width;
+	dy = match->mode.height - mode->mode.height;
+	diff = dx * dx + dy * dy;
+	if (target_mode == NULL || diff < target_diff)
+	{
+	    target_mode = mode;
+	    target_diff = diff;
+	}
+    }
+    return target_mode;
+}
+
+static int
+I830RRPickCrtcs (RROutputPtr	*outputs,
+		 RRCrtcPtr	*best_crtcs,
+		 RRModePtr	*modes,
+		 int		num_outputs,
+		 int		n)
+{
+    int		c, o, l;
+    RROutputPtr	output;
+    RRCrtcPtr	crtc;
+    RRCrtcPtr	*crtcs;
+    RRCrtcPtr	best_crtc;
+    int		best_score;
+    int		score;
+    int		my_score;
+    
+    if (n == num_outputs)
+	return 0;
+    output = outputs[n];
+    
+    /*
+     * Compute score with this output disabled
+     */
+    best_crtcs[n] = NULL;
+    best_crtc = NULL;
+    best_score = I830RRPickCrtcs (outputs, best_crtcs, modes, num_outputs, n+1);
+    if (modes[n] == NULL)
+	return best_score;
+    
+    crtcs = xalloc (num_outputs * sizeof (RRCrtcPtr));
+    if (!crtcs)
+	return best_score;
+
+    my_score = 1;
+    /* Score outputs that are known to be connected higher */
+    if (output->connection == RR_Connected)
+	my_score++;
+    /* Score outputs with preferred modes higher */
+    if (output->numPreferred)
+	my_score++;
+    /*
+     * Select a crtc for this output and
+     * then attempt to configure the remaining
+     * outputs
+     */
+    for (c = 0; c < output->numCrtcs; c++)
+    {
+	crtc = output->crtcs[c];
+	/*
+	 * Check to see if some other output is
+	 * using this crtc
+	 */
+	for (o = 0; o < n; o++)
+	    if (best_crtcs[o] == crtc)
+		break;
+	if (o < n)
+	{
+	    /*
+	     * If the two outputs desire the same mode,
+	     * see if they can be cloned
+	     */
+	    if (modes[o] == modes[n])
+	    {
+		for (l = 0; l < output->numClones; l++)
+		    if (output->clones[l] == outputs[o])
+			break;
+		if (l == output->numClones)
+		    continue;		/* nope, try next CRTC */
+	    }
+	    else
+		continue;		/* different modes, can't clone */
+	}
+	crtcs[n] = crtc;
+	memcpy (crtcs, best_crtcs, n * sizeof (RRCrtcPtr));
+	score = my_score + I830RRPickCrtcs (outputs, crtcs, modes,
+					    num_outputs, n+1);
+	if (score >= best_score)
+	{
+	    best_crtc = crtc;
+	    best_score = score;
+	    memcpy (best_crtcs, crtcs, num_outputs * sizeof (RRCrtcPtr));
+	}
+    }
+    xfree (crtcs);
+    return best_score;
+}
+
+static Bool
+I830RRInitialConfiguration (RROutputPtr *outputs,
+			    RRCrtcPtr	*crtcs,
+			    RRModePtr	*modes,
+			    int		num_outputs)
+{
+    int		o;
+    RRModePtr	target_mode = NULL;
+
+    for (o = 0; o < num_outputs; o++)
+	modes[o] = NULL;
+    
+    /*
+     * Let outputs with preferred modes drive screen size
+     */
+    for (o = 0; o < num_outputs; o++)
+    {
+	RROutputPtr output = outputs[o];
+
+	if (output->connection != RR_Disconnected && output->numPreferred)
+	{
+	    target_mode = I830RRDefaultMode (output);
+	    if (target_mode)
+	    {
+		modes[o] = target_mode;
+		break;
+	    }
+	}
+    }
+    if (!target_mode)
+    {
+	for (o = 0; o < num_outputs; o++)
+	{
+	    RROutputPtr output = outputs[o];
+	    if (output->connection != RR_Disconnected)
+	    {
+		target_mode = I830RRDefaultMode (output);
+		if (target_mode)
+		{
+		    modes[o] = target_mode;
+		    break;
+		}
+	    }
+	}
+    }
+    for (o = 0; o < num_outputs; o++)
+    {
+	RROutputPtr output = outputs[o];
+	
+	if (output->connection != RR_Disconnected && !modes[o])
+	    modes[o] = I830ClosestMode (output, target_mode);
+    }
+
+    if (!I830RRPickCrtcs (outputs, crtcs, modes, num_outputs, 0))
+	return FALSE;
+    
+    return TRUE;
+}
+
+/*
+ * Compute the virtual size necessary to place all of the available
+ * crtcs in a panorama configuration
+ */
+
+static void
+I830RRDefaultScreenLimits (RROutputPtr *outputs, int num_outputs,
+			   RRCrtcPtr *crtcs, int num_crtc,
+			   int *widthp, int *heightp)
+{
+    int	    width = 0, height = 0;
+    int	    o;
+    int	    c;
+    int	    m;
+    int	    s;
+
+    for (c = 0; c < num_crtc; c++)
+    {
+	RRCrtcPtr   crtc = crtcs[c];
+	int	    crtc_width = 1600, crtc_height = 1200;
+
+	for (o = 0; o < num_outputs; o++) 
+	{
+	    RROutputPtr	output = outputs[o];
+
+	    for (s = 0; s < output->numCrtcs; s++)
+		if (output->crtcs[s] == crtc)
+		    break;
+	    if (s == output->numCrtcs)
+		continue;
+	    for (m = 0; m < output->numModes; m++)
+	    {
+		RRModePtr   mode = output->modes[m];
+		if (mode->mode.width > crtc_width)
+		    crtc_width = mode->mode.width;
+		if (mode->mode.height > crtc_width)
+		    crtc_height = mode->mode.height;
+	    }
+	}
+	width += crtc_width;
+	if (crtc_height > height)
+	    height = crtc_height;
+    }
+    *widthp = width;
+    *heightp = height;
+}
+
 #endif
 
 Bool
 I830RandRPreInit (ScrnInfoPtr pScrn)
 {
-    int n;
+    I830Ptr pI830 = I830PTR(pScrn);
+#if RANDR_12_INTERFACE
+    RROutputPtr	outputs[MAX_OUTPUTS];
+    RRCrtcPtr	output_crtcs[MAX_OUTPUTS];
+    RRModePtr	output_modes[MAX_OUTPUTS];
+    RRCrtcPtr	crtcs[MAX_DISPLAY_PIPES];
+    int		width, height;
+    int		o;
+    int		c;
+#endif
     
-    n = I830ValidateXF86ModeList(pScrn, TRUE);
-    if (n <= 0)
+    if (pI830->num_outputs <= 0)
 	return FALSE;
+    
+    i830_reprobe_output_modes(pScrn);
+
 #if RANDR_12_INTERFACE
     if (!I830RandRCreateObjects12 (pScrn))
 	return FALSE;
+
+    /*
+     * Configure output modes
+     */
+    if (!I830RandRSetInfo12 (pScrn))
+	return FALSE;
+    /*
+     * With RandR info set up, let RandR choose
+     * the initial configuration
+     */
+    for (o = 0; o < pI830->num_outputs; o++)
+	outputs[o] = pI830->output[o].randr_output;
+    for (c = 0; c < pI830->num_pipes; c++)
+	crtcs[c] = pI830->pipes[c].randr_crtc;
+    
+    if (!I830RRInitialConfiguration (outputs, output_crtcs, output_modes,
+				     pI830->num_outputs))
+	return FALSE;
+    
+    I830RRDefaultScreenLimits (outputs, pI830->num_outputs, 
+			       crtcs, pI830->num_pipes,
+			       &width, &height);
+    
+    if (width > pScrn->virtualX)
+	pScrn->virtualX = width;
+    if (height > pScrn->virtualY)
+	pScrn->virtualY = height;
+    
+    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;
+
+	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;
+	}
+	pI830->pipes[pipe].desiredMode = *mode;
+	pI830->output[o].pipe = pipe;
+	pI830->output[o].enabled = enabled;
+    }
 #endif
+    i830_set_xf86_modes_from_outputs (pScrn);
+    
+    i830_set_default_screen_size(pScrn);
+
     return TRUE;
 }
diff-tree 9948d8377d70e898260c12210151b952b3fb8bf1 (from parents)
Merge: 45a27f80e1c783627f570c309e7a853dcc9af0c1 b649f95ea6fd3555d073fdbf8f2f035dfe1afd33
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Nov 16 19:47:24 2006 -0800

    Merge branch 'master' into modesetting
    
    Conflicts:
    
    	src/i830.h
    	src/i830_cursor.c
    	src/i830_dri.c
    	src/i830_driver.c
    	src/i830_video.c

diff --cc configure.ac
index 257f97b,fc0f9cd..b1dd287
@@@ -113,16 -118,22 +118,21 @@@
  	-Wnested-externs -fno-strict-aliasing"
  fi
  
 -CFLAGS="$CFLAGS $WARN_CFLAGS"
 -
  AM_CONDITIONAL(DRI, test x$DRI = xyes)
  if test "$DRI" = yes; then
-         PKG_CHECK_MODULES(DRI, [libdrm >= 2.0 xf86driproto])
+         PKG_CHECK_MODULES(DRI, [libdrm >= 2.2 xf86driproto])
          AC_DEFINE(XF86DRI,1,[Enable DRI driver support])
          AC_DEFINE(XF86DRI_DEVEL,1,[Enable developmental DRI driver support])
  fi
  
+ AM_CONDITIONAL(VIDEO_DEBUG, test x$VIDEO_DEBUG = xyes)
+ if test "$VIDEO_DEBUG" = yes; then
+ 	AC_DEFINE(VIDEO_DEBUG,1,[Enable debug support])
+ fi
+ 
  AC_SUBST([DRI_CFLAGS])
  AC_SUBST([XORG_CFLAGS])
 +AC_SUBST([WARN_CFLAGS])
  AC_SUBST([moduledir])
  
  DRIVER_NAME=i810
diff --cc src/i830.h
index 96f0c29,0df41e3..ea7f1c0
@@@ -86,6 -84,36 +86,13 @@@
   * Paulo César Pereira de Andrade <pcpa at conectiva.com.br>.
   */
  
 -#define PIPE_NONE	0<<0
 -#define PIPE_CRT	1<<0
 -#define PIPE_TV		1<<1
 -#define PIPE_DFP	1<<2
 -#define PIPE_LFP	1<<3
 -#define PIPE_CRT2	1<<4
 -#define PIPE_TV2	1<<5
 -#define PIPE_DFP2	1<<6
 -#define PIPE_LFP2	1<<7
 -
 -typedef struct _VESARec {
 -   /* SVGA state */
 -   pointer state, pstate;
 -   int statePage, stateSize, stateMode, stateRefresh;
 -   CARD32 *savedPal;
 -   int savedScanlinePitch;
 -   /* Don't try to set the refresh rate for any modes. */
 -   Bool useDefaultRefresh;
 -   /* display start */
 -   int x, y;
 -} VESARec, *VESAPtr;
 -
 -
+ #ifdef XF86DRI
+ #define I830_MM_MINPAGES 512
+ #define I830_MM_MAXSIZE  (32*1024)
+ #define I830_KERNEL_MM  (1 << 0) /* Initialize the kernel memory manager*/
+ #define I830_KERNEL_TEX (1 << 1) /* Allocate texture memory pool */
+ #endif
+ 
  typedef struct _I830Rec *I830Ptr;
  
  typedef void (*I830WriteIndexedByteFunc)(I830Ptr pI830, IOADDRESS addr,
@@@ -719,12 -582,10 +728,18 @@@
  #define _845_DRAM_RW_CONTROL 0x90
  #define DRAM_WRITE    0x33330000
  
 +/* Compat definitions for older X Servers. */
 +#ifndef M_T_PREFERRED
 +#define M_T_PREFERRED	0x08
 +#endif
 +#ifndef M_T_DRIVER
 +#define M_T_DRIVER	0x40
 +#endif
 +
+ /* 
+  * Xserver MM compatibility. Remove code guarded by this when the
+  * XServer contains the libdrm mm code
+  */
+ #undef XSERVER_LIBDRM_MM
+ 
  #endif /* _I830_H_ */
diff --cc src/i830_dri.c
index 9e4ead0,524c4de..6b17f46
@@@ -1485,9 -1513,12 +1513,13 @@@
  
      if (pI830->directRenderingEnabled && pI830->drmMinor >= 5) {
  	if (on) {
- 	    if (pI830->pipes[1].enabled)
 -	    if (pI830->planeEnabled[1]) {
++	    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;
 +		pipe.pipe = DRM_I830_VBLANK_PIPE_B;
- 	    else
+ 	    } else
  		pipe.pipe = DRM_I830_VBLANK_PIPE_A;
  	} else {
  	    pipe.pipe = 0;
diff --cc src/i830_driver.c
index 0ea20e4,e950d7c..f5b403a
@@@ -263,9 -265,17 +265,11 @@@
     OPTION_FIXEDPIPE,
     OPTION_ROTATE,
     OPTION_LINEARALLOC,
 -   OPTION_MERGEDFB,
 -   OPTION_METAMODES,
 -   OPTION_SECONDHSYNC,
 -   OPTION_SECONDVREFRESH,
 -   OPTION_SECONDPOSITION,
 -   OPTION_INTELXINERAMA,
+    OPTION_INTELTEXPOOL,
+    OPTION_INTELMMSIZE
  } I830Opts;
  
 -static OptionInfoRec I830BIOSOptions[] = {
 +static OptionInfoRec I830Options[] = {
     {OPTION_NOACCEL,	"NoAccel",	OPTV_BOOLEAN,	{0},	FALSE},
     {OPTION_SW_CURSOR,	"SWcursor",	OPTV_BOOLEAN,	{0},	FALSE},
     {OPTION_CACHE_LINES,	"CacheLines",	OPTV_INTEGER,	{0},	FALSE},
@@@ -281,6 -294,14 +285,8 @@@
     {OPTION_FIXEDPIPE,   "FixedPipe",    OPTV_ANYSTR, 	{0},	FALSE},
     {OPTION_ROTATE,      "Rotate",       OPTV_ANYSTR,    {0},    FALSE},
     {OPTION_LINEARALLOC, "LinearAlloc",  OPTV_INTEGER,   {0},    FALSE},
 -   {OPTION_MERGEDFB, 	"MergedFB",	OPTV_BOOLEAN,	{0},	FALSE},
 -   {OPTION_METAMODES, 	"MetaModes",	OPTV_STRING,	{0},	FALSE},
 -   {OPTION_SECONDHSYNC,	"SecondMonitorHorizSync",OPTV_STRING,	{0}, FALSE },
 -   {OPTION_SECONDVREFRESH,"SecondMonitorVertRefresh",OPTV_STRING,{0}, FALSE },
 -   {OPTION_SECONDPOSITION,"SecondPosition",OPTV_STRING,	{0},	FALSE },
 -   {OPTION_INTELXINERAMA,"MergedXinerama",OPTV_BOOLEAN,	{0},	TRUE},
+    {OPTION_INTELTEXPOOL,"Legacy3D",     OPTV_BOOLEAN,	{0},	FALSE},
+    {OPTION_INTELMMSIZE, "AperTexSize",  OPTV_INTEGER,	{0},	FALSE},
     {-1,			NULL,		OPTV_NONE,	{0},	FALSE}
  };
  /* *INDENT-ON* */
@@@ -741,33 -3831,30 +747,54 @@@
     return TRUE;
  }
  
 +#define HOTKEY_BIOS_SWITCH	0
 +#define HOTKEY_DRIVER_NOTIFY	1
 +
 +/**
 + * Controls the BIOS's behavior on hotkey switch.
 + *
 + * If the mode is HOTKEY_BIOS_SWITCH, the BIOS will be set to do a mode switch
 + * on its own and update the state in the scratch register.
 + * If the mode is HOTKEY_DRIVER_NOTIFY, the BIOS won't do a mode switch and
 + * will just update the state to represent what it would have been switched to.
 + */
 +static void
 +i830SetHotkeyControl(ScrnInfoPtr pScrn, int mode)
 +{
 +   I830Ptr pI830 = I830PTR(pScrn);
 +   CARD8 gr18;
 +
 +   gr18 = pI830->readControl(pI830, GRX, 0x18);
 +   if (mode == HOTKEY_BIOS_SWITCH)
 +      gr18 &= ~HOTKEY_VBIOS_SWITCH_BLOCK;
 +   else
 +      gr18 |= HOTKEY_VBIOS_SWITCH_BLOCK;
 +   pI830->writeControl(pI830, GRX, 0x18, gr18);
 +}
 +
+ #ifdef XF86DRI
+ static void 
+ I830ReduceMMSize(ScrnInfoPtr pScrn, unsigned long newSize,
+ 		 const char *reason)
+ {
+    I830Ptr pI830 = I830PTR(pScrn);
+ 
+    newSize = ROUND_DOWN_TO(newSize, GTT_PAGE_SIZE);
+    if (newSize / GTT_PAGE_SIZE > I830_MM_MINPAGES) {
+       pI830->mmSize = newSize / 1024;
+       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ 		 "DRM memory manager aperture size is reduced to %d kiB\n"
+ 		 "\t%s\n", pI830->mmSize, reason);
+    } else {
+       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ 		 "DRM memory manager will be disabled\n\t%s\n", reason);
+       pI830->mmSize = 0;
+    }
+ }
+ #endif
+ 
 -
  static Bool
 -I830BIOSPreInit(ScrnInfoPtr pScrn, int flags)
 +I830PreInit(ScrnInfoPtr pScrn, int flags)
  {
     vgaHWPtr hwp;
     I830Ptr pI830;
@@@ -775,14 -3862,22 +802,17 @@@
     rgb defaultWeight = { 0, 0, 0 };
     EntityInfoPtr pEnt;
     I830EntPtr pI830Ent = NULL;					
 -   int mem, memsize;
 +   int mem;
     int flags24;
 -   int defmon = 0;
 -   int i, n;
 -   int DDCclock = 0, DDCclock2 = 0;
 +   int i;
     char *s;
 -   DisplayModePtr p, pMon;
 -   xf86MonPtr monitor = NULL;
 -   pointer pDDCModule = NULL, pVBEModule = NULL;
 +   pointer pVBEModule = NULL;
     Bool enable;
     const char *chipname;
 -   unsigned int ver;
 -   char v[5];
 +   int mem_skip;
+ #ifdef XF86DRI
+    unsigned long savedMMSize;
+ #endif
  
     if (pScrn->numEntities != 1)
        return FALSE;
@@@ -1819,10 -5560,36 +1910,20 @@@
  #endif
        pI830->disableTiling = TRUE; /* no DRI - so disableTiling */
  
+    if (pScrn->displayWidth >= 4096) {
+       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot support > 1024x768 in leftof/rightof configurations. disabling DRI.\n");
+       pI830->directRenderingDisabled = TRUE;
+    }
+ 
+    if (pScrn->virtualY > 2048) {
+       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot support > 2048 vertical lines. disabling acceleration.\n");
+       pI830->noAccel = TRUE;
+    }
+ 
     pI830->displayWidth = pScrn->displayWidth;
  
 -   SetPipeAccess(pScrn);
     I830PrintModes(pScrn);
  
 -   if (!pI830->vesa->useDefaultRefresh) {
 -      /*
 -       * This sets the parameters for the VBE modes according to the best
 -       * usable parameters from the Monitor sections modes (usually the
 -       * default VESA modes), allowing for better than default refresh rates.
 -       * This only works for VBE 3.0 and later.  Also, we only do this
 -       * if there are no non-CRT devices attached.
 -       */
 -      SetPipeAccess(pScrn);
 -      I830SetModeParameters(pScrn, pI830->pVbe);
 -   }
 -
 -   /* PreInit shouldn't leave any state changes, so restore this. */
 -   RestoreBIOSMemSize(pScrn);
 -
     /* Don't need MMIO access anymore. */
     if (pI830->swfSaved) {
        OUTREG(SWF0, pI830->saveSWF0);
@@@ -2732,8 -7112,89 +2833,89 @@@
     }
  }
  
+ #ifdef XF86DRI
+ #ifndef DRM_BO_MEM_TT
+ #error "Wrong drm.h file included. You need to compile and install a recent libdrm."
+ #endif
+ 
+ #ifndef XSERVER_LIBDRM_MM
+ 
+ static int
+ I830DrmMMInit(int drmFD, unsigned long pageOffs, unsigned long pageSize,
+ 	      unsigned memType)
+ {
+ 
+    drm_mm_init_arg_t arg;
+    int ret;
+    
+    memset(&arg, 0, sizeof(arg));
+    arg.req.op = mm_init;
+    arg.req.p_offset = pageOffs;
+    arg.req.p_size = pageSize;
+    arg.req.mem_type = memType;
+ 
+    ret = ioctl(drmFD, DRM_IOCTL_MM_INIT, &arg);
+    
+    if (ret)
+       return -errno;
+    
+    return 0;
+    
+ }
+ 
+ static int
+ I830DrmMMTakedown(int drmFD, unsigned memType)
+ {
+    drm_mm_init_arg_t arg;
+    int ret = 0;
+    
+    memset(&arg, 0, sizeof(arg));
+    arg.req.op = mm_takedown;
+    arg.req.mem_type = memType;
+    if (ioctl(drmFD, DRM_IOCTL_MM_INIT, &arg)) {
+       ret = -errno;
+    }
+    
+    return ret;
+ }
+ 
+ static int I830DrmMMLock(int fd, unsigned memType)
+ {
+     drm_mm_init_arg_t arg;
+     int ret;
+ 
+     memset(&arg, 0, sizeof(arg));
+     arg.req.op = mm_lock;
+     arg.req.mem_type = memType;
+ 
+     do{
+ 	ret = ioctl(fd, DRM_IOCTL_MM_INIT, &arg);
+     } while (ret && errno == EAGAIN);
+     
+     return ret;	
+ }
+ 
+ static int I830DrmMMUnlock(int fd, unsigned memType)
+ {
+     drm_mm_init_arg_t arg;
+     int ret;
+ 
+     memset(&arg, 0, sizeof(arg));
+     arg.req.op = mm_unlock;
+     arg.req.mem_type = memType;
+ 
+     do{
+ 	ret = ioctl(fd, DRM_IOCTL_MM_INIT, &arg);
+     } while (ret && errno == EAGAIN);
+     
+     return ret;	
+ }
+ 
+ #endif
+ #endif
+ 
  static Bool
 -I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
 +I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
  {
     ScrnInfoPtr pScrn;
     vgaHWPtr hwp;
@@@ -3178,28 -7700,156 +3360,70 @@@
           break;
     }
  
+ 
+ #ifdef XF86DRI
+    if (pI830->directRenderingEnabled && (pI830->mmModeFlags & I830_KERNEL_MM)) {
+       unsigned long aperEnd = ROUND_DOWN_TO(pI830->FbMapSize, GTT_PAGE_SIZE) 
+ 	 / GTT_PAGE_SIZE;
+       unsigned long aperStart = ROUND_TO(pI830->FbMapSize - KB(pI830->mmSize), GTT_PAGE_SIZE) 
+ 	 / GTT_PAGE_SIZE;
+ 
+       if (aperEnd < aperStart || aperEnd - aperStart < I830_MM_MINPAGES) {
+ 	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 
+ 		    "Too little AGP aperture space for DRM memory manager.\n"
+ 		    "\tPlease increase AGP aperture size from BIOS configuration screen\n"
+ 		    "\tor decrease the amount of video RAM using option \"VideoRam\".\n"
+ 		    "\tDisabling DRI.\n");
+ 	 pI830->directRenderingOpen = FALSE;
+ 	 I830DRICloseScreen(pScreen);
+ 	 pI830->directRenderingEnabled = FALSE;
+       } else {
+ #ifndef XSERVER_LIBDRM_MM
+ 	 if (I830DrmMMInit(pI830->drmSubFD, aperStart, aperEnd - aperStart,
+ 			   DRM_BO_MEM_TT)) {
+ #else
+ 	 if (drmMMInit(pI830->drmSubFD, aperStart, aperEnd - aperStart,
+ 		       DRM_BO_MEM_TT)) {
+ #endif	   
+ 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 
+ 		       "Could not initialize the DRM memory manager.\n");
+ 	    
+ 	    pI830->directRenderingOpen = FALSE;
+ 	    I830DRICloseScreen(pScreen);
+ 	    pI830->directRenderingEnabled = FALSE;
+ 	 } else {
+ 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
+ 		       "Initialized DRM memory manager, %ld AGP pages\n"
+ 		       "\tat AGP offset 0x%lx\n", 
+ 		       aperEnd - aperStart,
+ 		       aperStart);
+ 	 }
+       }
+    }
 -#endif
 -
 -   return TRUE;
 -}
 -
 -
 -static void
 -I830AdjustFrame(int scrnIndex, int x, int y, int flags)
 -{
 -   ScrnInfoPtr pScrn;
 -   I830Ptr pI830;
 -   vbeInfoPtr pVbe;
 -   unsigned long Start;
 -
 -   pScrn = xf86Screens[scrnIndex];
 -   pI830 = I830PTR(pScrn);
 -   pVbe = pI830->pVbe;
 -
 -   DPRINTF(PFX, "I830AdjustFrame: y = %d (+ %d), x = %d (+ %d)\n",
 -	   x, pI830->xoffset, y, pI830->yoffset);
 -
 -   /* Sync the engine before adjust frame */
 -   if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
 -      (*pI830->AccelInfoRec->Sync)(pScrn);
 -      pI830->AccelInfoRec->NeedToSync = FALSE;
 -   }
 -
 -   if (pI830->MergedFB) {
 -      I830AdjustFrameMerged(scrnIndex, x, y, flags);
 -
 -      if (pI830->pipe == 0) {
 -         OUTREG(DSPABASE, pI830->FrontBuffer.Start + ((pI830->FirstframeY0 * pScrn->displayWidth + pI830->FirstframeX0) * pI830->cpp));
 -         OUTREG(DSPBBASE, pI830->FrontBuffer.Start + ((pI830->pScrn_2->frameY0 * pScrn->displayWidth + pI830->pScrn_2->frameX0) * pI830->cpp));
 -      } else {
 -         OUTREG(DSPBBASE, pI830->FrontBuffer.Start + ((pI830->FirstframeY0 * pScrn->displayWidth + pI830->FirstframeX0) * pI830->cpp));
 -         OUTREG(DSPABASE, pI830->FrontBuffer.Start + ((pI830->pScrn_2->frameY0 * pScrn->displayWidth + pI830->pScrn_2->frameX0) * pI830->cpp));
 -      }
 -
 -      return;
 -   }
 -
 -   if (I830IsPrimary(pScrn))
 -      Start = pI830->FrontBuffer.Start;
 -   else {
 -      I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
 -      Start = pI8301->FrontBuffer2.Start;
 -   }
 -
 -   /* Sigh...
 -    * It seems that there are quite a few Video BIOS' that get this wrong.
 -    * So, we'll bypass the VBE call and hit the hardware directly.
 -    */
 -
 -   if (pI830->Clone) {
 -      if (!pI830->pipe == 0) {
 -         if (!IS_I965G(pI830)) {
 -            OUTREG(DSPABASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
 -         } else {
 -            OUTREG(DSPABASE, 0);
 -            OUTREG(DSPASURF, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
 -         }
 -      } else {
 -         if (!IS_I965G(pI830)) {
 -            OUTREG(DSPBBASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
 -         } else {
 -            OUTREG(DSPBBASE, 0);
 -            OUTREG(DSPBSURF, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
 -         }
 -      }
 -   }
 -
 -   if (pI830->pipe == 0) {
 -      if (!IS_I965G(pI830)) {
 -         OUTREG(DSPABASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
 -      } else {
 -         OUTREG(DSPABASE, 0);
 -         OUTREG(DSPASURF, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
 -      }
 -   } else {
 -      if (!IS_I965G(pI830)) {
 -         OUTREG(DSPBBASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
 -      } else {
 -         OUTREG(DSPBBASE, 0);
 -         OUTREG(DSPBSURF, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
 -      }
 -   }
 -}
++#endif
+ 
 -static void
 -I830BIOSFreeScreen(int scrnIndex, int flags)
 -{
 -   I830BIOSFreeRec(xf86Screens[scrnIndex]);
 -   if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
 -      vgaHWFreeHWRec(xf86Screens[scrnIndex]);
 +   return TRUE;
  }
  
 -#ifndef SAVERESTORE_HWSTATE
 -#define SAVERESTORE_HWSTATE 0
 -#endif
 -
 -#if SAVERESTORE_HWSTATE
  static void
 -SaveHWOperatingState(ScrnInfoPtr pScrn)
 +i830AdjustFrame(int scrnIndex, int x, int y, int flags)
  {
 +   ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
     I830Ptr pI830 = I830PTR(pScrn);
 -   I830RegPtr save = &pI830->SavedReg;
 +   int i;
 +
 +   DPRINTF(PFX, "i830AdjustFrame: y = %d (+ %d), x = %d (+ %d)\n",
 +	   x, pI830->xoffset, y, pI830->yoffset);
  
 -   DPRINTF(PFX, "SaveHWOperatingState\n");
 +   /* Sync the engine before adjust frame */
 +   if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
 +      (*pI830->AccelInfoRec->Sync)(pScrn);
 +      pI830->AccelInfoRec->NeedToSync = FALSE;
 +   }
  
 -   return;
 +   for (i = 0; i < pI830->num_pipes; i++)
 +      if (pI830->pipes[i].enabled)
 +	 i830PipeSetBase(pScrn, i, x, y);
  }
  
  static void
diff --cc src/i830_memory.c
index a14027d,09ef5be..5213177
@@@ -1099,8 -1107,21 +1099,14 @@@
     pI830->MemoryAperture.Start = pI830->StolenMemory.End;
     pI830->MemoryAperture.End = pI830->FbMapSize;
     pI830->MemoryAperture.Size = pI830->FbMapSize - pI830->StolenMemory.Size;
+ #ifdef XF86DRI
+    if (!pI830->directRenderingDisabled) {
+       pI830->MemoryAperture.End -= KB(pI830->mmSize);
+       pI830->MemoryAperture.Size -= KB(pI830->mmSize);
+    }
+ #endif
     pI830->StolenPool.Fixed = pI830->StolenMemory;
     pI830->StolenPool.Total = pI830->StolenMemory;
 -#if ALLOCATE_ALL_BIOSMEM
 -   if (pI830->overrideBIOSMemSize &&
 -       pI830->BIOSMemorySize > pI830->StolenMemory.Size) {
 -      pI830->StolenPool.Total.End = pI830->BIOSMemorySize;
 -      pI830->StolenPool.Total.Size = pI830->BIOSMemorySize;
 -   }
 -#endif
     pI830->StolenPool.Free = pI830->StolenPool.Total;
     pI830->FreeMemory = pI830->TotalVideoRam - pI830->StolenPool.Total.Size;
     pI830->allocatedMemory = 0;
diff --cc src/i830_video.c
index a5cd77c,054d26b..d84c1c9
@@@ -963,21 -941,7 +946,14 @@@
        pPriv->contrast = value;
        overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff);
        ErrorF("CONTRAST\n");
-       overlay->OCMD &= ~OVERLAY_ENABLE;
        OVERLAY_UPDATE;
- #if 1
-       OVERLAY_OFF;
- #endif
 +   } else if (attribute == xvSaturation) {
 +      if ((value < 0) || (value > 1023))
 +	 return BadValue;
 +      pPriv->saturation = value;
 +      overlay->OCLRC1 = pPriv->saturation;
 +      overlay->OCMD &= ~OVERLAY_ENABLE;
 +      OVERLAY_UPDATE;
- #if 1
-       OVERLAY_OFF;
- #endif
     } else if (pI830->Clone && attribute == xvPipe) {
        if ((value < 0) || (value > 1))
           return BadValue;
diff-tree 45a27f80e1c783627f570c309e7a853dcc9af0c1 (from 9aea79d1e954fe4fb5c101edcb7c2d0f706a5c4c)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Nov 16 13:38:35 2006 -0800

    Remove output options. Let outputs be connected to other crtcs.
    
    Output options will be replaced by properties.
    Permits outputs to be connected to arbitrary CRTCs (within hardware limits).
    No cloning yet.

diff --git a/src/i830_randr.c b/src/i830_randr.c
index 87864f2..f579f41 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -527,8 +527,8 @@ I830RandRCrtcSet (ScreenPtr	pScreen,
 		  int		x,
 		  int		y,
 		  Rotation	rotation,
-		  int		numOutputs,
-		  RROutputConfigPtr	outputs)
+		  int		num_randr_outputs,
+		  RROutputPtr	*randr_outputs)
 {
     XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
@@ -536,29 +536,85 @@ I830RandRCrtcSet (ScreenPtr	pScreen,
     int			pipe = (int) (crtc->devPrivate);
     I830PipePtr		pI830Pipe = &pI830->pipes[pipe];
     DisplayModePtr	display_mode = mode ? mode->devPrivate : NULL;
-
-    /* Sync the engine before adjust mode */
-    if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
-	(*pI830->AccelInfoRec->Sync)(pScrn);
-	pI830->AccelInfoRec->NeedToSync = FALSE;
-    }
+    Bool		changed = FALSE;
+    Bool		disable = FALSE;
+    int			o, ro;
+    struct {
+	int pipe;
+	int enabled;
+    }			save_output[MAX_OUTPUTS];
+    Bool		save_enabled = pI830Pipe->enabled;
 
     if (display_mode != randrp->modes[pipe])
     {
+	changed = TRUE;
+	if (!display_mode)
+	    disable = TRUE;
+    }
+    
+    for (o = 0; o < pI830->num_outputs; o++) 
+    {
+	I830OutputPtr	output = &pI830->output[o];
+	RROutputPtr	randr_output = NULL;
+	
+	save_output[o].enabled = output->enabled;
+	save_output[o].pipe = output->pipe;
+	for (ro = 0; ro < num_randr_outputs; ro++) 
+	{
+	    if (output->randr_output == randr_outputs[ro])
+	    {
+		randr_output = randr_outputs[ro];
+		break;
+	    }
+	}
+	if (randr_output)
+	{
+	    if (output->pipe != pipe || !output->enabled)
+	    {
+		output->pipe = pipe;
+		output->enabled = TRUE;
+		changed = TRUE;
+	    }
+	}
+	else
+	{
+	    /* Disable outputs which were on this pipe */
+	    if (output->enabled && output->pipe == pipe)
+	    {
+		output->enabled = FALSE;
+		changed = TRUE;
+		disable = TRUE;
+	    }
+	}
+    }
+    if (changed)
+    {
 	pI830Pipe->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 (!i830PipeSetMode (pScrn, display_mode, pipe, TRUE))
+	    {
+		pI830Pipe->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;
+		}
 		return FALSE;
-	    /* XXX need I830SDVOPostSetMode here */
-	}
-	else
-	{
-	    i830DisableUnusedFunctions (pScrn);
+	    }
+	    i830PipeSetBase(pScrn, pipe, x, y);
 	}
 	randrp->modes[pipe] = display_mode;
+	if (disable)
+	    i830DisableUnusedFunctions (pScrn);
     }
-    i830PipeSetBase(pScrn, pipe, x, y);
     return I830RandRCrtcNotify (crtc);
 }
 
@@ -644,8 +700,6 @@ I830RandRSetInfo12 (ScrnInfoPtr pScrn)
     int			    clone_types;
     int			    crtc_types;
     int			    subpixel;
-    CARD32		    possibleOptions = 0;
-    CARD32		    currentOptions = 0;
     RRCrtcPtr		    randr_crtc;
     RROutputPtr		    randr_output;
     int			    nclone;
@@ -678,10 +732,6 @@ I830RandRSetInfo12 (ScrnInfoPtr pScrn)
 	    crtc_types = (1 << 1);
 	    clone_types = (1 << I830_OUTPUT_LVDS);
 	    subpixel = SubPixelHorizontalRGB;
-	    possibleOptions = (RROutputOptionScaleNone|
-			       RROutputOptionScaleMaxAspect |
-			       RROutputOptionScaleMax);
-	    currentOptions = RROutputOptionScaleMax;
 	    break;
 	case I830_OUTPUT_TVOUT:
 	    crtc_types = ((1 << 0) |
@@ -695,19 +745,16 @@ I830RandRSetInfo12 (ScrnInfoPtr pScrn)
 	    subpixel = SubPixelUnknown;
 	    break;
 	}
+	ncrtc = 0;
+	for (p = 0; p < pI830->num_pipes; p++)
+	    if (crtc_types & (1 << p))
+		crtcs[ncrtc++] = pI830->pipes[p].randr_crtc;
+
 	if (output->enabled)
-	{
-	    ncrtc = 0;
-	    for (p = 0; p < pI830->num_pipes; p++)
-		if (crtc_types & (1 << p))
-		    crtcs[ncrtc++] = pI830->pipes[p].randr_crtc;
 	    randr_crtc = pI830->pipes[output->pipe].randr_crtc;
-	}
 	else
-	{
-	    ncrtc = 0;
 	    randr_crtc = NULL;
-	}
+
 	if (!RROutputSetCrtcs (output->randr_output, crtcs, ncrtc))
 	    return FALSE;
 
@@ -715,9 +762,6 @@ I830RandRSetInfo12 (ScrnInfoPtr pScrn)
 	RROutputSetPhysicalSize(output->randr_output, 
 				output->mm_width,
 				output->mm_height);
-	RROutputSetPossibleOptions (output->randr_output, possibleOptions);
-	RROutputSetCurrentOptions (output->randr_output, currentOptions);
-
 	I830xf86RROutputSetModes (output->randr_output, output->probed_modes);
 
 	switch (output->detect(pScrn, output)) {
@@ -833,7 +877,7 @@ I830RandRCreateScreenResources12 (Screen
 	mmHeight = pScreen->mmHeight;
 	if (mode->HDisplay != pScreen->width)
 	    mmWidth = mmWidth * mode->HDisplay / pScreen->width;
-	if (mode->VDisplay == pScreen->height)
+	if (mode->VDisplay != pScreen->height)
 	    mmHeight = mmHeight * mode->VDisplay / pScreen->height;
 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		   "Setting screen physical size to %d x %d\n",
diff-tree 9aea79d1e954fe4fb5c101edcb7c2d0f706a5c4c (from 4889b9f33336c92f07aac86d75f50316db6ef81a)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Nov 16 11:40:26 2006 -0800

    Inverted boolean sense when selecting pipe for CRT detection.
    
    Pipes are available when they are not in use.

diff --git a/src/i830_display.c b/src/i830_display.c
index f661c4e..a0809eb 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -904,7 +904,6 @@ int
 i830GetLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    Bool pipe_available[MAX_DISPLAY_PIPES];
     int i;
     /* VESA 640x480x72Hz mode to set on the pipe */
     DisplayModeRec mode = {
@@ -944,16 +943,12 @@ i830GetLoadDetectPipe(ScrnInfoPtr pScrn,
     }
 
     for (i = 0; i < pI830->num_pipes; i++)
-	pipe_available[i] = i830PipeInUse(pScrn, i);
-
-    for (i = 0; i < pI830->num_pipes; i++) {
-	if (pipe_available[i])
+	if (!i830PipeInUse(pScrn, i))
 	    break;
-    }
 
-    if (i == pI830->num_pipes) {
+    if (i == pI830->num_pipes)
 	return -1;
-    }
+
     output->load_detect_temp = TRUE;
     output->pipe = i;
     output->enabled = TRUE;
diff-tree 4889b9f33336c92f07aac86d75f50316db6ef81a (from 854ff826c0031a44e874239c0b0a3533f4d9e14b)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Nov 15 15:26:31 2006 -0800

    Enable the LVDS if we find it and assign it to a pipe (oops).

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 344f4c0..0ea20e4 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1349,6 +1349,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       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;
 	 break;
       case I830_OUTPUT_ANALOG:
       case I830_OUTPUT_DVO:
diff-tree 854ff826c0031a44e874239c0b0a3533f4d9e14b (from d51555fba4e57c059fd184c1e54822d7e5b62a2f)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Nov 14 09:14:24 2006 -0800

    Disable setup of the second SDVO device until we fix it.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 1f3ff0a..344f4c0 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -651,7 +651,13 @@ I830SetupOutputs(ScrnInfoPtr pScrn)
 
    if (IS_I9XX(pI830)) {
       i830_sdvo_init(pScrn, SDVOB);
-      i830_sdvo_init(pScrn, SDVOC);
+
+      /* Don't initialize the second SDVO port for now.  We have issues with
+       * dealing with two ports, where we stomp both SDVO channels' registers
+       * when interacting with each, channel, and commands to one SDVO
+       * device appear to be affecting the other.
+       */
+      /* i830_sdvo_init(pScrn, SDVOC); */
    } else {
       i830_dvo_init(pScrn);
    }
diff-tree d51555fba4e57c059fd184c1e54822d7e5b62a2f (from dd1dcfab0ab0f2d0c25077fa663209e2762f26e8)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Nov 10 14:40:40 2006 -0800

    Fix clock range for single-channel LVDS.

diff --git a/src/i830_display.c b/src/i830_display.c
index 3603660..f661c4e 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -189,7 +189,10 @@ i830FindBestPLL(ScrnInfoPtr pScrn, int p
 	min_p1 = 1;
 	max_p1 = 8;
 	if (i830PipeHasType (pScrn, pipe, I830_OUTPUT_LVDS)) {
-	    if (target < 200000) /* XXX: Is this the right cutoff? */
+	    /* The single-channel range is 25-112Mhz, and dual-channel
+	     * is 80-224Mhz.  Prefer single channel as much as possible.
+	     */
+	    if (target < 112000)
 		p2 = 14;
 	    else
 		p2 = 7;
diff-tree dd1dcfab0ab0f2d0c25077fa663209e2762f26e8 (from 3955f044cfe1d592bcb36c43c539fb4a75840b8d)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Nov 10 11:08:02 2006 -0800

    Fill in some of the high bits of mode timings for SDVO.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 4d4817a..8d1f296 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -555,16 +555,20 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn
     output_dtd.part2.h_sync_width = h_sync_len & 0xff;
     output_dtd.part2.v_sync_off_width = (v_sync_offset & 0xf) << 4 |
 	(v_sync_len & 0xf);
-    output_dtd.part2.sync_off_width_high = 0;
+    output_dtd.part2.sync_off_width_high = ((h_sync_offset & 0x300) >> 2) |
+	((h_sync_len & 0x300) >> 4) | ((v_sync_offset & 0x30) >> 2) |
+	((v_sync_len & 0x30) >> 4);
+
     output_dtd.part2.dtd_flags = 0x18;
-    output_dtd.part2.sdvo_flags = 0;
-    output_dtd.part2.v_sync_off_high = 0;
-    output_dtd.part2.reserved = 0;
     if (mode->Flags & V_PHSYNC)
 	output_dtd.part2.dtd_flags |= 0x2;
     if (mode->Flags & V_PVSYNC)
 	output_dtd.part2.dtd_flags |= 0x4;
 
+    output_dtd.part2.sdvo_flags = 0;
+    output_dtd.part2.v_sync_off_high = v_sync_offset & 0xc0;
+    output_dtd.part2.reserved = 0;
+
     /* Turn off the screens before adjusting timings */
     i830_sdvo_set_active_outputs(output, &no_outputs);
 
diff --git a/src/i830_sdvo_regs.h b/src/i830_sdvo_regs.h
index c43e17a..98aa7a6 100644
--- a/src/i830_sdvo_regs.h
+++ b/src/i830_sdvo_regs.h
@@ -25,6 +25,10 @@
  *
  */
 
+/**
+ * @file SDVO command definitions and structures.
+ */
+
 struct i830_sdvo_output_flags {
     unsigned int tmds0:1;
     unsigned int rgb0:1;
@@ -60,22 +64,28 @@ struct i830_sdvo_caps {
 /** This matches the EDID DTD structure, more or less */
 struct i830_sdvo_dtd {
     struct {
-	CARD16 clock;			/**< pixel clock, in 10kHz units */
-	CARD8 h_active;
-	CARD8 h_blank;
-	CARD8 h_high;
-	CARD8 v_active;
-	CARD8 v_blank;
-	CARD8 v_high;
+	CARD16 clock;		/**< pixel clock, in 10kHz units */
+	CARD8 h_active;		/**< lower 8 bits (pixels) */
+	CARD8 h_blank;		/**< lower 8 bits (pixels) */
+	CARD8 h_high;		/**< upper 4 bits each h_active, h_blank */
+	CARD8 v_active;		/**< lower 8 bits (lines) */
+	CARD8 v_blank;		/**< lower 8 bits (lines) */
+	CARD8 v_high;		/**< upper 4 bits each v_active, v_blank */
     } part1;
 
     struct {
-	CARD8 h_sync_off;
-	CARD8 h_sync_width;
+	CARD8 h_sync_off;	/**< lower 8 bits, from hblank start */
+	CARD8 h_sync_width;	/**< lower 8 bits (pixels) */
+	/** lower 4 bits each vsync offset, vsync width */
 	CARD8 v_sync_off_width;
+	/**
+	 * 2 high bits of hsync offset, 2 high bits of hsync width,
+	 * bits 4-5 of vsync offset, and 2 high bits of vsync width.
+	 */
 	CARD8 sync_off_width_high;
 	CARD8 dtd_flags;
 	CARD8 sdvo_flags;
+	/** bits 6-7 of vsync offset at bits 6-7 */
 	CARD8 v_sync_off_high;
 	CARD8 reserved;
     } part2;
@@ -250,8 +260,12 @@ struct i830_sdvo_set_target_input_args {
 # define SDVO_DTD_DTD_FLAG_SYNC_MASK				(3 << 1)
 # define SDVO_DTD_SDVO_FLAS				SDVO_I2C_ARG_5
 # define SDVO_DTD_SDVO_FLAG_STALL				(1 << 7)
-# define SDVO_DTD_SDVO_FLAG_NOT_CENTERED			(1 << 6)
+# define SDVO_DTD_SDVO_FLAG_CENTERED				(0 << 6)
+# define SDVO_DTD_SDVO_FLAG_UPPER_LEFT				(1 << 6)
 # define SDVO_DTD_SDVO_FLAG_SCALING_MASK			(3 << 4)
+# define SDVO_DTD_SDVO_FLAG_SCALING_NONE			(0 << 4)
+# define SDVO_DTD_SDVO_FLAG_SCALING_SHARP			(1 << 4)
+# define SDVO_DTD_SDVO_FLAG_SCALING_SMOOTH			(2 << 4)
 # define SDVO_DTD_VSYNC_OFF_HIGH			SDVO_I2C_ARG_6
 
 /**
diff-tree 3955f044cfe1d592bcb36c43c539fb4a75840b8d (from 0f5886689d7ef7dbbef6425d5c855ac6b67d3350)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Nov 9 20:28:46 2006 -0800

    Expose the DDC-probed EDID data as the EDID_DATA output property.

diff --git a/src/i830_modes.c b/src/i830_modes.c
index b6867c3..77db66c 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -48,6 +48,7 @@
 #include <math.h>
 
 #include "xf86.h"
+#include "X11/Xatom.h"
 #include "i830.h"
 #include "i830_display.h"
 #include "i830_xf86Modes.h"
@@ -612,6 +613,29 @@ I830ValidateXF86ModeList(ScrnInfoPtr pSc
     return 1; /* XXX */
 }
 
+#ifdef RANDR_12_INTERFACE
+
+#define EDID_ATOM_NAME		"EDID_DATA"
+
+static void
+i830_ddc_set_edid_property(ScrnInfoPtr pScrn, I830OutputPtr output,
+			   void *data, int data_len)
+{
+    Atom edid_atom = MakeAtom(EDID_ATOM_NAME, sizeof(EDID_ATOM_NAME), TRUE);
+
+    /* This may get called before the RandR resources have been created */
+    if (output->randr_output == NULL)
+	return;
+
+    if (data_len != 0) {
+	RRChangeOutputProperty(output->randr_output, edid_atom, XA_INTEGER, 8,
+			       PropModeReplace, data_len, data, FALSE);
+    } else {
+	RRDeleteOutputProperty(output->randr_output, edid_atom);
+    }
+}
+#endif
+
 /**
  * Generic get_modes function using DDC, used by many outputs.
  */
@@ -623,13 +647,27 @@ i830_ddc_get_modes(ScrnInfoPtr pScrn, I8
     int i;
 
     ddc_mon = xf86DoEDID_DDC2(pScrn->scrnIndex, output->pDDCBus);
-    if (ddc_mon == NULL)
+    if (ddc_mon == NULL) {
+#ifdef RANDR_12_INTERFACE
+	i830_ddc_set_edid_property(pScrn, output, NULL, 0);
+#endif
 	return NULL;
+    }
 
     if (output->MonInfo != NULL)
 	xfree(output->MonInfo);
     output->MonInfo = ddc_mon;
 
+#ifdef RANDR_12_INTERFACE
+    if (output->MonInfo->ver.version == 1) {
+	i830_ddc_set_edid_property(pScrn, output, ddc_mon->rawData, 128);
+    } else if (output->MonInfo->ver.version == 2) {
+	i830_ddc_set_edid_property(pScrn, output, ddc_mon->rawData, 256);
+    } else {
+	i830_ddc_set_edid_property(pScrn, 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]);
diff-tree 0f5886689d7ef7dbbef6425d5c855ac6b67d3350 (from 679c7bd82639a09cdce133becb8a08629ce3a4e9)
Author: Keith Packard <keithp at mandolin.keithp.com>
Date:   Wed Nov 8 23:19:59 2006 -0800

    Create RandR 1.2 objects in I830PreInit.
    
    Creating the objects early will allow the driver to use
    randr structures to select a reasonable configuration.
    That part has not been done yet.

diff --git a/src/i830.h b/src/i830.h
index ef46979..96f0c29 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -270,6 +270,9 @@ struct _I830OutputRec {
    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 {
@@ -280,6 +283,9 @@ typedef struct _I830PipeRec {
    Bool		  cursorInRange;
    Bool		  cursorShown;
    DisplayModeRec curMode;
+#ifdef RANDR_12_INTERFACE
+   RRCrtcPtr	  randr_crtc;
+#endif
 } I830PipeRec, *I830PipePtr;
 
 typedef struct _I830Rec {
@@ -676,6 +682,7 @@ Bool I830RandRSetConfig(ScreenPtr pScree
 			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 63c1fd2..1f3ff0a 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -771,7 +771,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    I830EntPtr pI830Ent = NULL;					
    int mem;
    int flags24;
-   int i, n;
+   int i;
    char *s;
    pointer pVBEModule = NULL;
    Bool enable;
@@ -1653,8 +1653,8 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
 	      "Maximum frambuffer space: %d kByte\n", pScrn->videoRam);
 
-   n = I830ValidateXF86ModeList(pScrn, TRUE);
-   if (n <= 0) {
+   if (!I830RandRPreInit (pScrn))
+   {
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
       PreInitCleanup(pScrn);
       return FALSE;
diff --git a/src/i830_randr.c b/src/i830_randr.c
index d6e5f0b..87864f2 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -53,8 +53,6 @@ typedef struct _i830RandRInfo {
     Rotation			    rotation; /* current mode */
     Rotation                        supported_rotations; /* driver supported */
 #ifdef RANDR_12_INTERFACE
-    RRCrtcPtr			    crtcs[MAX_DISPLAY_PIPES];
-    RROutputPtr			    outputs[MAX_OUTPUTS];
     DisplayModePtr  		    modes[MAX_DISPLAY_PIPES];
 #endif
 } XF86RandRInfoRec, *XF86RandRInfoPtr;
@@ -477,7 +475,6 @@ static Bool
 I830RandRCrtcNotify (RRCrtcPtr	crtc)
 {
     ScreenPtr		pScreen = crtc->pScreen;
-    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
     I830Ptr		pI830 = I830PTR(pScrn);
     RRModePtr		mode = NULL;
@@ -503,7 +500,7 @@ I830RandRCrtcNotify (RRCrtcPtr	crtc)
 	output = &pI830->output[i];
 	if (output->enabled && output->pipe == pipe)
 	{
-	    rrout = randrp->outputs[i];
+	    rrout = output->randr_output;
 	    outputs[numOutputs++] = rrout;
 	    /*
 	     * We make copies of modes, so pointer equality 
@@ -572,45 +569,91 @@ I830RandRCrtcSetGamma (ScreenPtr    pScr
     return FALSE;
 }
 
-/*
- * Mirror the current mode configuration to RandR
+/**
+ * Given a list of xf86 modes and a RandR Output object, construct
+ * RandR modes and assign them to the output
  */
 static Bool
-I830RandRSetInfo12 (ScreenPtr pScreen)
+I830xf86RROutputSetModes (RROutputPtr randr_output, DisplayModePtr modes)
 {
-    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
-    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
-    I830Ptr		pI830 = I830PTR(pScrn);
-    RROutputPtr		clones[MAX_OUTPUTS];
-    RRCrtcPtr		crtc;
-    int			nclone;
-    RRCrtcPtr		crtcs[MAX_DISPLAY_PIPES];
-    int			ncrtc;
-    int			nmode, npreferred;
-    struct _I830OutputRec   *output;
-    int			i;
-    int			j;
-    int			p;
-    int			clone_types;
-    int			crtc_types;
-    int			pipe;
-    int			subpixel;
-    DisplayModePtr	modes, mode;
-    xRRModeInfo		modeInfo;
-    RRModePtr		rrmode, *rrmodes;
-    CARD32		possibleOptions = 0;
-    CARD32		currentOptions = 0;
+    DisplayModePtr  mode;
+    RRModePtr	    *rrmodes = NULL;
+    int		    nmode = 0;
+    int		    npreferred = 0;
+    Bool	    ret = TRUE;
+    int		    pref;
+
+    for (mode = modes; mode; mode = mode->next)
+	nmode++;
+
+    if (nmode) {
+	rrmodes = xalloc (nmode * sizeof (RRModePtr));
+	
+	if (!rrmodes)
+	    return FALSE;
+	nmode = 0;
 
-    if (randrp->virtualX == -1 || randrp->virtualY == -1)
-    {
-	randrp->virtualX = pScrn->virtualX;
-	randrp->virtualY = pScrn->virtualY;
+	for (pref = 1; pref >= 0; pref--) {
+	    for (mode = modes; mode; mode = mode->next) {
+		if ((pref != 0) == ((mode->type & M_T_PREFERRED) != 0)) {
+		    xRRModeInfo		modeInfo;
+		    RRModePtr		rrmode;
+		    
+		    modeInfo.nameLength = strlen (mode->name);
+		    modeInfo.width = mode->HDisplay;
+		    modeInfo.dotClock = mode->Clock * 1000;
+		    modeInfo.hSyncStart = mode->HSyncStart;
+		    modeInfo.hSyncEnd = mode->HSyncEnd;
+		    modeInfo.hTotal = mode->HTotal;
+		    modeInfo.hSkew = mode->HSkew;
+
+		    modeInfo.height = mode->VDisplay;
+		    modeInfo.vSyncStart = mode->VSyncStart;
+		    modeInfo.vSyncEnd = mode->VSyncEnd;
+		    modeInfo.vTotal = mode->VTotal;
+		    modeInfo.modeFlags = mode->Flags;
+
+		    rrmode = RRModeGet (&modeInfo, mode->name);
+		    rrmode->devPrivate = mode;
+		    if (rrmode) {
+			rrmodes[nmode++] = rrmode;
+			npreferred += pref;
+		    }
+		}
+	    }
+	}
     }
-    RRScreenSetSizeRange (pScreen, 320, 240,
-			  randrp->virtualX, randrp->virtualY);
-    for (i = 0; i < pI830->num_outputs; i++)
+    
+    ret = RROutputSetModes (randr_output, rrmodes, nmode, npreferred);
+    xfree (rrmodes);
+    return ret;
+}
+
+/*
+ * Mirror the current mode configuration to RandR
+ */
+static Bool
+I830RandRSetInfo12 (ScrnInfoPtr pScrn)
+{
+    I830Ptr		    pI830 = I830PTR(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;
+    CARD32		    possibleOptions = 0;
+    CARD32		    currentOptions = 0;
+    RRCrtcPtr		    randr_crtc;
+    RROutputPtr		    randr_output;
+    int			    nclone;
+    
+    for (o = 0; o < pI830->num_outputs; o++)
     {
-	output = &pI830->output[i];
+	output = &pI830->output[o];
+	randr_output = output->randr_output;
 	/*
 	 * Valid crtcs
 	 */
@@ -625,7 +668,7 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
 	    subpixel = SubPixelHorizontalRGB;
 	    break;
 	case I830_OUTPUT_ANALOG:
-	    crtc_types = (1 << 0);
+	    crtc_types = ((1 << 0) | (1 << 1));
 	    clone_types = ((1 << I830_OUTPUT_ANALOG) |
 			   (1 << I830_OUTPUT_DVO) |
 			   (1 << I830_OUTPUT_SDVO));
@@ -654,110 +697,58 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
 	}
 	if (output->enabled)
 	{
-	    /* Can't flip outputs among crtcs yet */
-	    ncrtc = 1;
-	    pipe = output->pipe;
-	    crtc = randrp->crtcs[pipe];
-	    crtcs[0] = randrp->crtcs[pipe];
+	    ncrtc = 0;
+	    for (p = 0; p < pI830->num_pipes; p++)
+		if (crtc_types & (1 << p))
+		    crtcs[ncrtc++] = pI830->pipes[p].randr_crtc;
+	    randr_crtc = pI830->pipes[output->pipe].randr_crtc;
 	}
 	else
 	{
 	    ncrtc = 0;
-	    pipe = -1;
-	    crtc = NULL;
+	    randr_crtc = NULL;
 	}
-	if (!RROutputSetCrtcs (randrp->outputs[i], crtcs, ncrtc))
+	if (!RROutputSetCrtcs (output->randr_output, crtcs, ncrtc))
 	    return FALSE;
 
-	RROutputSetCrtc (randrp->outputs[i], crtc);
-	RROutputSetPhysicalSize(randrp->outputs[i], pI830->output[i].mm_width,
-				pI830->output[i].mm_height);
-	RROutputSetPossibleOptions (randrp->outputs[i], possibleOptions);
-	RROutputSetCurrentOptions (randrp->outputs[i], currentOptions);
-        nmode = 0;
-	npreferred = 0;
-	rrmodes = NULL;
-
-	modes = pI830->output[i].probed_modes;
-
-	for (mode = modes; mode; mode = mode->next)
-	    nmode++;
-
-	if (nmode) {
-	    rrmodes = xalloc (nmode * sizeof (RRModePtr));
-	    if (!rrmodes)
-		return FALSE;
-	    nmode = 0;
-
-	    for (p = 1; p >= 0; p--) {
-		for (mode = modes; mode; mode = mode->next) {
-		    if ((p != 0) == ((mode->type & M_T_PREFERRED) != 0)) {
-			modeInfo.nameLength = strlen (mode->name);
-
-			modeInfo.width = mode->HDisplay;
-			modeInfo.dotClock = mode->Clock * 1000;
-			modeInfo.hSyncStart = mode->HSyncStart;
-			modeInfo.hSyncEnd = mode->HSyncEnd;
-			modeInfo.hTotal = mode->HTotal;
-			modeInfo.hSkew = mode->HSkew;
-
-			modeInfo.height = mode->VDisplay;
-			modeInfo.vSyncStart = mode->VSyncStart;
-			modeInfo.vSyncEnd = mode->VSyncEnd;
-			modeInfo.vTotal = mode->VTotal;
-			modeInfo.modeFlags = mode->Flags;
-
-			rrmode = RRModeGet (&modeInfo, mode->name);
-			rrmode->devPrivate = mode;
-			if (rrmode) {
-			    rrmodes[nmode++] = rrmode;
-			    npreferred += p;
-			}
-		    }
-		}
-	    }
-	}
-
-    	if (!RROutputSetModes (randrp->outputs[i], rrmodes, nmode, npreferred))
-	{
-    	    xfree (rrmodes);
-	    return FALSE;
-	}
+	RROutputSetCrtc (output->randr_output, randr_crtc);
+	RROutputSetPhysicalSize(output->randr_output, 
+				output->mm_width,
+				output->mm_height);
+	RROutputSetPossibleOptions (output->randr_output, possibleOptions);
+	RROutputSetCurrentOptions (output->randr_output, currentOptions);
 
-	xfree (rrmodes);
+	I830xf86RROutputSetModes (output->randr_output, output->probed_modes);
 
-	switch (pI830->output[i].detect(pScrn, &pI830->output[i])) {
+	switch (output->detect(pScrn, output)) {
 	case OUTPUT_STATUS_CONNECTED:
-	    RROutputSetConnection (randrp->outputs[i], RR_Connected);
+	    RROutputSetConnection (output->randr_output, RR_Connected);
 	    break;
 	case OUTPUT_STATUS_DISCONNECTED:
-	    RROutputSetConnection (randrp->outputs[i], RR_Disconnected);
+	    RROutputSetConnection (output->randr_output, RR_Disconnected);
 	    break;
 	case OUTPUT_STATUS_UNKNOWN:
-	    RROutputSetConnection (randrp->outputs[i], RR_UnknownConnection);
+	    RROutputSetConnection (output->randr_output, RR_UnknownConnection);
 	    break;
 	}
 
-	RROutputSetSubpixelOrder (randrp->outputs[i], subpixel);
+	RROutputSetSubpixelOrder (output->randr_output, subpixel);
 
 	/*
 	 * Valid clones
 	 */
 	nclone = 0;
-	for (j = 0; j < pI830->num_outputs; j++)
+	for (c = 0; c < pI830->num_outputs; c++)
 	{
-	    if (i != j && ((1 << pI830->output[j].type) & clone_types))
-		clones[nclone++] = randrp->outputs[j];
+	    if (o != c && ((1 << pI830->output[c].type) & clone_types))
+		clones[nclone++] = pI830->output[c].randr_output;
 	}
-	if (!RROutputSetClones (randrp->outputs[i], clones, nclone))
+	if (!RROutputSetClones (output->randr_output, clones, nclone))
 	    return FALSE;
     }
-    for (i = 0; i < pI830->num_pipes; i++)
-	I830RandRCrtcNotify (randrp->crtcs[i]);
     return TRUE;
 }
 
-
 /*
  * Query the hardware for the current state, then mirror
  * that to RandR
@@ -768,43 +759,70 @@ I830RandRGetInfo12 (ScreenPtr pScreen, R
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
 
     i830_reprobe_output_modes(pScrn);
-    return I830RandRSetInfo12 (pScreen);
+    return I830RandRSetInfo12 (pScrn);
 }
 
 static Bool
-I830RandRCreateScreenResources12 (ScreenPtr pScreen)
+I830RandRCreateObjects12 (ScrnInfoPtr pScrn)
 {
-    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
-    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
     I830Ptr		pI830 = I830PTR(pScrn);
-    struct _I830OutputRec   *output;
-    const char		*name;
-    int			i;
-    DisplayModePtr	mode;
+    int			p;
+    int			o;
+    
+    if (!RRInit ())
+	return FALSE;
 
     /*
      * Create RandR resources, then probe them
      */
-    for (i = 0; i < pI830->num_pipes; i++)
+    for (p = 0; p < pI830->num_pipes; p++)
     {
-	randrp->crtcs[i] = RRCrtcCreate ((void *) i);
-	if (!randrp->crtcs[i])
+	I830PipePtr pipe = &pI830->pipes[p];
+	RRCrtcPtr   randr_crtc = RRCrtcCreate ((void *) p);
+	
+	if (!randr_crtc)
 	    return FALSE;
-	if (!RRCrtcAttachScreen (randrp->crtcs[i], pScreen))
-	    return FALSE;
-	RRCrtcGammaSetSize (randrp->crtcs[i], 256);
+	RRCrtcGammaSetSize (randr_crtc, 256);
+	pipe->randr_crtc = randr_crtc;
     }
 
-    for (i = 0; i < pI830->num_outputs; i++)
+    for (o = 0; o < pI830->num_outputs; o++)
     {
-	output = &pI830->output[i];
-	name = i830_output_type_names[output->type];
-	randrp->outputs[i] = RROutputCreate (name, strlen (name), (void *) i);
-	if (!randrp->outputs[i])
-	    return FALSE;
-	if (!RROutputAttachScreen (randrp->outputs[i], pScreen))
+	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;
     }
+    /*
+     * Configure output modes
+     */
+    if (!I830RandRSetInfo12 (pScrn))
+	return FALSE;
+    return TRUE;
+}
+
+static Bool
+I830RandRCreateScreenResources12 (ScreenPtr pScreen)
+{
+    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
+    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+    I830Ptr		pI830 = I830PTR(pScrn);
+    int			p, o;
+    DisplayModePtr	mode;
+
+    /*
+     * Attach RandR objects to screen
+     */
+    for (p = 0; p < pI830->num_pipes; p++)
+	if (!RRCrtcAttachScreen (pI830->pipes[p].randr_crtc, pScreen))
+	    return FALSE;
+
+    for (o = 0; o < pI830->num_outputs; o++)
+	if (!RROutputAttachScreen (pI830->output[o].randr_output, pScreen))
+	    return FALSE;
 
     mode = pScrn->currentMode;
     if (mode)
@@ -827,10 +845,22 @@ I830RandRCreateScreenResources12 (Screen
 				mmHeight);
     }
 
-    for (i = 0; i < pI830->num_pipes; i++)
-	i830PipeSetBase(pScrn, i, 0, 0);
+    for (p = 0; p < pI830->num_pipes; p++)
+    {
+	i830PipeSetBase(pScrn, p, 0, 0);
+	I830RandRCrtcNotify (pI830->pipes[p].randr_crtc);
+    }
 
-    return I830RandRSetInfo12 (pScreen);
+    
+    if (randrp->virtualX == -1 || randrp->virtualY == -1)
+    {
+	randrp->virtualX = pScrn->virtualX;
+	randrp->virtualY = pScrn->virtualY;
+    }
+    
+    RRScreenSetSizeRange (pScreen, 320, 240,
+			  randrp->virtualX, randrp->virtualY);
+    return TRUE;
 }
 
 static void
@@ -853,3 +883,18 @@ I830RandRInit12 (ScreenPtr pScreen)
     return TRUE;
 }
 #endif
+
+Bool
+I830RandRPreInit (ScrnInfoPtr pScrn)
+{
+    int n;
+    
+    n = I830ValidateXF86ModeList(pScrn, TRUE);
+    if (n <= 0)
+	return FALSE;
+#if RANDR_12_INTERFACE
+    if (!I830RandRCreateObjects12 (pScrn))
+	return FALSE;
+#endif
+    return TRUE;
+}
diff-tree 679c7bd82639a09cdce133becb8a08629ce3a4e9 (from 81b7b489afa2cab4d8614c64f4906be627f1d07e)
Author: Keith Packard <keithp at mandolin.keithp.com>
Date:   Wed Nov 8 21:39:28 2006 -0800

    ignore edited man page

diff --git a/.gitignore b/.gitignore
index b13e38f..cb52e9f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,3 +21,4 @@ libtool
 ltmain.sh
 missing
 stamp-h1
+i810.4
diff-tree 81b7b489afa2cab4d8614c64f4906be627f1d07e (from 81bace0c316c3ed80201a34eca533254d12cd193)
Author: Keith Packard <keithp at mandolin.keithp.com>
Date:   Wed Nov 8 21:38:00 2006 -0800

    Adapt to RandR updates that split object creation from screen association.
    
    RandR DIX code is preparing for xf86 drivers that want to allocate RandR
    objects at PreInit time. This patch adapts to that change without taking
    advantage of it.

diff --git a/src/i830_crt.c b/src/i830_crt.c
index 46eb788..f067260 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -103,13 +103,17 @@ i830_crt_post_set_mode(ScrnInfoPtr pScrn
 {
     I830Ptr pI830 = I830PTR(pScrn);
     int	    dpll_md_reg = (output->pipe == 0) ? DPLL_A_MD : DPLL_B_MD;
-    CARD32  adpa;
+    CARD32  adpa, dpll_md;
 
     /*
-     * Not quite sure precisely what this does...
+     * Disable separate mode multiplier used when cloning SDVO to CRT
+     * XXX this needs to be adjusted when we really are cloning
      */
     if (IS_I965G(pI830))
-	OUTREG(dpll_md_reg, 0x3 << DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT);
+    {
+	dpll_md = INREG(dpll_md_reg);
+	OUTREG(dpll_md_reg, dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK);
+    }
 
     adpa = ADPA_DAC_ENABLE;
 
diff --git a/src/i830_randr.c b/src/i830_randr.c
index 32cc877..d6e5f0b 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -707,7 +707,7 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
 			modeInfo.vTotal = mode->VTotal;
 			modeInfo.modeFlags = mode->Flags;
 
-			rrmode = RRModeGet (pScreen, &modeInfo, mode->name);
+			rrmode = RRModeGet (&modeInfo, mode->name);
 			rrmode->devPrivate = mode;
 			if (rrmode) {
 			    rrmodes[nmode++] = rrmode;
@@ -787,7 +787,11 @@ I830RandRCreateScreenResources12 (Screen
      */
     for (i = 0; i < pI830->num_pipes; i++)
     {
-	randrp->crtcs[i] = RRCrtcCreate (pScreen, (void *) i);
+	randrp->crtcs[i] = RRCrtcCreate ((void *) i);
+	if (!randrp->crtcs[i])
+	    return FALSE;
+	if (!RRCrtcAttachScreen (randrp->crtcs[i], pScreen))
+	    return FALSE;
 	RRCrtcGammaSetSize (randrp->crtcs[i], 256);
     }
 
@@ -795,9 +799,11 @@ I830RandRCreateScreenResources12 (Screen
     {
 	output = &pI830->output[i];
 	name = i830_output_type_names[output->type];
-	randrp->outputs[i] = RROutputCreate (pScreen,
-					     name, strlen (name),
-					     (void *) i);
+	randrp->outputs[i] = RROutputCreate (name, strlen (name), (void *) i);
+	if (!randrp->outputs[i])
+	    return FALSE;
+	if (!RROutputAttachScreen (randrp->outputs[i], pScreen))
+	    return FALSE;
     }
 
     mode = pScrn->currentMode;
diff-tree 81bace0c316c3ed80201a34eca533254d12cd193 (from parents)
Merge: 713c5b0899428edfea7cea0780244488115dbe1d beb89163d73376e70870e6e2a6b19863f3a058b1
Author: Keith Packard <keithp at mandolin.keithp.com>
Date:   Wed Nov 8 20:23:20 2006 -0800

    Merge branch 'modesetting-keithp' into modesetting
    
    Conflicts in PipeSetMode were resolved to use the keithp changes
    that pushed more modesetting stuff into the per-pipe function.
    
    Switched availablePipes to num_pipes.
    
    Used modesetting default output configuration.

diff --cc src/i830_display.c
index c81f454,6804a4d..3603660
@@@ -375,16 -375,27 +375,32 @@@
  }
  
  /**
+  * Return whether any outputs are connected to the specified pipe
+  */
+ 
 -static Bool
++Bool
+ i830PipeInUse (ScrnInfoPtr pScrn, int pipe)
+ {
+     I830Ptr pI830 = I830PTR(pScrn);
+     int	i;
+     
+     for (i = 0; i < pI830->num_outputs; i++)
 -	if (!pI830->output[i].disabled && pI830->output[i].pipe == pipe)
++	if (pI830->output[i].enabled && pI830->output[i].pipe == pipe)
+ 	    return TRUE;
+     return FALSE;
+ }
+ 
+ /**
 - * Sets the given video mode on the given pipe.  Assumes that plane A feeds
 - * pipe A, and plane B feeds pipe B.  Should not affect the other planes/pipes.
 + * Sets the given video mode on the given pipe.
 + *
 + * Plane A is always output to pipe A, and plane B to pipe B.  The plane
 + * will not be enabled if plane_enable is FALSE, which is used for
 + * load detection, when something else will be output to the pipe other than
 + * display data.
   */
  Bool
 -i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe)
 +i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe,
 +		Bool plane_enable)
  {
      I830Ptr pI830 = I830PTR(pScrn);
      I830PipePtr pI830Pipe = &pI830->pipes[pipe];
@@@ -417,10 -432,21 +437,21 @@@
      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested pix clock: %d\n",
  	       pMode->Clock);
  
 -    pI830->pipes[pipe].planeEnabled = i830PipeInUse (pScrn, pipe);
++    pI830->pipes[pipe].enabled = i830PipeInUse (pScrn, pipe);
+     
 -    if (!pI830->pipes[pipe].planeEnabled)
++    if (!pI830->pipes[pipe].enabled)
+ 	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].disabled)
 +	if (pI830->output[i].pipe != pipe || !pI830->output[i].enabled)
  	    continue;
  
+ 	pI830->output[i].pre_set_mode(pScrn, &pI830->output[i], pMode);
+ 	
  	switch (pI830->output[i].type) {
  	case I830_OUTPUT_LVDS:
  	    is_lvds = TRUE;
@@@ -666,21 -704,21 +705,21 @@@
  i830DisableUnusedFunctions(ScrnInfoPtr pScrn)
  {
      I830Ptr pI830 = I830PTR(pScrn);
-     int i, pipe;
 -    int i;
++    int output, pipe;
  
      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling unused functions\n");
  
--    for (i = 0; i < pI830->num_outputs; i++) {
- 	if (!pI830->output[i].enabled)
- 	    pI830->output[i].dpms(pScrn, &pI830->output[i], DPMSModeOff);
 -	if (pI830->output[i].disabled)
 -	    pI830->output[i].dpms(pScrn, &pI830->output[i], DPMSModeOff);
++    for (output = 0; output < pI830->num_outputs; output++) {
++	if (!pI830->output[output].enabled)
++	    pI830->output[output].dpms(pScrn, &pI830->output[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->availablePipes; pipe++) {
 -    for (i = 0; i < pI830->num_pipes; i++) {
 -	I830PipePtr pI830Pipe = &pI830->pipes[i];
++    for (pipe = 0; pipe < pI830->num_pipes; pipe++) {
 +	I830PipePtr pI830Pipe = &pI830->pipes[pipe];
  	int	    dspcntr_reg = pipe == 0 ? DSPACNTR : DSPBCNTR;
  	int	    pipeconf_reg = pipe == 0 ? PIPEACONF : PIPEBCONF;
  	int	    dpll_reg = pipe == 0 ? DPLL_A : DPLL_B;
@@@ -751,22 -770,9 +771,11 @@@
  
      DPRINTF(PFX, "i830SetMode\n");
  
- #ifdef XF86DRI
-     didLock = I830DRILock(pScrn);
- #endif
- 
-     for (i = 0; i < pI830->availablePipes; i++)
- 	pI830->pipes[i].enabled = i830PipeInUse (pScrn, i);
- 
-     for (i = 0; i < pI830->num_outputs; i++)
- 	pI830->output[i].pre_set_mode(pScrn, &pI830->output[i], pMode);
- 
-     for (i = 0; i < pI830->availablePipes; i++)
+     for (i = 0; i < pI830->num_pipes; i++)
      {
- 	if (pI830->pipes[i].enabled)
- 	    ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, i,
- 								pMode),
- 				 i, TRUE);
 -	ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, i, pMode), i);
++	ok = i830PipeSetMode(pScrn, 
++			     i830PipeFindClosestMode(pScrn, i, pMode), 
++			     i, TRUE);
  	if (!ok)
  	    goto done;
      }
@@@ -822,34 -823,14 +826,34 @@@
  
      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output configuration:\n");
  
-     for (i = 0; i < pI830->availablePipes; i++) {
+     for (i = 0; i < pI830->num_pipes; i++) {
  	CARD32 dspcntr = INREG(DSPACNTR + (DSPBCNTR - DSPACNTR) * i);
 +	CARD32 pipeconf = INREG(PIPEACONF + (PIPEBCONF - PIPEACONF) * i);
 +	Bool hw_plane_enable = (dspcntr & DISPLAY_PLANE_ENABLE) != 0;
 +	Bool hw_pipe_enable = (pipeconf & PIPEACONF_ENABLE) != 0;
  
  	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 +		   "  Pipe %c is %s\n",
 +		   'A' + i, pI830->pipes[i].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].planeEnabled ? "enabled" : "disabled",
 +		   pI830->pipes[i].enabled ? "enabled" : "disabled",
  		   dspcntr & DISPPLANE_SEL_PIPE_MASK ? 'B' : 'A');
 +	if (hw_pipe_enable != pI830->pipes[i].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");
 +	}
 +	if (hw_plane_enable != pI830->pipes[i].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");
 +	}
      }
  
      for (i = 0; i < pI830->num_outputs; i++) {
@@@ -879,91 -860,3 +883,91 @@@
  		   pI830->output[i].pipe == 0 ? 'A' : 'B');
      }
  }
 +
 +/**
 + * Get a pipe with a simple mode set on it for doing load-based monitor
 + * detection.
 + *
 + * It will be up to the load-detect code to adjust the pipe as appropriate for
 + * its requirements.  The pipe will be connected to no other outputs.
 + *
 + * Currently this code will only succeed if there is a pipe with no outputs
 + * 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.
 + */
 +int
 +i830GetLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output)
 +{
 +    I830Ptr pI830 = I830PTR(pScrn);
 +    Bool pipe_available[MAX_DISPLAY_PIPES];
 +    int i;
 +    /* VESA 640x480x72Hz mode to set on the pipe */
 +    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 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;
 +	}
 +    }
 +
-     for (i = 0; i < pI830->availablePipes; i++)
++    for (i = 0; i < pI830->num_pipes; i++)
 +	pipe_available[i] = i830PipeInUse(pScrn, i);
 +
-     for (i = 0; i < pI830->availablePipes; i++) {
++    for (i = 0; i < pI830->num_pipes; i++) {
 +	if (pipe_available[i])
 +	    break;
 +    }
 +
-     if (i == pI830->availablePipes) {
++    if (i == pI830->num_pipes) {
 +	return -1;
 +    }
 +    output->load_detect_temp = TRUE;
 +    output->pipe = i;
 +    output->enabled = TRUE;
 +
 +    I830xf86SetModeCrtc(&mode, INTERLACE_HALVE_V);
 +
 +    i830PipeSetMode(pScrn, &mode, i, FALSE);
 +
 +    return i;
 +}
 +
 +void
 +i830ReleaseLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output)
 +{
 +    if (output->load_detect_temp) {
 +	output->enabled = FALSE;
 +	i830DisableUnusedFunctions(pScrn);
 +	output->load_detect_temp = FALSE;
 +    }
 +}
diff --cc src/i830_driver.c
index ab0af4e,b632073..63c1fd2
@@@ -1359,23 -1341,15 +1341,22 @@@
  
        switch (pI830->output[i].type) {
        case I830_OUTPUT_LVDS:
- 	 /* LVDS must always be on pipe B. */
- 	 pI830->output[i].pipe = 1;
- 	 pI830->output[i].enabled = TRUE;
+ 	 /* LVDS must live on pipe B for two-pipe devices */
+ 	 pI830->output[i].pipe = pI830->num_pipes - 1;
  	 break;
        case I830_OUTPUT_ANALOG:
 -	 pI830->output[i].pipe = 0;
 -	 break;
        case I830_OUTPUT_DVO:
        case I830_OUTPUT_SDVO:
 -	 pI830->output[i].pipe = 1;
 +	 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;
 +	    }
 +	 }
  	 break;
        default:
  	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unhandled output type\n");
@@@ -1383,10 -1357,6 +1364,10 @@@
        }
     }
  
-    for (i = 0; i < pI830->availablePipes; i++) {
++   for (i = 0; i < pI830->num_pipes; i++) {
 +      pI830->pipes[i].enabled = i830PipeInUse(pScrn, i);
 +   }
 +
  #if 0
     pI830->CloneRefresh = 60; /* default to 60Hz */
     if (xf86GetOptValInteger(pI830->Options, OPTION_CLONE_REFRESH,
@@@ -3209,8 -3179,8 +3190,8 @@@
        pI830->AccelInfoRec->NeedToSync = FALSE;
     }
  
-    for (i = 0; i < pI830->availablePipes; i++)
+    for (i = 0; i < pI830->num_pipes; i++)
 -      if (pI830->pipes[i].planeEnabled)
 +      if (pI830->pipes[i].enabled)
  	 i830PipeSetBase(pScrn, i, x, y);
  }
  
diff-tree 713c5b0899428edfea7cea0780244488115dbe1d (from ff77e9d84f2037b99a8e4ac55da0b0ac92ed6b9b)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Nov 8 19:55:31 2006 -0800

    Change the output and pipe "is it on/off" field name to "enabled".

diff --git a/src/i830.h b/src/i830.h
index 9de7394..6a8e36e 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -184,7 +184,7 @@ enum detect_status {
 struct _I830OutputRec {
    int type;
    int pipe;
-   Bool disabled;
+   Bool enabled;
    /**
     * Marks that the output and associated pipe is temporarily enabled for
     * load detection.
@@ -273,12 +273,12 @@ struct _I830OutputRec {
 };
 
 typedef struct _I830PipeRec {
+   Bool		  enabled;
    Bool		  gammaEnabled;
    int		  x;
    int		  y;
    Bool		  cursorInRange;
    Bool		  cursorShown;
-   Bool		  planeEnabled;
    DisplayModeRec curMode;
 } I830PipeRec, *I830PipePtr;
 
diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index 6b0e58c..bf35d4e 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -109,7 +109,7 @@ I830SetPipeCursor (ScrnInfoPtr pScrn, in
    CARD32 temp;
     Bool show;
     
-    if (!pI830Pipe->planeEnabled)
+    if (!pI830Pipe->enabled)
 	return;
 
     show = pI830->cursorOn && pI830Pipe->cursorInRange;
@@ -491,7 +491,7 @@ I830SetCursorPosition(ScrnInfoPtr pScrn,
 	int		thisx = x - pI830Pipe->x;
 	int		thisy = y - pI830Pipe->y;
 
-	if (!pI830Pipe->planeEnabled)
+	if (!pI830Pipe->enabled)
 	    continue;
 
 	/*
@@ -580,14 +580,14 @@ I830SetCursorColors(ScrnInfoPtr pScrn, i
 
    DPRINTF(PFX, "I830SetCursorColors\n");
 
-   if (pI830->pipes[0].planeEnabled)
+   if (pI830->pipes[0].enabled)
    {
        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].planeEnabled)
+   if (pI830->pipes[1].enabled)
    {
       OUTREG(CURSOR_B_PALETTE0, bg & 0x00ffffff);
       OUTREG(CURSOR_B_PALETTE1, fg & 0x00ffffff);
diff --git a/src/i830_display.c b/src/i830_display.c
index 72037c4..c81f454 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -70,7 +70,7 @@ i830PipeHasType (ScrnInfoPtr pScrn, int 
     int	    i;
 
     for (i = 0; i < pI830->num_outputs; i++)
-	if (!pI830->output[i].disabled && pI830->output[i].pipe == pipe)
+	if (pI830->output[i].enabled && pI830->output[i].pipe == pipe)
 	{
 	    if (pI830->output[i].type == type)
 		return TRUE;
@@ -297,7 +297,7 @@ i830PipeFindClosestMode(ScrnInfoPtr pScr
     /* Assume that there's only one output connected to the given CRTC. */
     for (i = 0; i < pI830->num_outputs; i++) {
 	if (pI830->output[i].pipe == pipe &&
-	    !pI830->output[i].disabled &&
+	    pI830->output[i].enabled &&
 	    pI830->output[i].probed_modes != NULL)
 	{
 	    pScan = pI830->output[i].probed_modes;
@@ -418,7 +418,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	       pMode->Clock);
 
     for (i = 0; i < pI830->num_outputs; i++) {
-	if (pI830->output[i].pipe != pipe || pI830->output[i].disabled)
+	if (pI830->output[i].pipe != pipe || !pI830->output[i].enabled)
 	    continue;
 
 	switch (pI830->output[i].type) {
@@ -671,7 +671,7 @@ i830DisableUnusedFunctions(ScrnInfoPtr p
     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling unused functions\n");
 
     for (i = 0; i < pI830->num_outputs; i++) {
-	if (pI830->output[i].disabled)
+	if (!pI830->output[i].enabled)
 	    pI830->output[i].dpms(pScrn, &pI830->output[i], DPMSModeOff);
     }
 
@@ -687,7 +687,7 @@ i830DisableUnusedFunctions(ScrnInfoPtr p
 	CARD32	    dspcntr, pipeconf, dpll;
 	char	    *pipe_name = pipe == 0 ? "A" : "B";
 
-	if (pI830Pipe->planeEnabled)
+	if (pI830Pipe->enabled)
 	    continue;
 	
 	dspcntr = INREG(dspcntr_reg);
@@ -730,7 +730,7 @@ i830PipeInUse (ScrnInfoPtr pScrn, int pi
     int	i;
     
     for (i = 0; i < pI830->num_outputs; i++)
-	if (!pI830->output[i].disabled && pI830->output[i].pipe == pipe)
+	if (pI830->output[i].enabled && pI830->output[i].pipe == pipe)
 	    return TRUE;
     return FALSE;
 }
@@ -756,14 +756,14 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
 #endif
 
     for (i = 0; i < pI830->availablePipes; i++)
-	pI830->pipes[i].planeEnabled = i830PipeInUse (pScrn, i);
+	pI830->pipes[i].enabled = i830PipeInUse (pScrn, i);
 
     for (i = 0; i < pI830->num_outputs; i++)
 	pI830->output[i].pre_set_mode(pScrn, &pI830->output[i], pMode);
 
     for (i = 0; i < pI830->availablePipes; i++)
     {
-	if (pI830->pipes[i].planeEnabled)
+	if (pI830->pipes[i].enabled)
 	    ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, i,
 								pMode),
 				 i, TRUE);
@@ -786,7 +786,7 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
 	/* If we might have enabled/disabled some pipes, we need to reset
 	 * cloning mode support.
 	 */
-	if (pI830->pipes[0].planeEnabled && pI830->pipes[1].planeEnabled)
+	if (pI830->pipes[0].enabled && pI830->pipes[1].enabled)
 	    pI830->Clone = TRUE;
 	else
 	    pI830->Clone = FALSE;
@@ -830,25 +830,25 @@ i830DescribeOutputConfiguration(ScrnInfo
 
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		   "  Pipe %c is %s\n",
-		   'A' + i, pI830->pipes[i].planeEnabled ? "on" : "off");
+		   'A' + i, pI830->pipes[i].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].planeEnabled ? "enabled" : "disabled",
+		   pI830->pipes[i].enabled ? "enabled" : "disabled",
 		   dspcntr & DISPPLANE_SEL_PIPE_MASK ? 'B' : 'A');
-	if (hw_pipe_enable != pI830->pipes[i].planeEnabled) {
+	if (hw_pipe_enable != pI830->pipes[i].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].planeEnabled ? "on" : "off");
+		       pI830->pipes[i].enabled ? "on" : "off");
 	}
-	if (hw_plane_enable != pI830->pipes[i].planeEnabled) {
+	if (hw_plane_enable != pI830->pipes[i].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].planeEnabled ? "on" : "off");
+		       pI830->pipes[i].enabled ? "on" : "off");
 	}
     }
 
@@ -875,7 +875,7 @@ i830DescribeOutputConfiguration(ScrnInfo
 
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		   "  Output %s is %sabled and connected to pipe %c\n",
-		   name, pI830->output[i].disabled ? "dis" : "en",
+		   name, pI830->output[i].enabled ? "en" : "dis",
 		   pI830->output[i].pipe == 0 ? 'A' : 'B');
     }
 }
@@ -915,7 +915,7 @@ i830GetLoadDetectPipe(ScrnInfoPtr pScrn,
     /* 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->disabled) {
+    if (output->enabled) {
 	int pipeconf_reg = (output->pipe == 0) ? PIPEACONF : PIPEBCONF;
 
 	if (INREG(pipeconf_reg) & PIPEACONF_ENABLE) {
@@ -936,16 +936,8 @@ i830GetLoadDetectPipe(ScrnInfoPtr pScrn,
 	}
     }
 
-    for (i = 0; i < pI830->availablePipes; i++) {
-	pipe_available[i] = TRUE;
-    }
-
-    for (i = 0; i < pI830->num_outputs; i++) {
-	if (!pI830->output[i].disabled)
-	{
-	    pipe_available[pI830->output[i].pipe] = FALSE;
-	}
-    }
+    for (i = 0; i < pI830->availablePipes; i++)
+	pipe_available[i] = i830PipeInUse(pScrn, i);
 
     for (i = 0; i < pI830->availablePipes; i++) {
 	if (pipe_available[i])
@@ -957,7 +949,7 @@ i830GetLoadDetectPipe(ScrnInfoPtr pScrn,
     }
     output->load_detect_temp = TRUE;
     output->pipe = i;
-    output->disabled = FALSE;
+    output->enabled = TRUE;
 
     I830xf86SetModeCrtc(&mode, INTERLACE_HALVE_V);
 
@@ -970,7 +962,7 @@ void
 i830ReleaseLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output)
 {
     if (output->load_detect_temp) {
-	output->disabled = TRUE;
+	output->enabled = FALSE;
 	i830DisableUnusedFunctions(pScrn);
 	output->load_detect_temp = FALSE;
     }
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 41ea21c..9e4ead0 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1485,7 +1485,7 @@ I830DRISetVBlankInterrupt (ScrnInfoPtr p
 
     if (pI830->directRenderingEnabled && pI830->drmMinor >= 5) {
 	if (on) {
-	    if (pI830->pipes[1].planeEnabled)
+	    if (pI830->pipes[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 75c3b0e..ab0af4e 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -572,7 +572,7 @@ I830LoadPalette(ScrnInfoPtr pScrn, int n
 	 dspsurf = DSPBSURF;
       }
 
-      if (pI830Pipe->planeEnabled == 0)
+      if (pI830Pipe->enabled == 0)
 	 continue;  
 
       pI830Pipe->gammaEnabled = 1;
@@ -1355,13 +1355,13 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
     * we have better configuration support in the generic RandR code
     */
    for (i = 0; i < pI830->num_outputs; i++) {
-      pI830->output[i].disabled = TRUE;
+      pI830->output[i].enabled = FALSE;
 
       switch (pI830->output[i].type) {
       case I830_OUTPUT_LVDS:
 	 /* LVDS must always be on pipe B. */
 	 pI830->output[i].pipe = 1;
-	 pI830->output[i].disabled = FALSE;
+	 pI830->output[i].enabled = TRUE;
 	 break;
       case I830_OUTPUT_ANALOG:
       case I830_OUTPUT_DVO:
@@ -1370,10 +1370,10 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 	     OUTPUT_STATUS_DISCONNECTED) {
 	    if (!i830PipeInUse(pScrn, 0)) {
 	       pI830->output[i].pipe = 0;
-	       pI830->output[i].disabled = FALSE;
+	       pI830->output[i].enabled = TRUE;
 	    } else if (!i830PipeInUse(pScrn, 1)) {
 	       pI830->output[i].pipe = 1;
-	       pI830->output[i].disabled = FALSE;
+	       pI830->output[i].enabled = TRUE;
 	    }
 	 }
 	 break;
@@ -1384,7 +1384,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    }
 
    for (i = 0; i < pI830->availablePipes; i++) {
-      pI830->pipes[i].planeEnabled = i830PipeInUse(pScrn, i);
+      pI830->pipes[i].enabled = i830PipeInUse(pScrn, i);
    }
 
 #if 0
@@ -3210,7 +3210,7 @@ i830AdjustFrame(int scrnIndex, int x, in
    }
 
    for (i = 0; i < pI830->availablePipes; i++)
-      if (pI830->pipes[i].planeEnabled)
+      if (pI830->pipes[i].enabled)
 	 i830PipeSetBase(pScrn, i, x, y);
 }
 
@@ -3471,7 +3471,7 @@ I830SaveScreen(ScreenPtr pScreen, int mo
 	    base = DSPBADDR;
 	    surf = DSPBSURF;
         }
-        if (pI830->pipes[i].planeEnabled) {
+        if (pI830->pipes[i].enabled) {
 	   temp = INREG(ctrl);
 	   if (on)
 	      temp |= DISPLAY_PLANE_ENABLE;
@@ -3520,7 +3520,7 @@ I830DisplayPowerManagementSet(ScrnInfoPt
          ctrl = DSPBCNTR;
          base = DSPBADDR;
       }
-      if (pI830->pipes[i].planeEnabled) {
+      if (pI830->pipes[i].enabled) {
 	   temp = INREG(ctrl);
 	   if (PowerManagementMode == DPMSModeOn)
 	      temp |= DISPLAY_PLANE_ENABLE;
diff --git a/src/i830_randr.c b/src/i830_randr.c
index d2228cf..184bf01 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -501,7 +501,7 @@ I830RandRCrtcNotify (RRCrtcPtr	crtc)
     for (i = 0; i < pI830->num_outputs; i++)
     {
 	output = &pI830->output[i];
-	if (!output->disabled && output->pipe == pipe)
+	if (output->enabled && output->pipe == pipe)
 	{
 	    rrout = randrp->outputs[i];
 	    outputs[numOutputs++] = rrout;
@@ -548,7 +548,7 @@ I830RandRCrtcSet (ScreenPtr	pScreen,
 
     if (display_mode != randrp->modes[pipe])
     {
-	pI830Pipe->planeEnabled = mode != NULL;
+	pI830Pipe->enabled = mode != NULL;
 	if (display_mode)
 	{
 	    if (!i830PipeSetMode (pScrn, display_mode, pipe, TRUE))
@@ -652,7 +652,7 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
 	    subpixel = SubPixelUnknown;
 	    break;
 	}
-	if (!output->disabled)
+	if (output->enabled)
 	{
 	    /* Can't flip outputs among crtcs yet */
 	    ncrtc = 1;
diff-tree ff77e9d84f2037b99a8e4ac55da0b0ac92ed6b9b (from 9b267014b55f49d9362c1d432d6ba19ddd0ad95d)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Nov 8 19:53:31 2006 -0800

    Clean up i830_crt_detect_load() a bit more.
    
    ADPA might not have been set right in some cases (DPMS-off monitor, for
    example), and a wait for vsync that the bios does was missing.

diff --git a/src/i830_crt.c b/src/i830_crt.c
index 9287a20..68006f9 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -170,7 +170,7 @@ static Bool
 i830_crt_detect_load(ScrnInfoPtr pScrn, I830OutputPtr output)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    CARD32 adpa, pipeconf, bclrpat;
+    CARD32 save_adpa, adpa, pipeconf, bclrpat;
     CARD8 st00;
     int pipeconf_reg, bclrpat_reg, dpll_reg;
     int pipe;
@@ -186,17 +186,17 @@ i830_crt_detect_load(ScrnInfoPtr pScrn, 
 	dpll_reg = DPLL_B;
     }
 
-    /* Don't try this if the DPLL isn't running. */
-    if (!(INREG(dpll_reg) & DPLL_VCO_ENABLE))
-	return FALSE;
-
     adpa = INREG(ADPA);
+    save_adpa = adpa;
 
-    /* Enable CRT output if disabled. */
-    if (!(adpa & ADPA_DAC_ENABLE)) {
-	OUTREG(ADPA, adpa | ADPA_DAC_ENABLE |
-	       ((pipe == 1) ? ADPA_PIPE_B_SELECT : 0));
-    }
+    /* Enable CRT output. */
+    adpa |= ADPA_DAC_ENABLE;
+    if (pipe == 1)
+ 	adpa |= ADPA_PIPE_B_SELECT;
+    else
+ 	adpa &= ~ADPA_PIPE_B_SELECT;
+    adpa |= ADPA_VSYNC_CNTL_ENABLE | ADPA_HSYNC_CNTL_ENABLE;
+    OUTREG(ADPA, adpa);
 
     /* Set the border color to purple.  Maybe we should save/restore this
      * reg.
@@ -204,6 +204,8 @@ i830_crt_detect_load(ScrnInfoPtr pScrn, 
     bclrpat = INREG(bclrpat_reg);
     OUTREG(bclrpat_reg, 0x00500050);
 
+    i830WaitForVblank(pScrn);
+
     /* Force the border color through the active region */
     pipeconf = INREG(pipeconf_reg);
     OUTREG(pipeconf_reg, pipeconf | PIPECONF_FORCE_BORDER);
@@ -214,7 +216,7 @@ i830_crt_detect_load(ScrnInfoPtr pScrn, 
     /* Restore previous settings */
     OUTREG(bclrpat_reg, bclrpat);
     OUTREG(pipeconf_reg, pipeconf);
-    OUTREG(ADPA, adpa);
+    OUTREG(ADPA, save_adpa);
 
     if (st00 & (1 << 4))
 	return TRUE;
diff-tree 9b267014b55f49d9362c1d432d6ba19ddd0ad95d (from 35ab689bbde5f74752598cd743d735640486b639)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Nov 8 19:39:18 2006 -0800

    Go back to only setting up outputs that have a display connected.

diff --git a/src/i830_display.c b/src/i830_display.c
index 893b9b0..72037c4 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -723,7 +723,7 @@ i830DisableUnusedFunctions(ScrnInfoPtr p
  * Return whether any outputs are connected to the specified pipe
  */
 
-static Bool
+Bool
 i830PipeInUse (ScrnInfoPtr pScrn, int pipe)
 {
     I830Ptr pI830 = I830PTR(pScrn);
diff --git a/src/i830_display.h b/src/i830_display.h
index 5c0f133..67f3c7b 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -35,3 +35,4 @@ 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);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index e6cd9bc..75c3b0e 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1355,19 +1355,27 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
     * we have better configuration support in the generic RandR code
     */
    for (i = 0; i < pI830->num_outputs; i++) {
-      pI830->output[i].disabled = FALSE;
+      pI830->output[i].disabled = TRUE;
 
       switch (pI830->output[i].type) {
       case I830_OUTPUT_LVDS:
-	 /* LVDS must live on pipe B for two-pipe devices */
-	 pI830->output[i].pipe = pI830->availablePipes - 1;
+	 /* LVDS must always be on pipe B. */
+	 pI830->output[i].pipe = 1;
+	 pI830->output[i].disabled = FALSE;
 	 break;
       case I830_OUTPUT_ANALOG:
-	 pI830->output[i].pipe = 0;
-	 break;
       case I830_OUTPUT_DVO:
       case I830_OUTPUT_SDVO:
-	 pI830->output[i].pipe = 0;
+	 if (pI830->output[i].detect(pScrn, &pI830->output[i]) !=
+	     OUTPUT_STATUS_DISCONNECTED) {
+	    if (!i830PipeInUse(pScrn, 0)) {
+	       pI830->output[i].pipe = 0;
+	       pI830->output[i].disabled = FALSE;
+	    } else if (!i830PipeInUse(pScrn, 1)) {
+	       pI830->output[i].pipe = 1;
+	       pI830->output[i].disabled = FALSE;
+	    }
+	 }
 	 break;
       default:
 	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unhandled output type\n");
@@ -1375,6 +1383,10 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       }
    }
 
+   for (i = 0; i < pI830->availablePipes; i++) {
+      pI830->pipes[i].planeEnabled = i830PipeInUse(pScrn, i);
+   }
+
 #if 0
    pI830->CloneRefresh = 60; /* default to 60Hz */
    if (xf86GetOptValInteger(pI830->Options, OPTION_CLONE_REFRESH,
diff-tree 35ab689bbde5f74752598cd743d735640486b639 (from f1ff01e31eb8e9dc05190bf1a8b318d4f587f64a)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Nov 8 19:35:49 2006 -0800

    Fix i830DisableUnusedFunctions after pipe structure change.
    
    Using "pipe" instead of the index "i" meant pipe(3) got referenced instead of
    a nice small integer.  Oops.

diff --git a/src/i830_display.c b/src/i830_display.c
index c1fc562..893b9b0 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -666,7 +666,7 @@ void
 i830DisableUnusedFunctions(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    int i;
+    int i, pipe;
 
     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling unused functions\n");
 
@@ -679,8 +679,8 @@ 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 (i = 0; i < pI830->availablePipes; i++) {
-	I830PipePtr pI830Pipe = &pI830->pipes[i];
+    for (pipe = 0; pipe < pI830->availablePipes; pipe++) {
+	I830PipePtr pI830Pipe = &pI830->pipes[pipe];
 	int	    dspcntr_reg = pipe == 0 ? DSPACNTR : DSPBCNTR;
 	int	    pipeconf_reg = pipe == 0 ? PIPEACONF : PIPEBCONF;
 	int	    dpll_reg = pipe == 0 ? DPLL_A : DPLL_B;
diff-tree f1ff01e31eb8e9dc05190bf1a8b318d4f587f64a (from 0b2d36d4f038c4e8fa08632b6f1368627f010392)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Sat Nov 4 00:46:18 2006 -0800

    Eliminate operatingDevices member and PIPE_* values.
    
    operatingDevices and MonType1/MonType2 duplicate information already stored
    in the device structures. Eliminate them and replace uses with direct
    references to the appropriate other data.
    (cherry picked from 3ab7f9693217d8fe993bdc94c376b219b0082961 commit)

diff --git a/src/i830.h b/src/i830.h
index 84c0dbe..9de7394 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -86,26 +86,6 @@ typedef struct _I830OutputRec I830Output
  * Paulo César Pereira de Andrade <pcpa at conectiva.com.br>.
  */
 
-#define PIPE_CRT_ID	0
-#define PIPE_TV_ID    	1
-#define PIPE_DFP_ID	2
-#define PIPE_LFP_ID	3
-#define PIPE_CRT2_ID	4
-#define PIPE_TV2_ID	5
-#define PIPE_DFP2_ID	6
-#define PIPE_LFP2_ID	7
-#define PIPE_NUM_ID	8
-
-#define PIPE_NONE	0<<0
-#define PIPE_CRT	1<<0
-#define PIPE_TV		1<<1
-#define PIPE_DFP	1<<2
-#define PIPE_LFP	1<<3
-#define PIPE_CRT2	1<<4
-#define PIPE_TV2	1<<5
-#define PIPE_DFP2	1<<6
-#define PIPE_LFP2	1<<7
-
 typedef struct _I830Rec *I830Ptr;
 
 typedef void (*I830WriteIndexedByteFunc)(I830Ptr pI830, IOADDRESS addr,
@@ -319,7 +299,9 @@ typedef struct _I830Rec {
    int CloneVDisplay;
 
    I830EntPtr entityPrivate;	
+#if 0
    int pipe, origPipe;
+#endif
    int init;
 
    unsigned int bufferOffset;		/* for I830SelectBuffer */
@@ -396,9 +378,6 @@ typedef struct _I830Rec {
    Bool CursorIsARGB;
    CursorPtr pCurs;
 
-   int MonType1;
-   int MonType2;
-
    DGAModePtr DGAModes;
    int numDGAModes;
    Bool DGAactive;
@@ -474,7 +453,6 @@ typedef struct _I830Rec {
    CARD32 saveSWF4;
 
    Bool checkDevices;
-   int operatingDevices;
 
    /* [0] is Pipe A, [1] is Pipe B. */
    int availablePipes;
@@ -668,6 +646,10 @@ extern Bool I830FixOffset(ScrnInfoPtr pS
 extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg,
 			char *name);
 
+/* i830_display.c */
+Bool
+i830PipeHasType (ScrnInfoPtr pScrn, int pipe, int type);
+
 /* i830_crt.c */
 void i830_crt_init(ScrnInfoPtr pScrn);
 
diff --git a/src/i830_crt.c b/src/i830_crt.c
index 4c704b2..9287a20 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -170,7 +170,7 @@ static Bool
 i830_crt_detect_load(ScrnInfoPtr pScrn, I830OutputPtr output)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    CARD32 adpa, pipeconf;
+    CARD32 adpa, pipeconf, bclrpat;
     CARD8 st00;
     int pipeconf_reg, bclrpat_reg, dpll_reg;
     int pipe;
@@ -198,9 +198,10 @@ i830_crt_detect_load(ScrnInfoPtr pScrn, 
 	       ((pipe == 1) ? ADPA_PIPE_B_SELECT : 0));
     }
 
-    /* Set the border color to red, green.  Maybe we should save/restore this
+    /* Set the border color to purple.  Maybe we should save/restore this
      * reg.
      */
+    bclrpat = INREG(bclrpat_reg);
     OUTREG(bclrpat_reg, 0x00500050);
 
     /* Force the border color through the active region */
@@ -211,6 +212,7 @@ i830_crt_detect_load(ScrnInfoPtr pScrn, 
     st00 = pI830->readStandard(pI830, 0x3c2);
 
     /* Restore previous settings */
+    OUTREG(bclrpat_reg, bclrpat);
     OUTREG(pipeconf_reg, pipeconf);
     OUTREG(ADPA, adpa);
 
diff --git a/src/i830_display.c b/src/i830_display.c
index 2f9b3fd..c1fc562 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -61,6 +61,24 @@ i830PrintPll(char *prefix, int refclk, i
 }
 
 /**
+ * Returns whether any output on the specified pipe is an LVDS output
+ */
+Bool
+i830PipeHasType (ScrnInfoPtr pScrn, int pipe, int type)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    int	    i;
+
+    for (i = 0; i < pI830->num_outputs; i++)
+	if (!pI830->output[i].disabled && pI830->output[i].pipe == pipe)
+	{
+	    if (pI830->output[i].type == type)
+		return TRUE;
+	}
+    return FALSE;
+}
+
+/**
  * Returns whether the given set of divisors are valid for a given refclk with
  * the given outputs.
  *
@@ -68,7 +86,7 @@ i830PrintPll(char *prefix, int refclk, i
  * clk = refclk * (5 * m1 + m2) / n / (p1 * p2)
  */
 static Bool
-i830PllIsValid(ScrnInfoPtr pScrn, int outputs, int refclk, int m1, int m2,
+i830PllIsValid(ScrnInfoPtr pScrn, int pipe, int refclk, int m1, int m2,
 	       int n, int p1, int p2)
 {
     I830Ptr pI830 = I830PTR(pScrn);
@@ -87,7 +105,7 @@ i830PllIsValid(ScrnInfoPtr pScrn, int ou
 	max_n = 8;
 	min_p1 = 1;
 	max_p1 = 8;
-	if (outputs & PIPE_LCD_ACTIVE) {
+	if (i830PipeHasType (pScrn, pipe, I830_OUTPUT_LVDS)) {
 	    min_p = 7;
 	    max_p = 98;
 	} else {
@@ -153,7 +171,7 @@ i830PllIsValid(ScrnInfoPtr pScrn, int ou
  * clk = refclk * (5 * m1 + m2) / n / (p1 * p2)
  */
 static Bool
-i830FindBestPLL(ScrnInfoPtr pScrn, int outputs, int target, int refclk,
+i830FindBestPLL(ScrnInfoPtr pScrn, int pipe, int target, int refclk,
 		int *outm1, int *outm2, int *outn, int *outp1, int *outp2)
 {
     I830Ptr pI830 = I830PTR(pScrn);
@@ -170,7 +188,7 @@ i830FindBestPLL(ScrnInfoPtr pScrn, int o
 	max_n = 8;
 	min_p1 = 1;
 	max_p1 = 8;
-	if (outputs & PIPE_LCD_ACTIVE) {
+	if (i830PipeHasType (pScrn, pipe, I830_OUTPUT_LVDS)) {
 	    if (target < 200000) /* XXX: Is this the right cutoff? */
 		p2 = 14;
 	    else
@@ -203,7 +221,7 @@ i830FindBestPLL(ScrnInfoPtr pScrn, int o
 		for (p1 = min_p1; p1 <= max_p1; p1++) {
 		    int clock, this_err;
 
-		    if (!i830PllIsValid(pScrn, outputs, refclk, m1, m2, n,
+		    if (!i830PllIsValid(pScrn, pipe, refclk, m1, m2, n,
 					p1, p2)) {
 			continue;
 		    }
@@ -377,7 +395,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     Bool ok, is_sdvo = FALSE, is_dvo = FALSE;
     Bool is_crt = FALSE, is_lvds = FALSE, is_tv = FALSE;
     int refclk, pixel_clock;
-    int outputs, i;
+    int i;
     int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
     int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
     int fp_reg = (pipe == 0) ? FPA0 : FPB0;
@@ -393,11 +411,6 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
     int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
 
-    if (pipe == 0)
-	outputs = pI830->operatingDevices & 0xff;
-    else
-	outputs = (pI830->operatingDevices >> 8) & 0xff;
-
     if (I830ModesEqual(&pI830Pipe->curMode, pMode))
 	return TRUE;
 
@@ -502,7 +515,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     } else {
 	refclk = 48000;
     }
-    ok = i830FindBestPLL(pScrn, outputs, pixel_clock, refclk, &m1, &m2, &n,
+    ok = i830FindBestPLL(pScrn, pipe, pixel_clock, refclk, &m1, &m2, &n,
 			 &p1, &p2);
     if (!ok) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
@@ -707,6 +720,22 @@ i830DisableUnusedFunctions(ScrnInfoPtr p
 }
 
 /**
+ * Return whether any outputs are connected to the specified pipe
+ */
+
+static Bool
+i830PipeInUse (ScrnInfoPtr pScrn, int pipe)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    int	i;
+    
+    for (i = 0; i < pI830->num_outputs; i++)
+	if (!pI830->output[i].disabled && pI830->output[i].pipe == pipe)
+	    return TRUE;
+    return FALSE;
+}
+
+/**
  * This function configures the screens in clone mode on
  * all active outputs using a mode similar to the specified mode.
  */
@@ -726,8 +755,8 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
     didLock = I830DRILock(pScrn);
 #endif
 
-    pI830->pipes[0].planeEnabled = (pI830->operatingDevices & 0xff) != 0;
-    pI830->pipes[1].planeEnabled = (pI830->operatingDevices & 0xff00) != 0;
+    for (i = 0; i < pI830->availablePipes; i++)
+	pI830->pipes[i].planeEnabled = i830PipeInUse (pScrn, i);
 
     for (i = 0; i < pI830->num_outputs; i++)
 	pI830->output[i].pre_set_mode(pScrn, &pI830->output[i], pMode);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 78f83d7..e6cd9bc 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -387,88 +387,6 @@ I830ProbeDDC(ScrnInfoPtr pScrn, int inde
    ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
 }
 
-/*
- * Returns a string matching the device corresponding to the first bit set
- * in "device".  savedDevice is then set to device with that bit cleared.
- * Subsequent calls with device == -1 will use savedDevice.
- */
-
-static const char *displayDevices[] = {
-   "CRT",
-   "TV",
-   "DFP (digital flat panel)",
-   "LFP (local flat panel)",
-   "CRT2 (second CRT)",
-   "TV2 (second TV)",
-   "DFP2 (second digital flat panel)",
-   "LFP2 (second local flat panel)",
-   NULL
-};
-
-static const char *
-DeviceToString(int device)
-{
-   static int savedDevice = -1;
-   int bit = 0;
-   const char *name;
-
-   if (device == -1) {
-      device = savedDevice;
-      bit = 0;
-   }
-
-   if (device == -1)
-      return NULL;
-
-   while (displayDevices[bit]) {
-      if (device & (1 << bit)) {
-	 name = displayDevices[bit];
-	 savedDevice = device & ~(1 << bit);
-	 bit++;
-	 return name;
-      }
-      bit++;
-   }
-   return NULL;
-}
-
-static void
-PrintDisplayDeviceInfo(ScrnInfoPtr pScrn)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   int pipe, n;
-   int displays;
-
-   DPRINTF(PFX, "PrintDisplayDeviceInfo\n");
-
-   displays = pI830->operatingDevices;
-   if (displays == -1) {
-      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		 "No active display devices.\n");
-      return;
-   }
-
-   /* Check for active devices connected to each display pipe. */
-   for (n = 0; n < pI830->availablePipes; n++) {
-      pipe = ((displays >> PIPE_SHIFT(n)) & PIPE_ACTIVE_MASK);
-      if (pipe) {
-	 const char *name;
-
-	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		    "Currently active displays on Pipe %c:\n", PIPE_NAME(n));
-	 name = DeviceToString(pipe);
-	 do {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\t%s\n", name);
-	    name = DeviceToString(-1);
-	 } while (name);
-
-      } else {
-	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		    "No active displays on Pipe %c.\n", PIPE_NAME(n));
-      }
-   }
-}
-
 static int
 I830DetectMemory(ScrnInfoPtr pScrn)
 {
@@ -1268,9 +1186,10 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 
    I830PreInitDDC(pScrn);
 
-   pI830->MonType1 = PIPE_NONE;
-   pI830->MonType2 = PIPE_NONE;
-
+#if 0
+   /*
+    * This moves to generic RandR-based configuration code
+    */
    if ((s = xf86GetOptValString(pI830->Options, OPTION_MONITOR_LAYOUT)) &&
       I830IsPrimary(pScrn)) {
       char *Mon1;
@@ -1355,7 +1274,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       else
 	 pI830->pipe = 1;
 
-      pI830->operatingDevices = (pI830->MonType2 << 8) | pI830->MonType1;
    } else if (I830IsPrimary(pScrn)) {
       /* Choose a default set of outputs to use based on what we've detected.
        *
@@ -1401,7 +1319,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 	 pI830->pipe = 0;
       else
 	 pI830->pipe = 1;
-      pI830->operatingDevices = (pI830->MonType2 << 8) | pI830->MonType1;
 
       if (pI830->MonType1 != 0 && pI830->MonType2 != 0) {
          xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
@@ -1410,11 +1327,11 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       }
    } else {
       I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
-      pI830->operatingDevices = pI8301->operatingDevices;
       pI830->pipe = !pI8301->pipe;
       pI830->MonType1 = pI8301->MonType1;
       pI830->MonType2 = pI8301->MonType2;
    }
+#endif
 
    if (xf86ReturnOptValBool(pI830->Options, OPTION_CLONE, FALSE)) {
       if (pI830->availablePipes == 1) {
@@ -1434,38 +1351,23 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    }
 
 
-   /* Perform the pipe assignment of outputs.  This code shouldn't exist,
-    * but for now we're supporting the existing MonitorLayout configuration
-    * scheme.
+   /* 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].disabled = FALSE;
 
       switch (pI830->output[i].type) {
       case I830_OUTPUT_LVDS:
-	 if (pI830->MonType1 & PIPE_LFP)
-	    pI830->output[i].pipe = 0;
-	 else if (pI830->MonType2 & PIPE_LFP)
-	    pI830->output[i].pipe = 1;
-	 else
-	    pI830->output[i].disabled = TRUE;
+	 /* LVDS must live on pipe B for two-pipe devices */
+	 pI830->output[i].pipe = pI830->availablePipes - 1;
 	 break;
       case I830_OUTPUT_ANALOG:
-	 if (pI830->MonType1 & PIPE_CRT)
-	    pI830->output[i].pipe = 0;
-	 else if (pI830->MonType2 & PIPE_CRT)
-	    pI830->output[i].pipe = 1;
-	 else
-	    pI830->output[i].disabled = TRUE;
+	 pI830->output[i].pipe = 0;
 	 break;
       case I830_OUTPUT_DVO:
       case I830_OUTPUT_SDVO:
-	 if (pI830->MonType1 & PIPE_DFP)
-	    pI830->output[i].pipe = 0;
-	 else if (pI830->MonType2 & PIPE_DFP)
-	    pI830->output[i].pipe = 1;
-	 else
-	    pI830->output[i].disabled = TRUE;
+	 pI830->output[i].pipe = 0;
 	 break;
       default:
 	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unhandled output type\n");
@@ -1473,8 +1375,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       }
    }
 
-   
-
+#if 0
    pI830->CloneRefresh = 60; /* default to 60Hz */
    if (xf86GetOptValInteger(pI830->Options, OPTION_CLONE_REFRESH,
 			    &(pI830->CloneRefresh))) {
@@ -1497,6 +1398,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
          return FALSE;
       }
    }
+#endif
 
    pI830->rotation = RR_Rotate_0;
    if ((s = xf86GetOptValString(pI830->Options, OPTION_ROTATE))) {
@@ -1672,8 +1574,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       }
    }
 
-   PrintDisplayDeviceInfo(pScrn);
-
+#if 0
    if (xf86IsEntityShared(pScrn->entityList[0])) {
       if (!I830IsPrimary(pScrn)) {
 	 /* This could be made to work with a little more fiddling */
@@ -1689,6 +1590,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       xf86DrvMsg(pScrn->scrnIndex, from, "Display is using Pipe %s\n",
 		pI830->pipe ? "B" : "A");
    }
+#endif
 
    /* Alloc our pointers for the primary head */
    if (I830IsPrimary(pScrn)) {
@@ -2898,17 +2800,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    }
 #endif
 
-   if (xf86IsEntityShared(pScrn->entityList[0])) {
-      /* PreInit failed on the second head, so make sure we turn it off */
-      if (I830IsPrimary(pScrn) && !pI830->entityPrivate->pScrn_2) {
-         if (pI830->pipe == 0) {
-            pI830->operatingDevices &= 0xFF;
-         } else {
-            pI830->operatingDevices &= 0xFF00;
-         }
-      }
-   }
-
    pI830->starting = TRUE;
 
    /* Alloc our pointers for the primary head */
@@ -3295,6 +3186,7 @@ i830AdjustFrame(int scrnIndex, int x, in
 {
    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
    I830Ptr pI830 = I830PTR(pScrn);
+   int i;
 
    DPRINTF(PFX, "i830AdjustFrame: y = %d (+ %d), x = %d (+ %d)\n",
 	   x, pI830->xoffset, y, pI830->yoffset);
@@ -3305,9 +3197,9 @@ i830AdjustFrame(int scrnIndex, int x, in
       pI830->AccelInfoRec->NeedToSync = FALSE;
    }
 
-   i830PipeSetBase(pScrn, pI830->pipe, x, y);
-   if (pI830->Clone)
-      i830PipeSetBase(pScrn, !pI830->pipe, x, y);
+   for (i = 0; i < pI830->availablePipes; i++)
+      if (pI830->pipes[i].planeEnabled)
+	 i830PipeSetBase(pScrn, i, x, y);
 }
 
 static void
diff --git a/src/i830_randr.c b/src/i830_randr.c
index 4f3cbee..d2228cf 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -492,45 +492,31 @@ I830RandRCrtcNotify (RRCrtcPtr	crtc)
     I830PipePtr		pI830Pipe = &pI830->pipes[pipe];
     int			i, j;
     DisplayModePtr	pipeMode = &pI830Pipe->curMode;
-    int			pipe_type;
 
     x = pI830Pipe->x;
     y = pI830Pipe->y;
     rotation = RR_Rotate_0;
     numOutputs = 0;
+    mode = NULL;
     for (i = 0; i < pI830->num_outputs; i++)
     {
 	output = &pI830->output[i];
-	/*
-	 * Valid crtcs
-	 */
-	switch (output->type) {
-	case I830_OUTPUT_DVO:
-	case I830_OUTPUT_SDVO:
-	    pipe_type = PIPE_DFP;
-	    break;
-	case I830_OUTPUT_ANALOG:
-	    pipe_type = PIPE_CRT;
-	    break;
-	case I830_OUTPUT_LVDS:
-	    pipe_type = PIPE_LFP;
-	    break;
-	case I830_OUTPUT_TVOUT:
-	    pipe_type = PIPE_TV;
-	    break;
-	default:
-	    pipe_type = PIPE_NONE;
-	    break;
-	}
-	if (pI830->operatingDevices & (pipe_type << (pipe << 3)))
+	if (!output->disabled && output->pipe == pipe)
 	{
 	    rrout = randrp->outputs[i];
 	    outputs[numOutputs++] = rrout;
+	    /*
+	     * We make copies of modes, so pointer equality 
+	     * isn't sufficient
+	     */
 	    for (j = 0; j < rrout->numModes; j++)
 	    {
 		DisplayModePtr	outMode = rrout->modes[j]->devPrivate;
 		if (I830ModesEqual(pipeMode, outMode))
+		{
 		    mode = rrout->modes[j];
+		    break;
+		}
 	    }
 	}
     }
@@ -571,14 +557,7 @@ I830RandRCrtcSet (ScreenPtr	pScreen,
 	}
 	else
 	{
-	    CARD32  operatingDevices = pI830->operatingDevices;
-
-	    if (pipe == 0)
-		pI830->operatingDevices &= ~0xff;
-	    else
-		pI830->operatingDevices &= ~0xff00;
 	    i830DisableUnusedFunctions (pScrn);
-	    pI830->operatingDevices = operatingDevices;
 	}
 	randrp->modes[pipe] = display_mode;
     }
@@ -614,7 +593,6 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
     int			p;
     int			clone_types;
     int			crtc_types;
-    int			pipe_type;
     int			pipe;
     int			subpixel;
     DisplayModePtr	modes, mode;
@@ -644,7 +622,6 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
 	    clone_types = ((1 << I830_OUTPUT_ANALOG) |
 			   (1 << I830_OUTPUT_DVO) |
 			   (1 << I830_OUTPUT_SDVO));
-	    pipe_type = PIPE_DFP;
 	    subpixel = SubPixelHorizontalRGB;
 	    break;
 	case I830_OUTPUT_ANALOG:
@@ -652,13 +629,11 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
 	    clone_types = ((1 << I830_OUTPUT_ANALOG) |
 			   (1 << I830_OUTPUT_DVO) |
 			   (1 << I830_OUTPUT_SDVO));
-	    pipe_type = PIPE_CRT;
 	    subpixel = SubPixelNone;
 	    break;
 	case I830_OUTPUT_LVDS:
 	    crtc_types = (1 << 1);
 	    clone_types = (1 << I830_OUTPUT_LVDS);
-	    pipe_type = PIPE_LFP;
 	    subpixel = SubPixelHorizontalRGB;
 	    possibleOptions = (RROutputOptionScaleNone|
 			       RROutputOptionScaleMaxAspect |
@@ -669,32 +644,27 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
 	    crtc_types = ((1 << 0) |
 			  (1 << 1));
 	    clone_types = (1 << I830_OUTPUT_TVOUT);
-	    pipe_type = PIPE_TV;
 	    subpixel = SubPixelNone;
 	    break;
 	default:
 	    crtc_types = 0;
 	    clone_types = 0;
-	    pipe_type = PIPE_NONE;
 	    subpixel = SubPixelUnknown;
 	    break;
 	}
-	ncrtc = 0;
-	pipe = -1;
-	crtc = NULL;
-	for (j = 0; j < pI830->availablePipes; j++)
+	if (!output->disabled)
 	{
-#if 0
-	     /* Can't flip outputs among crtcs yet */
-	    if (crtc_types & (1 << j))
-		crtcs[ncrtc++] = randrp->crtcs[j];
-#endif
-	    if (pI830->operatingDevices & (pipe_type << (j << 3)))
-	    {
-		pipe = j;
-		crtc = randrp->crtcs[j];
-		crtcs[ncrtc++] = crtc;
-	    }
+	    /* Can't flip outputs among crtcs yet */
+	    ncrtc = 1;
+	    pipe = output->pipe;
+	    crtc = randrp->crtcs[pipe];
+	    crtcs[0] = randrp->crtcs[pipe];
+	}
+	else
+	{
+	    ncrtc = 0;
+	    pipe = -1;
+	    crtc = NULL;
 	}
 	if (!RROutputSetCrtcs (randrp->outputs[i], crtcs, ncrtc))
 	    return FALSE;
diff --git a/src/i830_video.c b/src/i830_video.c
index 47f4a03..a5cd77c 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -722,7 +722,7 @@ I830SetupImageVideoOverlay(ScreenPtr pSc
    pPriv->brightness = 0;
    pPriv->contrast = 64;
    pPriv->saturation = 128;
-   pPriv->pipe = pI830->pipe; /* default to current pipe */
+   pPriv->pipe = 0;  /* XXX must choose pipe wisely */
    pPriv->linear = NULL;
    pPriv->currentBuf = 0;
    pPriv->gamma5 = 0xc0c0c0;
@@ -3592,6 +3592,8 @@ I830VideoSwitchModeAfter(ScrnInfoPtr pSc
 
    pPriv->overlayOK = TRUE;
 
+#if 0
+   /* XXX Must choose pipe wisely */
    /* ensure pipe is updated on mode switch */
    if (!pI830->Clone) {
       if (pPriv->pipe != pI830->pipe) {
@@ -3600,6 +3602,7 @@ I830VideoSwitchModeAfter(ScrnInfoPtr pSc
          pPriv->pipe = pI830->pipe;
       }
    }
+#endif
 
    if (!IS_I965G(pI830)) {
       if (pPriv->pipe == 0) {
@@ -3628,8 +3631,8 @@ I830VideoSwitchModeAfter(ScrnInfoPtr pSc
    }
 
    /* Check we have an LFP connected */
-   if ((pPriv->pipe == 1 && pI830->operatingDevices & (PIPE_LFP << 8)) ||
-       (pPriv->pipe == 0 && pI830->operatingDevices & PIPE_LFP) ) {
+   if (i830PipeHasType (pScrn, pPriv->pipe, I830_OUTPUT_LVDS)) 
+   {
       size = pPriv->pipe ? INREG(PIPEBSRC) : INREG(PIPEASRC);
       hsize = (size >> 16) & 0x7FF;
       vsize = size & 0x7FF;
diff-tree 0b2d36d4f038c4e8fa08632b6f1368627f010392 (from d0ef9e99acb9e999e1b6d3eb76edc6355555043b)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Fri Nov 3 23:29:12 2006 -0800

    Use pI830->availablePipes instead of MAX_DISPLAY_PIPES everywhere
    (cherry picked from e4bcec796e80e9fd66ab0c36394f5946915531f1 commit)

diff --git a/src/i830.h b/src/i830.h
index b93ab3c..84c0dbe 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -313,8 +313,6 @@ typedef struct _I830Rec {
     */
    DisplayModePtr savedCurrentMode;
 
-   I830PipeRec	  pipes[MAX_DISPLAY_PIPES];
-   
    Bool Clone;
    int CloneRefresh;
    int CloneHDisplay;
@@ -481,7 +479,8 @@ typedef struct _I830Rec {
    /* [0] is Pipe A, [1] is Pipe B. */
    int availablePipes;
    /* [0] is display plane A, [1] is display plane B. */
-
+   I830PipeRec	  pipes[MAX_DISPLAY_PIPES];
+   
    /* Driver phase/state information */
    Bool preinit;
    Bool starting;
diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index 0b7e772..6b0e58c 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -180,11 +180,11 @@ I830InitHWCursor(ScrnInfoPtr pScrn)
    int i;
 
    DPRINTF(PFX, "I830InitHWCursor\n");
-   for (i = 0; i < MAX_DISPLAY_PIPES; i++) 
+   for (i = 0; i < pI830->availablePipes; i++) 
       pI830->pipes[i].cursorShown = FALSE;
    /* Initialise the HW cursor registers, leaving the cursor hidden. */
    if (IS_MOBILE(pI830) || IS_I9XX(pI830)) {
-      for (i = 0; i < MAX_DISPLAY_PIPES; i++)
+      for (i = 0; i < pI830->availablePipes; i++)
       {
 	 int   cursor_control = i == 0 ? CURSOR_A_CONTROL : CURSOR_B_CONTROL;
 	 temp = INREG(cursor_control);
@@ -484,7 +484,7 @@ I830SetCursorPosition(ScrnInfoPtr pScrn,
     x -= hotspotx;
     y -= hotspoty;
 
-    for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++)
+    for (pipe = 0; pipe < pI830->availablePipes; pipe++)
     {
 	I830PipePtr	pI830Pipe = &pI830->pipes[pipe];
 	DisplayModePtr	mode = &pI830Pipe->curMode;
@@ -550,7 +550,7 @@ I830ShowCursor(ScrnInfoPtr pScrn)
 	   pI830->CursorMemARGB->Physical, pI830->CursorMemARGB->Start);
 
     pI830->cursorOn = TRUE;
-    for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++)
+    for (pipe = 0; pipe < pI830->availablePipes; pipe++)
 	I830SetPipeCursor (pScrn, pipe, TRUE);
 }
 
@@ -563,7 +563,7 @@ I830HideCursor(ScrnInfoPtr pScrn)
    DPRINTF(PFX, "I830HideCursor\n");
 
    pI830->cursorOn = FALSE;
-    for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++)
+    for (pipe = 0; pipe < pI830->availablePipes; pipe++)
 	I830SetPipeCursor (pScrn, pipe, TRUE);
 }
 
diff --git a/src/i830_display.c b/src/i830_display.c
index 672bc53..2f9b3fd 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -666,7 +666,7 @@ 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 (i = 0; i < MAX_DISPLAY_PIPES; i++) {
+    for (i = 0; i < pI830->availablePipes; i++) {
 	I830PipePtr pI830Pipe = &pI830->pipes[i];
 	int	    dspcntr_reg = pipe == 0 ? DSPACNTR : DSPBCNTR;
 	int	    pipeconf_reg = pipe == 0 ? PIPEACONF : PIPEBCONF;
@@ -732,7 +732,7 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
     for (i = 0; i < pI830->num_outputs; i++)
 	pI830->output[i].pre_set_mode(pScrn, &pI830->output[i], pMode);
 
-    for (i = 0; i < MAX_DISPLAY_PIPES; i++)
+    for (i = 0; i < pI830->availablePipes; i++)
     {
 	if (pI830->pipes[i].planeEnabled)
 	    ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, i,
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 8dcda42..78f83d7 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3413,7 +3413,7 @@ I830EnterVT(int scrnIndex, int flags)
    SetHWOperatingState(pScrn);
 
    /* Mark that we'll need to re-set the mode for sure */
-   for (i = 0; i < MAX_DISPLAY_PIPES; i++)
+   for (i = 0; i < pI830->availablePipes; i++)
       memset(&pI830->pipes[i].curMode, 0, sizeof(pI830->pipes[i].curMode));
 
    if (!i830SetMode(pScrn, pScrn->currentMode))
diff --git a/src/i830_randr.c b/src/i830_randr.c
index 8b6ad49..4f3cbee 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -682,7 +682,7 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
 	ncrtc = 0;
 	pipe = -1;
 	crtc = NULL;
-	for (j = 0; j < MAX_DISPLAY_PIPES; j++)
+	for (j = 0; j < pI830->availablePipes; j++)
 	{
 #if 0
 	     /* Can't flip outputs among crtcs yet */
@@ -782,7 +782,7 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
 	if (!RROutputSetClones (randrp->outputs[i], clones, nclone))
 	    return FALSE;
     }
-    for (i = 0; i < MAX_DISPLAY_PIPES; i++)
+    for (i = 0; i < pI830->availablePipes; i++)
 	I830RandRCrtcNotify (randrp->crtcs[i]);
     return TRUE;
 }
@@ -815,7 +815,7 @@ I830RandRCreateScreenResources12 (Screen
     /*
      * Create RandR resources, then probe them
      */
-    for (i = 0; i < MAX_DISPLAY_PIPES; i++)
+    for (i = 0; i < pI830->availablePipes; i++)
     {
 	randrp->crtcs[i] = RRCrtcCreate (pScreen, (void *) i);
 	RRCrtcGammaSetSize (randrp->crtcs[i], 256);
@@ -851,7 +851,7 @@ I830RandRCreateScreenResources12 (Screen
 				mmHeight);
     }
 
-    for (i = 0; i < MAX_DISPLAY_PIPES; i++)
+    for (i = 0; i < pI830->availablePipes; i++)
 	i830PipeSetBase(pScrn, i, 0, 0);
 
     return I830RandRSetInfo12 (pScreen);
diff-tree d0ef9e99acb9e999e1b6d3eb76edc6355555043b (from 94a3731c2b4f2ea2e696a8c87dccc0d214d41e8e)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Nov 6 18:30:46 2006 -0800

    Restore PFIT_CONTROL before turning the LVDS back on in the restore method.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 79b4f60..8dcda42 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2380,6 +2380,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]);
    }
@@ -2409,8 +2411,6 @@ RestoreHWState(ScrnInfoPtr pScrn)
    OUTREG(SWF31, pI830->saveSWF[15]);
    OUTREG(SWF32, pI830->saveSWF[16]);
 
-   OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL);
-
    i830CompareRegsToSnapshot(pScrn);
 
    return TRUE;
diff-tree 94a3731c2b4f2ea2e696a8c87dccc0d214d41e8e (from 27df2ff7908ea7ea2943a5f3445e12dbc24d97c9)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Nov 6 18:26:48 2006 -0800

    Move PFIT_CONTROL disable for G965 up before post_set_mode.
    
    Also, remove setting of some other random registers that appears to have
    been spammed in at the same time, and don't try to disable on the I830, before
    this register existed.

diff --git a/src/i830_display.c b/src/i830_display.c
index e36b5ef..672bc53 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -609,21 +609,20 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     OUTREG(fp_reg, fp);
     OUTREG(dpll_reg, dpll);
 
+    /*
+     * If the panel fitter is stuck on our pipe, turn it off.
+     * The LVDS output will set it as necessary in post_set_mode.
+     */
+    if (!IS_I830(pI830)) {
+	if (((INREG(PFIT_CONTROL) >> 29) & 0x3) == pipe)
+	    OUTREG(PFIT_CONTROL, 0);
+    }
+
     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);
     }
 
-    /*
-     * If the panel fitter is stuck on our pipe, turn it off
-     * the LVDS output will whack it correctly if it needs it
-     */
-    if (((INREG(PFIT_CONTROL) >> 29) & 0x3) == pipe)
-	OUTREG(PFIT_CONTROL, 0);
-	   
-    OUTREG(PFIT_PGM_RATIOS, 0x10001000);
-    OUTREG(DSPARB, (47 << 0) | (95 << 7));
-    
     OUTREG(htot_reg, htot);
     OUTREG(hblank_reg, hblank);
     OUTREG(hsync_reg, hsync);
diff-tree beb89163d73376e70870e6e2a6b19863f3a058b1 (from 997e8c9bb4235cab1fff4738387df9afcbea0a03)
Author: Keith Packard <keithp at mandolin.keithp.com>
Date:   Sun Nov 5 19:06:45 2006 -0800

    DSPSURF must be page aligned. Place intra-screen offset in DSPBASE.
    
    DSPASURF/DSPBSURF can only take page aligned values, ignoring
    the lower order bits. So, place the offset for the output
    within the frame buffer in the DSPABASE/DSPBBASE registers instead.

diff --git a/src/i830_display.c b/src/i830_display.c
index 077e318..6804a4d 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -268,8 +268,8 @@ i830PipeSetBase(ScrnInfoPtr pScrn, int p
     }
 
     if (IS_I965G(pI830)) {
-	OUTREG(dspbase, 0);
-	OUTREG(dspsurf, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
+	OUTREG(dspbase, ((y * pScrn->displayWidth + x) * pI830->cpp));
+	OUTREG(dspsurf, Start);
     } else {
 	OUTREG(dspbase, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
     }
diff-tree 997e8c9bb4235cab1fff4738387df9afcbea0a03 (from 5a355c72614ed77f2000e5ede45f3ff5990c79d9)
Author: Keith Packard <keithp at mandolin.keithp.com>
Date:   Sun Nov 5 18:56:33 2006 -0800

    Don't allocate stuff in the first 256K of video memory (GATT?)
    
    Letting the ring buffer or other objects be allocated within the lowest
    portion of memory appears to trash some memory mapping data; I'm assuming
    this is the GATT table on the 965. Just marking this out of bounds for
    allocation fixes this problem.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 8d9712a..b632073 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -776,6 +776,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    pointer pVBEModule = NULL;
    Bool enable;
    const char *chipname;
+   int mem_skip;
 
    if (pScrn->numEntities != 1)
       return FALSE;
@@ -1092,8 +1093,15 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    /*
     * Get the pre-allocated (stolen) memory size.
     */
-   pI830->StolenMemory.Size = I830DetectMemory(pScrn);
-   pI830->StolenMemory.Start = 0;
+    
+   mem_skip = 0;
+   
+   /* On 965, it looks like the GATT table is inside the aperture? */
+   if (IS_I965G(pI830))
+      mem_skip = pI830->FbMapSize >> 10;
+    
+   pI830->StolenMemory.Size = I830DetectMemory(pScrn) - mem_skip;
+   pI830->StolenMemory.Start = mem_skip;
    pI830->StolenMemory.End = pI830->StolenMemory.Size;
 
    /* Find the maximum amount of agpgart memory available. */
@@ -1341,7 +1349,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 	 break;
       case I830_OUTPUT_DVO:
       case I830_OUTPUT_SDVO:
-	 pI830->output[i].pipe = 0;
+	 pI830->output[i].pipe = 1;
 	 break;
       default:
 	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unhandled output type\n");
diff-tree 5a355c72614ed77f2000e5ede45f3ff5990c79d9 (from 68c3185046b27ab936ca6c92b924b443b3cd6fce)
Author: Keith Packard <keithp at mandolin.keithp.com>
Date:   Sun Nov 5 18:51:28 2006 -0800

    Fix CRT output on 965 chipset.
    
    A few more register settings are needed to get CRT output working on the
    965 chipset, in particular the the SDVO/UDI clock multiplier register
    needed to get set to the default value (3). No, I really don't know what
    this does, but it does get the CRT running at a wide range of sizes.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index e126904..0ece7ee 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -800,11 +800,19 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 # define PLL_P1_DIVIDE_BY_TWO			(1 << 21) /* i830 */
 # define PLL_REF_INPUT_DREFCLK			(0 << 13)
 # define PLL_REF_INPUT_TVCLKINA			(1 << 13) /* i830 */
-# define PLL_REF_INPUT_TVCLKINBC		(2 << 13)
+# define PLL_REF_INPUT_TVCLKINBC		(2 << 13) /* SDVO TVCLKIN */
 # define PLLB_REF_INPUT_SPREADSPECTRUMIN	(3 << 13)
+# define PLL_LOAD_PULSE_PHASE_SHIFT		9
+/*
+ * Parallel to Serial Load Pulse phase selection.
+ * Selects the phase for the 10X DPLL clock for the PCIe
+ * digital display port. The range is 4 to 13; 10 or more
+ * is just a flip delay. The default is 6
+ */
+# define PLL_LOAD_PULSE_PHASE_MASK		(0xf << PLL_LOAD_PULSE_PHASE_SHIFT)
 # define DISPLAY_RATE_SELECT_FPA1		(1 << 8)
 /**
- * SDVO multiplier for 945G/GM.
+ * SDVO multiplier for 945G/GM. Not used on 965.
  *
  * \sa DPLL_MD_UDI_MULTIPLIER_MASK
  */
@@ -848,7 +856,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
  */
 # define DPLL_MD_UDI_MULTIPLIER_MASK		0x00003f00
 # define DPLL_MD_UDI_MULTIPLIER_SHIFT		8
-/** SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK. */
+/** SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK. 
+ * This best be set to the default value (3) or the CRT won't work. No,
+ * I don't entirely understand what this does...
+ */
 # define DPLL_MD_VGA_UDI_MULTIPLIER_MASK	0x0000003f
 # define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT	0
 /** @} */
diff --git a/src/i830_crt.c b/src/i830_crt.c
index adc2d62..a7b0493 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -101,8 +101,14 @@ i830_crt_post_set_mode(ScrnInfoPtr pScrn
 		       DisplayModePtr pMode)
 {
     I830Ptr pI830 = I830PTR(pScrn);
+    int	    dpll_md_reg = (output->pipe == 0) ? DPLL_A_MD : DPLL_B_MD;
+    CARD32  adpa;
 
-    CARD32 adpa;
+    /*
+     * Not quite sure precisely what this does...
+     */
+    if (IS_I965G(pI830))
+	OUTREG(dpll_md_reg, 0x3 << DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT);
 
     adpa = ADPA_DAC_ENABLE;
 
diff --git a/src/i830_display.c b/src/i830_display.c
index 795c6f9..077e318 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -570,6 +570,8 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	    dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
 	    break;
 	}
+	if (IS_I965G(pI830))
+	    dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT);
     } else {
 	dpll |= (p1 - 2) << 16;
 	if (p2 == 4)
@@ -660,8 +662,14 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     if (((INREG(PFIT_CONTROL) >> 29) & 0x3) == pipe)
 	OUTREG(PFIT_CONTROL, 0);
 	   
+    /* 
+     * Docs say to not mess with this register. I think we will
+     * need to eventually though
+     */
+#if 0     
     OUTREG(DSPARB, (47 << 0) | (95 << 7));
-    
+#endif
+
     OUTREG(htot_reg, htot);
     OUTREG(hblank_reg, hblank);
     OUTREG(hsync_reg, hsync);
diff-tree 68c3185046b27ab936ca6c92b924b443b3cd6fce (from 15ef08046bcc3e746453301379f7c5d1bf929ee1)
Author: Keith Packard <keithp at mandolin.keithp.com>
Date:   Sun Nov 5 13:30:32 2006 -0800

    Avoid crashing when disabling sdvo output. XXX

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index da61159..4d4817a 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -517,8 +517,8 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn
 {
     I830Ptr pI830 = I830PTR(pScrn);
     struct i830_sdvo_priv *dev_priv = output->dev_priv;
-    CARD16 width = mode->CrtcHDisplay;
-    CARD16 height = mode->CrtcVDisplay;
+    CARD16 width;
+    CARD16 height;
     CARD16 h_blank_len, h_sync_len, v_blank_len, v_sync_len;
     CARD16 h_sync_offset, v_sync_offset;
     struct i830_sdvo_dtd output_dtd;
@@ -526,6 +526,11 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn
 
     memset(&no_outputs, 0, sizeof(no_outputs));
 
+    if (!mode)
+	return;
+    width = mode->CrtcHDisplay;
+    height = mode->CrtcVDisplay;
+    
     /* do some mode translations */
     h_blank_len = mode->CrtcHBlankEnd - mode->CrtcHBlankStart;
     h_sync_len = mode->CrtcHSyncEnd - mode->CrtcHSyncStart;
diff-tree 15ef08046bcc3e746453301379f7c5d1bf929ee1 (from 7fcb555735a58e19ccc10875b211402983170a87)
Author: Keith Packard <keithp at mandolin.keithp.com>
Date:   Sun Nov 5 13:29:56 2006 -0800

    Move remaining pipe mode setting logic to i830PipeSetMode

diff --git a/src/i830_display.c b/src/i830_display.c
index 6c5645b..795c6f9 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -375,6 +375,22 @@ i830PipeFindClosestMode(ScrnInfoPtr pScr
 }
 
 /**
+ * Return whether any outputs are connected to the specified pipe
+ */
+
+static Bool
+i830PipeInUse (ScrnInfoPtr pScrn, int pipe)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    int	i;
+    
+    for (i = 0; i < pI830->num_outputs; i++)
+	if (!pI830->output[i].disabled && pI830->output[i].pipe == pipe)
+	    return TRUE;
+    return FALSE;
+}
+
+/**
  * Sets the given video mode on the given pipe.  Assumes that plane A feeds
  * pipe A, and plane B feeds pipe B.  Should not affect the other planes/pipes.
  */
@@ -405,6 +421,10 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     int dspstride_reg = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
     int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
     int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
+    Bool ret = FALSE;
+#ifdef XF86DRI
+    Bool didLock = FALSE;
+#endif
 
     if (I830ModesEqual(&pI830Pipe->curMode, pMode))
 	return TRUE;
@@ -412,10 +432,21 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested pix clock: %d\n",
 	       pMode->Clock);
 
+    pI830->pipes[pipe].planeEnabled = i830PipeInUse (pScrn, pipe);
+    
+    if (!pI830->pipes[pipe].planeEnabled)
+	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].disabled)
 	    continue;
 
+	pI830->output[i].pre_set_mode(pScrn, &pI830->output[i], pMode);
+	
 	switch (pI830->output[i].type) {
 	case I830_OUTPUT_LVDS:
 	    is_lvds = TRUE;
@@ -438,18 +469,18 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     if (is_lvds && (is_sdvo || is_dvo || is_tv || is_crt)) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		   "Can't enable LVDS and non-LVDS on the same pipe\n");
-	return FALSE;
+	goto done;
     }
     if (is_tv && (is_sdvo || is_dvo || is_crt || is_lvds)) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		   "Can't enable a TV and any other output on the same "
 		   "pipe\n");
-	return FALSE;
+	goto done;
     }
     if (pipe == 0 && is_lvds) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		   "Can't support LVDS on pipe A\n");
-	return FALSE;
+	goto done;
     }
 
     htot = (pMode->CrtcHDisplay - 1) | ((pMode->CrtcHTotal - 1) << 16);
@@ -515,7 +546,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     if (!ok) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		   "Couldn't find PLL settings for mode!\n");
-	return FALSE;
+	goto done;
     }
 
     dpll = DPLL_VCO_ENABLE | DPLL_VGA_MODE_DIS;
@@ -629,7 +660,6 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     if (((INREG(PFIT_CONTROL) >> 29) & 0x3) == pipe)
 	OUTREG(PFIT_CONTROL, 0);
 	   
-    OUTREG(PFIT_PGM_RATIOS, 0x10001000);
     OUTREG(DSPARB, (47 << 0) | (95 << 7));
     
     OUTREG(htot_reg, htot);
@@ -653,7 +683,13 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 
     pI830Pipe->curMode = *pMode;
 
-    return TRUE;
+    ret = TRUE;
+done:
+#ifdef XF86DRI
+    if (didLock)
+	I830DRIUnlock(pScrn);
+#endif
+    return ret;
 }
 
 void
@@ -714,22 +750,6 @@ i830DisableUnusedFunctions(ScrnInfoPtr p
 }
 
 /**
- * Return whether any outputs are connected to the specified pipe
- */
-
-static Bool
-i830PipeInUse (ScrnInfoPtr pScrn, int pipe)
-{
-    I830Ptr pI830 = I830PTR(pScrn);
-    int	i;
-    
-    for (i = 0; i < pI830->num_outputs; i++)
-	if (!pI830->output[i].disabled && pI830->output[i].pipe == pipe)
-	    return TRUE;
-    return FALSE;
-}
-
-/**
  * This function configures the screens in clone mode on
  * all active outputs using a mode similar to the specified mode.
  */
@@ -738,28 +758,13 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
 {
     I830Ptr pI830 = I830PTR(pScrn);
     Bool ok = TRUE;
-#ifdef XF86DRI
-    Bool didLock = FALSE;
-#endif
     int i;
 
     DPRINTF(PFX, "i830SetMode\n");
 
-#ifdef XF86DRI
-    didLock = I830DRILock(pScrn);
-#endif
-
-    for (i = 0; i < pI830->num_pipes; i++)
-	pI830->pipes[i].planeEnabled = i830PipeInUse (pScrn, i);
-
-    for (i = 0; i < pI830->num_outputs; i++)
-	pI830->output[i].pre_set_mode(pScrn, &pI830->output[i], pMode);
-
     for (i = 0; i < pI830->num_pipes; i++)
     {
-	if (pI830->pipes[i].planeEnabled)
-	    ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, i, pMode),
-				 i);
+	ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, i, pMode), i);
 	if (!ok)
 	    goto done;
     }
@@ -797,11 +802,6 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
    I830DRISetVBlankInterrupt (pScrn, TRUE);
 #endif
 done:
-#ifdef XF86DRI
-    if (didLock)
-	I830DRIUnlock(pScrn);
-#endif
-
     i830DumpRegs (pScrn);
     i830_sdvo_dump(pScrn);
     return ok;
diff-tree 7fcb555735a58e19ccc10875b211402983170a87 (from 3ab7f9693217d8fe993bdc94c376b219b0082961)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Sat Nov 4 00:52:21 2006 -0800

    Rename availablePipes to num_pipes

diff --git a/src/i830.h b/src/i830.h
index 9e5c844..333b595 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -447,7 +447,7 @@ typedef struct _I830Rec {
    Bool checkDevices;
 
    /* [0] is Pipe A, [1] is Pipe B. */
-   int availablePipes;
+   int num_pipes;
    /* [0] is display plane A, [1] is display plane B. */
    I830PipeRec	  pipes[MAX_DISPLAY_PIPES];
    
diff --git a/src/i830_crt.c b/src/i830_crt.c
index 4c6c3ca..adc2d62 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -174,12 +174,12 @@ i830_crt_detect_load(ScrnInfoPtr pScrn)
     int pipeconf_reg, bclrpat_reg, dpll_reg;
     int pipe;
 
-    for (pipe = 0; pipe < pI830->availablePipes; pipe++)
+    for (pipe = 0; pipe < pI830->num_pipes; pipe++)
 	if (!pI830->pipes[pipe].planeEnabled)
 	    break;
     
     /* No available pipes for load detection */
-    if (pipe == pI830->availablePipes)
+    if (pipe == pI830->num_pipes)
 	return FALSE;
     
     if (pipe == 0) {
diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index 6b0e58c..05e93fa 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -86,7 +86,7 @@ I830SetPipeCursorBase (ScrnInfoPtr pScrn
     int cursor_base = (pipe == 0 ? CURSOR_A_BASE : CURSOR_B_BASE);
     I830MemRange *cursor_mem;
 
-    if (pipe >= pI830->availablePipes)
+    if (pipe >= pI830->num_pipes)
 	FatalError("Bad pipe number for cursor base setting\n");
 
     if (pI830->CursorIsARGB)
@@ -180,11 +180,11 @@ I830InitHWCursor(ScrnInfoPtr pScrn)
    int i;
 
    DPRINTF(PFX, "I830InitHWCursor\n");
-   for (i = 0; i < pI830->availablePipes; i++) 
+   for (i = 0; i < pI830->num_pipes; i++) 
       pI830->pipes[i].cursorShown = FALSE;
    /* Initialise the HW cursor registers, leaving the cursor hidden. */
    if (IS_MOBILE(pI830) || IS_I9XX(pI830)) {
-      for (i = 0; i < pI830->availablePipes; i++)
+      for (i = 0; i < pI830->num_pipes; i++)
       {
 	 int   cursor_control = i == 0 ? CURSOR_A_CONTROL : CURSOR_B_CONTROL;
 	 temp = INREG(cursor_control);
@@ -484,7 +484,7 @@ I830SetCursorPosition(ScrnInfoPtr pScrn,
     x -= hotspotx;
     y -= hotspoty;
 
-    for (pipe = 0; pipe < pI830->availablePipes; pipe++)
+    for (pipe = 0; pipe < pI830->num_pipes; pipe++)
     {
 	I830PipePtr	pI830Pipe = &pI830->pipes[pipe];
 	DisplayModePtr	mode = &pI830Pipe->curMode;
@@ -550,7 +550,7 @@ I830ShowCursor(ScrnInfoPtr pScrn)
 	   pI830->CursorMemARGB->Physical, pI830->CursorMemARGB->Start);
 
     pI830->cursorOn = TRUE;
-    for (pipe = 0; pipe < pI830->availablePipes; pipe++)
+    for (pipe = 0; pipe < pI830->num_pipes; pipe++)
 	I830SetPipeCursor (pScrn, pipe, TRUE);
 }
 
@@ -563,7 +563,7 @@ I830HideCursor(ScrnInfoPtr pScrn)
    DPRINTF(PFX, "I830HideCursor\n");
 
    pI830->cursorOn = FALSE;
-    for (pipe = 0; pipe < pI830->availablePipes; pipe++)
+    for (pipe = 0; pipe < pI830->num_pipes; pipe++)
 	I830SetPipeCursor (pScrn, pipe, TRUE);
 }
 
diff --git a/src/i830_display.c b/src/i830_display.c
index c9b6b4d..6c5645b 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -673,7 +673,7 @@ 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 (i = 0; i < pI830->availablePipes; i++) {
+    for (i = 0; i < pI830->num_pipes; i++) {
 	I830PipePtr pI830Pipe = &pI830->pipes[i];
 	int	    dspcntr_reg = pipe == 0 ? DSPACNTR : DSPBCNTR;
 	int	    pipeconf_reg = pipe == 0 ? PIPEACONF : PIPEBCONF;
@@ -749,13 +749,13 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
     didLock = I830DRILock(pScrn);
 #endif
 
-    for (i = 0; i < pI830->availablePipes; i++)
+    for (i = 0; i < pI830->num_pipes; i++)
 	pI830->pipes[i].planeEnabled = i830PipeInUse (pScrn, i);
 
     for (i = 0; i < pI830->num_outputs; i++)
 	pI830->output[i].pre_set_mode(pScrn, &pI830->output[i], pMode);
 
-    for (i = 0; i < pI830->availablePipes; i++)
+    for (i = 0; i < pI830->num_pipes; i++)
     {
 	if (pI830->pipes[i].planeEnabled)
 	    ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, i, pMode),
@@ -815,7 +815,7 @@ i830DescribeOutputConfiguration(ScrnInfo
 
     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output configuration:\n");
 
-    for (i = 0; i < pI830->availablePipes; i++) {
+    for (i = 0; i < pI830->num_pipes; i++) {
 	CARD32 dspcntr = INREG(DSPACNTR + (DSPBCNTR - DSPACNTR) * i);
 
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 92c27af..8d9712a 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -542,7 +542,7 @@ I830LoadPalette(ScrnInfoPtr pScrn, int n
    DPRINTF(PFX, "I830LoadPalette: numColors: %d\n", numColors);
    pI830 = I830PTR(pScrn);
 
-   for(p=0; p < pI830->availablePipes; p++) {
+   for(p=0; p < pI830->num_pipes; p++) {
       I830PipePtr pI830Pipe = &pI830->pipes[p];
 
       if (p == 0) {
@@ -1080,14 +1080,14 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    }
 
    if (pI830->PciInfo->chipType == PCI_CHIP_E7221_G)
-      pI830->availablePipes = 1;
+      pI830->num_pipes = 1;
    else
    if (IS_MOBILE(pI830) || IS_I9XX(pI830))
-      pI830->availablePipes = 2;
+      pI830->num_pipes = 2;
    else
-      pI830->availablePipes = 1;
+      pI830->num_pipes = 1;
    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%d display pipe%s available.\n",
-	      pI830->availablePipes, pI830->availablePipes > 1 ? "s" : "");
+	      pI830->num_pipes, pI830->num_pipes > 1 ? "s" : "");
 
    /*
     * Get the pre-allocated (stolen) memory size.
@@ -1231,7 +1231,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
             } while (sub);
          }
     
-         if (pI830->availablePipes == 1 && pI830->MonType2 != PIPE_NONE) {
+         if (pI830->num_pipes == 1 && pI830->MonType2 != PIPE_NONE) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		    "Monitor 2 cannot be specified on single pipe devices\n");
             return FALSE;
@@ -1308,7 +1308,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 #endif
 
    if (xf86ReturnOptValBool(pI830->Options, OPTION_CLONE, FALSE)) {
-      if (pI830->availablePipes == 1) {
+      if (pI830->num_pipes == 1) {
          xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 
  		 "Can't enable Clone Mode because this is a single pipe device\n");
          PreInitCleanup(pScrn);
@@ -1334,7 +1334,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       switch (pI830->output[i].type) {
       case I830_OUTPUT_LVDS:
 	 /* LVDS must live on pipe B for two-pipe devices */
-	 pI830->output[i].pipe = pI830->availablePipes - 1;
+	 pI830->output[i].pipe = pI830->num_pipes - 1;
 	 break;
       case I830_OUTPUT_ANALOG:
 	 pI830->output[i].pipe = 0;
@@ -2091,7 +2091,7 @@ SaveHWState(ScrnInfoPtr pScrn)
    temp = INREG(PIPEACONF);
    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEACONF is 0x%08lx\n", 
 	      (unsigned long) temp);
-   if (pI830->availablePipes == 2) {
+   if (pI830->num_pipes == 2) {
       temp = INREG(PIPEBCONF);
       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEBCONF is 0x%08lx\n", 
 		 (unsigned long) temp);
@@ -2123,7 +2123,7 @@ SaveHWState(ScrnInfoPtr pScrn)
       pI830->savePaletteA[i] = INREG(PALETTE_A + (i << 2));
    }
 
-   if(pI830->availablePipes == 2) {
+   if(pI830->num_pipes == 2) {
       pI830->savePIPEBCONF = INREG(PIPEBCONF);
       pI830->savePIPEBSRC = INREG(PIPEBSRC);
       pI830->saveDSPBCNTR = INREG(DSPBCNTR);
@@ -2234,7 +2234,7 @@ RestoreHWState(ScrnInfoPtr pScrn)
          OUTREG(PALETTE_A + (i << 2), pI830->savePaletteA[i]);
    }
 
-   if(pI830->availablePipes == 2) {
+   if(pI830->num_pipes == 2) {
       OUTREG(FPB0, pI830->saveFPB0);
       OUTREG(FPB1, pI830->saveFPB1);
       OUTREG(DPLL_B, pI830->saveDPLL_B);
@@ -3171,7 +3171,7 @@ i830AdjustFrame(int scrnIndex, int x, in
       pI830->AccelInfoRec->NeedToSync = FALSE;
    }
 
-   for (i = 0; i < pI830->availablePipes; i++)
+   for (i = 0; i < pI830->num_pipes; i++)
       if (pI830->pipes[i].planeEnabled)
 	 i830PipeSetBase(pScrn, i, x, y);
 }
@@ -3279,7 +3279,7 @@ I830EnterVT(int scrnIndex, int flags)
    SetHWOperatingState(pScrn);
 
    /* Mark that we'll need to re-set the mode for sure */
-   for (i = 0; i < pI830->availablePipes; i++)
+   for (i = 0; i < pI830->num_pipes; i++)
       memset(&pI830->pipes[i].curMode, 0, sizeof(pI830->pipes[i].curMode));
 
    if (!i830SetMode(pScrn, pScrn->currentMode))
@@ -3423,7 +3423,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->availablePipes; i++) {
+      for (i = 0; i < pI830->num_pipes; i++) {
         if (i == 0) {
 	    ctrl = DSPACNTR;
 	    base = DSPABASE;
@@ -3474,7 +3474,7 @@ I830DisplayPowerManagementSet(ScrnInfoPt
       pI830->output[i].dpms(pScrn, &pI830->output[i], PowerManagementMode);
    }
 
-   for (i = 0; i < pI830->availablePipes; i++) {
+   for (i = 0; i < pI830->num_pipes; i++) {
       if (i == 0) {
          ctrl = DSPACNTR;
          base = DSPABASE;
diff --git a/src/i830_randr.c b/src/i830_randr.c
index afa1848..84727a6 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -752,7 +752,7 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
 	if (!RROutputSetClones (randrp->outputs[i], clones, nclone))
 	    return FALSE;
     }
-    for (i = 0; i < pI830->availablePipes; i++)
+    for (i = 0; i < pI830->num_pipes; i++)
 	I830RandRCrtcNotify (randrp->crtcs[i]);
     return TRUE;
 }
@@ -785,7 +785,7 @@ I830RandRCreateScreenResources12 (Screen
     /*
      * Create RandR resources, then probe them
      */
-    for (i = 0; i < pI830->availablePipes; i++)
+    for (i = 0; i < pI830->num_pipes; i++)
     {
 	randrp->crtcs[i] = RRCrtcCreate (pScreen, (void *) i);
 	RRCrtcGammaSetSize (randrp->crtcs[i], 256);
@@ -821,7 +821,7 @@ I830RandRCreateScreenResources12 (Screen
 				mmHeight);
     }
 
-    for (i = 0; i < pI830->availablePipes; i++)
+    for (i = 0; i < pI830->num_pipes; i++)
 	i830PipeSetBase(pScrn, i, 0, 0);
 
     return I830RandRSetInfo12 (pScreen);
diff-tree 3ab7f9693217d8fe993bdc94c376b219b0082961 (from e4bcec796e80e9fd66ab0c36394f5946915531f1)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Sat Nov 4 00:46:18 2006 -0800

    Eliminate operatingDevices member and PIPE_* values.
    
    operatingDevices and MonType1/MonType2 duplicate information already stored
    in the device structures. Eliminate them and replace uses with direct
    references to the appropriate other data.

diff --git a/src/i830.h b/src/i830.h
index ea7f4c9..9e5c844 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -86,26 +86,6 @@ typedef struct _I830OutputRec I830Output
  * Paulo César Pereira de Andrade <pcpa at conectiva.com.br>.
  */
 
-#define PIPE_CRT_ID	0
-#define PIPE_TV_ID    	1
-#define PIPE_DFP_ID	2
-#define PIPE_LFP_ID	3
-#define PIPE_CRT2_ID	4
-#define PIPE_TV2_ID	5
-#define PIPE_DFP2_ID	6
-#define PIPE_LFP2_ID	7
-#define PIPE_NUM_ID	8
-
-#define PIPE_NONE	0<<0
-#define PIPE_CRT	1<<0
-#define PIPE_TV		1<<1
-#define PIPE_DFP	1<<2
-#define PIPE_LFP	1<<3
-#define PIPE_CRT2	1<<4
-#define PIPE_TV2	1<<5
-#define PIPE_DFP2	1<<6
-#define PIPE_LFP2	1<<7
-
 typedef struct _I830Rec *I830Ptr;
 
 typedef void (*I830WriteIndexedByteFunc)(I830Ptr pI830, IOADDRESS addr,
@@ -314,7 +294,9 @@ typedef struct _I830Rec {
    int CloneVDisplay;
 
    I830EntPtr entityPrivate;	
+#if 0
    int pipe, origPipe;
+#endif
    int init;
 
    unsigned int bufferOffset;		/* for I830SelectBuffer */
@@ -391,9 +373,6 @@ typedef struct _I830Rec {
    Bool CursorIsARGB;
    CursorPtr pCurs;
 
-   int MonType1;
-   int MonType2;
-
    DGAModePtr DGAModes;
    int numDGAModes;
    Bool DGAactive;
@@ -466,7 +445,6 @@ typedef struct _I830Rec {
    CARD32 saveSWF4;
 
    Bool checkDevices;
-   int operatingDevices;
 
    /* [0] is Pipe A, [1] is Pipe B. */
    int availablePipes;
@@ -660,6 +638,10 @@ extern Bool I830FixOffset(ScrnInfoPtr pS
 extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg,
 			char *name);
 
+/* i830_display.c */
+Bool
+i830PipeHasType (ScrnInfoPtr pScrn, int pipe, int type);
+
 /* i830_crt.c */
 void i830_crt_init(ScrnInfoPtr pScrn);
 
diff --git a/src/i830_crt.c b/src/i830_crt.c
index 0225727..4c6c3ca 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -169,12 +169,19 @@ static Bool
 i830_crt_detect_load(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    CARD32 adpa, pipeconf;
+    CARD32 adpa, pipeconf, bclrpat;
     CARD8 st00;
     int pipeconf_reg, bclrpat_reg, dpll_reg;
     int pipe;
 
-    pipe = pI830->pipe;
+    for (pipe = 0; pipe < pI830->availablePipes; pipe++)
+	if (!pI830->pipes[pipe].planeEnabled)
+	    break;
+    
+    /* No available pipes for load detection */
+    if (pipe == pI830->availablePipes)
+	return FALSE;
+    
     if (pipe == 0) {
 	bclrpat_reg = BCLRPAT_A;
 	pipeconf_reg = PIPEACONF;
@@ -197,9 +204,10 @@ i830_crt_detect_load(ScrnInfoPtr pScrn)
 	       ((pipe == 1) ? ADPA_PIPE_B_SELECT : 0));
     }
 
-    /* Set the border color to red, green.  Maybe we should save/restore this
+    /* Set the border color to purple.  Maybe we should save/restore this
      * reg.
      */
+    bclrpat = INREG(bclrpat_reg);
     OUTREG(bclrpat_reg, 0x00500050);
 
     /* Force the border color through the active region */
@@ -210,6 +218,7 @@ i830_crt_detect_load(ScrnInfoPtr pScrn)
     st00 = pI830->readStandard(pI830, 0x3c2);
 
     /* Restore previous settings */
+    OUTREG(bclrpat_reg, bclrpat);
     OUTREG(pipeconf_reg, pipeconf);
     OUTREG(ADPA, adpa);
 
diff --git a/src/i830_display.c b/src/i830_display.c
index 8cb6660..c9b6b4d 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -61,6 +61,24 @@ i830PrintPll(char *prefix, int refclk, i
 }
 
 /**
+ * Returns whether any output on the specified pipe is an LVDS output
+ */
+Bool
+i830PipeHasType (ScrnInfoPtr pScrn, int pipe, int type)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    int	    i;
+
+    for (i = 0; i < pI830->num_outputs; i++)
+	if (!pI830->output[i].disabled && pI830->output[i].pipe == pipe)
+	{
+	    if (pI830->output[i].type == type)
+		return TRUE;
+	}
+    return FALSE;
+}
+
+/**
  * Returns whether the given set of divisors are valid for a given refclk with
  * the given outputs.
  *
@@ -68,7 +86,7 @@ i830PrintPll(char *prefix, int refclk, i
  * clk = refclk * (5 * m1 + m2) / n / (p1 * p2)
  */
 static Bool
-i830PllIsValid(ScrnInfoPtr pScrn, int outputs, int refclk, int m1, int m2,
+i830PllIsValid(ScrnInfoPtr pScrn, int pipe, int refclk, int m1, int m2,
 	       int n, int p1, int p2)
 {
     I830Ptr pI830 = I830PTR(pScrn);
@@ -87,7 +105,7 @@ i830PllIsValid(ScrnInfoPtr pScrn, int ou
 	max_n = 8;
 	min_p1 = 1;
 	max_p1 = 8;
-	if (outputs & PIPE_LCD_ACTIVE) {
+	if (i830PipeHasType (pScrn, pipe, I830_OUTPUT_LVDS)) {
 	    min_p = 7;
 	    max_p = 98;
 	} else {
@@ -153,7 +171,7 @@ i830PllIsValid(ScrnInfoPtr pScrn, int ou
  * clk = refclk * (5 * m1 + m2) / n / (p1 * p2)
  */
 static Bool
-i830FindBestPLL(ScrnInfoPtr pScrn, int outputs, int target, int refclk,
+i830FindBestPLL(ScrnInfoPtr pScrn, int pipe, int target, int refclk,
 		int *outm1, int *outm2, int *outn, int *outp1, int *outp2)
 {
     I830Ptr pI830 = I830PTR(pScrn);
@@ -170,7 +188,7 @@ i830FindBestPLL(ScrnInfoPtr pScrn, int o
 	max_n = 8;
 	min_p1 = 1;
 	max_p1 = 8;
-	if (outputs & PIPE_LCD_ACTIVE) {
+	if (i830PipeHasType (pScrn, pipe, I830_OUTPUT_LVDS)) {
 	    if (target < 200000) /* XXX: Is this the right cutoff? */
 		p2 = 14;
 	    else
@@ -203,7 +221,7 @@ i830FindBestPLL(ScrnInfoPtr pScrn, int o
 		for (p1 = min_p1; p1 <= max_p1; p1++) {
 		    int clock, this_err;
 
-		    if (!i830PllIsValid(pScrn, outputs, refclk, m1, m2, n,
+		    if (!i830PllIsValid(pScrn, pipe, refclk, m1, m2, n,
 					p1, p2)) {
 			continue;
 		    }
@@ -372,7 +390,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     Bool ok, is_sdvo = FALSE, is_dvo = FALSE;
     Bool is_crt = FALSE, is_lvds = FALSE, is_tv = FALSE;
     int refclk, pixel_clock;
-    int outputs, i;
+    int i;
     int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
     int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
     int fp_reg = (pipe == 0) ? FPA0 : FPB0;
@@ -388,11 +406,6 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
     int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
 
-    if (pipe == 0)
-	outputs = pI830->operatingDevices & 0xff;
-    else
-	outputs = (pI830->operatingDevices >> 8) & 0xff;
-
     if (I830ModesEqual(&pI830Pipe->curMode, pMode))
 	return TRUE;
 
@@ -497,7 +510,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     } else {
 	refclk = 48000;
     }
-    ok = i830FindBestPLL(pScrn, outputs, pixel_clock, refclk, &m1, &m2, &n,
+    ok = i830FindBestPLL(pScrn, pipe, pixel_clock, refclk, &m1, &m2, &n,
 			 &p1, &p2);
     if (!ok) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
@@ -701,6 +714,22 @@ i830DisableUnusedFunctions(ScrnInfoPtr p
 }
 
 /**
+ * Return whether any outputs are connected to the specified pipe
+ */
+
+static Bool
+i830PipeInUse (ScrnInfoPtr pScrn, int pipe)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    int	i;
+    
+    for (i = 0; i < pI830->num_outputs; i++)
+	if (!pI830->output[i].disabled && pI830->output[i].pipe == pipe)
+	    return TRUE;
+    return FALSE;
+}
+
+/**
  * This function configures the screens in clone mode on
  * all active outputs using a mode similar to the specified mode.
  */
@@ -720,8 +749,8 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
     didLock = I830DRILock(pScrn);
 #endif
 
-    pI830->pipes[0].planeEnabled = (pI830->operatingDevices & 0xff) != 0;
-    pI830->pipes[1].planeEnabled = (pI830->operatingDevices & 0xff00) != 0;
+    for (i = 0; i < pI830->availablePipes; i++)
+	pI830->pipes[i].planeEnabled = i830PipeInUse (pScrn, i);
 
     for (i = 0; i < pI830->num_outputs; i++)
 	pI830->output[i].pre_set_mode(pScrn, &pI830->output[i], pMode);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 1b75649..92c27af 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -382,88 +382,6 @@ I830ProbeDDC(ScrnInfoPtr pScrn, int inde
    ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
 }
 
-/*
- * Returns a string matching the device corresponding to the first bit set
- * in "device".  savedDevice is then set to device with that bit cleared.
- * Subsequent calls with device == -1 will use savedDevice.
- */
-
-static const char *displayDevices[] = {
-   "CRT",
-   "TV",
-   "DFP (digital flat panel)",
-   "LFP (local flat panel)",
-   "CRT2 (second CRT)",
-   "TV2 (second TV)",
-   "DFP2 (second digital flat panel)",
-   "LFP2 (second local flat panel)",
-   NULL
-};
-
-static const char *
-DeviceToString(int device)
-{
-   static int savedDevice = -1;
-   int bit = 0;
-   const char *name;
-
-   if (device == -1) {
-      device = savedDevice;
-      bit = 0;
-   }
-
-   if (device == -1)
-      return NULL;
-
-   while (displayDevices[bit]) {
-      if (device & (1 << bit)) {
-	 name = displayDevices[bit];
-	 savedDevice = device & ~(1 << bit);
-	 bit++;
-	 return name;
-      }
-      bit++;
-   }
-   return NULL;
-}
-
-static void
-PrintDisplayDeviceInfo(ScrnInfoPtr pScrn)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   int pipe, n;
-   int displays;
-
-   DPRINTF(PFX, "PrintDisplayDeviceInfo\n");
-
-   displays = pI830->operatingDevices;
-   if (displays == -1) {
-      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		 "No active display devices.\n");
-      return;
-   }
-
-   /* Check for active devices connected to each display pipe. */
-   for (n = 0; n < pI830->availablePipes; n++) {
-      pipe = ((displays >> PIPE_SHIFT(n)) & PIPE_ACTIVE_MASK);
-      if (pipe) {
-	 const char *name;
-
-	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		    "Currently active displays on Pipe %c:\n", PIPE_NAME(n));
-	 name = DeviceToString(pipe);
-	 do {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\t%s\n", name);
-	    name = DeviceToString(-1);
-	 } while (name);
-
-      } else {
-	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		    "No active displays on Pipe %c.\n", PIPE_NAME(n));
-      }
-   }
-}
-
 static int
 I830DetectMemory(ScrnInfoPtr pScrn)
 {
@@ -1242,9 +1160,10 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 
    I830PreInitDDC(pScrn);
 
-   pI830->MonType1 = PIPE_NONE;
-   pI830->MonType2 = PIPE_NONE;
-
+#if 0
+   /*
+    * This moves to generic RandR-based configuration code
+    */
    if ((s = xf86GetOptValString(pI830->Options, OPTION_MONITOR_LAYOUT)) &&
       I830IsPrimary(pScrn)) {
       char *Mon1;
@@ -1329,7 +1248,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       else
 	 pI830->pipe = 1;
 
-      pI830->operatingDevices = (pI830->MonType2 << 8) | pI830->MonType1;
    } else if (I830IsPrimary(pScrn)) {
       /* Choose a default set of outputs to use based on what we've detected.
        *
@@ -1375,7 +1293,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 	 pI830->pipe = 0;
       else
 	 pI830->pipe = 1;
-      pI830->operatingDevices = (pI830->MonType2 << 8) | pI830->MonType1;
 
       if (pI830->MonType1 != 0 && pI830->MonType2 != 0) {
          xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
@@ -1384,11 +1301,11 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       }
    } else {
       I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
-      pI830->operatingDevices = pI8301->operatingDevices;
       pI830->pipe = !pI8301->pipe;
       pI830->MonType1 = pI8301->MonType1;
       pI830->MonType2 = pI8301->MonType2;
    }
+#endif
 
    if (xf86ReturnOptValBool(pI830->Options, OPTION_CLONE, FALSE)) {
       if (pI830->availablePipes == 1) {
@@ -1408,38 +1325,23 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    }
 
 
-   /* Perform the pipe assignment of outputs.  This code shouldn't exist,
-    * but for now we're supporting the existing MonitorLayout configuration
-    * scheme.
+   /* 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].disabled = FALSE;
 
       switch (pI830->output[i].type) {
       case I830_OUTPUT_LVDS:
-	 if (pI830->MonType1 & PIPE_LFP)
-	    pI830->output[i].pipe = 0;
-	 else if (pI830->MonType2 & PIPE_LFP)
-	    pI830->output[i].pipe = 1;
-	 else
-	    pI830->output[i].disabled = TRUE;
+	 /* LVDS must live on pipe B for two-pipe devices */
+	 pI830->output[i].pipe = pI830->availablePipes - 1;
 	 break;
       case I830_OUTPUT_ANALOG:
-	 if (pI830->MonType1 & PIPE_CRT)
-	    pI830->output[i].pipe = 0;
-	 else if (pI830->MonType2 & PIPE_CRT)
-	    pI830->output[i].pipe = 1;
-	 else
-	    pI830->output[i].disabled = TRUE;
+	 pI830->output[i].pipe = 0;
 	 break;
       case I830_OUTPUT_DVO:
       case I830_OUTPUT_SDVO:
-	 if (pI830->MonType1 & PIPE_DFP)
-	    pI830->output[i].pipe = 0;
-	 else if (pI830->MonType2 & PIPE_DFP)
-	    pI830->output[i].pipe = 1;
-	 else
-	    pI830->output[i].disabled = TRUE;
+	 pI830->output[i].pipe = 0;
 	 break;
       default:
 	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unhandled output type\n");
@@ -1447,8 +1349,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       }
    }
 
-   
-
+#if 0
    pI830->CloneRefresh = 60; /* default to 60Hz */
    if (xf86GetOptValInteger(pI830->Options, OPTION_CLONE_REFRESH,
 			    &(pI830->CloneRefresh))) {
@@ -1471,6 +1372,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
          return FALSE;
       }
    }
+#endif
 
    pI830->rotation = RR_Rotate_0;
    if ((s = xf86GetOptValString(pI830->Options, OPTION_ROTATE))) {
@@ -1646,8 +1548,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       }
    }
 
-   PrintDisplayDeviceInfo(pScrn);
-
+#if 0
    if (xf86IsEntityShared(pScrn->entityList[0])) {
       if (!I830IsPrimary(pScrn)) {
 	 /* This could be made to work with a little more fiddling */
@@ -1663,6 +1564,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       xf86DrvMsg(pScrn->scrnIndex, from, "Display is using Pipe %s\n",
 		pI830->pipe ? "B" : "A");
    }
+#endif
 
    /* Alloc our pointers for the primary head */
    if (I830IsPrimary(pScrn)) {
@@ -2872,17 +2774,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    }
 #endif
 
-   if (xf86IsEntityShared(pScrn->entityList[0])) {
-      /* PreInit failed on the second head, so make sure we turn it off */
-      if (I830IsPrimary(pScrn) && !pI830->entityPrivate->pScrn_2) {
-         if (pI830->pipe == 0) {
-            pI830->operatingDevices &= 0xFF;
-         } else {
-            pI830->operatingDevices &= 0xFF00;
-         }
-      }
-   }
-
    pI830->starting = TRUE;
 
    /* Alloc our pointers for the primary head */
@@ -3269,6 +3160,7 @@ i830AdjustFrame(int scrnIndex, int x, in
 {
    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
    I830Ptr pI830 = I830PTR(pScrn);
+   int i;
 
    DPRINTF(PFX, "i830AdjustFrame: y = %d (+ %d), x = %d (+ %d)\n",
 	   x, pI830->xoffset, y, pI830->yoffset);
@@ -3279,9 +3171,9 @@ i830AdjustFrame(int scrnIndex, int x, in
       pI830->AccelInfoRec->NeedToSync = FALSE;
    }
 
-   i830PipeSetBase(pScrn, pI830->pipe, x, y);
-   if (pI830->Clone)
-      i830PipeSetBase(pScrn, !pI830->pipe, x, y);
+   for (i = 0; i < pI830->availablePipes; i++)
+      if (pI830->pipes[i].planeEnabled)
+	 i830PipeSetBase(pScrn, i, x, y);
 }
 
 static void
diff --git a/src/i830_randr.c b/src/i830_randr.c
index d097283..afa1848 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -492,45 +492,31 @@ I830RandRCrtcNotify (RRCrtcPtr	crtc)
     I830PipePtr		pI830Pipe = &pI830->pipes[pipe];
     int			i, j;
     DisplayModePtr	pipeMode = &pI830Pipe->curMode;
-    int			pipe_type;
 
     x = pI830Pipe->x;
     y = pI830Pipe->y;
     rotation = RR_Rotate_0;
     numOutputs = 0;
+    mode = NULL;
     for (i = 0; i < pI830->num_outputs; i++)
     {
 	output = &pI830->output[i];
-	/*
-	 * Valid crtcs
-	 */
-	switch (output->type) {
-	case I830_OUTPUT_DVO:
-	case I830_OUTPUT_SDVO:
-	    pipe_type = PIPE_DFP;
-	    break;
-	case I830_OUTPUT_ANALOG:
-	    pipe_type = PIPE_CRT;
-	    break;
-	case I830_OUTPUT_LVDS:
-	    pipe_type = PIPE_LFP;
-	    break;
-	case I830_OUTPUT_TVOUT:
-	    pipe_type = PIPE_TV;
-	    break;
-	default:
-	    pipe_type = PIPE_NONE;
-	    break;
-	}
-	if (pI830->operatingDevices & (pipe_type << (pipe << 3)))
+	if (!output->disabled && output->pipe == pipe)
 	{
 	    rrout = randrp->outputs[i];
 	    outputs[numOutputs++] = rrout;
+	    /*
+	     * We make copies of modes, so pointer equality 
+	     * isn't sufficient
+	     */
 	    for (j = 0; j < rrout->numModes; j++)
 	    {
 		DisplayModePtr	outMode = rrout->modes[j]->devPrivate;
 		if (I830ModesEqual(pipeMode, outMode))
+		{
 		    mode = rrout->modes[j];
+		    break;
+		}
 	    }
 	}
     }
@@ -571,14 +557,7 @@ I830RandRCrtcSet (ScreenPtr	pScreen,
 	}
 	else
 	{
-	    CARD32  operatingDevices = pI830->operatingDevices;
-
-	    if (pipe == 0)
-		pI830->operatingDevices &= ~0xff;
-	    else
-		pI830->operatingDevices &= ~0xff00;
 	    i830DisableUnusedFunctions (pScrn);
-	    pI830->operatingDevices = operatingDevices;
 	}
 	randrp->modes[pipe] = display_mode;
     }
@@ -614,7 +593,6 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
     int			p;
     int			clone_types;
     int			crtc_types;
-    int			pipe_type;
     int			pipe;
     int			subpixel;
     DisplayModePtr	modes, mode;
@@ -644,7 +622,6 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
 	    clone_types = ((1 << I830_OUTPUT_ANALOG) |
 			   (1 << I830_OUTPUT_DVO) |
 			   (1 << I830_OUTPUT_SDVO));
-	    pipe_type = PIPE_DFP;
 	    subpixel = SubPixelHorizontalRGB;
 	    break;
 	case I830_OUTPUT_ANALOG:
@@ -652,13 +629,11 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
 	    clone_types = ((1 << I830_OUTPUT_ANALOG) |
 			   (1 << I830_OUTPUT_DVO) |
 			   (1 << I830_OUTPUT_SDVO));
-	    pipe_type = PIPE_CRT;
 	    subpixel = SubPixelNone;
 	    break;
 	case I830_OUTPUT_LVDS:
 	    crtc_types = (1 << 1);
 	    clone_types = (1 << I830_OUTPUT_LVDS);
-	    pipe_type = PIPE_LFP;
 	    subpixel = SubPixelHorizontalRGB;
 	    possibleOptions = (RROutputOptionScaleNone|
 			       RROutputOptionScaleMaxAspect |
@@ -669,32 +644,27 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
 	    crtc_types = ((1 << 0) |
 			  (1 << 1));
 	    clone_types = (1 << I830_OUTPUT_TVOUT);
-	    pipe_type = PIPE_TV;
 	    subpixel = SubPixelNone;
 	    break;
 	default:
 	    crtc_types = 0;
 	    clone_types = 0;
-	    pipe_type = PIPE_NONE;
 	    subpixel = SubPixelUnknown;
 	    break;
 	}
-	ncrtc = 0;
-	pipe = -1;
-	crtc = NULL;
-	for (j = 0; j < pI830->availablePipes; j++)
+	if (!output->disabled)
 	{
-#if 0
-	     /* Can't flip outputs among crtcs yet */
-	    if (crtc_types & (1 << j))
-		crtcs[ncrtc++] = randrp->crtcs[j];
-#endif
-	    if (pI830->operatingDevices & (pipe_type << (j << 3)))
-	    {
-		pipe = j;
-		crtc = randrp->crtcs[j];
-		crtcs[ncrtc++] = crtc;
-	    }
+	    /* Can't flip outputs among crtcs yet */
+	    ncrtc = 1;
+	    pipe = output->pipe;
+	    crtc = randrp->crtcs[pipe];
+	    crtcs[0] = randrp->crtcs[pipe];
+	}
+	else
+	{
+	    ncrtc = 0;
+	    pipe = -1;
+	    crtc = NULL;
 	}
 	if (!RROutputSetCrtcs (randrp->outputs[i], crtcs, ncrtc))
 	    return FALSE;
diff --git a/src/i830_video.c b/src/i830_video.c
index 47f4a03..a5cd77c 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -722,7 +722,7 @@ I830SetupImageVideoOverlay(ScreenPtr pSc
    pPriv->brightness = 0;
    pPriv->contrast = 64;
    pPriv->saturation = 128;
-   pPriv->pipe = pI830->pipe; /* default to current pipe */
+   pPriv->pipe = 0;  /* XXX must choose pipe wisely */
    pPriv->linear = NULL;
    pPriv->currentBuf = 0;
    pPriv->gamma5 = 0xc0c0c0;
@@ -3592,6 +3592,8 @@ I830VideoSwitchModeAfter(ScrnInfoPtr pSc
 
    pPriv->overlayOK = TRUE;
 
+#if 0
+   /* XXX Must choose pipe wisely */
    /* ensure pipe is updated on mode switch */
    if (!pI830->Clone) {
       if (pPriv->pipe != pI830->pipe) {
@@ -3600,6 +3602,7 @@ I830VideoSwitchModeAfter(ScrnInfoPtr pSc
          pPriv->pipe = pI830->pipe;
       }
    }
+#endif
 
    if (!IS_I965G(pI830)) {
       if (pPriv->pipe == 0) {
@@ -3628,8 +3631,8 @@ I830VideoSwitchModeAfter(ScrnInfoPtr pSc
    }
 
    /* Check we have an LFP connected */
-   if ((pPriv->pipe == 1 && pI830->operatingDevices & (PIPE_LFP << 8)) ||
-       (pPriv->pipe == 0 && pI830->operatingDevices & PIPE_LFP) ) {
+   if (i830PipeHasType (pScrn, pPriv->pipe, I830_OUTPUT_LVDS)) 
+   {
       size = pPriv->pipe ? INREG(PIPEBSRC) : INREG(PIPEASRC);
       hsize = (size >> 16) & 0x7FF;
       vsize = size & 0x7FF;
diff-tree e4bcec796e80e9fd66ab0c36394f5946915531f1 (from b7262a9a9110dac66e1a92c39dcb3ab59d95d081)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Fri Nov 3 23:29:12 2006 -0800

    Use pI830->availablePipes instead of MAX_DISPLAY_PIPES everywhere

diff --git a/src/i830.h b/src/i830.h
index 3e0625e..ea7f4c9 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -308,8 +308,6 @@ typedef struct _I830Rec {
     */
    DisplayModePtr savedCurrentMode;
 
-   I830PipeRec	  pipes[MAX_DISPLAY_PIPES];
-   
    Bool Clone;
    int CloneRefresh;
    int CloneHDisplay;
@@ -473,7 +471,8 @@ typedef struct _I830Rec {
    /* [0] is Pipe A, [1] is Pipe B. */
    int availablePipes;
    /* [0] is display plane A, [1] is display plane B. */
-
+   I830PipeRec	  pipes[MAX_DISPLAY_PIPES];
+   
    /* Driver phase/state information */
    Bool preinit;
    Bool starting;
diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index 0b7e772..6b0e58c 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -180,11 +180,11 @@ I830InitHWCursor(ScrnInfoPtr pScrn)
    int i;
 
    DPRINTF(PFX, "I830InitHWCursor\n");
-   for (i = 0; i < MAX_DISPLAY_PIPES; i++) 
+   for (i = 0; i < pI830->availablePipes; i++) 
       pI830->pipes[i].cursorShown = FALSE;
    /* Initialise the HW cursor registers, leaving the cursor hidden. */
    if (IS_MOBILE(pI830) || IS_I9XX(pI830)) {
-      for (i = 0; i < MAX_DISPLAY_PIPES; i++)
+      for (i = 0; i < pI830->availablePipes; i++)
       {
 	 int   cursor_control = i == 0 ? CURSOR_A_CONTROL : CURSOR_B_CONTROL;
 	 temp = INREG(cursor_control);
@@ -484,7 +484,7 @@ I830SetCursorPosition(ScrnInfoPtr pScrn,
     x -= hotspotx;
     y -= hotspoty;
 
-    for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++)
+    for (pipe = 0; pipe < pI830->availablePipes; pipe++)
     {
 	I830PipePtr	pI830Pipe = &pI830->pipes[pipe];
 	DisplayModePtr	mode = &pI830Pipe->curMode;
@@ -550,7 +550,7 @@ I830ShowCursor(ScrnInfoPtr pScrn)
 	   pI830->CursorMemARGB->Physical, pI830->CursorMemARGB->Start);
 
     pI830->cursorOn = TRUE;
-    for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++)
+    for (pipe = 0; pipe < pI830->availablePipes; pipe++)
 	I830SetPipeCursor (pScrn, pipe, TRUE);
 }
 
@@ -563,7 +563,7 @@ I830HideCursor(ScrnInfoPtr pScrn)
    DPRINTF(PFX, "I830HideCursor\n");
 
    pI830->cursorOn = FALSE;
-    for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++)
+    for (pipe = 0; pipe < pI830->availablePipes; pipe++)
 	I830SetPipeCursor (pScrn, pipe, TRUE);
 }
 
diff --git a/src/i830_display.c b/src/i830_display.c
index 1175cf1..8cb6660 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -660,7 +660,7 @@ 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 (i = 0; i < MAX_DISPLAY_PIPES; i++) {
+    for (i = 0; i < pI830->availablePipes; i++) {
 	I830PipePtr pI830Pipe = &pI830->pipes[i];
 	int	    dspcntr_reg = pipe == 0 ? DSPACNTR : DSPBCNTR;
 	int	    pipeconf_reg = pipe == 0 ? PIPEACONF : PIPEBCONF;
@@ -726,7 +726,7 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
     for (i = 0; i < pI830->num_outputs; i++)
 	pI830->output[i].pre_set_mode(pScrn, &pI830->output[i], pMode);
 
-    for (i = 0; i < MAX_DISPLAY_PIPES; i++)
+    for (i = 0; i < pI830->availablePipes; i++)
     {
 	if (pI830->pipes[i].planeEnabled)
 	    ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, i, pMode),
diff --git a/src/i830_driver.c b/src/i830_driver.c
index dd96ff1..1b75649 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3387,7 +3387,7 @@ I830EnterVT(int scrnIndex, int flags)
    SetHWOperatingState(pScrn);
 
    /* Mark that we'll need to re-set the mode for sure */
-   for (i = 0; i < MAX_DISPLAY_PIPES; i++)
+   for (i = 0; i < pI830->availablePipes; i++)
       memset(&pI830->pipes[i].curMode, 0, sizeof(pI830->pipes[i].curMode));
 
    if (!i830SetMode(pScrn, pScrn->currentMode))
diff --git a/src/i830_randr.c b/src/i830_randr.c
index c4e91fd..d097283 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -682,7 +682,7 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
 	ncrtc = 0;
 	pipe = -1;
 	crtc = NULL;
-	for (j = 0; j < MAX_DISPLAY_PIPES; j++)
+	for (j = 0; j < pI830->availablePipes; j++)
 	{
 #if 0
 	     /* Can't flip outputs among crtcs yet */
@@ -782,7 +782,7 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
 	if (!RROutputSetClones (randrp->outputs[i], clones, nclone))
 	    return FALSE;
     }
-    for (i = 0; i < MAX_DISPLAY_PIPES; i++)
+    for (i = 0; i < pI830->availablePipes; i++)
 	I830RandRCrtcNotify (randrp->crtcs[i]);
     return TRUE;
 }
@@ -815,7 +815,7 @@ I830RandRCreateScreenResources12 (Screen
     /*
      * Create RandR resources, then probe them
      */
-    for (i = 0; i < MAX_DISPLAY_PIPES; i++)
+    for (i = 0; i < pI830->availablePipes; i++)
     {
 	randrp->crtcs[i] = RRCrtcCreate (pScreen, (void *) i);
 	RRCrtcGammaSetSize (randrp->crtcs[i], 256);
@@ -851,7 +851,7 @@ I830RandRCreateScreenResources12 (Screen
 				mmHeight);
     }
 
-    for (i = 0; i < MAX_DISPLAY_PIPES; i++)
+    for (i = 0; i < pI830->availablePipes; i++)
 	i830PipeSetBase(pScrn, i, 0, 0);
 
     return I830RandRSetInfo12 (pScreen);
diff-tree b7262a9a9110dac66e1a92c39dcb3ab59d95d081 (from 4625073244d4f521a07e12adcf0609e85658acbe)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Fri Nov 3 23:24:07 2006 -0800

    Finish removing persistant vbe data

diff --git a/src/i830.h b/src/i830.h
index 10061d1..3e0625e 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -463,11 +463,6 @@ typedef struct _I830Rec {
    /* Stolen memory support */
    Bool StolenOnly;
 
-#if 0
-   /* Video BIOS support. */
-   vbeInfoPtr pVbe;
-#endif
-
    Bool swfSaved;
    CARD32 saveSWF0;
    CARD32 saveSWF4;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 1e92dac..dd96ff1 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -367,13 +367,6 @@ I830FreeRec(ScrnInfoPtr pScrn)
 
    pI830 = I830PTR(pScrn);
 
-#if 0
-   if (I830IsPrimary(pScrn)) {
-      if (pI830->pVbe)
-         vbeFree(pI830->pVbe);
-   }
-#endif
-
    xfree(pScrn->driverPrivate);
    pScrn->driverPrivate = NULL;
 }
@@ -547,20 +540,6 @@ I830DetectMemory(ScrnInfoPtr pScrn)
       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "no video memory detected.\n");
    }
 
-#if 0
-   /* Sanity check: compare with what the BIOS thinks. */
-   vbeInfo = VBEGetVBEInfo(pI830->pVbe);
-   if (vbeInfo != NULL && vbeInfo->TotalMemory != memsize / 1024 / 64) {
-      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		 "Detected stolen memory (%d kB) doesn't match what the BIOS"
-		 " reports (%d kB)\n",
-		 ROUND_DOWN_TO(memsize / 1024, 64),
-		 vbeInfo->TotalMemory * 64);
-   }
-   if (vbeInfo != NULL)
-      VBEFreeVBEInfo(vbeInfo);
-#endif
-
    return memsize;
 }
 
@@ -1007,19 +986,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    /* We have to use PIO to probe, because we haven't mapped yet. */
    I830SetPIOAccess(pI830);
 
-#if 0
-   /* Initialize VBE record */
-   if (I830IsPrimary(pScrn)) {
-      if ((pI830->pVbe = VBEInit(NULL, pI830->pEnt->index)) == NULL) {
-         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "VBE initialization failed.\n");
-         return FALSE;
-      }
-   } else {
-      I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
-      pI830->pVbe = pI8301->pVbe;
-   }
-#endif
-
    switch (pI830->PciInfo->chipType) {
    case PCI_CHIP_I830_M:
       chipname = "830M";
diff-tree 4625073244d4f521a07e12adcf0609e85658acbe (from 719ad68515be9b996a6314de5448843de1146b88)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Fri Nov 3 23:23:38 2006 -0800

    Oops, martian memset of randr modes pointer

diff --git a/src/i830_randr.c b/src/i830_randr.c
index 67641d6..c4e91fd 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -873,7 +873,6 @@ I830RandRInit12 (ScreenPtr pScreen)
     rp->rrCrtcSet = I830RandRCrtcSet;
     rp->rrCrtcSetGamma = I830RandRCrtcSetGamma;
     rp->rrSetConfig = NULL;
-    memset (rp->modes, '\0', sizeof (rp->modes));
     pScrn->PointerMoved = I830RandRPointerMoved;
     return TRUE;
 }
diff-tree 719ad68515be9b996a6314de5448843de1146b88 (from 9681602177124e84a817a1e1d428f1779f2a45c9)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Fri Nov 3 19:41:41 2006 -0800

    Use VBE only temporarily to fetch BIOS rom image
    (cherry picked from 6a9386651785afc70a29e355255e8295b321f28e commit)

diff --git a/src/i830.h b/src/i830.h
index b4b17de..10061d1 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -463,8 +463,10 @@ typedef struct _I830Rec {
    /* Stolen memory support */
    Bool StolenOnly;
 
+#if 0
    /* Video BIOS support. */
    vbeInfoPtr pVbe;
+#endif
 
    Bool swfSaved;
    CARD32 saveSWF0;
diff --git a/src/i830_bios.c b/src/i830_bios.c
index 97fb7fc..0821845 100644
--- a/src/i830_bios.c
+++ b/src/i830_bios.c
@@ -84,15 +84,18 @@ i830GetBIOS(ScrnInfoPtr pScrn)
     struct vbt_header *vbt;
     int vbt_off;
     unsigned char *bios;
+    vbeInfoPtr	pVbe;
 
     bios = xalloc(INTEL_VBIOS_SIZE);
     if (bios == NULL)
 	return NULL;
 
-    if (pI830->pVbe != NULL) {
-	memcpy(bios, xf86int10Addr(pI830->pVbe->pInt10,
-					   pI830->pVbe->pInt10->BIOSseg << 4),
+    pVbe = VBEInit (NULL, pI830->pEnt->index);
+    if (pVbe != NULL) {
+	memcpy(bios, xf86int10Addr(pVbe->pInt10,
+				   pVbe->pInt10->BIOSseg << 4),
 	       INTEL_VBIOS_SIZE);
+	vbeFree (pVbe);
     } else {
 	xf86ReadPciBIOS(0, pI830->PciTag, 0, bios, INTEL_VBIOS_SIZE);
     }
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 3b21974..1e92dac 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -367,10 +367,12 @@ I830FreeRec(ScrnInfoPtr pScrn)
 
    pI830 = I830PTR(pScrn);
 
+#if 0
    if (I830IsPrimary(pScrn)) {
       if (pI830->pVbe)
          vbeFree(pI830->pVbe);
    }
+#endif
 
    xfree(pScrn->driverPrivate);
    pScrn->driverPrivate = NULL;
@@ -477,7 +479,9 @@ I830DetectMemory(ScrnInfoPtr pScrn)
    CARD16 gmch_ctrl;
    int memsize = 0;
    int range;
+#if 0
    VbeInfoBlock *vbeInfo;
+#endif
 
    bridge = pciTag(0, 0, 0);		/* This is always the host bridge */
    gmch_ctrl = pciReadWord(bridge, I830_GMCH_CTRL);
@@ -543,6 +547,7 @@ I830DetectMemory(ScrnInfoPtr pScrn)
       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "no video memory detected.\n");
    }
 
+#if 0
    /* Sanity check: compare with what the BIOS thinks. */
    vbeInfo = VBEGetVBEInfo(pI830->pVbe);
    if (vbeInfo != NULL && vbeInfo->TotalMemory != memsize / 1024 / 64) {
@@ -554,6 +559,7 @@ I830DetectMemory(ScrnInfoPtr pScrn)
    }
    if (vbeInfo != NULL)
       VBEFreeVBEInfo(vbeInfo);
+#endif
 
    return memsize;
 }
@@ -1001,6 +1007,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    /* We have to use PIO to probe, because we haven't mapped yet. */
    I830SetPIOAccess(pI830);
 
+#if 0
    /* Initialize VBE record */
    if (I830IsPrimary(pScrn)) {
       if ((pI830->pVbe = VBEInit(NULL, pI830->pEnt->index)) == NULL) {
@@ -1011,6 +1018,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
       pI830->pVbe = pI8301->pVbe;
    }
+#endif
 
    switch (pI830->PciInfo->chipType) {
    case PCI_CHIP_I830_M:
diff-tree 27df2ff7908ea7ea2943a5f3445e12dbc24d97c9 (from ecbe73b940b2d642115de4b73c2f757eb46ff956)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Nov 3 15:55:10 2006 -0800

    Report pipe status (and status mismatches) in i830DescribeOutputConfiguration()

diff --git a/src/i830_display.c b/src/i830_display.c
index e3db8ad..e36b5ef 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -796,12 +796,32 @@ i830DescribeOutputConfiguration(ScrnInfo
 
     for (i = 0; i < pI830->availablePipes; i++) {
 	CARD32 dspcntr = INREG(DSPACNTR + (DSPBCNTR - DSPACNTR) * i);
+	CARD32 pipeconf = INREG(PIPEACONF + (PIPEBCONF - PIPEACONF) * i);
+	Bool hw_plane_enable = (dspcntr & DISPLAY_PLANE_ENABLE) != 0;
+	Bool hw_pipe_enable = (pipeconf & PIPEACONF_ENABLE) != 0;
 
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		   "  Pipe %c is %s\n",
+		   'A' + i, pI830->pipes[i].planeEnabled ? "on" : "off");
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		   "  Display plane %c is now %s and connected to pipe %c.\n",
 		   'A' + i,
 		   pI830->pipes[i].planeEnabled ? "enabled" : "disabled",
 		   dspcntr & DISPPLANE_SEL_PIPE_MASK ? 'B' : 'A');
+	if (hw_pipe_enable != pI830->pipes[i].planeEnabled) {
+	    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].planeEnabled ? "on" : "off");
+	}
+	if (hw_plane_enable != pI830->pipes[i].planeEnabled) {
+	    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].planeEnabled ? "on" : "off");
+	}
     }
 
     for (i = 0; i < pI830->num_outputs; i++) {
diff-tree ecbe73b940b2d642115de4b73c2f757eb46ff956 (from parents)
Merge: 561af007974b8cdad1eea907fb73ed9d430c21ac 9681602177124e84a817a1e1d428f1779f2a45c9
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Nov 3 15:59:59 2006 -0800

    Merge branch 'modesetting-origin' into modesetting
    
    Conflicts:
    
    	src/i830_display.c

diff --cc src/i830_display.c
index 6107c47,1175cf1..e3db8ad
@@@ -356,18 -357,14 +357,19 @@@
  }
  
  /**
 - * Sets the given video mode on the given pipe.  Assumes that plane A feeds
 - * pipe A, and plane B feeds pipe B.  Should not affect the other planes/pipes.
 + * Sets the given video mode on the given pipe.
 + *
 + * Plane A is always output to pipe A, and plane B to pipe B.  The plane
 + * will not be enabled if plane_enable is FALSE, which is used for
 + * load detection, when something else will be output to the pipe other than
 + * display data.
   */
  Bool
 -i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe)
 +i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe,
 +		Bool plane_enable)
  {
      I830Ptr pI830 = I830PTR(pScrn);
+     I830PipePtr pI830Pipe = &pI830->pipes[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;
@@@ -628,12 -635,10 +640,12 @@@
      temp = INREG(pipeconf_reg);
      OUTREG(pipeconf_reg, temp | PIPEACONF_ENABLE);
  
 -    /* And then turn the plane on */
 -    OUTREG(dspcntr_reg, dspcntr);
 +    if (plane_enable) {
 +	/* And then turn the plane on */
 +	OUTREG(dspcntr_reg, dspcntr);
 +    }
  
-     pI830->pipeCurMode[pipe] = *pMode;
+     pI830Pipe->curMode = *pMode;
  
      return TRUE;
  }
@@@ -729,31 -720,17 +727,18 @@@
      didLock = I830DRILock(pScrn);
  #endif
  
-     if (pI830->operatingDevices & 0xff) {
- 	pI830->planeEnabled[0] = 1;
-     } else {
- 	pI830->planeEnabled[0] = 0;
-     }
- 
-     if (pI830->operatingDevices & 0xff00) {
- 	pI830->planeEnabled[1] = 1;
-     } else {
- 	pI830->planeEnabled[1] = 0;
-     }
+     pI830->pipes[0].planeEnabled = (pI830->operatingDevices & 0xff) != 0;
+     pI830->pipes[1].planeEnabled = (pI830->operatingDevices & 0xff00) != 0;
  
-     for (i = 0; i < pI830->num_outputs; i++) {
+     for (i = 0; i < pI830->num_outputs; i++)
  	pI830->output[i].pre_set_mode(pScrn, &pI830->output[i], pMode);
-     }
  
-     if (pI830->planeEnabled[0]) {
- 	ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, 0, pMode),
- 			     0, TRUE);
- 	if (!ok)
- 	    goto done;
-     }
-     if (pI830->planeEnabled[1]) {
- 	ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, 1, pMode),
- 			     1, TRUE);
+     for (i = 0; i < MAX_DISPLAY_PIPES; i++)
+     {
+ 	if (pI830->pipes[i].planeEnabled)
 -	    ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, i, pMode),
 -				 i);
++	    ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, i,
++								pMode),
++				 i, TRUE);
  	if (!ok)
  	    goto done;
      }
diff --cc src/i830_randr.c
index 5b02a53,67641d6..8b6ad49
@@@ -560,10 -562,10 +562,10 @@@
  
      if (display_mode != randrp->modes[pipe])
      {
- 	pI830->planeEnabled[pipe] = mode != NULL;
+ 	pI830Pipe->planeEnabled = mode != NULL;
  	if (display_mode)
  	{
 -	    if (!i830PipeSetMode (pScrn, display_mode, pipe))
 +	    if (!i830PipeSetMode (pScrn, display_mode, pipe, TRUE))
  		return FALSE;
  	    /* XXX need I830SDVOPostSetMode here */
  	}
diff-tree 561af007974b8cdad1eea907fb73ed9d430c21ac (from e416b426d83de031441ada7a77b6bd66cec8b5c9)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Nov 3 15:26:14 2006 -0800

    Add support for load-based CRT detection.

diff --git a/src/i830.h b/src/i830.h
index a07ba8e..4ce1a55 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -205,6 +205,11 @@ struct _I830OutputRec {
    int type;
    int pipe;
    Bool disabled;
+   /**
+    * 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.
diff --git a/src/i830_crt.c b/src/i830_crt.c
index 0225727..4c704b2 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -32,6 +32,7 @@
 #include "xf86.h"
 #include "i830.h"
 #include "i830_xf86Modes.h"
+#include "i830_display.h"
 
 static void
 i830_crt_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
@@ -166,7 +167,7 @@ i830_crt_detect_hotplug(ScrnInfoPtr pScr
  * \return FALSE if CRT is disconnected.
  */
 static Bool
-i830_crt_detect_load(ScrnInfoPtr pScrn)
+i830_crt_detect_load(ScrnInfoPtr pScrn, I830OutputPtr output)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     CARD32 adpa, pipeconf;
@@ -174,7 +175,7 @@ i830_crt_detect_load(ScrnInfoPtr pScrn)
     int pipeconf_reg, bclrpat_reg, dpll_reg;
     int pipe;
 
-    pipe = pI830->pipe;
+    pipe = output->pipe;
     if (pipe == 0) {
 	bclrpat_reg = BCLRPAT_A;
 	pipeconf_reg = PIPEACONF;
@@ -263,15 +264,12 @@ i830_crt_detect(ScrnInfoPtr pScrn, I830O
     if (i830_crt_detect_ddc(pScrn))
 	return OUTPUT_STATUS_CONNECTED;
 
-    /* Use the load-detect method if we're not currently outputting to the CRT,
-     * or we don't care.
-     *
-     * Actually, the method is unreliable currently.  We need to not share a
-     * pipe, as it seems having other outputs on that pipe will result in a
-     * false positive.
-     */
-    if (0) {
-	if (i830_crt_detect_load(pScrn))
+    /* 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);
+
+	i830ReleaseLoadDetectPipe(pScrn, output);
+	if (connected)
 	    return OUTPUT_STATUS_CONNECTED;
 	else
 	    return OUTPUT_STATUS_DISCONNECTED;
diff --git a/src/i830_display.c b/src/i830_display.c
index b3019f8..6107c47 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -356,11 +356,16 @@ i830PipeFindClosestMode(ScrnInfoPtr pScr
 }
 
 /**
- * Sets the given video mode on the given pipe.  Assumes that plane A feeds
- * pipe A, and plane B feeds pipe B.  Should not affect the other planes/pipes.
+ * Sets the given video mode on the given pipe.
+ *
+ * Plane A is always output to pipe A, and plane B to pipe B.  The plane
+ * will not be enabled if plane_enable is FALSE, which is used for
+ * load detection, when something else will be output to the pipe other than
+ * display data.
  */
 Bool
-i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe)
+i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe,
+		Bool plane_enable)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     int m1 = 0, m2 = 0, n = 0, p1 = 0, p2 = 0;
@@ -623,8 +628,10 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     temp = INREG(pipeconf_reg);
     OUTREG(pipeconf_reg, temp | PIPEACONF_ENABLE);
 
-    /* And then turn the plane on */
-    OUTREG(dspcntr_reg, dspcntr);
+    if (plane_enable) {
+	/* And then turn the plane on */
+	OUTREG(dspcntr_reg, dspcntr);
+    }
 
     pI830->pipeCurMode[pipe] = *pMode;
 
@@ -740,13 +747,13 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
 
     if (pI830->planeEnabled[0]) {
 	ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, 0, pMode),
-			     0);
+			     0, TRUE);
 	if (!ok)
 	    goto done;
     }
     if (pI830->planeEnabled[1]) {
 	ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, 1, pMode),
-			     1);
+			     1, TRUE);
 	if (!ok)
 	    goto done;
     }
@@ -842,3 +849,99 @@ i830DescribeOutputConfiguration(ScrnInfo
 		   pI830->output[i].pipe == 0 ? 'A' : 'B');
     }
 }
+
+/**
+ * Get a pipe with a simple mode set on it for doing load-based monitor
+ * detection.
+ *
+ * It will be up to the load-detect code to adjust the pipe as appropriate for
+ * its requirements.  The pipe will be connected to no other outputs.
+ *
+ * Currently this code will only succeed if there is a pipe with no outputs
+ * 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.
+ */
+int
+i830GetLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    Bool pipe_available[MAX_DISPLAY_PIPES];
+    int i;
+    /* VESA 640x480x72Hz mode to set on the pipe */
+    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 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->disabled) {
+	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;
+	}
+    }
+
+    for (i = 0; i < pI830->availablePipes; i++) {
+	pipe_available[i] = TRUE;
+    }
+
+    for (i = 0; i < pI830->num_outputs; i++) {
+	if (!pI830->output[i].disabled)
+	{
+	    pipe_available[pI830->output[i].pipe] = FALSE;
+	}
+    }
+
+    for (i = 0; i < pI830->availablePipes; i++) {
+	if (pipe_available[i])
+	    break;
+    }
+
+    if (i == pI830->availablePipes) {
+	return -1;
+    }
+    output->load_detect_temp = TRUE;
+    output->pipe = i;
+    output->disabled = FALSE;
+
+    I830xf86SetModeCrtc(&mode, INTERLACE_HALVE_V);
+
+    i830PipeSetMode(pScrn, &mode, i, FALSE);
+
+    return i;
+}
+
+void
+i830ReleaseLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output)
+{
+    if (output->load_detect_temp) {
+	output->disabled = TRUE;
+	i830DisableUnusedFunctions(pScrn);
+	output->load_detect_temp = FALSE;
+    }
+}
diff --git a/src/i830_display.h b/src/i830_display.h
index 8a6e9e9..5c0f133 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -26,9 +26,12 @@
  */
 
 /* i830_display.c */
-Bool i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe);
+Bool i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe,
+		     Bool plane_enable);
 void i830DisableUnusedFunctions(ScrnInfoPtr pScrn);
 Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
 void i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y);
 void i830WaitForVblank(ScrnInfoPtr pScrn);
 void i830DescribeOutputConfiguration(ScrnInfoPtr pScrn);
+int i830GetLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output);
+void i830ReleaseLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output);
diff --git a/src/i830_randr.c b/src/i830_randr.c
index e4ae9d0..5b02a53 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -563,7 +563,7 @@ I830RandRCrtcSet (ScreenPtr	pScreen,
 	pI830->planeEnabled[pipe] = mode != NULL;
 	if (display_mode)
 	{
-	    if (!i830PipeSetMode (pScrn, display_mode, pipe))
+	    if (!i830PipeSetMode (pScrn, display_mode, pipe, TRUE))
 		return FALSE;
 	    /* XXX need I830SDVOPostSetMode here */
 	}
diff-tree e416b426d83de031441ada7a77b6bd66cec8b5c9 (from 282a9e073ea985cbf0d0f3f296d593af1426bad5)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Nov 3 15:25:41 2006 -0800

    Print out modelines as info, not error (which had been used for debugging).

diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c
index 166f41a..ca92e4d 100644
--- a/src/i830_xf86Modes.c
+++ b/src/i830_xf86Modes.c
@@ -317,7 +317,7 @@ PrintModeline(int scrnIndex,DisplayModeP
 #if 0
     if (mode->Flags & V_CLKDIV2) add(&flags, "vclk/2");
 #endif
-    xf86DrvMsg(scrnIndex, X_ERROR,
+    xf86DrvMsg(scrnIndex, X_INFO,
 		   "Modeline \"%s\"x%.01f  %6.2f  %i %i %i %i  %i %i %i %i%s "
 		   "(%.01f kHz)\n",
 		   mode->name, mode->VRefresh, mode->Clock/1000., mode->HDisplay,
diff-tree 282a9e073ea985cbf0d0f3f296d593af1426bad5 (from 0510671a6c5233468ac20f0ec8096e084df03ce6)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Nov 3 13:46:09 2006 -0800

    Don't memset the modes pointer on init, which was dereferencing NULL.

diff --git a/src/i830_randr.c b/src/i830_randr.c
index 59ebcc0..e4ae9d0 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -874,7 +874,6 @@ I830RandRInit12 (ScreenPtr pScreen)
     rp->rrCrtcSet = I830RandRCrtcSet;
     rp->rrCrtcSetGamma = I830RandRCrtcSetGamma;
     rp->rrSetConfig = NULL;
-    memset (rp->modes, '\0', sizeof (rp->modes));
     pScrn->PointerMoved = I830RandRPointerMoved;
     return TRUE;
 }
diff-tree 9681602177124e84a817a1e1d428f1779f2a45c9 (from 2c9ab6e0594769274f2dbcdf7c00fe297fc385d5)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Fri Nov 3 12:55:25 2006 -0800

    Create I830PipeRec to hold pipe-specific data. Remove unused I830 members.
    
    I830 contained six parallel arrays for pipe-specific data; these
    have been moved to a I830PipeRec structure instead.
    
    I830 also contained several unused members:
    
       unsigned int bios_version;
       Bool newPipeSwitch;
       Bool fakeSwitch;
       int fixedPipe;
    
    These have been removed, along with the code that set them.

diff --git a/src/i830.h b/src/i830.h
index bb17f3f..b4b17de 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -287,31 +287,29 @@ struct _I830OutputRec {
    void *dev_priv;
 };
 
+typedef struct _I830PipeRec {
+   Bool		  gammaEnabled;
+   int		  x;
+   int		  y;
+   Bool		  cursorInRange;
+   Bool		  cursorShown;
+   Bool		  planeEnabled;
+   DisplayModeRec curMode;
+} I830PipeRec, *I830PipePtr;
+
 typedef struct _I830Rec {
    unsigned char *MMIOBase;
    unsigned char *FbBase;
    int cpp;
 
-   unsigned int bios_version;
-
-   Bool newPipeSwitch;
-
-   Bool fakeSwitch;
-   
-   int fixedPipe;
-
    DisplayModePtr currentMode;
    /* Mode saved during randr reprobe, which will need to be freed at the point
     * of the next SwitchMode, when we lose this last reference to it.
     */
    DisplayModePtr savedCurrentMode;
 
-   Bool gammaEnabled[MAX_DISPLAY_PIPES];
-
-   int pipeX[MAX_DISPLAY_PIPES];
-   int pipeY[MAX_DISPLAY_PIPES];
-   Bool cursorInRange[MAX_DISPLAY_PIPES];
-   Bool cursorShown[MAX_DISPLAY_PIPES];
+   I830PipeRec	  pipes[MAX_DISPLAY_PIPES];
+   
    Bool Clone;
    int CloneRefresh;
    int CloneHDisplay;
@@ -478,8 +476,6 @@ typedef struct _I830Rec {
    /* [0] is Pipe A, [1] is Pipe B. */
    int availablePipes;
    /* [0] is display plane A, [1] is display plane B. */
-   int planeEnabled[MAX_DISPLAY_PIPES];
-   DisplayModeRec pipeCurMode[MAX_DISPLAY_PIPES];
 
    /* Driver phase/state information */
    Bool preinit;
diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index 92239f1..0b7e772 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -105,14 +105,15 @@ void
 I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe, Bool force)
 {
    I830Ptr pI830 = I830PTR(pScrn);
+   I830PipePtr pI830Pipe = &pI830->pipes[pipe];
    CARD32 temp;
     Bool show;
     
-    if (!pI830->planeEnabled[pipe])
+    if (!pI830Pipe->planeEnabled)
 	return;
 
-    show = pI830->cursorOn && pI830->cursorInRange[pipe];
-    if (show && (force || !pI830->cursorShown[pipe]))
+    show = pI830->cursorOn && pI830Pipe->cursorInRange;
+    if (show && (force || !pI830Pipe->cursorShown))
     {
 	if (IS_MOBILE(pI830) || IS_I9XX(pI830)) {
 	    int	cursor_control;
@@ -124,7 +125,7 @@ I830SetPipeCursor (ScrnInfoPtr pScrn, in
 	    temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
 	    if (pI830->CursorIsARGB) {
 		temp |= CURSOR_MODE_64_ARGB_AX;
-		if (pI830->gammaEnabled[pipe])
+		if (pI830Pipe->gammaEnabled)
 		    temp |= MCURSOR_GAMMA_ENABLE;
 	    } else
 		temp |= CURSOR_MODE_64_4C_AX;
@@ -138,15 +139,15 @@ I830SetPipeCursor (ScrnInfoPtr pScrn, in
 	    temp |= CURSOR_ENABLE;
 	    if (pI830->CursorIsARGB) {
 		temp |= CURSOR_FORMAT_ARGB;
-		if (pI830->gammaEnabled[pipe])
+		if (pI830Pipe->gammaEnabled)
 		    temp |= CURSOR_GAMMA_ENABLE;
 	    } else
 		temp |= CURSOR_FORMAT_3C;
 	    OUTREG(CURSOR_CONTROL, temp);
 	}
-	pI830->cursorShown[pipe] = TRUE;
+	pI830Pipe->cursorShown = TRUE;
     }
-    else if (!show && (force || pI830->cursorShown[pipe]))
+    else if (!show && (force || pI830Pipe->cursorShown))
     {
 	if (IS_MOBILE(pI830) || IS_I9XX(pI830)) 
 	{
@@ -164,7 +165,7 @@ I830SetPipeCursor (ScrnInfoPtr pScrn, in
 	    temp &= ~(CURSOR_ENABLE|CURSOR_GAMMA_ENABLE);
 	    OUTREG(CURSOR_CONTROL, temp);
 	}
-	pI830->cursorShown[pipe] = FALSE;
+	pI830Pipe->cursorShown = FALSE;
     }
 
     /* Flush cursor changes. */
@@ -179,7 +180,8 @@ I830InitHWCursor(ScrnInfoPtr pScrn)
    int i;
 
    DPRINTF(PFX, "I830InitHWCursor\n");
-   for (i = 0; i < MAX_DISPLAY_PIPES; i++) pI830->cursorShown[i] = FALSE;
+   for (i = 0; i < MAX_DISPLAY_PIPES; i++) 
+      pI830->pipes[i].cursorShown = FALSE;
    /* Initialise the HW cursor registers, leaving the cursor hidden. */
    if (IS_MOBILE(pI830) || IS_I9XX(pI830)) {
       for (i = 0; i < MAX_DISPLAY_PIPES; i++)
@@ -484,11 +486,12 @@ I830SetCursorPosition(ScrnInfoPtr pScrn,
 
     for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++)
     {
-	DisplayModePtr	mode = &pI830->pipeCurMode[pipe];
-	int		thisx = x - pI830->pipeX[pipe];
-	int		thisy = y - pI830->pipeY[pipe];
+	I830PipePtr	pI830Pipe = &pI830->pipes[pipe];
+	DisplayModePtr	mode = &pI830Pipe->curMode;
+	int		thisx = x - pI830Pipe->x;
+	int		thisy = y - pI830Pipe->y;
 
-	if (!pI830->planeEnabled[pipe])
+	if (!pI830Pipe->planeEnabled)
 	    continue;
 
 	/*
@@ -524,7 +527,7 @@ I830SetCursorPosition(ScrnInfoPtr pScrn,
 	if (pipe == 1)
 	    OUTREG(CURSOR_B_POSITION, temp);
 
-	pI830->cursorInRange[pipe] = inrange;
+	pI830Pipe->cursorInRange = inrange;
 	
         I830SetPipeCursor (pScrn, pipe, FALSE);
     }
@@ -577,14 +580,14 @@ I830SetCursorColors(ScrnInfoPtr pScrn, i
 
    DPRINTF(PFX, "I830SetCursorColors\n");
 
-   if (pI830->planeEnabled[0])
+   if (pI830->pipes[0].planeEnabled)
    {
        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->planeEnabled[1])
+   if (pI830->pipes[1].planeEnabled)
    {
       OUTREG(CURSOR_B_PALETTE0, bg & 0x00ffffff);
       OUTREG(CURSOR_B_PALETTE1, fg & 0x00ffffff);
diff --git a/src/i830_display.c b/src/i830_display.c
index 4716e86..1175cf1 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -237,6 +237,7 @@ void
 i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y)
 {
     I830Ptr pI830 = I830PTR(pScrn);
+    I830PipePtr pI830Pipe = &pI830->pipes[pipe];
     unsigned long Start;
     int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE);
     int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
@@ -255,8 +256,8 @@ i830PipeSetBase(ScrnInfoPtr pScrn, int p
 	OUTREG(dspbase, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
     }
 
-    pI830->pipeX[pipe] = x;
-    pI830->pipeY[pipe] = y;
+    pI830Pipe->x = x;
+    pI830Pipe->y = y;
 }
 
 /**
@@ -363,6 +364,7 @@ Bool
 i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe)
 {
     I830Ptr pI830 = I830PTR(pScrn);
+    I830PipePtr pI830Pipe = &pI830->pipes[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;
@@ -391,7 +393,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     else
 	outputs = (pI830->operatingDevices >> 8) & 0xff;
 
-    if (I830ModesEqual(&pI830->pipeCurMode[pipe], pMode))
+    if (I830ModesEqual(&pI830Pipe->curMode, pMode))
 	return TRUE;
 
     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested pix clock: %d\n",
@@ -576,7 +578,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	FatalError("unknown display bpp\n");
     }
 
-    if (pI830->gammaEnabled[pipe]) {
+    if (pI830Pipe->gammaEnabled) {
  	dspcntr |= DISPPLANE_GAMMA_ENABLE;
     }
 
@@ -626,7 +628,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     OUTREG(dspstride_reg, pScrn->displayWidth * pI830->cpp);
     OUTREG(dspsize_reg, dspsize);
     OUTREG(dsppos_reg, 0);
-    i830PipeSetBase(pScrn, pipe, pI830->pipeX[pipe], pI830->pipeX[pipe]);
+    i830PipeSetBase(pScrn, pipe, pI830Pipe->x, pI830Pipe->y);
     OUTREG(pipesrc_reg, pipesrc);
 
     /* Then, turn the pipe on first */
@@ -636,7 +638,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     /* And then turn the plane on */
     OUTREG(dspcntr_reg, dspcntr);
 
-    pI830->pipeCurMode[pipe] = *pMode;
+    pI830Pipe->curMode = *pMode;
 
     return TRUE;
 }
@@ -658,63 +660,49 @@ i830DisableUnusedFunctions(ScrnInfoPtr p
      * internal TV) should have no outputs trying to pull data out of it, so
      * we're ready to turn those off.
      */
-    if (!pI830->planeEnabled[0]) {
-	CARD32 dspcntr, pipeconf, dpll;
+    for (i = 0; i < MAX_DISPLAY_PIPES; i++) {
+	I830PipePtr pI830Pipe = &pI830->pipes[i];
+	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";
 
-	dspcntr = INREG(DSPACNTR);
+	if (pI830Pipe->planeEnabled)
+	    continue;
+	
+	dspcntr = INREG(dspcntr_reg);
 	if (dspcntr & DISPLAY_PLANE_ENABLE) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling plane A\n");
-	    OUTREG(DSPACNTR, dspcntr & ~DISPLAY_PLANE_ENABLE);
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling plane %s\n",
+		       pipe_name);
+	    
+	    OUTREG(dspcntr_reg, dspcntr & ~DISPLAY_PLANE_ENABLE);
 
 	    /* Wait for vblank for the disable to take effect */
 	    i830WaitForVblank(pScrn);
 	}
 
-	pipeconf = INREG(PIPEACONF);
+	pipeconf = INREG(pipeconf_reg);
 	if (pipeconf & PIPEACONF_ENABLE) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling pipe A\n");
-	   OUTREG(PIPEACONF, pipeconf & ~PIPEACONF_ENABLE);
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling pipe %s\n",
+		       pipe_name);
+	   OUTREG(pipeconf_reg, pipeconf & ~PIPEACONF_ENABLE);
 	}
 
-	dpll = INREG(DPLL_A);
+	dpll = INREG(dpll_reg);
 	if (dpll & DPLL_VCO_ENABLE) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling DPLL A\n");
-	    OUTREG(DPLL_A, dpll & ~DPLL_VCO_ENABLE);
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling DPLL %s\n",
+		       pipe_name);
+	    OUTREG(dpll_reg, dpll & ~DPLL_VCO_ENABLE);
 	}
 
-	memset(&pI830->pipeCurMode[0], 0, sizeof(pI830->pipeCurMode[0]));
-    }
-
-    if (!pI830->planeEnabled[1]) {
-	CARD32 dspcntr, pipeconf, dpll;
-
-	dspcntr = INREG(DSPBCNTR);
-	if (dspcntr & DISPLAY_PLANE_ENABLE) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling plane B\n");
-	    OUTREG(DSPBCNTR, dspcntr & ~DISPLAY_PLANE_ENABLE);
-
-	    /* Wait for vblank for the disable to take effect */
-	    i830WaitForVblank(pScrn);
-	}
-
-	pipeconf = INREG(PIPEBCONF);
-	if (pipeconf & PIPEBCONF_ENABLE) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling pipe B\n");
-	   OUTREG(PIPEBCONF, pipeconf & ~PIPEBCONF_ENABLE);
-	}
-
-	dpll = INREG(DPLL_B);
-	if (dpll & DPLL_VCO_ENABLE) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling DPLL B\n");
-	    OUTREG(DPLL_B, dpll & ~DPLL_VCO_ENABLE);
-	}
-
-	memset(&pI830->pipeCurMode[1], 0, sizeof(pI830->pipeCurMode[1]));
+	memset(&pI830Pipe->curMode, 0, sizeof(pI830Pipe->curMode));
     }
 }
 
 /**
- * This function sets the given mode on the active pipes.
+ * This function configures the screens in clone mode on
+ * all active outputs using a mode similar to the specified mode.
  */
 Bool
 i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
@@ -732,31 +720,17 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
     didLock = I830DRILock(pScrn);
 #endif
 
-    if (pI830->operatingDevices & 0xff) {
-	pI830->planeEnabled[0] = 1;
-    } else {
-	pI830->planeEnabled[0] = 0;
-    }
+    pI830->pipes[0].planeEnabled = (pI830->operatingDevices & 0xff) != 0;
+    pI830->pipes[1].planeEnabled = (pI830->operatingDevices & 0xff00) != 0;
 
-    if (pI830->operatingDevices & 0xff00) {
-	pI830->planeEnabled[1] = 1;
-    } else {
-	pI830->planeEnabled[1] = 0;
-    }
-
-    for (i = 0; i < pI830->num_outputs; i++) {
+    for (i = 0; i < pI830->num_outputs; i++)
 	pI830->output[i].pre_set_mode(pScrn, &pI830->output[i], pMode);
-    }
 
-    if (pI830->planeEnabled[0]) {
-	ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, 0, pMode),
-			     0);
-	if (!ok)
-	    goto done;
-    }
-    if (pI830->planeEnabled[1]) {
-	ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, 1, pMode),
-			     1);
+    for (i = 0; i < MAX_DISPLAY_PIPES; i++)
+    {
+	if (pI830->pipes[i].planeEnabled)
+	    ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, i, pMode),
+				 i);
 	if (!ok)
 	    goto done;
     }
@@ -776,13 +750,10 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
 	/* If we might have enabled/disabled some pipes, we need to reset
 	 * cloning mode support.
 	 */
-	if ((pI830->operatingDevices & 0x00ff) &&
-	    (pI830->operatingDevices & 0xff00))
-	{
+	if (pI830->pipes[0].planeEnabled && pI830->pipes[1].planeEnabled)
 	    pI830->Clone = TRUE;
-	} else {
+	else
 	    pI830->Clone = FALSE;
-	}
 
 	/* If HW cursor currently showing, reset cursor state */
 	if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn)
@@ -821,7 +792,7 @@ i830DescribeOutputConfiguration(ScrnInfo
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		   "  Display plane %c is now %s and connected to pipe %c.\n",
 		   'A' + i,
-		   pI830->planeEnabled[i] ? "enabled" : "disabled",
+		   pI830->pipes[i].planeEnabled ? "enabled" : "disabled",
 		   dspcntr & DISPPLANE_SEL_PIPE_MASK ? 'B' : 'A');
     }
 
diff --git a/src/i830_dri.c b/src/i830_dri.c
index c9b52c4..41ea21c 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1485,7 +1485,7 @@ I830DRISetVBlankInterrupt (ScrnInfoPtr p
 
     if (pI830->directRenderingEnabled && pI830->drmMinor >= 5) {
 	if (on) {
-	    if (pI830->planeEnabled[1])
+	    if (pI830->pipes[1].planeEnabled)
 		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 4fb8ac2..3b21974 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -640,6 +640,7 @@ I830LoadPalette(ScrnInfoPtr pScrn, int n
    pI830 = I830PTR(pScrn);
 
    for(p=0; p < pI830->availablePipes; p++) {
+      I830PipePtr pI830Pipe = &pI830->pipes[p];
 
       if (p == 0) {
          palreg = PALETTE_A;
@@ -653,10 +654,10 @@ I830LoadPalette(ScrnInfoPtr pScrn, int n
 	 dspsurf = DSPBSURF;
       }
 
-      if (pI830->planeEnabled[p] == 0)
+      if (pI830Pipe->planeEnabled == 0)
 	 continue;  
 
-      pI830->gammaEnabled[p] = 1;
+      pI830Pipe->gammaEnabled = 1;
       
       /* To ensure gamma is enabled we need to turn off and on the plane */
       temp = INREG(dspreg);
@@ -1265,16 +1266,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
          pI830->LinearAlloc = 0;
    }
 
-   pI830->fixedPipe = -1;
-   if ((s = xf86GetOptValString(pI830->Options, OPTION_FIXEDPIPE)) &&
-      I830IsPrimary(pScrn)) {
-
-      if (strstr(s, "A") || strstr(s, "a") || strstr(s, "0"))
-         pI830->fixedPipe = 0;
-      else if (strstr(s, "B") || strstr(s, "b") || strstr(s, "1"))
-         pI830->fixedPipe = 1;
-   }
-
    I830PreInitDDC(pScrn);
 
    pI830->MonType1 = PIPE_NONE;
@@ -1681,16 +1672,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       }
    }
 
-   if (IS_I9XX(pI830))
-      pI830->newPipeSwitch = TRUE;
-   else
-   if (pI830->availablePipes == 2 && pI830->bios_version >= 3062) {
-      /* BIOS build 3062 changed the pipe switching functionality */
-      pI830->newPipeSwitch = TRUE;
-      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using new Pipe switch code\n");
-   } else
-      pI830->newPipeSwitch = FALSE;
-
    PrintDisplayDeviceInfo(pScrn);
 
    if (xf86IsEntityShared(pScrn->entityList[0])) {
@@ -3400,7 +3381,8 @@ static Bool
 I830EnterVT(int scrnIndex, int flags)
 {
    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
-   I830Ptr pI830 = I830PTR(pScrn);
+   I830Ptr  pI830 = I830PTR(pScrn);
+   int	    i;
 
    DPRINTF(PFX, "Enter VT\n");
 
@@ -3431,7 +3413,8 @@ I830EnterVT(int scrnIndex, int flags)
    SetHWOperatingState(pScrn);
 
    /* Mark that we'll need to re-set the mode for sure */
-   memset(pI830->pipeCurMode, 0, sizeof(pI830->pipeCurMode));
+   for (i = 0; i < MAX_DISPLAY_PIPES; i++)
+      memset(&pI830->pipes[i].curMode, 0, sizeof(pI830->pipes[i].curMode));
 
    if (!i830SetMode(pScrn, pScrn->currentMode))
       return FALSE;
@@ -3584,7 +3567,7 @@ I830SaveScreen(ScreenPtr pScreen, int mo
 	    base = DSPBADDR;
 	    surf = DSPBSURF;
         }
-        if (pI830->planeEnabled[i]) {
+        if (pI830->pipes[i].planeEnabled) {
 	   temp = INREG(ctrl);
 	   if (on)
 	      temp |= DISPLAY_PLANE_ENABLE;
@@ -3633,7 +3616,7 @@ I830DisplayPowerManagementSet(ScrnInfoPt
          ctrl = DSPBCNTR;
          base = DSPBADDR;
       }
-      if (pI830->planeEnabled[i]) {
+      if (pI830->pipes[i].planeEnabled) {
 	   temp = INREG(ctrl);
 	   if (PowerManagementMode == DPMSModeOn)
 	      temp |= DISPLAY_PLANE_ENABLE;
diff --git a/src/i830_modes.c b/src/i830_modes.c
index 0bb17a5..b6867c3 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -385,27 +385,6 @@ i830GetModeListTail(DisplayModePtr pMode
 }
 
 /**
- * Appends a list of modes to another mode list, without duplication.
- */
-static void
-i830AppendModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList,
-		DisplayModePtr addModes)
-{
-    DisplayModePtr first = *modeList;
-    DisplayModePtr last = i830GetModeListTail(first);
-
-    if (addModes == NULL)
-      return;
-
-    if (first == NULL) {
-	*modeList = addModes;
-    } else {
-	last->next = addModes;
-	addModes->prev = last;
-    }
-}
-
-/**
  * This function removes a mode from a list of modes.  It should probably be
  * moved to xf86Mode.c.
  *
diff --git a/src/i830_randr.c b/src/i830_randr.c
index 59ebcc0..67641d6 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -489,12 +489,13 @@ I830RandRCrtcNotify (RRCrtcPtr	crtc)
     struct _I830OutputRec   *output;
     RROutputPtr		rrout;
     int			pipe = (int) crtc->devPrivate;
+    I830PipePtr		pI830Pipe = &pI830->pipes[pipe];
     int			i, j;
-    DisplayModePtr	pipeMode = &pI830->pipeCurMode[pipe];
+    DisplayModePtr	pipeMode = &pI830Pipe->curMode;
     int			pipe_type;
 
-    x = pI830->pipeX[pipe];
-    y = pI830->pipeY[pipe];
+    x = pI830Pipe->x;
+    y = pI830Pipe->y;
     rotation = RR_Rotate_0;
     numOutputs = 0;
     for (i = 0; i < pI830->num_outputs; i++)
@@ -550,6 +551,7 @@ I830RandRCrtcSet (ScreenPtr	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;
 
     /* Sync the engine before adjust mode */
@@ -560,7 +562,7 @@ I830RandRCrtcSet (ScreenPtr	pScreen,
 
     if (display_mode != randrp->modes[pipe])
     {
-	pI830->planeEnabled[pipe] = mode != NULL;
+	pI830Pipe->planeEnabled = mode != NULL;
 	if (display_mode)
 	{
 	    if (!i830PipeSetMode (pScrn, display_mode, pipe))
@@ -833,18 +835,15 @@ I830RandRCreateScreenResources12 (Screen
     {
 	int mmWidth, mmHeight;
 
-	if (mode->HDisplay == pScreen->width &&
-	    mode->VDisplay == pScreen->height)
-	{
-	    mmWidth = pScrn->widthmm;
-	    mmHeight = pScrn->heightmm;
-	}
-	else
-	{
-#define MMPERINCH 25.4
-	    mmWidth = (double) mode->HDisplay / pScrn->xDpi * MMPERINCH;
-	    mmHeight = (double) mode->VDisplay / pScrn->yDpi * MMPERINCH;
-	}
+	mmWidth = pScreen->mmWidth;
+	mmHeight = pScreen->mmHeight;
+	if (mode->HDisplay != pScreen->width)
+	    mmWidth = mmWidth * mode->HDisplay / pScreen->width;
+	if (mode->VDisplay == pScreen->height)
+	    mmHeight = mmHeight * mode->VDisplay / pScreen->height;
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		   "Setting screen physical size to %d x %d\n",
+		   mmWidth, mmHeight);
 	I830RandRScreenSetSize (pScreen,
 				mode->HDisplay,
 				mode->VDisplay,
diff-tree 0510671a6c5233468ac20f0ec8096e084df03ce6 (from ffbd6ca09bc2300bf967d7c248a559d85b8706e0)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Nov 3 10:58:23 2006 -0800

    Fix a pasteo in I965 register restore.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 3612af7..d996bcd 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2404,8 +2404,8 @@ RestoreHWState(ScrnInfoPtr pScrn)
    }
 
    if (IS_I965G(pI830)) {
-      OUTREG(DSPASURF, pI830->saveDSPABASE);
-      OUTREG(DSPBSURF, pI830->saveDSPBBASE);
+      OUTREG(DSPASURF, pI830->saveDSPASURF);
+      OUTREG(DSPBSURF, pI830->saveDSPBSURF);
    }
 
    OUTREG(VCLK_DIVISOR_VGA0, pI830->saveVCLK_DIVISOR_VGA0);
diff-tree 2c9ab6e0594769274f2dbcdf7c00fe297fc385d5 (from 56f6d4f1bb67f447500af3f4f7fa557c3e887baa)
Author: Keith Packard <keithp at mandolin.keithp.com>
Date:   Thu Nov 2 13:44:55 2006 -0800

    set the v_sync_off_high to zero. XXX should check docs

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index eda2857..da61159 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -553,7 +553,7 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn
     output_dtd.part2.sync_off_width_high = 0;
     output_dtd.part2.dtd_flags = 0x18;
     output_dtd.part2.sdvo_flags = 0;
-    output_dtd.part2.v_sync_off_width = 0;
+    output_dtd.part2.v_sync_off_high = 0;
     output_dtd.part2.reserved = 0;
     if (mode->Flags & V_PHSYNC)
 	output_dtd.part2.dtd_flags |= 0x2;
diff-tree 56f6d4f1bb67f447500af3f4f7fa557c3e887baa (from f22d9bcc25aea19ba38d35282367b591fd1b7ca0)
Author: Keith Packard <keithp at mandolin.keithp.com>
Date:   Thu Nov 2 13:42:17 2006 -0800

    Disable the panel fitter when not using it. Cleans up SDVO DVI output.
    
    The panel fitter appears to exist on the 965 hardware (at least) and
    causes troubles with DVI output over SDVO when enabled. This patch
    checks to see if the panel fitter is pointing at the pipe being configured
    and disables it unconditionally in that case. The LVDS driver will configure
    it correctly if necessary afterwards.

diff --git a/src/i830_display.c b/src/i830_display.c
index b3019f8..4716e86 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -607,6 +607,16 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	    pI830->output[i].post_set_mode(pScrn, &pI830->output[i], pMode);
     }
 
+    /*
+     * If the panel fitter is stuck on our pipe, turn it off
+     * the LVDS output will whack it correctly if it needs it
+     */
+    if (((INREG(PFIT_CONTROL) >> 29) & 0x3) == pipe)
+	OUTREG(PFIT_CONTROL, 0);
+	   
+    OUTREG(PFIT_PGM_RATIOS, 0x10001000);
+    OUTREG(DSPARB, (47 << 0) | (95 << 7));
+    
     OUTREG(htot_reg, htot);
     OUTREG(hblank_reg, hblank);
     OUTREG(hsync_reg, hsync);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 779037b..4fb8ac2 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2308,6 +2308,8 @@ SaveHWState(ScrnInfoPtr pScrn)
    pI830->saveSWF[15] = INREG(SWF31);
    pI830->saveSWF[16] = INREG(SWF32);
 
+   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]);
@@ -2426,6 +2428,8 @@ RestoreHWState(ScrnInfoPtr pScrn)
    OUTREG(SWF31, pI830->saveSWF[15]);
    OUTREG(SWF32, pI830->saveSWF[16]);
 
+   OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL);
+
    i830CompareRegsToSnapshot(pScrn);
 
    return TRUE;
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index 7b9fe63..ea45420 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -86,7 +86,6 @@ i830_lvds_save(ScrnInfoPtr pScrn, I830Ou
 {
     I830Ptr pI830 = I830PTR(pScrn);
 
-    pI830->savePFIT_CONTROL = INREG(PFIT_CONTROL);
     pI830->savePP_ON = INREG(LVDSPP_ON);
     pI830->savePP_OFF = INREG(LVDSPP_OFF);
     pI830->saveLVDS = INREG(LVDS);
@@ -115,7 +114,6 @@ i830_lvds_restore(ScrnInfoPtr pScrn, I83
     OUTREG(LVDSPP_ON, pI830->savePP_ON);
     OUTREG(LVDSPP_OFF, pI830->savePP_OFF);
     OUTREG(PP_CYCLE, pI830->savePP_CYCLE);
-    OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL);
     OUTREG(LVDS, pI830->saveLVDS);
     OUTREG(PP_CONTROL, pI830->savePP_CONTROL);
     if (pI830->savePP_CONTROL & POWER_TARGET_ON)
diff-tree f22d9bcc25aea19ba38d35282367b591fd1b7ca0 (from a9eac38bcdb49df2ce1122b49bd8b1eb19e8cae5)
Author: Keith Packard <keithp at mandolin.keithp.com>
Date:   Thu Nov 2 13:34:45 2006 -0800

    Add another couple of new registers

diff --git a/src/i810_reg.h b/src/i810_reg.h
index d6f7147..e126904 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -1652,6 +1652,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define DSPBADDR		DSPBBASE
 #define DSPBSTRIDE		0x71188
 
+#define DSPAKEYVAL		0x70194
+#define DSPAKEYMASK		0x70198
+
 #define DSPAPOS			0x7018C /* reserved */
 #define DSPASIZE		0x70190
 #define DSPBPOS			0x7118C
diff-tree a9eac38bcdb49df2ce1122b49bd8b1eb19e8cae5 (from 7887c76062b7c79e14fb8e4f13486aa592dcbce8)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Nov 2 13:24:54 2006 -0800

    Remove duplicated register defs that were just added.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index 11c0659..d6f7147 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -853,20 +853,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 # define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT	0
 /** @} */
 
-/* SDVO/UDI Multiplier/Divisor register */
-#define DPLLAMD			0x601c
-#define DPLLBMD			0x6020
-
-/* Hi res source UDI divider (-1), non-zeor for UDI fixed freq mode */
-# define DPLLMD_UDI_DIVIDER_HIRES_MASK		(0x3f << 24)
-# define DPLLMD_UDI_DIVIDER_HIRES_SHIFT		24
-# define DPLLMD_UDI_DIVIDER_VGA_MASK		(0x3f << 16)
-# define DPLLMD_UDI_DIVIDER_VGA_SHIFT		16
-# define DPLLMD_SDVOUDI_MULTIPLIER_HIRES_MASK	(0x3f << 8)
-# define DPLLMD_SDVOUDI_MULTIPLIER_HIRES_SHIFT	8
-# define DPLLMD_SDVOUDI_MULTIPLIER_VGA_MASK	(0x3f << 0)
-# define DPLLMD_SDVOUDI_MULTIPLIER_VGA_SHIFT	0
-
 #define DPLL_TEST		0x606c
 
 #define D_STATE			0x6104
diff --git a/src/i830_debug.c b/src/i830_debug.c
index 802330e..7922af0 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -59,7 +59,6 @@ static struct i830SnapshotRec {
     DEFINEREG(DSPFW1),
     DEFINEREG(DSPFW2),
     DEFINEREG(DSPFW3),
-    
 
     DEFINEREG(ADPA),
     DEFINEREG(LVDS),
@@ -90,7 +89,7 @@ static struct i830SnapshotRec {
     DEFINEREG(FPA0),
     DEFINEREG(FPA1),
     DEFINEREG(DPLL_A),
-    DEFINEREG(DPLLAMD),
+    DEFINEREG(DPLL_A_MD),
     DEFINEREG(HTOTAL_A),
     DEFINEREG(HBLANK_A),
     DEFINEREG(HSYNC_A),
@@ -113,7 +112,7 @@ static struct i830SnapshotRec {
     DEFINEREG(FPB0),
     DEFINEREG(FPB1),
     DEFINEREG(DPLL_B),
-    DEFINEREG(DPLLBMD),
+    DEFINEREG(DPLL_B_MD),
     DEFINEREG(HTOTAL_B),
     DEFINEREG(HBLANK_B),
     DEFINEREG(HSYNC_B),
diff-tree 7887c76062b7c79e14fb8e4f13486aa592dcbce8 (from 87b15cfbf762468d4b8728b3e7a39c76654017de)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Nov 2 12:27:21 2006 -0800

    Add airlied's I2C code, ifdeffed out.
    
    I've gone back to compare our behavior to it several times, so I'll just keep
    the code in tree for now.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index 31f8885..11c0659 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -276,11 +276,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define GPIOG			0x5028
 #define GPIOH			0x502c
 # define GPIO_CLOCK_DIR_MASK		(1 << 0)
+# define GPIO_CLOCK_DIR_IN		(0 << 1)
 # define GPIO_CLOCK_DIR_OUT		(1 << 1)
 # define GPIO_CLOCK_VAL_MASK		(1 << 2)
 # define GPIO_CLOCK_VAL_OUT		(1 << 3)
 # define GPIO_CLOCK_VAL_IN		(1 << 4)
 # define GPIO_DATA_DIR_MASK		(1 << 8)
+# define GPIO_DATA_DIR_IN		(0 << 9)
 # define GPIO_DATA_DIR_OUT		(1 << 9)
 # define GPIO_DATA_VAL_MASK		(1 << 10)
 # define GPIO_DATA_VAL_OUT		(1 << 11)
diff --git a/src/i830_i2c.c b/src/i830_i2c.c
index cee7bb5..8b93c8e 100644
--- a/src/i830_i2c.c
+++ b/src/i830_i2c.c
@@ -48,6 +48,219 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "shadow.h"
 #include "i830.h"
 
+#define AIRLIED_I2C	0
+
+#if AIRLIED_I2C
+
+#define I2C_TIMEOUT(x)	/*(x)*/  /* Report timeouts */
+#define I2C_TRACE(x)    /*(x)*/  /* Report progress */
+
+static void i830_setscl(I2CBusPtr b, int state)
+{
+    ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD32 val;
+
+    OUTREG(b->DriverPrivate.uval,
+	   (state ? GPIO_CLOCK_VAL_OUT : 0) | GPIO_CLOCK_DIR_OUT |
+	   GPIO_CLOCK_DIR_MASK | GPIO_CLOCK_VAL_MASK);
+    val = INREG(b->DriverPrivate.uval);
+}
+
+static void i830_setsda(I2CBusPtr b, int state)
+{
+    ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD32 val;
+
+    OUTREG(b->DriverPrivate.uval,
+	   (state ? GPIO_DATA_VAL_OUT : 0) | GPIO_DATA_DIR_OUT |
+	   GPIO_DATA_DIR_MASK | GPIO_DATA_VAL_MASK);
+    val = INREG(b->DriverPrivate.uval);
+}
+
+static void i830_getscl(I2CBusPtr b, int *state)
+{
+    ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD32 val;
+
+    OUTREG(b->DriverPrivate.uval, GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK);
+    OUTREG(b->DriverPrivate.uval, 0);
+    val = INREG(b->DriverPrivate.uval);
+    *state = ((val & GPIO_DATA_VAL_IN) != 0);
+}
+
+static int i830_getsda(I2CBusPtr b)
+ {
+     ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
+     I830Ptr pI830 = I830PTR(pScrn);
+     CARD32 val;
+
+     OUTREG(b->DriverPrivate.uval, GPIO_DATA_DIR_IN | GPIO_DATA_DIR_MASK);
+     OUTREG(b->DriverPrivate.uval, 0);
+     val = INREG(b->DriverPrivate.uval);
+     return ((val & GPIO_DATA_VAL_IN) != 0);
+}
+
+static inline void sdalo(I2CBusPtr b)
+{
+    i830_setsda(b, 0);
+    b->I2CUDelay(b, b->RiseFallTime);
+}
+
+static inline void sdahi(I2CBusPtr b)
+{
+    i830_setsda(b, 1);
+    b->I2CUDelay(b, b->RiseFallTime);
+}
+
+static inline void scllo(I2CBusPtr b)
+{
+    i830_setscl(b, 0);
+    b->I2CUDelay(b, b->RiseFallTime);
+}
+
+static inline int sclhi(I2CBusPtr b, int timeout)
+{
+    int scl = 0;
+    int i;
+
+    i830_setscl(b, 1);
+    b->I2CUDelay(b, b->RiseFallTime);
+
+    for (i = timeout; i > 0; i -= b->RiseFallTime) {
+	i830_getscl(b, &scl);
+	if (scl) break;
+	b->I2CUDelay(b, b->RiseFallTime);
+    }
+
+    if (i <= 0) {
+	I2C_TIMEOUT(ErrorF("[I2CRaiseSCL(<%s>, %d) timeout]",
+			   b->BusName, timeout));
+	return FALSE;
+    }
+    return TRUE;
+}
+
+static Bool
+I830I2CGetByte(I2CDevPtr d, I2CByte *data, Bool last)
+{
+    I2CBusPtr b = d->pI2CBus;
+    int i, sda;
+    unsigned char indata = 0;
+
+    sdahi(b);
+
+    for (i = 0; i < 8; i++) {
+	if (sclhi(b, d->BitTimeout) == FALSE) {
+	    I2C_TRACE(ErrorF("timeout at bit #%d\n", 7-i));
+	    return FALSE;
+	};
+	indata *= 2;
+	if (i830_getsda(b))
+	    indata |= 0x01;
+	scllo(b);
+    }
+
+    if (last) {
+	sdahi(b);
+    } else {
+	sdalo(b);
+    }
+
+    if (sclhi(b, d->BitTimeout) == FALSE) {
+	sdahi(b);
+	return FALSE;
+    };
+
+    scllo(b);
+    sdahi(b);
+
+    *data = indata & 0xff;
+    I2C_TRACE(ErrorF("R%02x ", (int) *data));
+
+    return TRUE;
+}
+
+static Bool
+I830I2CPutByte(I2CDevPtr d, I2CByte c)
+{
+    Bool r;
+    int i, scl, sda;
+    int sb, ack;
+    I2CBusPtr b = d->pI2CBus;
+
+    for (i = 7; i >= 0; i--) {
+	sb = c & (1 << i);
+	i830_setsda(b, sb);
+	b->I2CUDelay(b, b->RiseFallTime);
+
+	if (sclhi(b, d->ByteTimeout) == FALSE) {
+	    sdahi(b);
+	    return FALSE;
+	}
+
+	i830_setscl(b, 0);
+	b->I2CUDelay(b, b->RiseFallTime);
+    }
+    sdahi(b);
+    if (sclhi(b, d->ByteTimeout) == FALSE) {
+	I2C_TIMEOUT(ErrorF("[I2CPutByte(<%s>, 0x%02x, %d, %d, %d) timeout]",
+			   b->BusName, c, d->BitTimeout,
+			   d->ByteTimeout, d->AcknTimeout));
+	return FALSE;
+    }
+    ack = i830_getsda(b);
+    I2C_TRACE(ErrorF("Put byte 0x%02x , getsda() = %d\n", c & 0xff, ack));
+
+    scllo(b);
+    return (0 == ack);
+}
+
+static Bool
+I830I2CStart(I2CBusPtr b, int timeout)
+{
+    if (sclhi(b, timeout) == FALSE)
+	return FALSE;
+
+    sdalo(b);
+    scllo(b);
+
+    return TRUE;
+}
+
+static void
+I830I2CStop(I2CDevPtr d)
+{
+    I2CBusPtr b = d->pI2CBus;
+
+    sdalo(b);
+    sclhi(b, d->ByteTimeout);
+    sdahi(b);
+}
+
+static Bool
+I830I2CAddress(I2CDevPtr d, I2CSlaveAddr addr)
+{
+    if (I830I2CStart(d->pI2CBus, d->StartTimeout)) {
+	if (I830I2CPutByte(d, addr & 0xFF)) {
+	    if ((addr & 0xF8) != 0xF0 &&
+		(addr & 0xFE) != 0x00)
+		return TRUE;
+
+	    if (I830I2CPutByte(d, (addr >> 8) & 0xFF))
+		return TRUE;
+	}
+
+	I830I2CStop(d);
+    }
+
+    return FALSE;
+}
+
+#else
+
 static void
 i830I2CGetBits(I2CBusPtr b, int *clock, int *data)
 {
@@ -76,6 +289,7 @@ i830I2CPutBits(I2CBusPtr b, int clock, i
 	GPIO_DATA_DIR_MASK |
 	GPIO_DATA_VAL_MASK);
 }
+#endif
 
 /* the i830 has a number of I2C Buses */
 Bool
@@ -90,8 +304,16 @@ I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr
 
     pI2CBus->BusName = name;
     pI2CBus->scrnIndex = pScrn->scrnIndex;
+#if AIRLIED_I2C
+    pI2CBus->I2CGetByte = I830I2CGetByte;
+    pI2CBus->I2CPutByte = I830I2CPutByte;
+    pI2CBus->I2CStart = I830I2CStart;
+    pI2CBus->I2CStop = I830I2CStop;
+    pI2CBus->I2CAddress = I830I2CAddress;
+#else
     pI2CBus->I2CGetBits = i830I2CGetBits;
     pI2CBus->I2CPutBits = i830I2CPutBits;
+#endif
     pI2CBus->DriverPrivate.uval = i2c_reg;
 
     if (!xf86I2CBusInit(pI2CBus))
diff-tree 87b15cfbf762468d4b8728b3e7a39c76654017de (from 2636d68663a02f6d9eaf36971706b67036ebf56c)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Nov 2 11:30:21 2006 -0800

    Remove dead specifiedMonitor field.

diff --git a/src/i830.h b/src/i830.h
index a07ba8e..bb17f3f 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -397,7 +397,6 @@ typedef struct _I830Rec {
 
    int MonType1;
    int MonType2;
-   Bool specifiedMonitor;
 
    DGAModePtr DGAModes;
    int numDGAModes;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 3612af7..779037b 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1279,7 +1279,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 
    pI830->MonType1 = PIPE_NONE;
    pI830->MonType2 = PIPE_NONE;
-   pI830->specifiedMonitor = FALSE;
 
    if ((s = xf86GetOptValString(pI830->Options, OPTION_MONITOR_LAYOUT)) &&
       I830IsPrimary(pScrn)) {
@@ -1366,7 +1365,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 	 pI830->pipe = 1;
 
       pI830->operatingDevices = (pI830->MonType2 << 8) | pI830->MonType1;
-      pI830->specifiedMonitor = TRUE;
    } else if (I830IsPrimary(pScrn)) {
       /* Choose a default set of outputs to use based on what we've detected.
        *
diff-tree 2636d68663a02f6d9eaf36971706b67036ebf56c (from 786ec54c4c1540f4aced63ef21d567c3b9f3282e)
Author: Keith Packard <keithp at mandolin.keithp.com>
Date:   Thu Nov 2 11:57:11 2006 -0800

    Dump more registers for debug purposes

diff --git a/src/i830_debug.c b/src/i830_debug.c
index a48e9f2..802330e 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -41,6 +41,26 @@ static struct i830SnapshotRec {
     char *name;
     CARD32 regval;
 } i830_snapshot[] = {
+    DEFINEREG(VCLK_DIVISOR_VGA0),
+    DEFINEREG(VCLK_DIVISOR_VGA1),
+    DEFINEREG(VCLK_POST_DIV),
+    DEFINEREG(DPLL_TEST),
+    DEFINEREG(D_STATE),
+    DEFINEREG(DSPCLK_GATE_D),
+    DEFINEREG(RENCLK_GATE_D1),
+    DEFINEREG(RENCLK_GATE_D2),
+/*  DEFINEREG(RAMCLK_GATE_D),	CRL only */
+    DEFINEREG(SDVOB),
+    DEFINEREG(SDVOC),
+/*    DEFINEREG(UDIB_SVB_SHB_CODES), CRL only */
+/*    DEFINEREG(UDIB_SHA_BLANK_CODES), CRL only */
+    DEFINEREG(SDVOUDI),
+    DEFINEREG(DSPARB),
+    DEFINEREG(DSPFW1),
+    DEFINEREG(DSPFW2),
+    DEFINEREG(DSPFW3),
+    
+
     DEFINEREG(ADPA),
     DEFINEREG(LVDS),
     DEFINEREG(DVOA),
@@ -62,36 +82,46 @@ static struct i830SnapshotRec {
     DEFINEREG(DSPAPOS),
     DEFINEREG(DSPASIZE),
     DEFINEREG(DSPABASE),
+    DEFINEREG(DSPASURF),
+    DEFINEREG(DSPATILEOFF),
     DEFINEREG(PIPEACONF),
     DEFINEREG(PIPEASRC),
 
     DEFINEREG(FPA0),
     DEFINEREG(FPA1),
     DEFINEREG(DPLL_A),
+    DEFINEREG(DPLLAMD),
     DEFINEREG(HTOTAL_A),
     DEFINEREG(HBLANK_A),
     DEFINEREG(HSYNC_A),
     DEFINEREG(VTOTAL_A),
     DEFINEREG(VBLANK_A),
     DEFINEREG(VSYNC_A),
+    DEFINEREG(BCLRPAT_A),
+    DEFINEREG(VSYNCSHIFT_A),
 
     DEFINEREG(DSPBCNTR),
     DEFINEREG(DSPBSTRIDE),
     DEFINEREG(DSPBPOS),
     DEFINEREG(DSPBSIZE),
     DEFINEREG(DSPBBASE),
+    DEFINEREG(DSPBSURF),
+    DEFINEREG(DSPBTILEOFF),
     DEFINEREG(PIPEBCONF),
     DEFINEREG(PIPEBSRC),
 
     DEFINEREG(FPB0),
     DEFINEREG(FPB1),
     DEFINEREG(DPLL_B),
+    DEFINEREG(DPLLBMD),
     DEFINEREG(HTOTAL_B),
     DEFINEREG(HBLANK_B),
     DEFINEREG(HSYNC_B),
     DEFINEREG(VTOTAL_B),
     DEFINEREG(VBLANK_B),
     DEFINEREG(VSYNC_B),
+    DEFINEREG(BCLRPAT_B),
+    DEFINEREG(VSYNCSHIFT_B),
 
     DEFINEREG(VCLK_DIVISOR_VGA0),
     DEFINEREG(VCLK_DIVISOR_VGA1),
@@ -129,13 +159,115 @@ void i830CompareRegsToSnapshot(ScrnInfoP
     }
 }
 
+static void i830DumpIndexed (ScrnInfoPtr pScrn, char *name, int id, int val, int min, int max)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    int	i;
+
+    for (i = min; i <= max; i++) {
+	OUTREG8 (id, i);
+	xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "%18.18s%02x: 0x%02x\n",
+		    name, i, INREG8(val));
+    }
+}
+
 void i830DumpRegs (ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     int i;
+    int	fp, dpll;
+    int pipe;
+    int	n, m1, m2, m, p1, p2;
+    int ref;
+    int	dot;
+    int phase;
+    int msr;
+    int crt;
 
+    xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "DumpRegsBegin\n");
     for (i = 0; i < NUM_I830_SNAPSHOTREGS; i++) {
-	xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "%10.10s: 0x%08x\n",
+	xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "%20.20s: 0x%08x\n",
 		    i830_snapshot[i].name, (unsigned int) INREG(i830_snapshot[i].reg));
     }
+    i830DumpIndexed (pScrn, "SR", 0x3c4, 0x3c5, 0, 7);
+    msr = INREG8(0x3cc);
+    xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "%20.20s: 0x%02x\n",
+		    "MSR", (unsigned int) msr);
+
+    if (msr & 1)
+	crt = 0x3d0;
+    else
+	crt = 0x3b0;
+    i830DumpIndexed (pScrn, "CR", crt + 4, crt + 5, 0, 0x24);
+    for (pipe = 0; pipe <= 1; pipe++)
+    {
+	fp = INREG(pipe == 0 ? FPA0 : FPB0);
+	dpll = INREG(pipe == 0 ? DPLL_A : DPLL_B);
+	switch ((dpll >> 24) & 0x3) {
+	case 0:
+	    p2 = 10;
+	    break;
+	case 1:
+	    p2 = 5;
+	    break;
+	default:
+	    p2 = 1;
+	    xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "p2 out of range\n");
+	    break;
+	}
+	switch ((dpll >> 16) & 0xff) {
+	case 1:
+	    p1 = 1; break;
+	case 2:
+	    p1 = 2; break;
+	case 4:
+	    p1 = 3; break;
+	case 8:
+	    p1 = 4; break;
+	case 16:
+	    p1 = 5; break;
+	case 32:
+	    p1 = 6; break;
+	case 64:
+	    p1 = 7; break;
+	case 128:
+	    p1 = 8; break;
+	default:
+	    p1 = 1;
+	    xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "p1 out of range\n");
+	    break;
+	}
+	switch ((dpll >> 13) & 0x3) {
+	case 0:
+	    ref = 96000;
+	    break;
+	default:
+	    ref = 0;
+	    xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "ref out of range\n");
+	    break;
+	}
+	phase = (dpll >> 9) & 0xf;
+	switch (phase) {
+	case 6:
+	    break;
+	default:
+	    xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "phase %d out of range\n", phase);
+	    break;
+	}
+	switch ((dpll >> 8) & 1) {
+	case 0:
+	    break;
+	default:
+	    xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "fp select out of range\n");
+	    break;
+	}
+	n = ((fp >> 16) & 0x3f);
+	m1 = ((fp >> 8) & 0x3f);
+	m2 = ((fp >> 0) & 0x3f);
+	m = 5 * (m1 + 2) + (m2 + 2);
+	dot = (ref * (5 * (m1 + 2) + (m2 + 2)) / (n + 2)) / (p1 * p2);
+	xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "pipe %s dot %d n %d m1 %d m2 %d p1 %d p2 %d\n",
+		    pipe == 0 ? "A" : "B", dot, n, m1, m2, p1, p2);
+    }
+    xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "DumpRegsEnd\n");
 }
diff-tree 786ec54c4c1540f4aced63ef21d567c3b9f3282e (from 85e32ad2dadcce1134fcadb14ece8ff30f3925f2)
Author: Keith Packard <keithp at mandolin.keithp.com>
Date:   Thu Nov 2 11:56:50 2006 -0800

    Add a few more registers from the 965 spec

diff --git a/src/i810_reg.h b/src/i810_reg.h
index 34e6e53..31f8885 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -739,6 +739,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define VSYNC_A 	0x60014
 #define PIPEASRC	0x6001c
 #define BCLRPAT_A	0x60020
+#define VSYNCSHIFT_A	0x60028
 
 #define HTOTAL_B	0x61000
 #define HBLANK_B	0x61004
@@ -748,6 +749,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define VSYNC_B 	0x61014
 #define PIPEBSRC	0x6101c
 #define BCLRPAT_B	0x61020
+#define VSYNCSHIFT_B	0x61028
 
 #define PP_STATUS	0x61200
 # define PP_ON					(1 << 31)
@@ -849,6 +851,28 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 # define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT	0
 /** @} */
 
+/* SDVO/UDI Multiplier/Divisor register */
+#define DPLLAMD			0x601c
+#define DPLLBMD			0x6020
+
+/* Hi res source UDI divider (-1), non-zeor for UDI fixed freq mode */
+# define DPLLMD_UDI_DIVIDER_HIRES_MASK		(0x3f << 24)
+# define DPLLMD_UDI_DIVIDER_HIRES_SHIFT		24
+# define DPLLMD_UDI_DIVIDER_VGA_MASK		(0x3f << 16)
+# define DPLLMD_UDI_DIVIDER_VGA_SHIFT		16
+# define DPLLMD_SDVOUDI_MULTIPLIER_HIRES_MASK	(0x3f << 8)
+# define DPLLMD_SDVOUDI_MULTIPLIER_HIRES_SHIFT	8
+# define DPLLMD_SDVOUDI_MULTIPLIER_VGA_MASK	(0x3f << 0)
+# define DPLLMD_SDVOUDI_MULTIPLIER_VGA_SHIFT	0
+
+#define DPLL_TEST		0x606c
+
+#define D_STATE			0x6104
+#define DSPCLK_GATE_D		0x6200
+#define RENCLK_GATE_D1		0x6204
+#define RENCLK_GATE_D2		0x6208
+#define RAMCLK_GATE_D		0x6210		/* CRL only */
+
 #define BLC_PWM_CTL		0x61254
 #define BACKLIGHT_MODULATION_FREQ_SHIFT		(17)
 #define BACKLIGHT_MODULATION_FREQ_MASK		(0x7fff << 17)
@@ -856,6 +880,21 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define BACKLIGHT_DUTY_CYCLE_SHIFT		(0)
 #define BACKLIGHT_DUTY_CYCLE_MASK		(0xffff)
 
+#define BLM_CTL			0x61260
+#define BLM_THRESHOLD_0		0x61270
+#define BLM_THRESHOLD_1		0x61274
+#define BLM_THRESHOLD_2		0x61278
+#define BLM_THRESHOLD_3		0x6127c
+#define BLM_THRESHOLD_4		0x61280
+#define BLM_THRESHOLD_5		0x61284
+
+#define BLM_ACCUMULATOR_0	0x61290
+#define BLM_ACCUMULATOR_1	0x61294
+#define BLM_ACCUMULATOR_2	0x61298
+#define BLM_ACCUMULATOR_3	0x6129c
+#define BLM_ACCUMULATOR_4	0x612a0
+#define BLM_ACCUMULATOR_5	0x612a4
+
 #define FPA0		0x06040
 #define FPA1		0x06044
 #define FPB0		0x06048
@@ -907,6 +946,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define SDVOB_PRESERVE_MASK			((1 << 17) | (1 << 16) | (1 << 14))
 #define SDVOC_PRESERVE_MASK			(1 << 17)
 
+#define UDIB_SVB_SHB_CODES    		0x61144
+#define UDIB_SHA_BLANK_CODES		0x61148
+#define UDIB_START_END_FILL_CODES	0x6114c
+
+
+#define SDVOUDI				0x61150
+
 #define I830_HTOTAL_MASK 	0xfff0000
 #define I830_HACTIVE_MASK	0x7ff
 
@@ -1554,6 +1600,19 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define PIPEACONF_GAMMA 	(1<<24)
 #define PIPECONF_FORCE_BORDER	(1<<25)
 
+#define PIPEAGCMAXRED		0x70010
+#define PIPEAGCMAXGREEN		0x70014
+#define PIPEAGCMAXBLUE		0x70018
+#define PIPEASTAT		0x70024
+
+#define DSPARB			0x70030
+#define DSPFW1			0x70034
+#define DSPFW2			0x70038
+#define DSPFW3			0x7003c
+#define PIPEAFRAMEHIGH		0x70040
+#define PIPEAFRAMEPIXEL		0x70044
+
+
 #define PIPEBCONF 0x71008
 #define PIPEBCONF_ENABLE	(1<<31)
 #define PIPEBCONF_DISABLE	0
@@ -1562,6 +1621,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define PIPEBCONF_GAMMA 	(1<<24)
 #define PIPEBCONF_PALETTE	0
 
+#define PIPEBGCMAXRED		0x71010
+#define PIPEBGCMAXGREEN		0x71014
+#define PIPEBGCMAXBLUE		0x71018
+#define PIPEBSTAT		0x71024
+#define PIPEBFRAMEHIGH		0x71040
+#define PIPEBFRAMEPIXEL		0x71044
+
 #define DSPACNTR		0x70180
 #define DSPBCNTR		0x71180
 #define DISPLAY_PLANE_ENABLE 			(1<<31)
diff-tree 85e32ad2dadcce1134fcadb14ece8ff30f3925f2 (from ffbd6ca09bc2300bf967d7c248a559d85b8706e0)
Author: Keith Packard <keithp at mandolin.keithp.com>
Date:   Thu Nov 2 11:56:12 2006 -0800

    ch7xxxSaveRegs receives real type instead of void *

diff --git a/src/ch7xxx/ch7xxx.c b/src/ch7xxx/ch7xxx.c
index fdc96d0..d11c355 100644
--- a/src/ch7xxx/ch7xxx.c
+++ b/src/ch7xxx/ch7xxx.c
@@ -38,7 +38,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "ch7xxx.h"
 #include "ch7xxx_reg.h"
 
-static void ch7xxxSaveRegs(void *d);
+static void ch7xxxSaveRegs(I2CDevPtr d);
 
 static CARD8 ch7xxxFreqRegs[][7] =
   { { 0, 0x23, 0x08, 0x16, 0x30, 0x60, 0x00 },
@@ -243,9 +243,9 @@ static void ch7xxxPrintRegs(I2CDevPtr d)
   }
 }
 
-static void ch7xxxSaveRegs(void *d)
+static void ch7xxxSaveRegs(I2CDevPtr d)
 {
-  CH7xxxPtr ch7xxx = CH7PTR(((I2CDevPtr)d));
+  CH7xxxPtr ch7xxx = CH7PTR(d);
   int ret;
   int i;
 
diff-tree ffbd6ca09bc2300bf967d7c248a559d85b8706e0 (from 97c3a1b2421031e41f0b2b1630fde1dc4262d264)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Nov 1 13:05:44 2006 -0800

    Remove dead VESARec struct.

diff --git a/src/i830.h b/src/i830.h
index eca9396..a07ba8e 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -106,18 +106,6 @@ typedef struct _I830OutputRec I830Output
 #define PIPE_DFP2	1<<6
 #define PIPE_LFP2	1<<7
 
-typedef struct _VESARec {
-   /* SVGA state */
-   pointer state, pstate;
-   int statePage, stateSize, stateMode, stateRefresh;
-   CARD32 *savedPal;
-   int savedScanlinePitch;
-   xf86MonPtr monitor;
-   /* display start */
-   int x, y;
-} VESARec, *VESAPtr;
-
-
 typedef struct _I830Rec *I830Ptr;
 
 typedef void (*I830WriteIndexedByteFunc)(I830Ptr pI830, IOADDRESS addr,
@@ -480,7 +468,6 @@ typedef struct _I830Rec {
 
    /* Video BIOS support. */
    vbeInfoPtr pVbe;
-   VESAPtr vesa;
 
    Bool swfSaved;
    CARD32 saveSWF0;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 7c15174..3612af7 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -352,7 +352,6 @@ I830GetRec(ScrnInfoPtr pScrn)
    if (pScrn->driverPrivate)
       return TRUE;
    pI830 = pScrn->driverPrivate = xnfcalloc(sizeof(I830Rec), 1);
-   pI830->vesa = xnfcalloc(sizeof(VESARec), 1);
    return TRUE;
 }
 
@@ -360,7 +359,6 @@ static void
 I830FreeRec(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830;
-   VESAPtr pVesa;
 
    if (!pScrn)
       return;
@@ -374,11 +372,6 @@ I830FreeRec(ScrnInfoPtr pScrn)
          vbeFree(pI830->pVbe);
    }
 
-   pVesa = pI830->vesa;
-   if (pVesa->savedPal)
-      xfree(pVesa->savedPal);
-   xfree(pVesa);
-
    xfree(pScrn->driverPrivate);
    pScrn->driverPrivate = NULL;
 }
diff-tree 97c3a1b2421031e41f0b2b1630fde1dc4262d264 (from 7971c401554c218c84a8c45335c9b31bbccfece7)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Nov 1 13:04:08 2006 -0800

    Remove the refresh rate appended to some mode names.
    
    This gets the SDVO and CRT outputs I have to have at least 1 common mode
    according to RandR.

diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c
index 8e8a94c..166f41a 100644
--- a/src/i830_xf86Modes.c
+++ b/src/i830_xf86Modes.c
@@ -100,8 +100,7 @@ i830xf86SetModeDefaultName(DisplayModePt
     if (mode->name != NULL)
 	xfree(mode->name);
 
-    mode->name = XNFprintf("%dx%dx%.0f", mode->HDisplay, mode->VDisplay,
-			   i830xf86ModeVRefresh(mode));
+    mode->name = XNFprintf("%dx%d", mode->HDisplay, mode->VDisplay);
 }
 
 /*
diff-tree 7971c401554c218c84a8c45335c9b31bbccfece7 (from fb94c1210966f7875e5f034f10ea31c06c502c3a)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Nov 1 12:42:56 2006 -0800

    Attempt to pull monitor physical size information out of DDC EDID data.

diff --git a/src/i830.h b/src/i830.h
index a4dc4ba..eca9396 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -272,6 +272,8 @@ struct _I830OutputRec {
    /**
     * 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);
@@ -283,7 +285,13 @@ struct _I830OutputRec {
     * 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;
diff --git a/src/i830_crt.c b/src/i830_crt.c
index 407ebe3..0225727 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -32,6 +32,7 @@
 #include "xf86.h"
 #include "i830.h"
 #include "i830_xf86Modes.h"
+
 static void
 i830_crt_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
 {
diff --git a/src/i830_modes.c b/src/i830_modes.c
index d6866ad..0bb17a5 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -641,6 +641,7 @@ i830_ddc_get_modes(ScrnInfoPtr pScrn, I8
 {
     xf86MonPtr ddc_mon;
     DisplayModePtr ddc_modes, mode;
+    int i;
 
     ddc_mon = xf86DoEDID_DDC2(pScrn->scrnIndex, output->pDDCBus);
     if (ddc_mon == NULL)
@@ -666,7 +667,17 @@ i830_ddc_get_modes(ScrnInfoPtr pScrn, I8
     }
     i830xf86PruneInvalidModes(pScrn, &ddc_modes, TRUE);
 
-    xfree(ddc_mon);
+    /* Pull out a phyiscal size from a detailed timing if available. */
+    for (i = 0; i < 4; i++) {
+	if (ddc_mon->det_mon[i].type == DT &&
+	    ddc_mon->det_mon[i].section.d_timings.h_size != 0 &&
+	    ddc_mon->det_mon[i].section.d_timings.v_size != 0)
+	{
+	    output->mm_width = ddc_mon->det_mon[i].section.d_timings.h_size;
+	    output->mm_height = ddc_mon->det_mon[i].section.d_timings.v_size;
+	    break;
+	}
+    }
 
     return ddc_modes;
 }
diff --git a/src/i830_randr.c b/src/i830_randr.c
index 69063a8..59ebcc0 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -698,12 +698,8 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
 	    return FALSE;
 
 	RROutputSetCrtc (randrp->outputs[i], crtc);
-
-	/* We should pull info out of EDID to get the output physical
-	 * size when available.
-	 */
-	RROutputSetPhysicalSize(randrp->outputs[i], 0, 0);
-
+	RROutputSetPhysicalSize(randrp->outputs[i], pI830->output[i].mm_width,
+				pI830->output[i].mm_height);
 	RROutputSetPossibleOptions (randrp->outputs[i], possibleOptions);
 	RROutputSetCurrentOptions (randrp->outputs[i], currentOptions);
         nmode = 0;
diff-tree fb94c1210966f7875e5f034f10ea31c06c502c3a (from f30d7f912f36b110c3af7dc795e35456593781ab)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Nov 1 12:23:50 2006 -0800

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

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

    Update for the move of RandR phyiscal size information.

diff --git a/src/i830_randr.c b/src/i830_randr.c
index a1c4b12..f8064b9 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -723,17 +723,15 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
 		return FALSE;
 	    nmode = 0;
 
+	    /* We should pull info out of EDID to get the output physical
+	     * size when available.
+	     */
+	    RROutputSetPhysicalSize(randrp->outputs[i], 0, 0);
+
 	    for (p = 1; p >= 0; p--) {
 		for (mode = modes; mode; mode = mode->next) {
 		    if ((p != 0) == ((mode->type & M_T_PREFERRED) != 0)) {
 			modeInfo.nameLength = strlen (mode->name);
-			if (mon != NULL) {
-			    modeInfo.mmWidth = mon->widthmm;
-			    modeInfo.mmHeight = mon->heightmm;
-			} else {
-			    modeInfo.mmWidth = 0;
-			    modeInfo.mmHeight = 0;
-			}
 
 			modeInfo.width = mode->HDisplay;
 			modeInfo.dotClock = mode->Clock * 1000;
diff-tree 7195dfabd56239f08cdd8175a2ef3a66ef9600de (from cc3728be2481637dda321d3bc2e4e89a220699cd)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Oct 31 17:10:08 2006 -0800

    Give each output a get_modes function and expose those modes through RandR.
    
    The get_modes should return the probed modes only.  The driver should then
    append to the list (for example, compatible modes listed in other outputs,
    or standard VESA modes) to create the list to expose through RandR.  That
    isn't done yet.

diff --git a/src/i830.h b/src/i830.h
index 27a9817..5915a17 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -269,6 +269,20 @@ struct _I830OutputRec {
     */
    enum detect_status (*detect)(ScrnInfoPtr pScrn, I830OutputPtr output);
 
+   /**
+    * Query the device for the modes it provides.
+    *
+    * \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;
    xf86MonPtr MonInfo;
    I2CBusPtr pI2CBus;
    I2CBusPtr pDDCBus;
@@ -680,6 +694,7 @@ DisplayModePtr i830GetGTF(int h_pixels, 
 
 /* i830_modes.c */
 int I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time);
+DisplayModePtr i830_ddc_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output);
 
 /* i830_randr.c */
 Bool I830RandRCreateScreenResources (ScreenPtr pScreen);
diff --git a/src/i830_crt.c b/src/i830_crt.c
index d271eed..bd0099a 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -286,6 +286,7 @@ i830_crt_init(ScrnInfoPtr pScrn)
     pI830->output[pI830->num_outputs].pre_set_mode = i830_crt_pre_set_mode;
     pI830->output[pI830->num_outputs].post_set_mode = i830_crt_post_set_mode;
     pI830->output[pI830->num_outputs].detect = i830_crt_detect;
+    pI830->output[pI830->num_outputs].get_modes = i830_ddc_get_modes;
 
     /* Set up the DDC bus. */
     I830I2CInit(pScrn, &pI830->output[pI830->num_outputs].pDDCBus,
diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index ed21ecc..c788e4f 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -201,6 +201,7 @@ i830_dvo_init(ScrnInfoPtr pScrn)
     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;
 
     /* Set up the I2C and DDC buses */
     ret = I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "DVOI2C_E");
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index e0e471f..4b89903 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -235,6 +235,11 @@ i830_lvds_init(ScrnInfoPtr pScrn)
     pI830->output[pI830->num_outputs].pre_set_mode = i830_lvds_pre_set_mode;
     pI830->output[pI830->num_outputs].post_set_mode = i830_lvds_post_set_mode;
     pI830->output[pI830->num_outputs].detect = i830_lvds_detect;
+    /* This will usually return NULL on laptop panels, which is no good.
+     * We need to construct a mode from the fixed panel info, and return a copy
+     * of that when DDC is unavailable.
+     */
+    pI830->output[pI830->num_outputs].get_modes = i830_ddc_get_modes;
 
     /* Set up the LVDS DDC channel.  Most panels won't support it, but it can
      * be useful if available.
diff --git a/src/i830_modes.c b/src/i830_modes.c
index 130b7fe..1ba1def 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -933,11 +933,22 @@ int
 I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    int pipe;
+    int pipe, i;
     DisplayModePtr saved_mode, last;
     Bool pipes_reconfigured = FALSE;
     int originalVirtualX, originalVirtualY;
 
+    /* Re-probe the list of modes for each output. */
+    for (i = 0; i < pI830->num_outputs; i++) {
+	while (pI830->output[i].probed_modes != NULL) {
+	    xf86DeleteMode(&pI830->output[i].probed_modes,
+			   pI830->output[i].probed_modes);
+	}
+
+	pI830->output[i].probed_modes =
+	    pI830->output[i].get_modes(pScrn, &pI830->output[i]);
+    }
+
     for (pipe = 0; pipe < pI830->availablePipes; pipe++) {
 	I830ReprobePipeModeList(pScrn, pipe);
     }
@@ -1099,3 +1110,23 @@ I830ValidateXF86ModeList(ScrnInfoPtr pSc
 
     return 1; /* XXX */
 }
+
+/**
+ * Generic get_modes function using DDC, used by many outputs.
+ */
+DisplayModePtr
+i830_ddc_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output)
+{
+    xf86MonPtr ddc_mon;
+    DisplayModePtr ddc_modes;
+
+    ddc_mon = xf86DoEDID_DDC2(pScrn->scrnIndex, output->pDDCBus);
+    if (ddc_mon == NULL)
+	return NULL;
+
+    ddc_modes = i830GetDDCModes(pScrn, ddc_mon);
+
+    xfree(ddc_mon);
+
+    return ddc_modes;
+}
diff --git a/src/i830_randr.c b/src/i830_randr.c
index 23ffaf6..a1c4b12 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -612,7 +612,6 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
     int			p;
     int			clone_types;
     int			crtc_types;
-    int			connection;
     int			pipe_type;
     int			pipe;
     int			subpixel;
@@ -631,6 +630,8 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
 			  randrp->virtualX, randrp->virtualY);
     for (i = 0; i < pI830->num_outputs; i++)
     {
+	MonPtr mon;
+
 	output = &pI830->output[i];
 	/*
 	 * Valid crtcs
@@ -705,50 +706,53 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
         nmode = 0;
 	npreferred = 0;
 	rrmodes = NULL;
-	if (pipe >= 0)
-	{
-	    MonPtr  mon = pI830->pipeMon[pipe];
-	    modes = mon->Modes;
 
-	    for (mode = modes; mode; mode = mode->next)
-		nmode++;
+	modes = pI830->output[i].probed_modes;
 
-	    if (nmode)
-	    {
-		rrmodes = xalloc (nmode * sizeof (RRModePtr));
-		if (!rrmodes)
-		    return FALSE;
-		nmode = 0;
-		for (p = 1; p >= 0; p--)
-		{
-		    for (mode = modes; mode; mode = mode->next)
-		    {
-			if ((p != 0) == ((mode->type & M_T_PREFERRED) != 0))
-			{
-			    modeInfo.nameLength = strlen (mode->name);
+	if (pI830->output[i].pipe >= 0)
+	    mon = pI830->pipeMon[pipe];
+	else
+	    mon = NULL;
+
+	for (mode = modes; mode; mode = mode->next)
+	    nmode++;
+
+	if (nmode) {
+	    rrmodes = xalloc (nmode * sizeof (RRModePtr));
+	    if (!rrmodes)
+		return FALSE;
+	    nmode = 0;
+
+	    for (p = 1; p >= 0; p--) {
+		for (mode = modes; mode; mode = mode->next) {
+		    if ((p != 0) == ((mode->type & M_T_PREFERRED) != 0)) {
+			modeInfo.nameLength = strlen (mode->name);
+			if (mon != NULL) {
 			    modeInfo.mmWidth = mon->widthmm;
 			    modeInfo.mmHeight = mon->heightmm;
+			} else {
+			    modeInfo.mmWidth = 0;
+			    modeInfo.mmHeight = 0;
+			}
 
-			    modeInfo.width = mode->HDisplay;
-			    modeInfo.dotClock = mode->Clock * 1000;
-			    modeInfo.hSyncStart = mode->HSyncStart;
-			    modeInfo.hSyncEnd = mode->HSyncEnd;
-			    modeInfo.hTotal = mode->HTotal;
-			    modeInfo.hSkew = mode->HSkew;
-
-			    modeInfo.height = mode->VDisplay;
-			    modeInfo.vSyncStart = mode->VSyncStart;
-			    modeInfo.vSyncEnd = mode->VSyncEnd;
-			    modeInfo.vTotal = mode->VTotal;
-			    modeInfo.modeFlags = mode->Flags;
-
-			    rrmode = RRModeGet (pScreen, &modeInfo, mode->name);
-			    rrmode->devPrivate = mode;
-			    if (rrmode)
-			    {
-				rrmodes[nmode++] = rrmode;
-				npreferred += p;
-			    }
+			modeInfo.width = mode->HDisplay;
+			modeInfo.dotClock = mode->Clock * 1000;
+			modeInfo.hSyncStart = mode->HSyncStart;
+			modeInfo.hSyncEnd = mode->HSyncEnd;
+			modeInfo.hTotal = mode->HTotal;
+			modeInfo.hSkew = mode->HSkew;
+
+			modeInfo.height = mode->VDisplay;
+			modeInfo.vSyncStart = mode->VSyncStart;
+			modeInfo.vSyncEnd = mode->VSyncEnd;
+			modeInfo.vTotal = mode->VTotal;
+			modeInfo.modeFlags = mode->Flags;
+
+			rrmode = RRModeGet (pScreen, &modeInfo, mode->name);
+			rrmode->devPrivate = mode;
+			if (rrmode) {
+			    rrmodes[nmode++] = rrmode;
+			    npreferred += p;
 			}
 		    }
 		}
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 3932ea6..b6a3d67 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -940,6 +940,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
     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;
 
     /* 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.
diff --git a/src/i830_tv.c b/src/i830_tv.c
index 3e72882..47c0d03 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -417,6 +417,18 @@ i830_tv_detect(ScrnInfoPtr pScrn, I830Ou
     return OUTPUT_STATUS_UNKNOWN;
 }
 
+/**
+ * Stub get_modes function.
+ *
+ * This should probably return a set of fixed modes, unless we can figure out
+ * how to probe modes off of TV connections.
+ */
+DisplayModePtr
+i830_tv_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output)
+{
+    return NULL;
+}
+
 void
 i830_tv_init(ScrnInfoPtr pScrn)
 {
@@ -438,6 +450,7 @@ i830_tv_init(ScrnInfoPtr pScrn)
     pI830->output[pI830->num_outputs].pre_set_mode = i830_tv_pre_set_mode;
     pI830->output[pI830->num_outputs].post_set_mode = i830_tv_post_set_mode;
     pI830->output[pI830->num_outputs].detect = i830_tv_detect;
+    pI830->output[pI830->num_outputs].get_modes = i830_tv_get_modes;
 
     pI830->num_outputs++;
 }
diff-tree cc3728be2481637dda321d3bc2e4e89a220699cd (from a71f283650e8cb7b760e5a53c4db79202c4cc5c4)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Oct 31 15:00:36 2006 -0800

    Add compat definitions for M_T_PREFERRED and M_T_DRIVER for older X Servers.

diff --git a/src/i830.h b/src/i830.h
index b962e88..27a9817 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -724,4 +724,12 @@ void i830_tv_init(ScrnInfoPtr pScrn);
 #define _845_DRAM_RW_CONTROL 0x90
 #define DRAM_WRITE    0x33330000
 
+/* Compat definitions for older X Servers. */
+#ifndef M_T_PREFERRED
+#define M_T_PREFERRED	0x08
+#endif
+#ifndef M_T_DRIVER
+#define M_T_DRIVER	0x40
+#endif
+
 #endif /* _I830_H_ */
diff-tree a71f283650e8cb7b760e5a53c4db79202c4cc5c4 (from 68cef9f4e028755bbf3e1862da2ef47d46ddaa6a)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Oct 31 14:46:23 2006 -0800

    Connect output detection up to RandR.

diff --git a/src/i830_randr.c b/src/i830_randr.c
index f64f3da..23ffaf6 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -763,11 +763,17 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
 
 	xfree (rrmodes);
 
-	connection = RR_Disconnected;
-	if (pipe >= 0)
-	    connection = RR_Connected;
-
-	RROutputSetConnection (randrp->outputs[i], connection);
+	switch (pI830->output[i].detect(pScrn, &pI830->output[i])) {
+	case OUTPUT_STATUS_CONNECTED:
+	    RROutputSetConnection (randrp->outputs[i], RR_Connected);
+	    break;
+	case OUTPUT_STATUS_DISCONNECTED:
+	    RROutputSetConnection (randrp->outputs[i], RR_Disconnected);
+	    break;
+	case OUTPUT_STATUS_UNKNOWN:
+	    RROutputSetConnection (randrp->outputs[i], RR_UnknownConnection);
+	    break;
+	}
 
 	RROutputSetSubpixelOrder (randrp->outputs[i], subpixel);
 
diff-tree 68cef9f4e028755bbf3e1862da2ef47d46ddaa6a (from 9fd719fce27f916ab5120f6e1234affa14eaed9d)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Oct 31 14:32:00 2006 -0800

    Move output connection detection to a per-output method.
    
    This will be used by RandR, and should let us clean up some of the initial
    display configuration, hopefully.
    
    Also, analog hotplug-based detection is now enabled on G965.

diff --git a/src/i830.h b/src/i830.h
index 40c8cce..b962e88 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -207,6 +207,12 @@ struct _I830DVODriver {
 
 extern const char *i830_output_type_names[];
 
+enum detect_status {
+   OUTPUT_STATUS_CONNECTED,
+   OUTPUT_STATUS_DISCONNECTED,
+   OUTPUT_STATUS_UNKNOWN
+};
+
 struct _I830OutputRec {
    int type;
    int pipe;
@@ -258,6 +264,11 @@ struct _I830OutputRec {
    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);
+
    xf86MonPtr MonInfo;
    I2CBusPtr pI2CBus;
    I2CBusPtr pDDCBus;
diff --git a/src/i830_crt.c b/src/i830_crt.c
index 7721a0c..d271eed 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -112,6 +112,167 @@ i830_crt_post_set_mode(ScrnInfoPtr pScrn
     OUTREG(ADPA, adpa);
 }
 
+/**
+ * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence.
+ *
+ * Only for I945G/GM.
+ *
+ * \return TRUE if CRT is connected.
+ * \return FALSE if CRT is disconnected.
+ */
+static Bool
+i830_crt_detect_hotplug(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD32 temp;
+    const int timeout_ms = 1000;
+    int starttime, curtime;
+
+    temp = INREG(PORT_HOTPLUG_EN);
+
+    OUTREG(PORT_HOTPLUG_EN, temp | CRT_HOTPLUG_FORCE_DETECT | (1 << 5));
+
+    for (curtime = starttime = GetTimeInMillis();
+	 (curtime - starttime) < timeout_ms; curtime = GetTimeInMillis())
+    {
+	if ((INREG(PORT_HOTPLUG_EN) & CRT_HOTPLUG_FORCE_DETECT) == 0)
+	    break;
+    }
+
+    if ((INREG(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_MONITOR_MASK) ==
+	CRT_HOTPLUG_MONITOR_COLOR)
+    {
+	return TRUE;
+    } else {
+	return FALSE;
+    }
+}
+
+/**
+ * Detects CRT presence by checking for load.
+ *
+ * Requires that the current pipe's DPLL is active.  This will cause flicker
+ * on the CRT, so it should not be used while the display is being used.  Only
+ * color (not monochrome) displays are detected.
+ *
+ * \return TRUE if CRT is connected.
+ * \return FALSE if CRT is disconnected.
+ */
+static Bool
+i830_crt_detect_load(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD32 adpa, pipeconf;
+    CARD8 st00;
+    int pipeconf_reg, bclrpat_reg, dpll_reg;
+    int pipe;
+
+    pipe = pI830->pipe;
+    if (pipe == 0) {
+	bclrpat_reg = BCLRPAT_A;
+	pipeconf_reg = PIPEACONF;
+	dpll_reg = DPLL_A;
+    } else {
+	bclrpat_reg = BCLRPAT_B;
+	pipeconf_reg = PIPEBCONF;
+	dpll_reg = DPLL_B;
+    }
+
+    /* Don't try this if the DPLL isn't running. */
+    if (!(INREG(dpll_reg) & DPLL_VCO_ENABLE))
+	return FALSE;
+
+    adpa = INREG(ADPA);
+
+    /* Enable CRT output if disabled. */
+    if (!(adpa & ADPA_DAC_ENABLE)) {
+	OUTREG(ADPA, adpa | ADPA_DAC_ENABLE |
+	       ((pipe == 1) ? ADPA_PIPE_B_SELECT : 0));
+    }
+
+    /* Set the border color to red, green.  Maybe we should save/restore this
+     * reg.
+     */
+    OUTREG(bclrpat_reg, 0x00500050);
+
+    /* Force the border color through the active region */
+    pipeconf = INREG(pipeconf_reg);
+    OUTREG(pipeconf_reg, pipeconf | PIPECONF_FORCE_BORDER);
+
+    /* Read the ST00 VGA status register */
+    st00 = pI830->readStandard(pI830, 0x3c2);
+
+    /* Restore previous settings */
+    OUTREG(pipeconf_reg, pipeconf);
+    OUTREG(ADPA, adpa);
+
+    if (st00 & (1 << 4))
+	return TRUE;
+    else
+	return FALSE;
+}
+
+/**
+ * Detects CRT presence by probing for a response on the DDC address.
+ *
+ * This takes approximately 5ms in testing on an i915GM, with CRT connected or
+ * not.
+ *
+ * \return TRUE if the CRT is connected and responded to DDC.
+ * \return FALSE if no DDC response was detected.
+ */
+static Bool
+i830_crt_detect_ddc(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    struct _I830OutputRec *output;
+
+    output = &pI830->output[0];
+    /* CRT should always be at 0, but check anyway */
+    if (output->type != I830_OUTPUT_ANALOG)
+	return FALSE;
+
+    return xf86I2CProbeAddress(output->pDDCBus, 0x00A0);
+}
+
+/**
+ * Attempts to detect CRT presence through any method available.
+ *
+ * @param allow_disturb enables detection methods that may cause flickering
+ *        on active displays.
+ */
+static enum detect_status
+i830_crt_detect(ScrnInfoPtr pScrn, I830OutputPtr output)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    if (IS_I945G(pI830) || IS_I945GM(pI830) || IS_I965G(pI830)) {
+	if (i830_crt_detect_hotplug(pScrn))
+	    return OUTPUT_STATUS_CONNECTED;
+	else
+	    return OUTPUT_STATUS_DISCONNECTED;
+    }
+
+    if (i830_crt_detect_ddc(pScrn))
+	return OUTPUT_STATUS_CONNECTED;
+
+    /* Use the load-detect method if we're not currently outputting to the CRT,
+     * or we don't care.
+     *
+     * Actually, the method is unreliable currently.  We need to not share a
+     * pipe, as it seems having other outputs on that pipe will result in a
+     * false positive.
+     */
+    if (0) {
+	if (i830_crt_detect_load(pScrn))
+	    return OUTPUT_STATUS_CONNECTED;
+	else
+	    return OUTPUT_STATUS_DISCONNECTED;
+    }
+
+    return OUTPUT_STATUS_UNKNOWN;
+}
+
 void
 i830_crt_init(ScrnInfoPtr pScrn)
 {
@@ -124,6 +285,7 @@ i830_crt_init(ScrnInfoPtr pScrn)
     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;
 
     /* Set up the DDC bus. */
     I830I2CInit(pScrn, &pI830->output[pI830->num_outputs].pDDCBus,
diff --git a/src/i830_display.c b/src/i830_display.c
index 41f8c21..3151fd1 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -831,150 +831,3 @@ i830DescribeOutputConfiguration(ScrnInfo
 		   pI830->output[i].pipe == 0 ? 'A' : 'B');
     }
 }
-
-/**
- * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence.
- *
- * Only for I945G/GM.
- */
-static Bool
-i830HotplugDetectCRT(ScrnInfoPtr pScrn)
-{
-    I830Ptr pI830 = I830PTR(pScrn);
-    CARD32 temp;
-    const int timeout_ms = 1000;
-    int starttime, curtime;
-
-    temp = INREG(PORT_HOTPLUG_EN);
-
-    OUTREG(PORT_HOTPLUG_EN, temp | CRT_HOTPLUG_FORCE_DETECT | (1 << 5));
-
-    for (curtime = starttime = GetTimeInMillis();
-	 (curtime - starttime) < timeout_ms; curtime = GetTimeInMillis())
-    {
-	if ((INREG(PORT_HOTPLUG_EN) & CRT_HOTPLUG_FORCE_DETECT) == 0)
-	    break;
-    }
-
-    if ((INREG(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_MONITOR_MASK) ==
-	CRT_HOTPLUG_MONITOR_COLOR)
-    {
-	return TRUE;
-    } else {
-	return FALSE;
-    }
-}
-
-/**
- * Detects CRT presence by checking for load.
- *
- * Requires that the current pipe's DPLL is active.  This will cause flicker
- * on the CRT, so it should not be used while the display is being used.  Only
- * color (not monochrome) displays are detected.
- */
-static Bool
-i830LoadDetectCRT(ScrnInfoPtr pScrn)
-{
-    I830Ptr pI830 = I830PTR(pScrn);
-    CARD32 adpa, pipeconf;
-    CARD8 st00;
-    int pipeconf_reg, bclrpat_reg, dpll_reg;
-    int pipe;
-
-    pipe = pI830->pipe;
-    if (pipe == 0) {
-	bclrpat_reg = BCLRPAT_A;
-	pipeconf_reg = PIPEACONF;
-	dpll_reg = DPLL_A;
-    } else {
-	bclrpat_reg = BCLRPAT_B;
-	pipeconf_reg = PIPEBCONF;
-	dpll_reg = DPLL_B;
-    }
-
-    /* Don't try this if the DPLL isn't running. */
-    if (!(INREG(dpll_reg) & DPLL_VCO_ENABLE))
-	return FALSE;
-
-    adpa = INREG(ADPA);
-
-    /* Enable CRT output if disabled. */
-    if (!(adpa & ADPA_DAC_ENABLE)) {
-	OUTREG(ADPA, adpa | ADPA_DAC_ENABLE |
-	       ((pipe == 1) ? ADPA_PIPE_B_SELECT : 0));
-    }
-
-    /* Set the border color to red, green.  Maybe we should save/restore this
-     * reg.
-     */
-    OUTREG(bclrpat_reg, 0x00500050);
-
-    /* Force the border color through the active region */
-    pipeconf = INREG(pipeconf_reg);
-    OUTREG(pipeconf_reg, pipeconf | PIPECONF_FORCE_BORDER);
-
-    /* Read the ST00 VGA status register */
-    st00 = pI830->readStandard(pI830, 0x3c2);
-
-    /* Restore previous settings */
-    OUTREG(pipeconf_reg, pipeconf);
-    OUTREG(ADPA, adpa);
-
-    if (st00 & (1 << 4))
-	return TRUE;
-    else
-	return FALSE;
-}
-
-/**
- * Detects CRT presence by probing for a response on the DDC address.
- *
- * This takes approximately 5ms in testing on an i915GM, with CRT connected or
- * not.
- */
-static Bool
-i830DDCDetectCRT(ScrnInfoPtr pScrn)
-{
-    I830Ptr pI830 = I830PTR(pScrn);
-    struct _I830OutputRec *output;
-
-    output = &pI830->output[0];
-    /* CRT should always be at 0, but check anyway */
-    if (output->type != I830_OUTPUT_ANALOG)
-	return FALSE;
-
-    return xf86I2CProbeAddress(output->pDDCBus, 0x00A0);
-}
-
-/**
- * Attempts to detect CRT presence through any method available.
- *
- * @param allow_disturb enables detection methods that may cause flickering
- *        on active displays.
- */
-Bool
-i830DetectCRT(ScrnInfoPtr pScrn, Bool allow_disturb)
-{
-    I830Ptr pI830 = I830PTR(pScrn);
-    Bool found_ddc;
-
-    if (IS_I945G(pI830) || IS_I945GM(pI830))
-	return i830HotplugDetectCRT(pScrn);
-
-    found_ddc = i830DDCDetectCRT(pScrn);
-    if (found_ddc)
-	return TRUE;
-
-    /* Use the load-detect method if we're not currently outputting to the CRT,
-     * or we don't care.
-     *
-     * Actually, the method is unreliable currently.  We need to not share a
-     * pipe, as it seems having other outputs on that pipe will result in a
-     * false positive.
-     */
-    if (0 && (allow_disturb || !(INREG(ADPA) & !ADPA_DAC_ENABLE))) {
-	return i830LoadDetectCRT(pScrn);
-    }
-
-    return FALSE;
-}
diff --git a/src/i830_display.h b/src/i830_display.h
index 576a149..8a6e9e9 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -29,7 +29,6 @@
 Bool i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe);
 void i830DisableUnusedFunctions(ScrnInfoPtr pScrn);
 Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
-Bool i830DetectCRT(ScrnInfoPtr pScrn, Bool allow_disturb);
 void i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y);
 void i830WaitForVblank(ScrnInfoPtr pScrn);
 void i830DescribeOutputConfiguration(ScrnInfoPtr pScrn);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index f142c4b..2c7eca7 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1439,28 +1439,36 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       pI830->operatingDevices = (pI830->MonType2 << 8) | pI830->MonType1;
       pI830->specifiedMonitor = TRUE;
    } else if (I830IsPrimary(pScrn)) {
-      /* Choose a default set of outputs to use based on what we've detected. */
-      if (i830DetectCRT(pScrn, TRUE)) {
-	 pI830->MonType1 |= PIPE_CRT;
-      }
-
-      /* Check for attached SDVO outputs.  Assume that they're flat panels for
-       * now.  Though really, it's just a name at the moment, since we don't
-       * treat different SDVO outputs differently.  Also, check for LVDS and
-       * set it  to the right pipe if available.
+      /* Choose a default set of outputs to use based on what we've detected.
+       *
+       * Assume that SDVO outputs are flat panels for now.  It's just a name
+       * at the moment, since we don't treat different SDVO outputs
+       * differently.
        */
       for (i = 0; i < pI830->num_outputs; i++) {
 	 if (pI830->output[i].type == I830_OUTPUT_LVDS)
-	    pI830->MonType2 |= PIPE_LFP;
+	    pI830->MonType2 = PIPE_LFP;
 
-	 if (pI830->output[i].type == I830_OUTPUT_SDVO) {
-	    if (!i830_sdvo_detect_displays(pScrn, &pI830->output[i]))
+	 if (pI830->output[i].type == I830_OUTPUT_SDVO ||
+	     pI830->output[i].type == I830_OUTPUT_ANALOG)
+	 {
+	    int pipetype;
+
+	    if (pI830->output[i].detect(pScrn, &pI830->output[i]) ==
+		OUTPUT_STATUS_DISCONNECTED)
+	    {
 	       continue;
+	    }
+
+	    if (pI830->output[i].type == I830_OUTPUT_SDVO)
+	       pipetype = PIPE_DFP;
+	    else
+	       pipetype = PIPE_CRT;
 
 	    if (pI830->MonType1 == PIPE_NONE)
-	       pI830->MonType1 |= PIPE_DFP;
+	       pI830->MonType1 |= pipetype;
 	    else if (pI830->MonType2 == PIPE_NONE)
-	       pI830->MonType2 |= PIPE_DFP;
+	       pI830->MonType2 |= pipetype;
 	 }
       }
 
@@ -3891,22 +3899,23 @@ i830MonitorDetectDebugger(ScrnInfoPtr pS
    if (!pScrn->vtSema)
       return 1000;
 
-   start = GetTimeInMillis();
-   found_crt = i830DetectCRT(pScrn, FALSE);   
-   finish = GetTimeInMillis();
-   xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Detected CRT as %s in %dms\n",
-	      found_crt ? "connected" : "disconnected", finish - start);
-
    for (i = 0; i < pI830->num_outputs; i++) {
-      Bool found_sdvo = TRUE;
+      enum output_status ret;
+      char *result;
 
-      if (pI830->output[i].type != I830_OUTPUT_SDVO)
-	 continue;
       start = GetTimeInMillis();
-      found_sdvo = i830_sdvo_detect_displays(pScrn, &pI830->output[i]);
+      ret = pI830->output[i].detect(pScrn, &pI830->output[i]);
       finish = GetTimeInMillis();
+
+      if (ret == OUTPUT_STATUS_CONNECTED)
+	 result = "connected";
+      else if (ret == OUTPUT_STATUS_DISCONNECTED)
+	 result = "disconnected";
+      else
+	 result = "unknown";
+
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Detected SDVO as %s in %dms\n",
-		 found_sdvo ? "connected" : "disconnected", finish - start);
+		 result, finish - start);
    }
 }
 #endif
diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index 01858f2..ed21ecc 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -144,6 +144,17 @@ i830_dvo_post_set_mode(ScrnInfoPtr pScrn
     OUTREG(DVOC, dvo);
 }
 
+/**
+ * Detect the output connection on our DVO device.
+ *
+ * Unimplemented.
+ */
+static enum detect_status
+i830_dvo_detect(ScrnInfoPtr pScrn, I830OutputPtr output)
+{
+    return OUTPUT_STATUS_UNKNOWN;
+}
+
 static Bool
 I830I2CDetectDVOControllers(ScrnInfoPtr pScrn, I2CBusPtr pI2CBus,
 			    struct _I830DVODriver **retdrv)
@@ -189,6 +200,7 @@ i830_dvo_init(ScrnInfoPtr pScrn)
     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;
 
     /* Set up the I2C and DDC buses */
     ret = I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "DVOI2C_E");
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index 5b039b8..e0e471f 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -31,6 +31,7 @@
 
 #include "xf86.h"
 #include "i830.h"
+#include "i830_bios.h"
 
 /**
  * Sets the power state for the panel.
@@ -176,6 +177,18 @@ i830_lvds_post_set_mode(ScrnInfoPtr pScr
     i830SetLVDSPanelPower(pScrn, TRUE);
 }
 
+/**
+ * Detect the LVDS connection.
+ *
+ * This always returns OUTPUT_STATUS_CONNECTED.  This output should only have
+ * been set up if the LVDS was actually connected anyway.
+ */
+static enum detect_status
+i830_lvds_detect(ScrnInfoPtr pScrn, I830OutputPtr output)
+{
+    return OUTPUT_STATUS_CONNECTED;
+}
+
 void
 i830_lvds_init(ScrnInfoPtr pScrn)
 {
@@ -221,6 +234,7 @@ i830_lvds_init(ScrnInfoPtr pScrn)
     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;
 
     /* Set up the LVDS DDC channel.  Most panels won't support it, but it can
      * be useful if available.
diff --git a/src/i830_modes.c b/src/i830_modes.c
index 633ac83..130b7fe 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -803,17 +803,18 @@ I830ReprobePipeModeList(ScrnInfoPtr pScr
      * is plugged in, then assume that it is.
      */
     if (pI830->pipeMon[pipe] == NULL) {
+	enum detect_status detect;
+
+	detect = pI830->output[output_index].detect(pScrn,
+		&pI830->output[output_index]);
+
 	switch (pI830->output[output_index].type) {
 	case I830_OUTPUT_SDVO:
-	    if (i830_sdvo_detect_displays(pScrn, &pI830->output[output_index]))
+	    if (detect == OUTPUT_STATUS_CONNECTED)
 		pI830->pipeMon[pipe] = i830GetConfiguredMonitor(pScrn);
 	    break;
 	case I830_OUTPUT_ANALOG:
-	    /* Do a disruptive detect if necessary, since we want to be sure we
-	     * know if a monitor is attached, and this detect process should be
-	     * infrequent.
-	     */
-	    if (i830DetectCRT(pScrn, TRUE)) {
+	    if (detect == OUTPUT_STATUS_CONNECTED) {
 /*		if (pipe == pI830->pipe)
 		    pI830->pipeMon[pipe] = i830GetConfiguredMonitor(pScrn);
 		else */
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index d3f509e..3932ea6 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -904,8 +904,8 @@ i830_sdvo_dump(ScrnInfoPtr pScrn)
  *
  * Takes 14ms on average on my i945G.
  */
-Bool
-i830_sdvo_detect_displays(ScrnInfoPtr pScrn, I830OutputPtr output)
+static enum detect_status
+i830_sdvo_detect(ScrnInfoPtr pScrn, I830OutputPtr output)
 {
     CARD8 response[2];
     CARD8 status;
@@ -914,9 +914,12 @@ i830_sdvo_detect_displays(ScrnInfoPtr pS
     status = i830_sdvo_read_response(output, &response, 2);
 
     if (status != SDVO_CMD_STATUS_SUCCESS)
-	return FALSE;
+	return OUTPUT_STATUS_UNKNOWN;
 
-    return (response[0] != 0 || response[1] != 0);
+    if (response[0] != 0 || response[1] != 0)
+	return OUTPUT_STATUS_CONNECTED;
+    else
+	return OUTPUT_STATUS_DISCONNECTED;
 }
 
 void
@@ -936,6 +939,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
     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;
 
     /* 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.
diff --git a/src/i830_sdvo.h b/src/i830_sdvo.h
index b1d86b4..1368e43 100644
--- a/src/i830_sdvo.h
+++ b/src/i830_sdvo.h
@@ -31,8 +31,5 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
 int
 i830_sdvo_get_pixel_multiplier(DisplayModePtr pMode);
 
-Bool
-i830_sdvo_detect_displays(ScrnInfoPtr pScrn, I830OutputPtr output);
-
 void
 i830_sdvo_dump(ScrnInfoPtr pScrn);
diff --git a/src/i830_tv.c b/src/i830_tv.c
index 2adbe91..3e72882 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -405,6 +405,18 @@ i830_tv_post_set_mode(ScrnInfoPtr pScrn,
     OUTREG(TV_CTL, tv_ctl);
 }
 
+/**
+ * Detect the TV connection.
+ *
+ * Currently this always returns OUTPUT_STATUS_UNKNOWN, as we need to be sure
+ * we have a pipe programmed in order to probe the TV.
+ */
+static enum detect_status
+i830_tv_detect(ScrnInfoPtr pScrn, I830OutputPtr output)
+{
+    return OUTPUT_STATUS_UNKNOWN;
+}
+
 void
 i830_tv_init(ScrnInfoPtr pScrn)
 {
@@ -425,6 +437,7 @@ i830_tv_init(ScrnInfoPtr pScrn)
     pI830->output[pI830->num_outputs].mode_valid = i830_tv_mode_valid;
     pI830->output[pI830->num_outputs].pre_set_mode = i830_tv_pre_set_mode;
     pI830->output[pI830->num_outputs].post_set_mode = i830_tv_post_set_mode;
+    pI830->output[pI830->num_outputs].detect = i830_tv_detect;
 
     pI830->num_outputs++;
 }
diff-tree 9fd719fce27f916ab5120f6e1234affa14eaed9d (from 4f5d4d8870fc2784192f95a561163cf4fc8737ac)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Oct 31 14:29:44 2006 -0800

    Move SDVOB_PRESERVE_MASK next to SDVOC_PRESERVE_MASK.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index bc6c0f8..34e6e53 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -880,7 +880,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 # define CRT_HOTPLUG_MONITOR_NONE		(0 << 8)
 # define SDVOC_HOTPLUG_INT_STATUS		(1 << 7)
 # define SDVOB_HOTPLUG_INT_STATUS		(1 << 6)
-#define SDVOB_PRESERVE_MASK			((1 << 17) | (1 << 16) | (1 << 14))
 
 #define SDVOB			0x61140
 #define SDVOC			0x61160
@@ -905,6 +904,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define SDVOB_PCIE_CONCURRENCY			(1 << 3)
 #define SDVO_DETECTED				(1 << 2)
 /* Bits to be preserved when writing */
+#define SDVOB_PRESERVE_MASK			((1 << 17) | (1 << 16) | (1 << 14))
 #define SDVOC_PRESERVE_MASK			(1 << 17)
 
 #define I830_HTOTAL_MASK 	0xfff0000
diff-tree 4f5d4d8870fc2784192f95a561163cf4fc8737ac (from 49bbdf16c02107c08169f8d2b6e9c6dbd7d8cd95)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Oct 31 13:37:23 2006 -0800

    i830SetLVDSPanelPower is now a static function in i830_lvds.c, so remove it.

diff --git a/src/i830_display.h b/src/i830_display.h
index 229e576..576a149 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -30,7 +30,6 @@ Bool i830PipeSetMode(ScrnInfoPtr pScrn, 
 void i830DisableUnusedFunctions(ScrnInfoPtr pScrn);
 Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
 Bool i830DetectCRT(ScrnInfoPtr pScrn, Bool allow_disturb);
-void i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on);
 void i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y);
 void i830WaitForVblank(ScrnInfoPtr pScrn);
 void i830DescribeOutputConfiguration(ScrnInfoPtr pScrn);
diff-tree 49bbdf16c02107c08169f8d2b6e9c6dbd7d8cd95 (from e7d546cac06767ec58325396a3bb5780b2257c53)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Oct 31 10:44:45 2006 -0800

    Fix many inconsistencies in the SDVO code compared to the spec.
    
    Also, fix some struct padding  so that the right bits are sent out.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index bbc1c72..d3f509e 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -54,21 +54,27 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 struct i830_sdvo_priv {
     /** SDVO device on SDVO I2C bus. */
     I2CDevRec d;
+
     /** Register for the SDVO device: SDVOB or SDVOC */
     int output_device;
+
+    /** Active outputs controlled by this SDVO output */
+    struct i830_sdvo_output_flags active_outputs;
+
     /**
      * Capabilities of the SDVO device returned by i830_sdvo_get_capabilities()
      */
-    i830_sdvo_caps caps;
+    struct i830_sdvo_caps caps;
+
     /** Pixel clock limitations reported by the SDVO device */
     CARD16 pixel_clock_min, pixel_clock_max;
 
     /** State for save/restore */
     /** @{ */
     int save_sdvo_mult;
-    Bool save_sdvo_active_1, save_sdvo_active_2;
+    struct i830_sdvo_output_flags save_active_outputs;
     struct i830_sdvo_dtd save_input_dtd_1, save_input_dtd_2;
-    struct i830_sdvo_dtd save_output_dtd_1, save_output_dtd_2;
+    struct i830_sdvo_dtd save_output_dtd;
     CARD32 save_SDVOX;
     /** @} */
 };
@@ -122,7 +128,7 @@ const struct _sdvo_cmd_name {
     SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HOT_PLUG_SUPPORT),
     SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_HOT_PLUG),
     SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_HOT_PLUG),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INTR_EVENT_SOURCE),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE),
     SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_INPUT),
     SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_OUTPUT),
     SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART1),
@@ -187,7 +193,7 @@ static const char *cmd_status_names[] = 
 	"Not supported",
 	"Invalid arg",
 	"Pending",
-	"Target not supported",
+	"Target not specified",
 	"Scaling not supported"
 };
 
@@ -249,14 +255,19 @@ i830_sdvo_set_control_bus_switch(I830Out
 }
 
 static Bool
-i830_sdvo_set_target_input(I830OutputPtr output, Bool target_1, Bool target_2)
+i830_sdvo_set_target_input(I830OutputPtr output, Bool target_0, Bool target_1)
 {
-    CARD8 targets[2];
+    struct i830_sdvo_set_target_input_args targets = {0};
     CARD8 status;
 
-    targets[0] = target_1;
-    targets[1] = target_2;
-    i830_sdvo_write_cmd(output, SDVO_CMD_SET_TARGET_INPUT, &targets, 2);
+    if (target_0 && target_1)
+	return SDVO_CMD_STATUS_NOTSUPP;
+
+    if (target_1)
+	targets.target_1 = 1;
+
+    i830_sdvo_write_cmd(output, SDVO_CMD_SET_TARGET_INPUT, &targets,
+			sizeof(targets));
 
     status = i830_sdvo_read_response(output, NULL, 0);
 
@@ -272,47 +283,41 @@ i830_sdvo_set_target_input(I830OutputPtr
 static Bool
 i830_sdvo_get_trained_inputs(I830OutputPtr output, Bool *input_1, Bool *input_2)
 {
-    CARD8 response[2];
+    struct i830_sdvo_get_trained_inputs_response response;
     CARD8 status;
 
     i830_sdvo_write_cmd(output, SDVO_CMD_GET_TRAINED_INPUTS, NULL, 0);
 
-    status = i830_sdvo_read_response(output, response, 2);
+    status = i830_sdvo_read_response(output, &response, sizeof(response));
     if (status != SDVO_CMD_STATUS_SUCCESS)
 	return FALSE;
 
-    *input_1 = response[0];
-    *input_2 = response[1];
+    *input_1 = response.input0_trained;
+    *input_2 = response.input1_trained;
 
     return TRUE;
 }
 
 static Bool
-i830_sdvo_get_active_outputs(I830OutputPtr output, Bool *on_1, Bool *on_2)
+i830_sdvo_get_active_outputs(I830OutputPtr output,
+			     struct i830_sdvo_output_flags *outputs)
 {
-    CARD8 response[2];
     CARD8 status;
 
     i830_sdvo_write_cmd(output, SDVO_CMD_GET_ACTIVE_OUTPUTS, NULL, 0);
-
-    status = i830_sdvo_read_response(output, &response, 2);
-
-    *on_1 = response[0];
-    *on_2 = response[1];
+    status = i830_sdvo_read_response(output, outputs, sizeof(*outputs));
 
     return (status == SDVO_CMD_STATUS_SUCCESS);
 }
 
 static Bool
-i830_sdvo_set_active_outputs(I830OutputPtr output, Bool on_1, Bool on_2)
+i830_sdvo_set_active_outputs(I830OutputPtr output,
+			     struct i830_sdvo_output_flags *outputs)
 {
-    CARD8 outputs[2];
     CARD8 status;
 
-    outputs[0] = on_1;
-    outputs[1] = on_2;
-    i830_sdvo_write_cmd(output, SDVO_CMD_SET_ACTIVE_OUTPUTS, &outputs, 2);
-
+    i830_sdvo_write_cmd(output, SDVO_CMD_SET_ACTIVE_OUTPUTS, outputs,
+			sizeof(*outputs));
     status = i830_sdvo_read_response(output, NULL, 0);
 
     return (status == SDVO_CMD_STATUS_SUCCESS);
@@ -339,14 +344,13 @@ i830_sdvo_get_input_pixel_clock_range(I8
 }
 
 static Bool
-i830_sdvo_set_target_output(I830OutputPtr output, Bool target_1, Bool target_2)
+i830_sdvo_set_target_output(I830OutputPtr output,
+			    struct i830_sdvo_output_flags *outputs)
 {
-    CARD8 targets[2];
     CARD8 status;
 
-    targets[0] = target_1;
-    targets[1] = target_2;
-    i830_sdvo_write_cmd(output, SDVO_CMD_SET_TARGET_OUTPUT, &targets, 2);
+    i830_sdvo_write_cmd(output, SDVO_CMD_SET_TARGET_OUTPUT, outputs,
+			sizeof(*outputs));
 
     status = i830_sdvo_read_response(output, NULL, 0);
 
@@ -508,11 +512,15 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn
 		       DisplayModePtr mode)
 {
     I830Ptr pI830 = I830PTR(pScrn);
+    struct i830_sdvo_priv *dev_priv = output->dev_priv;
     CARD16 width = mode->CrtcHDisplay;
     CARD16 height = mode->CrtcVDisplay;
     CARD16 h_blank_len, h_sync_len, v_blank_len, v_sync_len;
     CARD16 h_sync_offset, v_sync_offset;
     struct i830_sdvo_dtd output_dtd;
+    struct i830_sdvo_output_flags no_outputs;
+
+    memset(&no_outputs, 0, sizeof(no_outputs));
 
     /* do some mode translations */
     h_blank_len = mode->CrtcHBlankEnd - mode->CrtcHBlankStart;
@@ -549,13 +557,13 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn
 	output_dtd.part2.dtd_flags |= 0x4;
 
     /* Turn off the screens before adjusting timings */
-    i830_sdvo_set_active_outputs(output, FALSE, FALSE);
+    i830_sdvo_set_active_outputs(output, &no_outputs);
 
     /* Set the output timing to the screen */
-    i830_sdvo_set_target_output(output, TRUE, FALSE);
+    i830_sdvo_set_target_output(output, &dev_priv->active_outputs);
     i830_sdvo_set_output_timing(output, &output_dtd);
 
-    /* Set the input timing to the screen */
+    /* Set the input timing to the screen. Assume always input 0. */
     i830_sdvo_set_target_input(output, TRUE, FALSE);
 
     /* We would like to use i830_sdvo_create_preferred_input_timing() to
@@ -597,29 +605,15 @@ i830_sdvo_post_set_mode(ScrnInfoPtr pScr
 			DisplayModePtr mode)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    Bool out1, out2, input1, input2;
+    struct i830_sdvo_priv *dev_priv = output->dev_priv;
+    Bool input1, input2;
     CARD32 dpll, sdvob, sdvoc;
     int dpll_reg = (output->pipe == 0) ? DPLL_A : DPLL_B;
     int dpll_md_reg = (output->pipe == 0) ? DPLL_A_MD : DPLL_B_MD;
     int sdvo_pixel_multiply;
+    int i;
     CARD8 status;
 
-    /* the BIOS writes out 6 commands post mode set */
-    /* two 03s, 04 05, 10, 1d */
-    /* these contain the height and mode clock / 10 by the looks of it */
-
-    status = i830_sdvo_get_trained_inputs(output, &input1, &input2);
-
-    /* Warn if the device reported failure to sync. */
-    if (status == SDVO_CMD_STATUS_SUCCESS && !input1) {
-	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		   "First SDVO output reported failure to sync\n");
-    }
-
-    i830_sdvo_get_active_outputs(output, &out1, &out2);
-    i830_sdvo_set_active_outputs(output, TRUE, FALSE);
-    i830_sdvo_set_target_input(output, FALSE, FALSE);
-
     /* Set the SDVO control regs. */
     sdvob = INREG(SDVOB) & SDVOB_PRESERVE_MASK;
     sdvoc = INREG(SDVOC) & SDVOC_PRESERVE_MASK;
@@ -644,18 +638,37 @@ i830_sdvo_post_set_mode(ScrnInfoPtr pScr
 
     OUTREG(SDVOB, sdvob);
     OUTREG(SDVOC, sdvoc);
+
+    for (i = 0; i < 2; i++)
+	i830WaitForVblank(pScrn);
+
+    status = i830_sdvo_get_trained_inputs(output, &input1, &input2);
+
+    /* Warn if the device reported failure to sync. */
+    if (status == SDVO_CMD_STATUS_SUCCESS && !input1) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "First SDVO output reported failure to sync\n");
+    }
+
+    i830_sdvo_set_active_outputs(output, &dev_priv->active_outputs);
+    i830_sdvo_set_target_input(output, TRUE, FALSE);
 }
 
 static void
 i830_sdvo_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
 {
     I830Ptr pI830 = I830PTR(pScrn);
+    struct i830_sdvo_priv *dev_priv = output->dev_priv;
 
     if (mode != DPMSModeOn) {
-	i830_sdvo_set_active_outputs(output, FALSE, FALSE);
+	struct i830_sdvo_output_flags no_outputs;
+
+	memset(&no_outputs, 0, sizeof(no_outputs));
+
+	i830_sdvo_set_active_outputs(output, &no_outputs);
 	OUTREG(SDVOB, INREG(SDVOB) & ~SDVO_ENABLE);
     } else {
-	i830_sdvo_set_active_outputs(output, TRUE, FALSE);
+	i830_sdvo_set_active_outputs(output, &dev_priv->active_outputs);
 	OUTREG(SDVOB, INREG(SDVOB) | SDVO_ENABLE);
     }
 }
@@ -666,12 +679,13 @@ i830_sdvo_save(ScrnInfoPtr pScrn, I830Ou
     I830Ptr pI830 = I830PTR(pScrn);
     struct i830_sdvo_priv *dev_priv = output->dev_priv;
 
+    /* XXX: We should save the in/out mapping. */
+
     dev_priv->save_sdvo_mult = i830_sdvo_get_clock_rate_mult(output);
-    i830_sdvo_get_active_outputs(output, &dev_priv->save_sdvo_active_1,
-				 &dev_priv->save_sdvo_active_2);
+    i830_sdvo_get_active_outputs(output, &dev_priv->save_active_outputs);
 
     if (dev_priv->caps.sdvo_inputs_mask & 0x1) {
-       i830_sdvo_set_target_input(output, FALSE, FALSE);
+       i830_sdvo_set_target_input(output, TRUE, FALSE);
        i830_sdvo_get_input_timing(output, &dev_priv->save_input_dtd_1);
     }
 
@@ -680,15 +694,11 @@ i830_sdvo_save(ScrnInfoPtr pScrn, I830Ou
        i830_sdvo_get_input_timing(output, &dev_priv->save_input_dtd_2);
     }
 
-    if (dev_priv->caps.output_0_supported) {
-       i830_sdvo_set_target_output(output, TRUE, FALSE);
-       i830_sdvo_get_output_timing(output, &dev_priv->save_output_dtd_1);
-    }
-
-    if (dev_priv->caps.output_1_supported) {
-       i830_sdvo_set_target_output(output, FALSE, TRUE);
-       i830_sdvo_get_output_timing(output, &dev_priv->save_output_dtd_2);
-    }
+    /* XXX: We should really iterate over the enabled outputs and save each
+     * one's state.
+     */
+    i830_sdvo_set_target_output(output, &dev_priv->save_active_outputs);
+    i830_sdvo_get_output_timing(output, &dev_priv->save_output_dtd);
 
     dev_priv->save_SDVOX = INREG(dev_priv->output_device);
 }
@@ -700,7 +710,7 @@ i830_sdvo_restore(ScrnInfoPtr pScrn, I83
     struct i830_sdvo_priv *dev_priv = output->dev_priv;
 
     if (dev_priv->caps.sdvo_inputs_mask & 0x1) {
-       i830_sdvo_set_target_input(output, FALSE, FALSE);
+       i830_sdvo_set_target_input(output, TRUE, FALSE);
        i830_sdvo_set_input_timing(output, &dev_priv->save_input_dtd_1);
     }
 
@@ -709,22 +719,14 @@ i830_sdvo_restore(ScrnInfoPtr pScrn, I83
        i830_sdvo_set_input_timing(output, &dev_priv->save_input_dtd_2);
     }
 
-    if (dev_priv->caps.output_0_supported) {
-       i830_sdvo_set_target_output(output, TRUE, FALSE);
-       i830_sdvo_set_output_timing(output, &dev_priv->save_output_dtd_1);
-    }
-
-    if (dev_priv->caps.output_1_supported) {
-       i830_sdvo_set_target_output(output, FALSE, TRUE);
-       i830_sdvo_set_output_timing(output, &dev_priv->save_output_dtd_2);
-    }
+    i830_sdvo_set_target_output(output, &dev_priv->save_active_outputs);
+    i830_sdvo_set_output_timing(output, &dev_priv->save_output_dtd);
 
     i830_sdvo_set_clock_rate_mult(output, dev_priv->save_sdvo_mult);
 
     OUTREG(dev_priv->output_device, dev_priv->save_SDVOX);
 
-    i830_sdvo_set_active_outputs(output, dev_priv->save_sdvo_active_1,
-				 dev_priv->save_sdvo_active_2);
+    i830_sdvo_set_active_outputs(output, &dev_priv->save_active_outputs);
 }
 
 static int
@@ -743,7 +745,7 @@ i830_sdvo_mode_valid(ScrnInfoPtr pScrn, 
 }
 
 static Bool
-i830_sdvo_get_capabilities(I830OutputPtr output, i830_sdvo_caps *caps)
+i830_sdvo_get_capabilities(I830OutputPtr output, struct i830_sdvo_caps *caps)
 {
     CARD8 status;
 
@@ -866,7 +868,7 @@ i830_sdvo_dump_device(I830OutputPtr outp
     i830_sdvo_dump_cmd(output, SDVO_CMD_GET_ATTACHED_DISPLAYS);
     i830_sdvo_dump_cmd(output, SDVO_CMD_GET_HOT_PLUG_SUPPORT);
     i830_sdvo_dump_cmd(output, SDVO_CMD_GET_ACTIVE_HOT_PLUG);
-    i830_sdvo_dump_cmd(output, SDVO_CMD_GET_INTR_EVENT_SOURCE);
+    i830_sdvo_dump_cmd(output, SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE);
     i830_sdvo_dump_cmd(output, SDVO_CMD_GET_INPUT_TIMINGS_PART1);
     i830_sdvo_dump_cmd(output, SDVO_CMD_GET_INPUT_TIMINGS_PART2);
     i830_sdvo_dump_cmd(output, SDVO_CMD_GET_OUTPUT_TIMINGS_PART1);
@@ -1023,6 +1025,9 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
     i830_sdvo_get_input_pixel_clock_range(output, &dev_priv->pixel_clock_min,
 					  &dev_priv->pixel_clock_max);
 
+    memset(&dev_priv->active_outputs, 0, sizeof(dev_priv->active_outputs));
+    dev_priv->active_outputs.tmds0 = 1;
+
     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 	       "SDVO device VID/DID: %02X:%02X.%02X, "
 	       "input 1: %c, input 2: %c, "
@@ -1031,8 +1036,8 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
 	       dev_priv->caps.device_rev_id,
 	       (dev_priv->caps.sdvo_inputs_mask & 0x1) ? 'Y' : 'N',
 	       (dev_priv->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N',
-	       dev_priv->caps.output_0_supported ? 'Y' : 'N',
-	       dev_priv->caps.output_1_supported ? 'Y' : 'N');
+	       dev_priv->caps.output_flags.tmds0 ? 'Y' : 'N',
+	       dev_priv->caps.output_flags.tmds1 ? 'Y' : 'N');
 
     pI830->num_outputs++;
 }
diff --git a/src/i830_sdvo_regs.h b/src/i830_sdvo_regs.h
index be3294b..c43e17a 100644
--- a/src/i830_sdvo_regs.h
+++ b/src/i830_sdvo_regs.h
@@ -25,7 +25,23 @@
  *
  */
 
-typedef struct _i830_sdvo_caps {
+struct i830_sdvo_output_flags {
+    unsigned int tmds0:1;
+    unsigned int rgb0:1;
+    unsigned int cvbs0:1;
+    unsigned int svid0:1;
+    unsigned int yprpb0:1;
+    unsigned int scart0:1;
+    unsigned int lvds0:1;
+    unsigned int pad0:1;
+    unsigned int tmds1:1;
+    unsigned int pad1:4;
+    unsigned int rgb1:1;
+    unsigned int lvds1:1;
+    unsigned int pad2:1;
+} __attribute__((packed));
+
+struct i830_sdvo_caps {
     CARD8 vendor_id;
     CARD8 device_id;
     CARD8 device_rev_id;
@@ -38,13 +54,13 @@ typedef struct _i830_sdvo_caps {
     unsigned int down_scaling:1;
     unsigned int stall_support:1;
     unsigned int pad:1;
-    CARD8 output_0_supported;
-    CARD8 output_1_supported;
-} __attribute__((packed)) i830_sdvo_caps;
+    struct i830_sdvo_output_flags output_flags;
+} __attribute__((packed));
 
+/** This matches the EDID DTD structure, more or less */
 struct i830_sdvo_dtd {
     struct {
-	CARD16 clock;
+	CARD16 clock;			/**< pixel clock, in 10kHz units */
 	CARD8 h_active;
 	CARD8 h_blank;
 	CARD8 h_high;
@@ -66,8 +82,8 @@ struct i830_sdvo_dtd {
 } __attribute__((packed));
 
 struct i830_sdvo_pixel_clock_range {
-    CARD16 min;
-    CARD16 max;
+    CARD16 min;			/**< pixel clock, in 10kHz units */
+    CARD16 max;			/**< pixel clock, in 10kHz units */
 } __attribute__((packed));
 
 struct i830_sdvo_preferred_input_timing_args {
@@ -103,7 +119,7 @@ struct i830_sdvo_preferred_input_timing_
 #define SDVO_CMD_STATUS_NOTSUPP			0x2
 #define SDVO_CMD_STATUS_INVALID_ARG		0x3
 #define SDVO_CMD_STATUS_PENDING			0x4
-#define SDVO_CMD_STATUS_TARGET_NOT_SUPP		0x5
+#define SDVO_CMD_STATUS_TARGET_NOT_SPECIFIED	0x5
 #define SDVO_CMD_STATUS_SCALING_NOT_SUPP	0x6
 
 /* SDVO commands, argument/result registers */
@@ -116,29 +132,93 @@ struct i830_sdvo_preferred_input_timing_
 #define SDVO_CMD_GET_FIRMWARE_REV			0x86
 # define SDVO_DEVICE_FIRMWARE_MINOR			SDVO_I2C_RETURN_0
 # define SDVO_DEVICE_FIRMWARE_MAJOR			SDVO_I2C_RETURN_1
+# define SDVO_DEVICE_FIRMWARE_PATCH			SDVO_I2C_RETURN_2
 
+/**
+ * Reports which inputs are trained (managed to sync).
+ *
+ * Devices must have trained within 2 vsyncs of a mode change.
+ */
 #define SDVO_CMD_GET_TRAINED_INPUTS			0x03
+struct i830_sdvo_get_trained_inputs_response {
+    unsigned int input0_trained:1;
+    unsigned int input1_trained:1;
+    unsigned int pad:6;
+} __attribute__((packed));
 
+/** Returns a struct i830_sdvo_output_flags of active outputs. */
 #define SDVO_CMD_GET_ACTIVE_OUTPUTS			0x04
 
+/**
+ * Sets the current set of active outputs.
+ *
+ * Takes a struct i830_sdvo_output_flags.  Must be preceded by a SET_IN_OUT_MAP
+ * on multi-output devices.
+ */
 #define SDVO_CMD_SET_ACTIVE_OUTPUTS			0x05
 
+/**
+ * Returns the current mapping of SDVO inputs to outputs on the device.
+ *
+ * Returns two struct i830_sdvo_output_flags structures.
+ */
 #define SDVO_CMD_GET_IN_OUT_MAP				0x06
 
+/**
+ * Sets the current mapping of SDVO inputs to outputs on the device.
+ *
+ * Takes two struct i380_sdvo_output_flags structures.
+ */
 #define SDVO_CMD_SET_IN_OUT_MAP				0x07
 
+/**
+ * Returns a struct i830_sdvo_output_flags of attached displays.
+ */
 #define SDVO_CMD_GET_ATTACHED_DISPLAYS			0x0b
 
+/**
+ * Returns a struct i830_sdvo_ouptut_flags of displays supporting hot plugging.
+ */
 #define SDVO_CMD_GET_HOT_PLUG_SUPPORT			0x0c
 
+/**
+ * Takes a struct i830_sdvo_output_flags.
+ */
 #define SDVO_CMD_SET_ACTIVE_HOT_PLUG			0x0d
 
+/**
+ * Returns a struct i830_sdvo_output_flags of displays with hot plug
+ * interrupts enabled.
+ */
 #define SDVO_CMD_GET_ACTIVE_HOT_PLUG			0x0e
 
-#define SDVO_CMD_GET_INTR_EVENT_SOURCE			0x0f
+#define SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE		0x0f
+struct i830_sdvo_get_interrupt_event_source_response {
+    struct i830_sdvo_output_flags interrupt_status;
+    unsigned int ambient_light_interrupt:1;
+    unsigned int pad:7;
+} __attribute__((packed));
 
+/**
+ * Selects which input is affected by future input commands.
+ *
+ * Commands affected include SET_INPUT_TIMINGS_PART[12],
+ * GET_INPUT_TIMINGS_PART[12], GET_PREFERRED_INPUT_TIMINGS_PART[12],
+ * GET_INPUT_PIXEL_CLOCK_RANGE, and CREATE_PREFERRED_INPUT_TIMINGS.
+ */
 #define SDVO_CMD_SET_TARGET_INPUT			0x10
+struct i830_sdvo_set_target_input_args {
+    unsigned int target_1:1;
+    unsigned int pad:7;
+} __attribute__((packed));
 
+/**
+ * Takes a struct i830_sdvo_output_flags of which outputs are targetted by
+ * future output commands.
+ *
+ * Affected commands inclue SET_OUTPUT_TIMINGS_PART[12],
+ * GET_OUTPUT_TIMINGS_PART[12], and GET_OUTPUT_PIXEL_CLOCK_RANGE.
+ */
 #define SDVO_CMD_SET_TARGET_OUTPUT			0x11
 
 #define SDVO_CMD_GET_INPUT_TIMINGS_PART1		0x12
@@ -174,6 +254,12 @@ struct i830_sdvo_preferred_input_timing_
 # define SDVO_DTD_SDVO_FLAG_SCALING_MASK			(3 << 4)
 # define SDVO_DTD_VSYNC_OFF_HIGH			SDVO_I2C_ARG_6
 
+/**
+ * Generates a DTD based on the given width, height, and flags.
+ *
+ * This will be supported by any device supporting scaling or interlaced
+ * modes.
+ */
 #define SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING		0x1a
 # define SDVO_PREFERRED_INPUT_TIMING_CLOCK_LOW		SDVO_I2C_ARG_0
 # define SDVO_PREFERRED_INPUT_TIMING_CLOCK_HIGH		SDVO_I2C_ARG_1
@@ -193,15 +279,16 @@ struct i830_sdvo_preferred_input_timing_
 /** Returns a struct i830_sdvo_pixel_clock_range */
 #define SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE		0x1e
 
+/** Returns a byte bitfield containing SDVO_CLOCK_RATE_MULT_* flags */
 #define SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS		0x1f
 
+/** Returns a byte containing a SDVO_CLOCK_RATE_MULT_* flag */
 #define SDVO_CMD_GET_CLOCK_RATE_MULT			0x20
+/** Takes a byte containing a SDVO_CLOCK_RATE_MULT_* flag */
 #define SDVO_CMD_SET_CLOCK_RATE_MULT			0x21
 # define SDVO_CLOCK_RATE_MULT_1X				(1 << 0)
 # define SDVO_CLOCK_RATE_MULT_2X				(1 << 1)
-# define SDVO_CLOCK_RATE_MULT_3X				(1 << 2)
 # define SDVO_CLOCK_RATE_MULT_4X				(1 << 3)
-# define SDVO_CLOCK_RATE_MULT_5X				(1 << 4)
 
 #define SDVO_CMD_GET_SUPPORTED_TV_FORMATS		0x27
 
diff-tree e7d546cac06767ec58325396a3bb5780b2257c53 (from 2ca57040b0cd24ad3dbe693789091e28be4e69f8)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Oct 30 11:24:43 2006 -0800

    Remove some dead code from BIOS modesetting.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 609e1b5..f142c4b 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -300,10 +300,6 @@ static void i830AdjustFrame(int scrnInde
 static Bool I830CloseScreen(int scrnIndex, ScreenPtr pScreen);
 static Bool I830SaveScreen(ScreenPtr pScreen, int unblack);
 static Bool I830EnterVT(int scrnIndex, int flags);
-#if 0
-static Bool I830VESASetVBEMode(ScrnInfoPtr pScrn, int mode,
-			       VbeCRTCInfoBlock *block);
-#endif
 static CARD32 I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg);
 
 extern int I830EntityIndex;
@@ -398,28 +394,6 @@ I830ProbeDDC(ScrnInfoPtr pScrn, int inde
    ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
 }
 
-/* Various extended video BIOS functions. 
- * 100 and 120Hz aren't really supported, they work but only get close
- * to the requested refresh, and really not close enough.
- * I've seen 100Hz come out at 104Hz, and 120Hz come out at 128Hz */
-const int i830refreshes[] = {
-   43, 56, 60, 70, 72, 75, 85 /* 100, 120 */
-};
-static const int nrefreshes = sizeof(i830refreshes) / sizeof(i830refreshes[0]);
-
-struct panelid {
-	short hsize;
-	short vsize;
-	short fptype;
-	char redbpp;
-	char greenbpp;
-	char bluebpp;
-	char reservedbpp;
-	int rsvdoffscrnmemsize;
-	int rsvdoffscrnmemptr;
-	char reserved[14];
-};
-
 /*
  * Returns a string matching the device corresponding to the first bit set
  * in "device".  savedDevice is then set to device with that bit cleared.
@@ -760,73 +734,6 @@ I830LoadPalette(ScrnInfoPtr pScrn, int n
       pI830->CursorInfoRec->ShowCursor(pScrn);
 }
 
-#if 0
-static int
-I830UseDDC(ScrnInfoPtr pScrn)
-{
-   xf86MonPtr DDC = (xf86MonPtr)(pScrn->monitor->DDC);
-   struct detailed_monitor_section* detMon;
-   struct monitor_ranges *mon_range = NULL;
-   int i;
-
-   if (!DDC) return 0;
-
-   /* Now change the hsync/vrefresh values of the current monitor to
-    * match those of DDC */
-   for (i = 0; i < 4; i++) {
-      detMon = &DDC->det_mon[i];
-      if(detMon->type == DS_RANGES)
-         mon_range = &detMon->section.ranges;
-   }
-
-   if (!mon_range || mon_range->min_h == 0 || mon_range->max_h == 0 ||
-		     mon_range->min_v == 0 || mon_range->max_v == 0)
-      return 0;	/* bad ddc */
-
-   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using detected DDC timings\n");
-   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\tHorizSync %d-%d\n", 
-		mon_range->min_h, mon_range->max_h);
-   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\tVertRefresh %d-%d\n", 
-		mon_range->min_v, mon_range->max_v);
-#define DDC_SYNC_TOLERANCE SYNC_TOLERANCE
-   if (pScrn->monitor->nHsync > 0) {
-      for (i = 0; i < pScrn->monitor->nHsync; i++) {
-         if ((1.0 - DDC_SYNC_TOLERANCE) * mon_range->min_h >
-				pScrn->monitor->hsync[i].lo ||
-	     (1.0 + DDC_SYNC_TOLERANCE) * mon_range->max_h <
-				pScrn->monitor->hsync[i].hi) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-			  "config file hsync range %g-%gkHz not within DDC "
-			  "hsync range %d-%dkHz\n",
-			  pScrn->monitor->hsync[i].lo, pScrn->monitor->hsync[i].hi,
-			  mon_range->min_h, mon_range->max_h);
-         }
-         pScrn->monitor->hsync[i].lo = mon_range->min_h;
-	 pScrn->monitor->hsync[i].hi = mon_range->max_h;
-      }
-   }
-
-   if (pScrn->monitor->nVrefresh > 0) {
-      for (i=0; i<pScrn->monitor->nVrefresh; i++) {
-         if ((1.0 - DDC_SYNC_TOLERANCE) * mon_range->min_v >
-				pScrn->monitor->vrefresh[i].lo ||
-	     (1.0 + DDC_SYNC_TOLERANCE) * mon_range->max_v <
-				pScrn->monitor->vrefresh[i].hi) {
-   	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-			  "config file vrefresh range %g-%gHz not within DDC "
-			  "vrefresh range %d-%dHz\n",
-			  pScrn->monitor->vrefresh[i].lo, pScrn->monitor->vrefresh[i].hi,
-			  mon_range->min_v, mon_range->max_v);
-         }
-         pScrn->monitor->vrefresh[i].lo = mon_range->min_v;
-         pScrn->monitor->vrefresh[i].hi = mon_range->max_v;
-      }
-   }
-
-   return mon_range->max_clock;
-}
-#endif
-
 /**
  * Set up the outputs according to what type of chip we are.
  *
diff --git a/src/i830_gtf.c b/src/i830_gtf.c
index 663a2f4..523e167 100644
--- a/src/i830_gtf.c
+++ b/src/i830_gtf.c
@@ -67,8 +67,6 @@
 #define C_PRIME           (((C - J) * K/256.0) + J)
 #define M_PRIME           (K/256.0 * M)
 
-extern const int i830refreshes[];
-
 DisplayModePtr
 i830GetGTF(int h_pixels, int v_lines, float freq, int interlaced, int margins)
 {
diff --git a/src/i830_modes.c b/src/i830_modes.c
index f430693..633ac83 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -99,8 +99,6 @@ static struct
 
 #define DEBUG_REPROBE 1
 
-extern const int i830refreshes[];
-
 void
 I830PrintModes(ScrnInfoPtr scrp)
 {
diff-tree 2ca57040b0cd24ad3dbe693789091e28be4e69f8 (from 837b2f632062bc29268f109895a577bd90cabd6d)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Oct 30 11:19:19 2006 -0800

    Remove GetBIOSVersion().
    
    This info hardly useful now that we don't use the BIOS for mode setting.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 29c3ba3..609e1b5 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -407,27 +407,6 @@ const int i830refreshes[] = {
 };
 static const int nrefreshes = sizeof(i830refreshes) / sizeof(i830refreshes[0]);
 
-static Bool
-Check5fStatus(ScrnInfoPtr pScrn, int func, int ax)
-{
-   if (ax == 0x005f)
-      return TRUE;
-   else if (ax == 0x015f) {
-      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		 "Extended BIOS function 0x%04x failed.\n", func);
-      return FALSE;
-   } else if ((ax & 0xff) != 0x5f) {
-      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		 "Extended BIOS function 0x%04x not supported.\n", func);
-      return FALSE;
-   } else {
-      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		 "Extended BIOS function 0x%04x returns 0x%04x.\n",
-		 func, ax & 0xffff);
-      return FALSE;
-   }
-}
-
 struct panelid {
 	short hsize;
 	short vsize;
@@ -441,26 +420,6 @@ struct panelid {
 	char reserved[14];
 };
 
-static Bool
-GetBIOSVersion(ScrnInfoPtr pScrn, unsigned int *version)
-{
-   vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
-
-   DPRINTF(PFX, "GetBIOSVersion\n");
-
-   pVbe->pInt10->num = 0x10;
-   pVbe->pInt10->ax = 0x5f01;
-
-   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
-   if (Check5fStatus(pScrn, 0x5f01, pVbe->pInt10->ax)) {
-      *version = pVbe->pInt10->bx;
-      return TRUE;
-   }
-
-   *version = 0;
-   return FALSE;
-}
-
 /*
  * Returns a string matching the device corresponding to the first bit set
  * in "device".  savedDevice is then set to device with that bit cleared.
@@ -1062,8 +1021,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    pointer pVBEModule = NULL;
    Bool enable;
    const char *chipname;
-   unsigned int ver;
-   char v[5];
 
    if (pScrn->numEntities != 1)
       return FALSE;
@@ -1882,18 +1839,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       }
    }
 
-   GetBIOSVersion(pScrn, &ver);
-
-   v[0] = (ver & 0xff000000) >> 24;
-   v[1] = (ver & 0x00ff0000) >> 16;
-   v[2] = (ver & 0x0000ff00) >> 8;
-   v[3] = (ver & 0x000000ff) >> 0;
-   v[4] = 0;
-   
-   pI830->bios_version = atoi(v);
-
-   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIOS Build: %d\n",pI830->bios_version);
-
    if (IS_I9XX(pI830))
       pI830->newPipeSwitch = TRUE;
    else
diff-tree 837b2f632062bc29268f109895a577bd90cabd6d (from bca9e6ccbd14eb8f2f103e8e64b28a623113d494)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Oct 30 11:17:55 2006 -0800

    Warning fix.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 688d970..29c3ba3 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -621,7 +621,7 @@ I830DetectMemory(ScrnInfoPtr pScrn)
    vbeInfo = VBEGetVBEInfo(pI830->pVbe);
    if (vbeInfo != NULL && vbeInfo->TotalMemory != memsize / 1024 / 64) {
       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		 "Detected stolen memory (%ld kB) doesn't match what the BIOS"
+		 "Detected stolen memory (%d kB) doesn't match what the BIOS"
 		 " reports (%d kB)\n",
 		 ROUND_DOWN_TO(memsize / 1024, 64),
 		 vbeInfo->TotalMemory * 64);
diff-tree bca9e6ccbd14eb8f2f103e8e64b28a623113d494 (from 819a47b27cd4728feb269a08be32403304993ffa)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Oct 30 11:17:27 2006 -0800

    Remove SetPipeAccess and now-unnecessary VBE reinit.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 5494abb..688d970 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -305,7 +305,6 @@ static Bool I830VESASetVBEMode(ScrnInfoP
 			       VbeCRTCInfoBlock *block);
 #endif
 static CARD32 I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg);
-static Bool SetPipeAccess(ScrnInfoPtr pScrn);
 
 extern int I830EntityIndex;
 
@@ -443,49 +442,6 @@ struct panelid {
 };
 
 static Bool
-SetBIOSPipe(ScrnInfoPtr pScrn, int pipe)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   vbeInfoPtr pVbe = pI830->pVbe;
-
-   DPRINTF(PFX, "SetBIOSPipe: pipe 0x%x\n", pipe);
-
-   /* single pipe machines should always return TRUE */
-   if (pI830->availablePipes == 1) return TRUE;
-
-   pVbe->pInt10->num = 0x10;
-   pVbe->pInt10->ax = 0x5f1c;
-   if (pI830->newPipeSwitch) {
-      pVbe->pInt10->bx = pipe;
-      pVbe->pInt10->cx = 0;
-   } else {
-      pVbe->pInt10->bx = 0x0;
-      pVbe->pInt10->cx = pipe << 8;
-   }
-
-   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
-   if (Check5fStatus(pScrn, 0x5f1c, pVbe->pInt10->ax)) {
-      return TRUE;
-   }
-	
-   return FALSE;
-}
-
-static Bool
-SetPipeAccess(ScrnInfoPtr pScrn)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-
-   /* Don't try messing with the pipe, unless we're dual head */
-   if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone || pI830->origPipe != pI830->pipe) {
-      if (!SetBIOSPipe(pScrn, pI830->pipe))
-         return FALSE;
-   }
-   
-   return TRUE;
-}
-
-static Bool
 GetBIOSVersion(ScrnInfoPtr pScrn, unsigned int *version)
 {
    vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
@@ -3219,24 +3175,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       pI830->used3D = pI8301->used3D;
    }
 
-   /*
-    * If we're changing the BIOS's view of the video memory size, do that
-    * first, then re-initialise the VBE information.
-    */
-   if (I830IsPrimary(pScrn)) {
-      SetPipeAccess(pScrn);
-      if (pI830->pVbe)
-         vbeFree(pI830->pVbe);
-      pI830->pVbe = VBEInit(NULL, pI830->pEnt->index);
-   } else {
-      pI830->pVbe = pI8301->pVbe;
-   }
-
-   if (!pI830->pVbe)
-      return FALSE;
-
-   SetPipeAccess(pScrn);
-
    miClearVisualTypes();
    if (!miSetVisualTypes(pScrn->depth,
 			    miGetDefaultVisualMask(pScrn->depth),
diff-tree 819a47b27cd4728feb269a08be32403304993ffa (from 71545db4614cfc4650acc4325912474e777c3b36)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Oct 30 09:50:33 2006 -0800

    Use the new fields for SDVO pixel multiply on the G965.
    
    This should fix display at resolutions/refresh rates in a different multiplier
    class than the console display (generally, high resolution modes).

diff --git a/src/i810_reg.h b/src/i810_reg.h
index a80b66e..bc6c0f8 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -799,10 +799,56 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 # define PLL_REF_INPUT_TVCLKINBC		(2 << 13)
 # define PLLB_REF_INPUT_SPREADSPECTRUMIN	(3 << 13)
 # define DISPLAY_RATE_SELECT_FPA1		(1 << 8)
+/**
+ * SDVO multiplier for 945G/GM.
+ *
+ * \sa DPLL_MD_UDI_MULTIPLIER_MASK
+ */
 # define SDVO_MULTIPLIER_MASK			0x000000ff
 # define SDVO_MULTIPLIER_SHIFT_HIRES		4
 # define SDVO_MULTIPLIER_SHIFT_VGA		0
 
+/** @defgroup DPLL_MD
+ * @{
+ */
+/** Pipe A SDVO/UDI clock multiplier/divider register for G965. */
+#define DPLL_A_MD		0x0601c
+/** Pipe B SDVO/UDI clock multiplier/divider register for G965. */
+#define DPLL_B_MD		0x06020
+/**
+ * UDI pixel divider, controlling how many pixels are stuffed into a packet.
+ *
+ * Value is pixels minus 1.  Must be set to 1 pixel for SDVO.
+ */
+# define DPLL_MD_UDI_DIVIDER_MASK		0x3f000000
+# define DPLL_MD_UDI_DIVIDER_SHIFT		24
+/** UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */
+# define DPLL_MD_VGA_UDI_DIVIDER_MASK		0x003f0000
+# define DPLL_MD_VGA_UDI_DIVIDER_SHIFT		16
+/**
+ * SDVO/UDI pixel multiplier.
+ *
+ * SDVO requires that the bus clock rate be between 1 and 2 Ghz, and the bus
+ * clock rate is 10 times the DPLL clock.  At low resolution/refresh rate
+ * modes, the bus rate would be below the limits, so SDVO allows for stuffing
+ * dummy bytes in the datastream at an increased clock rate, with both sides of
+ * the link knowing how many bytes are fill.
+ *
+ * So, for a mode with a dotclock of 65Mhz, we would want to double the clock
+ * rate to 130Mhz to get a bus rate of 1.30Ghz.  The DPLL clock rate would be
+ * set to 130Mhz, and the SDVO multiplier set to 2x in this register and
+ * through an SDVO command.
+ *
+ * This register field has values of multiplication factor minus 1, with
+ * a maximum multiplier of 5 for SDVO.
+ */
+# define DPLL_MD_UDI_MULTIPLIER_MASK		0x00003f00
+# define DPLL_MD_UDI_MULTIPLIER_SHIFT		8
+/** SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK. */
+# define DPLL_MD_VGA_UDI_MULTIPLIER_MASK	0x0000003f
+# define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT	0
+/** @} */
+
 #define BLC_PWM_CTL		0x61254
 #define BACKLIGHT_MODULATION_FREQ_SHIFT		(17)
 #define BACKLIGHT_MODULATION_FREQ_MASK		(0x7fff << 17)
@@ -842,7 +888,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define SDVO_PIPE_B_SELECT			(1 << 30)
 #define SDVO_STALL_SELECT			(1 << 29)
 #define SDVO_INTERRUPT_ENABLE			(1 << 26)
-/* Programmed value is multiplier - 1, up to 5x.  alv, gdg only */
+/**
+ * 915G/GM SDVO pixel multiplier.
+ *
+ * Programmed value is multiplier - 1, up to 5x.
+ *
+ * \sa DPLL_MD_UDI_MULTIPLIER_MASK
+ */
 #define SDVO_PORT_MULTIPLY_MASK			(7 << 23)
 #define SDVO_PORT_MULTIPLY_SHIFT		23
 #define SDVO_PHASE_SELECT_MASK			(15 << 19)
diff --git a/src/i830.h b/src/i830.h
index 3f4eacc..40c8cce 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -509,6 +509,7 @@ typedef struct _I830Rec {
    CARD32 saveFPA0;
    CARD32 saveFPA1;
    CARD32 saveDPLL_A;
+   CARD32 saveDPLL_A_MD;
    CARD32 saveHTOTAL_A;
    CARD32 saveHBLANK_A;
    CARD32 saveHSYNC_A;
@@ -523,6 +524,7 @@ typedef struct _I830Rec {
    CARD32 saveFPB0;
    CARD32 saveFPB1;
    CARD32 saveDPLL_B;
+   CARD32 saveDPLL_B_MD;
    CARD32 saveHTOTAL_B;
    CARD32 saveHBLANK_B;
    CARD32 saveHSYNC_B;
diff --git a/src/i830_display.c b/src/i830_display.c
index a94e21d..41f8c21 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -472,11 +472,8 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	}
     }
 
-    /* In SDVO, we need to keep the clock on the bus between 1Ghz and 2Ghz.
-     * The clock on the bus is 10 times the pixel clock normally.  If that
-     * would be too low, we run the DPLL at a multiple of the pixel clock, and
-     * tell the SDVO device the multiplier so it can throw away the dummy
-     * bytes.
+    /* Adjust the clock for pixel multiplication.
+     * See DPLL_MD_UDI_MULTIPLIER_MASK.
      */
     if (is_sdvo) {
 	pixel_clock *= i830_sdvo_get_pixel_multiplier(pMode);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 10c6f09..5494abb 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2506,6 +2506,8 @@ SaveHWState(ScrnInfoPtr pScrn)
    pI830->saveFPA0 = INREG(FPA0);
    pI830->saveFPA1 = INREG(FPA1);
    pI830->saveDPLL_A = INREG(DPLL_A);
+   if (IS_I965G(pI830))
+      pI830->saveDPLL_A_MD = INREG(DPLL_A_MD);
    pI830->saveHTOTAL_A = INREG(HTOTAL_A);
    pI830->saveHBLANK_A = INREG(HBLANK_A);
    pI830->saveHSYNC_A = INREG(HSYNC_A);
@@ -2528,6 +2530,8 @@ SaveHWState(ScrnInfoPtr pScrn)
       pI830->saveFPB0 = INREG(FPB0);
       pI830->saveFPB1 = INREG(FPB1);
       pI830->saveDPLL_B = INREG(DPLL_B);
+      if (IS_I965G(pI830))
+	 pI830->saveDPLL_B_MD = INREG(DPLL_B_MD);
       pI830->saveHTOTAL_B = INREG(HTOTAL_B);
       pI830->saveHBLANK_B = INREG(HBLANK_B);
       pI830->saveHSYNC_B = INREG(HSYNC_B);
@@ -2611,6 +2615,8 @@ RestoreHWState(ScrnInfoPtr pScrn)
    OUTREG(FPA0, pI830->saveFPA0);
    OUTREG(FPA1, pI830->saveFPA1);
    OUTREG(DPLL_A, pI830->saveDPLL_A);
+   if (IS_I965G(pI830))
+      OUTREG(DPLL_A_MD, pI830->saveDPLL_A_MD);
    OUTREG(HTOTAL_A, pI830->saveHTOTAL_A);
    OUTREG(HBLANK_A, pI830->saveHBLANK_A);
    OUTREG(HSYNC_A, pI830->saveHSYNC_A);
@@ -2630,6 +2636,8 @@ RestoreHWState(ScrnInfoPtr pScrn)
       OUTREG(FPB0, pI830->saveFPB0);
       OUTREG(FPB1, pI830->saveFPB1);
       OUTREG(DPLL_B, pI830->saveDPLL_B);
+      if (IS_I965G(pI830))
+	 OUTREG(DPLL_B_MD, pI830->saveDPLL_B_MD);
       OUTREG(HTOTAL_B, pI830->saveHTOTAL_B);
       OUTREG(HBLANK_B, pI830->saveHBLANK_B);
       OUTREG(HSYNC_B, pI830->saveHSYNC_B);
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 87453b9..bbc1c72 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -600,6 +600,7 @@ i830_sdvo_post_set_mode(ScrnInfoPtr pScr
     Bool out1, out2, input1, input2;
     CARD32 dpll, sdvob, sdvoc;
     int dpll_reg = (output->pipe == 0) ? DPLL_A : DPLL_B;
+    int dpll_md_reg = (output->pipe == 0) ? DPLL_A_MD : DPLL_B_MD;
     int sdvo_pixel_multiply;
     CARD8 status;
 
@@ -630,10 +631,14 @@ i830_sdvo_post_set_mode(ScrnInfoPtr pScr
     dpll = INREG(dpll_reg);
 
     sdvo_pixel_multiply = i830_sdvo_get_pixel_multiplier(mode);
-    if (IS_I945G(pI830) || IS_I945GM(pI830))
+    if (IS_I965G(pI830)) {
+	OUTREG(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) |
+	       ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT));
+    } else if (IS_I945G(pI830) || IS_I945GM(pI830)) {
 	dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
-    else
+    } else {
 	sdvob |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT;
+    }
 
     OUTREG(dpll_reg, dpll | DPLL_DVO_HIGH_SPEED);
 
diff-tree 71545db4614cfc4650acc4325912474e777c3b36 (from c357eca10ca1c535d305e1f3028471a912ae4102)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Oct 30 09:46:10 2006 -0800

    Return and use valid status bits for i830_sdvo_get_trained_inputs().

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index ac5ae48..87453b9 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -277,7 +277,7 @@ i830_sdvo_get_trained_inputs(I830OutputP
 
     i830_sdvo_write_cmd(output, SDVO_CMD_GET_TRAINED_INPUTS, NULL, 0);
 
-    i830_sdvo_read_response(output, response, 2);
+    status = i830_sdvo_read_response(output, response, 2);
     if (status != SDVO_CMD_STATUS_SUCCESS)
 	return FALSE;
 
@@ -607,7 +607,7 @@ i830_sdvo_post_set_mode(ScrnInfoPtr pScr
     /* two 03s, 04 05, 10, 1d */
     /* these contain the height and mode clock / 10 by the looks of it */
 
-    i830_sdvo_get_trained_inputs(output, &input1, &input2);
+    status = i830_sdvo_get_trained_inputs(output, &input1, &input2);
 
     /* Warn if the device reported failure to sync. */
     if (status == SDVO_CMD_STATUS_SUCCESS && !input1) {
diff-tree c357eca10ca1c535d305e1f3028471a912ae4102 (from 3ab9f5a4a8cd62c8a8c2a09d3d105adbe815a83d)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Oct 30 09:44:55 2006 -0800

    Clean up whitespace in i830_randr.c.

diff --git a/src/i830_randr.c b/src/i830_randr.c
index e4075f2..f64f3da 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -58,7 +58,7 @@ typedef struct _i830RandRInfo {
     DisplayModePtr  		    modes[MAX_DISPLAY_PIPES];
 #endif
 } XF86RandRInfoRec, *XF86RandRInfoPtr;
-    
+
 #ifdef RANDR_12_INTERFACE
 static Bool I830RandRInit12 (ScreenPtr pScreen);
 static Bool I830RandRCreateScreenResources12 (ScreenPtr pScreen);
@@ -67,7 +67,8 @@ static Bool I830RandRCreateScreenResourc
 static int	    i830RandRIndex;
 static int	    i830RandRGeneration;
 
-#define XF86RANDRINFO(p)    ((XF86RandRInfoPtr) (p)->devPrivates[i830RandRIndex].ptr)
+#define XF86RANDRINFO(p) \
+	((XF86RandRInfoPtr)(p)->devPrivates[i830RandRIndex].ptr)
 
 static int
 I830RandRModeRefresh (DisplayModePtr mode)
@@ -87,10 +88,10 @@ I830RandRGetInfo (ScreenPtr pScreen, Rot
     DisplayModePtr	    mode;
     int			    refresh0 = 60;
     int			    maxX = 0, maxY = 0;
-    
+
     *rotations = randrp->supported_rotations;
 
-    if (randrp->virtualX == -1 || randrp->virtualY == -1) 
+    if (randrp->virtualX == -1 || randrp->virtualY == -1)
     {
 	randrp->virtualX = scrp->virtualX;
 	randrp->virtualY = scrp->virtualY;
@@ -133,7 +134,7 @@ I830RandRGetInfo (ScreenPtr pScreen, Rot
 	randrp->maxX = maxX;
 	randrp->maxY = maxY;
     }
-   
+
     if (scrp->currentMode->HDisplay != randrp->virtualX ||
 	scrp->currentMode->VDisplay != randrp->virtualY)
     {
@@ -144,7 +145,7 @@ I830RandRGetInfo (ScreenPtr pScreen, Rot
 	if (!pSize)
 	    return FALSE;
 	RRRegisterRate (pScreen, pSize, refresh0);
-	if (scrp->virtualX == randrp->virtualX && 
+	if (scrp->virtualX == randrp->virtualX &&
 	    scrp->virtualY == randrp->virtualY)
 	{
 	    RRSetCurrentConfig (pScreen, randrp->rotation, refresh0, pSize);
@@ -171,7 +172,7 @@ I830RandRSetMode (ScreenPtr	    pScreen,
     DisplayModePtr      currentMode = NULL;
     Bool 		ret = TRUE;
     PixmapPtr 		pspix = NULL;
-    
+
     if (pRoot)
 	(*scrp->EnableDisableFBAccess) (pScreen->myNum, FALSE);
     if (useVirtual)
@@ -227,7 +228,7 @@ I830RandRSetMode (ScreenPtr	    pScreen,
     pspix = (*pScreen->GetScreenPixmap) (pScreen);
     if (pspix->devPrivate.ptr)
        scrp->pixmapPrivate = pspix->devPrivate;
-    
+
     /*
      * Make sure the layout is correct
      */
@@ -259,7 +260,7 @@ I830RandRSetConfig (ScreenPtr		pScreen,
 
     randrp->rotation = rotation;
 
-    if (randrp->virtualX == -1 || randrp->virtualY == -1) 
+    if (randrp->virtualX == -1 || randrp->virtualY == -1)
     {
 	randrp->virtualX = scrp->virtualX;
 	randrp->virtualY = scrp->virtualY;
@@ -275,7 +276,7 @@ I830RandRSetConfig (ScreenPtr		pScreen,
 		if (maxY < mode->VDisplay)
 			maxY = mode->VDisplay;
 	}
-	if (mode->HDisplay == pSize->width && 
+	if (mode->HDisplay == pSize->width &&
 	    mode->VDisplay == pSize->height &&
 	    (rate == 0 || I830RandRModeRefresh (mode) == rate))
 	    break;
@@ -303,7 +304,8 @@ I830RandRSetConfig (ScreenPtr		pScreen,
 	randrp->maxY = maxY;
     }
 
-    if (!I830RandRSetMode (pScreen, mode, useVirtual, pSize->mmWidth, pSize->mmHeight)) {
+    if (!I830RandRSetMode (pScreen, mode, useVirtual, pSize->mmWidth,
+			   pSize->mmHeight)) {
         randrp->rotation = oldRotation;
 	return FALSE;
     }
@@ -361,17 +363,17 @@ I830RandRCreateScreenResources (ScreenPt
 	pI830->starting = TRUE; /* abuse this for dual head & rotation */
 	I830RandRSetConfig (pScreen, requestedRotation, 0, &p);
 	pI830->starting = FALSE;
-    } 
+    }
     return TRUE;
 }
-    
-    
+
+
 Bool
 I830RandRInit (ScreenPtr    pScreen, int rotation)
 {
     rrScrPrivPtr	rp;
     XF86RandRInfoPtr	randrp;
-    
+
 #ifdef PANORAMIX
     /* XXX disable RandR when using Xinerama */
     if (!noPanoramiXExtension)
@@ -382,11 +384,11 @@ I830RandRInit (ScreenPtr    pScreen, int
 	i830RandRIndex = AllocateScreenPrivateIndex();
 	i830RandRGeneration = serverGeneration;
     }
-    
+
     randrp = xalloc (sizeof (XF86RandRInfoRec));
     if (!randrp)
 	return FALSE;
-			
+
     if (!RRScreenInit(pScreen))
     {
 	xfree (randrp);
@@ -400,7 +402,7 @@ I830RandRInit (ScreenPtr    pScreen, int
     randrp->virtualY = -1;
     randrp->mmWidth = pScreen->mmWidth;
     randrp->mmHeight = pScreen->mmHeight;
-    
+
     randrp->rotation = RR_Rotate_0; /* initial rotated mode */
 
     randrp->supported_rotations = rotation;
@@ -446,8 +448,8 @@ I830RandRScreenSetSize (ScreenPtr	pScree
     ScrnInfoPtr		pScrn = XF86SCRNINFO(pScreen);
     WindowPtr		pRoot = WindowTable[pScreen->myNum];
     Bool 		ret = TRUE;
-    
-    if (randrp->virtualX == -1 || randrp->virtualY == -1) 
+
+    if (randrp->virtualX == -1 || randrp->virtualY == -1)
     {
 	randrp->virtualX = pScrn->virtualX;
 	randrp->virtualY = pScrn->virtualY;
@@ -461,7 +463,7 @@ I830RandRScreenSetSize (ScreenPtr	pScree
     pScreen->height = pScrn->virtualY;
     pScreen->mmWidth = mmWidth;
     pScreen->mmHeight = mmHeight;
-    
+
     xf86SetViewport (pScreen, pScreen->width, pScreen->height);
     xf86SetViewport (pScreen, 0, 0);
     if (pRoot)
@@ -490,7 +492,7 @@ I830RandRCrtcNotify (RRCrtcPtr	crtc)
     int			i, j;
     DisplayModePtr	pipeMode = &pI830->pipeCurMode[pipe];
     int			pipe_type;
-    
+
     x = pI830->pipeX[pipe];
     y = pI830->pipeY[pipe];
     rotation = RR_Rotate_0;
@@ -533,7 +535,7 @@ I830RandRCrtcNotify (RRCrtcPtr	crtc)
     }
     return RRCrtcNotify (crtc, mode, x, y, rotation, numOutputs, outputs);
 }
-    
+
 static Bool
 I830RandRCrtcSet (ScreenPtr	pScreen,
 		  RRCrtcPtr	crtc,
@@ -549,7 +551,7 @@ I830RandRCrtcSet (ScreenPtr	pScreen,
     I830Ptr		pI830 = I830PTR(pScrn);
     int			pipe = (int) (crtc->devPrivate);
     DisplayModePtr	display_mode = mode ? mode->devPrivate : NULL;
-    
+
     /* Sync the engine before adjust mode */
     if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
 	(*pI830->AccelInfoRec->Sync)(pScrn);
@@ -619,13 +621,13 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
     RRModePtr		rrmode, *rrmodes;
     CARD32		possibleOptions = 0;
     CARD32		currentOptions = 0;
-    
-    if (randrp->virtualX == -1 || randrp->virtualY == -1) 
+
+    if (randrp->virtualX == -1 || randrp->virtualY == -1)
     {
 	randrp->virtualX = pScrn->virtualX;
 	randrp->virtualY = pScrn->virtualY;
     }
-    RRScreenSetSizeRange (pScreen, 320, 240, 
+    RRScreenSetSizeRange (pScreen, 320, 240,
 			  randrp->virtualX, randrp->virtualY);
     for (i = 0; i < pI830->num_outputs; i++)
     {
@@ -697,17 +699,17 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
 	    return FALSE;
 
 	RROutputSetCrtc (randrp->outputs[i], crtc);
-    
+
 	RROutputSetPossibleOptions (randrp->outputs[i], possibleOptions);
 	RROutputSetCurrentOptions (randrp->outputs[i], currentOptions);
         nmode = 0;
 	npreferred = 0;
 	rrmodes = NULL;
-	if (pipe >= 0) 
+	if (pipe >= 0)
 	{
 	    MonPtr  mon = pI830->pipeMon[pipe];
 	    modes = mon->Modes;
-	
+
 	    for (mode = modes; mode; mode = mode->next)
 		nmode++;
 
@@ -726,20 +728,20 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
 			    modeInfo.nameLength = strlen (mode->name);
 			    modeInfo.mmWidth = mon->widthmm;
 			    modeInfo.mmHeight = mon->heightmm;
-	
+
 			    modeInfo.width = mode->HDisplay;
 			    modeInfo.dotClock = mode->Clock * 1000;
 			    modeInfo.hSyncStart = mode->HSyncStart;
 			    modeInfo.hSyncEnd = mode->HSyncEnd;
 			    modeInfo.hTotal = mode->HTotal;
 			    modeInfo.hSkew = mode->HSkew;
-	
+
 			    modeInfo.height = mode->VDisplay;
 			    modeInfo.vSyncStart = mode->VSyncStart;
 			    modeInfo.vSyncEnd = mode->VSyncEnd;
 			    modeInfo.vTotal = mode->VTotal;
 			    modeInfo.modeFlags = mode->Flags;
-	
+
 			    rrmode = RRModeGet (pScreen, &modeInfo, mode->name);
 			    rrmode->devPrivate = mode;
 			    if (rrmode)
@@ -752,21 +754,21 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
 		}
 	    }
 	}
-	
+
     	if (!RROutputSetModes (randrp->outputs[i], rrmodes, nmode, npreferred))
 	{
     	    xfree (rrmodes);
 	    return FALSE;
 	}
-	
+
 	xfree (rrmodes);
-	
+
 	connection = RR_Disconnected;
 	if (pipe >= 0)
 	    connection = RR_Connected;
 
 	RROutputSetConnection (randrp->outputs[i], connection);
-	    
+
 	RROutputSetSubpixelOrder (randrp->outputs[i], subpixel);
 
 	/*
@@ -786,7 +788,7 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
     return TRUE;
 }
 
-    
+
 /*
  * Query the hardware for the current state, then mirror
  * that to RandR
@@ -828,7 +830,7 @@ I830RandRCreateScreenResources12 (Screen
 					     name, strlen (name),
 					     (void *) i);
     }
-    
+
     mode = pScrn->currentMode;
     if (mode)
     {
@@ -852,10 +854,10 @@ I830RandRCreateScreenResources12 (Screen
 				mmWidth,
 				mmHeight);
     }
-			    
+
     for (i = 0; i < MAX_DISPLAY_PIPES; i++)
 	i830PipeSetBase(pScrn, i, 0, 0);
-	
+
     return I830RandRSetInfo12 (pScreen);
 }
 
diff-tree 25e6e497824a23eb231fc6fd6e483f601d612cee (from 0bdcce2e4541c6e441c44aad49254ad3093cedb2)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Oct 26 15:47:49 2006 -0700

    Major cleanup of 3D invariant state, fixing hangs with rotation and render.
    
    Now, the generic invariant state is always set while the X Server is active,
    and happens automatically when the X Server grabs the DRI lock.  More 3D state
    is moved to the generic code.
    
    Then, the 3D consumers (video, rotation, render) set last_3d to their enum
    entry, and can update their own invariant state when another consumer was
    active.

diff --git a/src/i830.h b/src/i830.h
index df1c171..9c37068 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -192,6 +192,13 @@ typedef struct _region {
     int x0,x1,y0,y1;
 } region;
 
+/** 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 _I830Rec {
    unsigned char *MMIOBase;
@@ -453,6 +460,8 @@ typedef struct _I830Rec {
 
    CARD32 savedAsurf;
    CARD32 savedBsurf;
+
+    enum last_3d last_3d;
 } I830Rec;
 
 #define I830PTR(p) ((I830Ptr)((p)->driverPrivate))
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 8a52750..b844d33 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1000,6 +1000,8 @@ I830DRISwapContext(ScreenPtr pScreen, DR
       if (I810_DEBUG & DEBUG_VERBOSE_DRI)
 	 ErrorF("i830DRISwapContext (in)\n");
 
+      pI830->last_3d = LAST_3D_OTHER;
+
       if (!pScrn->vtSema)
      	 return;
       pI830->LockHeld = 1;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index f9ca77c..12fc524 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -7041,10 +7041,23 @@ IntelEmitInvarientState(ScrnInfoPtr pScr
 {
    I830Ptr pI830 = I830PTR(pScrn);
    CARD32 ctx_addr;
+#ifdef XF86DRI
+   drmI830Sarea *sarea;
+#endif
 
    if (pI830->noAccel)
       return;
 
+#ifdef XF86DRI
+   if (pI830->directRenderingEnabled) {
+      sarea = DRIGetSAREAPrivate(pScrn->pScreen);
+
+      /* Mark that the X Server was the last holder of the context */
+      if (sarea)
+	 sarea->ctxOwner = DRIGetContext(pScrn->pScreen);
+   }
+#endif
+
    ctx_addr = pI830->ContextMem.Start;
    /* Align to a 2k boundry */
    ctx_addr = ((ctx_addr + 2048 - 1) / 2048) * 2048;
diff --git a/src/i830_exa_render.c b/src/i830_exa_render.c
index 86e11d2..f63313f 100644
--- a/src/i830_exa_render.c
+++ b/src/i830_exa_render.c
@@ -404,6 +404,8 @@ I830EXAPrepareComposite(int op, PictureP
     dst_offset = exaGetPixmapOffset(pDst);
     dst_pitch = exaGetPixmapPitch(pDst);
 
+    pI830->last_3d = LAST_3D_RENDER;
+
     if (!I830TextureSetup(pSrcPicture, pSrc, 0))
 	I830FALLBACK("fail to setup src texture\n");
     if (pMask != NULL) {
diff --git a/src/i830_rotate.c b/src/i830_rotate.c
index 76effa2..3cdb3ae 100644
--- a/src/i830_rotate.c
+++ b/src/i830_rotate.c
@@ -211,11 +211,6 @@ I915UpdateRotate (ScreenPtr      pScreen
    struct matrix23 rotMatrix;
    int j;
    int use_fence;
-   Bool updateInvarient = FALSE;
-#ifdef XF86DRI
-   drmI830Sarea *sarea = NULL;
-   drm_context_t myContext = 0;
-#endif
    Bool didLock = FALSE;
 
    if (I830IsPrimary(pScrn)) {
@@ -246,58 +241,20 @@ I915UpdateRotate (ScreenPtr      pScreen
    }
 
 #ifdef XF86DRI
-   if (pI8301->directRenderingEnabled) {
-      sarea = DRIGetSAREAPrivate(pScrn1->pScreen);
-      myContext = DRIGetContext(pScrn1->pScreen);
+   if (pI8301->directRenderingEnabled)
       didLock = I830DRILock(pScrn1);
-   }
 #endif
 
+   /* If another screen was active, we don't know the current state. */
    if (pScrn->scrnIndex != *pI830->used3D)
-      updateInvarient = TRUE;
- 
-#ifdef XF86DRI
-   if (sarea && sarea->ctxOwner != myContext)
-      updateInvarient = TRUE;
-#endif
+      pI830->last_3d = LAST_3D_OTHER;
 
-   if (updateInvarient) {
+   if (pI830->last_3d != LAST_3D_ROTATION) {
       FS_LOCALS(3);
       *pI830->used3D = pScrn->scrnIndex;
-#ifdef XF86DRI
-      if (sarea)
-         sarea->ctxOwner = myContext;
-#endif
-      BEGIN_LP_RING(54);
-      /* invarient state */
-      OUT_RING(MI_NOOP);
-      OUT_RING(_3DSTATE_AA_CMD |
-	       AA_LINE_ECAAR_WIDTH_ENABLE | AA_LINE_ECAAR_WIDTH_1_0 |
-	       AA_LINE_REGION_WIDTH_ENABLE | AA_LINE_REGION_WIDTH_1_0);
-
-      OUT_RING(_3DSTATE_DFLT_DIFFUSE_CMD);
-      OUT_RING(0x00000000);
-
-      OUT_RING(_3DSTATE_DFLT_SPEC_CMD);
-      OUT_RING(0x00000000);
-
-      OUT_RING(_3DSTATE_DFLT_Z_CMD);
-      OUT_RING(0x00000000);
 
-      OUT_RING(_3DSTATE_COORD_SET_BINDINGS |
-	       CSB_TCB(0, 0) | CSB_TCB(1, 1) |
-	       CSB_TCB(2, 2) | CSB_TCB(3, 3) |
-	       CSB_TCB(4, 4) | CSB_TCB(5, 5) |
-	       CSB_TCB(6, 6) | CSB_TCB(7, 7));
-
-      OUT_RING(_3DSTATE_RASTER_RULES_CMD |
-	       ENABLE_TRI_FAN_PROVOKE_VRTX | TRI_FAN_PROVOKE_VRTX(2) |
-	       ENABLE_LINE_STRIP_PROVOKE_VRTX | LINE_STRIP_PROVOKE_VRTX(1) |
-	       ENABLE_TEXKILL_3D_4D | TEXKILL_4D |
-	       ENABLE_POINT_RASTER_RULE | OGL_POINT_RASTER_RULE);
-
-      OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | 1);
-      OUT_RING(0x00000000);
+      BEGIN_LP_RING(34);
+      /* invarient state */
 
       /* flush map & render cache */
       OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
@@ -313,24 +270,13 @@ I915UpdateRotate (ScreenPtr      pScreen
 
       OUT_RING(MI_NOOP);
 
-      OUT_RING(_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT);
-      OUT_RING(_3DSTATE_SCISSOR_RECT_0_CMD);
-      OUT_RING(0x00000000); /* ymin, xmin */
-      OUT_RING(0x00000000); /* ymax, xmax */
-
       OUT_RING(0x7c000003); /* XXX: magic numbers */
       OUT_RING(0x7d070000);
       OUT_RING(0x00000000);
       OUT_RING(0x68000002);
 
-      /* context setup */
-      OUT_RING(_3DSTATE_MODES_4_CMD |
-	       ENABLE_LOGIC_OP_FUNC | LOGIC_OP_FUNC(LOGICOP_COPY) |
-	       MODE4_ENABLE_STENCIL_WRITE_MASK |
-	       MODE4_ENABLE_STENCIL_TEST_MASK);
-
       OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
-	       I1_LOAD_S(2) | I1_LOAD_S(4) | I1_LOAD_S(5) | I1_LOAD_S(6) | 4);
+	       I1_LOAD_S(2) | I1_LOAD_S(4) | I1_LOAD_S(5) | I1_LOAD_S(6) | 3);
 
       OUT_RING(S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D) |
 	       S2_TEXCOORD_FMT(1, TEXCOORDFMT_NOT_PRESENT) |
@@ -349,14 +295,6 @@ I915UpdateRotate (ScreenPtr      pScreen
 	       (1 << S6_CBUF_DST_BLEND_FACT_SHIFT) | S6_COLOR_WRITE_ENABLE |
 	       (2 << S6_TRISTRIP_PV_SHIFT));
 
-      OUT_RING(_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD |
-	       IAB_MODIFY_ENABLE |
-	       IAB_MODIFY_FUNC | (BLENDFUNC_ADD << IAB_FUNC_SHIFT) |
-	       IAB_MODIFY_SRC_FACTOR |
-	       (BLENDFACT_ONE << IAB_SRC_FACTOR_SHIFT) |
-	       IAB_MODIFY_DST_FACTOR |
-	       (BLENDFACT_ZERO << IAB_DST_FACTOR_SHIFT));
-
       OUT_RING(_3DSTATE_CONST_BLEND_COLOR_CMD);
       OUT_RING(0x00000000);
 
@@ -373,9 +311,6 @@ I915UpdateRotate (ScreenPtr      pScreen
 		  DEPTH_FRMT_24_FIXED_8_OTHER);
       }
 
-      OUT_RING(_3DSTATE_STIPPLE);
-      OUT_RING(0x00000000);
-
       /* texture sampler state */
       OUT_RING(_3DSTATE_SAMPLER_STATE | 3);
       OUT_RING(0x00000001);
@@ -493,13 +428,8 @@ I830UpdateRotate (ScreenPtr      pScreen
    CARD32	vb[32];	/* 32 dword vertex buffer */
    float verts[4][2], tex[4][2];
    struct matrix23 rotMatrix;
-   Bool updateInvarient = FALSE;
    int use_fence;
    int j;
-#ifdef XF86DRI
-   drmI830Sarea *sarea = NULL;
-   drm_context_t myContext = 0;
-#endif
    Bool didLock = FALSE;
 
    if (I830IsPrimary(pScrn)) {
@@ -530,28 +460,18 @@ I830UpdateRotate (ScreenPtr      pScreen
    }
 
 #ifdef XF86DRI
-   if (pI8301->directRenderingEnabled) {
-      sarea = DRIGetSAREAPrivate(pScrn1->pScreen);
-      myContext = DRIGetContext(pScrn1->pScreen);
+   if (pI8301->directRenderingEnabled)
       didLock = I830DRILock(pScrn1);
-   }
 #endif
 
    if (pScrn->scrnIndex != *pI830->used3D)
-      updateInvarient = TRUE;
+      pI830->last_3d = LAST_3D_OTHER;
 
-#ifdef XF86DRI
-   if (sarea && sarea->ctxOwner != myContext)
-      updateInvarient = TRUE;
-#endif
-
-   if (updateInvarient) {
+   if (pI830->last_3d != LAST_3D_ROTATION) {
       *pI830->used3D = pScrn->scrnIndex;
-#ifdef XF86DRI
-      if (sarea)
-         sarea->ctxOwner = myContext;
-#endif
-      
+
+      pI830->last_3d = LAST_3D_ROTATION;
+
       BEGIN_LP_RING(48);
       OUT_RING(0x682008a1);
       OUT_RING(0x6f402100);
diff --git a/src/i915_3d.c b/src/i915_3d.c
index e70bb24..ff59171 100644
--- a/src/i915_3d.c
+++ b/src/i915_3d.c
@@ -38,7 +38,7 @@ void I915EmitInvarientState( ScrnInfoPtr
 {
    I830Ptr pI830 = I830PTR(pScrn);
 
-   BEGIN_LP_RING(20);
+   BEGIN_LP_RING(24);
 
    OUT_RING(_3DSTATE_AA_CMD |
 	     AA_LINE_ECAAR_WIDTH_ENABLE |
@@ -46,6 +46,13 @@ void I915EmitInvarientState( ScrnInfoPtr
 	     AA_LINE_REGION_WIDTH_ENABLE |
 	     AA_LINE_REGION_WIDTH_1_0);
 
+   /* Disable independent alpha blend */
+   OUT_RING(_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD |
+	    IAB_MODIFY_ENABLE |
+	    IAB_MODIFY_FUNC | (BLENDFUNC_ADD << IAB_FUNC_SHIFT) |
+	    IAB_MODIFY_SRC_FACTOR | (BLENDFACT_ONE << IAB_SRC_FACTOR_SHIFT) |
+	    IAB_MODIFY_DST_FACTOR | (BLENDFACT_ZERO << IAB_DST_FACTOR_SHIFT));
+
    OUT_RING(_3DSTATE_DFLT_DIFFUSE_CMD);
    OUT_RING(0);
 
@@ -76,15 +83,15 @@ void I915EmitInvarientState( ScrnInfoPtr
 	     ENABLE_TEXKILL_3D_4D |
 	     TEXKILL_4D);
 
-   /* Need to initialize this to zero.
-    */
+   OUT_RING(_3DSTATE_MODES_4_CMD |
+	    ENABLE_LOGIC_OP_FUNC | LOGIC_OP_FUNC(LOGICOP_COPY) |
+	    ENABLE_STENCIL_WRITE_MASK | STENCIL_WRITE_MASK(0xff) |
+	    ENABLE_STENCIL_TEST_MASK | STENCIL_TEST_MASK(0xff));
+
    OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | 0);
-   OUT_RING(0);
- 
-   /* XXX: Use this */
-   OUT_RING(_3DSTATE_SCISSOR_ENABLE_CMD | 
-	     DISABLE_SCISSOR_RECT);
+   OUT_RING(0x00000000);	/* Disable texture coordinate wrap-shortest */
 
+   OUT_RING(_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT);
    OUT_RING(_3DSTATE_SCISSOR_RECT_0_CMD);
    OUT_RING(0);
    OUT_RING(0);
@@ -94,12 +101,11 @@ void I915EmitInvarientState( ScrnInfoPtr
    OUT_RING(_3DSTATE_LOAD_INDIRECT | 0); /* disable indirect state */
    OUT_RING(0);
 
-   /* Don't support twosided stencil yet */
-   OUT_RING(_3DSTATE_BACKFACE_STENCIL_OPS |
-	     BFO_ENABLE_STENCIL_TWO_SIDE |
-	     0 );
+   OUT_RING(_3DSTATE_STIPPLE);
+   OUT_RING(0x00000000);
+
+   OUT_RING(_3DSTATE_BACKFACE_STENCIL_OPS | BFO_ENABLE_STENCIL_TWO_SIDE | 0 );
+   OUT_RING(MI_NOOP);
 
-   OUT_RING(0);
-   
    ADVANCE_LP_RING();
 }
diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
index 13fe3ee..eae8171 100644
--- a/src/i915_exa_render.c
+++ b/src/i915_exa_render.c
@@ -329,6 +329,8 @@ I915EXAPrepareComposite(int op, PictureP
     ErrorF("Enter i915 prepareComposite\n");
 #endif
 
+    pI830->last_3d = LAST_3D_RENDER;
+
     I915GetDestFormat(pDstPicture, &dst_format);
     dst_offset = exaGetPixmapOffset(pDst);
     dst_pitch = exaGetPixmapPitch(pDst);
@@ -383,7 +385,7 @@ I915EXAPrepareComposite(int op, PictureP
     {
 	CARD32 ss2;
 
-	BEGIN_LP_RING(26);
+	BEGIN_LP_RING(18);
 	/* color buffer
 	 * XXX: Need to add USE_FENCE if we ever tile the X Server's pixmaps or
 	 * visible screen.
@@ -391,23 +393,12 @@ I915EXAPrepareComposite(int op, PictureP
 	OUT_RING(_3DSTATE_BUF_INFO_CMD);
 	OUT_RING(BUF_3D_ID_COLOR_BACK| BUF_3D_PITCH(dst_pitch));
 	OUT_RING(BUF_3D_ADDR(dst_offset));
-	OUT_RING(MI_NOOP);
 
 	OUT_RING(_3DSTATE_DST_BUF_VARS_CMD);
 	OUT_RING(dst_format);
 
-	/* XXX: defaults */
-	OUT_RING(_3DSTATE_DFLT_Z_CMD);
-	OUT_RING(0x00000000);
-
-	OUT_RING(_3DSTATE_DFLT_DIFFUSE_CMD);
-	OUT_RING(0x00000000);
-
-	OUT_RING(_3DSTATE_DFLT_SPEC_CMD);
-	OUT_RING(0x00000000);
-
 	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) |
-		 I1_LOAD_S(3) | I1_LOAD_S(4) | I1_LOAD_S(5) | I1_LOAD_S(6) | 4);
+		 I1_LOAD_S(4) | I1_LOAD_S(5) | I1_LOAD_S(6) | 3);
 	ss2 = S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D);
 	if (pMask)
 		ss2 |= S2_TEXCOORD_FMT(1, TEXCOORDFMT_2D);
@@ -420,7 +411,6 @@ I915EXAPrepareComposite(int op, PictureP
 	ss2 |= S2_TEXCOORD_FMT(6, TEXCOORDFMT_NOT_PRESENT);
 	ss2 |= S2_TEXCOORD_FMT(7, TEXCOORDFMT_NOT_PRESENT);
 	OUT_RING(ss2);
-	OUT_RING(0x00000000); /* Disable texture coordinate wrap-shortest */
 	OUT_RING((1 << S4_POINT_WIDTH_SHIFT) | S4_LINE_WIDTH_ONE |
 		 S4_CULLMODE_NONE| S4_VFMT_XY);
 	blendctl = I915GetBlendCntl(op, pMaskPicture, pDstPicture->format);
diff --git a/src/i915_video.c b/src/i915_video.c
index 0833d50..aa192af 100644
--- a/src/i915_video.c
+++ b/src/i915_video.c
@@ -89,35 +89,9 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
     */
    *pI830->used3D |= 1 << 30;
 
-   BEGIN_LP_RING(44);
+   pI830->last_3d = LAST_3D_VIDEO;
 
-   /* invarient state */
-   OUT_RING(MI_NOOP);
-   OUT_RING(_3DSTATE_AA_CMD |
-	    AA_LINE_ECAAR_WIDTH_ENABLE | AA_LINE_ECAAR_WIDTH_1_0 |
-	    AA_LINE_REGION_WIDTH_ENABLE | AA_LINE_REGION_WIDTH_1_0);
-
-   OUT_RING(_3DSTATE_DFLT_DIFFUSE_CMD);
-   OUT_RING(0x00000000);
-
-   OUT_RING(_3DSTATE_DFLT_SPEC_CMD);
-   OUT_RING(0x00000000);
-
-   OUT_RING(_3DSTATE_DFLT_Z_CMD);
-   OUT_RING(0x00000000);
-
-   OUT_RING(_3DSTATE_COORD_SET_BINDINGS | CSB_TCB(0, 0) | CSB_TCB(1, 1) |
-	    CSB_TCB(2,2) | CSB_TCB(3,3) | CSB_TCB(4,4) | CSB_TCB(5,5) |
-	    CSB_TCB(6,6) | CSB_TCB(7,7));
-
-   OUT_RING(_3DSTATE_RASTER_RULES_CMD |
-	    ENABLE_TRI_FAN_PROVOKE_VRTX | TRI_FAN_PROVOKE_VRTX(2) |
-	    ENABLE_LINE_STRIP_PROVOKE_VRTX | LINE_STRIP_PROVOKE_VRTX(1) |
-	    ENABLE_TEXKILL_3D_4D | TEXKILL_4D |
-	    ENABLE_POINT_RASTER_RULE | OGL_POINT_RASTER_RULE);
-
-   OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | 1);
-   OUT_RING(0x00000000); /* texture coordinate wrap */
+   BEGIN_LP_RING(24);
 
    /* flush map & render cache */
    OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
@@ -132,25 +106,13 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
    OUT_RING(0x00000000);	/* yorigin, xorigin */
    OUT_RING(MI_NOOP);
 
-   /* scissor */
-   OUT_RING(_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT);
-   OUT_RING(_3DSTATE_SCISSOR_RECT_0_CMD);
-   OUT_RING(0x00000000);	/* ymin, xmin */
-   OUT_RING(0x00000000);	/* ymax, xmax */
-
    OUT_RING(0x7c000003);	/* unknown command */
    OUT_RING(0x7d070000);
    OUT_RING(0x00000000);
    OUT_RING(0x68000002);
 
-   /* context setup */
-   OUT_RING(_3DSTATE_MODES_4_CMD |
-	    ENABLE_LOGIC_OP_FUNC | LOGIC_OP_FUNC(LOGICOP_COPY) |
-	    ENABLE_STENCIL_WRITE_MASK | STENCIL_WRITE_MASK(0xff) |
-	    ENABLE_STENCIL_TEST_MASK | STENCIL_TEST_MASK(0xff));
-
    OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) |
-	    I1_LOAD_S(4) | I1_LOAD_S(5) | I1_LOAD_S(6) | 4);
+	    I1_LOAD_S(4) | I1_LOAD_S(5) | I1_LOAD_S(6) | 3);
    s2 = S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D);
    if (planar)
       s2 |= S2_TEXCOORD_FMT(1, TEXCOORDFMT_2D);
@@ -171,12 +133,6 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
 	    (1 << S6_CBUF_DST_BLEND_FACT_SHIFT) | S6_COLOR_WRITE_ENABLE |
 	    (2 << S6_TRISTRIP_PV_SHIFT));
 
-   OUT_RING(_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD |
-	    IAB_MODIFY_ENABLE |
-	    IAB_MODIFY_FUNC | (BLENDFUNC_ADD << IAB_FUNC_SHIFT) |
-	    IAB_MODIFY_SRC_FACTOR | (BLENDFACT_ONE << IAB_SRC_FACTOR_SHIFT) |
-	    IAB_MODIFY_DST_FACTOR | (BLENDFACT_ZERO << IAB_DST_FACTOR_SHIFT));
-
    OUT_RING(_3DSTATE_CONST_BLEND_COLOR_CMD);
    OUT_RING(0x00000000);
 
@@ -189,9 +145,6 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
    OUT_RING(LOD_PRECLAMP_OGL |
      DSTORG_HORT_BIAS(0x80) | DSTORG_VERT_BIAS(0x80) | format);
 
-   OUT_RING(_3DSTATE_STIPPLE);
-   OUT_RING(0x00000000);
-
    /* front buffer, pitch, offset */
    OUT_RING(_3DSTATE_BUF_INFO_CMD);
    OUT_RING(BUF_3D_ID_COLOR_BACK | BUF_3D_USE_FENCE |
diff-tree 0bdcce2e4541c6e441c44aad49254ad3093cedb2 (from c3666a968b1cfac61b7867874d5fbe2acd894720)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Oct 26 14:30:46 2006 -0700

    Note alignment requirement for i915 3D (texturing).

diff --git a/src/i830_exa.c b/src/i830_exa.c
index a1c7546..7de5617 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -457,6 +457,7 @@ I830EXAInit(ScreenPtr pScreen)
 	/* disable Xv here... */
     }
 
+    /* i915 3D requires 16 byte alignment (4k if tiled) */
     pI830->EXADriverPtr->pixmapOffsetAlign = 256;
     pI830->EXADriverPtr->pixmapPitchAlign = 64;
 
diff-tree c3666a968b1cfac61b7867874d5fbe2acd894720 (from f272f0d811f9ee059e8f8617a516e6c8bff917a1)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Oct 26 14:30:25 2006 -0700

    Don't write unused values beyond the end of scale_units array.

diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
index 3bc2c0b..13fe3ee 100644
--- a/src/i915_exa_render.c
+++ b/src/i915_exa_render.c
@@ -332,8 +332,6 @@ I915EXAPrepareComposite(int op, PictureP
     I915GetDestFormat(pDstPicture, &dst_format);
     dst_offset = exaGetPixmapOffset(pDst);
     dst_pitch = exaGetPixmapPitch(pDst);
-    scale_units[2][0] = pDst->drawable.width;
-    scale_units[2][1] = pDst->drawable.height;
     FS_LOCALS(20);
 
     if (!I915TextureSetup(pSrcPicture, pSrc, 0))
diff-tree 3ab9f5a4a8cd62c8a8c2a09d3d105adbe815a83d (from df14838eb5d0a056f663d9f12bd8b5c25cf97330)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Oct 24 00:26:09 2006 -0700

    Move vbeInfo out of the driver struct to the one place it's used.

diff --git a/src/i830.h b/src/i830.h
index b4408c2..3f4eacc 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -447,7 +447,6 @@ typedef struct _I830Rec {
 
    /* Video BIOS support. */
    vbeInfoPtr pVbe;
-   VbeInfoBlock *vbeInfo;
    VESAPtr vesa;
 
    Bool swfSaved;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 0c0aa95..10c6f09 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -375,8 +375,6 @@ I830FreeRec(ScrnInfoPtr pScrn)
    pI830 = I830PTR(pScrn);
 
    if (I830IsPrimary(pScrn)) {
-      if (pI830->vbeInfo)
-         VBEFreeVBEInfo(pI830->vbeInfo);
       if (pI830->pVbe)
          vbeFree(pI830->pVbe);
    }
@@ -597,6 +595,7 @@ I830DetectMemory(ScrnInfoPtr pScrn)
    CARD16 gmch_ctrl;
    int memsize = 0;
    int range;
+   VbeInfoBlock *vbeInfo;
 
    bridge = pciTag(0, 0, 0);		/* This is always the host bridge */
    gmch_ctrl = pciReadWord(bridge, I830_GMCH_CTRL);
@@ -661,6 +660,19 @@ I830DetectMemory(ScrnInfoPtr pScrn)
    } else {
       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "no video memory detected.\n");
    }
+
+   /* Sanity check: compare with what the BIOS thinks. */
+   vbeInfo = VBEGetVBEInfo(pI830->pVbe);
+   if (vbeInfo != NULL && vbeInfo->TotalMemory != memsize / 1024 / 64) {
+      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		 "Detected stolen memory (%ld kB) doesn't match what the BIOS"
+		 " reports (%d kB)\n",
+		 ROUND_DOWN_TO(memsize / 1024, 64),
+		 vbeInfo->TotalMemory * 64);
+   }
+   if (vbeInfo != NULL)
+      VBEFreeVBEInfo(vbeInfo);
+
    return memsize;
 }
 
@@ -1301,13 +1313,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 	      "Integrated Graphics Chipset: Intel(R) %s\n", chipname);
 
-   if (I830IsPrimary(pScrn)) {
-      pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe);
-   } else {
-      I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
-      pI830->vbeInfo = pI8301->vbeInfo;
-   }
-
    /* Set the Chipset and ChipRev, allowing config file entries to override. */
    if (pI830->pEnt->device->chipset && *pI830->pEnt->device->chipset) {
       pScrn->chipset = pI830->pEnt->device->chipset;
@@ -1434,15 +1439,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    pI830->StolenMemory.Start = 0;
    pI830->StolenMemory.End = pI830->StolenMemory.Size;
 
-   /* Sanity check: compare with what the BIOS thinks. */
-   if (pI830->vbeInfo->TotalMemory != pI830->StolenMemory.Size / 1024 / 64) {
-      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		 "Detected stolen memory (%ld kB) doesn't match what the BIOS"
-		 " reports (%d kB)\n",
-		 ROUND_DOWN_TO(pI830->StolenMemory.Size / 1024, 64),
-		 pI830->vbeInfo->TotalMemory * 64);
-   }
-
    /* Find the maximum amount of agpgart memory available. */
    if (I830IsPrimary(pScrn)) {
       mem = I830CheckAvailableMemory(pScrn);
@@ -2243,10 +2239,8 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 
 #if 0
    if (I830IsPrimary(pScrn)) {
-      VBEFreeVBEInfo(pI830->vbeInfo);
       vbeFree(pI830->pVbe);
    }
-   pI830->vbeInfo = NULL;
    pI830->pVbe = NULL;
 #endif
 
@@ -3233,14 +3227,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    if (!pI830->pVbe)
       return FALSE;
 
-   if (I830IsPrimary(pScrn)) {
-      if (pI830->vbeInfo)
-         VBEFreeVBEInfo(pI830->vbeInfo);
-      pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe);
-   } else {
-      pI830->vbeInfo = pI8301->vbeInfo;
-   }
-
    SetPipeAccess(pScrn);
 
    miClearVisualTypes();
diff-tree df14838eb5d0a056f663d9f12bd8b5c25cf97330 (from 3a6104ab89b159241845314ccf88fa62da14cf7d)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Oct 24 00:18:33 2006 -0700

    Remove dead memsize reporting.
    
    The calculation no longer made sense, as we don't use the BIOS for mode
    selection.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index be83431..0c0aa95 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1087,7 +1087,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    rgb defaultWeight = { 0, 0, 0 };
    EntityInfoPtr pEnt;
    I830EntPtr pI830Ent = NULL;					
-   int mem, memsize;
+   int mem;
    int flags24;
    int i, n;
    char *s;
@@ -2038,17 +2038,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
 	      "Maximum frambuffer space: %d kByte\n", pScrn->videoRam);
 
-   /*
-    * Limit videoram available for mode selection to what the video
-    * BIOS can see.
-    */
-   if (pScrn->videoRam > (pI830->vbeInfo->TotalMemory * 64))
-      memsize = pI830->vbeInfo->TotalMemory * 64;
-   else
-      memsize = pScrn->videoRam;
-   xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
-	      "Maximum space available for video modes: %d kByte\n", memsize);
-
    n = I830ValidateXF86ModeList(pScrn, TRUE);
    if (n <= 0) {
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
diff-tree 3a6104ab89b159241845314ccf88fa62da14cf7d (from 88c12f577f80fa132ec45cdf456d8060f2ece4fd)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Oct 23 19:15:30 2006 -0700

    Remove disabled I830DetectMonitorChange().
    
    This used to be called when switching back in to X.  It might make some sense
    to detect monitors at this time (it happens to occur at resume time, when
    monitors are likely to have changed), but it should probably live in either
    userland policy with RandR 1.2 or RandR 1.2 XFree86-DDX generic code.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 9f986ec..be83431 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3681,210 +3681,6 @@ I830LeaveVT(int scrnIndex, int flags)
       pI830->AccelInfoRec->NeedToSync = FALSE;
 }
 
-static Bool
-I830DetectMonitorChange(ScrnInfoPtr pScrn)
-{
-   return FALSE;
-#if 0 /* Disabled until we rewrite this natively */
-   I830Ptr pI830 = I830PTR(pScrn);
-   pointer pDDCModule = NULL;
-   DisplayModePtr p, pMon;
-   int memsize;
-   int DDCclock = 0, DDCclock2 = 0;
-   int displayWidth = pScrn->displayWidth;
-   int curHDisplay = pScrn->currentMode->HDisplay;
-   int curVDisplay = pScrn->currentMode->VDisplay;
-   xf86MonPtr monitor = NULL;
-
-   DPRINTF(PFX, "Detect Monitor Change\n");
-   
-   SetPipeAccess(pScrn);
-
-   /* Re-read EDID */
-   pDDCModule = xf86LoadSubModule(pScrn, "ddc");
-
-   pI830->pVbe->ddc = DDC_UNCHECKED;
-   monitor = vbeDoEDID(pI830->pVbe, pDDCModule);
-   xf86UnloadSubModule(pDDCModule);
-   if ((pScrn->monitor->DDC = monitor) != NULL) {
-      xf86PrintEDID(monitor);
-      xf86SetDDCproperties(pScrn, monitor);
-   } 
-
-   DDCclock = I830UseDDC(pScrn);
-
-   /* Revalidate the modes */
-
-   /*
-    * Note: VBE modes (> 0x7f) won't work with Intel's extended BIOS
-    * functions.  
-    */
-   SetPipeAccess(pScrn);
-
-   pScrn->modePool = I830GetModePool(pScrn, pI830->pVbe, pI830->vbeInfo);
-
-   if (!pScrn->modePool) {
-      /* This is bad, which would cause the Xserver to exit, maybe
-       * we should default to a 640x480 @ 60Hz mode here ??? */
-      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		 "No Video BIOS modes for chosen depth.\n");
-      return FALSE;
-   }
-
-   VBESetModeNames(pScrn->modePool);
-
-   if (pScrn->videoRam > (pI830->vbeInfo->TotalMemory * 64))
-      memsize = pI830->vbeInfo->TotalMemory * 64;
-   else
-      memsize = pScrn->videoRam;
-
-   VBEValidateModes(pScrn, pScrn->monitor->Modes, pScrn->display->modes, NULL,
-			NULL, 0, MAX_DISPLAY_PITCH, 1,
-			0, MAX_DISPLAY_HEIGHT,
-			pScrn->display->virtualX,
-			pScrn->display->virtualY,
-			memsize, LOOKUP_BEST_REFRESH);
-
-   if (pI830->MergedFB) {
-      VBEValidateModes(pI830->pScrn_2, pI830->pScrn_2->monitor->Modes, 
-		        pI830->pScrn_2->display->modes, NULL,
-			NULL, 0, MAX_DISPLAY_PITCH, 1,
-			0, MAX_DISPLAY_HEIGHT,
-			pScrn->display->virtualX,
-			pScrn->display->virtualY,
-			memsize, LOOKUP_BEST_REFRESH);
-   }
-
-   if (DDCclock > 0) {
-      p = pScrn->modes;
-      if (p == NULL)
-         return FALSE;
-      do {
-         int Clock = 100000000; /* incredible value */
-
-         if (p->status == MODE_OK) {
-            for (pMon = pScrn->monitor->Modes; pMon != NULL; pMon = pMon->next) {
-               if ((pMon->HDisplay != p->HDisplay) ||
-                   (pMon->VDisplay != p->VDisplay) ||
-                   (pMon->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2)))
-                  continue;
-
-               /* Find lowest supported Clock for this resolution */
-               if (Clock > pMon->Clock)
-                  Clock = pMon->Clock;
-            } 
-
-            if (Clock != 100000000 && DDCclock < 2550 && Clock / 1000.0 > DDCclock) {
-               ErrorF("(%s,%s) mode clock %gMHz exceeds DDC maximum %dMHz\n",
-		   p->name, pScrn->monitor->id,
-		   Clock/1000.0, DDCclock);
-               p->status = MODE_BAD;
-            } 
-         }
-         p = p->next;
-      } while (p != NULL && p != pScrn->modes);
-   }
-
-   /* Only use this if we've got DDC available */
-   if (pI830->MergedFB && DDCclock2 > 0) {
-      p = pI830->pScrn_2->modes;
-      if (p == NULL)
-         return FALSE;
-      do {
-         int Clock = 100000000; /* incredible value */
-
-	 if (p->status == MODE_OK) {
-            for (pMon = pI830->pScrn_2->monitor->Modes; pMon != NULL; pMon = pMon->next) {
-               if ((pMon->HDisplay != p->HDisplay) ||
-                   (pMon->VDisplay != p->VDisplay) ||
-                   (pMon->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2)))
-                   continue;
-
-               /* Find lowest supported Clock for this resolution */
-               if (Clock > pMon->Clock)
-                  Clock = pMon->Clock;
-            } 
-
-            if (Clock != 100000000 && DDCclock2 < 2550 && Clock / 1000.0 > DDCclock2) {
-               ErrorF("(%s,%s) mode clock %gMHz exceeds DDC maximum %dMHz\n",
-		   p->name, pI830->pScrn_2->monitor->id,
-		   Clock/1000.0, DDCclock2);
-               p->status = MODE_BAD;
-            } 
- 	 }
-         p = p->next;
-      } while (p != NULL && p != pI830->pScrn_2->modes);
-   }
-
-   xf86PruneDriverModes(pScrn);
-   I830PrintModes(pScrn);
-
-   /* Now check if the previously used mode is o.k. for the current monitor.
-    * This allows VT switching to continue happily when not disconnecting
-    * and reconnecting monitors */
-
-   pScrn->currentMode = pScrn->modes;
-
-   if (pI830->MergedFB) {
-      /* If no virtual dimension was given by the user,
-       * calculate a sane one now. Adapts pScrn->virtualX,
-       * pScrn->virtualY and pScrn->displayWidth.
-       */
-      I830RecalcDefaultVirtualSize(pScrn);
-
-      pScrn->modes = pScrn->modes->next;  /* We get the last from GenerateModeList(), skip to first */
-      pScrn->currentMode = pScrn->modes;
-      pI830->currentMode = pScrn->currentMode;
-   }
-
-   pScrn->displayWidth = displayWidth; /* restore old displayWidth */
-
-   p = pScrn->modes;
-   if (p == NULL)
-      return FALSE;
-   do {
-      if ((p->HDisplay == curHDisplay) &&
-          (p->VDisplay == curVDisplay) &&
-          (!(p->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2)))) {
-   		pScrn->currentMode = p; /* previous mode is o.k. */
-	}
-      p = p->next;
-   } while (p != NULL && p != pScrn->modes);
-
-   I830PrintModes(pScrn);
-
-   /* Now readjust for panning if necessary */
-   {
-      pScrn->frameX0 = (pScrn->frameX0 + pScrn->frameX1 + 1 - pScrn->currentMode->HDisplay) / 2;
-
-      if (pScrn->frameX0 < 0)
-         pScrn->frameX0 = 0;
-
-      pScrn->frameX1 = pScrn->frameX0 + pScrn->currentMode->HDisplay - 1;
-      if (pScrn->frameX1 >= pScrn->virtualX) {
-         pScrn->frameX0 = pScrn->virtualX - pScrn->currentMode->HDisplay;
-         pScrn->frameX1 = pScrn->virtualX - 1;
-      }
-
-      pScrn->frameY0 = (pScrn->frameY0 + pScrn->frameY1 + 1 - pScrn->currentMode->VDisplay) / 2;
-
-      if (pScrn->frameY0 < 0)
-         pScrn->frameY0 = 0;
-
-      pScrn->frameY1 = pScrn->frameY0 + pScrn->currentMode->VDisplay - 1;
-      if (pScrn->frameY1 >= pScrn->virtualY) {
-        pScrn->frameY0 = pScrn->virtualY - pScrn->currentMode->VDisplay;
-        pScrn->frameY1 = pScrn->virtualY - 1;
-      }
-   }
-
-   if (pI830->MergedFB)
-      I830AdjustFrameMerged(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
-
-   return TRUE;
-#endif /* 0 */
-}
-
 /*
  * This gets called when gaining control of the VT, and from ScreenInit().
  */
@@ -3925,10 +3721,6 @@ I830EnterVT(int scrnIndex, int flags)
    /* Mark that we'll need to re-set the mode for sure */
    memset(pI830->pipeCurMode, 0, sizeof(pI830->pipeCurMode));
 
-   /* Detect monitor change and switch to suitable mode */
-   if (!pI830->starting)
-      I830DetectMonitorChange(pScrn);
-
    if (!i830SetMode(pScrn, pScrn->currentMode))
       return FALSE;
    
diff-tree 88c12f577f80fa132ec45cdf456d8060f2ece4fd (from 2631014e9d5b2e64908ea413729eb5fd819b17fc)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Oct 23 18:57:57 2006 -0700

    Move LVDS initialization and blacklisting damage to the LVDS support file.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 4ee5fc2..9f986ec 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1092,7 +1092,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    int i, n;
    char *s;
    pointer pVBEModule = NULL;
-   Bool enable, has_lvds, is_apple_945gm = FALSE;
+   Bool enable;
    const char *chipname;
    unsigned int ver;
    char v[5];
@@ -1235,7 +1235,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       pI830->pVbe = pI8301->pVbe;
    }
 
-   has_lvds = TRUE;
    switch (pI830->PciInfo->chipType) {
    case PCI_CHIP_I830_M:
       chipname = "830M";
@@ -1269,11 +1268,9 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       break;
    case PCI_CHIP_I865_G:
       chipname = "865G";
-      has_lvds = FALSE;
       break;
    case PCI_CHIP_I915_G:
       chipname = "915G";
-      has_lvds = FALSE;
       break;
    case PCI_CHIP_E7221_G:
       chipname = "E7221 (i915)";
@@ -1283,7 +1280,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       break;
    case PCI_CHIP_I945_G:
       chipname = "945G";
-      has_lvds = FALSE;
       break;
    case PCI_CHIP_I945_GM:
       chipname = "945GM";
@@ -1540,23 +1536,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    pI830->MonType2 = PIPE_NONE;
    pI830->specifiedMonitor = FALSE;
 
-   /* Always check for LVDS info once at startup.  We hook in the BIOS data
-    * dumping here (this should be cleaner) and we get to rely on having the
-    * LVDS info later on.
-    */
-   if (!i830GetLVDSInfoFromBIOS(pScrn))
-      has_lvds = FALSE;
-
-   /* Blacklist machines with known broken BIOSes */
-   if (pI830->PciInfo->chipType == PCI_CHIP_I945_GM) {
-	if (pI830->PciInfo->subsysVendor == 0xa0a0)  /* aopen mini pc */
-	    has_lvds = FALSE;
-
-	if ((pI830->PciInfo->subsysVendor == 0x8086) &&
-	    (pI830->PciInfo->subsysCard == 0x7270)) /* mini, macbook pro... */
-	    is_apple_945gm = TRUE;
-   }
-
    if ((s = xf86GetOptValString(pI830->Options, OPTION_MONITOR_LAYOUT)) &&
       I830IsPrimary(pScrn)) {
       char *Mon1;
@@ -1645,33 +1624,19 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       pI830->specifiedMonitor = TRUE;
    } else if (I830IsPrimary(pScrn)) {
       /* Choose a default set of outputs to use based on what we've detected. */
-
-      /*
-       * Apple hardware is out to get us.  The macbook pro has a real LVDS
-       * panel, but the mac mini does not, and they have the same device IDs.
-       * We'll distinguish by panel size, on the assumption that Apple isn't
-       * about to make any machines with an 800x600 display.
-       */
-      if (is_apple_945gm && pI830->PanelXRes == 800 && pI830->PanelYRes == 600)
-      {
-	  xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		     "Suspected Mac Mini, ignoring the LFP\n");
-	  has_lvds = FALSE;
-      }
-
-      if (has_lvds) {
-	 pI830->MonType2 |= PIPE_LFP;
-      }
-
       if (i830DetectCRT(pScrn, TRUE)) {
 	 pI830->MonType1 |= PIPE_CRT;
       }
 
       /* Check for attached SDVO outputs.  Assume that they're flat panels for
        * now.  Though really, it's just a name at the moment, since we don't
-       * treat different SDVO outputs differently.
+       * treat different SDVO outputs differently.  Also, check for LVDS and
+       * set it  to the right pipe if available.
        */
       for (i = 0; i < pI830->num_outputs; i++) {
+	 if (pI830->output[i].type == I830_OUTPUT_LVDS)
+	    pI830->MonType2 |= PIPE_LFP;
+
 	 if (pI830->output[i].type == I830_OUTPUT_SDVO) {
 	    if (!i830_sdvo_detect_displays(pScrn, &pI830->output[i]))
 	       continue;
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index 399324f..5b039b8 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -181,6 +181,39 @@ i830_lvds_init(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
 
+    /* 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
+     * for now.
+     */
+    if (!i830GetLVDSInfoFromBIOS(pScrn))
+	return;
+
+    /* Blacklist machines with BIOSes that list an LVDS panel without actually
+     * having one.
+     */
+    if (pI830->PciInfo->chipType == PCI_CHIP_I945_GM) {
+	if (pI830->PciInfo->subsysVendor == 0xa0a0)  /* aopen mini pc */
+	    return;
+
+	if ((pI830->PciInfo->subsysVendor == 0x8086) &&
+	    (pI830->PciInfo->subsysCard == 0x7270)) {
+	    /* It's a Mac Mini or Macbook Pro.
+	     *
+	     * Apple hardware is out to get us.  The macbook pro has a real
+	     * LVDS panel, but the mac mini does not, and they have the same
+	     * device IDs.  We'll distinguish by panel size, on the assumption
+	     * that Apple isn't about to make any machines with an 800x600
+	     * display.
+	     */
+
+	    if (pI830->PanelXRes == 800 && pI830->PanelYRes == 600) {
+		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+			   "Suspected Mac Mini, ignoring the LVDS\n");
+		return;
+	    }
+	}
+   }
+
     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;
diff-tree 2631014e9d5b2e64908ea413729eb5fd819b17fc (from ddb986e54f5320359abac06f512f2d3f446872db)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Oct 25 12:21:44 2006 -0700

    Clean up the SDVO code.
    
    The main change is to send SDVO commands using data passed into the send
    command function, and receive responses into memory passed into the read
    response function, rather than stuff things in/out through dev_priv->sdvo_regs.
    This lets us use structures to represent some arguments, which results in a
    nice cleanup (and 100% fewer arguments named magicN as a side effect).
    
    Also, the mode set path is changed to not do any preferred input timing
    work.  We weren't doing anything legitimate with the results, since we didn't
    modify the CRTC timing appropriately, so now we just stuff the CRTC timing into
    both and hope for the best.  This should probably be revisited later.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 523eed2..ac5ae48 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -54,8 +54,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 struct i830_sdvo_priv {
     /** SDVO device on SDVO I2C bus. */
     I2CDevRec d;
-    /** Temporary storage for reg read/writes */
-    unsigned char sdvo_regs[20];
     /** Register for the SDVO device: SDVOB or SDVOC */
     int output_device;
     /**
@@ -69,14 +67,12 @@ struct i830_sdvo_priv {
     /** @{ */
     int save_sdvo_mult;
     Bool save_sdvo_active_1, save_sdvo_active_2;
-    i830_sdvo_dtd save_input_dtd_1, save_input_dtd_2;
-    i830_sdvo_dtd save_output_dtd_1, save_output_dtd_2;
+    struct i830_sdvo_dtd save_input_dtd_1, save_input_dtd_2;
+    struct i830_sdvo_dtd save_output_dtd_1, save_output_dtd_2;
     CARD32 save_SDVOX;
     /** @} */
 };
 
-CARD16 curr_table[6];
-
 /** Read a single byte from the given address on the SDVO device. */
 static Bool i830_sdvo_read_byte(I830OutputPtr output, int addr,
 				unsigned char *ch)
@@ -153,33 +149,36 @@ const struct _sdvo_cmd_name {
     SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTROL_BUS_SWITCH),
 };
 
-/* following on from tracing the intel BIOS i2c routines */
+/**
+ * Writes out the data given in args (up to 8 bytes), followed by the opcode.
+ */
 static void
-i830_sdvo_write_outputs(I830OutputPtr output, int num_out)
+i830_sdvo_write_cmd(I830OutputPtr output, CARD8 cmd, void *args, int args_len)
 {
-    struct i830_sdvo_priv *dev_priv = output->dev_priv;
     int i;
 
-    ErrorF("SDVO: W: %02X ", dev_priv->sdvo_regs[SDVO_I2C_OPCODE]);
-    for (i = SDVO_I2C_ARG_0; i > SDVO_I2C_ARG_0 - num_out; i--)
-	ErrorF("%02X ", dev_priv->sdvo_regs[i]);
-    for (; i > SDVO_I2C_ARG_7; i--)
-	ErrorF("   ");
+    /* Write the SDVO command logging */
+    xf86DrvMsg(output->pI2CBus->scrnIndex, X_INFO, "SDVO: W: %02X ", cmd);
+    for (i = 0; i < args_len; i++)
+	LogWrite(1, "%02X ", ((CARD8 *)args)[i]);
+    for (; i < 8; i++)
+	LogWrite(1, "   ");
     for (i = 0; i < sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]); i++) {
-	if (dev_priv->sdvo_regs[SDVO_I2C_OPCODE] == sdvo_cmd_names[i].cmd) {
-	    ErrorF("(%s)", sdvo_cmd_names[i].name);
+	if (cmd == sdvo_cmd_names[i].cmd) {
+	    LogWrite(1, "(%s)", sdvo_cmd_names[i].name);
 	    break;
 	}
     }
-    ErrorF("\n");
-
-    /* blast the output regs */
-    for (i = SDVO_I2C_ARG_0; i > SDVO_I2C_ARG_0 - num_out; i--) {
-	i830_sdvo_write_byte(output, i, dev_priv->sdvo_regs[i]);
+    if (i == sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]))
+	LogWrite(1, "(%02X)", cmd);
+    LogWrite(1, "\n");
+
+    /* send the output regs */
+    for (i = 0; i < args_len; i++) {
+	i830_sdvo_write_byte(output, SDVO_I2C_ARG_0 - i, ((CARD8 *)args)[i]);
     }
     /* blast the command reg */
-    i830_sdvo_write_byte(output, SDVO_I2C_OPCODE,
-			 dev_priv->sdvo_regs[SDVO_I2C_OPCODE]);
+    i830_sdvo_write_byte(output, SDVO_I2C_OPCODE, cmd);
 }
 
 static const char *cmd_status_names[] = {
@@ -192,45 +191,40 @@ static const char *cmd_status_names[] = 
 	"Scaling not supported"
 };
 
-static void
-i830_sdvo_read_input_regs(I830OutputPtr output)
+/**
+ * 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)
 {
-    struct i830_sdvo_priv *dev_priv = output->dev_priv;
     int i;
+    CARD8 status;
 
-    /* follow BIOS ordering */
-    i830_sdvo_read_byte(output, SDVO_I2C_CMD_STATUS,
-			&dev_priv->sdvo_regs[SDVO_I2C_CMD_STATUS]);
-
-    i830_sdvo_read_byte(output, SDVO_I2C_RETURN_3,
-			&dev_priv->sdvo_regs[SDVO_I2C_RETURN_3]);
-    i830_sdvo_read_byte(output, SDVO_I2C_RETURN_2,
-			&dev_priv->sdvo_regs[SDVO_I2C_RETURN_2]);
-    i830_sdvo_read_byte(output, SDVO_I2C_RETURN_1,
-			&dev_priv->sdvo_regs[SDVO_I2C_RETURN_1]);
-    i830_sdvo_read_byte(output, SDVO_I2C_RETURN_0,
-			&dev_priv->sdvo_regs[SDVO_I2C_RETURN_0]);
-    i830_sdvo_read_byte(output, SDVO_I2C_RETURN_7,
-			&dev_priv->sdvo_regs[SDVO_I2C_RETURN_7]);
-    i830_sdvo_read_byte(output, SDVO_I2C_RETURN_6,
-			&dev_priv->sdvo_regs[SDVO_I2C_RETURN_6]);
-    i830_sdvo_read_byte(output, SDVO_I2C_RETURN_5,
-			&dev_priv->sdvo_regs[SDVO_I2C_RETURN_5]);
-    i830_sdvo_read_byte(output, SDVO_I2C_RETURN_4,
-			&dev_priv->sdvo_regs[SDVO_I2C_RETURN_4]);
-
-    ErrorF("SDVO: R: ");
-    for (i = SDVO_I2C_RETURN_0; i <= SDVO_I2C_RETURN_7; i++)
-	ErrorF("%02X ", dev_priv->sdvo_regs[i]);
-    if (dev_priv->sdvo_regs[SDVO_I2C_CMD_STATUS] <=
-	SDVO_CMD_STATUS_SCALING_NOT_SUPP)
+    /* Read the command response */
+    for (i = 0; i < response_len; i++) {
+	i830_sdvo_read_byte(output, SDVO_I2C_RETURN_0 + i,
+			    &((CARD8 *)response)[i]);
+    }
+
+    /* Read the return status */
+    i830_sdvo_read_byte(output, SDVO_I2C_CMD_STATUS, &status);
+
+    /* Write the SDVO command logging */
+    xf86DrvMsg(output->pI2CBus->scrnIndex, X_INFO,
+	       "SDVO: R: ");
+    for (i = 0; i < response_len; i++)
+	LogWrite(1, "%02X ", ((CARD8 *)response)[i]);
+    for (; i < 8; i++)
+	LogWrite(1, "   ");
+    if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP)
     {
-	ErrorF("(%s)",
-	       cmd_status_names[dev_priv->sdvo_regs[SDVO_I2C_CMD_STATUS]]);
+	LogWrite(1, "(%s)", cmd_status_names[status]);
     } else {
-	ErrorF("(??? %d)", dev_priv->sdvo_regs[SDVO_I2C_CMD_STATUS]);
+	LogWrite(1, "(??? %d)", status);
     }
-    ErrorF("\n");
+    LogWrite(1, "\n");
+
+    return status;
 }
 
 int
@@ -248,49 +242,47 @@ i830_sdvo_get_pixel_multiplier(DisplayMo
  * PROM.  It resets from the DDC bus back to internal registers at the next I2C
  * STOP.  PROM access is terminated by accessing an internal register.
  */
-static Bool
+static void
 i830_sdvo_set_control_bus_switch(I830OutputPtr output, CARD8 target)
 {
-    struct i830_sdvo_priv *dev_priv = output->dev_priv;
-
-    memset(dev_priv->sdvo_regs, 0, 9);
-
-    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_CONTROL_BUS_SWITCH;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = target;
-
-    i830_sdvo_write_outputs(output, 1);
-    return TRUE;
+    i830_sdvo_write_cmd(output, SDVO_CMD_SET_CONTROL_BUS_SWITCH, &target, 1);
 }
 
 static Bool
 i830_sdvo_set_target_input(I830OutputPtr output, Bool target_1, Bool target_2)
 {
-    struct i830_sdvo_priv *dev_priv = output->dev_priv;
+    CARD8 targets[2];
+    CARD8 status;
 
-    memset(dev_priv->sdvo_regs, 0, 9);
+    targets[0] = target_1;
+    targets[1] = target_2;
+    i830_sdvo_write_cmd(output, SDVO_CMD_SET_TARGET_INPUT, &targets, 2);
 
-    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_TARGET_INPUT;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = target_1;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_1] = target_2;
+    status = i830_sdvo_read_response(output, NULL, 0);
 
-    i830_sdvo_write_outputs(output, 2);
-
-    i830_sdvo_read_input_regs(output);
-
-    return TRUE;
+    return (status == SDVO_CMD_STATUS_SUCCESS);
 }
 
+/**
+ * Return whether each input is trained.
+ *
+ * This function is making an assumption about the layout of the response,
+ * which should be checked against the docs.
+ */
 static Bool
-i830_sdvo_get_trained_inputs(I830OutputPtr output)
+i830_sdvo_get_trained_inputs(I830OutputPtr output, Bool *input_1, Bool *input_2)
 {
-    struct i830_sdvo_priv *dev_priv = output->dev_priv;
+    CARD8 response[2];
+    CARD8 status;
 
-    memset(dev_priv->sdvo_regs, 0, 9);
+    i830_sdvo_write_cmd(output, SDVO_CMD_GET_TRAINED_INPUTS, NULL, 0);
 
-    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_TRAINED_INPUTS;
+    i830_sdvo_read_response(output, response, 2);
+    if (status != SDVO_CMD_STATUS_SUCCESS)
+	return FALSE;
 
-    i830_sdvo_write_outputs(output, 0);
-    i830_sdvo_read_input_regs(output);
+    *input_1 = response[0];
+    *input_2 = response[1];
 
     return TRUE;
 }
@@ -298,56 +290,50 @@ i830_sdvo_get_trained_inputs(I830OutputP
 static Bool
 i830_sdvo_get_active_outputs(I830OutputPtr output, Bool *on_1, Bool *on_2)
 {
-    struct i830_sdvo_priv *dev_priv = output->dev_priv;
+    CARD8 response[2];
+    CARD8 status;
 
-    memset(dev_priv->sdvo_regs, 0, 9);
+    i830_sdvo_write_cmd(output, SDVO_CMD_GET_ACTIVE_OUTPUTS, NULL, 0);
 
-    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_ACTIVE_OUTPUTS;
+    status = i830_sdvo_read_response(output, &response, 2);
 
-    i830_sdvo_write_outputs(output, 0);
-    i830_sdvo_read_input_regs(output);
+    *on_1 = response[0];
+    *on_2 = response[1];
 
-    *on_1 = dev_priv->sdvo_regs[SDVO_I2C_RETURN_0];
-    *on_2 = dev_priv->sdvo_regs[SDVO_I2C_RETURN_1];
-
-    return TRUE;
+    return (status == SDVO_CMD_STATUS_SUCCESS);
 }
 
 static Bool
 i830_sdvo_set_active_outputs(I830OutputPtr output, Bool on_1, Bool on_2)
 {
-    struct i830_sdvo_priv *dev_priv = output->dev_priv;
-
-    memset(dev_priv->sdvo_regs, 0, 9);
+    CARD8 outputs[2];
+    CARD8 status;
 
-    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_ACTIVE_OUTPUTS;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = on_1;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_1] = on_2;
+    outputs[0] = on_1;
+    outputs[1] = on_2;
+    i830_sdvo_write_cmd(output, SDVO_CMD_SET_ACTIVE_OUTPUTS, &outputs, 2);
 
-    i830_sdvo_write_outputs(output, 2);
-    i830_sdvo_read_input_regs(output);
+    status = i830_sdvo_read_response(output, NULL, 0);
 
-    return TRUE;
+    return (status == SDVO_CMD_STATUS_SUCCESS);
 }
 
 static Bool
 i830_sdvo_get_input_pixel_clock_range(I830OutputPtr output, CARD16 *clock_min,
 				      CARD16 *clock_max)
 {
-    struct i830_sdvo_priv *dev_priv = output->dev_priv;
+    struct i830_sdvo_pixel_clock_range clocks;
+    CARD8 status;
 
-    memset(dev_priv->sdvo_regs, 0, 9);
+    i830_sdvo_write_cmd(output, SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE, NULL, 0);
 
-    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] =
-	SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE;
+    status = i830_sdvo_read_response(output, &clocks, sizeof(clocks));
 
-    i830_sdvo_write_outputs(output, 0);
-    i830_sdvo_read_input_regs(output);
+    if (status != SDVO_CMD_STATUS_SUCCESS)
+	return FALSE;
 
-    *clock_min = dev_priv->sdvo_regs[SDVO_I2C_RETURN_0] |
-		 (dev_priv->sdvo_regs[SDVO_I2C_RETURN_1] << 8);
-    *clock_max = dev_priv->sdvo_regs[SDVO_I2C_RETURN_2] |
-		 (dev_priv->sdvo_regs[SDVO_I2C_RETURN_3] << 8);
+    *clock_min = clocks.min;
+    *clock_max = clocks.max;
 
     return TRUE;
 }
@@ -355,282 +341,164 @@ i830_sdvo_get_input_pixel_clock_range(I8
 static Bool
 i830_sdvo_set_target_output(I830OutputPtr output, Bool target_1, Bool target_2)
 {
-    struct i830_sdvo_priv *dev_priv = output->dev_priv;
-
-    memset(dev_priv->sdvo_regs, 0, 9);
+    CARD8 targets[2];
+    CARD8 status;
 
-    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_TARGET_OUTPUT;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = target_1;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_1] = target_2;
+    targets[0] = target_1;
+    targets[1] = target_2;
+    i830_sdvo_write_cmd(output, SDVO_CMD_SET_TARGET_OUTPUT, &targets, 2);
 
-    i830_sdvo_write_outputs(output, 2);
-    i830_sdvo_read_input_regs(output);
+    status = i830_sdvo_read_response(output, NULL, 0);
 
-    return TRUE;
+    return (status == SDVO_CMD_STATUS_SUCCESS);
 }
 
-/* Fetches either input or output timings to *dtd, depending on cmd. */
+/** Fetches either input or output timings to *dtd, depending on cmd. */
 static Bool
-i830_sdvo_get_timings(I830OutputPtr output, i830_sdvo_dtd *dtd, CARD8 cmd)
+i830_sdvo_get_timing(I830OutputPtr output, CARD8 cmd, struct i830_sdvo_dtd *dtd)
 {
-    struct i830_sdvo_priv *dev_priv = output->dev_priv;
-
-    memset(dev_priv->sdvo_regs, 0, 9);
-    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = cmd;
-    i830_sdvo_write_outputs(output, 0);
-    i830_sdvo_read_input_regs(output);
-
-    dtd->clock = dev_priv->sdvo_regs[SDVO_I2C_RETURN_0] |
-		 (dev_priv->sdvo_regs[SDVO_I2C_RETURN_1] << 8);
-    dtd->h_active = dev_priv->sdvo_regs[SDVO_I2C_RETURN_2];
-    dtd->h_blank = dev_priv->sdvo_regs[SDVO_I2C_RETURN_3];
-    dtd->h_high = dev_priv->sdvo_regs[SDVO_I2C_RETURN_4];
-    dtd->v_active = dev_priv->sdvo_regs[SDVO_I2C_RETURN_5];
-    dtd->v_blank = dev_priv->sdvo_regs[SDVO_I2C_RETURN_6];
-    dtd->v_high = dev_priv->sdvo_regs[SDVO_I2C_RETURN_7];
-
-    memset(dev_priv->sdvo_regs, 0, 9);
-    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = cmd + 1;
-    i830_sdvo_write_outputs(output, 0);
-    i830_sdvo_read_input_regs(output);
-
-    dtd->h_sync_off = dev_priv->sdvo_regs[SDVO_I2C_RETURN_0];
-    dtd->h_sync_width = dev_priv->sdvo_regs[SDVO_I2C_RETURN_1];
-    dtd->v_sync_off_width = dev_priv->sdvo_regs[SDVO_I2C_RETURN_2];
-    dtd->sync_off_width_high = dev_priv->sdvo_regs[SDVO_I2C_RETURN_3];
-    dtd->dtd_flags = dev_priv->sdvo_regs[SDVO_I2C_RETURN_4];
-    dtd->sdvo_flags = dev_priv->sdvo_regs[SDVO_I2C_RETURN_5];
-    dtd->v_sync_off_high = dev_priv->sdvo_regs[SDVO_I2C_RETURN_6];
-    dtd->reserved = dev_priv->sdvo_regs[SDVO_I2C_RETURN_7];
-
-    return TRUE;
-}
-
-/* Sets either input or output timings to *dtd, depending on cmd. */
-static Bool
-i830_sdvo_set_timings(I830OutputPtr output, i830_sdvo_dtd *dtd, CARD8 cmd)
-{
-    struct i830_sdvo_priv *dev_priv = output->dev_priv;
-
-    memset(dev_priv->sdvo_regs, 0, 9);
-    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = cmd;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = dtd->clock & 0xff;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_1] = dtd->clock >> 8;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_2] = dtd->h_active;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_3] = dtd->h_blank;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_4] = dtd->h_high;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_5] = dtd->v_active;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_6] = dtd->v_blank;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_7] = dtd->v_high;
-    i830_sdvo_write_outputs(output, 8);
-    i830_sdvo_read_input_regs(output);
-
-    memset(dev_priv->sdvo_regs, 0, 9);
-    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = cmd + 1;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = dtd->h_sync_off;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_1] = dtd->h_sync_width;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_2] = dtd->v_sync_off_width;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_3] = dtd->sync_off_width_high;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_4] = dtd->dtd_flags;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_5] = dtd->sdvo_flags;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_6] = dtd->v_sync_off_high;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_7] = dtd->reserved;
-    i830_sdvo_write_outputs(output, 7);
-    i830_sdvo_read_input_regs(output);
-
-    return TRUE;
-}
-
-static Bool
-i830_sdvo_set_timings_part1(I830OutputPtr output, char cmd, CARD16 clock,
-			    CARD16 magic1, CARD16 magic2, CARD16 magic3)
-{
-    struct i830_sdvo_priv *dev_priv = output->dev_priv;
+    CARD8 status;
 
-    memset(dev_priv->sdvo_regs, 0, 9);
+    i830_sdvo_write_cmd(output, cmd, NULL, 0);
 
-    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = cmd;
+    status = i830_sdvo_read_response(output, &dtd->part1, sizeof(dtd->part1));
+    if (status != SDVO_CMD_STATUS_SUCCESS)
+	return FALSE;
 
-    /* set clock regs */
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = clock & 0xff;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_1] = (clock >> 8) & 0xff;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_2] = magic3 & 0xff;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_3] = (magic3 >> 8) & 0xff;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_4] = magic2 & 0xff;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_5] = (magic2 >> 8) & 0xff;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_6] = magic1 & 0xff;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_7] = (magic1 >> 8) & 0xff;
+    i830_sdvo_write_cmd(output, cmd + 1, NULL, 0);
 
-    i830_sdvo_write_outputs(output, 8);
-    i830_sdvo_read_input_regs(output);
+    status = i830_sdvo_read_response(output, &dtd->part2, sizeof(dtd->part2));
+    if (status != SDVO_CMD_STATUS_SUCCESS)
+	return FALSE;
 
     return TRUE;
 }
 
 static Bool
-i830_sdvo_set_input_timings_part1(I830OutputPtr output, CARD16 clock,
-				  CARD16 magic1, CARD16 magic2, CARD16 magic3)
+i830_sdvo_get_input_timing(I830OutputPtr output, struct i830_sdvo_dtd *dtd)
 {
-    return i830_sdvo_set_timings_part1(output,
-				       SDVO_CMD_SET_INPUT_TIMINGS_PART1,
-				       clock, magic1, magic2, magic3);
+    return i830_sdvo_get_timing(output, SDVO_CMD_GET_INPUT_TIMINGS_PART1, dtd);
 }
 
 static Bool
-i830_sdvo_set_output_timings_part1(I830OutputPtr output, CARD16 clock,
-				   CARD16 magic1, CARD16 magic2, CARD16 magic3)
+i830_sdvo_get_output_timing(I830OutputPtr output, struct i830_sdvo_dtd *dtd)
 {
-    return i830_sdvo_set_timings_part1(output,
-				       SDVO_CMD_SET_OUTPUT_TIMINGS_PART1,
-				       clock, magic1, magic2, magic3);
+    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_timings_part2(I830OutputPtr output, CARD8 cmd,
-			    CARD16 magic4, CARD16 magic5, CARD16 magic6)
+i830_sdvo_set_timing(I830OutputPtr output, CARD8 cmd, struct i830_sdvo_dtd *dtd)
 {
-    struct i830_sdvo_priv *dev_priv = output->dev_priv;
-
-    memset(dev_priv->sdvo_regs, 0, 9);
+    CARD8 status;
 
-    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = cmd;
-
-    /* set clock regs */
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = magic4 & 0xff;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_1] = (magic4 >> 8) & 0xff;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_2] = magic5 & 0xff;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_3] = (magic5 >> 8) & 0xff;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_4] = magic6 & 0xff;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_5] = (magic6 >> 8) & 0xff;
+    i830_sdvo_write_cmd(output, cmd, &dtd->part1, sizeof(dtd->part1));
+    status = i830_sdvo_read_response(output, NULL, 0);
+    if (status != SDVO_CMD_STATUS_SUCCESS)
+	return FALSE;
 
-    i830_sdvo_write_outputs(output, 8);
-    i830_sdvo_read_input_regs(output);
+    i830_sdvo_write_cmd(output, cmd + 1, &dtd->part2, sizeof(dtd->part2));
+    status = i830_sdvo_read_response(output, NULL, 0);
+    if (status != SDVO_CMD_STATUS_SUCCESS)
+	return FALSE;
 
     return TRUE;
 }
 
 static Bool
-i830_sdvo_set_input_timings_part2(I830OutputPtr output,
-				  CARD16 magic4, CARD16 magic5, CARD16 magic6)
+i830_sdvo_set_input_timing(I830OutputPtr output, struct i830_sdvo_dtd *dtd)
 {
-    return i830_sdvo_set_timings_part2(output,
-				       SDVO_CMD_SET_INPUT_TIMINGS_PART2,
-				       magic4, magic5, magic6);
+    return i830_sdvo_set_timing(output, SDVO_CMD_SET_INPUT_TIMINGS_PART1, dtd);
 }
 
 static Bool
-i830_sdvo_set_output_timings_part2(I830OutputPtr output,
-			      CARD16 magic4, CARD16 magic5, CARD16 magic6)
+i830_sdvo_set_output_timing(I830OutputPtr output, struct i830_sdvo_dtd *dtd)
 {
-    return i830_sdvo_set_timings_part2(output,
-				       SDVO_CMD_SET_OUTPUT_TIMINGS_PART2,
-				       magic4, magic5, magic6);
+    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,
 					CARD16 width, CARD16 height)
 {
     struct i830_sdvo_priv *dev_priv = output->dev_priv;
+    struct i830_sdvo_preferred_input_timing_args args;
 
-    memset(dev_priv->sdvo_regs, 0, 9);
-
-    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] =
-	SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING;
-
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = clock & 0xff;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_1] = (clock >> 8) & 0xff;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_2] = width & 0xff;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_3] = (width >> 8) & 0xff;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_4] = height & 0xff;
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_5] = (height >> 8) & 0xff;
-
-    i830_sdvo_write_outputs(output, 7);
-    i830_sdvo_read_input_regs(output);
+    args.clock = clock;
+    args.width = width;
+    args.height = height;
+    i830_sdvo_write_cmd(output, SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING,
+			&args, sizeof(args));
+    status = i830_sdvo_read_response(output, NULL, 0);
+    if (status != SDVO_CMD_STATUS_SUCCESS)
+	return FALSE;
 
     return TRUE;
 }
 
 static Bool
-i830_sdvo_get_preferred_input_timing_part1(I830OutputPtr output)
+i830_sdvo_get_preferred_input_timing(I830OutputPtr output,
+				     struct i830_sdvo_dtd *dtd)
 {
     struct i830_sdvo_priv *dev_priv = output->dev_priv;
 
-    memset(dev_priv->sdvo_regs, 0, 9);
-
-    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] =
-	SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1;
-
-    i830_sdvo_write_outputs(output, 0);
-    i830_sdvo_read_input_regs(output);
-
-    curr_table[0] = dev_priv->sdvo_regs[SDVO_I2C_RETURN_6] |
-		    (dev_priv->sdvo_regs[SDVO_I2C_RETURN_7] << 8);
-    curr_table[1] = dev_priv->sdvo_regs[SDVO_I2C_RETURN_4] |
-		    (dev_priv->sdvo_regs[SDVO_I2C_RETURN_5] << 8);
-    curr_table[2] = dev_priv->sdvo_regs[SDVO_I2C_RETURN_2] |
-		    (dev_priv->sdvo_regs[SDVO_I2C_RETURN_3] << 8);
+    i830_sdvo_write_cmd(output, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1,
+			NULL, 0);
 
-    return TRUE;
-}
-
-static Bool
-i830_sdvo_get_preferred_input_timing_part2(I830OutputPtr output)
-{
-    struct i830_sdvo_priv *dev_priv = output->dev_priv;
-
-    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] =
-	SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2;
+    status = i830_sdvo_read_response(output, &dtd->part1, sizeof(dtd->part1));
+    if (status != SDVO_CMD_STATUS_SUCCESS)
+	return FALSE;
 
-    i830_sdvo_write_outputs(output, 0);
-    i830_sdvo_read_input_regs(output);
+    i830_sdvo_write_cmd(output, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2,
+			NULL, 0);
 
-    curr_table[3] = dev_priv->sdvo_regs[SDVO_I2C_RETURN_0] |
-		    (dev_priv->sdvo_regs[SDVO_I2C_RETURN_1] << 8);
-    curr_table[4] = dev_priv->sdvo_regs[SDVO_I2C_RETURN_2] |
-		    (dev_priv->sdvo_regs[SDVO_I2C_RETURN_3] << 8);
-    curr_table[5] = 0x1e;
+    status = i830_sdvo_read_response(output, &dtd->part2, sizeof(dtd->part2));
+    if (status != SDVO_CMD_STATUS_SUCCESS)
+	return FALSE;
 
     return TRUE;
 }
+#endif
 
+/** Returns the SDVO_CLOCK_RATE_MULT_* for the current clock multiplier */
 static int
 i830_sdvo_get_clock_rate_mult(I830OutputPtr output)
 {
     struct i830_sdvo_priv *dev_priv = output->dev_priv;
+    CARD8 response;
+    CARD8 status;
 
-    memset(dev_priv->sdvo_regs, 0, 9);
-
-    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_CLOCK_RATE_MULT;
+    i830_sdvo_write_cmd(output, SDVO_CMD_GET_CLOCK_RATE_MULT, NULL, 0);
+    status = i830_sdvo_read_response(output, &response, 1);
 
-    i830_sdvo_write_outputs(output, 0);
-    i830_sdvo_read_input_regs(output);
-
-    if (dev_priv->sdvo_regs[SDVO_I2C_CMD_STATUS] != SDVO_CMD_STATUS_SUCCESS) {
+    if (status != SDVO_CMD_STATUS_SUCCESS) {
 	xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex, X_ERROR,
 		   "Couldn't get SDVO clock rate multiplier\n");
 	return SDVO_CLOCK_RATE_MULT_1X;
     } else {
 	xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex, X_INFO,
-		   "Current clock rate multiplier: %d\n",
-		   dev_priv->sdvo_regs[SDVO_I2C_RETURN_0]);
+		   "Current clock rate multiplier: %d\n", response);
     }
 
-    return dev_priv->sdvo_regs[SDVO_I2C_RETURN_0];
+    return response;
 }
 
+/**
+ * Sets the current clock multiplier.
+ *
+ * This has to match with the settings in the DPLL/SDVO reg when the output
+ * is actually turned on.
+ */
 static Bool
 i830_sdvo_set_clock_rate_mult(I830OutputPtr output, CARD8 val)
 {
-    struct i830_sdvo_priv *dev_priv = output->dev_priv;
-
-    memset(dev_priv->sdvo_regs, 0, 9);
-
-    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_CLOCK_RATE_MULT;
+    CARD8 status;
 
-    dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = val;
-    i830_sdvo_write_outputs(output, 1);
-    i830_sdvo_read_input_regs(output);
+    i830_sdvo_write_cmd(output, SDVO_CMD_SET_CLOCK_RATE_MULT, &val, 1);
+    status = i830_sdvo_read_response(output, NULL, 0);
+    if (status != SDVO_CMD_STATUS_SUCCESS)
+	return FALSE;
 
     return TRUE;
 }
@@ -640,15 +508,11 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn
 		       DisplayModePtr mode)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    CARD16 clock = mode->Clock/10, width = mode->CrtcHDisplay;
+    CARD16 width = mode->CrtcHDisplay;
     CARD16 height = mode->CrtcVDisplay;
     CARD16 h_blank_len, h_sync_len, v_blank_len, v_sync_len;
     CARD16 h_sync_offset, v_sync_offset;
-    CARD16 sync_flags;
-    CARD8 c16a[8];
-    CARD8 c17a[8];
-    CARD16 out_timings[6];
-    Bool out1, out2;
+    struct i830_sdvo_dtd output_dtd;
 
     /* do some mode translations */
     h_blank_len = mode->CrtcHBlankEnd - mode->CrtcHBlankStart;
@@ -660,62 +524,57 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn
     h_sync_offset = mode->CrtcHSyncStart - mode->CrtcHBlankStart;
     v_sync_offset = mode->CrtcVSyncStart - mode->CrtcVBlankStart;
 
-    sync_flags = 0x18;
+    output_dtd.part1.clock = mode->Clock / 10;
+    output_dtd.part1.h_active = width & 0xff;
+    output_dtd.part1.h_blank = h_blank_len & 0xff;
+    output_dtd.part1.h_high = (((width >> 8) & 0xf) << 4) |
+	((h_blank_len >> 8) & 0xf);
+    output_dtd.part1.v_active = height & 0xff;
+    output_dtd.part1.v_blank = v_blank_len & 0xff;
+    output_dtd.part1.v_high = (((height >> 8) & 0xf) << 4) |
+	((v_blank_len >> 8) & 0xf);
+
+    output_dtd.part2.h_sync_off = h_sync_offset;
+    output_dtd.part2.h_sync_width = h_sync_len & 0xff;
+    output_dtd.part2.v_sync_off_width = (v_sync_offset & 0xf) << 4 |
+	(v_sync_len & 0xf);
+    output_dtd.part2.sync_off_width_high = 0;
+    output_dtd.part2.dtd_flags = 0x18;
+    output_dtd.part2.sdvo_flags = 0;
+    output_dtd.part2.v_sync_off_width = 0;
+    output_dtd.part2.reserved = 0;
     if (mode->Flags & V_PHSYNC)
-	sync_flags |= 0x2;
+	output_dtd.part2.dtd_flags |= 0x2;
     if (mode->Flags & V_PVSYNC)
-	sync_flags |= 0x4;
-    /* high bits of 0 */
-    c16a[7] = clock & 0xff;
-    c16a[6] = (clock >> 8) & 0xff;
-    c16a[5] = (width & 0xff);
-    c16a[4] = (h_blank_len & 0xff);
-    c16a[3] = (((width >> 8) & 0xf) << 4) | ((h_blank_len >> 8) & 0xf);
-    c16a[2] = (height & 0xff);
-    c16a[1] = (v_blank_len & 0xff);
-    c16a[0] = (((height >> 8) & 0xf) << 4) | ((v_blank_len >> 8) & 0xf);
-
-    c17a[7] = h_sync_offset;
-    c17a[6] = h_sync_len & 0xff;
-    c17a[5] = (v_sync_offset & 0xf) << 4 | (v_sync_len & 0xf);
-    c17a[4] = 0;
-    c17a[3] = sync_flags;
-    c17a[2] = 0;
-    out_timings[0] = c16a[1] | ((short)c16a[0] << 8);
-    out_timings[1] = c16a[3] | ((short)c16a[2] << 8);
-    out_timings[2] = c16a[5] | ((short)c16a[4] << 8);
-    out_timings[3] = c17a[7] | ((short)c17a[6] << 8);
-    out_timings[4] = c17a[5] | ((short)c17a[4] << 8);
-    out_timings[5] = c17a[3] | ((short)c17a[2] << 8);
-
-    i830_sdvo_set_target_input(output, FALSE, FALSE);
-
-    i830_sdvo_get_active_outputs(output, &out1, &out2);
+	output_dtd.part2.dtd_flags |= 0x4;
 
+    /* Turn off the screens before adjusting timings */
     i830_sdvo_set_active_outputs(output, FALSE, FALSE);
 
+    /* Set the output timing to the screen */
     i830_sdvo_set_target_output(output, TRUE, FALSE);
-    i830_sdvo_set_output_timings_part1(output, clock,
-				       out_timings[0], out_timings[1],
-				       out_timings[2]);
-    i830_sdvo_set_output_timings_part2(output, out_timings[3], out_timings[4],
-				       out_timings[5]);
-
-    i830_sdvo_set_target_input(output, FALSE, FALSE);
-
-    i830_sdvo_create_preferred_input_timing(output, clock, width, height);
-    i830_sdvo_get_preferred_input_timing_part1(output);
-    i830_sdvo_get_preferred_input_timing_part2(output);
-
-    i830_sdvo_set_target_input(output, FALSE, FALSE);
+    i830_sdvo_set_output_timing(output, &output_dtd);
 
-    i830_sdvo_set_input_timings_part1(output, clock,
-				      curr_table[0], curr_table[1],
-				      curr_table[2]);
-    i830_sdvo_set_input_timings_part2(output, curr_table[3], curr_table[4],
-				      out_timings[5]);
+    /* Set the input timing to the screen */
+    i830_sdvo_set_target_input(output, TRUE, FALSE);
 
-    i830_sdvo_set_target_input(output, FALSE, FALSE);
+    /* We would like to use i830_sdvo_create_preferred_input_timing() to
+     * provide the device with a timing it can support, if it supports that
+     * feature.  However, presumably we would need to adjust the CRTC to output
+     * the preferred timing, and we don't support that currently.
+     */
+#if 0
+    success = i830_sdvo_create_preferred_input_timing(output, clock,
+						      width, height);
+    if (success) {
+	struct i830_sdvo_dtd *input_dtd;
+
+	i830_sdvo_get_preferred_input_timing(output, &input_dtd);
+	i830_sdvo_set_input_timing(output, &input_dtd);
+    }
+#else
+    i830_sdvo_set_input_timing(output, &output_dtd);
+#endif
 
     switch (i830_sdvo_get_pixel_multiplier(mode)) {
     case 1:
@@ -738,26 +597,22 @@ i830_sdvo_post_set_mode(ScrnInfoPtr pScr
 			DisplayModePtr mode)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    struct i830_sdvo_priv *dev_priv = output->dev_priv;
-    Bool ret = TRUE;
-    Bool out1, out2;
+    Bool out1, out2, input1, input2;
     CARD32 dpll, sdvob, sdvoc;
     int dpll_reg = (output->pipe == 0) ? DPLL_A : DPLL_B;
     int sdvo_pixel_multiply;
+    CARD8 status;
 
     /* the BIOS writes out 6 commands post mode set */
     /* two 03s, 04 05, 10, 1d */
     /* these contain the height and mode clock / 10 by the looks of it */
 
-    i830_sdvo_get_trained_inputs(output);
+    i830_sdvo_get_trained_inputs(output, &input1, &input2);
 
-    /* THIS IS A DIRTY HACK - sometimes for some reason on startup
-     * the BIOS doesn't find my DVI monitor -
-     * without this hack the driver doesn't work.. this causes the modesetting
-     * to be re-run
-     */
-    if (dev_priv->sdvo_regs[SDVO_I2C_RETURN_0] != 0x1) {
-	ret = FALSE;
+    /* Warn if the device reported failure to sync. */
+    if (status == SDVO_CMD_STATUS_SUCCESS && !input1) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "First SDVO output reported failure to sync\n");
     }
 
     i830_sdvo_get_active_outputs(output, &out1, &out2);
@@ -810,28 +665,24 @@ i830_sdvo_save(ScrnInfoPtr pScrn, I830Ou
     i830_sdvo_get_active_outputs(output, &dev_priv->save_sdvo_active_1,
 				 &dev_priv->save_sdvo_active_2);
 
-    if (dev_priv->caps.caps & 0x1) {
+    if (dev_priv->caps.sdvo_inputs_mask & 0x1) {
        i830_sdvo_set_target_input(output, FALSE, FALSE);
-       i830_sdvo_get_timings(output, &dev_priv->save_input_dtd_1,
-			     SDVO_CMD_GET_INPUT_TIMINGS_PART1);
+       i830_sdvo_get_input_timing(output, &dev_priv->save_input_dtd_1);
     }
 
-    if (dev_priv->caps.caps & 0x2) {
+    if (dev_priv->caps.sdvo_inputs_mask & 0x2) {
        i830_sdvo_set_target_input(output, FALSE, TRUE);
-       i830_sdvo_get_timings(output, &dev_priv->save_input_dtd_2,
-			     SDVO_CMD_GET_INPUT_TIMINGS_PART1);
+       i830_sdvo_get_input_timing(output, &dev_priv->save_input_dtd_2);
     }
 
     if (dev_priv->caps.output_0_supported) {
        i830_sdvo_set_target_output(output, TRUE, FALSE);
-       i830_sdvo_get_timings(output, &dev_priv->save_output_dtd_1,
-			     SDVO_CMD_GET_OUTPUT_TIMINGS_PART1);
+       i830_sdvo_get_output_timing(output, &dev_priv->save_output_dtd_1);
     }
 
     if (dev_priv->caps.output_1_supported) {
        i830_sdvo_set_target_output(output, FALSE, TRUE);
-       i830_sdvo_get_timings(output, &dev_priv->save_output_dtd_2,
-			     SDVO_CMD_GET_OUTPUT_TIMINGS_PART1);
+       i830_sdvo_get_output_timing(output, &dev_priv->save_output_dtd_2);
     }
 
     dev_priv->save_SDVOX = INREG(dev_priv->output_device);
@@ -843,28 +694,24 @@ i830_sdvo_restore(ScrnInfoPtr pScrn, I83
     I830Ptr pI830 = I830PTR(pScrn);
     struct i830_sdvo_priv *dev_priv = output->dev_priv;
 
-    if (dev_priv->caps.caps & 0x1) {
+    if (dev_priv->caps.sdvo_inputs_mask & 0x1) {
        i830_sdvo_set_target_input(output, FALSE, FALSE);
-       i830_sdvo_set_timings(output, &dev_priv->save_input_dtd_1,
-			     SDVO_CMD_SET_INPUT_TIMINGS_PART1);
+       i830_sdvo_set_input_timing(output, &dev_priv->save_input_dtd_1);
     }
 
-    if (dev_priv->caps.caps & 0x2) {
+    if (dev_priv->caps.sdvo_inputs_mask & 0x2) {
        i830_sdvo_set_target_input(output, FALSE, TRUE);
-       i830_sdvo_set_timings(output, &dev_priv->save_input_dtd_2,
-			     SDVO_CMD_SET_INPUT_TIMINGS_PART1);
+       i830_sdvo_set_input_timing(output, &dev_priv->save_input_dtd_2);
     }
 
     if (dev_priv->caps.output_0_supported) {
        i830_sdvo_set_target_output(output, TRUE, FALSE);
-       i830_sdvo_set_timings(output, &dev_priv->save_output_dtd_1,
-			     SDVO_CMD_SET_OUTPUT_TIMINGS_PART1);
+       i830_sdvo_set_output_timing(output, &dev_priv->save_output_dtd_1);
     }
 
     if (dev_priv->caps.output_1_supported) {
        i830_sdvo_set_target_output(output, FALSE, TRUE);
-       i830_sdvo_set_timings(output, &dev_priv->save_output_dtd_2,
-			     SDVO_CMD_SET_OUTPUT_TIMINGS_PART1);
+       i830_sdvo_set_output_timing(output, &dev_priv->save_output_dtd_2);
     }
 
     i830_sdvo_set_clock_rate_mult(output, dev_priv->save_sdvo_mult);
@@ -890,24 +737,17 @@ i830_sdvo_mode_valid(ScrnInfoPtr pScrn, 
     return MODE_OK;
 }
 
-static void
+static Bool
 i830_sdvo_get_capabilities(I830OutputPtr output, i830_sdvo_caps *caps)
 {
-    struct i830_sdvo_priv *dev_priv = output->dev_priv;
+    CARD8 status;
+
+    i830_sdvo_write_cmd(output, SDVO_CMD_GET_DEVICE_CAPS, NULL, 0);
+    status = i830_sdvo_read_response(output, caps, sizeof(*caps));
+    if (status != SDVO_CMD_STATUS_SUCCESS)
+	return FALSE;
 
-    memset(dev_priv->sdvo_regs, 0, 9);
-    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_DEVICE_CAPS;
-    i830_sdvo_write_outputs(output, 0);
-    i830_sdvo_read_input_regs(output);
-
-    caps->vendor_id = dev_priv->sdvo_regs[SDVO_I2C_RETURN_0];
-    caps->device_id = dev_priv->sdvo_regs[SDVO_I2C_RETURN_1];
-    caps->device_rev_id = dev_priv->sdvo_regs[SDVO_I2C_RETURN_2];
-    caps->sdvo_version_major = dev_priv->sdvo_regs[SDVO_I2C_RETURN_3];
-    caps->sdvo_version_minor = dev_priv->sdvo_regs[SDVO_I2C_RETURN_4];
-    caps->caps = dev_priv->sdvo_regs[SDVO_I2C_RETURN_5];
-    caps->output_0_supported = dev_priv->sdvo_regs[SDVO_I2C_RETURN_6];
-    caps->output_1_supported = dev_priv->sdvo_regs[SDVO_I2C_RETURN_7];
+    return TRUE;
 }
 
 /** Forces the device over to the real I2C bus and uses its GetByte */
@@ -1001,12 +841,10 @@ i830_sdvo_ddc_i2c_address(I2CDevPtr d, I
 static void
 i830_sdvo_dump_cmd(I830OutputPtr output, int opcode)
 {
-    struct i830_sdvo_priv *dev_priv = output->dev_priv;
+    CARD8 response[8];
 
-    memset(dev_priv->sdvo_regs, 0, sizeof(dev_priv->sdvo_regs));
-    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = opcode;
-    i830_sdvo_write_outputs(output, 0);
-    i830_sdvo_read_input_regs(output);
+    i830_sdvo_write_cmd(output, opcode, NULL, 0);
+    i830_sdvo_read_response(output, response, 8);
 }
 
 static void
@@ -1062,17 +900,16 @@ i830_sdvo_dump(ScrnInfoPtr pScrn)
 Bool
 i830_sdvo_detect_displays(ScrnInfoPtr pScrn, I830OutputPtr output)
 {
-    struct i830_sdvo_priv *dev_priv = output->dev_priv;
+    CARD8 response[2];
+    CARD8 status;
 
-    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_ATTACHED_DISPLAYS;
-    i830_sdvo_write_outputs(output, 0);
-    i830_sdvo_read_input_regs(output);
+    i830_sdvo_write_cmd(output, SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0);
+    status = i830_sdvo_read_response(output, &response, 2);
 
-    if (dev_priv->sdvo_regs[SDVO_I2C_CMD_STATUS] != SDVO_CMD_STATUS_SUCCESS)
+    if (status != SDVO_CMD_STATUS_SUCCESS)
 	return FALSE;
 
-    return (dev_priv->sdvo_regs[SDVO_I2C_RETURN_0] != 0 ||
-	    dev_priv->sdvo_regs[SDVO_I2C_RETURN_1] != 0);
+    return (response[0] != 0 || response[1] != 0);
 }
 
 void
@@ -1182,10 +1019,13 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
 					  &dev_priv->pixel_clock_max);
 
     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-	       "SDVO device VID/DID: %02X:%02X.%02X, %02X,"
+	       "SDVO device VID/DID: %02X:%02X.%02X, "
+	       "input 1: %c, input 2: %c, "
 	       "output 1: %c, output 2: %c\n",
 	       dev_priv->caps.vendor_id, dev_priv->caps.device_id,
-	       dev_priv->caps.device_rev_id, dev_priv->caps.caps,
+	       dev_priv->caps.device_rev_id,
+	       (dev_priv->caps.sdvo_inputs_mask & 0x1) ? 'Y' : 'N',
+	       (dev_priv->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N',
 	       dev_priv->caps.output_0_supported ? 'Y' : 'N',
 	       dev_priv->caps.output_1_supported ? 'Y' : 'N');
 
diff --git a/src/i830_sdvo.h b/src/i830_sdvo.h
index db7eb97..b1d86b4 100644
--- a/src/i830_sdvo.h
+++ b/src/i830_sdvo.h
@@ -25,36 +25,6 @@
  *
  */
 
-typedef struct _i830_sdvo_caps {
-  CARD8 vendor_id;
-  CARD8 device_id;
-  CARD8 device_rev_id;
-  CARD8 sdvo_version_major;
-  CARD8 sdvo_version_minor;
-  CARD8 caps;
-  CARD8 output_0_supported;
-  CARD8 output_1_supported;
-} __attribute__((packed)) i830_sdvo_caps;
-
-typedef struct _i830_sdvo_dtd {
-    CARD16 clock;
-    CARD8 h_active;
-    CARD8 h_blank;
-    CARD8 h_high;
-    CARD8 v_active;
-    CARD8 v_blank;
-    CARD8 v_high;
-
-    CARD8 h_sync_off;
-    CARD8 h_sync_width;
-    CARD8 v_sync_off_width;
-    CARD8 sync_off_width_high;
-    CARD8 dtd_flags;
-    CARD8 sdvo_flags;
-    CARD8 v_sync_off_high;
-    CARD8 reserved;
-} __attribute__((packed)) i830_sdvo_dtd;
-
 void
 i830_sdvo_init(ScrnInfoPtr pScrn, int output_device);
 
diff --git a/src/i830_sdvo_regs.h b/src/i830_sdvo_regs.h
index a35d5a4..be3294b 100644
--- a/src/i830_sdvo_regs.h
+++ b/src/i830_sdvo_regs.h
@@ -25,6 +25,57 @@
  *
  */
 
+typedef struct _i830_sdvo_caps {
+    CARD8 vendor_id;
+    CARD8 device_id;
+    CARD8 device_rev_id;
+    CARD8 sdvo_version_major;
+    CARD8 sdvo_version_minor;
+    unsigned int sdvo_inputs_mask:2;
+    unsigned int smooth_scaling:1;
+    unsigned int sharp_scaling:1;
+    unsigned int up_scaling:1;
+    unsigned int down_scaling:1;
+    unsigned int stall_support:1;
+    unsigned int pad:1;
+    CARD8 output_0_supported;
+    CARD8 output_1_supported;
+} __attribute__((packed)) i830_sdvo_caps;
+
+struct i830_sdvo_dtd {
+    struct {
+	CARD16 clock;
+	CARD8 h_active;
+	CARD8 h_blank;
+	CARD8 h_high;
+	CARD8 v_active;
+	CARD8 v_blank;
+	CARD8 v_high;
+    } part1;
+
+    struct {
+	CARD8 h_sync_off;
+	CARD8 h_sync_width;
+	CARD8 v_sync_off_width;
+	CARD8 sync_off_width_high;
+	CARD8 dtd_flags;
+	CARD8 sdvo_flags;
+	CARD8 v_sync_off_high;
+	CARD8 reserved;
+    } part2;
+} __attribute__((packed));
+
+struct i830_sdvo_pixel_clock_range {
+    CARD16 min;
+    CARD16 max;
+} __attribute__((packed));
+
+struct i830_sdvo_preferred_input_timing_args {
+    CARD16 clock;
+    CARD16 width;
+    CARD16 height;
+} __attribute__((packed));
+
 /* I2C registers for SDVO */
 #define SDVO_I2C_ARG_0				0x07
 #define SDVO_I2C_ARG_1				0x06
@@ -56,22 +107,11 @@
 #define SDVO_CMD_STATUS_SCALING_NOT_SUPP	0x6
 
 /* SDVO commands, argument/result registers */
+
 #define SDVO_CMD_RESET					0x01
+
+/** Returns a struct i830_sdvo_caps */
 #define SDVO_CMD_GET_DEVICE_CAPS			0x02
-# define SDVO_DEVICE_CAPS_VENDOR_ID			SDVO_I2C_RETURN_0
-# define SDVO_DEVICE_CAPS_DEVICE_ID			SDVO_I2C_RETURN_1
-# define SDVO_DEVICE_CAPS_DEVICE_REV_ID			SDVO_I2C_RETURN_2
-# define SDVO_DEVICE_CAPS_SDVOVERSION_MINOR		SDVO_I2C_RETURN_3
-# define SDVO_DEVICE_CAPS_SDVOVERSION_MAJOR		SDVO_I2C_RETURN_4
-# define SDVO_DEVICE_CAPS_CAPS				SDVO_I2C_RETURN_5
-# define SDVO_DEVICE_CAPS_INPUTS_MASK				(3 << 0)
-# define SDVO_DEVICE_CAPS_SMOOTH_SCALING			(1 << 2)
-# define SDVO_DEVICE_CAPS_SHARP_SCALING				(1 << 3)
-# define SDVO_DEVICE_CAPS_UP_SCALING				(1 << 4)
-# define SDVO_DEVICE_CAPS_DOWN_SCALING				(1 << 5)
-# define SDVO_DEVICE_CAPS_STALL_SUPPORT				(1 << 6)
-# define SDVO_DEVICE_CAPS_OUTPUT_0_SUPPORTED		SDVO_I2C_RETURN_6
-# define SDVO_DEVICE_CAPS_OUTPUT_1_SUPPORTED		SDVO_I2C_RETURN_7
 
 #define SDVO_CMD_GET_FIRMWARE_REV			0x86
 # define SDVO_DEVICE_FIRMWARE_MINOR			SDVO_I2C_RETURN_0
@@ -148,7 +188,9 @@
 #define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1	0x1b
 #define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2	0x1c
 
+/** Returns a struct i830_sdvo_pixel_clock_range */
 #define SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE		0x1d
+/** Returns a struct i830_sdvo_pixel_clock_range */
 #define SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE		0x1e
 
 #define SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS		0x1f
diff-tree ddb986e54f5320359abac06f512f2d3f446872db (from cd2f0d948a6cae61b0d77d2c7184ed8d695be8c3)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Oct 24 17:47:58 2006 -0700

    Nuke trailing whitespace in SDVO code not already cleaned up.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index e028a9b..523eed2 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -1,7 +1,7 @@
 /**************************************************************************
 
  Copyright 2006 Dave Airlie <airlied at linux.ie>
- 
+
 Permission is hereby granted, free of charge, to any person obtaining a
 copy of this software and associated documentation files (the "Software"),
 to deal in the Software without restriction, including without limitation
@@ -463,7 +463,7 @@ i830_sdvo_set_timings_part1(I830OutputPt
 
     i830_sdvo_write_outputs(output, 8);
     i830_sdvo_read_input_regs(output);
-  
+
     return TRUE;
 }
 
@@ -492,9 +492,9 @@ i830_sdvo_set_timings_part2(I830OutputPt
     struct i830_sdvo_priv *dev_priv = output->dev_priv;
 
     memset(dev_priv->sdvo_regs, 0, 9);
-  
+
     dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = cmd;
- 
+
     /* set clock regs */
     dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = magic4 & 0xff;
     dev_priv->sdvo_regs[SDVO_I2C_ARG_1] = (magic4 >> 8) & 0xff;
@@ -505,7 +505,7 @@ i830_sdvo_set_timings_part2(I830OutputPt
 
     i830_sdvo_write_outputs(output, 8);
     i830_sdvo_read_input_regs(output);
-  
+
     return TRUE;
 }
 
@@ -691,7 +691,7 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn
     i830_sdvo_set_target_input(output, FALSE, FALSE);
 
     i830_sdvo_get_active_outputs(output, &out1, &out2);
-    
+
     i830_sdvo_set_active_outputs(output, FALSE, FALSE);
 
     i830_sdvo_set_target_output(output, TRUE, FALSE);
@@ -702,13 +702,13 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn
 				       out_timings[5]);
 
     i830_sdvo_set_target_input(output, FALSE, FALSE);
-    
+
     i830_sdvo_create_preferred_input_timing(output, clock, width, height);
     i830_sdvo_get_preferred_input_timing_part1(output);
     i830_sdvo_get_preferred_input_timing_part2(output);
-    
+
     i830_sdvo_set_target_input(output, FALSE, FALSE);
-    
+
     i830_sdvo_set_input_timings_part1(output, clock,
 				      curr_table[0], curr_table[1],
 				      curr_table[2]);
@@ -821,7 +821,7 @@ i830_sdvo_save(ScrnInfoPtr pScrn, I830Ou
        i830_sdvo_get_timings(output, &dev_priv->save_input_dtd_2,
 			     SDVO_CMD_GET_INPUT_TIMINGS_PART1);
     }
-    
+
     if (dev_priv->caps.output_0_supported) {
        i830_sdvo_set_target_output(output, TRUE, FALSE);
        i830_sdvo_get_timings(output, &dev_priv->save_output_dtd_1,
diff-tree cd2f0d948a6cae61b0d77d2c7184ed8d695be8c3 (from cd9c6e29146e1debaba4b0b9ad0d241f07bdbc14)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Oct 24 17:47:47 2006 -0700

    Clean up SDVO code, moving the private structure internal and cleaning up caps.
    
    All the SDVO code should now be in lower case rather than StudlyCaps.
    
    This also adjusts the I2C setup to create a bus per SDVO output we set up.
    The previous setup with shared buses was failing in some circumstances, which
    is probably due to the lack of refcounting in xf86i2c.c.

diff --git a/src/i830.h b/src/i830.h
index 832061c..b4408c2 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -205,22 +205,6 @@ struct _I830DVODriver {
    pointer modhandle;
 };
 
-typedef struct _I830SDVODriver {
-   I2CDevRec d;
-   unsigned char sdvo_regs[20];
-   CARD32 output_device;		/* SDVOB or SDVOC */
-
-   i830_sdvo_caps caps;
-
-   CARD16 pixel_clock_min, pixel_clock_max;
-
-   int save_sdvo_mult;
-   Bool save_sdvo_active_1, save_sdvo_active_2;
-   i830_sdvo_dtd save_input_dtd_1, save_input_dtd_2;
-   i830_sdvo_dtd save_output_dtd_1, save_output_dtd_2;
-   CARD32 save_SDVOX;
-} I830SDVORec, *I830SDVOPtr;
-
 extern const char *i830_output_type_names[];
 
 struct _I830OutputRec {
@@ -278,8 +262,7 @@ struct _I830OutputRec {
    I2CBusPtr pI2CBus;
    I2CBusPtr pDDCBus;
    struct _I830DVODriver *i2c_drv;
-   I830SDVOPtr sdvo_drv;
-   /** Output-private structure.  Should replace i2c_drv and sdvo_drv */
+   /** Output-private structure.  Should replace i2c_drv */
    void *dev_priv;
 };
 
@@ -499,7 +482,6 @@ typedef struct _I830Rec {
    int ddc2;
    int num_outputs;
    struct _I830OutputRec output[MAX_OUTPUTS];
-   I830SDVOPtr sdvo;
 
    /* Panel size pulled from the BIOS */
    int PanelXRes, PanelYRes;
diff --git a/src/i830_display.c b/src/i830_display.c
index 9b20d65..a94e21d 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -785,7 +785,7 @@ done:
 #endif
 
     i830DumpRegs (pScrn);
-    I830DumpSDVO (pScrn);
+    i830_sdvo_dump(pScrn);
     return ok;
 }
 
diff --git a/src/i830_display.h b/src/i830_display.h
index 9719406..229e576 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -34,7 +34,3 @@ void i830SetLVDSPanelPower(ScrnInfoPtr p
 void i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y);
 void i830WaitForVblank(ScrnInfoPtr pScrn);
 void i830DescribeOutputConfiguration(ScrnInfoPtr pScrn);
-
-/* i830_sdvo.c */
-Bool I830SDVOPreSetMode(I830SDVOPtr s, DisplayModePtr mode);
-Bool I830SDVOPostSetMode(I830SDVOPtr s, DisplayModePtr mode);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 972df13..4ee5fc2 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1673,7 +1673,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
        */
       for (i = 0; i < pI830->num_outputs; i++) {
 	 if (pI830->output[i].type == I830_OUTPUT_SDVO) {
-	    if (!I830DetectSDVODisplays(pScrn, i))
+	    if (!i830_sdvo_detect_displays(pScrn, &pI830->output[i]))
 	       continue;
 
 	    if (pI830->MonType1 == PIPE_NONE)
@@ -4373,7 +4373,7 @@ i830MonitorDetectDebugger(ScrnInfoPtr pS
       if (pI830->output[i].type != I830_OUTPUT_SDVO)
 	 continue;
       start = GetTimeInMillis();
-      found_sdvo = I830DetectSDVODisplays(pScrn, i);   
+      found_sdvo = i830_sdvo_detect_displays(pScrn, &pI830->output[i]);
       finish = GetTimeInMillis();
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Detected SDVO as %s in %dms\n",
 		 found_sdvo ? "connected" : "disconnected", finish - start);
diff --git a/src/i830_modes.c b/src/i830_modes.c
index bc4536d..f430693 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -807,7 +807,7 @@ I830ReprobePipeModeList(ScrnInfoPtr pScr
     if (pI830->pipeMon[pipe] == NULL) {
 	switch (pI830->output[output_index].type) {
 	case I830_OUTPUT_SDVO:
-	    if (I830DetectSDVODisplays(pScrn, output_index))
+	    if (i830_sdvo_detect_displays(pScrn, &pI830->output[output_index]))
 		pI830->pipeMon[pipe] = i830GetConfiguredMonitor(pScrn);
 	    break;
 	case I830_OUTPUT_ANALOG:
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 76080df..e028a9b 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -23,6 +23,19 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 **************************************************************************/
 
+/** @file
+ * SDVO support for i915 and newer chipsets.
+ *
+ * The SDVO outputs send digital display data out over the PCIE bus to display
+ * cards implementing a defined interface.  These cards may have DVI, TV, CRT,
+ * or other outputs on them.
+ *
+ * The system has two SDVO channels, which may be used for SDVO chips on the
+ * motherboard, or in the external cards.  The two channels may also be used
+ * in a ganged mode to provide higher bandwidth to a single output.  Currently,
+ * this code doesn't deal with either ganged mode or more than one SDVO output.
+ */
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
@@ -37,26 +50,58 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "i810_reg.h"
 #include "i830_sdvo_regs.h"
 
+/** SDVO driver private structure. */
+struct i830_sdvo_priv {
+    /** SDVO device on SDVO I2C bus. */
+    I2CDevRec d;
+    /** Temporary storage for reg read/writes */
+    unsigned char sdvo_regs[20];
+    /** Register for the SDVO device: SDVOB or SDVOC */
+    int output_device;
+    /**
+     * Capabilities of the SDVO device returned by i830_sdvo_get_capabilities()
+     */
+    i830_sdvo_caps caps;
+    /** Pixel clock limitations reported by the SDVO device */
+    CARD16 pixel_clock_min, pixel_clock_max;
+
+    /** State for save/restore */
+    /** @{ */
+    int save_sdvo_mult;
+    Bool save_sdvo_active_1, save_sdvo_active_2;
+    i830_sdvo_dtd save_input_dtd_1, save_input_dtd_2;
+    i830_sdvo_dtd save_output_dtd_1, save_output_dtd_2;
+    CARD32 save_SDVOX;
+    /** @} */
+};
+
 CARD16 curr_table[6];
 
-/* SDVO support for i9xx chipsets */
-static Bool sReadByte(I830SDVOPtr s, int addr, unsigned char *ch)
-{
-    if (!xf86I2CReadByte(&s->d, addr, ch)) {
-	xf86DrvMsg(s->d.pI2CBus->scrnIndex, X_ERROR,
-		   "Unable to read from %s Slave %d.\n", s->d.pI2CBus->BusName,
-		   s->d.SlaveAddr);
+/** Read a single byte from the given address on the SDVO device. */
+static Bool i830_sdvo_read_byte(I830OutputPtr output, int addr,
+				unsigned char *ch)
+{
+    struct i830_sdvo_priv *dev_priv = output->dev_priv;
+
+    if (!xf86I2CReadByte(&dev_priv->d, addr, ch)) {
+	xf86DrvMsg(output->pI2CBus->scrnIndex, X_ERROR,
+		   "Unable to read from %s slave %d.\n",
+		   output->pI2CBus->BusName, dev_priv->d.SlaveAddr);
 	return FALSE;
     }
     return TRUE;
 }
 
-static Bool sWriteByte(I830SDVOPtr s, int addr, unsigned char ch)
-{
-    if (!xf86I2CWriteByte(&s->d, addr, ch)) {
-	xf86DrvMsg(s->d.pI2CBus->scrnIndex, X_ERROR,
-		   "Unable to write to %s Slave %d.\n", s->d.pI2CBus->BusName,
-		   s->d.SlaveAddr);
+/** Write a single byte to the given address on the SDVO device. */
+static Bool i830_sdvo_write_byte(I830OutputPtr output,
+				 int addr, unsigned char ch)
+{
+    struct i830_sdvo_priv *dev_priv = output->dev_priv;
+
+    if (!xf86I2CWriteByte(&dev_priv->d, addr, ch)) {
+	xf86DrvMsg(output->pI2CBus->scrnIndex, X_ERROR,
+		   "Unable to write to %s Slave %d.\n",
+		   output->pI2CBus->BusName, dev_priv->d.SlaveAddr);
 	return FALSE;
     }
     return TRUE;
@@ -64,6 +109,7 @@ static Bool sWriteByte(I830SDVOPtr s, in
 
 
 #define SDVO_CMD_NAME_ENTRY(cmd) {cmd, #cmd}
+/** Mapping of command numbers to names, for debug output */
 const struct _sdvo_cmd_name {
     CARD8 cmd;
     char *name;
@@ -106,19 +152,21 @@ const struct _sdvo_cmd_name {
     SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_RESOLUTION_SUPPORT),
     SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTROL_BUS_SWITCH),
 };
+
 /* following on from tracing the intel BIOS i2c routines */
 static void
-I830SDVOWriteOutputs(I830SDVOPtr s, int num_out)
+i830_sdvo_write_outputs(I830OutputPtr output, int num_out)
 {
+    struct i830_sdvo_priv *dev_priv = output->dev_priv;
     int i;
 
-    ErrorF("SDVO: W: %02X ", s->sdvo_regs[SDVO_I2C_OPCODE]);
+    ErrorF("SDVO: W: %02X ", dev_priv->sdvo_regs[SDVO_I2C_OPCODE]);
     for (i = SDVO_I2C_ARG_0; i > SDVO_I2C_ARG_0 - num_out; i--)
-	ErrorF("%02X ", s->sdvo_regs[i]);
+	ErrorF("%02X ", dev_priv->sdvo_regs[i]);
     for (; i > SDVO_I2C_ARG_7; i--)
 	ErrorF("   ");
     for (i = 0; i < sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]); i++) {
-	if (s->sdvo_regs[SDVO_I2C_OPCODE] == sdvo_cmd_names[i].cmd) {
+	if (dev_priv->sdvo_regs[SDVO_I2C_OPCODE] == sdvo_cmd_names[i].cmd) {
 	    ErrorF("(%s)", sdvo_cmd_names[i].name);
 	    break;
 	}
@@ -127,10 +175,11 @@ I830SDVOWriteOutputs(I830SDVOPtr s, int 
 
     /* blast the output regs */
     for (i = SDVO_I2C_ARG_0; i > SDVO_I2C_ARG_0 - num_out; i--) {
-	sWriteByte(s, i, s->sdvo_regs[i]);
+	i830_sdvo_write_byte(output, i, dev_priv->sdvo_regs[i]);
     }
     /* blast the command reg */
-    sWriteByte(s, SDVO_I2C_OPCODE, s->sdvo_regs[SDVO_I2C_OPCODE]);
+    i830_sdvo_write_byte(output, SDVO_I2C_OPCODE,
+			 dev_priv->sdvo_regs[SDVO_I2C_OPCODE]);
 }
 
 static const char *cmd_status_names[] = {
@@ -144,29 +193,43 @@ static const char *cmd_status_names[] = 
 };
 
 static void
-I830SDVOReadInputRegs(I830SDVOPtr s)
+i830_sdvo_read_input_regs(I830OutputPtr output)
 {
+    struct i830_sdvo_priv *dev_priv = output->dev_priv;
     int i;
 
     /* follow BIOS ordering */
-    sReadByte(s, SDVO_I2C_CMD_STATUS, &s->sdvo_regs[SDVO_I2C_CMD_STATUS]);
-  
-    sReadByte(s, SDVO_I2C_RETURN_3, &s->sdvo_regs[SDVO_I2C_RETURN_3]);
-    sReadByte(s, SDVO_I2C_RETURN_2, &s->sdvo_regs[SDVO_I2C_RETURN_2]);
-    sReadByte(s, SDVO_I2C_RETURN_1, &s->sdvo_regs[SDVO_I2C_RETURN_1]);
-    sReadByte(s, SDVO_I2C_RETURN_0, &s->sdvo_regs[SDVO_I2C_RETURN_0]);
-    sReadByte(s, SDVO_I2C_RETURN_7, &s->sdvo_regs[SDVO_I2C_RETURN_7]);
-    sReadByte(s, SDVO_I2C_RETURN_6, &s->sdvo_regs[SDVO_I2C_RETURN_6]);
-    sReadByte(s, SDVO_I2C_RETURN_5, &s->sdvo_regs[SDVO_I2C_RETURN_5]);
-    sReadByte(s, SDVO_I2C_RETURN_4, &s->sdvo_regs[SDVO_I2C_RETURN_4]);
+    i830_sdvo_read_byte(output, SDVO_I2C_CMD_STATUS,
+			&dev_priv->sdvo_regs[SDVO_I2C_CMD_STATUS]);
+
+    i830_sdvo_read_byte(output, SDVO_I2C_RETURN_3,
+			&dev_priv->sdvo_regs[SDVO_I2C_RETURN_3]);
+    i830_sdvo_read_byte(output, SDVO_I2C_RETURN_2,
+			&dev_priv->sdvo_regs[SDVO_I2C_RETURN_2]);
+    i830_sdvo_read_byte(output, SDVO_I2C_RETURN_1,
+			&dev_priv->sdvo_regs[SDVO_I2C_RETURN_1]);
+    i830_sdvo_read_byte(output, SDVO_I2C_RETURN_0,
+			&dev_priv->sdvo_regs[SDVO_I2C_RETURN_0]);
+    i830_sdvo_read_byte(output, SDVO_I2C_RETURN_7,
+			&dev_priv->sdvo_regs[SDVO_I2C_RETURN_7]);
+    i830_sdvo_read_byte(output, SDVO_I2C_RETURN_6,
+			&dev_priv->sdvo_regs[SDVO_I2C_RETURN_6]);
+    i830_sdvo_read_byte(output, SDVO_I2C_RETURN_5,
+			&dev_priv->sdvo_regs[SDVO_I2C_RETURN_5]);
+    i830_sdvo_read_byte(output, SDVO_I2C_RETURN_4,
+			&dev_priv->sdvo_regs[SDVO_I2C_RETURN_4]);
 
     ErrorF("SDVO: R: ");
     for (i = SDVO_I2C_RETURN_0; i <= SDVO_I2C_RETURN_7; i++)
-	ErrorF("%02X ", s->sdvo_regs[i]);
-    if (s->sdvo_regs[SDVO_I2C_CMD_STATUS] <= SDVO_CMD_STATUS_SCALING_NOT_SUPP)
-	ErrorF("(%s)", cmd_status_names[s->sdvo_regs[SDVO_I2C_CMD_STATUS]]);
-    else
-	ErrorF("(??? %d)", s->sdvo_regs[SDVO_I2C_CMD_STATUS]);
+	ErrorF("%02X ", dev_priv->sdvo_regs[i]);
+    if (dev_priv->sdvo_regs[SDVO_I2C_CMD_STATUS] <=
+	SDVO_CMD_STATUS_SCALING_NOT_SUPP)
+    {
+	ErrorF("(%s)",
+	       cmd_status_names[dev_priv->sdvo_regs[SDVO_I2C_CMD_STATUS]]);
+    } else {
+	ErrorF("(??? %d)", dev_priv->sdvo_regs[SDVO_I2C_CMD_STATUS]);
+    }
     ErrorF("\n");
 }
 
@@ -186,355 +249,395 @@ i830_sdvo_get_pixel_multiplier(DisplayMo
  * STOP.  PROM access is terminated by accessing an internal register.
  */
 static Bool
-I830SDVOSetControlBusSwitch(I830SDVOPtr s, CARD8 target)
+i830_sdvo_set_control_bus_switch(I830OutputPtr output, CARD8 target)
 {
-    memset(s->sdvo_regs, 0, 9);
+    struct i830_sdvo_priv *dev_priv = output->dev_priv;
+
+    memset(dev_priv->sdvo_regs, 0, 9);
 
-    s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_CONTROL_BUS_SWITCH;
-    s->sdvo_regs[SDVO_I2C_ARG_0] = target;
+    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_CONTROL_BUS_SWITCH;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = target;
 
-    I830SDVOWriteOutputs(s, 1);
+    i830_sdvo_write_outputs(output, 1);
     return TRUE;
 }
 
 static Bool
-I830SDVOSetTargetInput(I830SDVOPtr s, Bool target_1, Bool target_2)
+i830_sdvo_set_target_input(I830OutputPtr output, Bool target_1, Bool target_2)
 {
-    memset(s->sdvo_regs, 0, 9);
+    struct i830_sdvo_priv *dev_priv = output->dev_priv;
 
-    s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_TARGET_INPUT;
-    s->sdvo_regs[SDVO_I2C_ARG_0] = target_1;
-    s->sdvo_regs[SDVO_I2C_ARG_1] = target_2;
+    memset(dev_priv->sdvo_regs, 0, 9);
 
-    I830SDVOWriteOutputs(s, 2);
+    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_TARGET_INPUT;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = target_1;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_1] = target_2;
 
-    I830SDVOReadInputRegs(s);
+    i830_sdvo_write_outputs(output, 2);
+
+    i830_sdvo_read_input_regs(output);
 
     return TRUE;
 }
 
 static Bool
-I830SDVOGetTrainedInputs(I830SDVOPtr s)
+i830_sdvo_get_trained_inputs(I830OutputPtr output)
 {
-    memset(s->sdvo_regs, 0, 9);
+    struct i830_sdvo_priv *dev_priv = output->dev_priv;
+
+    memset(dev_priv->sdvo_regs, 0, 9);
 
-    s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_TRAINED_INPUTS;
+    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_TRAINED_INPUTS;
 
-    I830SDVOWriteOutputs(s, 0);
-    I830SDVOReadInputRegs(s);
+    i830_sdvo_write_outputs(output, 0);
+    i830_sdvo_read_input_regs(output);
 
     return TRUE;
 }
 
 static Bool
-I830SDVOGetActiveOutputs(I830SDVOPtr s, Bool *on_1, Bool *on_2)
+i830_sdvo_get_active_outputs(I830OutputPtr output, Bool *on_1, Bool *on_2)
 {
-    memset(s->sdvo_regs, 0, 9);
+    struct i830_sdvo_priv *dev_priv = output->dev_priv;
+
+    memset(dev_priv->sdvo_regs, 0, 9);
 
-    s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_ACTIVE_OUTPUTS;
+    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_ACTIVE_OUTPUTS;
 
-    I830SDVOWriteOutputs(s, 0);
-    I830SDVOReadInputRegs(s);
+    i830_sdvo_write_outputs(output, 0);
+    i830_sdvo_read_input_regs(output);
 
-    *on_1 = s->sdvo_regs[SDVO_I2C_RETURN_0];
-    *on_2 = s->sdvo_regs[SDVO_I2C_RETURN_1];
+    *on_1 = dev_priv->sdvo_regs[SDVO_I2C_RETURN_0];
+    *on_2 = dev_priv->sdvo_regs[SDVO_I2C_RETURN_1];
 
     return TRUE;
 }
 
 static Bool
-I830SDVOSetActiveOutputs(I830SDVOPtr s, Bool on_1, Bool on_2)
+i830_sdvo_set_active_outputs(I830OutputPtr output, Bool on_1, Bool on_2)
 {
-    memset(s->sdvo_regs, 0, 9);
+    struct i830_sdvo_priv *dev_priv = output->dev_priv;
 
-    s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_ACTIVE_OUTPUTS;
-    s->sdvo_regs[SDVO_I2C_ARG_0] = on_1;
-    s->sdvo_regs[SDVO_I2C_ARG_1] = on_2;
+    memset(dev_priv->sdvo_regs, 0, 9);
 
-    I830SDVOWriteOutputs(s, 2);
-    I830SDVOReadInputRegs(s);
+    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_ACTIVE_OUTPUTS;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = on_1;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_1] = on_2;
+
+    i830_sdvo_write_outputs(output, 2);
+    i830_sdvo_read_input_regs(output);
 
     return TRUE;
 }
 
 static Bool
-I830SDVOGetInputPixelClockRange(I830SDVOPtr s, CARD16 *clock_min,
-				CARD16 *clock_max)
+i830_sdvo_get_input_pixel_clock_range(I830OutputPtr output, CARD16 *clock_min,
+				      CARD16 *clock_max)
 {
-    memset(s->sdvo_regs, 0, 9);
+    struct i830_sdvo_priv *dev_priv = output->dev_priv;
+
+    memset(dev_priv->sdvo_regs, 0, 9);
 
-    s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE;
+    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] =
+	SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE;
 
-    I830SDVOWriteOutputs(s, 0);
-    I830SDVOReadInputRegs(s);
+    i830_sdvo_write_outputs(output, 0);
+    i830_sdvo_read_input_regs(output);
 
-    *clock_min = s->sdvo_regs[SDVO_I2C_RETURN_0] |
-		 (s->sdvo_regs[SDVO_I2C_RETURN_1] << 8);
-    *clock_max = s->sdvo_regs[SDVO_I2C_RETURN_2] |
-		 (s->sdvo_regs[SDVO_I2C_RETURN_3] << 8);
+    *clock_min = dev_priv->sdvo_regs[SDVO_I2C_RETURN_0] |
+		 (dev_priv->sdvo_regs[SDVO_I2C_RETURN_1] << 8);
+    *clock_max = dev_priv->sdvo_regs[SDVO_I2C_RETURN_2] |
+		 (dev_priv->sdvo_regs[SDVO_I2C_RETURN_3] << 8);
 
     return TRUE;
 }
 
 static Bool
-I830SDVOSetTargetOutput(I830SDVOPtr s, Bool target_1, Bool target_2)
+i830_sdvo_set_target_output(I830OutputPtr output, Bool target_1, Bool target_2)
 {
-    memset(s->sdvo_regs, 0, 9);
+    struct i830_sdvo_priv *dev_priv = output->dev_priv;
+
+    memset(dev_priv->sdvo_regs, 0, 9);
 
-    s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_TARGET_OUTPUT;
-    s->sdvo_regs[SDVO_I2C_ARG_0] = target_1;
-    s->sdvo_regs[SDVO_I2C_ARG_1] = target_2;
+    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_TARGET_OUTPUT;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = target_1;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_1] = target_2;
 
-    I830SDVOWriteOutputs(s, 2);
-    I830SDVOReadInputRegs(s);
+    i830_sdvo_write_outputs(output, 2);
+    i830_sdvo_read_input_regs(output);
 
     return TRUE;
 }
 
 /* Fetches either input or output timings to *dtd, depending on cmd. */
 static Bool
-I830SDVOGetTimings(I830SDVOPtr s, i830_sdvo_dtd *dtd, CARD8 cmd)
+i830_sdvo_get_timings(I830OutputPtr output, i830_sdvo_dtd *dtd, CARD8 cmd)
 {
-    memset(s->sdvo_regs, 0, 9);
-    s->sdvo_regs[SDVO_I2C_OPCODE] = cmd;
-    I830SDVOWriteOutputs(s, 0);
-    I830SDVOReadInputRegs(s);
-
-    dtd->clock = s->sdvo_regs[SDVO_I2C_RETURN_0] |
-		 (s->sdvo_regs[SDVO_I2C_RETURN_1] << 8);
-    dtd->h_active = s->sdvo_regs[SDVO_I2C_RETURN_2];
-    dtd->h_blank = s->sdvo_regs[SDVO_I2C_RETURN_3];
-    dtd->h_high = s->sdvo_regs[SDVO_I2C_RETURN_4];
-    dtd->v_active = s->sdvo_regs[SDVO_I2C_RETURN_5];
-    dtd->v_blank = s->sdvo_regs[SDVO_I2C_RETURN_6];
-    dtd->v_high = s->sdvo_regs[SDVO_I2C_RETURN_7];
-
-    memset(s->sdvo_regs, 0, 9);
-    s->sdvo_regs[SDVO_I2C_OPCODE] = cmd + 1;
-    I830SDVOWriteOutputs(s, 0);
-    I830SDVOReadInputRegs(s);
-
-    dtd->h_sync_off = s->sdvo_regs[SDVO_I2C_RETURN_0];
-    dtd->h_sync_width = s->sdvo_regs[SDVO_I2C_RETURN_1];
-    dtd->v_sync_off_width = s->sdvo_regs[SDVO_I2C_RETURN_2];
-    dtd->sync_off_width_high = s->sdvo_regs[SDVO_I2C_RETURN_3];
-    dtd->dtd_flags = s->sdvo_regs[SDVO_I2C_RETURN_4];
-    dtd->sdvo_flags = s->sdvo_regs[SDVO_I2C_RETURN_5];
-    dtd->v_sync_off_high = s->sdvo_regs[SDVO_I2C_RETURN_6];
-    dtd->reserved = s->sdvo_regs[SDVO_I2C_RETURN_7];
+    struct i830_sdvo_priv *dev_priv = output->dev_priv;
+
+    memset(dev_priv->sdvo_regs, 0, 9);
+    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = cmd;
+    i830_sdvo_write_outputs(output, 0);
+    i830_sdvo_read_input_regs(output);
+
+    dtd->clock = dev_priv->sdvo_regs[SDVO_I2C_RETURN_0] |
+		 (dev_priv->sdvo_regs[SDVO_I2C_RETURN_1] << 8);
+    dtd->h_active = dev_priv->sdvo_regs[SDVO_I2C_RETURN_2];
+    dtd->h_blank = dev_priv->sdvo_regs[SDVO_I2C_RETURN_3];
+    dtd->h_high = dev_priv->sdvo_regs[SDVO_I2C_RETURN_4];
+    dtd->v_active = dev_priv->sdvo_regs[SDVO_I2C_RETURN_5];
+    dtd->v_blank = dev_priv->sdvo_regs[SDVO_I2C_RETURN_6];
+    dtd->v_high = dev_priv->sdvo_regs[SDVO_I2C_RETURN_7];
+
+    memset(dev_priv->sdvo_regs, 0, 9);
+    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = cmd + 1;
+    i830_sdvo_write_outputs(output, 0);
+    i830_sdvo_read_input_regs(output);
+
+    dtd->h_sync_off = dev_priv->sdvo_regs[SDVO_I2C_RETURN_0];
+    dtd->h_sync_width = dev_priv->sdvo_regs[SDVO_I2C_RETURN_1];
+    dtd->v_sync_off_width = dev_priv->sdvo_regs[SDVO_I2C_RETURN_2];
+    dtd->sync_off_width_high = dev_priv->sdvo_regs[SDVO_I2C_RETURN_3];
+    dtd->dtd_flags = dev_priv->sdvo_regs[SDVO_I2C_RETURN_4];
+    dtd->sdvo_flags = dev_priv->sdvo_regs[SDVO_I2C_RETURN_5];
+    dtd->v_sync_off_high = dev_priv->sdvo_regs[SDVO_I2C_RETURN_6];
+    dtd->reserved = dev_priv->sdvo_regs[SDVO_I2C_RETURN_7];
 
     return TRUE;
 }
 
 /* Sets either input or output timings to *dtd, depending on cmd. */
 static Bool
-I830SDVOSetTimings(I830SDVOPtr s, i830_sdvo_dtd *dtd, CARD8 cmd)
+i830_sdvo_set_timings(I830OutputPtr output, i830_sdvo_dtd *dtd, CARD8 cmd)
 {
-    memset(s->sdvo_regs, 0, 9);
-    s->sdvo_regs[SDVO_I2C_OPCODE] = cmd;
-    s->sdvo_regs[SDVO_I2C_ARG_0] = dtd->clock & 0xff;
-    s->sdvo_regs[SDVO_I2C_ARG_1] = dtd->clock >> 8;
-    s->sdvo_regs[SDVO_I2C_ARG_2] = dtd->h_active;
-    s->sdvo_regs[SDVO_I2C_ARG_3] = dtd->h_blank;
-    s->sdvo_regs[SDVO_I2C_ARG_4] = dtd->h_high;
-    s->sdvo_regs[SDVO_I2C_ARG_5] = dtd->v_active;
-    s->sdvo_regs[SDVO_I2C_ARG_6] = dtd->v_blank;
-    s->sdvo_regs[SDVO_I2C_ARG_7] = dtd->v_high;
-    I830SDVOWriteOutputs(s, 8);
-    I830SDVOReadInputRegs(s);
-
-    memset(s->sdvo_regs, 0, 9);
-    s->sdvo_regs[SDVO_I2C_OPCODE] = cmd + 1;
-    s->sdvo_regs[SDVO_I2C_ARG_0] = dtd->h_sync_off;
-    s->sdvo_regs[SDVO_I2C_ARG_1] = dtd->h_sync_width;
-    s->sdvo_regs[SDVO_I2C_ARG_2] = dtd->v_sync_off_width;
-    s->sdvo_regs[SDVO_I2C_ARG_3] = dtd->sync_off_width_high;
-    s->sdvo_regs[SDVO_I2C_ARG_4] = dtd->dtd_flags;
-    s->sdvo_regs[SDVO_I2C_ARG_5] = dtd->sdvo_flags;
-    s->sdvo_regs[SDVO_I2C_ARG_6] = dtd->v_sync_off_high;
-    s->sdvo_regs[SDVO_I2C_ARG_7] = dtd->reserved;
-    I830SDVOWriteOutputs(s, 7);
-    I830SDVOReadInputRegs(s);
+    struct i830_sdvo_priv *dev_priv = output->dev_priv;
+
+    memset(dev_priv->sdvo_regs, 0, 9);
+    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = cmd;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = dtd->clock & 0xff;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_1] = dtd->clock >> 8;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_2] = dtd->h_active;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_3] = dtd->h_blank;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_4] = dtd->h_high;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_5] = dtd->v_active;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_6] = dtd->v_blank;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_7] = dtd->v_high;
+    i830_sdvo_write_outputs(output, 8);
+    i830_sdvo_read_input_regs(output);
+
+    memset(dev_priv->sdvo_regs, 0, 9);
+    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = cmd + 1;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = dtd->h_sync_off;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_1] = dtd->h_sync_width;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_2] = dtd->v_sync_off_width;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_3] = dtd->sync_off_width_high;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_4] = dtd->dtd_flags;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_5] = dtd->sdvo_flags;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_6] = dtd->v_sync_off_high;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_7] = dtd->reserved;
+    i830_sdvo_write_outputs(output, 7);
+    i830_sdvo_read_input_regs(output);
 
     return TRUE;
 }
 
 static Bool
-I830SDVOSetTimingsPart1(I830SDVOPtr s, char cmd, CARD16 clock, CARD16 magic1,
-			CARD16 magic2, CARD16 magic3)
+i830_sdvo_set_timings_part1(I830OutputPtr output, char cmd, CARD16 clock,
+			    CARD16 magic1, CARD16 magic2, CARD16 magic3)
 {
-    memset(s->sdvo_regs, 0, 9);
+    struct i830_sdvo_priv *dev_priv = output->dev_priv;
+
+    memset(dev_priv->sdvo_regs, 0, 9);
 
-    s->sdvo_regs[SDVO_I2C_OPCODE] = cmd;
+    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = cmd;
 
     /* set clock regs */
-    s->sdvo_regs[SDVO_I2C_ARG_0] = clock & 0xff;
-    s->sdvo_regs[SDVO_I2C_ARG_1] = (clock >> 8) & 0xff;
-    s->sdvo_regs[SDVO_I2C_ARG_2] = magic3 & 0xff;  
-    s->sdvo_regs[SDVO_I2C_ARG_3] = (magic3 >> 8) & 0xff;
-    s->sdvo_regs[SDVO_I2C_ARG_4] = magic2 & 0xff;  
-    s->sdvo_regs[SDVO_I2C_ARG_5] = (magic2 >> 8) & 0xff;
-    s->sdvo_regs[SDVO_I2C_ARG_6] = magic1 & 0xff;
-    s->sdvo_regs[SDVO_I2C_ARG_7] = (magic1 >> 8) & 0xff;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = clock & 0xff;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_1] = (clock >> 8) & 0xff;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_2] = magic3 & 0xff;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_3] = (magic3 >> 8) & 0xff;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_4] = magic2 & 0xff;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_5] = (magic2 >> 8) & 0xff;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_6] = magic1 & 0xff;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_7] = (magic1 >> 8) & 0xff;
 
-    I830SDVOWriteOutputs(s, 8);
-    I830SDVOReadInputRegs(s);
+    i830_sdvo_write_outputs(output, 8);
+    i830_sdvo_read_input_regs(output);
   
     return TRUE;
 }
 
 static Bool
-I830SDVOSetInputTimingsPart1(I830SDVOPtr s, CARD16 clock,
-			     CARD16 magic1, CARD16 magic2, CARD16 magic3)
+i830_sdvo_set_input_timings_part1(I830OutputPtr output, CARD16 clock,
+				  CARD16 magic1, CARD16 magic2, CARD16 magic3)
 {
-    return I830SDVOSetTimingsPart1(s, SDVO_CMD_SET_INPUT_TIMINGS_PART1,
-				   clock, magic1, magic2, magic3);
+    return i830_sdvo_set_timings_part1(output,
+				       SDVO_CMD_SET_INPUT_TIMINGS_PART1,
+				       clock, magic1, magic2, magic3);
 }
 
 static Bool
-I830SDVOSetOutputTimingsPart1(I830SDVOPtr s, CARD16 clock, CARD16 magic1,
-			      CARD16 magic2, CARD16 magic3)
+i830_sdvo_set_output_timings_part1(I830OutputPtr output, CARD16 clock,
+				   CARD16 magic1, CARD16 magic2, CARD16 magic3)
 {
-    return I830SDVOSetTimingsPart1(s, SDVO_CMD_SET_OUTPUT_TIMINGS_PART1,
-				   clock, magic1, magic2, magic3);
+    return i830_sdvo_set_timings_part1(output,
+				       SDVO_CMD_SET_OUTPUT_TIMINGS_PART1,
+				       clock, magic1, magic2, magic3);
 }
 
 static Bool
-I830SDVOSetTimingsPart2(I830SDVOPtr s, CARD8 cmd, CARD16 magic4, CARD16 magic5,
-			CARD16 magic6)
+i830_sdvo_set_timings_part2(I830OutputPtr output, CARD8 cmd,
+			    CARD16 magic4, CARD16 magic5, CARD16 magic6)
 {
-    memset(s->sdvo_regs, 0, 9);
+    struct i830_sdvo_priv *dev_priv = output->dev_priv;
+
+    memset(dev_priv->sdvo_regs, 0, 9);
   
-    s->sdvo_regs[SDVO_I2C_OPCODE] = cmd;
+    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = cmd;
  
     /* set clock regs */
-    s->sdvo_regs[SDVO_I2C_ARG_0] = magic4 & 0xff;
-    s->sdvo_regs[SDVO_I2C_ARG_1] = (magic4 >> 8) & 0xff;
-    s->sdvo_regs[SDVO_I2C_ARG_2] = magic5 & 0xff;
-    s->sdvo_regs[SDVO_I2C_ARG_3] = (magic5 >> 8) & 0xff;
-    s->sdvo_regs[SDVO_I2C_ARG_4] = magic6 & 0xff;
-    s->sdvo_regs[SDVO_I2C_ARG_5] = (magic6 >> 8) & 0xff;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = magic4 & 0xff;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_1] = (magic4 >> 8) & 0xff;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_2] = magic5 & 0xff;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_3] = (magic5 >> 8) & 0xff;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_4] = magic6 & 0xff;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_5] = (magic6 >> 8) & 0xff;
 
-    I830SDVOWriteOutputs(s, 8);
-    I830SDVOReadInputRegs(s);
+    i830_sdvo_write_outputs(output, 8);
+    i830_sdvo_read_input_regs(output);
   
     return TRUE;
 }
 
 static Bool
-I830SDVOSetInputTimingsPart2(I830SDVOPtr s, CARD16 magic4, CARD16 magic5,
-			     CARD16 magic6)
+i830_sdvo_set_input_timings_part2(I830OutputPtr output,
+				  CARD16 magic4, CARD16 magic5, CARD16 magic6)
 {
-    return I830SDVOSetTimingsPart2(s, SDVO_CMD_SET_INPUT_TIMINGS_PART2, magic4,
-				   magic5, magic6);
+    return i830_sdvo_set_timings_part2(output,
+				       SDVO_CMD_SET_INPUT_TIMINGS_PART2,
+				       magic4, magic5, magic6);
 }
 
 static Bool
-I830SDVOSetOutputTimingsPart2(I830SDVOPtr s, CARD16 magic4, CARD16 magic5,
-			      CARD16 magic6)
+i830_sdvo_set_output_timings_part2(I830OutputPtr output,
+			      CARD16 magic4, CARD16 magic5, CARD16 magic6)
 {
-    return I830SDVOSetTimingsPart2(s, SDVO_CMD_SET_OUTPUT_TIMINGS_PART2, magic4,
-				   magic5, magic6);
+    return i830_sdvo_set_timings_part2(output,
+				       SDVO_CMD_SET_OUTPUT_TIMINGS_PART2,
+				       magic4, magic5, magic6);
 }
 
 static Bool
-I830SDVOCreatePreferredInputTiming(I830SDVOPtr s, CARD16 clock, CARD16 width,
-				   CARD16 height)
+i830_sdvo_create_preferred_input_timing(I830OutputPtr output, CARD16 clock,
+					CARD16 width, CARD16 height)
 {
-    memset(s->sdvo_regs, 0, 9);
+    struct i830_sdvo_priv *dev_priv = output->dev_priv;
+
+    memset(dev_priv->sdvo_regs, 0, 9);
 
-    s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING;
+    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] =
+	SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING;
 
-    s->sdvo_regs[SDVO_I2C_ARG_0] = clock & 0xff;
-    s->sdvo_regs[SDVO_I2C_ARG_1] = (clock >> 8) & 0xff;
-    s->sdvo_regs[SDVO_I2C_ARG_2] = width & 0xff;
-    s->sdvo_regs[SDVO_I2C_ARG_3] = (width >> 8) & 0xff;
-    s->sdvo_regs[SDVO_I2C_ARG_4] = height & 0xff;  
-    s->sdvo_regs[SDVO_I2C_ARG_5] = (height >> 8) & 0xff;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = clock & 0xff;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_1] = (clock >> 8) & 0xff;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_2] = width & 0xff;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_3] = (width >> 8) & 0xff;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_4] = height & 0xff;
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_5] = (height >> 8) & 0xff;
 
-    I830SDVOWriteOutputs(s, 7);
-    I830SDVOReadInputRegs(s);
+    i830_sdvo_write_outputs(output, 7);
+    i830_sdvo_read_input_regs(output);
 
     return TRUE;
 }
 
 static Bool
-I830SDVOGetPreferredInputTimingPart1(I830SDVOPtr s)
+i830_sdvo_get_preferred_input_timing_part1(I830OutputPtr output)
 {
-    memset(s->sdvo_regs, 0, 9);
+    struct i830_sdvo_priv *dev_priv = output->dev_priv;
 
-    s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1;
+    memset(dev_priv->sdvo_regs, 0, 9);
 
-    I830SDVOWriteOutputs(s, 0);
-    I830SDVOReadInputRegs(s);
+    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] =
+	SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1;
 
-    curr_table[0] = s->sdvo_regs[SDVO_I2C_RETURN_6] |
-		    (s->sdvo_regs[SDVO_I2C_RETURN_7] << 8);
-    curr_table[1] = s->sdvo_regs[SDVO_I2C_RETURN_4] |
-		    (s->sdvo_regs[SDVO_I2C_RETURN_5] << 8);
-    curr_table[2] = s->sdvo_regs[SDVO_I2C_RETURN_2] |
-		    (s->sdvo_regs[SDVO_I2C_RETURN_3] << 8);
+    i830_sdvo_write_outputs(output, 0);
+    i830_sdvo_read_input_regs(output);
+
+    curr_table[0] = dev_priv->sdvo_regs[SDVO_I2C_RETURN_6] |
+		    (dev_priv->sdvo_regs[SDVO_I2C_RETURN_7] << 8);
+    curr_table[1] = dev_priv->sdvo_regs[SDVO_I2C_RETURN_4] |
+		    (dev_priv->sdvo_regs[SDVO_I2C_RETURN_5] << 8);
+    curr_table[2] = dev_priv->sdvo_regs[SDVO_I2C_RETURN_2] |
+		    (dev_priv->sdvo_regs[SDVO_I2C_RETURN_3] << 8);
 
     return TRUE;
 }
 
 static Bool
-I830SDVOGetPreferredInputTimingPart2(I830SDVOPtr s)
+i830_sdvo_get_preferred_input_timing_part2(I830OutputPtr output)
 {
-    s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2;
+    struct i830_sdvo_priv *dev_priv = output->dev_priv;
+
+    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] =
+	SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2;
 
-    I830SDVOWriteOutputs(s, 0);
-    I830SDVOReadInputRegs(s);
+    i830_sdvo_write_outputs(output, 0);
+    i830_sdvo_read_input_regs(output);
 
-    curr_table[3] = s->sdvo_regs[SDVO_I2C_RETURN_0] |
-		    (s->sdvo_regs[SDVO_I2C_RETURN_1] << 8);
-    curr_table[4] = s->sdvo_regs[SDVO_I2C_RETURN_2] |
-		    (s->sdvo_regs[SDVO_I2C_RETURN_3] << 8);
+    curr_table[3] = dev_priv->sdvo_regs[SDVO_I2C_RETURN_0] |
+		    (dev_priv->sdvo_regs[SDVO_I2C_RETURN_1] << 8);
+    curr_table[4] = dev_priv->sdvo_regs[SDVO_I2C_RETURN_2] |
+		    (dev_priv->sdvo_regs[SDVO_I2C_RETURN_3] << 8);
     curr_table[5] = 0x1e;
 
     return TRUE;
 }
 
 static int
-I830SDVOGetClockRateMult(I830SDVOPtr s)
+i830_sdvo_get_clock_rate_mult(I830OutputPtr output)
 {
-    memset(s->sdvo_regs, 0, 9);
+    struct i830_sdvo_priv *dev_priv = output->dev_priv;
 
-    s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_CLOCK_RATE_MULT;
+    memset(dev_priv->sdvo_regs, 0, 9);
 
-    I830SDVOWriteOutputs(s, 0);
-    I830SDVOReadInputRegs(s);
+    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_CLOCK_RATE_MULT;
 
-    if (s->sdvo_regs[SDVO_I2C_CMD_STATUS] != SDVO_CMD_STATUS_SUCCESS) {
-	xf86DrvMsg(s->d.pI2CBus->scrnIndex, X_ERROR,
+    i830_sdvo_write_outputs(output, 0);
+    i830_sdvo_read_input_regs(output);
+
+    if (dev_priv->sdvo_regs[SDVO_I2C_CMD_STATUS] != SDVO_CMD_STATUS_SUCCESS) {
+	xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex, X_ERROR,
 		   "Couldn't get SDVO clock rate multiplier\n");
 	return SDVO_CLOCK_RATE_MULT_1X;
     } else {
-	xf86DrvMsg(s->d.pI2CBus->scrnIndex, X_INFO,
+	xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex, X_INFO,
 		   "Current clock rate multiplier: %d\n",
-		   s->sdvo_regs[SDVO_I2C_RETURN_0]);
+		   dev_priv->sdvo_regs[SDVO_I2C_RETURN_0]);
     }
 
-    return s->sdvo_regs[SDVO_I2C_RETURN_0];
+    return dev_priv->sdvo_regs[SDVO_I2C_RETURN_0];
 }
 
 static Bool
-I830SDVOSetClockRateMult(I830SDVOPtr s, CARD8 val)
+i830_sdvo_set_clock_rate_mult(I830OutputPtr output, CARD8 val)
 {
-    memset(s->sdvo_regs, 0, 9);
+    struct i830_sdvo_priv *dev_priv = output->dev_priv;
+
+    memset(dev_priv->sdvo_regs, 0, 9);
 
-    s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_CLOCK_RATE_MULT;
+    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_CLOCK_RATE_MULT;
 
-    s->sdvo_regs[SDVO_I2C_ARG_0] = val;
-    I830SDVOWriteOutputs(s, 1);
-    I830SDVOReadInputRegs(s);
+    dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = val;
+    i830_sdvo_write_outputs(output, 1);
+    i830_sdvo_read_input_regs(output);
 
     return TRUE;
 }
 
 static void
 i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
-			DisplayModePtr mode)
+		       DisplayModePtr mode)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     CARD16 clock = mode->Clock/10, width = mode->CrtcHDisplay;
@@ -546,7 +649,6 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn
     CARD8 c17a[8];
     CARD16 out_timings[6];
     Bool out1, out2;
-    I830SDVOPtr s = output->sdvo_drv;
 
     /* do some mode translations */
     h_blank_len = mode->CrtcHBlankEnd - mode->CrtcHBlankStart;
@@ -586,42 +688,44 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn
     out_timings[4] = c17a[5] | ((short)c17a[4] << 8);
     out_timings[5] = c17a[3] | ((short)c17a[2] << 8);
 
-    I830SDVOSetTargetInput(s, FALSE, FALSE);
+    i830_sdvo_set_target_input(output, FALSE, FALSE);
 
-    I830SDVOGetActiveOutputs(s, &out1, &out2);
+    i830_sdvo_get_active_outputs(output, &out1, &out2);
     
-    I830SDVOSetActiveOutputs(s, FALSE, FALSE);
+    i830_sdvo_set_active_outputs(output, FALSE, FALSE);
 
-    I830SDVOSetTargetOutput(s, TRUE, FALSE);
-    I830SDVOSetOutputTimingsPart1(s, clock, out_timings[0], out_timings[1],
-				  out_timings[2]);
-    I830SDVOSetOutputTimingsPart2(s, out_timings[3], out_timings[4],
-				  out_timings[5]);
+    i830_sdvo_set_target_output(output, TRUE, FALSE);
+    i830_sdvo_set_output_timings_part1(output, clock,
+				       out_timings[0], out_timings[1],
+				       out_timings[2]);
+    i830_sdvo_set_output_timings_part2(output, out_timings[3], out_timings[4],
+				       out_timings[5]);
 
-    I830SDVOSetTargetInput (s, FALSE, FALSE);
+    i830_sdvo_set_target_input(output, FALSE, FALSE);
     
-    I830SDVOCreatePreferredInputTiming(s, clock, width, height);
-    I830SDVOGetPreferredInputTimingPart1(s);
-    I830SDVOGetPreferredInputTimingPart2(s);
+    i830_sdvo_create_preferred_input_timing(output, clock, width, height);
+    i830_sdvo_get_preferred_input_timing_part1(output);
+    i830_sdvo_get_preferred_input_timing_part2(output);
     
-    I830SDVOSetTargetInput (s, FALSE, FALSE);
+    i830_sdvo_set_target_input(output, FALSE, FALSE);
     
-    I830SDVOSetInputTimingsPart1(s, clock, curr_table[0], curr_table[1],
-				 curr_table[2]);
-    I830SDVOSetInputTimingsPart2(s, curr_table[3], curr_table[4],
-				 out_timings[5]);
+    i830_sdvo_set_input_timings_part1(output, clock,
+				      curr_table[0], curr_table[1],
+				      curr_table[2]);
+    i830_sdvo_set_input_timings_part2(output, curr_table[3], curr_table[4],
+				      out_timings[5]);
 
-    I830SDVOSetTargetInput (s, FALSE, FALSE);
+    i830_sdvo_set_target_input(output, FALSE, FALSE);
 
     switch (i830_sdvo_get_pixel_multiplier(mode)) {
     case 1:
-	I830SDVOSetClockRateMult(s, SDVO_CLOCK_RATE_MULT_1X);
+	i830_sdvo_set_clock_rate_mult(output, SDVO_CLOCK_RATE_MULT_1X);
 	break;
     case 2:
-	I830SDVOSetClockRateMult(s, SDVO_CLOCK_RATE_MULT_2X);
+	i830_sdvo_set_clock_rate_mult(output, SDVO_CLOCK_RATE_MULT_2X);
 	break;
     case 4:
-	I830SDVOSetClockRateMult(s, SDVO_CLOCK_RATE_MULT_4X);
+	i830_sdvo_set_clock_rate_mult(output, SDVO_CLOCK_RATE_MULT_4X);
 	break;
     }
 
@@ -634,31 +738,31 @@ i830_sdvo_post_set_mode(ScrnInfoPtr pScr
 			DisplayModePtr mode)
 {
     I830Ptr pI830 = I830PTR(pScrn);
+    struct i830_sdvo_priv *dev_priv = output->dev_priv;
     Bool ret = TRUE;
     Bool out1, out2;
     CARD32 dpll, sdvob, sdvoc;
     int dpll_reg = (output->pipe == 0) ? DPLL_A : DPLL_B;
     int sdvo_pixel_multiply;
-    I830SDVOPtr s = output->sdvo_drv;
 
     /* the BIOS writes out 6 commands post mode set */
     /* two 03s, 04 05, 10, 1d */
     /* these contain the height and mode clock / 10 by the looks of it */
 
-    I830SDVOGetTrainedInputs(s);
+    i830_sdvo_get_trained_inputs(output);
 
     /* THIS IS A DIRTY HACK - sometimes for some reason on startup
      * the BIOS doesn't find my DVI monitor -
      * without this hack the driver doesn't work.. this causes the modesetting
      * to be re-run
      */
-    if (s->sdvo_regs[SDVO_I2C_RETURN_0] != 0x1) {
+    if (dev_priv->sdvo_regs[SDVO_I2C_RETURN_0] != 0x1) {
 	ret = FALSE;
     }
 
-    I830SDVOGetActiveOutputs (s, &out1, &out2);
-    I830SDVOSetActiveOutputs(s, TRUE, FALSE);
-    I830SDVOSetTargetInput (s, FALSE, FALSE);
+    i830_sdvo_get_active_outputs(output, &out1, &out2);
+    i830_sdvo_set_active_outputs(output, TRUE, FALSE);
+    i830_sdvo_set_target_input(output, FALSE, FALSE);
 
     /* Set the SDVO control regs. */
     sdvob = INREG(SDVOB) & SDVOB_PRESERVE_MASK;
@@ -686,13 +790,12 @@ static void
 i830_sdvo_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    I830SDVOPtr sdvo = output->sdvo_drv;
 
     if (mode != DPMSModeOn) {
-	I830SDVOSetActiveOutputs(sdvo, FALSE, FALSE);
+	i830_sdvo_set_active_outputs(output, FALSE, FALSE);
 	OUTREG(SDVOB, INREG(SDVOB) & ~SDVO_ENABLE);
     } else {
-	I830SDVOSetActiveOutputs(sdvo, TRUE, FALSE);
+	i830_sdvo_set_active_outputs(output, TRUE, FALSE);
 	OUTREG(SDVOB, INREG(SDVOB) | SDVO_ENABLE);
     }
 }
@@ -701,115 +804,118 @@ static void
 i830_sdvo_save(ScrnInfoPtr pScrn, I830OutputPtr output)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    I830SDVOPtr sdvo = output->sdvo_drv;
+    struct i830_sdvo_priv *dev_priv = output->dev_priv;
 
-    sdvo->save_sdvo_mult = I830SDVOGetClockRateMult(sdvo);
-    I830SDVOGetActiveOutputs(sdvo, &sdvo->save_sdvo_active_1,
-			     &sdvo->save_sdvo_active_2);
-
-    if (sdvo->caps.caps & 0x1) {
-       I830SDVOSetTargetInput(sdvo, FALSE, FALSE);
-       I830SDVOGetTimings(sdvo, &sdvo->save_input_dtd_1,
-			  SDVO_CMD_GET_INPUT_TIMINGS_PART1);
-    }
-
-    if (sdvo->caps.caps & 0x2) {
-       I830SDVOSetTargetInput(sdvo, FALSE, TRUE);
-       I830SDVOGetTimings(sdvo, &sdvo->save_input_dtd_2,
-			  SDVO_CMD_GET_INPUT_TIMINGS_PART1);
+    dev_priv->save_sdvo_mult = i830_sdvo_get_clock_rate_mult(output);
+    i830_sdvo_get_active_outputs(output, &dev_priv->save_sdvo_active_1,
+				 &dev_priv->save_sdvo_active_2);
+
+    if (dev_priv->caps.caps & 0x1) {
+       i830_sdvo_set_target_input(output, FALSE, FALSE);
+       i830_sdvo_get_timings(output, &dev_priv->save_input_dtd_1,
+			     SDVO_CMD_GET_INPUT_TIMINGS_PART1);
+    }
+
+    if (dev_priv->caps.caps & 0x2) {
+       i830_sdvo_set_target_input(output, FALSE, TRUE);
+       i830_sdvo_get_timings(output, &dev_priv->save_input_dtd_2,
+			     SDVO_CMD_GET_INPUT_TIMINGS_PART1);
     }
     
-    if (sdvo->caps.output_0_supported) {
-       I830SDVOSetTargetOutput(sdvo, TRUE, FALSE);
-       I830SDVOGetTimings(sdvo, &sdvo->save_output_dtd_1,
-			  SDVO_CMD_GET_OUTPUT_TIMINGS_PART1);
+    if (dev_priv->caps.output_0_supported) {
+       i830_sdvo_set_target_output(output, TRUE, FALSE);
+       i830_sdvo_get_timings(output, &dev_priv->save_output_dtd_1,
+			     SDVO_CMD_GET_OUTPUT_TIMINGS_PART1);
     }
 
-    if (sdvo->caps.output_1_supported) {
-       I830SDVOSetTargetOutput(sdvo, FALSE, TRUE);
-       I830SDVOGetTimings(sdvo, &sdvo->save_output_dtd_2,
-			  SDVO_CMD_GET_OUTPUT_TIMINGS_PART1);
+    if (dev_priv->caps.output_1_supported) {
+       i830_sdvo_set_target_output(output, FALSE, TRUE);
+       i830_sdvo_get_timings(output, &dev_priv->save_output_dtd_2,
+			     SDVO_CMD_GET_OUTPUT_TIMINGS_PART1);
     }
 
-    sdvo->save_SDVOX = INREG(sdvo->output_device);
+    dev_priv->save_SDVOX = INREG(dev_priv->output_device);
 }
 
 static void
 i830_sdvo_restore(ScrnInfoPtr pScrn, I830OutputPtr output)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    I830SDVOPtr sdvo = output->sdvo_drv;
+    struct i830_sdvo_priv *dev_priv = output->dev_priv;
 
-    if (sdvo->caps.caps & 0x1) {
-       I830SDVOSetTargetInput(sdvo, FALSE, FALSE);
-       I830SDVOSetTimings(sdvo, &sdvo->save_input_dtd_1,
-			  SDVO_CMD_SET_INPUT_TIMINGS_PART1);
+    if (dev_priv->caps.caps & 0x1) {
+       i830_sdvo_set_target_input(output, FALSE, FALSE);
+       i830_sdvo_set_timings(output, &dev_priv->save_input_dtd_1,
+			     SDVO_CMD_SET_INPUT_TIMINGS_PART1);
     }
 
-    if (sdvo->caps.caps & 0x2) {
-       I830SDVOSetTargetInput(sdvo, FALSE, TRUE);
-       I830SDVOSetTimings(sdvo, &sdvo->save_input_dtd_2,
-			  SDVO_CMD_SET_INPUT_TIMINGS_PART1);
+    if (dev_priv->caps.caps & 0x2) {
+       i830_sdvo_set_target_input(output, FALSE, TRUE);
+       i830_sdvo_set_timings(output, &dev_priv->save_input_dtd_2,
+			     SDVO_CMD_SET_INPUT_TIMINGS_PART1);
     }
 
-    if (sdvo->caps.output_0_supported) {
-       I830SDVOSetTargetOutput(sdvo, TRUE, FALSE);
-       I830SDVOSetTimings(sdvo, &sdvo->save_output_dtd_1,
-			  SDVO_CMD_SET_OUTPUT_TIMINGS_PART1);
+    if (dev_priv->caps.output_0_supported) {
+       i830_sdvo_set_target_output(output, TRUE, FALSE);
+       i830_sdvo_set_timings(output, &dev_priv->save_output_dtd_1,
+			     SDVO_CMD_SET_OUTPUT_TIMINGS_PART1);
     }
 
-    if (sdvo->caps.output_1_supported) {
-       I830SDVOSetTargetOutput(sdvo, FALSE, TRUE);
-       I830SDVOSetTimings(sdvo, &sdvo->save_output_dtd_2,
-			  SDVO_CMD_SET_OUTPUT_TIMINGS_PART1);
+    if (dev_priv->caps.output_1_supported) {
+       i830_sdvo_set_target_output(output, FALSE, TRUE);
+       i830_sdvo_set_timings(output, &dev_priv->save_output_dtd_2,
+			     SDVO_CMD_SET_OUTPUT_TIMINGS_PART1);
     }
 
-    I830SDVOSetClockRateMult(sdvo, sdvo->save_sdvo_mult);
+    i830_sdvo_set_clock_rate_mult(output, dev_priv->save_sdvo_mult);
 
-    OUTREG(sdvo->output_device, sdvo->save_SDVOX);
+    OUTREG(dev_priv->output_device, dev_priv->save_SDVOX);
 
-    I830SDVOSetActiveOutputs(sdvo, sdvo->save_sdvo_active_1,
-			     sdvo->save_sdvo_active_2);
+    i830_sdvo_set_active_outputs(output, dev_priv->save_sdvo_active_1,
+				 dev_priv->save_sdvo_active_2);
 }
 
 static int
 i830_sdvo_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output,
 		     DisplayModePtr pMode)
 {
-    I830SDVOPtr sdvo = output->sdvo_drv;
+    struct i830_sdvo_priv *dev_priv = output->dev_priv;
 
-    if (sdvo->pixel_clock_min > pMode->Clock)
+    if (dev_priv->pixel_clock_min > pMode->Clock)
 	return MODE_CLOCK_HIGH;
 
-    if (sdvo->pixel_clock_max < pMode->Clock)
+    if (dev_priv->pixel_clock_max < pMode->Clock)
 	return MODE_CLOCK_LOW;
 
     return MODE_OK;
 }
 
 static void
-I830SDVOGetCapabilities(I830SDVOPtr s, i830_sdvo_caps *caps)
+i830_sdvo_get_capabilities(I830OutputPtr output, i830_sdvo_caps *caps)
 {
-  memset(s->sdvo_regs, 0, 9);
-  s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_DEVICE_CAPS;
-  I830SDVOWriteOutputs(s, 0);
-  I830SDVOReadInputRegs(s);
+    struct i830_sdvo_priv *dev_priv = output->dev_priv;
 
-  caps->vendor_id = s->sdvo_regs[SDVO_I2C_RETURN_0];
-  caps->device_id = s->sdvo_regs[SDVO_I2C_RETURN_1];
-  caps->device_rev_id = s->sdvo_regs[SDVO_I2C_RETURN_2];
-  caps->sdvo_version_major = s->sdvo_regs[SDVO_I2C_RETURN_3];
-  caps->sdvo_version_minor = s->sdvo_regs[SDVO_I2C_RETURN_4];
-  caps->caps = s->sdvo_regs[SDVO_I2C_RETURN_5];
-  caps->output_0_supported = s->sdvo_regs[SDVO_I2C_RETURN_6];
-  caps->output_1_supported = s->sdvo_regs[SDVO_I2C_RETURN_7];
+    memset(dev_priv->sdvo_regs, 0, 9);
+    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_DEVICE_CAPS;
+    i830_sdvo_write_outputs(output, 0);
+    i830_sdvo_read_input_regs(output);
+
+    caps->vendor_id = dev_priv->sdvo_regs[SDVO_I2C_RETURN_0];
+    caps->device_id = dev_priv->sdvo_regs[SDVO_I2C_RETURN_1];
+    caps->device_rev_id = dev_priv->sdvo_regs[SDVO_I2C_RETURN_2];
+    caps->sdvo_version_major = dev_priv->sdvo_regs[SDVO_I2C_RETURN_3];
+    caps->sdvo_version_minor = dev_priv->sdvo_regs[SDVO_I2C_RETURN_4];
+    caps->caps = dev_priv->sdvo_regs[SDVO_I2C_RETURN_5];
+    caps->output_0_supported = dev_priv->sdvo_regs[SDVO_I2C_RETURN_6];
+    caps->output_1_supported = dev_priv->sdvo_regs[SDVO_I2C_RETURN_7];
 }
 
+/** Forces the device over to the real I2C bus and uses its GetByte */
 static Bool
-I830SDVODDCI2CGetByte(I2CDevPtr d, I2CByte *data, Bool last)
+i830_sdvo_ddc_i2c_get_byte(I2CDevPtr d, I2CByte *data, Bool last)
 {
-    I830SDVOPtr sdvo = d->pI2CBus->DriverPrivate.ptr;
-    I2CBusPtr i2cbus = sdvo->d.pI2CBus, savebus;
+    I830OutputPtr output = d->pI2CBus->DriverPrivate.ptr;
+    I2CBusPtr i2cbus = output->pI2CBus, savebus;
     Bool ret;
 
     savebus = d->pI2CBus;
@@ -820,11 +926,12 @@ I830SDVODDCI2CGetByte(I2CDevPtr d, I2CBy
     return ret;
 }
 
+/** Forces the device over to the real I2C bus and uses its PutByte */
 static Bool
-I830SDVODDCI2CPutByte(I2CDevPtr d, I2CByte c)
+i830_sdvo_ddc_i2c_put_byte(I2CDevPtr d, I2CByte c)
 {
-    I830SDVOPtr sdvo = d->pI2CBus->DriverPrivate.ptr;
-    I2CBusPtr i2cbus = sdvo->d.pI2CBus, savebus;
+    I830OutputPtr output = d->pI2CBus->DriverPrivate.ptr;
+    I2CBusPtr i2cbus = output->pI2CBus, savebus;
     Bool ret;
 
     savebus = d->pI2CBus;
@@ -835,21 +942,29 @@ I830SDVODDCI2CPutByte(I2CDevPtr d, I2CBy
     return ret;
 }
 
+/**
+ * Sets the control bus over to DDC before sending the start on the real I2C
+ * bus.
+ *
+ * The control bus will flip back at the stop following the start executed
+ * here.
+ */
 static Bool
-I830SDVODDCI2CStart(I2CBusPtr b, int timeout)
+i830_sdvo_ddc_i2c_start(I2CBusPtr b, int timeout)
 {
-    I830SDVOPtr sdvo = b->DriverPrivate.ptr;
-    I2CBusPtr i2cbus = sdvo->d.pI2CBus;
+    I830OutputPtr output = b->DriverPrivate.ptr;
+    I2CBusPtr i2cbus = output->pI2CBus;
 
-    I830SDVOSetControlBusSwitch(sdvo, SDVO_CONTROL_BUS_DDC2);
+    i830_sdvo_set_control_bus_switch(output, SDVO_CONTROL_BUS_DDC2);
     return i2cbus->I2CStart(i2cbus, timeout);
 }
 
+/** Forces the device over to the real SDVO bus and sends a stop to it. */
 static void
-I830SDVODDCI2CStop(I2CDevPtr d)
+i830_sdvo_ddc_i2c_stop(I2CDevPtr d)
 {
-    I830SDVOPtr sdvo = d->pI2CBus->DriverPrivate.ptr;
-    I2CBusPtr i2cbus = sdvo->d.pI2CBus, savebus;
+    I830OutputPtr output = d->pI2CBus->DriverPrivate.ptr;
+    I2CBusPtr i2cbus = output->pI2CBus, savebus;
 
     savebus = d->pI2CBus;
     d->pI2CBus = i2cbus;
@@ -857,11 +972,15 @@ I830SDVODDCI2CStop(I2CDevPtr d)
     d->pI2CBus = savebus;
 }
 
-/* It's a shame that xf86i2c.c's I2CAddress() doesn't use the bus's pointers,
- * so it's useless to us here.
+/**
+ * Mirrors xf86i2c I2CAddress, using the bus's (wrapped) methods rather than
+ * the default methods.
+ *
+ * This ensures that our start commands always get wrapped with control bus
+ * switches.  xf86i2c should probably be fixed to do this.
  */
 static Bool
-I830SDVODDCI2CAddress(I2CDevPtr d, I2CSlaveAddr addr)
+i830_sdvo_ddc_i2c_address(I2CDevPtr d, I2CSlaveAddr addr)
 {
     if (d->pI2CBus->I2CStart(d->pI2CBus, d->StartTimeout)) {
 	if (d->pI2CBus->I2CPutByte(d, addr & 0xFF)) {
@@ -880,50 +999,54 @@ I830SDVODDCI2CAddress(I2CDevPtr d, I2CSl
 }
 
 static void
-I830DumpSDVOCmd (I830SDVOPtr s, int opcode)
+i830_sdvo_dump_cmd(I830OutputPtr output, int opcode)
 {
-    memset (s->sdvo_regs, 0, sizeof (s->sdvo_regs));
-    s->sdvo_regs[SDVO_I2C_OPCODE] = opcode;
-    I830SDVOWriteOutputs (s, 0);
-    I830SDVOReadInputRegs (s);
+    struct i830_sdvo_priv *dev_priv = output->dev_priv;
+
+    memset(dev_priv->sdvo_regs, 0, sizeof(dev_priv->sdvo_regs));
+    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = opcode;
+    i830_sdvo_write_outputs(output, 0);
+    i830_sdvo_read_input_regs(output);
 }
 
 static void
-I830DumpOneSDVO (I830SDVOPtr s)
+i830_sdvo_dump_device(I830OutputPtr output)
 {
-    ErrorF ("Dump %s\n", s->d.DevName);
-    I830DumpSDVOCmd (s, SDVO_CMD_GET_DEVICE_CAPS);
-    I830DumpSDVOCmd (s, SDVO_CMD_GET_FIRMWARE_REV);
-    I830DumpSDVOCmd (s, SDVO_CMD_GET_TRAINED_INPUTS);
-    I830DumpSDVOCmd (s, SDVO_CMD_GET_ACTIVE_OUTPUTS);
-    I830DumpSDVOCmd (s, SDVO_CMD_GET_IN_OUT_MAP);
-    I830DumpSDVOCmd (s, SDVO_CMD_GET_ATTACHED_DISPLAYS);
-    I830DumpSDVOCmd (s, SDVO_CMD_GET_HOT_PLUG_SUPPORT);
-    I830DumpSDVOCmd (s, SDVO_CMD_GET_ACTIVE_HOT_PLUG);
-    I830DumpSDVOCmd (s, SDVO_CMD_GET_INTR_EVENT_SOURCE);
-    I830DumpSDVOCmd (s, SDVO_CMD_GET_INPUT_TIMINGS_PART1);
-    I830DumpSDVOCmd (s, SDVO_CMD_GET_INPUT_TIMINGS_PART2);
-    I830DumpSDVOCmd (s, SDVO_CMD_GET_OUTPUT_TIMINGS_PART1);
-    I830DumpSDVOCmd (s, SDVO_CMD_GET_OUTPUT_TIMINGS_PART2);
-    I830DumpSDVOCmd (s, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1);
-    I830DumpSDVOCmd (s, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2);
-    I830DumpSDVOCmd (s, SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE);
-    I830DumpSDVOCmd (s, SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE);
-    I830DumpSDVOCmd (s, SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS);
-    I830DumpSDVOCmd (s, SDVO_CMD_GET_CLOCK_RATE_MULT);
-    I830DumpSDVOCmd (s, SDVO_CMD_GET_SUPPORTED_TV_FORMATS);
-    I830DumpSDVOCmd (s, SDVO_CMD_GET_TV_FORMAT);
+    struct i830_sdvo_priv *dev_priv = output->dev_priv;
+
+    ErrorF("Dump %s\n", dev_priv->d.DevName);
+    i830_sdvo_dump_cmd(output, SDVO_CMD_GET_DEVICE_CAPS);
+    i830_sdvo_dump_cmd(output, SDVO_CMD_GET_FIRMWARE_REV);
+    i830_sdvo_dump_cmd(output, SDVO_CMD_GET_TRAINED_INPUTS);
+    i830_sdvo_dump_cmd(output, SDVO_CMD_GET_ACTIVE_OUTPUTS);
+    i830_sdvo_dump_cmd(output, SDVO_CMD_GET_IN_OUT_MAP);
+    i830_sdvo_dump_cmd(output, SDVO_CMD_GET_ATTACHED_DISPLAYS);
+    i830_sdvo_dump_cmd(output, SDVO_CMD_GET_HOT_PLUG_SUPPORT);
+    i830_sdvo_dump_cmd(output, SDVO_CMD_GET_ACTIVE_HOT_PLUG);
+    i830_sdvo_dump_cmd(output, SDVO_CMD_GET_INTR_EVENT_SOURCE);
+    i830_sdvo_dump_cmd(output, SDVO_CMD_GET_INPUT_TIMINGS_PART1);
+    i830_sdvo_dump_cmd(output, SDVO_CMD_GET_INPUT_TIMINGS_PART2);
+    i830_sdvo_dump_cmd(output, SDVO_CMD_GET_OUTPUT_TIMINGS_PART1);
+    i830_sdvo_dump_cmd(output, SDVO_CMD_GET_OUTPUT_TIMINGS_PART2);
+    i830_sdvo_dump_cmd(output, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1);
+    i830_sdvo_dump_cmd(output, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2);
+    i830_sdvo_dump_cmd(output, SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE);
+    i830_sdvo_dump_cmd(output, SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE);
+    i830_sdvo_dump_cmd(output, SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS);
+    i830_sdvo_dump_cmd(output, SDVO_CMD_GET_CLOCK_RATE_MULT);
+    i830_sdvo_dump_cmd(output, SDVO_CMD_GET_SUPPORTED_TV_FORMATS);
+    i830_sdvo_dump_cmd(output, SDVO_CMD_GET_TV_FORMAT);
 }
-		 
+
 void
-I830DumpSDVO (ScrnInfoPtr pScrn)
+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)
-	    I830DumpOneSDVO (pI830->output[i].sdvo_drv);
+	    i830_sdvo_dump_device(&pI830->output[i]);
     }
 }
 
@@ -937,73 +1060,74 @@ I830DumpSDVO (ScrnInfoPtr pScrn)
  * Takes 14ms on average on my i945G.
  */
 Bool
-I830DetectSDVODisplays(ScrnInfoPtr pScrn, int output_index)
+i830_sdvo_detect_displays(ScrnInfoPtr pScrn, I830OutputPtr output)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
-    I830SDVOPtr s = pI830->output[output_index].sdvo_drv;
+    struct i830_sdvo_priv *dev_priv = output->dev_priv;
 
-    s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_ATTACHED_DISPLAYS;
-    I830SDVOWriteOutputs(s, 0);
-    I830SDVOReadInputRegs(s);
+    dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_ATTACHED_DISPLAYS;
+    i830_sdvo_write_outputs(output, 0);
+    i830_sdvo_read_input_regs(output);
 
-    if (s->sdvo_regs[SDVO_I2C_CMD_STATUS] != SDVO_CMD_STATUS_SUCCESS)
+    if (dev_priv->sdvo_regs[SDVO_I2C_CMD_STATUS] != SDVO_CMD_STATUS_SUCCESS)
 	return FALSE;
 
-    return (s->sdvo_regs[SDVO_I2C_RETURN_0] != 0 ||
-	    s->sdvo_regs[SDVO_I2C_RETURN_1] != 0);
+    return (dev_priv->sdvo_regs[SDVO_I2C_RETURN_0] != 0 ||
+	    dev_priv->sdvo_regs[SDVO_I2C_RETURN_1] != 0);
 }
 
 void
 i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    I830SDVOPtr sdvo;
+    I830OutputPtr output = &pI830->output[pI830->num_outputs];
+    struct i830_sdvo_priv *dev_priv;
     int i;
     unsigned char ch[0x40];
     I2CBusPtr i2cbus = NULL, ddcbus;
 
-    pI830->output[pI830->num_outputs].type = I830_OUTPUT_SDVO;
-    pI830->output[pI830->num_outputs].dpms = i830_sdvo_dpms;
-    pI830->output[pI830->num_outputs].save = i830_sdvo_save;
-    pI830->output[pI830->num_outputs].restore = i830_sdvo_restore;
-    pI830->output[pI830->num_outputs].mode_valid = i830_sdvo_mode_valid;
-    pI830->output[pI830->num_outputs].pre_set_mode = i830_sdvo_pre_set_mode;
-    pI830->output[pI830->num_outputs].post_set_mode = i830_sdvo_post_set_mode;
+    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;
+
+    /* 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.
+     */
+    if (output_device == SDVOB)
+	I830I2CInit(pScrn, &i2cbus, GPIOE, "SDVOCTRL_E for SDVOB");
+    else
+	I830I2CInit(pScrn, &i2cbus, GPIOE, "SDVOCTRL_E for SDVOC");
 
-    /* Find an existing SDVO I2CBus from another output, or allocate it. */
-    for (i = 0; i < pI830->num_outputs; i++) {
-	if (pI830->output[i].type == I830_OUTPUT_SDVO)
-	    i2cbus = pI830->output[i].pI2CBus;
-    }
-    if (i2cbus == NULL)
-	I830I2CInit(pScrn, &i2cbus, GPIOE, "SDVOCTRL_E");
     if (i2cbus == NULL)
 	return;
 
     /* Allocate the SDVO output private data */
-    sdvo = xcalloc(1, sizeof(I830SDVORec));
-    if (sdvo == NULL) {
+    dev_priv = xcalloc(1, sizeof(struct i830_sdvo_priv));
+    if (dev_priv == NULL) {
 	xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE);
 	return;
     }
 
     if (output_device == SDVOB) {
-	sdvo->d.DevName = "SDVO Controller B";
-	sdvo->d.SlaveAddr = 0x70;
+	dev_priv->d.DevName = "SDVO Controller B";
+	dev_priv->d.SlaveAddr = 0x70;
     } else {
-	sdvo->d.DevName = "SDVO Controller C";
-	sdvo->d.SlaveAddr = 0x72;
+	dev_priv->d.DevName = "SDVO Controller C";
+	dev_priv->d.SlaveAddr = 0x72;
     }
-    sdvo->d.pI2CBus = i2cbus;
-    sdvo->d.DriverPrivate.ptr = sdvo;
-    sdvo->output_device = output_device;
+    dev_priv->d.pI2CBus = i2cbus;
+    dev_priv->d.DriverPrivate.ptr = output;
+    dev_priv->output_device = output_device;
 
-    if (!xf86I2CDevInit(&sdvo->d)) {
+    if (!xf86I2CDevInit(&dev_priv->d)) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		   "Failed to initialize SDVO I2C device %s\n",
 		   output_device == SDVOB ? "SDVOB" : "SDVOC");
 	xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE);
-	xfree(sdvo);
+	xfree(dev_priv);
 	return;
     }
 
@@ -1014,9 +1138,9 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
      */
     ddcbus = xf86CreateI2CBusRec();
     if (ddcbus == NULL) {
-	xf86DestroyI2CDevRec(&sdvo->d, FALSE);
+	xf86DestroyI2CDevRec(&dev_priv->d, FALSE);
 	xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE);
-	xfree(sdvo);
+	xfree(dev_priv);
 	return;
     }
     if (output_device == SDVOB)
@@ -1024,47 +1148,46 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
     else
         ddcbus->BusName = "SDVOC DDC Bus";
     ddcbus->scrnIndex = i2cbus->scrnIndex;
-    ddcbus->I2CGetByte = I830SDVODDCI2CGetByte;
-    ddcbus->I2CPutByte = I830SDVODDCI2CPutByte;
-    ddcbus->I2CStart = I830SDVODDCI2CStart;
-    ddcbus->I2CStop = I830SDVODDCI2CStop;
-    ddcbus->I2CAddress = I830SDVODDCI2CAddress;
-    ddcbus->DriverPrivate.ptr = sdvo;
+    ddcbus->I2CGetByte = i830_sdvo_ddc_i2c_get_byte;
+    ddcbus->I2CPutByte = i830_sdvo_ddc_i2c_put_byte;
+    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(&sdvo->d, FALSE);
+	xf86DestroyI2CDevRec(&dev_priv->d, FALSE);
 	xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE);
-	xfree(sdvo);
+	xfree(dev_priv);
 	return;
     }
 
-    pI830->output[pI830->num_outputs].pI2CBus = i2cbus;
-    pI830->output[pI830->num_outputs].pDDCBus = ddcbus;
-    pI830->output[pI830->num_outputs].sdvo_drv = sdvo;
+    output->pI2CBus = i2cbus;
+    output->pDDCBus = ddcbus;
+    output->dev_priv = dev_priv;
 
     /* Read the regs to test if we can talk to the device */
     for (i = 0; i < 0x40; i++) {
-	if (!sReadByte(sdvo, i, &ch[i])) {
-	    xf86DestroyI2CBusRec(pI830->output[pI830->num_outputs].pDDCBus,
-				 FALSE, FALSE);
-	    xf86DestroyI2CDevRec(&sdvo->d, FALSE);
+	if (!i830_sdvo_read_byte(output, i, &ch[i])) {
+	    xf86DestroyI2CBusRec(output->pDDCBus, FALSE, FALSE);
+	    xf86DestroyI2CDevRec(&dev_priv->d, FALSE);
 	    xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE);
-	    xfree(sdvo);
+	    xfree(dev_priv);
 	    return;
 	}
     }
 
-    I830SDVOGetCapabilities(sdvo, &sdvo->caps);
+    i830_sdvo_get_capabilities(output, &dev_priv->caps);
 
-    I830SDVOGetInputPixelClockRange(sdvo, &sdvo->pixel_clock_min,
-				    &sdvo->pixel_clock_max);
+    i830_sdvo_get_input_pixel_clock_range(output, &dev_priv->pixel_clock_min,
+					  &dev_priv->pixel_clock_max);
 
     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 	       "SDVO device VID/DID: %02X:%02X.%02X, %02X,"
 	       "output 1: %c, output 2: %c\n",
-	       sdvo->caps.vendor_id, sdvo->caps.device_id,
-	       sdvo->caps.device_rev_id, sdvo->caps.caps,
-	       sdvo->caps.output_0_supported ? 'Y' : 'N',
-	       sdvo->caps.output_1_supported ? 'Y' : 'N');
+	       dev_priv->caps.vendor_id, dev_priv->caps.device_id,
+	       dev_priv->caps.device_rev_id, dev_priv->caps.caps,
+	       dev_priv->caps.output_0_supported ? 'Y' : 'N',
+	       dev_priv->caps.output_1_supported ? 'Y' : 'N');
 
     pI830->num_outputs++;
 }
diff --git a/src/i830_sdvo.h b/src/i830_sdvo.h
index 44bbfe4..db7eb97 100644
--- a/src/i830_sdvo.h
+++ b/src/i830_sdvo.h
@@ -62,7 +62,7 @@ int
 i830_sdvo_get_pixel_multiplier(DisplayModePtr pMode);
 
 Bool
-I830DetectSDVODisplays(ScrnInfoPtr pScrn, int output_index);
+i830_sdvo_detect_displays(ScrnInfoPtr pScrn, I830OutputPtr output);
 
 void
-I830DumpSDVO(ScrnInfoPtr pScrn);
+i830_sdvo_dump(ScrnInfoPtr pScrn);
diff-tree cd9c6e29146e1debaba4b0b9ad0d241f07bdbc14 (from parents)
Merge: c5cca4c20ae6b519e3b021a9d90809c1b3d1facb eec5580cefffc293bf547372ab63b2fedaef4a83
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Tue Oct 24 16:53:46 2006 -0700

    Merge branch 'modesetting-origin' into modesetting

diff-tree eec5580cefffc293bf547372ab63b2fedaef4a83 (from parents)
Merge: 53c28b3980d2682de830e8f86553ccad71527ac1 a91c0cbab5de51885bfce7c7dce76f82c1b19553
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Oct 23 14:52:55 2006 -0700

    Merge branch 'overhaul' into modesetting

diff-tree a91c0cbab5de51885bfce7c7dce76f82c1b19553 (from 8149681f2eac0af3b70a9457c5204e17da56142b)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Oct 23 14:30:38 2006 -0700

    Add work-in-progress integrated TV-out support.
    
    This is the TV connector on board for the 915GM and 945GM.
    
    It is currently not hooked up to output initialization as it's entirely
    untested.  However, I think this is a reasonable starting point for getting
    TV-out actually working.

diff --git a/src/Makefile.am b/src/Makefile.am
index cab6fe9..0fce5e4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -77,6 +77,7 @@ i810_drv_la_SOURCES = \
 	 i830_sdvo.c \
 	 i830_sdvo.h \
 	 i830_sdvo_regs.h \
+	 i830_tv.c \
 	 i830_xf86Modes.h \
 	 i830_xf86Modes.c \
 	 i915_3d.c \
diff --git a/src/i810_reg.h b/src/i810_reg.h
index 4fec65f..a80b66e 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -26,9 +26,14 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 **************************************************************************/
 
+/** @file
+ * Register names and fields for Intel graphics.
+ */
+
 /*
  * Authors:
  *   Keith Whitwell <keith at tungstengraphics.com>
+ *   Eric Anholt <eric at anholt.net>
  *
  *   based on the i740 driver by
  *        Kevin E. Martin <kevin at precisioninsight.com> 
@@ -928,6 +933,564 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 # define LVDS_CLKA_POWER_DOWN		(0 << 8)
 # define LVDS_CLKA_POWER_UP		(3 << 8)
 
+/** @defgroup TV_CTL
+ * @{
+ */
+#define TV_CTL			0x68000
+/** Enables the TV encoder */
+# define TV_ENC_ENABLE			(1 << 31)
+/** Sources the TV encoder input from pipe B instead of A. */
+# define TV_ENC_PIPEB_SELECT		(1 << 30)
+/** Outputs composite video (DAC A only) */
+# define TV_ENC_OUTPUT_COMPOSITE	(0 << 28)
+/** Outputs SVideo video (DAC B/C) */
+# define TV_ENC_OUTPUT_SVIDEO		(1 << 28)
+/** Outputs Component video (DAC A/B/C) */
+# define TV_ENC_OUTPUT_COMPONENT	(2 << 28)
+# define TV_TRILEVEL_SYNC		(1 << 21)
+/** Enables slow sync generation (945GM only) */
+# define TV_SLOW_SYNC			(1 << 20)
+/** Selects 4x oversampling for 480i and 576p */
+# define TV_OVERSAMPLE_4X		(0 << 18)
+/** Selects 2x oversampling for 720p and 1080i */
+# define TV_OVERSAMPLE_2X		(1 << 18)
+/** Selects no oversampling for 1080p */
+# define TV_OVERSAMPLE_NONE		(2 << 18)
+/** Selects 8x oversampling */
+# define TV_OVERSAMPLE_8X		(3 << 18)
+/** Selects progressive mode rather than interlaced */
+# define TV_PROGRESSIVE			(1 << 17)
+/** Sets the colorburst to PAL mode.  Required for non-M PAL modes. */
+# define TV_PAL_BURST			(1 << 16)
+/** Field for setting delay of Y compared to C */
+# define TV_YC_SKEW_MASK		(7 << 12)
+/** Enables a fix for 480p/576p standard definition modes on the 915GM only */
+# define TV_ENC_SDP_FIX			(1 << 11)
+/**
+ * Enables a fix for the 915GM only.
+ *
+ * Not sure what it does.
+ */
+# define TV_ENC_C0_FIX			(1 << 10)
+/** Bits that must be preserved by software */
+# define TV_CTL_SAVE			((3 << 8) | (3 << 6))
+# define TV_FUSE_STATE_MASK		(3 << 4)
+/** Read-only state that reports all features enabled */
+# define TV_FUSE_STATE_ENABLED		(0 << 4)
+/** Read-only state that reports that Macrovision is disabled in hardware*/
+# define TV_FUSE_STATE_NO_MACROVISION	(1 << 4)
+/** Read-only state that reports that TV-out is disabled in hardware. */
+# define TV_FUSE_STATE_DISABLED		(2 << 4)
+/**
+ * This test mode forces the DACs to 50% of full output.
+ *
+ * This is used for load detection in combination with TVDAC_SENSE_MASK
+ */
+# define TV_TEST_MODE_MONITOR_DETECT	(7 << 0)
+/** @} */
+
+/** @defgroup TV_DAC
+ * @{
+ */
+#define TV_DAC			0x68004
+/**
+ * Reports that DAC state change logic has reported change (RO).
+ *
+ * This gets cleared when TV_DAC_STATE_EN is cleared
+*/
+# define TVDAC_STATE_CHG		(1 << 31)
+# define TVDAC_SENSE_MASK		(7 << 28)
+/** Reports that DAC A voltage is above the detect threshold */
+# define TVDAC_A_SENSE			(1 << 30)
+/** Reports that DAC B voltage is above the detect threshold */
+# define TVDAC_B_SENSE			(1 << 29)
+/** Reports that DAC C voltage is above the detect threshold */
+# define TVDAC_C_SENSE			(1 << 28)
+/**
+ * Enables DAC state detection logic, for load-based TV detection.
+ *
+ * The PLL of the chosen pipe (in TV_CTL) must be running, and the encoder set
+ * to off, for load detection to work.
+ */
+# define TVDAC_STATE_CHG_EN		(1 << 27)
+/** Sets the DAC A sense value to high */
+# define TVDAC_A_SENSE_CTL		(1 << 26)
+/** Sets the DAC B sense value to high */
+# define TVDAC_B_SENSE_CTL		(1 << 25)
+/** Sets the DAC C sense value to high */
+# define TVDAC_C_SENSE_CTL		(1 << 24)
+/** Overrides the ENC_ENABLE and DAC voltage levels */
+# define DAC_CTL_OVERRIDE		(1 << 7)
+/** Sets the slew rate.  Must be preserved in software */
+# define ENC_TVDAC_SLEW_FAST		(1 << 6)
+# define DAC_A_1_3_V			(0 << 4)
+# define DAC_A_1_1_V			(1 << 4)
+# define DAC_A_0_7_V			(2 << 4)
+# define DAC_A_OFF			(3 << 4)
+# define DAC_B_1_3_V			(0 << 2)
+# define DAC_B_1_1_V			(1 << 2)
+# define DAC_B_0_7_V			(2 << 2)
+# define DAC_B_OFF			(3 << 2)
+# define DAC_C_1_3_V			(0 << 0)
+# define DAC_C_1_1_V			(1 << 0)
+# define DAC_C_0_7_V			(2 << 0)
+# define DAC_C_OFF			(3 << 0)
+/** @} */
+
+/**
+ * CSC coefficients are stored in a floating point format with 9 bits of
+ * mantissa and 2 or 3 bits of exponent.  The exponent is represented as 2**-n,
+ * where 2-bit exponents are unsigned n, and 3-bit exponents are signed n with
+ * -1 (0x3) being the only legal negative value.
+ */
+#define TV_CSC_Y		0x68010
+# define TV_RY_MASK			0x07ff0000
+# define TV_RY_SHIFT			16
+# define TV_GY_MASK			0x00000fff
+# define TV_GY_SHIFT			0
+
+#define TV_CSC_Y2		0x68014
+# define TV_BY_MASK			0x07ff0000
+# define TV_BY_SHIFT			16
+/**
+ * Y attenuation for component video.
+ *
+ * Stored in 1.9 fixed point.
+ */
+# define TV_AY_MASK			0x000003ff
+# define TV_AY_SHIFT			0
+
+#define TV_CSC_U		0x68018
+# define TV_RU_MASK			0x07ff0000
+# define TV_RU_SHIFT			16
+# define TV_GU_MASK			0x000007ff
+# define TV_GU_SHIFT			0
+
+#define TV_CSC_U2		0x6801c
+# define TV_BU_MASK			0x07ff0000
+# define TV_BU_SHIFT			16
+/**
+ * U attenuation for component video.
+ *
+ * Stored in 1.9 fixed point.
+ */
+# define TV_AU_MASK			0x000003ff
+# define TV_AU_SHIFT			0
+
+#define TV_CSC_V		0x68020
+# define TV_RV_MASK			0x0fff0000
+# define TV_RV_SHIFT			16
+# define TV_GV_MASK			0x000007ff
+# define TV_GV_SHIFT			0
+
+#define TV_CSC_V2		0x68024
+# define TV_BV_MASK			0x07ff0000
+# define TV_BV_SHIFT			16
+/**
+ * V attenuation for component video.
+ *
+ * Stored in 1.9 fixed point.
+ */
+# define TV_AV_MASK			0x000007ff
+# define TV_AV_SHIFT			0
+
+/** @defgroup TV_CSC_KNOBS
+ * @{
+ */
+#define TV_CLR_KNOBS		0x68028
+/** 2s-complement brightness adjustment */
+# define TV_BRIGHTNESS_MASK		0xff000000
+# define TV_BRIGHTNESS_SHIFT		24
+/** Contrast adjustment, as a 2.6 unsigned floating point number */
+# define TV_CONTRAST_MASK		0x00ff0000
+# define TV_CONTRAST_SHIFT		16
+/** Saturation adjustment, as a 2.6 unsigned floating point number */
+# define TV_SATURATION_MASK		0x0000ff00
+# define TV_SATURATION_SHIFT		8
+/** Hue adjustment, as an integer phase angle in degrees */
+# define TV_HUE_MASK			0x000000ff
+# define TV_HUE_SHIFT			0
+/** @} */
+
+/** @defgroup TV_CLR_LEVEL
+ * @{
+ */
+#define TV_CLR_LEVEL		0x6802c
+/** Controls the DAC level for black */
+# define TV_BLACK_LEVEL_MASK		0x01ff0000
+# define TV_BLACK_LEVEL_SHIFT		16
+/** Controls the DAC level for blanking */
+# define TV_BLANK_LEVEL_MASK		0x000001ff
+# define TV_BLANK_LEVEL_SHIFT		0
+/* @} */
+
+/** @defgroup TV_H_CTL_1
+ * @{
+ */
+#define TV_H_CTL_1		0x68030
+/** Number of pixels in the hsync. */
+# define TV_HSYNC_END_MASK		0x1fff0000
+# define TV_HSYNC_END_SHIFT		16
+/** Total number of pixels minus one in the line (display and blanking). */
+# define TV_HTOTAL_MASK			0x00001fff
+# define TV_HTOTAL_SHIFT		0
+/** @} */
+
+/** @defgroup TV_H_CTL_2
+ * @{
+ */
+#define TV_H_CTL_2		0x68034
+/** Enables the colorburst (needed for non-component color) */
+# define TV_BURST_ENA			(1 << 31)
+/** Offset of the colorburst from the start of hsync, in pixels minus one. */
+# define TV_HBURST_START_SHIFT		16
+# define TV_HBURST_START_MASK		0x1fff0000
+/** Length of the colorburst */
+# define TV_HBURST_LEN_SHIFT		0
+# define TV_HBURST_LEN_MASK		0x0001fff
+/** @} */
+
+/** @defgroup TV_H_CTL_3
+ * @{
+ */
+#define TV_H_CTL_3		0x68038
+/** End of hblank, measured in pixels minus one from start of hsync */
+# define TV_HBLANK_END_SHIFT		16
+# define TV_HBLANK_END_MASK		0x1fff0000
+/** Start of hblank, measured in pixels minus one from start of hsync */
+# define TV_HBLANK_START_SHIFT		0
+# define TV_HBLANK_START_MASK		0x0001fff
+/** @} */
+
+/** @defgroup TV_V_CTL_1
+ * @{
+ */
+#define TV_V_CTL_1		0x6803c
+/** XXX */
+# define TV_NBR_END_SHIFT		16
+# define TV_NBR_END_MASK		0x07ff0000
+/** XXX */
+# define TV_VI_END_F1_SHIFT		8
+# define TV_VI_END_F1_MASK		0x00003f00
+/** XXX */
+# define TV_VI_END_F2_SHIFT		0
+# define TV_VI_END_F2_MASK		0x0000003f
+/** @} */
+
+/** @defgroup TV_V_CTL_2
+ * @{
+ */
+#define TV_V_CTL_2		0x68040
+/** Length of vsync, in half lines */
+# define TV_VSYNC_LEN_MASK		0x07ff0000
+# define TV_VSYNC_LEN_SHIFT		16
+/** Offset of the start of vsync in field 1, measured in one less than the
+ * number of half lines.
+ */
+# define TV_VSYNC_START_F1_MASK		0x00007f00
+# define TV_VSYNC_START_F1_SHIFT	8
+/**
+ * Offset of the start of vsync in field 2, measured in one less than the
+ * number of half lines.
+ */
+# define TV_VSYNC_START_F2_MASK		0x0000007f
+# define TV_VSYNC_START_F2_SHIFT	0
+/** @} */
+
+/** @defgroup TV_V_CTL_3
+ * @{
+ */
+#define TV_V_CTL_3		0x68044
+/** Enables generation of the equalization signal */
+# define TV_EQUAL_ENA			(1 << 31)
+/** Length of vsync, in half lines */
+# define TV_VEQ_LEN_MASK		0x007f0000
+# define TV_VEQ_LEN_SHIFT		16
+/** Offset of the start of equalization in field 1, measured in one less than
+ * the number of half lines.
+ */
+# define TV_VEQ_START_F1_MASK		0x0007f00
+# define TV_VEQ_START_F1_SHIFT		8
+/**
+ * Offset of the start of equalization in field 2, measured in one less than
+ * the number of half lines.
+ */
+# define TV_VEQ_START_F2_MASK		0x000007f
+# define TV_VEQ_START_F2_SHIFT		0
+/** @} */
+
+/** @defgroup TV_V_CTL_4
+ * @{
+ */
+#define TV_V_CTL_4		0x68048
+/**
+ * Offset to start of vertical colorburst, measured in one less than the
+ * number of lines from vertical start.
+ */
+# define TV_VBURST_START_F1_MASK	0x003f0000
+# define TV_VBURST_START_F1_SHIFT	16
+/**
+ * Offset to the end of vertical colorburst, measured in one less than the
+ * number of lines from the start of NBR.
+ */
+# define TV_VBURST_END_F1_MASK		0x000000ff
+# define TV_VBURST_END_F1_SHIFT		0
+/** @} */
+
+/** @defgroup TV_V_CTL_5
+ * @{
+ */
+#define TV_V_CTL_5		0x6804c
+/**
+ * Offset to start of vertical colorburst, measured in one less than the
+ * number of lines from vertical start.
+ */
+# define TV_VBURST_START_F2_MASK	0x003f0000
+# define TV_VBURST_START_F2_SHIFT	16
+/**
+ * Offset to the end of vertical colorburst, measured in one less than the
+ * number of lines from the start of NBR.
+ */
+# define TV_VBURST_END_F2_MASK		0x000000ff
+# define TV_VBURST_END_F2_SHIFT		0
+/** @} */
+
+/** @defgroup TV_V_CTL_6
+ * @{
+ */
+#define TV_V_CTL_6		0x68050
+/**
+ * Offset to start of vertical colorburst, measured in one less than the
+ * number of lines from vertical start.
+ */
+# define TV_VBURST_START_F3_MASK	0x003f0000
+# define TV_VBURST_START_F3_SHIFT	16
+/**
+ * Offset to the end of vertical colorburst, measured in one less than the
+ * number of lines from the start of NBR.
+ */
+# define TV_VBURST_END_F3_MASK		0x000000ff
+# define TV_VBURST_END_F3_SHIFT		0
+/** @} */
+
+/** @defgroup TV_V_CTL_7
+ * @{
+ */
+#define TV_V_CTL_7		0x68054
+/**
+ * Offset to start of vertical colorburst, measured in one less than the
+ * number of lines from vertical start.
+ */
+# define TV_VBURST_START_F4_MASK	0x003f0000
+# define TV_VBURST_START_F4_SHIFT	16
+/**
+ * Offset to the end of vertical colorburst, measured in one less than the
+ * number of lines from the start of NBR.
+ */
+# define TV_VBURST_END_F4_MASK		0x000000ff
+# define TV_VBURST_END_F4_SHIFT		0
+/** @} */
+
+/** @defgroup TV_SC_CTL_1
+ * @{
+ */
+#define TV_SC_CTL_1		0x68060
+/** Turns on the first subcarrier phase generation DDA */
+# define TV_SC_DDA1_EN			(1 << 31)
+/** Turns on the first subcarrier phase generation DDA */
+# define TV_SC_DDA2_EN			(2 << 31)
+/** Turns on the first subcarrier phase generation DDA */
+# define TV_SC_DDA3_EN			(3 << 31)
+/** Sets the subcarrier DDA to reset frequency every other field */
+# define TV_SC_RESET_EVERY_2		(0 << 24)
+/** Sets the subcarrier DDA to reset frequency every fourth field */
+# define TV_SC_RESET_EVERY_4		(1 << 24)
+/** Sets the subcarrier DDA to reset frequency every eighth field */
+# define TV_SC_RESET_EVERY_8		(2 << 24)
+/** Sets the subcarrier DDA to never reset the frequency */
+# define TV_SC_RESET_NEVER		(3 << 24)
+/** Sets the peak amplitude of the colorburst.*/
+# define TV_BURST_LEVEL_MASK		0x00ff0000
+# define TV_BURST_LEVEL_SHIFT		16
+/** Sets the increment of the first subcarrier phase generation DDA */
+# define TV_SCDDA1_INC_MASK		0x00000fff
+# define TV_SCDDA1_INC_SHIFT		0
+/** @} */
+
+/** @defgroup TV_SC_CTL_2
+ * @{
+ */
+#define TV_SC_CTL_2		0x68068
+/** Sets the rollover for the second subcarrier phase generation DDA */
+# define TV_SCDDA2_SIZE_MASK		0x7fff0000
+# define TV_SCDDA2_SIZE_SHIFT		16
+/** Sets the increent of the second subcarrier phase generation DDA */
+# define TV_SCDDA2_INC_MASK		0x00007fff
+# define TV_SCDDA2_INC_SHIFT		0
+/** @} */
+
+/** @defgroup TV_SC_CTL_3
+ * @{
+ */
+#define TV_SC_CTL_3		0x68068
+/** Sets the rollover for the third subcarrier phase generation DDA */
+# define TV_SCDDA3_SIZE_MASK		0x7fff0000
+# define TV_SCDDA3_SIZE_SHIFT		16
+/** Sets the increent of the third subcarrier phase generation DDA */
+# define TV_SCDDA3_INC_MASK		0x00007fff
+# define TV_SCDDA3_INC_SHIFT		0
+/** @} */
+
+/** @defgroup TV_WIN_POS
+ * @{
+ */
+#define TV_WIN_POS		0x68070
+/** X coordinate of the display from the start of horizontal active */
+# define TV_XPOS_MASK			0x1fff0000
+# define TV_XPOS_SHIFT			16
+/** Y coordinate of the display from the start of vertical active (NBR) */
+# define TV_YPOS_MASK			0x00000fff
+# define TV_YPOS_SHIFT			0
+/** @} */
+
+/** @defgroup TV_WIN_SIZE
+ * @{
+ */
+#define TV_WIN_SIZE		0x68074
+/** Horizontal size of the display window, measured in pixels*/
+# define TV_XSIZE_MASK			0x1fff0000
+# define TV_XSIZE_SHIFT			16
+/**
+ * Vertical size of the display window, measured in pixels.
+ *
+ * Must be even for interlaced modes.
+ */
+# define TV_YSIZE_MASK			0x00000fff
+# define TV_YSIZE_SHIFT			0
+/** @} */
+
+/** @defgroup TV_FILTER_CTL_1
+ * @{
+ */
+#define TV_FILTER_CTL_1		0x68080
+/**
+ * Enables automatic scaling calculation.
+ *
+ * If set, the rest of the registers are ignored, and the calculated values can
+ * be read back from the register.
+ */
+# define TV_AUTO_SCALE			(1 << 31)
+/**
+ * Disables the vertical filter.
+ *
+ * This is required on modes more than 1024 pixels wide */
+# define TV_V_FILTER_BYPASS		(1 << 29)
+/** Enables adaptive vertical filtering */
+# define TV_VADAPT			(1 << 28)
+# define TV_VADAPT_MODE_MASK		(3 << 26)
+/** Selects the least adaptive vertical filtering mode */
+# define TV_VADAPT_MODE_LEAST		(0 << 26)
+/** Selects the moderately adaptive vertical filtering mode */
+# define TV_VADAPT_MODE_MODERATE	(1 << 26)
+/** Selects the most adaptive vertical filtering mode */
+# define TV_VADAPT_MODE_MOST		(3 << 26)
+/**
+ * Sets the horizontal scaling factor.
+ *
+ * This should be the fractional part of the horizontal scaling factor divided
+ * by the oversampling rate.  TV_HSCALE should be less than 1, and set to:
+ *
+ * (src width - 1) / ((oversample * dest width) - 1)
+ */
+# define TV_HSCALE_FRAC_MASK		0x00003fff
+# define TV_HSCALE_FRAC_SHIFT		0
+/** @} */
+
+/** @defgroup TV_FILTER_CTL_2
+ * @{
+ */
+#define TV_FILTER_CTL_2		0x68084
+/**
+ * Sets the integer part of the 3.15 fixed-point vertical scaling factor.
+ *
+ * TV_VSCALE should be (src height - 1) / ((interlace * dest height) - 1)
+ */
+# define TV_VSCALE_INT_MASK		0x00038000
+# define TV_VSCALE_INT_SHIFT		15
+/**
+ * Sets the fractional part of the 3.15 fixed-point vertical scaling factor.
+ *
+ * \sa TV_VSCALE_INT_MASK
+ */
+# define TV_VSCALE_FRAC_MASK		0x00007fff
+# define TV_VSCALE_FRAC_SHIFT		0
+/** @} */
+
+/** @defgroup TV_FILTER_CTL_3
+ * @{
+ */
+#define TV_FILTER_CTL_3		0x68088
+/**
+ * Sets the integer part of the 3.15 fixed-point vertical scaling factor.
+ *
+ * TV_VSCALE should be (src height - 1) / (1/4 * (dest height - 1))
+ *
+ * For progressive modes, TV_VSCALE_IP_INT should be set to zeroes.
+ */
+# define TV_VSCALE_IP_INT_MASK		0x00038000
+# define TV_VSCALE_IP_INT_SHIFT		15
+/**
+ * Sets the fractional part of the 3.15 fixed-point vertical scaling factor.
+ *
+ * For progressive modes, TV_VSCALE_IP_INT should be set to zeroes.
+ *
+ * \sa TV_VSCALE_IP_INT_MASK
+ */
+# define TV_VSCALE_IP_FRAC_MASK		0x00007fff
+# define TV_VSCALE_IP_FRAC_SHIFT		0
+/** @} */
+
+/** @defgroup TV_CC_CONTROL
+ * @{
+ */
+#define TV_CC_CONTROL		0x68090
+# define TV_CC_ENABLE			(1 << 31)
+/**
+ * Specifies which field to send the CC data in.
+ *
+ * CC data is usually sent in field 0.
+ */
+# define TV_CC_FID_MASK			(1 << 27)
+# define TV_CC_FID_SHIFT		27
+/** Sets the horizontal position of the CC data.  Usually 135. */
+# define TV_CC_HOFF_MASK		0x03ff0000
+# define TV_CC_HOFF_SHIFT		16
+/** Sets the vertical position of the CC data.  Usually 21 */
+# define TV_CC_LINE_MASK		0x0000003f
+# define TV_CC_LINE_SHIFT		0
+/** @} */
+
+/** @defgroup TV_CC_DATA
+ * @{
+ */
+#define TV_CC_DATA		0x68094
+# define TV_CC_RDY			(1 << 31)
+/** Second word of CC data to be transmitted. */
+# define TV_CC_DATA_2_MASK		0x007f0000
+# define TV_CC_DATA_2_SHIFT		16
+/** First word of CC data to be transmitted. */
+# define TV_CC_DATA_1_MASK		0x0000007f
+# define TV_CC_DATA_1_SHIFT		0
+/** @}
+ */
+
+/** @{ */
+#define TV_H_LUMA_0		0x68100
+#define TV_H_LUMA_59		0x681ec
+#define TV_H_CHROMA_0		0x68200
+#define TV_H_CHROMA_59		0x682ec
+/** @} */
+
 #define PIPEACONF 0x70008
 #define PIPEACONF_ENABLE	(1<<31)
 #define PIPEACONF_DISABLE	0
diff --git a/src/i830.h b/src/i830.h
index 90fdcb8..832061c 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -279,6 +279,8 @@ struct _I830OutputRec {
    I2CBusPtr pDDCBus;
    struct _I830DVODriver *i2c_drv;
    I830SDVOPtr sdvo_drv;
+   /** Output-private structure.  Should replace i2c_drv and sdvo_drv */
+   void *dev_priv;
 };
 
 typedef struct _I830Rec {
@@ -693,6 +695,9 @@ Bool I830RandRSetConfig(ScreenPtr pScree
 Rotation I830GetRotation(ScreenPtr pScreen);
 void I830GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y);
 
+/* i830_tv.c */
+void i830_tv_init(ScrnInfoPtr pScrn);
+
 /*
  * 12288 is set as the maximum, chosen because it is enough for
  * 1920x1440 at 32bpp with a 2048 pixel line pitch with some to spare.
diff --git a/src/i830_tv.c b/src/i830_tv.c
new file mode 100644
index 0000000..2adbe91
--- /dev/null
+++ b/src/i830_tv.c
@@ -0,0 +1,430 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
+/** @file
+ * Integrated TV-out support for the 915GM and 945GM.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "i830.h"
+#include "i830_display.h"
+
+enum tv_type {
+    TV_TYPE_UNKNOWN,
+    TV_TYPE_COMPOSITE,
+    TV_TYPE_SVIDEO,
+    TV_TYPE_COMPONENT
+};
+
+/** Private structure for the integrated TV support */
+struct i830_tv_priv {
+    CARD32 save_TV_H_CTL_1;
+    CARD32 save_TV_H_CTL_2;
+    CARD32 save_TV_H_CTL_3;
+    CARD32 save_TV_V_CTL_1;
+    CARD32 save_TV_V_CTL_2;
+    CARD32 save_TV_V_CTL_3;
+    CARD32 save_TV_V_CTL_4;
+    CARD32 save_TV_V_CTL_5;
+    CARD32 save_TV_V_CTL_6;
+    CARD32 save_TV_V_CTL_7;
+    CARD32 save_TV_SC_CTL_1, save_TV_SC_CTL_2, save_TV_SC_CTL_3;
+    CARD32 save_TV_DAC;
+    CARD32 save_TV_CTL;
+};
+
+enum burst_modes {
+    TV_SC_NTSC_MJ,
+    TV_SC_PAL,
+    TV_SC_PAL_NC,
+    TV_SC_PAL_M,
+    TV_SC_NTSC_443
+};
+
+const struct tv_sc_mode {
+    char *name;
+    int dda2_size, dda3_size, dda1_inc, dda2_inc, dda3_inc;
+    CARD32 sc_reset;
+    Bool pal_burst;
+} tv_sc_modes[] = {
+    [TV_SC_NTSC_MJ] = {
+	"NTSC M/J",
+	27456, 0, 135, 20800, 0,
+	TV_SC_RESET_EVERY_4,
+	FALSE
+    },
+    [TV_SC_PAL] = {
+	"PAL",
+	27648, 625, 168, 4122, 67,
+	TV_SC_RESET_EVERY_8,
+	TRUE
+    },
+    [TV_SC_PAL_NC] = {
+	"PAL Nc",
+	27648, 625, 135, 23578, 134,
+	TV_SC_RESET_EVERY_8,
+	TRUE
+    },
+    [TV_SC_PAL_M] = {
+	"PAL M",
+	27456, 0, 135, 16704, 0,
+	TV_SC_RESET_EVERY_8,
+	TRUE
+    },
+    [TV_SC_NTSC_443] = {
+	"NTSC-4.43",
+	27456, 525, 168, 4093, 310,
+	TV_SC_RESET_NEVER,
+	FALSE
+    },
+};
+
+/**
+ * Register programming values for TV modes.
+ *
+ * These values account for -1s required.
+ */
+const struct tv_mode {
+    char *name;
+    CARD32 oversample;
+    int hsync_end, hblank_end, hblank_start, htotal;
+    Bool progressive;
+    int vsync_start_f1, vsync_start_f2, vsync_len;
+    Bool veq_ena;
+    int veq_start_f1, veq_start_f2, veq_len;
+    int vi_end_f1, vi_end_f2, nbr_end;
+    Bool burst_ena;
+    int hburst_start, hburst_len;
+    int vburst_start_f1, vburst_end_f1;
+    int vburst_start_f2, vburst_end_f2;
+    int vburst_start_f3, vburst_end_f3;
+    int vburst_start_f4, vburst_end_f4;
+} tv_modes[] = {
+    {
+	"480i",
+	TV_OVERSAMPLE_8X,
+	64, 124, 836, 857,
+	FALSE,
+	6, 7, 6,
+	TRUE, 0, 1, 18,
+	20, 21, 240,
+	TRUE,
+	72, 34, 9, 240, 10, 240, 9, 240, 10, 240
+    }
+};
+
+
+static int
+i830_tv_detect_type(ScrnInfoPtr pScrn, I830OutputPtr output)
+{
+    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);
+
+    /* 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 (output->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(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    switch(mode) {
+    case DPMSModeOn:
+	OUTREG(TV_CTL, INREG(TV_CTL) | TV_ENC_ENABLE);
+	break;
+    case DPMSModeStandby:
+    case DPMSModeSuspend:
+    case DPMSModeOff:
+	OUTREG(TV_CTL, INREG(TV_CTL) & ~TV_ENC_ENABLE);
+	break;
+    }
+}
+
+static void
+i830_tv_save(ScrnInfoPtr pScrn, I830OutputPtr output)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    struct i830_tv_priv *dev_priv = 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);
+    dev_priv->save_TV_H_CTL_3 = INREG(TV_H_CTL_3);
+    dev_priv->save_TV_V_CTL_1 = INREG(TV_V_CTL_1);
+    dev_priv->save_TV_V_CTL_2 = INREG(TV_V_CTL_2);
+    dev_priv->save_TV_V_CTL_3 = INREG(TV_V_CTL_3);
+    dev_priv->save_TV_V_CTL_4 = INREG(TV_V_CTL_4);
+    dev_priv->save_TV_V_CTL_5 = INREG(TV_V_CTL_5);
+    dev_priv->save_TV_V_CTL_6 = INREG(TV_V_CTL_6);
+    dev_priv->save_TV_V_CTL_7 = INREG(TV_V_CTL_7);
+    dev_priv->save_TV_SC_CTL_1 = INREG(TV_SC_CTL_1);
+    dev_priv->save_TV_SC_CTL_2 = INREG(TV_SC_CTL_2);
+    dev_priv->save_TV_SC_CTL_3 = INREG(TV_SC_CTL_3);
+
+    dev_priv->save_TV_DAC = INREG(TV_DAC);
+    dev_priv->save_TV_CTL = INREG(TV_CTL);
+}
+
+static void
+i830_tv_restore(ScrnInfoPtr pScrn, I830OutputPtr output)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    struct i830_tv_priv *dev_priv = 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);
+    OUTREG(TV_H_CTL_3, dev_priv->save_TV_H_CTL_3);
+    OUTREG(TV_V_CTL_1, dev_priv->save_TV_V_CTL_1);
+    OUTREG(TV_V_CTL_2, dev_priv->save_TV_V_CTL_2);
+    OUTREG(TV_V_CTL_3, dev_priv->save_TV_V_CTL_3);
+    OUTREG(TV_V_CTL_4, dev_priv->save_TV_V_CTL_4);
+    OUTREG(TV_V_CTL_5, dev_priv->save_TV_V_CTL_5);
+    OUTREG(TV_V_CTL_6, dev_priv->save_TV_V_CTL_6);
+    OUTREG(TV_V_CTL_7, dev_priv->save_TV_V_CTL_7);
+    OUTREG(TV_SC_CTL_1, dev_priv->save_TV_SC_CTL_1);
+    OUTREG(TV_SC_CTL_2, dev_priv->save_TV_SC_CTL_2);
+    OUTREG(TV_SC_CTL_3, dev_priv->save_TV_SC_CTL_3);
+
+    OUTREG(TV_DAC, dev_priv->save_TV_DAC);
+    OUTREG(TV_CTL, dev_priv->save_TV_CTL);
+}
+
+static int
+i830_tv_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output,
+		   DisplayModePtr pMode)
+{
+    return MODE_OK;
+}
+
+static void
+i830_tv_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
+		     DisplayModePtr pMode)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    /* Disable the encoder while we set up the pipe. */
+    OUTREG(TV_CTL, INREG(TV_CTL) & ~TV_ENC_ENABLE);
+}
+
+static void
+i830_tv_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
+		      DisplayModePtr pMode)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    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;
+
+    /* Need to actually choose or construct the appropriate
+     * mode.  For now, just set the first one in the list, with
+     * NTSC format.
+     */
+    tv_mode = &tv_modes[0];
+    sc_mode = &tv_sc_modes[TV_SC_NTSC_MJ];
+
+    type = i830_tv_detect_type(pScrn, output);
+    if (type == TV_TYPE_UNKNOWN) {
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Defaulting TV to SVIDEO\n");
+	type = TV_TYPE_SVIDEO;
+    }
+
+    hctl1 = (tv_mode->hsync_end << TV_HSYNC_END_SHIFT) |
+	(tv_mode->htotal << TV_HTOTAL_SHIFT);
+
+    hctl2 = (tv_mode->hburst_start << 16) |
+	(tv_mode->hburst_len << TV_HBURST_LEN_SHIFT);
+    if (tv_mode->burst_ena)
+	hctl2 |= TV_BURST_ENA;
+
+    hctl3 = (tv_mode->hblank_start << TV_HBLANK_START_SHIFT) |
+	(tv_mode->hblank_end << TV_HBLANK_END_SHIFT);
+
+    vctl1 = (tv_mode->nbr_end << TV_NBR_END_SHIFT) |
+	(tv_mode->vi_end_f1 << TV_VI_END_F1_SHIFT) |
+	(tv_mode->vi_end_f2 << TV_VI_END_F2_SHIFT);
+
+    vctl2 = (tv_mode->vsync_len << TV_VSYNC_LEN_SHIFT) |
+	(tv_mode->vsync_start_f1 << TV_VSYNC_START_F1_SHIFT) |
+	(tv_mode->vsync_start_f2 << TV_VSYNC_START_F2_SHIFT);
+
+    vctl3 = (tv_mode->veq_len << TV_VEQ_LEN_SHIFT) |
+	(tv_mode->veq_start_f1 << TV_VEQ_START_F1_SHIFT) |
+	(tv_mode->veq_start_f2 << TV_VEQ_START_F2_SHIFT);
+    if (tv_mode->veq_ena)
+	vctl3 |= TV_EQUAL_ENA;
+
+    vctl4 = (tv_mode->vburst_start_f1 << TV_VBURST_START_F1_SHIFT) |
+	(tv_mode->vburst_end_f1 << TV_VBURST_END_F1_SHIFT);
+
+    vctl5 = (tv_mode->vburst_start_f2 << TV_VBURST_START_F2_SHIFT) |
+	(tv_mode->vburst_end_f2 << TV_VBURST_END_F2_SHIFT);
+
+    vctl6 = (tv_mode->vburst_start_f3 << TV_VBURST_START_F3_SHIFT) |
+	(tv_mode->vburst_end_f3 << TV_VBURST_END_F3_SHIFT);
+
+    vctl7 = (tv_mode->vburst_start_f4 << TV_VBURST_START_F4_SHIFT) |
+	(tv_mode->vburst_end_f4 << TV_VBURST_END_F4_SHIFT);
+
+    tv_ctl = TV_ENC_ENABLE;
+    if (output->pipe == 1)
+	tv_ctl |= TV_ENC_PIPEB_SELECT;
+
+    switch (type) {
+    case TV_TYPE_COMPOSITE:
+	tv_ctl |= TV_ENC_OUTPUT_COMPOSITE;
+	break;
+    case TV_TYPE_COMPONENT:
+	tv_ctl |= TV_ENC_OUTPUT_COMPONENT;
+	break;
+    default:
+    case TV_TYPE_SVIDEO:
+	tv_ctl |= TV_ENC_OUTPUT_SVIDEO;
+	break;
+    }
+    tv_ctl |= tv_mode->oversample;
+    if (tv_mode->progressive)
+	tv_ctl |= TV_PROGRESSIVE;
+    if (sc_mode->pal_burst)
+	tv_ctl |= TV_PAL_BURST;
+
+    scctl1 = TV_SC_DDA1_EN | TV_SC_DDA1_EN;
+    if (sc_mode->dda3_size != 0)
+	scctl1 |= TV_SC_DDA3_EN;
+    scctl1 |= sc_mode->sc_reset;
+    /* XXX: set the burst level */
+    scctl1 |= sc_mode->dda1_inc << TV_SCDDA1_INC_SHIFT;
+
+    scctl2 = sc_mode->dda2_size << TV_SCDDA2_SIZE_SHIFT |
+	sc_mode->dda2_inc << TV_SCDDA2_INC_SHIFT;
+
+    scctl3 = sc_mode->dda3_size << TV_SCDDA3_SIZE_SHIFT |
+	sc_mode->dda3_inc << TV_SCDDA3_INC_SHIFT;
+
+    /* Enable two fixes for the chips that need them. */
+    if (pI830->PciInfo->chipType < PCI_CHIP_I945_G)
+	tv_ctl |= TV_ENC_C0_FIX | TV_ENC_SDP_FIX;
+
+    tv_filter_ctl = TV_AUTO_SCALE;
+    if (pMode->HDisplay > 1024)
+	tv_ctl |= TV_V_FILTER_BYPASS;
+
+    OUTREG(TV_H_CTL_1, hctl1);
+    OUTREG(TV_H_CTL_2, hctl2);
+    OUTREG(TV_H_CTL_3, hctl3);
+    OUTREG(TV_V_CTL_1, vctl1);
+    OUTREG(TV_V_CTL_2, vctl2);
+    OUTREG(TV_V_CTL_3, vctl3);
+    OUTREG(TV_V_CTL_4, vctl4);
+    OUTREG(TV_V_CTL_5, vctl5);
+    OUTREG(TV_V_CTL_6, vctl6);
+    OUTREG(TV_V_CTL_7, vctl7);
+    OUTREG(TV_SC_CTL_1, scctl1);
+    OUTREG(TV_SC_CTL_2, scctl2);
+    OUTREG(TV_SC_CTL_3, scctl3);
+
+    OUTREG(TV_DAC, 0);
+    OUTREG(TV_CTL, tv_ctl);
+}
+
+void
+i830_tv_init(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    if ((INREG(TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED)
+	return;
+
+    pI830->output[pI830->num_outputs].dev_priv =
+	malloc(sizeof(struct i830_tv_priv));
+    if (pI830->output[pI830->num_outputs].dev_priv == NULL)
+	return;
+
+    pI830->output[pI830->num_outputs].type = I830_OUTPUT_ANALOG;
+    pI830->output[pI830->num_outputs].dpms = i830_tv_dpms;
+    pI830->output[pI830->num_outputs].save = i830_tv_save;
+    pI830->output[pI830->num_outputs].restore = i830_tv_restore;
+    pI830->output[pI830->num_outputs].mode_valid = i830_tv_mode_valid;
+    pI830->output[pI830->num_outputs].pre_set_mode = i830_tv_pre_set_mode;
+    pI830->output[pI830->num_outputs].post_set_mode = i830_tv_post_set_mode;
+
+    pI830->num_outputs++;
+}
diff-tree 8149681f2eac0af3b70a9457c5204e17da56142b (from 1838671476875e9f5b3dde235eacf9fb43afb66c)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Oct 16 16:51:04 2006 -0700

    Add a per-output mode-valid method.
    
    This is currently disconnected, but will be used in more overhaul work.
    This should be where any output limitations, such as clocks, resolution,
    scaling limits, or other options, are validated.  Other limitations, such as
    chipset resolution limits, CRTC clock limits, etc. should be elsewhere.

diff --git a/src/i830.h b/src/i830.h
index c41cb56..90fdcb8 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -211,6 +211,9 @@ typedef struct _I830SDVODriver {
    CARD32 output_device;		/* SDVOB or SDVOC */
 
    i830_sdvo_caps caps;
+
+   CARD16 pixel_clock_min, pixel_clock_max;
+
    int save_sdvo_mult;
    Bool save_sdvo_active_1, save_sdvo_active_2;
    i830_sdvo_dtd save_input_dtd_1, save_input_dtd_2;
@@ -245,6 +248,17 @@ struct _I830OutputRec {
    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
diff --git a/src/i830_crt.c b/src/i830_crt.c
index 1cf1687..7721a0c 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -76,6 +76,13 @@ i830_crt_restore(ScrnInfoPtr pScrn, I830
     OUTREG(ADPA, pI830->saveADPA);
 }
 
+static int
+i830_crt_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output,
+		    DisplayModePtr pMode)
+{
+    return MODE_OK;
+}
+
 static void
 i830_crt_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
 		      DisplayModePtr pMode)
@@ -114,6 +121,7 @@ i830_crt_init(ScrnInfoPtr pScrn)
     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;
 
diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index ea74337..01858f2 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -92,15 +92,22 @@ i830_dvo_restore(ScrnInfoPtr pScrn, I830
     output->i2c_drv->vid_rec->RestoreRegs(output->i2c_drv->dev_priv);
 }
 
+static int
+i830_dvo_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output,
+		    DisplayModePtr pMode)
+{
+    if (output->i2c_drv->vid_rec->ModeValid(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)
 {
     I830Ptr pI830 = I830PTR(pScrn);
 
-    if (output->i2c_drv == NULL)
-	return;
-
     output->i2c_drv->vid_rec->Mode(output->i2c_drv->dev_priv, pMode);
 
     OUTREG(DVOC, INREG(DVOC) & ~DVO_ENABLE);
@@ -179,8 +186,9 @@ i830_dvo_init(ScrnInfoPtr pScrn)
     pI830->output[i].dpms = i830_dvo_dpms;
     pI830->output[i].save = i830_dvo_save;
     pI830->output[i].restore = i830_dvo_restore;
-    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].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;
 
     /* Set up the I2C and DDC buses */
     ret = I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "DVOI2C_E");
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index 186d33b..399324f 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -123,6 +123,13 @@ i830_lvds_restore(ScrnInfoPtr pScrn, I83
 	i830SetLVDSPanelPower(pScrn, FALSE);
 }
 
+static int
+i830_lvds_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output,
+		    DisplayModePtr pMode)
+{
+   return MODE_OK;
+}
+
 static void
 i830_lvds_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
 		       DisplayModePtr pMode)
@@ -178,6 +185,7 @@ i830_lvds_init(ScrnInfoPtr pScrn)
     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;
 
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 9a1e155..76080df 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -545,7 +545,6 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn
     CARD8 c16a[8];
     CARD8 c17a[8];
     CARD16 out_timings[6];
-    CARD16 clock_min, clock_max;
     Bool out1, out2;
     I830SDVOPtr s = output->sdvo_drv;
 
@@ -588,8 +587,6 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn
     out_timings[5] = c17a[3] | ((short)c17a[2] << 8);
 
     I830SDVOSetTargetInput(s, FALSE, FALSE);
-    I830SDVOGetInputPixelClockRange(s, &clock_min, &clock_max);
-    ErrorF("clock min/max: %d %d\n", clock_min, clock_max);
 
     I830SDVOGetActiveOutputs(s, &out1, &out2);
     
@@ -775,6 +772,21 @@ i830_sdvo_restore(ScrnInfoPtr pScrn, I83
 			     sdvo->save_sdvo_active_2);
 }
 
+static int
+i830_sdvo_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output,
+		     DisplayModePtr pMode)
+{
+    I830SDVOPtr sdvo = output->sdvo_drv;
+
+    if (sdvo->pixel_clock_min > pMode->Clock)
+	return MODE_CLOCK_HIGH;
+
+    if (sdvo->pixel_clock_max < pMode->Clock)
+	return MODE_CLOCK_LOW;
+
+    return MODE_OK;
+}
+
 static void
 I830SDVOGetCapabilities(I830SDVOPtr s, i830_sdvo_caps *caps)
 {
@@ -954,6 +966,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
     pI830->output[pI830->num_outputs].dpms = i830_sdvo_dpms;
     pI830->output[pI830->num_outputs].save = i830_sdvo_save;
     pI830->output[pI830->num_outputs].restore = i830_sdvo_restore;
+    pI830->output[pI830->num_outputs].mode_valid = i830_sdvo_mode_valid;
     pI830->output[pI830->num_outputs].pre_set_mode = i830_sdvo_pre_set_mode;
     pI830->output[pI830->num_outputs].post_set_mode = i830_sdvo_post_set_mode;
 
@@ -1042,6 +1055,9 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
 
     I830SDVOGetCapabilities(sdvo, &sdvo->caps);
 
+    I830SDVOGetInputPixelClockRange(sdvo, &sdvo->pixel_clock_min,
+				    &sdvo->pixel_clock_max);
+
     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 	       "SDVO device VID/DID: %02X:%02X.%02X, %02X,"
 	       "output 1: %c, output 2: %c\n",
diff-tree c5cca4c20ae6b519e3b021a9d90809c1b3d1facb (from bf3820f1f505649ac0730add23d97d6de3f6d22c)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Fri Oct 13 15:31:43 2006 -0700

    Advertise textured video adapter first

diff --git a/src/i830_video.c b/src/i830_video.c
index 6a18f93..47f4a03 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -454,19 +454,6 @@ I830InitVideo(ScreenPtr pScreen)
    xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
    xvContrast = MAKE_ATOM("XV_CONTRAST");
 
-   /* Set up overlay video if we can do it at this depth. */
-   if (!IS_I965G(pI830) && pScrn->bitsPerPixel != 8) {
-      overlayAdaptor = I830SetupImageVideoOverlay(pScreen);
-      if (overlayAdaptor != NULL) {
-	 adaptors[num_adaptors++] = overlayAdaptor;
-	 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up overlay video\n");
-      } else {
-	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		    "Failed to set up overlay video\n");
-      }
-      I830InitOffscreenImages(pScreen);
-   }
-
    /* Set up textured video if we can do it at this depth and we are on
     * supported hardware.
     */
@@ -481,6 +468,19 @@ I830InitVideo(ScreenPtr pScreen)
       }
    }
 
+   /* Set up overlay video if we can do it at this depth. */
+   if (!IS_I965G(pI830) && pScrn->bitsPerPixel != 8) {
+      overlayAdaptor = I830SetupImageVideoOverlay(pScreen);
+      if (overlayAdaptor != NULL) {
+	 adaptors[num_adaptors++] = overlayAdaptor;
+	 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up overlay video\n");
+      } else {
+	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		    "Failed to set up overlay video\n");
+      }
+      I830InitOffscreenImages(pScreen);
+   }
+
    if (num_adaptors)
       xf86XVScreenInit(pScreen, adaptors, num_adaptors);
 
diff-tree 1838671476875e9f5b3dde235eacf9fb43afb66c (from 2591c1fcf15608d96031be4760cf08534461ca34)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Oct 10 12:41:01 2006 -0700

    Only disable the output when marked disabled.
    
    Also, remove a couple of dead variables.

diff --git a/src/i830_display.c b/src/i830_display.c
index 2693ded..9b20d65 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -627,16 +627,13 @@ void
 i830DisableUnusedFunctions(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    int outputsA, outputsB;
     int i;
 
-    outputsA = pI830->operatingDevices & 0xff;
-    outputsB = (pI830->operatingDevices >> 8) & 0xff;
-
     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling unused functions\n");
 
     for (i = 0; i < pI830->num_outputs; i++) {
-	pI830->output[i].dpms(pScrn, &pI830->output[i], DPMSModeOff);
+	if (pI830->output[i].disabled)
+	    pI830->output[i].dpms(pScrn, &pI830->output[i], DPMSModeOff);
     }
 
     /* Now, any unused plane, pipe, and DPLL (FIXME: except for DVO, i915
diff-tree 2591c1fcf15608d96031be4760cf08534461ca34 (from 09e3d10b0ff69d180467fa9099d12da08e4f681b)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Oct 9 14:20:49 2006 -0700

    Fix LVDS restore path, and move pipe assignment for outputs to the right place.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 3a278fb..1f53915 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1668,45 +1668,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 	 pI830->MonType1 |= PIPE_CRT;
       }
 
-      /* Perform the pipe assignment of outputs.  This code shouldn't exist,
-       * but for now we're supporting the existing MonitorLayout configuration
-       * scheme.
-       */
-      for (i = 0; i < pI830->num_outputs; i++) {
-	 pI830->output[i].disabled = FALSE;
-
-	 switch (pI830->output[i].type) {
-	 case I830_OUTPUT_LVDS:
-	    if (pI830->MonType1 & PIPE_LFP)
-	       pI830->output[i].pipe = 0;
-	    else if (pI830->MonType2 & PIPE_LFP)
-	       pI830->output[i].pipe = 1;
-	    else
-	       pI830->output[i].disabled = TRUE;
-	    break;
-	 case I830_OUTPUT_ANALOG:
-	    if (pI830->MonType1 & PIPE_CRT)
-	       pI830->output[i].pipe = 0;
-	    else if (pI830->MonType2 & PIPE_CRT)
-	       pI830->output[i].pipe = 1;
-	    else
-	       pI830->output[i].disabled = TRUE;
-	    break;
-	 case I830_OUTPUT_DVO:
-	 case I830_OUTPUT_SDVO:
-	    if (pI830->MonType1 & PIPE_DFP)
-	       pI830->output[i].pipe = 0;
-	    else if (pI830->MonType2 & PIPE_DFP)
-	       pI830->output[i].pipe = 1;
-	    else
-	       pI830->output[i].disabled = TRUE;
-	    break;
-	 default:
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unhandled output type\n");
-	    break;
-	 }
-      }
-
       /* Check for attached SDVO outputs.  Assume that they're flat panels for
        * now.  Though really, it's just a name at the moment, since we don't
        * treat different SDVO outputs differently.
@@ -1766,6 +1727,48 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       pI830->Clone = TRUE;
    }
 
+
+   /* Perform the pipe assignment of outputs.  This code shouldn't exist,
+    * but for now we're supporting the existing MonitorLayout configuration
+    * scheme.
+    */
+   for (i = 0; i < pI830->num_outputs; i++) {
+      pI830->output[i].disabled = FALSE;
+
+      switch (pI830->output[i].type) {
+      case I830_OUTPUT_LVDS:
+	 if (pI830->MonType1 & PIPE_LFP)
+	    pI830->output[i].pipe = 0;
+	 else if (pI830->MonType2 & PIPE_LFP)
+	    pI830->output[i].pipe = 1;
+	 else
+	    pI830->output[i].disabled = TRUE;
+	 break;
+      case I830_OUTPUT_ANALOG:
+	 if (pI830->MonType1 & PIPE_CRT)
+	    pI830->output[i].pipe = 0;
+	 else if (pI830->MonType2 & PIPE_CRT)
+	    pI830->output[i].pipe = 1;
+	 else
+	    pI830->output[i].disabled = TRUE;
+	 break;
+      case I830_OUTPUT_DVO:
+      case I830_OUTPUT_SDVO:
+	 if (pI830->MonType1 & PIPE_DFP)
+	    pI830->output[i].pipe = 0;
+	 else if (pI830->MonType2 & PIPE_DFP)
+	    pI830->output[i].pipe = 1;
+	 else
+	    pI830->output[i].disabled = TRUE;
+	 break;
+      default:
+	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unhandled output type\n");
+	 break;
+      }
+   }
+
+   
+
    pI830->CloneRefresh = 60; /* default to 60Hz */
    if (xf86GetOptValInteger(pI830->Options, OPTION_CLONE_REFRESH,
 			    &(pI830->CloneRefresh))) {
@@ -2703,6 +2706,10 @@ RestoreHWState(ScrnInfoPtr pScrn)
       }
    }
 
+   for (i = 0; i < pI830->num_outputs; i++) {
+      pI830->output[i].restore(pScrn, &pI830->output[i]);
+   }
+
    if (IS_I965G(pI830)) {
       OUTREG(DSPASURF, pI830->saveDSPABASE);
       OUTREG(DSPBSURF, pI830->saveDSPBBASE);
@@ -2719,10 +2726,6 @@ RestoreHWState(ScrnInfoPtr pScrn)
    OUTREG(DSPACNTR, pI830->saveDSPACNTR);
    OUTREG(DSPBCNTR, pI830->saveDSPBCNTR);
 
-   for (i = 0; i < pI830->num_outputs; i++) {
-      pI830->output[i].restore(pScrn, &pI830->output[i]);
-   }
-
    for(i = 0; i < 7; i++) {
 	   OUTREG(SWF0 + (i << 2), pI830->saveSWF[i]);
 	   OUTREG(SWF00 + (i << 2), pI830->saveSWF[i+7]);
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index 23fc0a7..186d33b 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -117,6 +117,10 @@ i830_lvds_restore(ScrnInfoPtr pScrn, I83
     OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL);
     OUTREG(LVDS, pI830->saveLVDS);
     OUTREG(PP_CONTROL, pI830->savePP_CONTROL);
+    if (pI830->savePP_CONTROL & POWER_TARGET_ON)
+	i830SetLVDSPanelPower(pScrn, TRUE);
+    else
+	i830SetLVDSPanelPower(pScrn, FALSE);
 }
 
 static void
@@ -159,6 +163,9 @@ i830_lvds_post_set_mode(ScrnInfoPtr pScr
      */
     OUTREG(LVDS, INREG(LVDS) | LVDS_PORT_EN | LVDS_PIPEB_SELECT);
 
+    /* Re-enable the PLL */
+    OUTREG(FPB0, INREG(FPB0) | DPLL_VCO_ENABLE);
+
     i830SetLVDSPanelPower(pScrn, TRUE);
 }
 
diff-tree 09e3d10b0ff69d180467fa9099d12da08e4f681b (from 317cc119c575650c1aa8bf992a0f42bdfffcd7ba)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Oct 9 13:09:18 2006 -0700

    Add a function for describing the output connection configuration.

diff --git a/src/i830_display.c b/src/i830_display.c
index 32ee6e2..2693ded 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -706,7 +706,6 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
 {
     I830Ptr pI830 = I830PTR(pScrn);
     Bool ok = TRUE;
-    CARD32 planeA, planeB;
 #ifdef XF86DRI
     Bool didLock = FALSE;
 #endif
@@ -777,18 +776,7 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
 
     i830DisableUnusedFunctions(pScrn);
 
-    planeA = INREG(DSPACNTR);
-    planeB = INREG(DSPBCNTR);
-
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-	       "Display plane A is now %s and connected to %s.\n",
-	       pI830->planeEnabled[0] ? "enabled" : "disabled",
-	       planeA & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A");
-    if (pI830->availablePipes == 2)
-	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		   "Display plane B is now %s and connected to %s.\n",
-		   pI830->planeEnabled[1] ? "enabled" : "disabled",
-		   planeB & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A");
+    i830DescribeOutputConfiguration(pScrn);
 
 #ifdef XF86DRI
    I830DRISetVBlankInterrupt (pScrn, TRUE);
@@ -804,6 +792,52 @@ done:
     return ok;
 }
 
+void
+i830DescribeOutputConfiguration(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    int i;
+
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output configuration:\n");
+
+    for (i = 0; i < pI830->availablePipes; i++) {
+	CARD32 dspcntr = INREG(DSPACNTR + (DSPBCNTR - DSPACNTR) * i);
+
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		   "  Display plane %c is now %s and connected to pipe %c.\n",
+		   'A' + i,
+		   pI830->planeEnabled[i] ? "enabled" : "disabled",
+		   dspcntr & DISPPLANE_SEL_PIPE_MASK ? 'B' : 'A');
+    }
+
+    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;
+	}
+
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		   "  Output %s is %sabled and connected to pipe %c\n",
+		   name, pI830->output[i].disabled ? "dis" : "en",
+		   pI830->output[i].pipe == 0 ? 'A' : 'B');
+    }
+}
+
 /**
  * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence.
  *
diff --git a/src/i830_display.h b/src/i830_display.h
index df8356a..9719406 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -33,6 +33,7 @@ Bool i830DetectCRT(ScrnInfoPtr pScrn, Bo
 void i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on);
 void i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y);
 void i830WaitForVblank(ScrnInfoPtr pScrn);
+void i830DescribeOutputConfiguration(ScrnInfoPtr pScrn);
 
 /* i830_sdvo.c */
 Bool I830SDVOPreSetMode(I830SDVOPtr s, DisplayModePtr mode);
diff-tree 317cc119c575650c1aa8bf992a0f42bdfffcd7ba (from 9bb7736ab36f172db58703c4664bb1b0cd7f80c3)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Oct 9 11:49:18 2006 -0700

    Move per-output mode setting code to per-output methods.
    
    This is not a very clean interface, as a number of outputs require tweaks to
    the DPLL registers.  When possible, the DPLLs are just adjusted in the
    per-output post_set_mode, which happens just after the DPLL is enabled.
    However, this seems better than the previous method of having all outputs
    programmed in the same function.

diff --git a/src/i830.h b/src/i830.h
index ae84846..c41cb56 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -222,12 +222,15 @@ extern const char *i830_output_type_name
 
 struct _I830OutputRec {
    int type;
-/*   int pipe;
-   int flags;*/
+   int pipe;
+   Bool disabled;
 
    /**
     * Turns the output on/off, or sets intermediate power levels if available.
-    * Unsupported intermediate modes drop to the lower power setting.
+    *
+    * 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);
 
@@ -241,6 +244,22 @@ struct _I830OutputRec {
     */
    void (*restore)(ScrnInfoPtr pScrn, I830OutputPtr output);
 
+   /**
+    * 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);
+
    xf86MonPtr MonInfo;
    I2CBusPtr pI2CBus;
    I2CBusPtr pDDCBus;
diff --git a/src/i830_crt.c b/src/i830_crt.c
index 72df6bc..1cf1687 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -40,15 +40,17 @@ i830_crt_dpms(ScrnInfoPtr pScrn, I830Out
 
     temp = INREG(ADPA);
     temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
+    temp &= ~ADPA_DAC_ENABLE;
 
     switch(mode) {
     case DPMSModeOn:
+	temp |= ADPA_DAC_ENABLE;
 	break;
     case DPMSModeStandby:
-	temp |= ADPA_HSYNC_CNTL_DISABLE;
+	temp |= ADPA_DAC_ENABLE | ADPA_HSYNC_CNTL_DISABLE;
 	break;
     case DPMSModeSuspend:
-	temp |= ADPA_VSYNC_CNTL_DISABLE;
+	temp |= ADPA_DAC_ENABLE | ADPA_VSYNC_CNTL_DISABLE;
 	break;
     case DPMSModeOff:
 	temp |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE;
@@ -74,6 +76,35 @@ i830_crt_restore(ScrnInfoPtr pScrn, I830
     OUTREG(ADPA, pI830->saveADPA);
 }
 
+static void
+i830_crt_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
+		      DisplayModePtr pMode)
+{
+}
+
+static void
+i830_crt_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
+		       DisplayModePtr pMode)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    CARD32 adpa;
+
+    adpa = ADPA_DAC_ENABLE;
+
+    if (pMode->Flags & V_PHSYNC)
+	adpa |= ADPA_HSYNC_ACTIVE_HIGH;
+    if (pMode->Flags & V_PVSYNC)
+	adpa |= ADPA_VSYNC_ACTIVE_HIGH;
+
+    if (output->pipe == 0)
+	adpa |= ADPA_PIPE_A_SELECT;
+    else
+	adpa |= ADPA_PIPE_B_SELECT;
+
+    OUTREG(ADPA, adpa);
+}
+
 void
 i830_crt_init(ScrnInfoPtr pScrn)
 {
@@ -83,6 +114,8 @@ i830_crt_init(ScrnInfoPtr pScrn)
     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].pre_set_mode = i830_crt_pre_set_mode;
+    pI830->output[pI830->num_outputs].post_set_mode = i830_crt_post_set_mode;
 
     /* Set up the DDC bus. */
     I830I2CInit(pScrn, &pI830->output[pI830->num_outputs].pDDCBus,
diff --git a/src/i830_display.c b/src/i830_display.c
index e3c3062..32ee6e2 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -226,7 +226,7 @@ i830FindBestPLL(ScrnInfoPtr pScrn, int o
     return (err != target);
 }
 
-static void
+void
 i830WaitForVblank(ScrnInfoPtr pScreen)
 {
     /* Wait for 20ms, i.e. one cycle at 50hz. */
@@ -260,6 +260,91 @@ i830PipeSetBase(ScrnInfoPtr pScrn, int p
 }
 
 /**
+ * In the current world order, there is a list of per-pipe modes, which may or
+ * may not include the mode that was asked to be set by XFree86's mode
+ * selection.  Find the closest one, in the following preference order:
+ *
+ * - Equality
+ * - Closer in size to the requested mode, but no larger
+ * - Closer in refresh rate to the requested mode.
+ */
+static DisplayModePtr
+i830PipeFindClosestMode(ScrnInfoPtr pScrn, int pipe, DisplayModePtr pMode)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    DisplayModePtr pBest = NULL, pScan;
+
+    /* If the pipe doesn't have any detected modes, just let the system try to
+     * spam the desired mode in.
+     */
+    if (pI830->pipeMon[pipe] == NULL) {
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		   "No pipe mode list for pipe %d,"
+		   "continuing with desired mode\n", pipe);
+	return pMode;
+    }
+
+    assert(pScan->VRefresh != 0.0);
+    for (pScan = pI830->pipeMon[pipe]->Modes; pScan != NULL;
+	 pScan = pScan->next) {
+	/* If there's an exact match, we're done. */
+	if (I830ModesEqual(pScan, pMode)) {
+	    pBest = pMode;
+	    break;
+	}
+
+	/* Reject if it's larger than the desired mode. */
+	if (pScan->HDisplay > pMode->HDisplay ||
+	    pScan->VDisplay > pMode->VDisplay)
+	{
+	    continue;
+	}
+
+	if (pBest == NULL) {
+	    pBest = pScan;
+	    continue;
+	}
+
+	/* Find if it's closer to the right size than the current best
+	 * option.
+	 */
+	if ((pScan->HDisplay > pBest->HDisplay &&
+	     pScan->VDisplay >= pBest->VDisplay) ||
+	    (pScan->HDisplay >= pBest->HDisplay &&
+	     pScan->VDisplay > pBest->VDisplay))
+	{
+	    pBest = pScan;
+	    continue;
+	}
+
+	/* Find if it's still closer to the right refresh than the current
+	 * best resolution.
+	 */
+	if (pScan->HDisplay == pBest->HDisplay &&
+	    pScan->VDisplay == pBest->VDisplay &&
+	    (fabs(pScan->VRefresh - pMode->VRefresh) <
+	     fabs(pBest->VRefresh - pMode->VRefresh))) {
+	    pBest = pScan;
+	}
+    }
+
+    if (pBest == NULL) {
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		   "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)) {
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		   "Choosing pipe %d's mode %dx%d@%.1f instead of xf86 "
+		   "mode %dx%d@%.1f\n", pipe,
+		   pBest->HDisplay, pBest->VDisplay, pBest->VRefresh,
+		   pMode->HDisplay, pMode->VDisplay, pMode->VRefresh);
+	pMode = pBest;
+    }
+    return pMode;
+}
+
+/**
  * Sets the given video mode on the given pipe.  Assumes that plane A feeds
  * pipe A, and plane B feeds pipe B.  Should not affect the other planes/pipes.
  */
@@ -270,119 +355,76 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     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;
-    CARD32 pipesrc, dspsize, adpa;
-    CARD32 sdvob = 0, sdvoc = 0, dvo = 0;
-    Bool ok, is_sdvo, is_dvo;
-    int refclk, pixel_clock, sdvo_pixel_multiply;
-    int outputs;
-    DisplayModePtr pMasterMode = pMode;
-
-    assert(pMode->VRefresh != 0.0);
-    /* If we've got a list of modes probed for the device, find the best match
-     * in there to the requested mode.
-     */
-    if (pI830->pipeMon[pipe] != NULL) {
-	DisplayModePtr pBest = NULL, pScan;
+    CARD32 pipesrc, dspsize;
+    Bool ok, is_sdvo = FALSE, is_dvo = FALSE;
+    Bool is_crt = FALSE, is_lvds = FALSE, is_tv = FALSE;
+    int refclk, pixel_clock;
+    int outputs, i;
+    int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
+    int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
+    int fp_reg = (pipe == 0) ? FPA0 : FPB0;
+    int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
+    int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
+    int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
+    int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
+    int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
+    int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
+    int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
+    int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE;
+    int dspstride_reg = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
+    int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
+    int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
 
-	assert(pScan->VRefresh != 0.0);
-	for (pScan = pI830->pipeMon[pipe]->Modes; pScan != NULL;
-	     pScan = pScan->next)
-	{
-	    /* If there's an exact match, we're done. */
-	    if (I830ModesEqual(pScan, pMode)) {
-		pBest = pMode;
-		break;
-	    }
-
-	    /* Reject if it's larger than the desired mode. */
-	    if (pScan->HDisplay > pMode->HDisplay ||
-		pScan->VDisplay > pMode->VDisplay)
-	    {
-		continue;
-	    }
-
-	    if (pBest == NULL) {
-		pBest = pScan;
-	        continue;
-	    }
-	    /* Find if it's closer to the right size than the current best
-	     * option.
-	     */
-	    if ((pScan->HDisplay > pBest->HDisplay && 
-		pScan->VDisplay >= pBest->VDisplay) ||
-	        (pScan->HDisplay >= pBest->HDisplay && 
-		pScan->VDisplay > pBest->VDisplay))
-	    {
-		pBest = pScan;
-		continue;
-	    }
-	    /* Find if it's still closer to the right refresh than the current
-	     * best resolution.
-	     */
-	    if (pScan->HDisplay == pBest->HDisplay && 
-		pScan->VDisplay == pBest->VDisplay &&
-		(fabs(pScan->VRefresh - pMode->VRefresh) <
-		fabs(pBest->VRefresh - pMode->VRefresh)))
-	    {
-		pBest = pScan;
-	    }
-	}
-	if (pBest != NULL) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		       "Choosing pipe %d's mode %dx%d@%.1f instead of xf86 "
-		       "mode %dx%d@%.1f\n", pipe,
-		       pBest->HDisplay, pBest->VDisplay, pBest->VRefresh,
-		       pMode->HDisplay, pMode->VDisplay, pMode->VRefresh);
-	    pMode = pBest;
-	}
-    }
     if (pipe == 0)
 	outputs = pI830->operatingDevices & 0xff;
     else
 	outputs = (pI830->operatingDevices >> 8) & 0xff;
 
-    if (outputs & PIPE_LCD_ACTIVE) {
-	if (I830ModesEqual(&pI830->pipeCurMode[pipe], pMasterMode))
-	    return TRUE;
-    } else {
-	if (I830ModesEqual(&pI830->pipeCurMode[pipe], pMode))
-	    return TRUE;
-    }
+    if (I830ModesEqual(&pI830->pipeCurMode[pipe], pMode))
+	return TRUE;
 
     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested pix clock: %d\n",
 	       pMode->Clock);
 
-    if ((outputs & PIPE_LCD_ACTIVE) && (outputs & ~PIPE_LCD_ACTIVE)) {
+    for (i = 0; i < pI830->num_outputs; i++) {
+	if (pI830->output[i].pipe != pipe || pI830->output[i].disabled)
+	    continue;
+
+	switch (pI830->output[i].type) {
+	case I830_OUTPUT_LVDS:
+	    is_lvds = TRUE;
+	    break;
+	case I830_OUTPUT_SDVO:
+	    is_sdvo = TRUE;
+	    break;
+	case I830_OUTPUT_DVO:
+	    is_dvo = TRUE;
+	    break;
+	case I830_OUTPUT_TVOUT:
+	    is_tv = TRUE;
+	    break;
+	case I830_OUTPUT_ANALOG:
+	    is_crt = TRUE;
+	    break;
+	}
+    }
+
+    if (is_lvds && (is_sdvo || is_dvo || is_tv || is_crt)) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		   "Can't enable LVDS and non-LVDS on the same pipe\n");
 	return FALSE;
     }
-    if (((outputs & PIPE_TV_ACTIVE) && (outputs & ~PIPE_TV_ACTIVE)) ||
-	((outputs & PIPE_TV2_ACTIVE) && (outputs & ~PIPE_TV2_ACTIVE))) {
+    if (is_tv && (is_sdvo || is_dvo || is_crt || is_lvds)) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		   "Can't enable a TV and any other output on the same pipe\n");
+		   "Can't enable a TV and any other output on the same "
+		   "pipe\n");
 	return FALSE;
     }
-    if (pipe == 0 && (outputs & PIPE_LCD_ACTIVE)) {
+    if (pipe == 0 && is_lvds) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		   "Can't support LVDS on pipe A\n");
 	return FALSE;
     }
-    if ((outputs & PIPE_DFP_ACTIVE) || (outputs & PIPE_DFP2_ACTIVE)) {
-	/* We'll change how we control outputs soon, but to get the SDVO code up
-	 * and running, just check for these two possibilities.
-	 */
-	if (IS_I9XX(pI830)) {
-	    is_sdvo = TRUE;
-	    is_dvo = FALSE;
-	} else {
-	    is_dvo = TRUE;
-	    is_sdvo = FALSE;
-	}
-    } else {
-	is_sdvo = FALSE;
-	is_dvo = FALSE;
-    }
 
     htot = (pMode->CrtcHDisplay - 1) | ((pMode->CrtcHTotal - 1) << 16);
     hblank = (pMode->CrtcHBlankStart - 1) | ((pMode->CrtcHBlankEnd - 1) << 16);
@@ -393,8 +435,8 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     pipesrc = ((pMode->HDisplay - 1) << 16) | (pMode->VDisplay - 1);
     dspsize = ((pMode->VDisplay - 1) << 16) | (pMode->HDisplay - 1);
     pixel_clock = pMode->Clock;
-    if (outputs & PIPE_LCD_ACTIVE && pI830->panel_fixed_hactive != 0)
-    {
+
+    if (is_lvds && pI830->panel_fixed_hactive != 0) {
 	/* To enable panel fitting, we need to set the pipe timings to that of
 	 * the screen at its full resolution.  So, drop the timings from the
 	 * BIOS VBT tables here.
@@ -420,30 +462,24 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 		  pI830->panel_fixed_vsyncwidth - 1) << 16);
 	pixel_clock = pI830->panel_fixed_clock;
 
-	if (pMasterMode->HDisplay <= pI830->panel_fixed_hactive &&
-	    pMasterMode->HDisplay <= pI830->panel_fixed_vactive)
+	if (pMode->HDisplay <= pI830->panel_fixed_hactive &&
+	    pMode->HDisplay <= pI830->panel_fixed_vactive)
 	{
-	    pipesrc = ((pMasterMode->HDisplay - 1) << 16) |
-		       (pMasterMode->VDisplay - 1);
-	    dspsize = ((pMasterMode->VDisplay - 1) << 16) |
-		       (pMasterMode->HDisplay - 1);
+	    pipesrc = ((pMode->HDisplay - 1) << 16) |
+		       (pMode->VDisplay - 1);
+	    dspsize = ((pMode->VDisplay - 1) << 16) |
+		       (pMode->HDisplay - 1);
 	}
     }
 
-    if (pMode->Clock >= 100000)
-	sdvo_pixel_multiply = 1;
-    else if (pMode->Clock >= 50000)
-	sdvo_pixel_multiply = 2;
-    else
-	sdvo_pixel_multiply = 4;
-
     /* In SDVO, we need to keep the clock on the bus between 1Ghz and 2Ghz.
      * The clock on the bus is 10 times the pixel clock normally.  If that
      * would be too low, we run the DPLL at a multiple of the pixel clock, and
-     * tell the SDVO device the multiplier so it can throw away the dummy bytes.
+     * tell the SDVO device the multiplier so it can throw away the dummy
+     * bytes.
      */
     if (is_sdvo) {
-	pixel_clock *= sdvo_pixel_multiply;
+	pixel_clock *= i830_sdvo_get_pixel_multiplier(pMode);
     }
 
     if (IS_I9XX(pI830)) {
@@ -461,7 +497,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 
     dpll = DPLL_VCO_ENABLE | DPLL_VGA_MODE_DIS;
     if (IS_I9XX(pI830)) {
-	if (outputs & PIPE_LCD_ACTIVE)
+	if (is_lvds)
 	    dpll |= DPLLB_MODE_LVDS;
 	else
 	    dpll |= DPLLB_MODE_DAC_SERIAL;
@@ -486,55 +522,15 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	    dpll |= PLL_P2_DIVIDE_BY_4;
     }
 
-    if (outputs & (PIPE_TV_ACTIVE | PIPE_TV2_ACTIVE))
+    if (is_tv)
 	dpll |= PLL_REF_INPUT_TVCLKINBC;
 #if 0    
-    else if (outputs & (PIPE_LCD_ACTIVE))
+    else if (is_lvds)
 	dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
 #endif
     else	
 	dpll |= PLL_REF_INPUT_DREFCLK;
 
-    if (is_dvo) {
-	dpll |= DPLL_DVO_HIGH_SPEED;
-
-	/* 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 (pipe == 1)
-	    dvo |= DVO_PIPE_B_SELECT;
-
-	if (pMode->Flags & V_PHSYNC)
-	    dvo |= DVO_HSYNC_ACTIVE_HIGH;
-	if (pMode->Flags & V_PVSYNC)
-	    dvo |= DVO_VSYNC_ACTIVE_HIGH;
-
-	OUTREG(DVOC, dvo & ~DVO_ENABLE);
-    }
-
-    if (is_sdvo) {
-	dpll |= DPLL_DVO_HIGH_SPEED;
-
-	ErrorF("DVOB: %08x\nDVOC: %08x\n", (int)INREG(SDVOB), (int)INREG(SDVOC));
-
-        sdvob = INREG(SDVOB) & SDVOB_PRESERVE_MASK;
-	sdvoc = INREG(SDVOC) & SDVOC_PRESERVE_MASK;
-	sdvob |= SDVO_ENABLE | (9 << 19) | SDVO_BORDER_ENABLE;
-	sdvoc |= 9 << 19;
-	if (pipe == 1)
-	    sdvob |= SDVO_PIPE_B_SELECT;
-
-	if (IS_I945G(pI830) || IS_I945GM(pI830))
-	    dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
-	else
-	    sdvob |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT;
-
-	OUTREG(SDVOC, INREG(SDVOC) & ~SDVO_ENABLE);
-	OUTREG(SDVOB, INREG(SDVOB) & ~SDVO_ENABLE);
-    }
-
     fp = ((n - 2) << 16) | ((m1 - 2) << 8) | (m2 - 2);
 
 #if 1
@@ -576,150 +572,53 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
  	dspcntr |= DISPPLANE_GAMMA_ENABLE;
     }
 
-    if (is_sdvo)
-	adpa = ADPA_DAC_DISABLE;
-    else
-	adpa = ADPA_DAC_ENABLE;
-    if (pMode->Flags & V_PHSYNC)
-	adpa |= ADPA_HSYNC_ACTIVE_HIGH;
-    if (pMode->Flags & V_PVSYNC)
-	adpa |= ADPA_VSYNC_ACTIVE_HIGH;
-    
-    if (pipe == 0) {
+    if (pipe == 0)
 	dspcntr |= DISPPLANE_SEL_PIPE_A;
-	adpa |= ADPA_PIPE_A_SELECT;
-    } else {
+    else
 	dspcntr |= DISPPLANE_SEL_PIPE_B;
-	adpa |= ADPA_PIPE_B_SELECT;
-    }
 
     OUTREG(VGACNTRL, VGA_DISP_DISABLE);
 
-    /* Set up display timings and PLLs for the pipe. */
-    if (pipe == 0) {
-	/* First, disable display planes */
-	temp = INREG(DSPACNTR);
-	OUTREG(DSPACNTR, temp & ~DISPLAY_PLANE_ENABLE);
-
-	/* Wait for vblank for the disable to take effect */
-	i830WaitForVblank(pScrn);
-
-	/* Next, disable display pipes */
-	temp = INREG(PIPEACONF);
-	OUTREG(PIPEACONF, temp & ~PIPEACONF_ENABLE);
-
-	OUTREG(FPA0, fp);
-	OUTREG(DPLL_A, dpll);
-
-	OUTREG(HTOTAL_A, htot);
-	OUTREG(HBLANK_A, hblank);
-	OUTREG(HSYNC_A, hsync);
-	OUTREG(VTOTAL_A, vtot);
-	OUTREG(VBLANK_A, vblank);
-	OUTREG(VSYNC_A, vsync);
-	OUTREG(DSPASTRIDE, pScrn->displayWidth * pI830->cpp);
-	OUTREG(DSPASIZE, dspsize);
-	OUTREG(DSPAPOS, 0);
-	i830PipeSetBase(pScrn, pipe, pI830->pipeX[pipe], pI830->pipeX[pipe]);
-	OUTREG(PIPEASRC, pipesrc);
-
-	/* Then, turn the pipe on first */
-	temp = INREG(PIPEACONF);
-	OUTREG(PIPEACONF, temp | PIPEACONF_ENABLE);
-
-	/* And then turn the plane on */
-	OUTREG(DSPACNTR, dspcntr);
-    } else {
-	/* Always make sure the LVDS is off before we play with DPLLs and pipe
-	 * configuration.
-	 */
-	i830SetLVDSPanelPower(pScrn, FALSE);
+    /* Finally, set the mode. */
+    /* First, disable display planes */
+    temp = INREG(dspcntr_reg);
+    OUTREG(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
+
+    /* Wait for vblank for the disable to take effect */
+    i830WaitForVblank(pScrn);
+
+    /* Next, disable display pipes */
+    temp = INREG(pipeconf_reg);
+    OUTREG(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
 
-	/* First, disable display planes */
-	temp = INREG(DSPBCNTR);
-	OUTREG(DSPBCNTR, temp & ~DISPLAY_PLANE_ENABLE);
-
-	/* Wait for vblank for the disable to take effect */
-	i830WaitForVblank(pScrn);
-
-	/* Next, disable display pipes */
-	temp = INREG(PIPEBCONF);
-	OUTREG(PIPEBCONF, temp & ~PIPEBCONF_ENABLE);
-
-	if (outputs & PIPE_LCD_ACTIVE) {
-	    /* Disable the PLL before messing with LVDS enable */
-	    OUTREG(FPB0, fp & ~DPLL_VCO_ENABLE);
-
-	    /* LVDS must be powered on before PLL is enabled and before power
-	     * sequencing the panel.
-	     */
-	    temp = INREG(LVDS);
-	    OUTREG(LVDS, temp | LVDS_PORT_EN | LVDS_PIPEB_SELECT);
-	}
-
-	OUTREG(FPB0, fp);
-	OUTREG(DPLL_B, dpll);
-	OUTREG(HTOTAL_B, htot);
-	OUTREG(HBLANK_B, hblank);
-	OUTREG(HSYNC_B, hsync);
-	OUTREG(VTOTAL_B, vtot);
-	OUTREG(VBLANK_B, vblank);
-	OUTREG(VSYNC_B, vsync);
-	OUTREG(DSPBSTRIDE, pScrn->displayWidth * pI830->cpp);
-	OUTREG(DSPBSIZE, dspsize);
-	OUTREG(DSPBPOS, 0);
-	i830PipeSetBase(pScrn, pipe, pI830->pipeX[pipe], pI830->pipeY[pipe]);
-	OUTREG(PIPEBSRC, pipesrc);
+    OUTREG(fp_reg, fp);
+    OUTREG(dpll_reg, dpll);
 
-	if (outputs & PIPE_LCD_ACTIVE) {
-	    CARD32  pfit_control;
-	    
-	    /* Enable automatic panel scaling so that non-native modes fill the
-	     * screen.
-	     */
-	    /* XXX: Allow (auto-?) enabling of 8-to-6 dithering */
-	    pfit_control = (PFIT_ENABLE |
-			    VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
-			    VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR);
-	    if (pI830->panel_wants_dither)
-		pfit_control |= PANEL_8TO6_DITHER_ENABLE;
-	    OUTREG(PFIT_CONTROL, pfit_control);
-	}
-
-	/* Then, turn the pipe on first */
-	temp = INREG(PIPEBCONF);
-	OUTREG(PIPEBCONF, temp | PIPEBCONF_ENABLE);
-
-	/* And then turn the plane on */
-	OUTREG(DSPBCNTR, dspcntr);
-
-	if (outputs & PIPE_LCD_ACTIVE) {
-	    i830SetLVDSPanelPower(pScrn, TRUE);
-	}
+    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);
     }
 
-    if (outputs & PIPE_CRT_ACTIVE)
-	OUTREG(ADPA, adpa);
-
-    if (is_dvo) {
-	/*OUTREG(DVOB_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
-	    (pMode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));*/
-	OUTREG(DVOC_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
-	    (pMode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));
-	/*OUTREG(DVOB, dvo);*/
-	OUTREG(DVOC, dvo);
-    }
+    OUTREG(htot_reg, htot);
+    OUTREG(hblank_reg, hblank);
+    OUTREG(hsync_reg, hsync);
+    OUTREG(vtot_reg, vtot);
+    OUTREG(vblank_reg, vblank);
+    OUTREG(vsync_reg, vsync);
+    OUTREG(dspstride_reg, pScrn->displayWidth * pI830->cpp);
+    OUTREG(dspsize_reg, dspsize);
+    OUTREG(dsppos_reg, 0);
+    i830PipeSetBase(pScrn, pipe, pI830->pipeX[pipe], pI830->pipeX[pipe]);
+    OUTREG(pipesrc_reg, pipesrc);
+
+    /* Then, turn the pipe on first */
+    temp = INREG(pipeconf_reg);
+    OUTREG(pipeconf_reg, temp | PIPEACONF_ENABLE);
 
-    if (is_sdvo) {
-	OUTREG(SDVOB, sdvob);
-	OUTREG(SDVOC, sdvoc);
-    }
+    /* And then turn the plane on */
+    OUTREG(dspcntr_reg, dspcntr);
 
-    if (outputs & PIPE_LCD_ACTIVE) {
-	pI830->pipeCurMode[pipe] = *pMasterMode;
-    } else {
-	pI830->pipeCurMode[pipe] = *pMode;
-    }
+    pI830->pipeCurMode[pipe] = *pMode;
 
     return TRUE;
 }
@@ -729,47 +628,15 @@ i830DisableUnusedFunctions(ScrnInfoPtr p
 {
     I830Ptr pI830 = I830PTR(pScrn);
     int outputsA, outputsB;
+    int i;
 
     outputsA = pI830->operatingDevices & 0xff;
     outputsB = (pI830->operatingDevices >> 8) & 0xff;
 
     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling unused functions\n");
 
-    /* First, disable the unused outputs */
-    if ((outputsA & PIPE_CRT_ACTIVE) == 0 &&
-	(outputsB & PIPE_CRT_ACTIVE) == 0)
-    {
-	CARD32 adpa = INREG(ADPA);
-
-	if (adpa & ADPA_DAC_ENABLE) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling CRT output\n");
-	    OUTREG(ADPA, adpa & ~ADPA_DAC_ENABLE);
-	}
-    }
-
-    if ((outputsB & PIPE_LCD_ACTIVE) == 0) {
-	CARD32 pp_status = INREG(PP_STATUS);
-
-	if (pp_status & PP_ON) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling LVDS output\n");
-	    i830SetLVDSPanelPower(pScrn, FALSE);
-	}
-    }
-
-    if (IS_I9XX(pI830) && ((outputsA & PIPE_DFP_ACTIVE) == 0 &&
-	(outputsB & PIPE_DFP_ACTIVE) == 0))
-    {
-	CARD32 sdvob = INREG(SDVOB);
-	CARD32 sdvoc = INREG(SDVOC);
-
-	if (sdvob & SDVO_ENABLE) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling SDVOB output\n");
-	    OUTREG(SDVOB, sdvob & ~SDVO_ENABLE);
-	}
-	if (sdvoc & SDVO_ENABLE) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling SDVOC output\n");
-	    OUTREG(SDVOC, sdvoc & ~SDVO_ENABLE);
-	}
+    for (i = 0; i < pI830->num_outputs; i++) {
+	pI830->output[i].dpms(pScrn, &pI830->output[i], DPMSModeOff);
     }
 
     /* Now, any unused plane, pipe, and DPLL (FIXME: except for DVO, i915
@@ -864,30 +731,21 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
     }
 
     for (i = 0; i < pI830->num_outputs; i++) {
-	I830OutputPtr output = &pI830->output[i];
-
-	if (pI830->output[i].type == I830_OUTPUT_SDVO)
-	    pI830->output[i].dpms(pScrn, &pI830->output[i], DPMSModeOff);
-
-	if (pI830->output[i].type == I830_OUTPUT_DVO)
-	    output->i2c_drv->vid_rec->Mode(output->i2c_drv->dev_priv,
-					   pMode);
+	pI830->output[i].pre_set_mode(pScrn, &pI830->output[i], pMode);
     }
 
     if (pI830->planeEnabled[0]) {
-	ok = i830PipeSetMode(pScrn, pMode, 0);
+	ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, 0, pMode),
+			     0);
 	if (!ok)
 	    goto done;
     }
     if (pI830->planeEnabled[1]) {
-	ok = i830PipeSetMode(pScrn, pMode, 1);
+	ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, 1, pMode),
+			     1);
 	if (!ok)
 	    goto done;
     }
-    for (i = 0; i < pI830->num_outputs; i++) {
-	if (pI830->output[i].type == I830_OUTPUT_SDVO)
-	    I830SDVOPostSetMode(pI830->output[i].sdvo_drv, pMode);
-    }
 
     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Mode bandwidth is %d Mpixel/s\n",
 	       (int)(pMode->HDisplay * pMode->VDisplay *
@@ -1092,42 +950,3 @@ i830DetectCRT(ScrnInfoPtr pScrn, Bool al
 
     return FALSE;
 }
-
-/**
- * Sets the power state for the panel.
- */
-void
-i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on)
-{
-    I830Ptr pI830 = I830PTR(pScrn);
-    CARD32 pp_status, pp_control;
-    CARD32 blc_pwm_ctl;
-    int backlight_duty_cycle;
-
-    blc_pwm_ctl = INREG (BLC_PWM_CTL);
-    backlight_duty_cycle = blc_pwm_ctl & BACKLIGHT_DUTY_CYCLE_MASK;
-    if (backlight_duty_cycle)
-        pI830->backlight_duty_cycle = backlight_duty_cycle;
-    
-    if (on) {
-	OUTREG(PP_STATUS, INREG(PP_STATUS) | PP_ON);
-	OUTREG(PP_CONTROL, INREG(PP_CONTROL) | POWER_TARGET_ON);
-	do {
-	    pp_status = INREG(PP_STATUS);
-	    pp_control = INREG(PP_CONTROL);
-	} while (!(pp_status & PP_ON) && !(pp_control & POWER_TARGET_ON));
-	OUTREG(BLC_PWM_CTL,
-	       (blc_pwm_ctl & ~BACKLIGHT_DUTY_CYCLE_MASK) |
-	       pI830->backlight_duty_cycle);
-    } else {
-	OUTREG(BLC_PWM_CTL,
-	       (blc_pwm_ctl & ~BACKLIGHT_DUTY_CYCLE_MASK));
-	       
-	OUTREG(PP_STATUS, INREG(PP_STATUS) & ~PP_ON);
-	OUTREG(PP_CONTROL, INREG(PP_CONTROL) & ~POWER_TARGET_ON);
-	do {
-	    pp_status = INREG(PP_STATUS);
-	    pp_control = INREG(PP_CONTROL);
-	} while ((pp_status & PP_ON) || (pp_control & POWER_TARGET_ON));
-    }
-}
diff --git a/src/i830_display.h b/src/i830_display.h
index 91450fe..df8356a 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -32,6 +32,7 @@ Bool i830SetMode(ScrnInfoPtr pScrn, Disp
 Bool i830DetectCRT(ScrnInfoPtr pScrn, Bool allow_disturb);
 void i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on);
 void i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y);
+void i830WaitForVblank(ScrnInfoPtr pScrn);
 
 /* i830_sdvo.c */
 Bool I830SDVOPreSetMode(I830SDVOPtr s, DisplayModePtr mode);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 4b55855..3a278fb 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1528,7 +1528,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
     * that we might find early in the list.  This hackery will go away when we
     * start doing independent per-head mode selection.
     */
-   for (i = MAX_OUTPUTS - 1; i >= 0; i--) {
+   for (i = pI830->num_outputs - 1; i >= 0; i--) {
      if (pI830->output[i].MonInfo) {
        pScrn->monitor->DDC = pI830->output[i].MonInfo;
        xf86SetDDCproperties(pScrn, pI830->output[i].MonInfo);
@@ -1668,11 +1668,50 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 	 pI830->MonType1 |= PIPE_CRT;
       }
 
+      /* Perform the pipe assignment of outputs.  This code shouldn't exist,
+       * but for now we're supporting the existing MonitorLayout configuration
+       * scheme.
+       */
+      for (i = 0; i < pI830->num_outputs; i++) {
+	 pI830->output[i].disabled = FALSE;
+
+	 switch (pI830->output[i].type) {
+	 case I830_OUTPUT_LVDS:
+	    if (pI830->MonType1 & PIPE_LFP)
+	       pI830->output[i].pipe = 0;
+	    else if (pI830->MonType2 & PIPE_LFP)
+	       pI830->output[i].pipe = 1;
+	    else
+	       pI830->output[i].disabled = TRUE;
+	    break;
+	 case I830_OUTPUT_ANALOG:
+	    if (pI830->MonType1 & PIPE_CRT)
+	       pI830->output[i].pipe = 0;
+	    else if (pI830->MonType2 & PIPE_CRT)
+	       pI830->output[i].pipe = 1;
+	    else
+	       pI830->output[i].disabled = TRUE;
+	    break;
+	 case I830_OUTPUT_DVO:
+	 case I830_OUTPUT_SDVO:
+	    if (pI830->MonType1 & PIPE_DFP)
+	       pI830->output[i].pipe = 0;
+	    else if (pI830->MonType2 & PIPE_DFP)
+	       pI830->output[i].pipe = 1;
+	    else
+	       pI830->output[i].disabled = TRUE;
+	    break;
+	 default:
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unhandled output type\n");
+	    break;
+	 }
+      }
+
       /* Check for attached SDVO outputs.  Assume that they're flat panels for
        * now.  Though really, it's just a name at the moment, since we don't
        * treat different SDVO outputs differently.
        */
-      for (i = 0; i < MAX_OUTPUTS; i++) {
+      for (i = 0; i < pI830->num_outputs; i++) {
 	 if (pI830->output[i].type == I830_OUTPUT_SDVO) {
 	    if (!I830DetectSDVODisplays(pScrn, i))
 	       continue;
@@ -2607,11 +2646,6 @@ RestoreHWState(ScrnInfoPtr pScrn)
    vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS);
    vgaHWLock(hwp);
 
-   /* Disable outputs */
-   for (i = 0; i < pI830->num_outputs; i++) {
-      pI830->output[i].dpms(pScrn, &pI830->output[i], DPMSModeOff);
-   }
-
    /* First, disable display planes */
    temp = INREG(DSPACNTR);
    OUTREG(DSPACNTR, temp & ~DISPLAY_PLANE_ENABLE);
@@ -2624,6 +2658,11 @@ RestoreHWState(ScrnInfoPtr pScrn)
    temp = INREG(PIPEBCONF);
    OUTREG(PIPEBCONF, temp & ~PIPEBCONF_ENABLE);
 
+   /* Disable outputs if necessary */
+   for (i = 0; i < pI830->num_outputs; i++) {
+      pI830->output[i].pre_set_mode(pScrn, &pI830->output[i], NULL);
+   }
+
    i830WaitForVblank(pScrn);
 
    OUTREG(FPA0, pI830->saveFPA0);
@@ -4333,7 +4372,7 @@ i830MonitorDetectDebugger(ScrnInfoPtr pS
    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Detected CRT as %s in %dms\n",
 	      found_crt ? "connected" : "disconnected", finish - start);
 
-   for (i = 0; i < MAX_OUTPUTS; i++) {
+   for (i = 0; i < pI830->num_outputs; i++) {
       Bool found_sdvo = TRUE;
 
       if (pI830->output[i].type != I830_OUTPUT_SDVO)
diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index 27f1755..ea74337 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -22,7 +22,8 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN A
 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 USE OR OTHER DEALINGS IN THE SOFTWARE.
 
-**************************************************************************/
+******
+********************************************************************/
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -30,6 +31,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #include "xf86.h"
 #include "i830.h"
+#include "i810_reg.h"
 
 #include "sil164/sil164.h"
 #include "ch7xxx/ch7xxx.h"
@@ -90,6 +92,51 @@ i830_dvo_restore(ScrnInfoPtr pScrn, I830
     output->i2c_drv->vid_rec->RestoreRegs(output->i2c_drv->dev_priv);
 }
 
+static void
+i830_dvo_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
+		      DisplayModePtr pMode)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    if (output->i2c_drv == NULL)
+	return;
+
+    output->i2c_drv->vid_rec->Mode(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)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD32 dvo;
+    int dpll_reg = (output->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)
+	dvo |= DVO_PIPE_B_SELECT;
+
+    if (pMode->Flags & V_PHSYNC)
+	dvo |= DVO_HSYNC_ACTIVE_HIGH;
+    if (pMode->Flags & V_PVSYNC)
+	dvo |= DVO_VSYNC_ACTIVE_HIGH;
+
+    OUTREG(dpll_reg, INREG(dpll_reg) | DPLL_DVO_HIGH_SPEED);
+
+    /*OUTREG(DVOB_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
+      (pMode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));*/
+    OUTREG(DVOC_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
+	   (pMode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));
+    /*OUTREG(DVOB, dvo);*/
+    OUTREG(DVOC, dvo);
+}
+
 static Bool
 I830I2CDetectDVOControllers(ScrnInfoPtr pScrn, I2CBusPtr pI2CBus,
 			    struct _I830DVODriver **retdrv)
@@ -132,6 +179,8 @@ i830_dvo_init(ScrnInfoPtr pScrn)
     pI830->output[i].dpms = i830_dvo_dpms;
     pI830->output[i].save = i830_dvo_save;
     pI830->output[i].restore = i830_dvo_restore;
+    pI830->output[i].pre_set_mode  = i830_dvo_pre_set_mode ;
+    pI830->output[i].post_set_mode  = i830_dvo_post_set_mode ;
 
     /* Set up the I2C and DDC buses */
     ret = I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "DVOI2C_E");
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index 3ce8cb6..23fc0a7 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -32,6 +32,45 @@
 #include "xf86.h"
 #include "i830.h"
 
+/**
+ * Sets the power state for the panel.
+ */
+static void
+i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD32 pp_status, pp_control;
+    CARD32 blc_pwm_ctl;
+    int backlight_duty_cycle;
+
+    blc_pwm_ctl = INREG (BLC_PWM_CTL);
+    backlight_duty_cycle = blc_pwm_ctl & BACKLIGHT_DUTY_CYCLE_MASK;
+    if (backlight_duty_cycle)
+        pI830->backlight_duty_cycle = backlight_duty_cycle;
+
+    if (on) {
+	OUTREG(PP_STATUS, INREG(PP_STATUS) | PP_ON);
+	OUTREG(PP_CONTROL, INREG(PP_CONTROL) | POWER_TARGET_ON);
+	do {
+	    pp_status = INREG(PP_STATUS);
+	    pp_control = INREG(PP_CONTROL);
+	} while (!(pp_status & PP_ON) && !(pp_control & POWER_TARGET_ON));
+	OUTREG(BLC_PWM_CTL,
+	       (blc_pwm_ctl & ~BACKLIGHT_DUTY_CYCLE_MASK) |
+	       pI830->backlight_duty_cycle);
+    } else {
+	OUTREG(BLC_PWM_CTL,
+	       (blc_pwm_ctl & ~BACKLIGHT_DUTY_CYCLE_MASK));
+
+	OUTREG(PP_STATUS, INREG(PP_STATUS) & ~PP_ON);
+	OUTREG(PP_CONTROL, INREG(PP_CONTROL) & ~POWER_TARGET_ON);
+	do {
+	    pp_status = INREG(PP_STATUS);
+	    pp_control = INREG(PP_CONTROL);
+	} while ((pp_status & PP_ON) || (pp_control & POWER_TARGET_ON));
+    }
+}
+
 static void
 i830_lvds_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
 {
@@ -80,6 +119,49 @@ i830_lvds_restore(ScrnInfoPtr pScrn, I83
     OUTREG(PP_CONTROL, pI830->savePP_CONTROL);
 }
 
+static void
+i830_lvds_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
+		       DisplayModePtr pMode)
+{
+    /* 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
+     * conservative for now.
+     */
+    i830SetLVDSPanelPower(pScrn, FALSE);
+}
+
+static void
+i830_lvds_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
+			DisplayModePtr pMode)
+{
+    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
+     * register description.
+     */
+    pfit_control = (PFIT_ENABLE |
+		    VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
+		    VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR);
+
+    if (pI830->panel_wants_dither)
+	pfit_control |= PANEL_8TO6_DITHER_ENABLE;
+
+    OUTREG(PFIT_CONTROL, pfit_control);
+
+    /* Disable the PLL before messing with LVDS enable */
+    OUTREG(FPB0, INREG(FPB0) & ~DPLL_VCO_ENABLE);
+
+    /* LVDS must be powered on before PLL is enabled and before power
+     * sequencing the panel.
+     */
+    OUTREG(LVDS, INREG(LVDS) | LVDS_PORT_EN | LVDS_PIPEB_SELECT);
+
+    i830SetLVDSPanelPower(pScrn, TRUE);
+}
+
 void
 i830_lvds_init(ScrnInfoPtr pScrn)
 {
@@ -89,6 +171,8 @@ i830_lvds_init(ScrnInfoPtr pScrn)
     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].pre_set_mode = i830_lvds_pre_set_mode;
+    pI830->output[pI830->num_outputs].post_set_mode = i830_lvds_post_set_mode;
 
     /* Set up the LVDS DDC channel.  Most panels won't support it, but it can
      * be useful if available.
diff --git a/src/i830_modes.c b/src/i830_modes.c
index f7d4695..83c6051 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -750,7 +750,7 @@ I830ReprobePipeModeList(ScrnInfoPtr pScr
     else
 	outputs = (pI830->operatingDevices >> 8) & 0xff;
 
-    for (i = 0; i < MAX_OUTPUTS; i++) {
+    for (i = 0; i < pI830->num_outputs; i++) {
 	switch (pI830->output[i].type) {
 	case I830_OUTPUT_ANALOG:
 	    if (outputs & PIPE_CRT) {
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index dc17af0..9a1e155 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -34,6 +34,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "compiler.h"
 #include "i830.h"
 #include "i830_display.h"
+#include "i810_reg.h"
 #include "i830_sdvo_regs.h"
 
 CARD16 curr_table[6];
@@ -169,6 +170,17 @@ I830SDVOReadInputRegs(I830SDVOPtr s)
     ErrorF("\n");
 }
 
+int
+i830_sdvo_get_pixel_multiplier(DisplayModePtr pMode)
+{
+    if (pMode->Clock >= 100000)
+	return 1;
+    else if (pMode->Clock >= 50000)
+	return 2;
+    else
+	return 4;
+}
+
 /* Sets the control bus switch to either point at one of the DDC buses or the
  * PROM.  It resets from the DDC bus back to internal registers at the next I2C
  * STOP.  PROM access is terminated by accessing an internal register.
@@ -520,9 +532,11 @@ I830SDVOSetClockRateMult(I830SDVOPtr s, 
     return TRUE;
 }
 
-Bool
-I830SDVOPreSetMode(I830SDVOPtr s, DisplayModePtr mode)
+static void
+i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
+			DisplayModePtr mode)
 {
+    I830Ptr pI830 = I830PTR(pScrn);
     CARD16 clock = mode->Clock/10, width = mode->CrtcHDisplay;
     CARD16 height = mode->CrtcVDisplay;
     CARD16 h_blank_len, h_sync_len, v_blank_len, v_sync_len;
@@ -533,6 +547,7 @@ I830SDVOPreSetMode(I830SDVOPtr s, Displa
     CARD16 out_timings[6];
     CARD16 clock_min, clock_max;
     Bool out1, out2;
+    I830SDVOPtr s = output->sdvo_drv;
 
     /* do some mode translations */
     h_blank_len = mode->CrtcHBlankEnd - mode->CrtcHBlankStart;
@@ -600,22 +615,34 @@ I830SDVOPreSetMode(I830SDVOPtr s, Displa
 				 out_timings[5]);
 
     I830SDVOSetTargetInput (s, FALSE, FALSE);
-    
-    if (clock >= 10000)
+
+    switch (i830_sdvo_get_pixel_multiplier(mode)) {
+    case 1:
 	I830SDVOSetClockRateMult(s, SDVO_CLOCK_RATE_MULT_1X);
-    else if (clock >= 5000)
+	break;
+    case 2:
 	I830SDVOSetClockRateMult(s, SDVO_CLOCK_RATE_MULT_2X);
-    else
+	break;
+    case 4:
 	I830SDVOSetClockRateMult(s, SDVO_CLOCK_RATE_MULT_4X);
+	break;
+    }
 
-    return TRUE;
+    OUTREG(SDVOC, INREG(SDVOC) & ~SDVO_ENABLE);
+    OUTREG(SDVOB, INREG(SDVOB) & ~SDVO_ENABLE);
 }
 
-Bool
-I830SDVOPostSetMode(I830SDVOPtr s, DisplayModePtr mode)
+static void
+i830_sdvo_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
+			DisplayModePtr mode)
 {
+    I830Ptr pI830 = I830PTR(pScrn);
     Bool ret = TRUE;
     Bool out1, out2;
+    CARD32 dpll, sdvob, sdvoc;
+    int dpll_reg = (output->pipe == 0) ? DPLL_A : DPLL_B;
+    int sdvo_pixel_multiply;
+    I830SDVOPtr s = output->sdvo_drv;
 
     /* the BIOS writes out 6 commands post mode set */
     /* two 03s, 04 05, 10, 1d */
@@ -636,18 +663,41 @@ I830SDVOPostSetMode(I830SDVOPtr s, Displ
     I830SDVOSetActiveOutputs(s, TRUE, FALSE);
     I830SDVOSetTargetInput (s, FALSE, FALSE);
 
-    return ret;
+    /* Set the SDVO control regs. */
+    sdvob = INREG(SDVOB) & SDVOB_PRESERVE_MASK;
+    sdvoc = INREG(SDVOC) & SDVOC_PRESERVE_MASK;
+    sdvob |= SDVO_ENABLE | (9 << 19) | SDVO_BORDER_ENABLE;
+    sdvoc |= 9 << 19;
+    if (output->pipe == 1)
+	sdvob |= SDVO_PIPE_B_SELECT;
+
+    dpll = INREG(dpll_reg);
+
+    sdvo_pixel_multiply = i830_sdvo_get_pixel_multiplier(mode);
+    if (IS_I945G(pI830) || IS_I945GM(pI830))
+	dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
+    else
+	sdvob |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT;
+
+    OUTREG(dpll_reg, dpll | DPLL_DVO_HIGH_SPEED);
+
+    OUTREG(SDVOB, sdvob);
+    OUTREG(SDVOC, sdvoc);
 }
 
 static void
 i830_sdvo_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
 {
+    I830Ptr pI830 = I830PTR(pScrn);
     I830SDVOPtr sdvo = output->sdvo_drv;
 
-    if (mode != DPMSModeOn)
+    if (mode != DPMSModeOn) {
 	I830SDVOSetActiveOutputs(sdvo, FALSE, FALSE);
-    else
+	OUTREG(SDVOB, INREG(SDVOB) & ~SDVO_ENABLE);
+    } else {
 	I830SDVOSetActiveOutputs(sdvo, TRUE, FALSE);
+	OUTREG(SDVOB, INREG(SDVOB) | SDVO_ENABLE);
+    }
 }
 
 static void
@@ -857,13 +907,11 @@ void
 I830DumpSDVO (ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    I830SDVOPtr	s;
     int	i;
 
-    for (i = 0; i < 4; i++) {
-	s = pI830->output[i].sdvo_drv;
-	if (s)
-	    I830DumpOneSDVO (s);
+    for (i = 0; i < pI830->num_outputs; i++) {
+	if (pI830->output[i].type == I830_OUTPUT_SDVO)
+	    I830DumpOneSDVO (pI830->output[i].sdvo_drv);
     }
 }
 
@@ -906,6 +954,8 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
     pI830->output[pI830->num_outputs].dpms = i830_sdvo_dpms;
     pI830->output[pI830->num_outputs].save = i830_sdvo_save;
     pI830->output[pI830->num_outputs].restore = i830_sdvo_restore;
+    pI830->output[pI830->num_outputs].pre_set_mode = i830_sdvo_pre_set_mode;
+    pI830->output[pI830->num_outputs].post_set_mode = i830_sdvo_post_set_mode;
 
     /* Find an existing SDVO I2CBus from another output, or allocate it. */
     for (i = 0; i < pI830->num_outputs; i++) {
@@ -974,7 +1024,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
 	return;
     }
 
-    pI830->output[pI830->num_outputs].pI2CBus = ddcbus;
+    pI830->output[pI830->num_outputs].pI2CBus = i2cbus;
     pI830->output[pI830->num_outputs].pDDCBus = ddcbus;
     pI830->output[pI830->num_outputs].sdvo_drv = sdvo;
 
diff --git a/src/i830_sdvo.h b/src/i830_sdvo.h
index 9a3586f..44bbfe4 100644
--- a/src/i830_sdvo.h
+++ b/src/i830_sdvo.h
@@ -58,6 +58,9 @@ typedef struct _i830_sdvo_dtd {
 void
 i830_sdvo_init(ScrnInfoPtr pScrn, int output_device);
 
+int
+i830_sdvo_get_pixel_multiplier(DisplayModePtr pMode);
+
 Bool
 I830DetectSDVODisplays(ScrnInfoPtr pScrn, int output_index);
 
diff-tree 53c28b3980d2682de830e8f86553ccad71527ac1 (from d649fb0d964a9b40b8e04314b5fc14bbbfd41bc3)
Author: Adam Jackson <ajax at benzedrine.nwnk.net>
Date:   Sat Oct 7 11:18:26 2006 -0400

    Expand the check for AOpen Mini-PC.
    
    Just match on subsystem vendor, don't bother inspecting the subsystem device
    ID, since apparently they're all busted.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 07a9d59..a69b5c6 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1577,8 +1577,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 
    /* Blacklist machines with known broken BIOSes */
    if (pI830->PciInfo->chipType == PCI_CHIP_I945_GM) {
-	if ((pI830->PciInfo->subsysVendor == 0xa0a0) &&
-	    (pI830->PciInfo->subsysCard == 0x0589))  /* aopen mini pc */
+	if (pI830->PciInfo->subsysVendor == 0xa0a0)  /* aopen mini pc */
 	    has_lvds = FALSE;
 
 	if ((pI830->PciInfo->subsysVendor == 0x8086) &&
diff-tree bf3820f1f505649ac0730add23d97d6de3f6d22c (from d649fb0d964a9b40b8e04314b5fc14bbbfd41bc3)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Fri Oct 6 21:57:26 2006 -0700

    Compute LVDS resolution from server DPI and native panel size.
    
    I was unable to find the native LVDS panel physical size in the BDB
    information. I would prefer to report accurate information through RandR if
    possible though.

diff --git a/src/i830_modes.c b/src/i830_modes.c
index ac7c4c5..9301dda 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -651,11 +651,27 @@ static MonPtr
 i830GetLVDSMonitor(ScrnInfoPtr pScrn)
 {
     MonPtr mon;
+    DisplayModePtr  mode;
 
     mon = xnfcalloc(1, sizeof(*mon));
     mon->Modes = i830GetLVDSModes(pScrn, pScrn->display->modes);
     mon->Last = i830GetModeListTail(mon->Modes);
-
+    /*
+     * Find the preferred mode, use the display resolution to compute
+     * the effective monitor size
+     */
+    for (mode = mon->Modes; mode; mode = mode->next)
+	if (mode->type & M_T_PREFERRED)
+	    break;
+    if (!mode)
+	mode = mon->Modes;
+    if (mode)
+    {
+#define MMPERINCH 25.4
+	mon->widthmm = (double) mode->HDisplay / pScrn->xDpi * MMPERINCH;
+	mon->heightmm = (double) mode->VDisplay / pScrn->yDpi * MMPERINCH;
+    }
+	
     return mon;
 }
 
diff-tree d649fb0d964a9b40b8e04314b5fc14bbbfd41bc3 (from 0a5504e59f90abecedd81a8435b88a60fe098f29)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Thu Oct 5 22:46:07 2006 -0700

    Don't require MonitorLayout when two monitors are plugged in.
    
    With randr12 working, we can just leave the second monitor off for now.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index d46fc1b..07a9d59 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1771,13 +1771,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    }
 
    if ((pI830->entityPrivate && I830IsPrimary(pScrn)) || pI830->Clone) {
-      if ((!xf86GetOptValString(pI830->Options, OPTION_MONITOR_LAYOUT))) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "You must have a MonitorLayout "
-	 		"defined for use in a DualHead, Clone or MergedFB setup.\n");
-         PreInitCleanup(pScrn);
-         return FALSE;
-      }
-
       if (pI830->MonType1 == PIPE_NONE || pI830->MonType2 == PIPE_NONE) {
          xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Monitor 1 or Monitor 2 "
 	 		"cannot be type NONE in DualHead or Clone setup.\n");
diff-tree 9bb7736ab36f172db58703c4664bb1b0cd7f80c3 (from ada8f62da263d1e93e22df4e0b1149bf1dbe24d4)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Oct 5 16:02:02 2006 -0700

    Remove checks for output privates in various bits of code.
    
    Now, the output is only set up if it fully initializes, so it will never exist
    if the private it requires doesn't.

diff --git a/src/i830_display.c b/src/i830_display.c
index 5a0fb9d..e3c3062 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -866,10 +866,10 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
     for (i = 0; i < pI830->num_outputs; i++) {
 	I830OutputPtr output = &pI830->output[i];
 
-	if (pI830->output[i].sdvo_drv != NULL)
+	if (pI830->output[i].type == I830_OUTPUT_SDVO)
 	    pI830->output[i].dpms(pScrn, &pI830->output[i], DPMSModeOff);
 
-	if (output->i2c_drv != NULL)
+	if (pI830->output[i].type == I830_OUTPUT_DVO)
 	    output->i2c_drv->vid_rec->Mode(output->i2c_drv->dev_priv,
 					   pMode);
     }
@@ -885,7 +885,7 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
 	    goto done;
     }
     for (i = 0; i < pI830->num_outputs; i++) {
-	if (pI830->output[i].sdvo_drv)
+	if (pI830->output[i].type == I830_OUTPUT_SDVO)
 	    I830SDVOPostSetMode(pI830->output[i].sdvo_drv, pMode);
     }
 
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 5da31a6..4b55855 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -985,14 +985,12 @@ I830DetectMonitors(ScrnInfoPtr pScrn)
 	 xf86PrintEDID(pI830->output[i].MonInfo);
       break;
       case I830_OUTPUT_SDVO:
-	 if (pI830->output[i].sdvo_drv != NULL) {
-	    pI830->output[i].MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex,
-						       pI830->output[i].pDDCBus);
-
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC SDVO %d, %08lX\n", i,
-		       pI830->output[i].pDDCBus->DriverPrivate.uval);
-	    xf86PrintEDID(pI830->output[i].MonInfo);
-	 }
+	 pI830->output[i].MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex,
+						    pI830->output[i].pDDCBus);
+
+	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC SDVO %d, %08lX\n", i,
+		    pI830->output[i].pDDCBus->DriverPrivate.uval);
+	 xf86PrintEDID(pI830->output[i].MonInfo);
 	 break;
       case I830_OUTPUT_UNUSED:
 	 break;
@@ -1675,8 +1673,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
        * treat different SDVO outputs differently.
        */
       for (i = 0; i < MAX_OUTPUTS; i++) {
-	 if (pI830->output[i].type == I830_OUTPUT_SDVO &&
-	     pI830->output[i].sdvo_drv != NULL) {
+	 if (pI830->output[i].type == I830_OUTPUT_SDVO) {
 	    if (!I830DetectSDVODisplays(pScrn, i))
 	       continue;
 
@@ -4339,11 +4336,8 @@ i830MonitorDetectDebugger(ScrnInfoPtr pS
    for (i = 0; i < MAX_OUTPUTS; i++) {
       Bool found_sdvo = TRUE;
 
-      if (pI830->output[i].type != I830_OUTPUT_SDVO ||
-	  pI830->output[i].sdvo_drv == NULL)
-      {
+      if (pI830->output[i].type != I830_OUTPUT_SDVO)
 	 continue;
-      }
       start = GetTimeInMillis();
       found_sdvo = I830DetectSDVODisplays(pScrn, i);   
       finish = GetTimeInMillis();
diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index 86d7d73..27f1755 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -57,9 +57,6 @@ struct _I830DVODriver i830_dvo_drivers[]
 static void
 i830_dvo_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
 {
-    if (output->i2c_drv == NULL)
-	return;
-
     if (mode == DPMSModeOn)
 	output->i2c_drv->vid_rec->Power(output->i2c_drv->dev_priv, TRUE);
     else
@@ -71,9 +68,6 @@ i830_dvo_save(ScrnInfoPtr pScrn, I830Out
 {
     I830Ptr pI830 = I830PTR(pScrn);
 
-    if (output->i2c_drv == NULL)
-	return;
-
     /* Each output should probably just save the registers it touches, but for
      * now, use more overkill.
      */
@@ -89,9 +83,6 @@ i830_dvo_restore(ScrnInfoPtr pScrn, I830
 {
     I830Ptr pI830 = I830PTR(pScrn);
 
-    if (output->i2c_drv == NULL)
-	return;
-
     OUTREG(DVOA, pI830->saveDVOA);
     OUTREG(DVOB, pI830->saveDVOB);
     OUTREG(DVOC, pI830->saveDVOC);
@@ -99,7 +90,7 @@ i830_dvo_restore(ScrnInfoPtr pScrn, I830
     output->i2c_drv->vid_rec->RestoreRegs(output->i2c_drv->dev_priv);
 }
 
-Bool
+static Bool
 I830I2CDetectDVOControllers(ScrnInfoPtr pScrn, I2CBusPtr pI2CBus,
 			    struct _I830DVODriver **retdrv)
 {
diff --git a/src/i830_modes.c b/src/i830_modes.c
index da1ccde..f7d4695 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -763,14 +763,12 @@ I830ReprobePipeModeList(ScrnInfoPtr pScr
 	    }
 	    break;
 	case I830_OUTPUT_DVO:
-	    if (outputs & PIPE_DFP && pI830->output[i].i2c_drv != NULL) {
+	    if (outputs & PIPE_DFP) {
 		output_index = i;
 	    }
 	    break;
 	case I830_OUTPUT_SDVO:
-	    if (outputs & PIPE_DFP &&
-		pI830->output[i].sdvo_drv != NULL)
-	    {
+	    if (outputs & PIPE_DFP) {
 		output_index = i;
 	    }
 	    break;
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 9792904..dc17af0 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -644,9 +644,6 @@ i830_sdvo_dpms(ScrnInfoPtr pScrn, I830Ou
 {
     I830SDVOPtr sdvo = output->sdvo_drv;
 
-    if (sdvo == NULL)
-	return;
-
     if (mode != DPMSModeOn)
 	I830SDVOSetActiveOutputs(sdvo, FALSE, FALSE);
     else
@@ -659,9 +656,6 @@ i830_sdvo_save(ScrnInfoPtr pScrn, I830Ou
     I830Ptr pI830 = I830PTR(pScrn);
     I830SDVOPtr sdvo = output->sdvo_drv;
 
-    if (sdvo == NULL)
-	return;
-
     sdvo->save_sdvo_mult = I830SDVOGetClockRateMult(sdvo);
     I830SDVOGetActiveOutputs(sdvo, &sdvo->save_sdvo_active_1,
 			     &sdvo->save_sdvo_active_2);
@@ -699,9 +693,6 @@ i830_sdvo_restore(ScrnInfoPtr pScrn, I83
     I830Ptr pI830 = I830PTR(pScrn);
     I830SDVOPtr sdvo = output->sdvo_drv;
 
-    if (sdvo == NULL)
-	return;
-
     if (sdvo->caps.caps & 0x1) {
        I830SDVOSetTargetInput(sdvo, FALSE, FALSE);
        I830SDVOSetTimings(sdvo, &sdvo->save_input_dtd_1,
diff-tree ada8f62da263d1e93e22df4e0b1149bf1dbe24d4 (from 103b4edce7859ddf58f3e1fadeb427a5e85c7acd)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Oct 5 15:55:07 2006 -0700

    Give each output type an init method in its file, making other methods static.

diff --git a/src/i830.h b/src/i830.h
index f92704b..ae84846 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -633,21 +633,13 @@ extern Bool I830I2CInit(ScrnInfoPtr pScr
 			char *name);
 
 /* i830_crt.c */
-void I830CRTDPMS(ScrnInfoPtr pScrn, I830OutputPtr output, int mode);
-void I830CRTSave(ScrnInfoPtr pScrn, I830OutputPtr output);
-void I830CRTRestore(ScrnInfoPtr pScrn, I830OutputPtr output);
+void i830_crt_init(ScrnInfoPtr pScrn);
 
 /* i830_dvo.c */
-void I830DVODPMS(ScrnInfoPtr pScrn, I830OutputPtr output, int mode);
-void I830DVOSave(ScrnInfoPtr pScrn, I830OutputPtr output);
-void I830DVORestore(ScrnInfoPtr pScrn, I830OutputPtr output);
-Bool I830I2CDetectDVOControllers(ScrnInfoPtr pScrn, I2CBusPtr pI2CBus,
-				 struct _I830DVODriver **retdrv);
+void i830_dvo_init(ScrnInfoPtr pScrn);
 
 /* i830_lvds.c */
-void I830LVDSDPMS(ScrnInfoPtr pScrn, I830OutputPtr output, int mode);
-void I830LVDSSave(ScrnInfoPtr pScrn, I830OutputPtr output);
-void I830LVDSRestore(ScrnInfoPtr pScrn, I830OutputPtr output);
+void i830_lvds_init(ScrnInfoPtr pScrn);
 
 /* i830_memory.c */
 Bool I830BindAGPMemory(ScrnInfoPtr pScrn);
diff --git a/src/i830_crt.c b/src/i830_crt.c
index 1a0dd0b..72df6bc 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -32,8 +32,8 @@
 #include "xf86.h"
 #include "i830.h"
 
-void
-I830CRTDPMS(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
+static void
+i830_crt_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     CARD32 temp;
@@ -58,18 +58,35 @@ I830CRTDPMS(ScrnInfoPtr pScrn, I830Outpu
     OUTREG(ADPA, temp);
 }
 
-void
-I830CRTSave(ScrnInfoPtr pScrn, I830OutputPtr output)
+static void
+i830_crt_save(ScrnInfoPtr pScrn, I830OutputPtr output)
 {
     I830Ptr pI830 = I830PTR(pScrn);
 
     pI830->saveADPA = INREG(ADPA);
 }
 
-void
-I830CRTRestore(ScrnInfoPtr pScrn, I830OutputPtr output)
+static void
+i830_crt_restore(ScrnInfoPtr pScrn, I830OutputPtr output)
 {
     I830Ptr pI830 = I830PTR(pScrn);
 
     OUTREG(ADPA, pI830->saveADPA);
 }
+
+void
+i830_crt_init(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    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;
+
+    /* Set up the DDC bus. */
+    I830I2CInit(pScrn, &pI830->output[pI830->num_outputs].pDDCBus,
+		GPIOA, "CRTDDC_A");
+
+    pI830->num_outputs++;
+}
diff --git a/src/i830_display.h b/src/i830_display.h
index 2b808ad..91450fe 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -34,7 +34,5 @@ void i830SetLVDSPanelPower(ScrnInfoPtr p
 void i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y);
 
 /* i830_sdvo.c */
-I830SDVOPtr I830SDVOInit(ScrnInfoPtr pScrn, int output_index,
-			 CARD32 output_device);
 Bool I830SDVOPreSetMode(I830SDVOPtr s, DisplayModePtr mode);
 Bool I830SDVOPostSetMode(I830SDVOPtr s, DisplayModePtr mode);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 93c7fc4..5da31a6 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -900,71 +900,30 @@ I830UseDDC(ScrnInfoPtr pScrn)
 }
 #endif
 
+/**
+ * Set up the outputs according to what type of chip we are.
+ *
+ * Some outputs may not initialize, due to allocation failure or because a
+ * controller chip isn't found.
+ */
 static void
-I830SetupOutputBusses(ScrnInfoPtr pScrn)
+I830SetupOutputs(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
-   int i = 0;
-   Bool ret;
 
    /* everyone has at least a single analog output */
-   pI830->output[i].type = I830_OUTPUT_ANALOG;
-   pI830->output[i].dpms = I830CRTDPMS;
-   pI830->output[i].save = I830CRTSave;
-   pI830->output[i].restore = I830CRTRestore;
-
-   /* setup the DDC bus for the analog output */
-   I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOA, "CRTDDC_A");
-   i++;
-
-   if (IS_MOBILE(pI830) && !IS_I830(pI830)) {
-      /* Set up integrated LVDS */
-      pI830->output[i].type = I830_OUTPUT_LVDS;
-      pI830->output[i].dpms = I830LVDSDPMS;
-      pI830->output[i].save = I830LVDSSave;
-      pI830->output[i].restore = I830LVDSRestore;
-      I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOC, "LVDSDDC_C");
-      i++;
-   }
+   i830_crt_init(pScrn);
 
-   if (IS_I9XX(pI830)) {
-      /* Set up SDVOB */
-      pI830->output[i].type = I830_OUTPUT_SDVO;
-      pI830->output[i].dpms = i830SDVODPMS;
-      pI830->output[i].save = i830SDVOSave;
-      pI830->output[i].restore = i830SDVORestore;
-      I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "SDVOCTRL_E");
-      I830SDVOInit(pScrn, i, SDVOB);
-      i++;
-
-      /* Set up SDVOC */
-      pI830->output[i].type = I830_OUTPUT_SDVO;
-      pI830->output[i].dpms = i830SDVODPMS;
-      pI830->output[i].save = i830SDVOSave;
-      pI830->output[i].restore = i830SDVORestore;
-      pI830->output[i].pI2CBus = pI830->output[i-1].pI2CBus;
-      I830SDVOInit(pScrn, i, SDVOC);
-      i++;
-   } else {
-      /* set up DVO */
-      pI830->output[i].type = I830_OUTPUT_DVO;
-      pI830->output[i].dpms = I830DVODPMS;
-      pI830->output[i].save = I830DVOSave;
-      pI830->output[i].restore = I830DVORestore;
-      I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOD, "DVODDC_D");
-      I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "DVOI2C_E");
-
-      ret = I830I2CDetectDVOControllers(pScrn, pI830->output[i].pI2CBus,
-					&pI830->output[i].i2c_drv);
-      if (ret == TRUE) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08lX\n",
-		    pI830->output[i].i2c_drv->modulename,
-		    pI830->output[i].pI2CBus->DriverPrivate.uval);
-      }
+   /* Set up integrated LVDS */
+   if (IS_MOBILE(pI830) && !IS_I830(pI830))
+      i830_lvds_init(pScrn);
 
-      i++;
+   if (IS_I9XX(pI830)) {
+      i830_sdvo_init(pScrn, SDVOB);
+      i830_sdvo_init(pScrn, SDVOC);
+   } else {
+      i830_dvo_init(pScrn);
    }
-   pI830->num_outputs = i;
 }
 
 static void 
@@ -985,7 +944,7 @@ I830PreInitDDC(ScrnInfoPtr pScrn)
       if (xf86LoadSubModule(pScrn, "i2c")) {
 	 xf86LoaderReqSymLists(I810i2cSymbols, NULL);
 
-	 I830SetupOutputBusses(pScrn);
+	 I830SetupOutputs(pScrn);
 
 	 pI830->ddc2 = TRUE;
       } else {
diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index f64a8e8..86d7d73 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -54,8 +54,8 @@ struct _I830DVODriver i830_dvo_drivers[]
 
 #define I830_NUM_DVO_DRIVERS (sizeof(i830_dvo_drivers)/sizeof(struct _I830DVODriver))
 
-void
-I830DVODPMS(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
+static void
+i830_dvo_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
 {
     if (output->i2c_drv == NULL)
 	return;
@@ -66,8 +66,8 @@ I830DVODPMS(ScrnInfoPtr pScrn, I830Outpu
 	output->i2c_drv->vid_rec->Power(output->i2c_drv->dev_priv, FALSE);
 }
 
-void
-I830DVOSave(ScrnInfoPtr pScrn, I830OutputPtr output)
+static void
+i830_dvo_save(ScrnInfoPtr pScrn, I830OutputPtr output)
 {
     I830Ptr pI830 = I830PTR(pScrn);
 
@@ -84,8 +84,8 @@ I830DVOSave(ScrnInfoPtr pScrn, I830Outpu
     output->i2c_drv->vid_rec->SaveRegs(output->i2c_drv->dev_priv);
 }
 
-void
-I830DVORestore(ScrnInfoPtr pScrn, I830OutputPtr output)
+static void
+i830_dvo_restore(ScrnInfoPtr pScrn, I830OutputPtr output)
 {
     I830Ptr pI830 = I830PTR(pScrn);
 
@@ -129,3 +129,42 @@ I830I2CDetectDVOControllers(ScrnInfoPtr 
     }
     return FALSE;
 }
+
+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;
+
+    /* Set up the I2C and DDC buses */
+    ret = I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "DVOI2C_E");
+    if (!ret)
+	return;
+
+    ret = I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOD, "DVODDC_D");
+    if (!ret) {
+	xf86DestroyI2CBusRec(pI830->output[i].pI2CBus, TRUE, TRUE);
+	return;
+    }
+
+    /* Now, try to find a controller */
+    ret = I830I2CDetectDVOControllers(pScrn, pI830->output[i].pI2CBus,
+				      &pI830->output[i].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);
+	return;
+    }
+
+    pI830->num_outputs++;
+}
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index fcd8fee..3ce8cb6 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -32,8 +32,8 @@
 #include "xf86.h"
 #include "i830.h"
 
-void
-I830LVDSDPMS(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
+static void
+i830_lvds_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
 {
     if (mode == DPMSModeOn)
 	i830SetLVDSPanelPower(pScrn, TRUE);
@@ -41,8 +41,8 @@ I830LVDSDPMS(ScrnInfoPtr pScrn, I830Outp
 	i830SetLVDSPanelPower(pScrn, FALSE);
 }
 
-void
-I830LVDSSave(ScrnInfoPtr pScrn, I830OutputPtr output)
+static void
+i830_lvds_save(ScrnInfoPtr pScrn, I830OutputPtr output)
 {
     I830Ptr pI830 = I830PTR(pScrn);
 
@@ -66,8 +66,8 @@ I830LVDSSave(ScrnInfoPtr pScrn, I830Outp
     }
 }
 
-void
-I830LVDSRestore(ScrnInfoPtr pScrn, I830OutputPtr output)
+static void
+i830_lvds_restore(ScrnInfoPtr pScrn, I830OutputPtr output)
 {
     I830Ptr pI830 = I830PTR(pScrn);
 
@@ -79,3 +79,22 @@ I830LVDSRestore(ScrnInfoPtr pScrn, I830O
     OUTREG(LVDS, pI830->saveLVDS);
     OUTREG(PP_CONTROL, pI830->savePP_CONTROL);
 }
+
+void
+i830_lvds_init(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(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;
+
+    /* 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++;
+}
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index a07e7c9..9792904 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -639,8 +639,22 @@ I830SDVOPostSetMode(I830SDVOPtr s, Displ
     return ret;
 }
 
-void
-i830SDVOSave(ScrnInfoPtr pScrn, I830OutputPtr output)
+static void
+i830_sdvo_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
+{
+    I830SDVOPtr sdvo = output->sdvo_drv;
+
+    if (sdvo == NULL)
+	return;
+
+    if (mode != DPMSModeOn)
+	I830SDVOSetActiveOutputs(sdvo, FALSE, FALSE);
+    else
+	I830SDVOSetActiveOutputs(sdvo, TRUE, FALSE);
+}
+
+static void
+i830_sdvo_save(ScrnInfoPtr pScrn, I830OutputPtr output)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     I830SDVOPtr sdvo = output->sdvo_drv;
@@ -679,23 +693,8 @@ i830SDVOSave(ScrnInfoPtr pScrn, I830Outp
     sdvo->save_SDVOX = INREG(sdvo->output_device);
 }
 
-void
-i830SDVODPMS(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
-{
-    I830Ptr pI830 = I830PTR(pScrn);
-    I830SDVOPtr sdvo = output->sdvo_drv;
-
-    if (sdvo == NULL)
-	return;
-
-    if (mode != DPMSModeOn)
-	I830SDVOSetActiveOutputs(sdvo, FALSE, FALSE);
-    else
-	I830SDVOSetActiveOutputs(sdvo, TRUE, FALSE);
-}
-
-void
-i830SDVORestore(ScrnInfoPtr pScrn, I830OutputPtr output)
+static void
+i830_sdvo_restore(ScrnInfoPtr pScrn, I830OutputPtr output)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     I830SDVOPtr sdvo = output->sdvo_drv;
@@ -827,95 +826,6 @@ I830SDVODDCI2CAddress(I2CDevPtr d, I2CSl
     return FALSE;
 }
 
-I830SDVOPtr
-I830SDVOInit(ScrnInfoPtr pScrn, int output_index, CARD32 output_device)
-{
-    I830Ptr pI830 = I830PTR(pScrn);
-    I830SDVOPtr sdvo;
-    int i;
-    unsigned char ch[0x40];
-    I2CBusPtr i2cbus, ddcbus;
-
-    i2cbus = pI830->output[output_index].pI2CBus;
-
-    sdvo = xcalloc(1, sizeof(I830SDVORec));
-    if (sdvo == NULL)
-	return NULL;
-
-    if (output_device == SDVOB) {
-	sdvo->d.DevName = "SDVO Controller B";
-	sdvo->d.SlaveAddr = 0x70;
-    } else {
-	sdvo->d.DevName = "SDVO Controller C";
-	sdvo->d.SlaveAddr = 0x72;
-    }
-    sdvo->d.pI2CBus = i2cbus;
-    sdvo->d.DriverPrivate.ptr = sdvo;
-    sdvo->output_device = output_device;
-
-    if (!xf86I2CDevInit(&sdvo->d)) {
-	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		   "Failed to initialize SDVO I2C device %s\n",
-		   output_device == SDVOB ? "SDVOB" : "SDVOC");
-	xfree(sdvo);
-	return NULL;
-    }
-
-    /* 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
-     * Start, extra attempts should be harmless.
-     */
-    ddcbus = xf86CreateI2CBusRec();
-    if (ddcbus == NULL) {
-	xf86DestroyI2CDevRec(&sdvo->d, 0);
-	xfree(sdvo);
-	return NULL;
-    }
-    if (output_device == SDVOB)
-        ddcbus->BusName = "SDVOB DDC Bus";
-    else
-        ddcbus->BusName = "SDVOC DDC Bus";
-    ddcbus->scrnIndex = i2cbus->scrnIndex;
-    ddcbus->I2CGetByte = I830SDVODDCI2CGetByte;
-    ddcbus->I2CPutByte = I830SDVODDCI2CPutByte;
-    ddcbus->I2CStart = I830SDVODDCI2CStart;
-    ddcbus->I2CStop = I830SDVODDCI2CStop;
-    ddcbus->I2CAddress = I830SDVODDCI2CAddress;
-    ddcbus->DriverPrivate.ptr = sdvo;
-    if (!xf86I2CBusInit(ddcbus)) {
-	xf86DestroyI2CDevRec(&sdvo->d, 0);
-	xfree(sdvo);
-	return NULL;
-    }
-
-    pI830->output[output_index].pDDCBus = ddcbus;
-
-    /* Read the regs to test if we can talk to the device */
-    for (i = 0; i < 0x40; i++) {
-	if (!sReadByte(sdvo, i, &ch[i])) {
-	    xf86DestroyI2CBusRec(pI830->output[output_index].pDDCBus, FALSE,
-		FALSE);
-	    xf86DestroyI2CDevRec(&sdvo->d, 0);
-	    xfree(sdvo);
-	    return NULL;
-	}
-    }
-
-    pI830->output[output_index].sdvo_drv = sdvo;
-
-    I830SDVOGetCapabilities(sdvo, &sdvo->caps);
-    
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-	       "SDVO device VID/DID: %02X:%02X.%02X, %02X, output 1: %c, output 2: %c\n",
-	       sdvo->caps.vendor_id, sdvo->caps.device_id,
-	       sdvo->caps.device_rev_id, sdvo->caps.caps,
-	       sdvo->caps.output_0_supported ? 'Y' : 'N',
-	       sdvo->caps.output_1_supported ? 'Y' : 'N');
-
-    return sdvo;
-}
-
 static void
 I830DumpSDVOCmd (I830SDVOPtr s, int opcode)
 {
@@ -991,3 +901,113 @@ I830DetectSDVODisplays(ScrnInfoPtr pScrn
     return (s->sdvo_regs[SDVO_I2C_RETURN_0] != 0 ||
 	    s->sdvo_regs[SDVO_I2C_RETURN_1] != 0);
 }
+
+void
+i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830SDVOPtr sdvo;
+    int i;
+    unsigned char ch[0x40];
+    I2CBusPtr i2cbus = NULL, ddcbus;
+
+    pI830->output[pI830->num_outputs].type = I830_OUTPUT_SDVO;
+    pI830->output[pI830->num_outputs].dpms = i830_sdvo_dpms;
+    pI830->output[pI830->num_outputs].save = i830_sdvo_save;
+    pI830->output[pI830->num_outputs].restore = i830_sdvo_restore;
+
+    /* Find an existing SDVO I2CBus from another output, or allocate it. */
+    for (i = 0; i < pI830->num_outputs; i++) {
+	if (pI830->output[i].type == I830_OUTPUT_SDVO)
+	    i2cbus = pI830->output[i].pI2CBus;
+    }
+    if (i2cbus == NULL)
+	I830I2CInit(pScrn, &i2cbus, GPIOE, "SDVOCTRL_E");
+    if (i2cbus == NULL)
+	return;
+
+    /* Allocate the SDVO output private data */
+    sdvo = xcalloc(1, sizeof(I830SDVORec));
+    if (sdvo == NULL) {
+	xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE);
+	return;
+    }
+
+    if (output_device == SDVOB) {
+	sdvo->d.DevName = "SDVO Controller B";
+	sdvo->d.SlaveAddr = 0x70;
+    } else {
+	sdvo->d.DevName = "SDVO Controller C";
+	sdvo->d.SlaveAddr = 0x72;
+    }
+    sdvo->d.pI2CBus = i2cbus;
+    sdvo->d.DriverPrivate.ptr = sdvo;
+    sdvo->output_device = output_device;
+
+    if (!xf86I2CDevInit(&sdvo->d)) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "Failed to initialize SDVO I2C device %s\n",
+		   output_device == SDVOB ? "SDVOB" : "SDVOC");
+	xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE);
+	xfree(sdvo);
+	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
+     * Start, extra attempts should be harmless.
+     */
+    ddcbus = xf86CreateI2CBusRec();
+    if (ddcbus == NULL) {
+	xf86DestroyI2CDevRec(&sdvo->d, FALSE);
+	xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE);
+	xfree(sdvo);
+	return;
+    }
+    if (output_device == SDVOB)
+        ddcbus->BusName = "SDVOB DDC Bus";
+    else
+        ddcbus->BusName = "SDVOC DDC Bus";
+    ddcbus->scrnIndex = i2cbus->scrnIndex;
+    ddcbus->I2CGetByte = I830SDVODDCI2CGetByte;
+    ddcbus->I2CPutByte = I830SDVODDCI2CPutByte;
+    ddcbus->I2CStart = I830SDVODDCI2CStart;
+    ddcbus->I2CStop = I830SDVODDCI2CStop;
+    ddcbus->I2CAddress = I830SDVODDCI2CAddress;
+    ddcbus->DriverPrivate.ptr = sdvo;
+    if (!xf86I2CBusInit(ddcbus)) {
+	xf86DestroyI2CDevRec(&sdvo->d, FALSE);
+	xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE);
+	xfree(sdvo);
+	return;
+    }
+
+    pI830->output[pI830->num_outputs].pI2CBus = ddcbus;
+    pI830->output[pI830->num_outputs].pDDCBus = ddcbus;
+    pI830->output[pI830->num_outputs].sdvo_drv = sdvo;
+
+    /* Read the regs to test if we can talk to the device */
+    for (i = 0; i < 0x40; i++) {
+	if (!sReadByte(sdvo, i, &ch[i])) {
+	    xf86DestroyI2CBusRec(pI830->output[pI830->num_outputs].pDDCBus,
+				 FALSE, FALSE);
+	    xf86DestroyI2CDevRec(&sdvo->d, FALSE);
+	    xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE);
+	    xfree(sdvo);
+	    return;
+	}
+    }
+
+    I830SDVOGetCapabilities(sdvo, &sdvo->caps);
+
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+	       "SDVO device VID/DID: %02X:%02X.%02X, %02X,"
+	       "output 1: %c, output 2: %c\n",
+	       sdvo->caps.vendor_id, sdvo->caps.device_id,
+	       sdvo->caps.device_rev_id, sdvo->caps.caps,
+	       sdvo->caps.output_0_supported ? 'Y' : 'N',
+	       sdvo->caps.output_1_supported ? 'Y' : 'N');
+
+    pI830->num_outputs++;
+}
diff --git a/src/i830_sdvo.h b/src/i830_sdvo.h
index 73ecf32..9a3586f 100644
--- a/src/i830_sdvo.h
+++ b/src/i830_sdvo.h
@@ -56,13 +56,7 @@ typedef struct _i830_sdvo_dtd {
 } __attribute__((packed)) i830_sdvo_dtd;
 
 void
-i830SDVODPMS(ScrnInfoPtr pScrn, I830OutputPtr output, int mode);
-
-void
-i830SDVOSave(ScrnInfoPtr pScrn, I830OutputPtr output);
-
-void
-i830SDVORestore(ScrnInfoPtr pScrn, I830OutputPtr output);
+i830_sdvo_init(ScrnInfoPtr pScrn, int output_device);
 
 Bool
 I830DetectSDVODisplays(ScrnInfoPtr pScrn, int output_index);
diff-tree 0a5504e59f90abecedd81a8435b88a60fe098f29 (from 4ac81d58b7e0fbffbb4981deffe6a576be821a9b)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Oct 5 09:11:29 2006 -0700

    Fix DPI at startup in RandR 1.2 code.
    
    Use requested monitor resolution to compute the appropriate screen size when
    resizing the screen during RandR initialization.

diff --git a/src/i830_randr.c b/src/i830_randr.c
index 3c594d8..e4075f2 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -832,12 +832,25 @@ I830RandRCreateScreenResources12 (Screen
     mode = pScrn->currentMode;
     if (mode)
     {
+	int mmWidth, mmHeight;
+
+	if (mode->HDisplay == pScreen->width &&
+	    mode->VDisplay == pScreen->height)
+	{
+	    mmWidth = pScrn->widthmm;
+	    mmHeight = pScrn->heightmm;
+	}
+	else
+	{
+#define MMPERINCH 25.4
+	    mmWidth = (double) mode->HDisplay / pScrn->xDpi * MMPERINCH;
+	    mmHeight = (double) mode->VDisplay / pScrn->yDpi * MMPERINCH;
+	}
 	I830RandRScreenSetSize (pScreen,
 				mode->HDisplay,
 				mode->VDisplay,
-				pScreen->mmWidth,
-				pScreen->mmHeight);
-	
+				mmWidth,
+				mmHeight);
     }
 			    
     for (i = 0; i < MAX_DISPLAY_PIPES; i++)
diff-tree 4ac81d58b7e0fbffbb4981deffe6a576be821a9b (from 16988b27258acfe3d56fc2415aa9ade1ae8d03a9)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Wed Oct 4 23:22:52 2006 -0700

    Remove mode origins, add preferred mode count.
    
    Just tracking changes in the 1.2 protocol spec.

diff --git a/src/i830_randr.c b/src/i830_randr.c
index 37bd6a1..3c594d8 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -603,10 +603,11 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
     int			nclone;
     RRCrtcPtr		crtcs[MAX_DISPLAY_PIPES];
     int			ncrtc;
-    int			nmode;
+    int			nmode, npreferred;
     struct _I830OutputRec   *output;
     int			i;
     int			j;
+    int			p;
     int			clone_types;
     int			crtc_types;
     int			connection;
@@ -700,6 +701,7 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
 	RROutputSetPossibleOptions (randrp->outputs[i], possibleOptions);
 	RROutputSetCurrentOptions (randrp->outputs[i], currentOptions);
         nmode = 0;
+	npreferred = 0;
 	rrmodes = NULL;
 	if (pipe >= 0) 
 	{
@@ -715,44 +717,43 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
 		if (!rrmodes)
 		    return FALSE;
 		nmode = 0;
-		for (mode = modes; mode; mode = mode->next)
+		for (p = 1; p >= 0; p--)
 		{
-		    modeInfo.nameLength = strlen (mode->name);
-		    modeInfo.mmWidth = mon->widthmm;
-		    modeInfo.mmHeight = mon->heightmm;
-
-		    modeInfo.width = mode->HDisplay;
-		    modeInfo.dotClock = mode->Clock * 1000;
-		    modeInfo.hSyncStart = mode->HSyncStart;
-		    modeInfo.hSyncEnd = mode->HSyncEnd;
-		    modeInfo.hTotal = mode->HTotal;
-		    modeInfo.hSkew = mode->HSkew;
-
-		    modeInfo.height = mode->VDisplay;
-		    modeInfo.vSyncStart = mode->VSyncStart;
-		    modeInfo.vSyncEnd = mode->VSyncEnd;
-		    modeInfo.vTotal = mode->VTotal;
-		    modeInfo.modeFlags = mode->Flags;
-		    if (mode->type & M_T_PREFERRED)
-			modeInfo.origin = RRModeOriginPreferred;
-		    else if (mode->type & M_T_DRIVER)
-			modeInfo.origin = RRModeOriginDetailed;
-		    else if (mode->type & M_T_USERDEF)
-			modeInfo.origin = RRModeOriginConfig;
-		    else if (mode->type & M_T_DEFAULT)
-			modeInfo.origin = RRModeOriginVESA;
-		    else
-			modeInfo.origin = RRModeOriginOther;
-
-		    rrmode = RRModeGet (pScreen, &modeInfo, mode->name);
-		    rrmode->devPrivate = mode;
-		    if (rrmode)
-			rrmodes[nmode++] = rrmode;
+		    for (mode = modes; mode; mode = mode->next)
+		    {
+			if ((p != 0) == ((mode->type & M_T_PREFERRED) != 0))
+			{
+			    modeInfo.nameLength = strlen (mode->name);
+			    modeInfo.mmWidth = mon->widthmm;
+			    modeInfo.mmHeight = mon->heightmm;
+	
+			    modeInfo.width = mode->HDisplay;
+			    modeInfo.dotClock = mode->Clock * 1000;
+			    modeInfo.hSyncStart = mode->HSyncStart;
+			    modeInfo.hSyncEnd = mode->HSyncEnd;
+			    modeInfo.hTotal = mode->HTotal;
+			    modeInfo.hSkew = mode->HSkew;
+	
+			    modeInfo.height = mode->VDisplay;
+			    modeInfo.vSyncStart = mode->VSyncStart;
+			    modeInfo.vSyncEnd = mode->VSyncEnd;
+			    modeInfo.vTotal = mode->VTotal;
+			    modeInfo.modeFlags = mode->Flags;
+	
+			    rrmode = RRModeGet (pScreen, &modeInfo, mode->name);
+			    rrmode->devPrivate = mode;
+			    if (rrmode)
+			    {
+				rrmodes[nmode++] = rrmode;
+				npreferred += p;
+			    }
+			}
+		    }
 		}
 	    }
 	}
 	
-    	if (!RROutputSetModes (randrp->outputs[i], rrmodes, nmode))
+    	if (!RROutputSetModes (randrp->outputs[i], rrmodes, nmode, npreferred))
 	{
     	    xfree (rrmodes);
 	    return FALSE;
diff-tree 103b4edce7859ddf58f3e1fadeb427a5e85c7acd (from 3e6f81f70f65a5ba6b5c3a4e0eeaf67776a5f54d)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Oct 4 15:00:19 2006 -0700

    Move the save, restore, and DPMS per-output settings to per-output files.

diff --git a/src/Makefile.am b/src/Makefile.am
index 7af2dd7..cab6fe9 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -53,6 +53,7 @@ i810_drv_la_SOURCES = \
          i830_bios.c \
          i830_bios.h \
          i830_common.h \
+	 i830_crt.c \
          i830_cursor.c \
 	 i830_debug.c \
 	 i830_debug.h \
@@ -65,6 +66,7 @@ i810_drv_la_SOURCES = \
          i830_gtf.c \
          i830_i2c.c \
          i830_io.c \
+	 i830_lvds.c \
          i830_memory.c \
          i830_modes.c \
          i830_video.c \
diff --git a/src/i830.h b/src/i830.h
index 7def141..f92704b 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -69,6 +69,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "i830_dri.h"
 #endif
 
+typedef struct _I830OutputRec I830OutputRec, *I830OutputPtr;
+
 #include "common.h"
 #include "i830_sdvo.h"
 #include "i2c_vid.h"
@@ -222,6 +224,23 @@ struct _I830OutputRec {
    int type;
 /*   int pipe;
    int flags;*/
+
+   /**
+    * Turns the output on/off, or sets intermediate power levels if available.
+    * Unsupported intermediate modes drop to the lower power setting.
+    */
+   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);
+
    xf86MonPtr MonInfo;
    I2CBusPtr pI2CBus;
    I2CBusPtr pDDCBus;
@@ -613,10 +632,23 @@ extern Bool I830FixOffset(ScrnInfoPtr pS
 extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg,
 			char *name);
 
+/* i830_crt.c */
+void I830CRTDPMS(ScrnInfoPtr pScrn, I830OutputPtr output, int mode);
+void I830CRTSave(ScrnInfoPtr pScrn, I830OutputPtr output);
+void I830CRTRestore(ScrnInfoPtr pScrn, I830OutputPtr output);
+
 /* i830_dvo.c */
+void I830DVODPMS(ScrnInfoPtr pScrn, I830OutputPtr output, int mode);
+void I830DVOSave(ScrnInfoPtr pScrn, I830OutputPtr output);
+void I830DVORestore(ScrnInfoPtr pScrn, I830OutputPtr output);
 Bool I830I2CDetectDVOControllers(ScrnInfoPtr pScrn, I2CBusPtr pI2CBus,
 				 struct _I830DVODriver **retdrv);
 
+/* i830_lvds.c */
+void I830LVDSDPMS(ScrnInfoPtr pScrn, I830OutputPtr output, int mode);
+void I830LVDSSave(ScrnInfoPtr pScrn, I830OutputPtr output);
+void I830LVDSRestore(ScrnInfoPtr pScrn, I830OutputPtr output);
+
 /* i830_memory.c */
 Bool I830BindAGPMemory(ScrnInfoPtr pScrn);
 Bool I830UnbindAGPMemory(ScrnInfoPtr pScrn);
diff --git a/src/i830_crt.c b/src/i830_crt.c
new file mode 100644
index 0000000..1a0dd0b
--- /dev/null
+++ b/src/i830_crt.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "i830.h"
+
+void
+I830CRTDPMS(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD32 temp;
+
+    temp = INREG(ADPA);
+    temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
+
+    switch(mode) {
+    case DPMSModeOn:
+	break;
+    case DPMSModeStandby:
+	temp |= ADPA_HSYNC_CNTL_DISABLE;
+	break;
+    case DPMSModeSuspend:
+	temp |= ADPA_VSYNC_CNTL_DISABLE;
+	break;
+    case DPMSModeOff:
+	temp |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE;
+	break;
+    }
+
+    OUTREG(ADPA, temp);
+}
+
+void
+I830CRTSave(ScrnInfoPtr pScrn, I830OutputPtr output)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    pI830->saveADPA = INREG(ADPA);
+}
+
+void
+I830CRTRestore(ScrnInfoPtr pScrn, I830OutputPtr output)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    OUTREG(ADPA, pI830->saveADPA);
+}
diff --git a/src/i830_display.c b/src/i830_display.c
index 2b53128..5a0fb9d 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -864,10 +864,10 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
     }
 
     for (i = 0; i < pI830->num_outputs; i++) {
-	struct _I830OutputRec *output = &pI830->output[i];
+	I830OutputPtr output = &pI830->output[i];
 
-	if (output->sdvo_drv)
-	    I830SDVOPreSetMode(output->sdvo_drv, pMode);
+	if (pI830->output[i].sdvo_drv != NULL)
+	    pI830->output[i].dpms(pScrn, &pI830->output[i], DPMSModeOff);
 
 	if (output->i2c_drv != NULL)
 	    output->i2c_drv->vid_rec->Mode(output->i2c_drv->dev_priv,
diff --git a/src/i830_driver.c b/src/i830_driver.c
index d46fc1b..93c7fc4 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -909,6 +909,9 @@ I830SetupOutputBusses(ScrnInfoPtr pScrn)
 
    /* everyone has at least a single analog output */
    pI830->output[i].type = I830_OUTPUT_ANALOG;
+   pI830->output[i].dpms = I830CRTDPMS;
+   pI830->output[i].save = I830CRTSave;
+   pI830->output[i].restore = I830CRTRestore;
 
    /* setup the DDC bus for the analog output */
    I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOA, "CRTDDC_A");
@@ -917,6 +920,9 @@ I830SetupOutputBusses(ScrnInfoPtr pScrn)
    if (IS_MOBILE(pI830) && !IS_I830(pI830)) {
       /* Set up integrated LVDS */
       pI830->output[i].type = I830_OUTPUT_LVDS;
+      pI830->output[i].dpms = I830LVDSDPMS;
+      pI830->output[i].save = I830LVDSSave;
+      pI830->output[i].restore = I830LVDSRestore;
       I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOC, "LVDSDDC_C");
       i++;
    }
@@ -924,18 +930,27 @@ I830SetupOutputBusses(ScrnInfoPtr pScrn)
    if (IS_I9XX(pI830)) {
       /* Set up SDVOB */
       pI830->output[i].type = I830_OUTPUT_SDVO;
+      pI830->output[i].dpms = i830SDVODPMS;
+      pI830->output[i].save = i830SDVOSave;
+      pI830->output[i].restore = i830SDVORestore;
       I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "SDVOCTRL_E");
       I830SDVOInit(pScrn, i, SDVOB);
       i++;
 
       /* Set up SDVOC */
       pI830->output[i].type = I830_OUTPUT_SDVO;
+      pI830->output[i].dpms = i830SDVODPMS;
+      pI830->output[i].save = i830SDVOSave;
+      pI830->output[i].restore = i830SDVORestore;
       pI830->output[i].pI2CBus = pI830->output[i-1].pI2CBus;
       I830SDVOInit(pScrn, i, SDVOC);
       i++;
    } else {
       /* set up DVO */
       pI830->output[i].type = I830_OUTPUT_DVO;
+      pI830->output[i].dpms = I830DVODPMS;
+      pI830->output[i].save = I830DVOSave;
+      pI830->output[i].restore = I830DVORestore;
       I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOD, "DVODDC_D");
       I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "DVOI2C_E");
 
@@ -2600,31 +2615,6 @@ SaveHWState(ScrnInfoPtr pScrn)
    pI830->saveVCLK_POST_DIV = INREG(VCLK_POST_DIV);
    pI830->saveVGACNTRL = INREG(VGACNTRL);
 
-   pI830->saveADPA = INREG(ADPA);
-
-   pI830->savePFIT_CONTROL = INREG(PFIT_CONTROL);
-   pI830->savePP_ON = INREG(LVDSPP_ON);
-   pI830->savePP_OFF = INREG(LVDSPP_OFF);
-   pI830->saveLVDS = INREG(LVDS);
-   pI830->savePP_CONTROL = INREG(PP_CONTROL);
-   pI830->savePP_CYCLE = INREG(PP_CYCLE);
-   pI830->saveBLC_PWM_CTL = INREG(BLC_PWM_CTL);
-   pI830->backlight_duty_cycle = (pI830->saveBLC_PWM_CTL & 
-				  BACKLIGHT_DUTY_CYCLE_MASK);
-   /*
-    * If the light is off at server startup, just make it full brightness
-    */
-   if (!pI830->backlight_duty_cycle)
-      pI830->backlight_duty_cycle = ((pI830->saveBLC_PWM_CTL &
-				      BACKLIGHT_MODULATION_FREQ_MASK) >>
-				     BACKLIGHT_MODULATION_FREQ_SHIFT);
-
-   if (!IS_I9XX(pI830)) {
-      pI830->saveDVOA = INREG(DVOA);
-      pI830->saveDVOB = INREG(DVOB);
-      pI830->saveDVOC = INREG(DVOC);
-   }
-
    for(i = 0; i < 7; i++) {
       pI830->saveSWF[i] = INREG(SWF0 + (i << 2));
       pI830->saveSWF[i+7] = INREG(SWF00 + (i << 2));
@@ -2634,17 +2624,8 @@ SaveHWState(ScrnInfoPtr pScrn)
    pI830->saveSWF[16] = INREG(SWF32);
 
    for (i = 0; i < pI830->num_outputs; i++) {
-      if (pI830->output[i].type == I830_OUTPUT_DVO &&
-	  pI830->output[i].i2c_drv != NULL)
-      {
-	 pI830->output[i].i2c_drv->vid_rec->SaveRegs(
-	    pI830->output[i].i2c_drv->dev_priv);
-      }
-      if (pI830->output[i].type == I830_OUTPUT_SDVO &&
-	  pI830->output[i].sdvo_drv != NULL)
-      {
-	 i830SDVOSave(pScrn, i);
-      }
+      if (pI830->output[i].save != NULL)
+	 pI830->output[i].save(pScrn, &pI830->output[i]);
    }
 
    vgaHWUnlock(hwp);
@@ -2670,6 +2651,11 @@ RestoreHWState(ScrnInfoPtr pScrn)
    vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS);
    vgaHWLock(hwp);
 
+   /* Disable outputs */
+   for (i = 0; i < pI830->num_outputs; i++) {
+      pI830->output[i].dpms(pScrn, &pI830->output[i], DPMSModeOff);
+   }
+
    /* First, disable display planes */
    temp = INREG(DSPACNTR);
    OUTREG(DSPACNTR, temp & ~DISPLAY_PLANE_ENABLE);
@@ -2682,18 +2668,7 @@ RestoreHWState(ScrnInfoPtr pScrn)
    temp = INREG(PIPEBCONF);
    OUTREG(PIPEBCONF, temp & ~PIPEBCONF_ENABLE);
 
-   /* XXX: Wait for a vblank */
-   sleep(1);
-
-   i830SetLVDSPanelPower(pScrn, FALSE);
-
-   for (i = 0; i < pI830->num_outputs; i++) {
-      if (pI830->output[i].type == I830_OUTPUT_SDVO &&
-	  pI830->output[i].sdvo_drv != NULL)
-      {
-	 i830SDVOPreRestore(pScrn, i);
-      }
-   }
+   i830WaitForVblank(pScrn);
 
    OUTREG(FPA0, pI830->saveFPA0);
    OUTREG(FPA1, pI830->saveFPA1);
@@ -2738,12 +2713,6 @@ RestoreHWState(ScrnInfoPtr pScrn)
       OUTREG(DSPBSURF, pI830->saveDSPBBASE);
    }
 
-   OUTREG(BLC_PWM_CTL, pI830->saveBLC_PWM_CTL);
-   OUTREG(LVDSPP_ON, pI830->savePP_ON);
-   OUTREG(LVDSPP_OFF, pI830->savePP_OFF);
-   OUTREG(PP_CYCLE, pI830->savePP_CYCLE);
-   OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL);
-   
    OUTREG(VCLK_DIVISOR_VGA0, pI830->saveVCLK_DIVISOR_VGA0);
    OUTREG(VCLK_DIVISOR_VGA1, pI830->saveVCLK_DIVISOR_VGA1);
    OUTREG(VCLK_POST_DIV, pI830->saveVCLK_POST_DIV);
@@ -2755,30 +2724,10 @@ RestoreHWState(ScrnInfoPtr pScrn)
    OUTREG(DSPACNTR, pI830->saveDSPACNTR);
    OUTREG(DSPBCNTR, pI830->saveDSPBCNTR);
 
-   OUTREG(ADPA, pI830->saveADPA);
-   OUTREG(LVDS, pI830->saveLVDS);
-   if (!IS_I9XX(pI830)) {
-      OUTREG(DVOA, pI830->saveDVOA);
-      OUTREG(DVOB, pI830->saveDVOB);
-      OUTREG(DVOC, pI830->saveDVOC);
-   }
-
    for (i = 0; i < pI830->num_outputs; i++) {
-      if (pI830->output[i].type == I830_OUTPUT_DVO &&
-	  pI830->output[i].i2c_drv != NULL)
-      {
-	 pI830->output[i].i2c_drv->vid_rec->RestoreRegs(
-	    pI830->output[i].i2c_drv->dev_priv);
-      }
-      if (pI830->output[i].type == I830_OUTPUT_SDVO &&
-	  pI830->output[i].sdvo_drv != NULL)
-      {
-	 i830SDVOPostRestore(pScrn, i);
-      }
+      pI830->output[i].restore(pScrn, &pI830->output[i]);
    }
 
-   OUTREG(PP_CONTROL, pI830->savePP_CONTROL);
-
    for(i = 0; i < 7; i++) {
 	   OUTREG(SWF0 + (i << 2), pI830->saveSWF[i]);
 	   OUTREG(SWF00 + (i << 2), pI830->saveSWF[i+7]);
@@ -4204,39 +4153,6 @@ I830SaveScreen(ScreenPtr pScreen, int mo
    return TRUE;
 }
 
-static void
-I830DPMSCRT(ScrnInfoPtr pScrn, int mode)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   CARD32 temp;
-   
-   temp = INREG(ADPA);
-   temp &= ~(ADPA_HSYNC_CNTL_DISABLE|ADPA_VSYNC_CNTL_DISABLE);
-   switch(mode) {
-   case DPMSModeOn:
-      break;
-   case DPMSModeStandby:
-      temp |= ADPA_HSYNC_CNTL_DISABLE;
-      break;
-   case DPMSModeSuspend:
-      temp |= ADPA_VSYNC_CNTL_DISABLE;
-      break;
-   case DPMSModeOff:
-      temp |= ADPA_HSYNC_CNTL_DISABLE|ADPA_VSYNC_CNTL_DISABLE;
-      break;
-   }
-   OUTREG(ADPA, temp);
-}
-
-static void
-I830DPMSLVDS(ScrnInfoPtr pScrn, int mode)
-{
-   if (mode == DPMSModeOn)
-      i830SetLVDSPanelPower(pScrn, TRUE);
-   else
-      i830SetLVDSPanelPower(pScrn, FALSE);
-}
-
 /* Use the VBE version when available. */
 static void
 I830DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
@@ -4246,6 +4162,10 @@ I830DisplayPowerManagementSet(ScrnInfoPt
    int i;
    CARD32 temp, ctrl, base;
 
+   for (i = 0; i < pI830->num_outputs; i++) {
+      pI830->output[i].dpms(pScrn, &pI830->output[i], PowerManagementMode);
+   }
+
    for (i = 0; i < pI830->availablePipes; i++) {
       if (i == 0) {
          ctrl = DSPACNTR;
@@ -4267,22 +4187,6 @@ I830DisplayPowerManagementSet(ScrnInfoPt
       }
    }
 
-   if (pI830->operatingDevices & (PIPE_CRT_ACTIVE | (PIPE_CRT_ACTIVE<<8))) {
-      I830DPMSCRT(pScrn, PowerManagementMode);
-   }
-
-   if (pI830->operatingDevices & (PIPE_LCD_ACTIVE | (PIPE_LCD_ACTIVE<<8))) {
-      I830DPMSLVDS(pScrn, PowerManagementMode);
-   }
-
-   if (pI830->operatingDevices & (PIPE_DFP_ACTIVE | (PIPE_DFP_ACTIVE<<8))) {
-      /* TBD */
-   }
-
-   if (pI830->operatingDevices & (PIPE_DFP2_ACTIVE | (PIPE_DFP2_ACTIVE<<8))) {
-      /* TBD */
-   }
-
    if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn) {
       if (PowerManagementMode == DPMSModeOn)
          pI830->CursorInfoRec->ShowCursor(pScrn);
diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index 242e3dd..f64a8e8 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -54,6 +54,51 @@ struct _I830DVODriver i830_dvo_drivers[]
 
 #define I830_NUM_DVO_DRIVERS (sizeof(i830_dvo_drivers)/sizeof(struct _I830DVODriver))
 
+void
+I830DVODPMS(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
+{
+    if (output->i2c_drv == NULL)
+	return;
+
+    if (mode == DPMSModeOn)
+	output->i2c_drv->vid_rec->Power(output->i2c_drv->dev_priv, TRUE);
+    else
+	output->i2c_drv->vid_rec->Power(output->i2c_drv->dev_priv, FALSE);
+}
+
+void
+I830DVOSave(ScrnInfoPtr pScrn, I830OutputPtr output)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    if (output->i2c_drv == NULL)
+	return;
+
+    /* Each output should probably just save the registers it touches, but for
+     * now, use more overkill.
+     */
+    pI830->saveDVOA = INREG(DVOA);
+    pI830->saveDVOB = INREG(DVOB);
+    pI830->saveDVOC = INREG(DVOC);
+
+    output->i2c_drv->vid_rec->SaveRegs(output->i2c_drv->dev_priv);
+}
+
+void
+I830DVORestore(ScrnInfoPtr pScrn, I830OutputPtr output)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    if (output->i2c_drv == NULL)
+	return;
+
+    OUTREG(DVOA, pI830->saveDVOA);
+    OUTREG(DVOB, pI830->saveDVOB);
+    OUTREG(DVOC, pI830->saveDVOC);
+
+    output->i2c_drv->vid_rec->RestoreRegs(output->i2c_drv->dev_priv);
+}
+
 Bool
 I830I2CDetectDVOControllers(ScrnInfoPtr pScrn, I2CBusPtr pI2CBus,
 			    struct _I830DVODriver **retdrv)
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
new file mode 100644
index 0000000..fcd8fee
--- /dev/null
+++ b/src/i830_lvds.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "i830.h"
+
+void
+I830LVDSDPMS(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
+{
+    if (mode == DPMSModeOn)
+	i830SetLVDSPanelPower(pScrn, TRUE);
+    else
+	i830SetLVDSPanelPower(pScrn, FALSE);
+}
+
+void
+I830LVDSSave(ScrnInfoPtr pScrn, I830OutputPtr output)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    pI830->savePFIT_CONTROL = INREG(PFIT_CONTROL);
+    pI830->savePP_ON = INREG(LVDSPP_ON);
+    pI830->savePP_OFF = INREG(LVDSPP_OFF);
+    pI830->saveLVDS = INREG(LVDS);
+    pI830->savePP_CONTROL = INREG(PP_CONTROL);
+    pI830->savePP_CYCLE = INREG(PP_CYCLE);
+    pI830->saveBLC_PWM_CTL = INREG(BLC_PWM_CTL);
+    pI830->backlight_duty_cycle = (pI830->saveBLC_PWM_CTL &
+				   BACKLIGHT_DUTY_CYCLE_MASK);
+
+    /*
+     * If the light is off at server startup, just make it full brightness
+     */
+    if (pI830->backlight_duty_cycle == 0) {
+	pI830->backlight_duty_cycle =
+	    (pI830->saveBLC_PWM_CTL & BACKLIGHT_MODULATION_FREQ_MASK) >>
+	    BACKLIGHT_MODULATION_FREQ_SHIFT;
+    }
+}
+
+void
+I830LVDSRestore(ScrnInfoPtr pScrn, I830OutputPtr output)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    OUTREG(BLC_PWM_CTL, pI830->saveBLC_PWM_CTL);
+    OUTREG(LVDSPP_ON, pI830->savePP_ON);
+    OUTREG(LVDSPP_OFF, pI830->savePP_OFF);
+    OUTREG(PP_CYCLE, pI830->savePP_CYCLE);
+    OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL);
+    OUTREG(LVDS, pI830->saveLVDS);
+    OUTREG(PP_CONTROL, pI830->savePP_CONTROL);
+}
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index c762541..a07e7c9 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -640,10 +640,13 @@ I830SDVOPostSetMode(I830SDVOPtr s, Displ
 }
 
 void
-i830SDVOSave(ScrnInfoPtr pScrn, int output_index)
+i830SDVOSave(ScrnInfoPtr pScrn, I830OutputPtr output)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    I830SDVOPtr sdvo = pI830->output[output_index].sdvo_drv;
+    I830SDVOPtr sdvo = output->sdvo_drv;
+
+    if (sdvo == NULL)
+	return;
 
     sdvo->save_sdvo_mult = I830SDVOGetClockRateMult(sdvo);
     I830SDVOGetActiveOutputs(sdvo, &sdvo->save_sdvo_active_1,
@@ -677,19 +680,28 @@ i830SDVOSave(ScrnInfoPtr pScrn, int outp
 }
 
 void
-i830SDVOPreRestore(ScrnInfoPtr pScrn, int output_index)
+i830SDVODPMS(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    I830SDVOPtr sdvo = pI830->output[output_index].sdvo_drv;
+    I830SDVOPtr sdvo = output->sdvo_drv;
+
+    if (sdvo == NULL)
+	return;
 
-    I830SDVOSetActiveOutputs(sdvo, FALSE, FALSE);
+    if (mode != DPMSModeOn)
+	I830SDVOSetActiveOutputs(sdvo, FALSE, FALSE);
+    else
+	I830SDVOSetActiveOutputs(sdvo, TRUE, FALSE);
 }
 
 void
-i830SDVOPostRestore(ScrnInfoPtr pScrn, int output_index)
+i830SDVORestore(ScrnInfoPtr pScrn, I830OutputPtr output)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    I830SDVOPtr sdvo = pI830->output[output_index].sdvo_drv;
+    I830SDVOPtr sdvo = output->sdvo_drv;
+
+    if (sdvo == NULL)
+	return;
 
     if (sdvo->caps.caps & 0x1) {
        I830SDVOSetTargetInput(sdvo, FALSE, FALSE);
diff --git a/src/i830_sdvo.h b/src/i830_sdvo.h
index 52621e0..73ecf32 100644
--- a/src/i830_sdvo.h
+++ b/src/i830_sdvo.h
@@ -56,13 +56,13 @@ typedef struct _i830_sdvo_dtd {
 } __attribute__((packed)) i830_sdvo_dtd;
 
 void
-i830SDVOSave(ScrnInfoPtr pScrn, int output_index);
+i830SDVODPMS(ScrnInfoPtr pScrn, I830OutputPtr output, int mode);
 
 void
-i830SDVOPreRestore(ScrnInfoPtr pScrn, int output_index);
+i830SDVOSave(ScrnInfoPtr pScrn, I830OutputPtr output);
 
 void
-i830SDVOPostRestore(ScrnInfoPtr pScrn, int output_index);
+i830SDVORestore(ScrnInfoPtr pScrn, I830OutputPtr output);
 
 Bool
 I830DetectSDVODisplays(ScrnInfoPtr pScrn, int output_index);
diff-tree 16988b27258acfe3d56fc2415aa9ade1ae8d03a9 (from parents)
Merge: cc4148e25dc226cb1365e090db21f01b77cb3cbe 5a060002487e16c53dc96e32af72cd1bfcf6a227
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Wed Oct 4 18:44:43 2006 -0700

    Merge branch 'modesetting-guitar' into modesetting

diff-tree 5a060002487e16c53dc96e32af72cd1bfcf6a227 (from 33629ed304b64e45d5640397bd1807c5a98907d1)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Wed Oct 4 18:43:07 2006 -0700

    Add mode origins for randr

diff --git a/src/i830_modes.c b/src/i830_modes.c
index da1ccde..ac7c4c5 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -290,7 +290,10 @@ i830GetDDCModes(ScrnInfoPtr pScrn, xf86M
 	    new->Clock      = d_timings->clock / 1000;
 	    new->Flags      = (d_timings->interlaced ? V_INTERLACE : 0);
 	    new->status     = MODE_OK;
-	    new->type       = M_T_DEFAULT;
+	    if (PREFERRED_TIMING_MODE(ddc->features.msc))
+		new->type   = M_T_PREFERRED;
+	    else
+		new->type   = M_T_DRIVER;
 
 	    i830xf86SetModeDefaultName(new);
 
@@ -419,7 +422,7 @@ i830FPNativeMode(ScrnInfoPtr pScrn)
    new->VTotal     = new->VSyncEnd + 1;
    new->Clock      = pI830->panel_fixed_clock;
 
-   new->type       = M_T_USERDEF;
+   new->type       = M_T_PREFERRED;
 
    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 	      "No valid mode specified, force to native mode\n");
@@ -475,7 +478,7 @@ i830GetLVDSModes(ScrnInfoPtr pScrn, char
       }
 
       new = i830GetGTF(width, height, 60.0, FALSE, FALSE);
-      new->type |= M_T_USERDEF;
+      new->type |= M_T_DEFAULT;
 
       new->next       = NULL;
       new->prev       = last;
@@ -510,10 +513,7 @@ i830GetLVDSModes(ScrnInfoPtr pScrn, char
 	 }
 	 if (!tmp) {
 	    new = i830GetGTF(p->HDisplay, p->VDisplay, 60.0, FALSE, FALSE);
-	    if (ppModeName[i] == NULL)
-		new->type |= M_T_USERDEF;
-	    else
-		new->type |= M_T_DEFAULT;
+	    new->type |= M_T_DEFAULT;
 
 	    I830xf86SortModes(new, &first, &last);
 
diff --git a/src/i830_randr.c b/src/i830_randr.c
index 7abfb3b..37bd6a1 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -542,7 +542,7 @@ I830RandRCrtcSet (ScreenPtr	pScreen,
 		  int		y,
 		  Rotation	rotation,
 		  int		numOutputs,
-		  RROutputPtr	*outputs)
+		  RROutputConfigPtr	outputs)
 {
     XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
@@ -603,7 +603,6 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
     int			nclone;
     RRCrtcPtr		crtcs[MAX_DISPLAY_PIPES];
     int			ncrtc;
-    RRModePtr		*modes;
     int			nmode;
     struct _I830OutputRec   *output;
     int			i;
@@ -617,6 +616,8 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
     DisplayModePtr	modes, mode;
     xRRModeInfo		modeInfo;
     RRModePtr		rrmode, *rrmodes;
+    CARD32		possibleOptions = 0;
+    CARD32		currentOptions = 0;
     
     if (randrp->virtualX == -1 || randrp->virtualY == -1) 
     {
@@ -655,6 +656,10 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
 	    clone_types = (1 << I830_OUTPUT_LVDS);
 	    pipe_type = PIPE_LFP;
 	    subpixel = SubPixelHorizontalRGB;
+	    possibleOptions = (RROutputOptionScaleNone|
+			       RROutputOptionScaleMaxAspect |
+			       RROutputOptionScaleMax);
+	    currentOptions = RROutputOptionScaleMax;
 	    break;
 	case I830_OUTPUT_TVOUT:
 	    crtc_types = ((1 << 0) |
@@ -692,11 +697,14 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
 
 	RROutputSetCrtc (randrp->outputs[i], crtc);
     
+	RROutputSetPossibleOptions (randrp->outputs[i], possibleOptions);
+	RROutputSetCurrentOptions (randrp->outputs[i], currentOptions);
         nmode = 0;
 	rrmodes = NULL;
 	if (pipe >= 0) 
 	{
-	    modes = pI830->pipeMon[pipe]->Modes;
+	    MonPtr  mon = pI830->pipeMon[pipe];
+	    modes = mon->Modes;
 	
 	    for (mode = modes; mode; mode = mode->next)
 		nmode++;
@@ -725,6 +733,16 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
 		    modeInfo.vSyncEnd = mode->VSyncEnd;
 		    modeInfo.vTotal = mode->VTotal;
 		    modeInfo.modeFlags = mode->Flags;
+		    if (mode->type & M_T_PREFERRED)
+			modeInfo.origin = RRModeOriginPreferred;
+		    else if (mode->type & M_T_DRIVER)
+			modeInfo.origin = RRModeOriginDetailed;
+		    else if (mode->type & M_T_USERDEF)
+			modeInfo.origin = RRModeOriginConfig;
+		    else if (mode->type & M_T_DEFAULT)
+			modeInfo.origin = RRModeOriginVESA;
+		    else
+			modeInfo.origin = RRModeOriginOther;
 
 		    rrmode = RRModeGet (pScreen, &modeInfo, mode->name);
 		    rrmode->devPrivate = mode;
@@ -776,8 +794,6 @@ static Bool
 I830RandRGetInfo12 (ScreenPtr pScreen, Rotation *rotations)
 {
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
-    I830Ptr		pI830 = I830PTR(pScrn);
-    int			found_crt;
 
     I830ValidateXF86ModeList(pScrn, FALSE);
     return I830RandRSetInfo12 (pScreen);
diff-tree cc4148e25dc226cb1365e090db21f01b77cb3cbe (from parents)
Merge: 1bc1cedbcdf6ea4d2a3e8b07b553ac50b3c126f4 3e6f81f70f65a5ba6b5c3a4e0eeaf67776a5f54d
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Tue Oct 3 22:00:41 2006 -0700

    Merge branch 'modesetting-origin' into modesetting

diff-tree 1bc1cedbcdf6ea4d2a3e8b07b553ac50b3c126f4 (from 6ea16bf6b06c8b3aed4d2c98679ab28304d1b56c)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Tue Oct 3 22:00:14 2006 -0700

    Enable XV_PORT attribute even when not in Clone mode.
    
    As Clone mode is now something that can change after server startup, always
    enable the XV_PORT attribute as we cannot change the list of reported
    attributes.

diff --git a/src/i830_video.c b/src/i830_video.c
index 83c032b..6a18f93 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -689,8 +689,7 @@ I830SetupImageVideoOverlay(ScreenPtr pSc
 
    adapt->pPortPrivates[0].ptr = (pointer) (pPriv);
    adapt->nAttributes = NUM_ATTRIBUTES;
-   if (pI830->Clone)
-      adapt->nAttributes += CLONE_ATTRIBUTES;
+   adapt->nAttributes += CLONE_ATTRIBUTES;
    if (IS_I9XX(pI830))
       adapt->nAttributes += GAMMA_ATTRIBUTES; /* has gamma */
    adapt->pAttributes = xnfalloc(sizeof(XF86AttributeRec) * adapt->nAttributes);
@@ -698,10 +697,8 @@ I830SetupImageVideoOverlay(ScreenPtr pSc
    att = adapt->pAttributes;
    memcpy((char *)att, (char*)Attributes, sizeof(XF86AttributeRec)* NUM_ATTRIBUTES);
    att+=NUM_ATTRIBUTES;
-   if (pI830->Clone) {
-      memcpy((char*)att, (char*)CloneAttributes, sizeof(XF86AttributeRec) * CLONE_ATTRIBUTES);
-      att+=CLONE_ATTRIBUTES;
-   }
+   memcpy((char*)att, (char*)CloneAttributes, sizeof(XF86AttributeRec) * CLONE_ATTRIBUTES);
+   att+=CLONE_ATTRIBUTES;
    if (IS_I9XX(pI830)) {
       memcpy((char*)att, (char*)GammaAttributes, sizeof(XF86AttributeRec) * GAMMA_ATTRIBUTES);
       att+=GAMMA_ATTRIBUTES;
@@ -764,8 +761,7 @@ I830SetupImageVideoOverlay(ScreenPtr pSc
    xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER");
 
    /* Allow the pipe to be switched from pipe A to B when in clone mode */
-   if (pI830->Clone)
-     xvPipe = MAKE_ATOM("XV_PIPE");
+   xvPipe = MAKE_ATOM("XV_PIPE");
    
    if (IS_I9XX(pI830)) {
      xvGamma0 = MAKE_ATOM("XV_GAMMA0");
@@ -1073,7 +1069,7 @@ I830GetPortAttribute(ScrnInfoPtr pScrn,
       *value = pPriv->contrast;
    } else if (attribute == xvSaturation) {
       *value = pPriv->saturation;
-   } else if (pI830->Clone && attribute == xvPipe) {
+   } else if (attribute == xvPipe) {
       *value = pPriv->pipe;
    } else if (attribute == xvGamma0 && (IS_I9XX(pI830))) {
       *value = pPriv->gamma0;
diff-tree 33629ed304b64e45d5640397bd1807c5a98907d1 (from 6ea16bf6b06c8b3aed4d2c98679ab28304d1b56c)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Tue Oct 3 09:39:22 2006 -0700

    Always register list of modes for outputs, even when disabled.

diff --git a/src/i830_randr.c b/src/i830_randr.c
index d973173..7abfb3b 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -614,6 +614,9 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
     int			pipe_type;
     int			pipe;
     int			subpixel;
+    DisplayModePtr	modes, mode;
+    xRRModeInfo		modeInfo;
+    RRModePtr		rrmode, *rrmodes;
     
     if (randrp->virtualX == -1 || randrp->virtualY == -1) 
     {
@@ -689,24 +692,22 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
 
 	RROutputSetCrtc (randrp->outputs[i], crtc);
     
-	if (pipe >= 0)
+        nmode = 0;
+	rrmodes = NULL;
+	if (pipe >= 0) 
 	{
-	    MonPtr	    mon = pI830->pipeMon[pipe];
-	    DisplayModePtr  mode;
-	    xRRModeInfo	    modeInfo;
-	    RRModePtr	    rrmode;
-	    
-	    nmode = 0;
-	    for (mode = mon->Modes; mode; mode = mode->next)
+	    modes = pI830->pipeMon[pipe]->Modes;
+	
+	    for (mode = modes; mode; mode = mode->next)
 		nmode++;
-	    
+
 	    if (nmode)
 	    {
-		modes = xalloc (nmode * sizeof (RRModePtr));
-		if (!modes)
+		rrmodes = xalloc (nmode * sizeof (RRModePtr));
+		if (!rrmodes)
 		    return FALSE;
 		nmode = 0;
-		for (mode = mon->Modes; mode; mode = mode->next)
+		for (mode = modes; mode; mode = mode->next)
 		{
 		    modeInfo.nameLength = strlen (mode->name);
 		    modeInfo.mmWidth = mon->widthmm;
@@ -728,17 +729,19 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
 		    rrmode = RRModeGet (pScreen, &modeInfo, mode->name);
 		    rrmode->devPrivate = mode;
 		    if (rrmode)
-			modes[nmode++] = rrmode;
-		}
-		if (!RROutputSetModes (randrp->outputs[i], modes, nmode))
-		{
-		    xfree (modes);
-		    return FALSE;
+			rrmodes[nmode++] = rrmode;
 		}
-
-		xfree (modes);
 	    }
 	}
+	
+    	if (!RROutputSetModes (randrp->outputs[i], rrmodes, nmode))
+	{
+    	    xfree (rrmodes);
+	    return FALSE;
+	}
+	
+	xfree (rrmodes);
+	
 	connection = RR_Disconnected;
 	if (pipe >= 0)
 	    connection = RR_Connected;
diff-tree 3e6f81f70f65a5ba6b5c3a4e0eeaf67776a5f54d (from 6ea16bf6b06c8b3aed4d2c98679ab28304d1b56c)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Oct 2 09:53:57 2006 -0700

    Move cursor base address register setting to a separate function.

diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index 55bbe6a..92239f1 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -79,6 +79,28 @@ static void I830LoadCursorARGB(ScrnInfoP
 static Bool I830UseHWCursorARGB(ScreenPtr pScrn, CursorPtr pCurs);
 #endif
 
+static void
+I830SetPipeCursorBase (ScrnInfoPtr pScrn, int pipe)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    int cursor_base = (pipe == 0 ? CURSOR_A_BASE : CURSOR_B_BASE);
+    I830MemRange *cursor_mem;
+
+    if (pipe >= pI830->availablePipes)
+	FatalError("Bad pipe number for cursor base setting\n");
+
+    if (pI830->CursorIsARGB)
+	cursor_mem = pI830->CursorMemARGB;
+    else
+	cursor_mem = pI830->CursorMem;
+
+    if (pI830->CursorNeedsPhysical) {
+	OUTREG(cursor_base, cursor_mem->Physical);
+    } else {
+	OUTREG(cursor_base, cursor_mem->Start);
+    }
+}
+
 void
 I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe, Bool force)
 {
@@ -93,17 +115,11 @@ I830SetPipeCursor (ScrnInfoPtr pScrn, in
     if (show && (force || !pI830->cursorShown[pipe]))
     {
 	if (IS_MOBILE(pI830) || IS_I9XX(pI830)) {
-	    int	cursor_control, cursor_base;
+	    int	cursor_control;
 	    if (pipe == 0)
-	    {
 		cursor_control = CURSOR_A_CONTROL;
-		cursor_base = CURSOR_A_BASE;
-	    }
 	    else
-	    {
 		cursor_control = CURSOR_B_CONTROL;
-		cursor_base = CURSOR_B_BASE;
-	    }
 	    temp = INREG(cursor_control);
 	    temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
 	    if (pI830->CursorIsARGB) {
@@ -116,17 +132,6 @@ I830SetPipeCursor (ScrnInfoPtr pScrn, in
 	    temp |= (pipe << 28); /* Connect to correct pipe */
 	    /* Need to set mode, then address. */
 	    OUTREG(cursor_control, temp);
-	    if (pI830->CursorNeedsPhysical) {
-		if (pI830->CursorIsARGB)
-		    OUTREG(cursor_base, pI830->CursorMemARGB->Physical);
-		else
-		    OUTREG(cursor_base, pI830->CursorMem->Physical);
-	    } else {
-		if (pI830->CursorIsARGB)
-		    OUTREG(cursor_base, pI830->CursorMemARGB->Start);
-		else
-		    OUTREG(cursor_base, pI830->CursorMem->Start);
-	    }
 	} else {
 	    temp = INREG(CURSOR_CONTROL);
 	    temp &= ~(CURSOR_FORMAT_MASK);
@@ -138,10 +143,6 @@ I830SetPipeCursor (ScrnInfoPtr pScrn, in
 	    } else
 		temp |= CURSOR_FORMAT_3C;
 	    OUTREG(CURSOR_CONTROL, temp);
-	    if (pI830->CursorIsARGB)
-		OUTREG(CURSOR_BASEADDR, pI830->CursorMemARGB->Start);
-	    else
-		OUTREG(CURSOR_BASEADDR, pI830->CursorMem->Start);
 	}
 	pI830->cursorShown[pipe] = TRUE;
     }
@@ -149,33 +150,15 @@ I830SetPipeCursor (ScrnInfoPtr pScrn, in
     {
 	if (IS_MOBILE(pI830) || IS_I9XX(pI830)) 
 	{
-	    int	cursor_control, cursor_base;
+	    int	cursor_control;
 	    if (pipe == 0)
-	    {
 		cursor_control = CURSOR_A_CONTROL;
-		cursor_base = CURSOR_A_BASE;
-	    }
 	    else
-	    {
 		cursor_control = CURSOR_B_CONTROL;
-		cursor_base = CURSOR_B_BASE;
-	    }
 	    temp = INREG(cursor_control);
 	    temp &= ~(CURSOR_MODE|MCURSOR_GAMMA_ENABLE);
 	    temp |= CURSOR_MODE_DISABLE;
 	    OUTREG(cursor_control, temp);
-	    /* This is needed to flush the above change. */
-	    if (pI830->CursorNeedsPhysical) {
-		if (pI830->CursorIsARGB)
-		    OUTREG(cursor_base, pI830->CursorMemARGB->Physical);
-		else
-		    OUTREG(cursor_base, pI830->CursorMem->Physical);
-	    } else {
-		if (pI830->CursorIsARGB)
-		    OUTREG(cursor_base, pI830->CursorMemARGB->Start);
-		else
-		    OUTREG(cursor_base, pI830->CursorMem->Start);
-	    }
 	} else {
 	    temp = INREG(CURSOR_CONTROL);
 	    temp &= ~(CURSOR_ENABLE|CURSOR_GAMMA_ENABLE);
@@ -183,6 +166,9 @@ I830SetPipeCursor (ScrnInfoPtr pScrn, in
 	}
 	pI830->cursorShown[pipe] = FALSE;
     }
+
+    /* Flush cursor changes. */
+    I830SetPipeCursorBase(pScrn, pipe);
 }
 
 void
@@ -199,7 +185,6 @@ I830InitHWCursor(ScrnInfoPtr pScrn)
       for (i = 0; i < MAX_DISPLAY_PIPES; i++)
       {
 	 int   cursor_control = i == 0 ? CURSOR_A_CONTROL : CURSOR_B_CONTROL;
-	 int   cursor_base = i == 0 ? CURSOR_A_BASE : CURSOR_B_BASE;
 	 temp = INREG(cursor_control);
 	 temp &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE |
 		   MCURSOR_MEM_TYPE_LOCAL |
@@ -211,17 +196,7 @@ I830InitHWCursor(ScrnInfoPtr pScrn)
 	    temp |= CURSOR_MODE_64_4C_AX;
 	 /* Need to set control, then address. */
 	 OUTREG(cursor_control, temp);
-	 if (pI830->CursorNeedsPhysical) {
-	    if (pI830->CursorIsARGB)
-	       OUTREG(cursor_base, pI830->CursorMemARGB->Physical);
-	    else
-	       OUTREG(cursor_base, pI830->CursorMem->Physical);
-	 } else {
-	    if (pI830->CursorIsARGB)
-	       OUTREG(cursor_base, pI830->CursorMemARGB->Start);
-	    else
-	       OUTREG(cursor_base, pI830->CursorMem->Start);
-	 }
+	 I830SetPipeCursorBase(pScrn, i);
       }
    } else {
       temp = INREG(CURSOR_CONTROL);
@@ -234,10 +209,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. */
-      if (pI830->CursorIsARGB)
-         OUTREG(CURSOR_BASEADDR, pI830->CursorMemARGB->Start);
-      else
-         OUTREG(CURSOR_BASEADDR, pI830->CursorMem->Start);
+      I830SetPipeCursorBase(pScrn, 0);
       temp = ((I810_CURSOR_X & CURSOR_SIZE_MASK) << CURSOR_SIZE_HSHIFT) |
 	     ((I810_CURSOR_Y & CURSOR_SIZE_MASK) << CURSOR_SIZE_VSHIFT);
       OUTREG(CURSOR_SIZE, temp);
@@ -555,22 +527,6 @@ I830SetCursorPosition(ScrnInfoPtr pScrn,
 	pI830->cursorInRange[pipe] = inrange;
 	
         I830SetPipeCursor (pScrn, pipe, FALSE);
-
-	/* have to upload the base for the new position */
-	if (IS_I9XX(pI830)) {
-	    int base = pipe == 0 ? CURSOR_A_BASE : CURSOR_B_BASE;
-	    if (pI830->CursorNeedsPhysical) {
-	       if (pI830->CursorIsARGB)
-		  OUTREG(base, pI830->CursorMemARGB->Physical);
-	       else
-		  OUTREG(base, pI830->CursorMem->Physical);
-	    } else {
-	       if (pI830->CursorIsARGB)
-		  OUTREG(base, pI830->CursorMemARGB->Start);
-	       else
-		  OUTREG(base, pI830->CursorMem->Start);
-	    }
-	}
     }
 }
 
diff-tree 6ea16bf6b06c8b3aed4d2c98679ab28304d1b56c (from parents)
Merge: fdb6de663579d3b9f31bf9e8a93430b8505ca73f b970166eab95ac024ff481b0f5fd9aaf3644aabf
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Sep 27 16:38:01 2006 -0700

    Merge branch 'master' into modesetting
    
    This reverts most of the mergedfb code.  This will instead be done in device-
    independent RandR code.
    
    Conflicts:
    
    	src/Makefile.am
    	src/i810_driver.c
    	src/i810_reg.h
    	src/i830.h
    	src/i830_cursor.c
    	src/i830_driver.c
    	src/i830_modes.c
    	src/i830_video.c

diff --cc src/Makefile.am
index 72d6276,ce7b40e..7af2dd7
@@@ -31,8 -31,11 +31,12 @@@
  i810_drv_ladir = @moduledir@/drivers
  
  i810_drv_la_SOURCES = \
+          brw_defines.h \
+          brw_structs.h \
+ 	 sf_prog.h \
+          wm_prog.h \
           common.h \
 +	 i2c_vid.h \
           i810_accel.c \
           i810_common.h \
           i810_cursor.c \
@@@ -44,32 -47,33 +48,47 @@@
           i810_reg.h \
           i810_video.c \
           i810_wmark.c \
++	 i830_3d.c \
           i830_accel.c \
 +         i830_bios.c \
 +         i830_bios.h \
           i830_common.h \
           i830_cursor.c \
 +	 i830_debug.c \
 +	 i830_debug.h \
           i830_dga.c \
 +	 i830_display.c \
 +	 i830_display.h \
           i830_driver.c \
 +	 i830_dvo.c \
           i830.h \
 +         i830_gtf.c \
 +         i830_i2c.c \
           i830_io.c \
           i830_memory.c \
           i830_modes.c \
           i830_video.c \
+          i830_video.h \
++	 i830_reg.h \
           i830_rotate.c \
  	 i830_randr.c \
 -	 i830_3d.c \
 -	 i830_reg.h \
 +	 i830_sdvo.c \
 +	 i830_sdvo.h \
 +	 i830_sdvo_regs.h \
 +	 i830_xf86Modes.h \
- 	 i830_xf86Modes.c
++	 i830_xf86Modes.c \
+ 	 i915_3d.c \
+ 	 i915_3d.h \
+ 	 i915_reg.h \
+ 	 i915_video.c
+ 
+ if HAVE_GEN4ASM
+ sf_prog.h: packed_yuv_sf.g4a
+ 	intel-gen4asm -o sf_prog.h packed_yuv_sf.g4a
+ wm_prog.h: packed_yuv_wm.g4a
+ 	intel-gen4asm -o wm_prog.h packed_yuv_wm.g4a
+ endif
+ 
  if DRI
  i810_drv_la_SOURCES += \
           i810_dri.c \
diff --cc src/i810_reg.h
index 3a15a46,4bb5bf1..4fec65f
@@@ -923,11 -837,12 +988,17 @@@
  #define DSPBPOS			0x7118C
  #define DSPBSIZE		0x71190
  
+ #define DSPASURF		0x7019C
+ #define DSPATILEOFF		0x701A4
+ 
+ #define DSPBSURF		0x7119C
+ #define DSPBTILEOFF		0x711A4
+ 
 +#define VGACNTRL		0x71400
 +# define VGA_DISP_DISABLE			(1 << 31)
 +# define VGA_2X_MODE				(1 << 30)
 +# define VGA_PIPE_B_SELECT			(1 << 29)
 +
  /* Various masks for reserved bits, etc. */
  #define I830_FWATER1_MASK        (~((1<<11)|(1<<10)|(1<<9)|      \
          (1<<8)|(1<<26)|(1<<25)|(1<<24)|(1<<5)|(1<<4)|(1<<3)|    \
diff --cc src/i830.h
index 1acba66,38a880f..7def141
@@@ -69,11 -71,14 +70,15 @@@
  #endif
  
  #include "common.h"
 +#include "i830_sdvo.h"
 +#include "i2c_vid.h"
  
 +/* I830 Video support */
+ #define NEED_REPLIES				/* ? */
+ #define EXTENSION_PROC_ARGS void *
+ #include "extnsionst.h" 			/* required */
+ #include <X11/extensions/panoramiXproto.h> 	/* required */
  
 -/* I830 Video BIOS support */
 -
  /*
   * The mode handling is based upon the VESA driver written by
   * Paulo César Pereira de Andrade <pcpa at conectiva.com.br>.
@@@ -295,8 -247,26 +300,7 @@@
     I830MemRange *OverlayMem;
     I830MemRange LinearMem;
  #endif
 -   int LinearAlloc;
 -
 -   Bool MergedFB;
 -   ScrnInfoPtr pScrn_2;
 -   char	*SecondHSync;
 -   char	*SecondVRefresh;
 -   char	*MetaModes;
 -   int SecondPosition;
 -   int FirstXOffs, FirstYOffs, SecondXOffs, SecondYOffs;
 -   int FirstframeX0, FirstframeX1, FirstframeY0, FirstframeY1;
 -   int MBXNR1XMAX, MBXNR1YMAX, MBXNR2XMAX, MBXNR2YMAX;
 -   Bool	NonRect, HaveNonRect, HaveOffsRegions, MouseRestrictions;
 -   int maxFirst_X1, maxFirst_X2, maxFirst_Y1, maxFirst_Y2;
 -   int maxSecond_X1, maxSecond_X2, maxSecond_Y1, maxSecond_Y2;
 -   region NonRectDead, OffDead1, OffDead2;
 -   Bool	IntelXinerama;
 -   Bool	SecondIsScrn0;
 -   ExtensionEntry *XineramaExtEntry;
 -   int I830XineramaVX, I830XineramaVY;
 -  
 +   unsigned long LinearAlloc;
-   
     XF86ModReqInfo shadowReq; /* to test for later libshadow */
     I830MemRange RotatedMem;
     I830MemRange RotatedMem2;
@@@ -432,79 -428,11 +442,81 @@@
 -   Bool vbeRestoreWorkaround;
 -   Bool displayInfo;
 -   Bool devicePresence;
  
     OsTimerPtr devicesTimer;
  
 -   CARD32 savedAsurf;
 -   CARD32 savedBsurf;
 +   int ddc2;
 +   int num_outputs;
 +   struct _I830OutputRec output[MAX_OUTPUTS];
 +   I830SDVOPtr sdvo;
 +
 +   /* Panel size pulled from the BIOS */
 +   int PanelXRes, PanelYRes;
 +
 +   /* The BIOS's fixed timings for the LVDS */
 +   int panel_fixed_clock;
 +   int panel_fixed_hactive;
 +   int panel_fixed_hblank;
 +   int panel_fixed_hsyncoff;
 +   int panel_fixed_hsyncwidth;
 +   int panel_fixed_vactive;
 +   int panel_fixed_vblank;
 +   int panel_fixed_vsyncoff;
 +   int panel_fixed_vsyncwidth;
 +
 +   int backlight_duty_cycle;  /* restore backlight to this value */
 +   
 +   Bool panel_wants_dither;
 +
 +   CARD32 saveDSPACNTR;
 +   CARD32 saveDSPBCNTR;
 +   CARD32 savePIPEACONF;
 +   CARD32 savePIPEBCONF;
 +   CARD32 savePIPEASRC;
 +   CARD32 savePIPEBSRC;
 +   CARD32 saveFPA0;
 +   CARD32 saveFPA1;
 +   CARD32 saveDPLL_A;
 +   CARD32 saveHTOTAL_A;
 +   CARD32 saveHBLANK_A;
 +   CARD32 saveHSYNC_A;
 +   CARD32 saveVTOTAL_A;
 +   CARD32 saveVBLANK_A;
 +   CARD32 saveVSYNC_A;
 +   CARD32 saveDSPASTRIDE;
 +   CARD32 saveDSPASIZE;
 +   CARD32 saveDSPAPOS;
 +   CARD32 saveDSPABASE;
++   CARD32 saveDSPASURF;
 +   CARD32 saveFPB0;
 +   CARD32 saveFPB1;
 +   CARD32 saveDPLL_B;
 +   CARD32 saveHTOTAL_B;
 +   CARD32 saveHBLANK_B;
 +   CARD32 saveHSYNC_B;
 +   CARD32 saveVTOTAL_B;
 +   CARD32 saveVBLANK_B;
 +   CARD32 saveVSYNC_B;
 +   CARD32 saveDSPBSTRIDE;
 +   CARD32 saveDSPBSIZE;
 +   CARD32 saveDSPBPOS;
 +   CARD32 saveDSPBBASE;
++   CARD32 saveDSPBSURF;
 +   CARD32 saveVCLK_DIVISOR_VGA0;
 +   CARD32 saveVCLK_DIVISOR_VGA1;
 +   CARD32 saveVCLK_POST_DIV;
 +   CARD32 saveVGACNTRL;
 +   CARD32 saveADPA;
 +   CARD32 saveLVDS;
 +   CARD32 saveDVOA;
 +   CARD32 saveDVOB;
 +   CARD32 saveDVOC;
 +   CARD32 savePP_ON;
 +   CARD32 savePP_OFF;
 +   CARD32 savePP_CONTROL;
 +   CARD32 savePP_CYCLE;
 +   CARD32 savePFIT_CONTROL;
 +   CARD32 savePaletteA[256];
 +   CARD32 savePaletteB[256];
 +   CARD32 saveSWF[17];
 +   CARD32 saveBLC_PWM_CTL;
  } I830Rec;
  
  #define I830PTR(p) ((I830Ptr)((p)->driverPrivate))
@@@ -519,11 -447,13 +531,14 @@@
  extern void I830SetPIOAccess(I830Ptr pI830);
  extern void I830SetMMIOAccess(I830Ptr pI830);
  extern void I830PrintErrorState(ScrnInfoPtr pScrn);
+ 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 Bool I830CursorInit(ScreenPtr pScreen);
+ extern void IntelEmitInvarientState(ScrnInfoPtr pScrn);
  extern void I830EmitInvarientState(ScrnInfoPtr pScrn);
+ extern void I915EmitInvarientState(ScrnInfoPtr pScrn);
  extern void I830SelectBuffer(ScrnInfoPtr pScrn, int buffer);
  
  extern void I830RefreshRing(ScrnInfoPtr pScrn);
diff --cc src/i830_cursor.c
index 7389b66,c9e04e9..55bbe6a
@@@ -80,124 -80,51 +80,148 @@@
  #endif
  
  void
 +I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe, Bool force)
 +{
 +   I830Ptr pI830 = I830PTR(pScrn);
 +   CARD32 temp;
 +    Bool show;
 +    
 +    if (!pI830->planeEnabled[pipe])
 +	return;
 +
 +    show = pI830->cursorOn && pI830->cursorInRange[pipe];
 +    if (show && (force || !pI830->cursorShown[pipe]))
 +    {
 +	if (IS_MOBILE(pI830) || IS_I9XX(pI830)) {
 +	    int	cursor_control, cursor_base;
 +	    if (pipe == 0)
 +	    {
 +		cursor_control = CURSOR_A_CONTROL;
 +		cursor_base = CURSOR_A_BASE;
 +	    }
 +	    else
 +	    {
 +		cursor_control = CURSOR_B_CONTROL;
 +		cursor_base = CURSOR_B_BASE;
 +	    }
 +	    temp = INREG(cursor_control);
 +	    temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
 +	    if (pI830->CursorIsARGB) {
 +		temp |= CURSOR_MODE_64_ARGB_AX;
 +		if (pI830->gammaEnabled[pipe])
 +		    temp |= MCURSOR_GAMMA_ENABLE;
 +	    } else
 +		temp |= CURSOR_MODE_64_4C_AX;
 +	    
 +	    temp |= (pipe << 28); /* Connect to correct pipe */
 +	    /* Need to set mode, then address. */
 +	    OUTREG(cursor_control, temp);
- 	    if (pI830->CursorIsARGB)
- 		OUTREG(cursor_base, pI830->CursorMemARGB->Physical);
- 	    else
- 		OUTREG(cursor_base, pI830->CursorMem->Physical);
++	    if (pI830->CursorNeedsPhysical) {
++		if (pI830->CursorIsARGB)
++		    OUTREG(cursor_base, pI830->CursorMemARGB->Physical);
++		else
++		    OUTREG(cursor_base, pI830->CursorMem->Physical);
++	    } else {
++		if (pI830->CursorIsARGB)
++		    OUTREG(cursor_base, pI830->CursorMemARGB->Start);
++		else
++		    OUTREG(cursor_base, pI830->CursorMem->Start);
++	    }
 +	} else {
 +	    temp = INREG(CURSOR_CONTROL);
 +	    temp &= ~(CURSOR_FORMAT_MASK);
 +	    temp |= CURSOR_ENABLE;
 +	    if (pI830->CursorIsARGB) {
 +		temp |= CURSOR_FORMAT_ARGB;
 +		if (pI830->gammaEnabled[pipe])
 +		    temp |= CURSOR_GAMMA_ENABLE;
 +	    } else
 +		temp |= CURSOR_FORMAT_3C;
 +	    OUTREG(CURSOR_CONTROL, temp);
 +	    if (pI830->CursorIsARGB)
 +		OUTREG(CURSOR_BASEADDR, pI830->CursorMemARGB->Start);
 +	    else
 +		OUTREG(CURSOR_BASEADDR, pI830->CursorMem->Start);
 +	}
 +	pI830->cursorShown[pipe] = TRUE;
 +    }
 +    else if (!show && (force || pI830->cursorShown[pipe]))
 +    {
 +	if (IS_MOBILE(pI830) || IS_I9XX(pI830)) 
 +	{
 +	    int	cursor_control, cursor_base;
 +	    if (pipe == 0)
 +	    {
 +		cursor_control = CURSOR_A_CONTROL;
 +		cursor_base = CURSOR_A_BASE;
 +	    }
 +	    else
 +	    {
 +		cursor_control = CURSOR_B_CONTROL;
 +		cursor_base = CURSOR_B_BASE;
 +	    }
 +	    temp = INREG(cursor_control);
 +	    temp &= ~(CURSOR_MODE|MCURSOR_GAMMA_ENABLE);
 +	    temp |= CURSOR_MODE_DISABLE;
 +	    OUTREG(cursor_control, temp);
 +	    /* This is needed to flush the above change. */
- 	    if (pI830->CursorIsARGB)
- 		OUTREG(cursor_base, pI830->CursorMemARGB->Physical);
- 	    else
- 		OUTREG(cursor_base, pI830->CursorMem->Physical);
++	    if (pI830->CursorNeedsPhysical) {
++		if (pI830->CursorIsARGB)
++		    OUTREG(cursor_base, pI830->CursorMemARGB->Physical);
++		else
++		    OUTREG(cursor_base, pI830->CursorMem->Physical);
++	    } else {
++		if (pI830->CursorIsARGB)
++		    OUTREG(cursor_base, pI830->CursorMemARGB->Start);
++		else
++		    OUTREG(cursor_base, pI830->CursorMem->Start);
++	    }
 +	} else {
 +	    temp = INREG(CURSOR_CONTROL);
 +	    temp &= ~(CURSOR_ENABLE|CURSOR_GAMMA_ENABLE);
 +	    OUTREG(CURSOR_CONTROL, temp);
 +	}
 +	pI830->cursorShown[pipe] = FALSE;
 +    }
 +}
 +
 +void
  I830InitHWCursor(ScrnInfoPtr pScrn)
  {
     I830Ptr pI830 = I830PTR(pScrn);
     CARD32 temp;
 +   int i;
  
     DPRINTF(PFX, "I830InitHWCursor\n");
 +   for (i = 0; i < MAX_DISPLAY_PIPES; i++) pI830->cursorShown[i] = FALSE;
     /* Initialise the HW cursor registers, leaving the cursor hidden. */
     if (IS_MOBILE(pI830) || IS_I9XX(pI830)) {
 -      temp = INREG(CURSOR_A_CONTROL);
 -      temp &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE | MCURSOR_MEM_TYPE_LOCAL |
 -		MCURSOR_PIPE_SELECT);
 -      temp |= CURSOR_MODE_DISABLE;
 -      temp |= (pI830->pipe << 28);
 -      if (pI830->CursorIsARGB)
 -         temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
 -      else
 -         temp |= CURSOR_MODE_64_4C_AX;
 -      /* Need to set control, then address. */
 -      OUTREG(CURSOR_A_CONTROL, temp);
 -      if (pI830->CursorNeedsPhysical) {
 -         if (pI830->CursorIsARGB)
 -            OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical);
 -         else
 -            OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical);
 -      } else {
 -         if (pI830->CursorIsARGB)
 -            OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Start);
 -         else
 -            OUTREG(CURSOR_A_BASE, pI830->CursorMem->Start);
 -      }
 -      if (pI830->Clone || pI830->MergedFB) {
 -         temp &= ~MCURSOR_PIPE_SELECT;
 -         temp |= (!pI830->pipe << 28);
 -         OUTREG(CURSOR_B_CONTROL, temp);
 -         if (pI830->CursorNeedsPhysical) {
 -            if (pI830->CursorIsARGB)
 -               OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical);
 -            else
 -               OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical);
 +      for (i = 0; i < MAX_DISPLAY_PIPES; i++)
 +      {
 +	 int   cursor_control = i == 0 ? CURSOR_A_CONTROL : CURSOR_B_CONTROL;
 +	 int   cursor_base = i == 0 ? CURSOR_A_BASE : CURSOR_B_BASE;
 +	 temp = INREG(cursor_control);
 +	 temp &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE |
 +		   MCURSOR_MEM_TYPE_LOCAL |
 +		   MCURSOR_PIPE_SELECT);
- 	 temp |= CURSOR_MODE_DISABLE;
 +	 temp |= (i << 28);
- 	 /* Need to set control, then address. */
- 	 OUTREG(cursor_control, temp);
 +	 if (pI830->CursorIsARGB)
- 	    OUTREG(cursor_base, pI830->CursorMemARGB->Physical);
++	    temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
 +	 else
- 	    OUTREG(cursor_base, pI830->CursorMem->Physical);
++	    temp |= CURSOR_MODE_64_4C_AX;
++	 /* Need to set control, then address. */
++	 OUTREG(cursor_control, temp);
++	 if (pI830->CursorNeedsPhysical) {
++	    if (pI830->CursorIsARGB)
++	       OUTREG(cursor_base, pI830->CursorMemARGB->Physical);
++	    else
++	       OUTREG(cursor_base, pI830->CursorMem->Physical);
+ 	 } else {
 -            if (pI830->CursorIsARGB)
 -               OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Start);
 -            else
 -               OUTREG(CURSOR_B_BASE, pI830->CursorMem->Start);
++	    if (pI830->CursorIsARGB)
++	       OUTREG(cursor_base, pI830->CursorMemARGB->Start);
++	    else
++	       OUTREG(cursor_base, pI830->CursorMem->Start);
+ 	 }
        }
     } else {
        temp = INREG(CURSOR_CONTROL);
@@@ -447,97 -377,223 +474,104 @@@
 -#define CDMPTR    ((I830ModePrivatePtr)pI830->currentMode->Private)->merged
 -
 -static void
 -I830SetCursorPositionMerged(ScrnInfoPtr pScrn, int x, int y)
 -{
 -   I830Ptr pI830 = I830PTR(pScrn);
 -   ScrnInfoPtr    pScrn2 = pI830->pScrn_2;
 -   DisplayModePtr mode1 = CDMPTR.First;
 -   Bool hide = FALSE, show = FALSE;
 -   DisplayModePtr mode2 = CDMPTR.Second;
 -   int x1, y1, x2, y2;
 -   int total_y1 = pScrn->frameY1 - pScrn->frameY0;
 -   int total_y2 = pScrn2->frameY1 - pScrn2->frameY0;
 -   CARD32 temp = 0, temp2 = 0;
 -
 -   x += pScrn->frameX0;
 -   y += pScrn->frameY0;
 -
 -   x1 = x - pI830->FirstframeX0;
 -   y1 = y - pI830->FirstframeY0;
 -
 -   x2 = x - pScrn2->frameX0;
 -   y2 = y - pScrn2->frameY0;
 -
 -   if (y1 > total_y1)
 -      y1 = total_y1;
 -   if (y2 > total_y2)                  
 -      y2 = total_y2;
 -
 -   /* move cursor offscreen */
 -   if (y1 >= 0 && y2 >= mode2->VDisplay) {
 -      y2 = -I810_CURSOR_Y;  
 -   } else if (y2 >= 0 && y1 >= mode1->VDisplay) {
 -      y1 = -I810_CURSOR_Y;  
 -   }
 -   if (x1 >= 0 && x2 >= mode2->HDisplay) {
 -      x2 = -I810_CURSOR_X;  
 -   } else if (x2 >= 0 && x1 >= mode1->HDisplay) {
 -      x1 = -I810_CURSOR_X;  
 -   }
 -
 -   /* Clamp the cursor position to the visible screen area */
 -   if (x1 >= mode1->HDisplay) x1 = mode1->HDisplay - 1;
 -   if (y1 >= mode1->VDisplay) y1 = mode1->VDisplay - 1;
 -   if (x1 <= -I810_CURSOR_X) x1 = -I810_CURSOR_X + 1;
 -   if (y1 <= -I810_CURSOR_Y) y1 = -I810_CURSOR_Y + 1;
 -   if (x2 >= mode2->HDisplay) x2 = mode2->HDisplay - 1;
 -   if (y2 >= mode2->VDisplay) y2 = mode2->VDisplay - 1;
 -   if (x2 <= -I810_CURSOR_X) x2 = -I810_CURSOR_X + 1;
 -   if (y2 <= -I810_CURSOR_Y) y2 = -I810_CURSOR_Y + 1;
 -
 -   if (x1 < 0) {
 -      temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
 -      x1 = -x1;
 -   }
 -   if (y1 < 0) {
 -      temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT);
 -      y1 = -y1;
 -   }
 -   if (x2 < 0) {
 -      temp2 |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
 -      x2 = -x2;
 -   }
 -   if (y2 < 0) {
 -      temp2 |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT);
 -      y2 = -y2;
 -   }
 -
 -   temp |= ((x1 & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
 -   temp |= ((y1 & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
 -   temp2 |= ((x2 & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
 -   temp2 |= ((y2 & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
 -
 -   OUTREG(CURSOR_A_POSITION, temp);
 -   OUTREG(CURSOR_B_POSITION, temp2);
 -
 -   if (pI830->cursorOn) {
 -      if (hide)
 -	 pI830->CursorInfoRec->HideCursor(pScrn);
 -      else if (show)
 -	 pI830->CursorInfoRec->ShowCursor(pScrn);
 -      pI830->cursorOn = TRUE;
 -   }
 -
 -   /* have to upload the base for the new position */
 -   if (IS_I9XX(pI830)) {
 -      if (pI830->CursorIsARGB) {
 -         OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical);
 -         OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical);
 -      } else {
 -         OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical);
 -         OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical);
 -      }
 -   }
 -}
 -
  static void
  I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
  {
 -   I830Ptr pI830 = I830PTR(pScrn);
 -   CARD32 temp = 0;
 -   Bool hide = FALSE, show = FALSE;
 -   int oldx = x, oldy = y;
 -   int hotspotx = 0, hotspoty = 0;
 -#if 0
 -   static Bool outsideViewport = FALSE;
 -#endif
 -
 -   if (pI830->MergedFB) {
 -      I830SetCursorPositionMerged(pScrn, x, y);
 -      return;
 -   }
 -
 -   oldx += pScrn->frameX0; /* undo what xf86HWCurs did */
 -   oldy += pScrn->frameY0;
 -
 -   switch (pI830->rotation) {
 -      case RR_Rotate_0:
 -         x = oldx;
 -         y = oldy;
 -         break;
 -      case RR_Rotate_90:
 -         x = oldy;
 -         y = pScrn->pScreen->width - oldx;
 -         hotspoty = I810_CURSOR_X;
 -         break;
 -      case RR_Rotate_180:
 -         x = pScrn->pScreen->width - oldx;
 -         y = pScrn->pScreen->height - oldy;
 -         hotspotx = I810_CURSOR_X;
 -         hotspoty = I810_CURSOR_Y;
 -         break;
 -      case RR_Rotate_270:
 -         x = pScrn->pScreen->height - oldy;
 -         y = oldx;
 -         hotspotx = I810_CURSOR_Y;
 -         break;
 -   }
 -
 -   x -= hotspotx;
 -   y -= hotspoty;
 -
 -   /* Now, readjust */
 -   x -= pScrn->frameX0;
 -   y -= pScrn->frameY0;
 -
 -   /* Clamp the cursor position to the visible screen area */
 -   if (x >= pScrn->currentMode->HDisplay) x = pScrn->currentMode->HDisplay - 1;
 -   if (y >= pScrn->currentMode->VDisplay) y = pScrn->currentMode->VDisplay - 1;
 -   if (x <= -I810_CURSOR_X) x = -I810_CURSOR_X + 1;
 -   if (y <= -I810_CURSOR_Y) y = -I810_CURSOR_Y + 1;
 -
 -#if 0
 -   /*
 -    * There is a screen display problem when the cursor position is set
 -    * wholely outside of the viewport.  We trap that here, turning the
 -    * cursor off when that happens, and back on when it comes back into
 -    * the viewport.
 -    */
 -   if (x >= pScrn->currentMode->HDisplay ||
 -       y >= pScrn->currentMode->VDisplay ||
 -       x <= -I810_CURSOR_X || y <= -I810_CURSOR_Y) {
 -      hide = TRUE;
 -      outsideViewport = TRUE;
 -   } else if (outsideViewport) {
 -      show = TRUE;
 -      outsideViewport = FALSE;
 -   }
 -#endif
 -
 -   if (x < 0) {
 -      temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
 -      x = -x;
 -   }
 -   if (y < 0) {
 -      temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT);
 -      y = -y;
 -   }
 -   temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
 -   temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
 -
 -   OUTREG(CURSOR_A_POSITION, temp);
 -   if (pI830->Clone)
 -      OUTREG(CURSOR_B_POSITION, temp);
 -
 -   if (pI830->cursorOn) {
 -      if (hide)
 -	 pI830->CursorInfoRec->HideCursor(pScrn);
 -      else if (show)
 -	 pI830->CursorInfoRec->ShowCursor(pScrn);
 -      pI830->cursorOn = TRUE;
 -   }
 -
 -   /* have to upload the base for the new position */
 -   if (IS_I9XX(pI830)) {
 -      if (pI830->CursorNeedsPhysical) {
 -         if (pI830->CursorIsARGB)
 -            OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical);
 -         else
 -            OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical);
 -      } else {
 -         if (pI830->CursorIsARGB)
 -            OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Start);
 -         else
 -            OUTREG(CURSOR_A_BASE, pI830->CursorMem->Start);
 -      }
 -      if (pI830->Clone) {
 -         if (pI830->CursorNeedsPhysical) {
 -            if (pI830->CursorIsARGB)
 -               OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical);
 -            else
 -               OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical);
 -	 } else {
 -            if (pI830->CursorIsARGB)
 -               OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Start);
 -            else
 -               OUTREG(CURSOR_B_BASE, pI830->CursorMem->Start);
 -	 }
 -      }
 -   }
 +    I830Ptr pI830 = I830PTR(pScrn);
 +    CARD32 temp;
 +    Bool inrange;
 +    int oldx = x, oldy = y;
 +    int hotspotx = 0, hotspoty = 0;
 +    int pipe;
 +
 +    oldx += pScrn->frameX0; /* undo what xf86HWCurs did */
 +    oldy += pScrn->frameY0;
 +
 +    switch (pI830->rotation) {
 +    case RR_Rotate_0:
 +	x = oldx;
 +	y = oldy;
 +	break;
 +    case RR_Rotate_90:
 +	x = oldy;
 +	y = pScrn->pScreen->width - oldx;
 +	hotspoty = I810_CURSOR_X;
 +	break;
 +    case RR_Rotate_180:
 +	x = pScrn->pScreen->width - oldx;
 +	y = pScrn->pScreen->height - oldy;
 +	hotspotx = I810_CURSOR_X;
 +	hotspoty = I810_CURSOR_Y;
 +	break;
 +    case RR_Rotate_270:
 +	x = pScrn->pScreen->height - oldy;
 +	y = oldx;
 +	hotspotx = I810_CURSOR_Y;
 +	break;
 +    }
 +
 +    x -= hotspotx;
 +    y -= hotspoty;
 +
 +    for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++)
 +    {
 +	DisplayModePtr	mode = &pI830->pipeCurMode[pipe];
 +	int		thisx = x - pI830->pipeX[pipe];
 +	int		thisy = y - pI830->pipeY[pipe];
 +
 +	if (!pI830->planeEnabled[pipe])
 +	    continue;
 +
 +	/*
 +	 * There is a screen display problem when the cursor position is set
 +	 * wholely outside of the viewport.  We trap that here, turning the
 +	 * cursor off when that happens, and back on when it comes back into
 +	 * the viewport.
 +	 */
 +	inrange = TRUE;
 +	if (thisx >= mode->HDisplay ||
 +	    thisy >= mode->VDisplay ||
 +	    thisx <= -I810_CURSOR_X || thisy <= -I810_CURSOR_Y) 
 +	{
 +	    inrange = FALSE;
 +	    thisx = 0;
 +	    thisy = 0;
 +	}
 +
 +	temp = 0;
 +	if (thisx < 0) {
 +	    temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
 +	    thisx = -thisx;
 +	}
 +	if (thisy < 0) {
 +	    temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT);
 +	    thisy = -thisy;
 +	}
 +	temp |= ((thisx & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
 +	temp |= ((thisy & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
 +
 +	if (pipe == 0)
 +	    OUTREG(CURSOR_A_POSITION, temp);
 +	if (pipe == 1)
 +	    OUTREG(CURSOR_B_POSITION, temp);
 +
 +	pI830->cursorInRange[pipe] = inrange;
 +	
 +        I830SetPipeCursor (pScrn, pipe, FALSE);
 +
 +	/* have to upload the base for the new position */
 +	if (IS_I9XX(pI830)) {
 +	    int base = pipe == 0 ? CURSOR_A_BASE : CURSOR_B_BASE;
- 	    if (pI830->CursorIsARGB)
- 		OUTREG(base, pI830->CursorMemARGB->Physical);
- 	    else
- 		OUTREG(base, pI830->CursorMem->Physical);
++	    if (pI830->CursorNeedsPhysical) {
++	       if (pI830->CursorIsARGB)
++		  OUTREG(base, pI830->CursorMemARGB->Physical);
++	       else
++		  OUTREG(base, pI830->CursorMem->Physical);
++	    } else {
++	       if (pI830->CursorIsARGB)
++		  OUTREG(base, pI830->CursorMemARGB->Start);
++	       else
++		  OUTREG(base, pI830->CursorMem->Start);
++	    }
 +	}
 +    }
  }
  
  static void
diff --cc src/i830_display.c
index 24ce50f,0000000..2b53128
mode 100644,000000..100644
@@@ -1,1128 -1,0 +1,1133 @@@
 +/* -*- c-basic-offset: 4 -*- */
 +/*
 + * Copyright © 2006 Intel Corporation
 + *
 + * Permission is hereby granted, free of charge, to any person obtaining a
 + * copy of this software and associated documentation files (the "Software"),
 + * to deal in the Software without restriction, including without limitation
 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 + * and/or sell copies of the Software, and to permit persons to whom the
 + * Software is furnished to do so, subject to the following conditions:
 + *
 + * The above copyright notice and this permission notice (including the next
 + * paragraph) shall be included in all copies or substantial portions of the
 + * Software.
 + *
 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 + * SOFTWARE.
 + *
 + * Authors:
 + *    Eric Anholt <eric at anholt.net>
 + *
 + */
 +
 +#ifdef HAVE_CONFIG_H
 +#include "config.h"
 +#endif
 +
 +#include <unistd.h>
 +#include <string.h>
 +#include <assert.h>
 +#include <stdlib.h>
 +#include <math.h>
 +
 +#include "xf86.h"
 +#include "i830.h"
 +#include "i830_bios.h"
 +#include "i830_display.h"
 +#include "i830_debug.h"
 +#include "i830_xf86Modes.h"
 +
 +/** Returns the pixel clock for the given refclk and divisors. */
 +static int i830_clock(int refclk, int m1, int m2, int n, int p1, int p2)
 +{
 +    return refclk * (5 * m1 + m2) / n / (p1 * p2);
 +}
 +
 +static void
 +i830PrintPll(char *prefix, int refclk, int m1, int m2, int n, int p1, int p2)
 +{
 +    int dotclock;
 +
 +    dotclock = i830_clock(refclk, m1, m2, n, p1, p2);
 +
 +    ErrorF("%s: dotclock %d ((%d, %d), %d, (%d, %d))\n", prefix, dotclock,
 +	   m1, m2, n, p1, p2);
 +}
 +
 +/**
 + * Returns whether the given set of divisors are valid for a given refclk with
 + * the given outputs.
 + *
 + * The equation for these divisors would be:
 + * clk = refclk * (5 * m1 + m2) / n / (p1 * p2)
 + */
 +static Bool
 +i830PllIsValid(ScrnInfoPtr pScrn, int outputs, int refclk, int m1, int m2,
 +	       int n, int p1, int p2)
 +{
 +    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;
 +    int min_p1, max_p1, min_p, max_p, min_vco, max_vco, min_dot, max_dot;
 +
 +    if (IS_I9XX(pI830)) {
 +	min_m1 = 10;
 +	max_m1 = 20;
 +	min_m2 = 5;
 +	max_m2 = 9;
 +	min_m = 70;
 +	max_m = 120;
 +	min_n = 3;
 +	max_n = 8;
 +	min_p1 = 1;
 +	max_p1 = 8;
 +	if (outputs & PIPE_LCD_ACTIVE) {
 +	    min_p = 7;
 +	    max_p = 98;
 +	} else {
 +	    min_p = 5;
 +	    max_p = 80;
 +	}
 +	min_vco = 1400000;
 +	max_vco = 2800000;
 +	min_dot = 20000;
 +	max_dot = 400000;
 +    } else {
 +	min_m1 = 18;
 +	max_m1 = 26;
 +	min_m2 = 6;
 +	max_m2 = 16;
 +	min_m = 96;
 +	max_m = 140;
 +	min_n = 3;
 +	max_n = 16;
 +	min_p1 = 2;
 +	max_p1 = 18;
 +	min_vco = 930000;
 +	max_vco = 1400000;
 +	min_dot = 20000;
 +	max_dot = 350000;
 +	min_p = 4;
 +	max_p = 128;
 +    }
 +
 +    p = p1 * p2;
 +    m = 5 * m1 + m2;
 +    vco = refclk * m / n;
 +    dotclock = i830_clock(refclk, m1, m2, n, p1, p2);
 +
 +    if (p1 < min_p1 || p1 > max_p1)
 +	return FALSE;
 +    if (p < min_p || p > max_p)
 +	return FALSE;
 +    if (m2 < min_m2 || m2 > max_m2)
 +	return FALSE;
 +    if (m1 < min_m1 || m1 > max_m1)
 +	return FALSE;
 +    if (m1 <= m2)
 +	return FALSE;
 +    if (m < min_m || m > max_m)
 +	return FALSE;
 +    if (n < min_n || n > max_n)
 +	return FALSE;
 +    if (vco < min_vco || vco > max_vco)
 +	return FALSE;
 +    /* XXX: We may need to be checking "Dot clock" depending on the multiplier,
 +     * output, etc., rather than just a single range.
 +     */
 +    if (dotclock < min_dot || dotclock > max_dot)
 +	return FALSE;
 +
 +    return TRUE;
 +}
 +
 +/**
 + * Returns a set of divisors for the desired target clock with the given refclk,
 + * or FALSE.  Divisor values are the actual divisors for
 + * clk = refclk * (5 * m1 + m2) / n / (p1 * p2)
 + */
 +static Bool
 +i830FindBestPLL(ScrnInfoPtr pScrn, int outputs, int target, int refclk,
 +		int *outm1, int *outm2, int *outn, int *outp1, int *outp2)
 +{
 +    I830Ptr pI830 = I830PTR(pScrn);
 +    int m1, m2, n, p1, p2;
 +    int err = target;
 +    int min_m1, max_m1, min_m2, max_m2, min_n, max_n, min_p1, max_p1;
 +
 +    if (IS_I9XX(pI830)) {
 +	min_m1 = 10;
 +	max_m1 = 20;
 +	min_m2 = 5;
 +	max_m2 = 9;
 +	min_n = 3;
 +	max_n = 8;
 +	min_p1 = 1;
 +	max_p1 = 8;
 +	if (outputs & PIPE_LCD_ACTIVE) {
 +	    if (target < 200000) /* XXX: Is this the right cutoff? */
 +		p2 = 14;
 +	    else
 +		p2 = 7;
 +	} else {
 +	    if (target < 200000)
 +		p2 = 10;
 +	    else
 +		p2 = 5;
 +	}
 +    } else {
 +	min_m1 = 18;
 +	max_m1 = 26;
 +	min_m2 = 6;
 +	max_m2 = 16;
 +	min_n = 3;
 +	max_n = 16;
 +	min_p1 = 2;
 +	max_p1 = 18;
 +	if (target < 165000)
 +	    p2 = 4;
 +	else
 +	    p2 = 2;
 +    }
 +
 +
 +    for (m1 = min_m1; m1 <= max_m1; m1++) {
 +	for (m2 = min_m2; m2 < max_m2; m2++) {
 +	    for (n = min_n; n <= max_n; n++) {
 +		for (p1 = min_p1; p1 <= max_p1; p1++) {
 +		    int clock, this_err;
 +
 +		    if (!i830PllIsValid(pScrn, outputs, refclk, m1, m2, n,
 +					p1, p2)) {
 +			continue;
 +		    }
 +
 +		    clock = i830_clock(refclk, m1, m2, n, p1, p2);
 +		    this_err = abs(clock - target);
 +		    if (this_err < err) {
 +			*outm1 = m1;
 +			*outm2 = m2;
 +			*outn = n;
 +			*outp1 = p1;
 +			*outp2 = p2;
 +			err = this_err;
 +		    }
 +		}
 +	    }
 +	}
 +    }
 +
 +    return (err != target);
 +}
 +
 +static void
 +i830WaitForVblank(ScrnInfoPtr pScreen)
 +{
 +    /* Wait for 20ms, i.e. one cycle at 50hz. */
 +    usleep(20000);
 +}
 +
 +void
 +i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y)
 +{
 +    I830Ptr pI830 = I830PTR(pScrn);
 +    unsigned long Start;
++    int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE);
++    int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
 +
 +    if (I830IsPrimary(pScrn))
 +	Start = pI830->FrontBuffer.Start;
 +    else {
 +	I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
 +	Start = pI8301->FrontBuffer2.Start;
 +    }
 +
-     if (pipe == 0)
- 	OUTREG(DSPABASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
-     else
- 	OUTREG(DSPBBASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
++    if (IS_I965G(pI830)) {
++	OUTREG(dspbase, 0);
++	OUTREG(dspsurf, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
++    } else {
++	OUTREG(dspbase, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
++    }
++
 +    pI830->pipeX[pipe] = x;
 +    pI830->pipeY[pipe] = y;
 +}
 +
 +/**
 + * Sets the given video mode on the given pipe.  Assumes that plane A feeds
 + * pipe A, and plane B feeds pipe B.  Should not affect the other planes/pipes.
 + */
 +Bool
 +i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe)
 +{
 +    I830Ptr pI830 = I830PTR(pScrn);
 +    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;
 +    CARD32 pipesrc, dspsize, adpa;
 +    CARD32 sdvob = 0, sdvoc = 0, dvo = 0;
 +    Bool ok, is_sdvo, is_dvo;
 +    int refclk, pixel_clock, sdvo_pixel_multiply;
 +    int outputs;
 +    DisplayModePtr pMasterMode = pMode;
 +
 +    assert(pMode->VRefresh != 0.0);
 +    /* If we've got a list of modes probed for the device, find the best match
 +     * in there to the requested mode.
 +     */
 +    if (pI830->pipeMon[pipe] != NULL) {
 +	DisplayModePtr pBest = NULL, pScan;
 +
 +	assert(pScan->VRefresh != 0.0);
 +	for (pScan = pI830->pipeMon[pipe]->Modes; pScan != NULL;
 +	     pScan = pScan->next)
 +	{
 +	    /* If there's an exact match, we're done. */
 +	    if (I830ModesEqual(pScan, pMode)) {
 +		pBest = pMode;
 +		break;
 +	    }
 +
 +	    /* Reject if it's larger than the desired mode. */
 +	    if (pScan->HDisplay > pMode->HDisplay ||
 +		pScan->VDisplay > pMode->VDisplay)
 +	    {
 +		continue;
 +	    }
 +
 +	    if (pBest == NULL) {
 +		pBest = pScan;
 +	        continue;
 +	    }
 +	    /* Find if it's closer to the right size than the current best
 +	     * option.
 +	     */
 +	    if ((pScan->HDisplay > pBest->HDisplay && 
 +		pScan->VDisplay >= pBest->VDisplay) ||
 +	        (pScan->HDisplay >= pBest->HDisplay && 
 +		pScan->VDisplay > pBest->VDisplay))
 +	    {
 +		pBest = pScan;
 +		continue;
 +	    }
 +	    /* Find if it's still closer to the right refresh than the current
 +	     * best resolution.
 +	     */
 +	    if (pScan->HDisplay == pBest->HDisplay && 
 +		pScan->VDisplay == pBest->VDisplay &&
 +		(fabs(pScan->VRefresh - pMode->VRefresh) <
 +		fabs(pBest->VRefresh - pMode->VRefresh)))
 +	    {
 +		pBest = pScan;
 +	    }
 +	}
 +	if (pBest != NULL) {
 +	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 +		       "Choosing pipe %d's mode %dx%d@%.1f instead of xf86 "
 +		       "mode %dx%d@%.1f\n", pipe,
 +		       pBest->HDisplay, pBest->VDisplay, pBest->VRefresh,
 +		       pMode->HDisplay, pMode->VDisplay, pMode->VRefresh);
 +	    pMode = pBest;
 +	}
 +    }
 +    if (pipe == 0)
 +	outputs = pI830->operatingDevices & 0xff;
 +    else
 +	outputs = (pI830->operatingDevices >> 8) & 0xff;
 +
 +    if (outputs & PIPE_LCD_ACTIVE) {
 +	if (I830ModesEqual(&pI830->pipeCurMode[pipe], pMasterMode))
 +	    return TRUE;
 +    } else {
 +	if (I830ModesEqual(&pI830->pipeCurMode[pipe], pMode))
 +	    return TRUE;
 +    }
 +
 +    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested pix clock: %d\n",
 +	       pMode->Clock);
 +
 +    if ((outputs & PIPE_LCD_ACTIVE) && (outputs & ~PIPE_LCD_ACTIVE)) {
 +	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 +		   "Can't enable LVDS and non-LVDS on the same pipe\n");
 +	return FALSE;
 +    }
 +    if (((outputs & PIPE_TV_ACTIVE) && (outputs & ~PIPE_TV_ACTIVE)) ||
 +	((outputs & PIPE_TV2_ACTIVE) && (outputs & ~PIPE_TV2_ACTIVE))) {
 +	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 +		   "Can't enable a TV and any other output on the same pipe\n");
 +	return FALSE;
 +    }
 +    if (pipe == 0 && (outputs & PIPE_LCD_ACTIVE)) {
 +	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 +		   "Can't support LVDS on pipe A\n");
 +	return FALSE;
 +    }
 +    if ((outputs & PIPE_DFP_ACTIVE) || (outputs & PIPE_DFP2_ACTIVE)) {
 +	/* We'll change how we control outputs soon, but to get the SDVO code up
 +	 * and running, just check for these two possibilities.
 +	 */
 +	if (IS_I9XX(pI830)) {
 +	    is_sdvo = TRUE;
 +	    is_dvo = FALSE;
 +	} else {
 +	    is_dvo = TRUE;
 +	    is_sdvo = FALSE;
 +	}
 +    } else {
 +	is_sdvo = FALSE;
 +	is_dvo = FALSE;
 +    }
 +
 +    htot = (pMode->CrtcHDisplay - 1) | ((pMode->CrtcHTotal - 1) << 16);
 +    hblank = (pMode->CrtcHBlankStart - 1) | ((pMode->CrtcHBlankEnd - 1) << 16);
 +    hsync = (pMode->CrtcHSyncStart - 1) | ((pMode->CrtcHSyncEnd - 1) << 16);
 +    vtot = (pMode->CrtcVDisplay - 1) | ((pMode->CrtcVTotal - 1) << 16);
 +    vblank = (pMode->CrtcVBlankStart - 1) | ((pMode->CrtcVBlankEnd - 1) << 16);
 +    vsync = (pMode->CrtcVSyncStart - 1) | ((pMode->CrtcVSyncEnd - 1) << 16);
 +    pipesrc = ((pMode->HDisplay - 1) << 16) | (pMode->VDisplay - 1);
 +    dspsize = ((pMode->VDisplay - 1) << 16) | (pMode->HDisplay - 1);
 +    pixel_clock = pMode->Clock;
 +    if (outputs & PIPE_LCD_ACTIVE && pI830->panel_fixed_hactive != 0)
 +    {
 +	/* To enable panel fitting, we need to set the pipe timings to that of
 +	 * the screen at its full resolution.  So, drop the timings from the
 +	 * BIOS VBT tables here.
 +	 */
 +	htot = (pI830->panel_fixed_hactive - 1) |
 +		((pI830->panel_fixed_hactive + pI830->panel_fixed_hblank - 1)
 +		 << 16);
 +	hblank = (pI830->panel_fixed_hactive - 1) |
 +		((pI830->panel_fixed_hactive + pI830->panel_fixed_hblank - 1)
 +		 << 16);
 +	hsync = (pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff - 1) |
 +		((pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff +
 +		  pI830->panel_fixed_hsyncwidth - 1) << 16);
 +
 +	vtot = (pI830->panel_fixed_vactive - 1) |
 +		((pI830->panel_fixed_vactive + pI830->panel_fixed_vblank - 1)
 +		 << 16);
 +	vblank = (pI830->panel_fixed_vactive - 1) |
 +		((pI830->panel_fixed_vactive + pI830->panel_fixed_vblank - 1)
 +		 << 16);
 +	vsync = (pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff - 1) |
 +		((pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff +
 +		  pI830->panel_fixed_vsyncwidth - 1) << 16);
 +	pixel_clock = pI830->panel_fixed_clock;
 +
 +	if (pMasterMode->HDisplay <= pI830->panel_fixed_hactive &&
 +	    pMasterMode->HDisplay <= pI830->panel_fixed_vactive)
 +	{
 +	    pipesrc = ((pMasterMode->HDisplay - 1) << 16) |
 +		       (pMasterMode->VDisplay - 1);
 +	    dspsize = ((pMasterMode->VDisplay - 1) << 16) |
 +		       (pMasterMode->HDisplay - 1);
 +	}
 +    }
 +
 +    if (pMode->Clock >= 100000)
 +	sdvo_pixel_multiply = 1;
 +    else if (pMode->Clock >= 50000)
 +	sdvo_pixel_multiply = 2;
 +    else
 +	sdvo_pixel_multiply = 4;
 +
 +    /* In SDVO, we need to keep the clock on the bus between 1Ghz and 2Ghz.
 +     * The clock on the bus is 10 times the pixel clock normally.  If that
 +     * would be too low, we run the DPLL at a multiple of the pixel clock, and
 +     * tell the SDVO device the multiplier so it can throw away the dummy bytes.
 +     */
 +    if (is_sdvo) {
 +	pixel_clock *= sdvo_pixel_multiply;
 +    }
 +
 +    if (IS_I9XX(pI830)) {
 +	refclk = 96000;
 +    } else {
 +	refclk = 48000;
 +    }
 +    ok = i830FindBestPLL(pScrn, outputs, pixel_clock, refclk, &m1, &m2, &n,
 +			 &p1, &p2);
 +    if (!ok) {
 +	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 +		   "Couldn't find PLL settings for mode!\n");
 +	return FALSE;
 +    }
 +
 +    dpll = DPLL_VCO_ENABLE | DPLL_VGA_MODE_DIS;
 +    if (IS_I9XX(pI830)) {
 +	if (outputs & PIPE_LCD_ACTIVE)
 +	    dpll |= DPLLB_MODE_LVDS;
 +	else
 +	    dpll |= DPLLB_MODE_DAC_SERIAL;
 +	dpll |= (1 << (p1 - 1)) << 16;
 +	switch (p2) {
 +	case 5:
 +	    dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5;
 +	    break;
 +	case 7:
 +	    dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7;
 +	    break;
 +	case 10:
 +	    dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10;
 +	    break;
 +	case 14:
 +	    dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
 +	    break;
 +	}
 +    } else {
 +	dpll |= (p1 - 2) << 16;
 +	if (p2 == 4)
 +	    dpll |= PLL_P2_DIVIDE_BY_4;
 +    }
 +
 +    if (outputs & (PIPE_TV_ACTIVE | PIPE_TV2_ACTIVE))
 +	dpll |= PLL_REF_INPUT_TVCLKINBC;
 +#if 0    
 +    else if (outputs & (PIPE_LCD_ACTIVE))
 +	dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
 +#endif
 +    else	
 +	dpll |= PLL_REF_INPUT_DREFCLK;
 +
 +    if (is_dvo) {
 +	dpll |= DPLL_DVO_HIGH_SPEED;
 +
 +	/* 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 (pipe == 1)
 +	    dvo |= DVO_PIPE_B_SELECT;
 +
 +	if (pMode->Flags & V_PHSYNC)
 +	    dvo |= DVO_HSYNC_ACTIVE_HIGH;
 +	if (pMode->Flags & V_PVSYNC)
 +	    dvo |= DVO_VSYNC_ACTIVE_HIGH;
 +
 +	OUTREG(DVOC, dvo & ~DVO_ENABLE);
 +    }
 +
 +    if (is_sdvo) {
 +	dpll |= DPLL_DVO_HIGH_SPEED;
 +
 +	ErrorF("DVOB: %08x\nDVOC: %08x\n", (int)INREG(SDVOB), (int)INREG(SDVOC));
 +
 +        sdvob = INREG(SDVOB) & SDVOB_PRESERVE_MASK;
 +	sdvoc = INREG(SDVOC) & SDVOC_PRESERVE_MASK;
 +	sdvob |= SDVO_ENABLE | (9 << 19) | SDVO_BORDER_ENABLE;
 +	sdvoc |= 9 << 19;
 +	if (pipe == 1)
 +	    sdvob |= SDVO_PIPE_B_SELECT;
 +
 +	if (IS_I945G(pI830) || IS_I945GM(pI830))
 +	    dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
 +	else
 +	    sdvob |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT;
 +
 +	OUTREG(SDVOC, INREG(SDVOC) & ~SDVO_ENABLE);
 +	OUTREG(SDVOB, INREG(SDVOB) & ~SDVO_ENABLE);
 +    }
 +
 +    fp = ((n - 2) << 16) | ((m1 - 2) << 8) | (m2 - 2);
 +
 +#if 1
 +    ErrorF("hact: %d htot: %d hbstart: %d hbend: %d hsyncstart: %d hsyncend: %d\n",
 +	(int)(htot & 0xffff) + 1, (int)(htot >> 16) + 1,
 +	(int)(hblank & 0xffff) + 1, (int)(hblank >> 16) + 1,
 +	(int)(hsync & 0xffff) + 1, (int)(hsync >> 16) + 1);
 +    ErrorF("vact: %d vtot: %d vbstart: %d vbend: %d vsyncstart: %d vsyncend: %d\n",
 +	(int)(vtot & 0xffff) + 1, (int)(vtot >> 16) + 1,
 +	(int)(vblank & 0xffff) + 1, (int)(vblank >> 16) + 1,
 +	(int)(vsync & 0xffff) + 1, (int)(vsync >> 16) + 1);
 +    ErrorF("pipesrc: %dx%d, dspsize: %dx%d\n",
 +	(int)(pipesrc >> 16) + 1, (int)(pipesrc & 0xffff) + 1,
 +	(int)(dspsize & 0xffff) + 1, (int)(dspsize >> 16) + 1);
 +#endif
 +
 +    i830PrintPll("chosen", refclk, m1, m2, n, p1, p2);
 +    ErrorF("clock regs: 0x%08x, 0x%08x\n", (int)dpll, (int)fp);
 +
 +    dspcntr = DISPLAY_PLANE_ENABLE;
 +    switch (pScrn->bitsPerPixel) {
 +    case 8:
 +	dspcntr |= DISPPLANE_8BPP | DISPPLANE_GAMMA_ENABLE;
 +	break;
 +    case 16:
 +	if (pScrn->depth == 15)
 +	    dspcntr |= DISPPLANE_15_16BPP;
 +	else
 +	    dspcntr |= DISPPLANE_16BPP;
 +	break;
 +    case 32:
 +	dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
 +	break;
 +    default:
 +	FatalError("unknown display bpp\n");
 +    }
 +
 +    if (pI830->gammaEnabled[pipe]) {
 + 	dspcntr |= DISPPLANE_GAMMA_ENABLE;
 +    }
 +
 +    if (is_sdvo)
 +	adpa = ADPA_DAC_DISABLE;
 +    else
 +	adpa = ADPA_DAC_ENABLE;
 +    if (pMode->Flags & V_PHSYNC)
 +	adpa |= ADPA_HSYNC_ACTIVE_HIGH;
 +    if (pMode->Flags & V_PVSYNC)
 +	adpa |= ADPA_VSYNC_ACTIVE_HIGH;
 +    
 +    if (pipe == 0) {
 +	dspcntr |= DISPPLANE_SEL_PIPE_A;
 +	adpa |= ADPA_PIPE_A_SELECT;
 +    } else {
 +	dspcntr |= DISPPLANE_SEL_PIPE_B;
 +	adpa |= ADPA_PIPE_B_SELECT;
 +    }
 +
 +    OUTREG(VGACNTRL, VGA_DISP_DISABLE);
 +
 +    /* Set up display timings and PLLs for the pipe. */
 +    if (pipe == 0) {
 +	/* First, disable display planes */
 +	temp = INREG(DSPACNTR);
 +	OUTREG(DSPACNTR, temp & ~DISPLAY_PLANE_ENABLE);
 +
 +	/* Wait for vblank for the disable to take effect */
 +	i830WaitForVblank(pScrn);
 +
 +	/* Next, disable display pipes */
 +	temp = INREG(PIPEACONF);
 +	OUTREG(PIPEACONF, temp & ~PIPEACONF_ENABLE);
 +
 +	OUTREG(FPA0, fp);
 +	OUTREG(DPLL_A, dpll);
 +
 +	OUTREG(HTOTAL_A, htot);
 +	OUTREG(HBLANK_A, hblank);
 +	OUTREG(HSYNC_A, hsync);
 +	OUTREG(VTOTAL_A, vtot);
 +	OUTREG(VBLANK_A, vblank);
 +	OUTREG(VSYNC_A, vsync);
 +	OUTREG(DSPASTRIDE, pScrn->displayWidth * pI830->cpp);
 +	OUTREG(DSPASIZE, dspsize);
 +	OUTREG(DSPAPOS, 0);
 +	i830PipeSetBase(pScrn, pipe, pI830->pipeX[pipe], pI830->pipeX[pipe]);
 +	OUTREG(PIPEASRC, pipesrc);
 +
 +	/* Then, turn the pipe on first */
 +	temp = INREG(PIPEACONF);
 +	OUTREG(PIPEACONF, temp | PIPEACONF_ENABLE);
 +
 +	/* And then turn the plane on */
 +	OUTREG(DSPACNTR, dspcntr);
 +    } else {
 +	/* Always make sure the LVDS is off before we play with DPLLs and pipe
 +	 * configuration.
 +	 */
 +	i830SetLVDSPanelPower(pScrn, FALSE);
 +
 +	/* First, disable display planes */
 +	temp = INREG(DSPBCNTR);
 +	OUTREG(DSPBCNTR, temp & ~DISPLAY_PLANE_ENABLE);
 +
 +	/* Wait for vblank for the disable to take effect */
 +	i830WaitForVblank(pScrn);
 +
 +	/* Next, disable display pipes */
 +	temp = INREG(PIPEBCONF);
 +	OUTREG(PIPEBCONF, temp & ~PIPEBCONF_ENABLE);
 +
 +	if (outputs & PIPE_LCD_ACTIVE) {
 +	    /* Disable the PLL before messing with LVDS enable */
 +	    OUTREG(FPB0, fp & ~DPLL_VCO_ENABLE);
 +
 +	    /* LVDS must be powered on before PLL is enabled and before power
 +	     * sequencing the panel.
 +	     */
 +	    temp = INREG(LVDS);
 +	    OUTREG(LVDS, temp | LVDS_PORT_EN | LVDS_PIPEB_SELECT);
 +	}
 +
 +	OUTREG(FPB0, fp);
 +	OUTREG(DPLL_B, dpll);
 +	OUTREG(HTOTAL_B, htot);
 +	OUTREG(HBLANK_B, hblank);
 +	OUTREG(HSYNC_B, hsync);
 +	OUTREG(VTOTAL_B, vtot);
 +	OUTREG(VBLANK_B, vblank);
 +	OUTREG(VSYNC_B, vsync);
 +	OUTREG(DSPBSTRIDE, pScrn->displayWidth * pI830->cpp);
 +	OUTREG(DSPBSIZE, dspsize);
 +	OUTREG(DSPBPOS, 0);
 +	i830PipeSetBase(pScrn, pipe, pI830->pipeX[pipe], pI830->pipeY[pipe]);
 +	OUTREG(PIPEBSRC, pipesrc);
 +
 +	if (outputs & PIPE_LCD_ACTIVE) {
 +	    CARD32  pfit_control;
 +	    
 +	    /* Enable automatic panel scaling so that non-native modes fill the
 +	     * screen.
 +	     */
 +	    /* XXX: Allow (auto-?) enabling of 8-to-6 dithering */
 +	    pfit_control = (PFIT_ENABLE |
 +			    VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
 +			    VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR);
 +	    if (pI830->panel_wants_dither)
 +		pfit_control |= PANEL_8TO6_DITHER_ENABLE;
 +	    OUTREG(PFIT_CONTROL, pfit_control);
 +	}
 +
 +	/* Then, turn the pipe on first */
 +	temp = INREG(PIPEBCONF);
 +	OUTREG(PIPEBCONF, temp | PIPEBCONF_ENABLE);
 +
 +	/* And then turn the plane on */
 +	OUTREG(DSPBCNTR, dspcntr);
 +
 +	if (outputs & PIPE_LCD_ACTIVE) {
 +	    i830SetLVDSPanelPower(pScrn, TRUE);
 +	}
 +    }
 +
 +    if (outputs & PIPE_CRT_ACTIVE)
 +	OUTREG(ADPA, adpa);
 +
 +    if (is_dvo) {
 +	/*OUTREG(DVOB_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
 +	    (pMode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));*/
 +	OUTREG(DVOC_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
 +	    (pMode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));
 +	/*OUTREG(DVOB, dvo);*/
 +	OUTREG(DVOC, dvo);
 +    }
 +
 +    if (is_sdvo) {
 +	OUTREG(SDVOB, sdvob);
 +	OUTREG(SDVOC, sdvoc);
 +    }
 +
 +    if (outputs & PIPE_LCD_ACTIVE) {
 +	pI830->pipeCurMode[pipe] = *pMasterMode;
 +    } else {
 +	pI830->pipeCurMode[pipe] = *pMode;
 +    }
 +
 +    return TRUE;
 +}
 +
 +void
 +i830DisableUnusedFunctions(ScrnInfoPtr pScrn)
 +{
 +    I830Ptr pI830 = I830PTR(pScrn);
 +    int outputsA, outputsB;
 +
 +    outputsA = pI830->operatingDevices & 0xff;
 +    outputsB = (pI830->operatingDevices >> 8) & 0xff;
 +
 +    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling unused functions\n");
 +
 +    /* First, disable the unused outputs */
 +    if ((outputsA & PIPE_CRT_ACTIVE) == 0 &&
 +	(outputsB & PIPE_CRT_ACTIVE) == 0)
 +    {
 +	CARD32 adpa = INREG(ADPA);
 +
 +	if (adpa & ADPA_DAC_ENABLE) {
 +	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling CRT output\n");
 +	    OUTREG(ADPA, adpa & ~ADPA_DAC_ENABLE);
 +	}
 +    }
 +
 +    if ((outputsB & PIPE_LCD_ACTIVE) == 0) {
 +	CARD32 pp_status = INREG(PP_STATUS);
 +
 +	if (pp_status & PP_ON) {
 +	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling LVDS output\n");
 +	    i830SetLVDSPanelPower(pScrn, FALSE);
 +	}
 +    }
 +
 +    if (IS_I9XX(pI830) && ((outputsA & PIPE_DFP_ACTIVE) == 0 &&
 +	(outputsB & PIPE_DFP_ACTIVE) == 0))
 +    {
 +	CARD32 sdvob = INREG(SDVOB);
 +	CARD32 sdvoc = INREG(SDVOC);
 +
 +	if (sdvob & SDVO_ENABLE) {
 +	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling SDVOB output\n");
 +	    OUTREG(SDVOB, sdvob & ~SDVO_ENABLE);
 +	}
 +	if (sdvoc & SDVO_ENABLE) {
 +	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling SDVOC output\n");
 +	    OUTREG(SDVOC, sdvoc & ~SDVO_ENABLE);
 +	}
 +    }
 +
 +    /* 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.
 +     */
 +    if (!pI830->planeEnabled[0]) {
 +	CARD32 dspcntr, pipeconf, dpll;
 +
 +	dspcntr = INREG(DSPACNTR);
 +	if (dspcntr & DISPLAY_PLANE_ENABLE) {
 +	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling plane A\n");
 +	    OUTREG(DSPACNTR, dspcntr & ~DISPLAY_PLANE_ENABLE);
 +
 +	    /* Wait for vblank for the disable to take effect */
 +	    i830WaitForVblank(pScrn);
 +	}
 +
 +	pipeconf = INREG(PIPEACONF);
 +	if (pipeconf & PIPEACONF_ENABLE) {
 +	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling pipe A\n");
 +	   OUTREG(PIPEACONF, pipeconf & ~PIPEACONF_ENABLE);
 +	}
 +
 +	dpll = INREG(DPLL_A);
 +	if (dpll & DPLL_VCO_ENABLE) {
 +	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling DPLL A\n");
 +	    OUTREG(DPLL_A, dpll & ~DPLL_VCO_ENABLE);
 +	}
 +
 +	memset(&pI830->pipeCurMode[0], 0, sizeof(pI830->pipeCurMode[0]));
 +    }
 +
 +    if (!pI830->planeEnabled[1]) {
 +	CARD32 dspcntr, pipeconf, dpll;
 +
 +	dspcntr = INREG(DSPBCNTR);
 +	if (dspcntr & DISPLAY_PLANE_ENABLE) {
 +	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling plane B\n");
 +	    OUTREG(DSPBCNTR, dspcntr & ~DISPLAY_PLANE_ENABLE);
 +
 +	    /* Wait for vblank for the disable to take effect */
 +	    i830WaitForVblank(pScrn);
 +	}
 +
 +	pipeconf = INREG(PIPEBCONF);
 +	if (pipeconf & PIPEBCONF_ENABLE) {
 +	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling pipe B\n");
 +	   OUTREG(PIPEBCONF, pipeconf & ~PIPEBCONF_ENABLE);
 +	}
 +
 +	dpll = INREG(DPLL_B);
 +	if (dpll & DPLL_VCO_ENABLE) {
 +	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling DPLL B\n");
 +	    OUTREG(DPLL_B, dpll & ~DPLL_VCO_ENABLE);
 +	}
 +
 +	memset(&pI830->pipeCurMode[1], 0, sizeof(pI830->pipeCurMode[1]));
 +    }
 +}
 +
 +/**
 + * This function sets the given mode on the active pipes.
 + */
 +Bool
 +i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
 +{
 +    I830Ptr pI830 = I830PTR(pScrn);
 +    Bool ok = TRUE;
 +    CARD32 planeA, planeB;
 +#ifdef XF86DRI
 +    Bool didLock = FALSE;
 +#endif
 +    int i;
 +
 +    DPRINTF(PFX, "i830SetMode\n");
 +
 +#ifdef XF86DRI
 +    didLock = I830DRILock(pScrn);
 +#endif
 +
 +    if (pI830->operatingDevices & 0xff) {
 +	pI830->planeEnabled[0] = 1;
 +    } else {
 +	pI830->planeEnabled[0] = 0;
 +    }
 +
 +    if (pI830->operatingDevices & 0xff00) {
 +	pI830->planeEnabled[1] = 1;
 +    } else {
 +	pI830->planeEnabled[1] = 0;
 +    }
 +
 +    for (i = 0; i < pI830->num_outputs; i++) {
 +	struct _I830OutputRec *output = &pI830->output[i];
 +
 +	if (output->sdvo_drv)
 +	    I830SDVOPreSetMode(output->sdvo_drv, pMode);
 +
 +	if (output->i2c_drv != NULL)
 +	    output->i2c_drv->vid_rec->Mode(output->i2c_drv->dev_priv,
 +					   pMode);
 +    }
 +
 +    if (pI830->planeEnabled[0]) {
 +	ok = i830PipeSetMode(pScrn, pMode, 0);
 +	if (!ok)
 +	    goto done;
 +    }
 +    if (pI830->planeEnabled[1]) {
 +	ok = i830PipeSetMode(pScrn, pMode, 1);
 +	if (!ok)
 +	    goto done;
 +    }
 +    for (i = 0; i < pI830->num_outputs; i++) {
 +	if (pI830->output[i].sdvo_drv)
 +	    I830SDVOPostSetMode(pI830->output[i].sdvo_drv, pMode);
 +    }
 +
 +    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Mode bandwidth is %d Mpixel/s\n",
 +	       (int)(pMode->HDisplay * pMode->VDisplay *
 +		     pMode->VRefresh / 1000000));
 +
 +    if (pI830->savedCurrentMode) {
 +	/* We're done with the currentMode that the last randr probe had left
 +	 * behind, so free it.
 +	 */
 +	xfree(pI830->savedCurrentMode->name);
 +	xfree(pI830->savedCurrentMode);
 +	pI830->savedCurrentMode = NULL;
 +	    
 +	/* If we might have enabled/disabled some pipes, we need to reset
 +	 * cloning mode support.
 +	 */
 +	if ((pI830->operatingDevices & 0x00ff) &&
 +	    (pI830->operatingDevices & 0xff00))
 +	{
 +	    pI830->Clone = TRUE;
 +	} else {
 +	    pI830->Clone = FALSE;
 +	}
 +
 +	/* If HW cursor currently showing, reset cursor state */
 +	if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn)
 +	    pI830->CursorInfoRec->ShowCursor(pScrn);
 +    }
 +
 +    i830DisableUnusedFunctions(pScrn);
 +
 +    planeA = INREG(DSPACNTR);
 +    planeB = INREG(DSPBCNTR);
 +
 +    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 +	       "Display plane A is now %s and connected to %s.\n",
 +	       pI830->planeEnabled[0] ? "enabled" : "disabled",
 +	       planeA & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A");
 +    if (pI830->availablePipes == 2)
 +	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 +		   "Display plane B is now %s and connected to %s.\n",
 +		   pI830->planeEnabled[1] ? "enabled" : "disabled",
 +		   planeB & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A");
 +
 +#ifdef XF86DRI
 +   I830DRISetVBlankInterrupt (pScrn, TRUE);
 +#endif
 +done:
 +#ifdef XF86DRI
 +    if (didLock)
 +	I830DRIUnlock(pScrn);
 +#endif
 +
 +    i830DumpRegs (pScrn);
 +    I830DumpSDVO (pScrn);
 +    return ok;
 +}
 +
 +/**
 + * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence.
 + *
 + * Only for I945G/GM.
 + */
 +static Bool
 +i830HotplugDetectCRT(ScrnInfoPtr pScrn)
 +{
 +    I830Ptr pI830 = I830PTR(pScrn);
 +    CARD32 temp;
 +    const int timeout_ms = 1000;
 +    int starttime, curtime;
 +
 +    temp = INREG(PORT_HOTPLUG_EN);
 +
 +    OUTREG(PORT_HOTPLUG_EN, temp | CRT_HOTPLUG_FORCE_DETECT | (1 << 5));
 +
 +    for (curtime = starttime = GetTimeInMillis();
 +	 (curtime - starttime) < timeout_ms; curtime = GetTimeInMillis())
 +    {
 +	if ((INREG(PORT_HOTPLUG_EN) & CRT_HOTPLUG_FORCE_DETECT) == 0)
 +	    break;
 +    }
 +
 +    if ((INREG(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_MONITOR_MASK) ==
 +	CRT_HOTPLUG_MONITOR_COLOR)
 +    {
 +	return TRUE;
 +    } else {
 +	return FALSE;
 +    }
 +}
 +
 +/**
 + * Detects CRT presence by checking for load.
 + *
 + * Requires that the current pipe's DPLL is active.  This will cause flicker
 + * on the CRT, so it should not be used while the display is being used.  Only
 + * color (not monochrome) displays are detected.
 + */
 +static Bool
 +i830LoadDetectCRT(ScrnInfoPtr pScrn)
 +{
 +    I830Ptr pI830 = I830PTR(pScrn);
 +    CARD32 adpa, pipeconf;
 +    CARD8 st00;
 +    int pipeconf_reg, bclrpat_reg, dpll_reg;
 +    int pipe;
 +
 +    pipe = pI830->pipe;
 +    if (pipe == 0) {
 +	bclrpat_reg = BCLRPAT_A;
 +	pipeconf_reg = PIPEACONF;
 +	dpll_reg = DPLL_A;
 +    } else {
 +	bclrpat_reg = BCLRPAT_B;
 +	pipeconf_reg = PIPEBCONF;
 +	dpll_reg = DPLL_B;
 +    }
 +
 +    /* Don't try this if the DPLL isn't running. */
 +    if (!(INREG(dpll_reg) & DPLL_VCO_ENABLE))
 +	return FALSE;
 +
 +    adpa = INREG(ADPA);
 +
 +    /* Enable CRT output if disabled. */
 +    if (!(adpa & ADPA_DAC_ENABLE)) {
 +	OUTREG(ADPA, adpa | ADPA_DAC_ENABLE |
 +	       ((pipe == 1) ? ADPA_PIPE_B_SELECT : 0));
 +    }
 +
 +    /* Set the border color to red, green.  Maybe we should save/restore this
 +     * reg.
 +     */
 +    OUTREG(bclrpat_reg, 0x00500050);
 +
 +    /* Force the border color through the active region */
 +    pipeconf = INREG(pipeconf_reg);
 +    OUTREG(pipeconf_reg, pipeconf | PIPECONF_FORCE_BORDER);
 +
 +    /* Read the ST00 VGA status register */
 +    st00 = pI830->readStandard(pI830, 0x3c2);
 +
 +    /* Restore previous settings */
 +    OUTREG(pipeconf_reg, pipeconf);
 +    OUTREG(ADPA, adpa);
 +
 +    if (st00 & (1 << 4))
 +	return TRUE;
 +    else
 +	return FALSE;
 +}
 +
 +/**
 + * Detects CRT presence by probing for a response on the DDC address.
 + *
 + * This takes approximately 5ms in testing on an i915GM, with CRT connected or
 + * not.
 + */
 +static Bool
 +i830DDCDetectCRT(ScrnInfoPtr pScrn)
 +{
 +    I830Ptr pI830 = I830PTR(pScrn);
 +    struct _I830OutputRec *output;
 +
 +    output = &pI830->output[0];
 +    /* CRT should always be at 0, but check anyway */
 +    if (output->type != I830_OUTPUT_ANALOG)
 +	return FALSE;
 +
 +    return xf86I2CProbeAddress(output->pDDCBus, 0x00A0);
 +}
 +
 +/**
 + * Attempts to detect CRT presence through any method available.
 + *
 + * @param allow_disturb enables detection methods that may cause flickering
 + *        on active displays.
 + */
 +Bool
 +i830DetectCRT(ScrnInfoPtr pScrn, Bool allow_disturb)
 +{
 +    I830Ptr pI830 = I830PTR(pScrn);
 +    Bool found_ddc;
 +
 +    if (IS_I945G(pI830) || IS_I945GM(pI830))
 +	return i830HotplugDetectCRT(pScrn);
 +
 +    found_ddc = i830DDCDetectCRT(pScrn);
 +    if (found_ddc)
 +	return TRUE;
 +
 +    /* Use the load-detect method if we're not currently outputting to the CRT,
 +     * or we don't care.
 +     *
 +     * Actually, the method is unreliable currently.  We need to not share a
 +     * pipe, as it seems having other outputs on that pipe will result in a
 +     * false positive.
 +     */
 +    if (0 && (allow_disturb || !(INREG(ADPA) & !ADPA_DAC_ENABLE))) {
 +	return i830LoadDetectCRT(pScrn);
 +    }
 +
 +    return FALSE;
 +}
 +
 +/**
 + * Sets the power state for the panel.
 + */
 +void
 +i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on)
 +{
 +    I830Ptr pI830 = I830PTR(pScrn);
 +    CARD32 pp_status, pp_control;
 +    CARD32 blc_pwm_ctl;
 +    int backlight_duty_cycle;
 +
 +    blc_pwm_ctl = INREG (BLC_PWM_CTL);
 +    backlight_duty_cycle = blc_pwm_ctl & BACKLIGHT_DUTY_CYCLE_MASK;
 +    if (backlight_duty_cycle)
 +        pI830->backlight_duty_cycle = backlight_duty_cycle;
 +    
 +    if (on) {
 +	OUTREG(PP_STATUS, INREG(PP_STATUS) | PP_ON);
 +	OUTREG(PP_CONTROL, INREG(PP_CONTROL) | POWER_TARGET_ON);
 +	do {
 +	    pp_status = INREG(PP_STATUS);
 +	    pp_control = INREG(PP_CONTROL);
 +	} while (!(pp_status & PP_ON) && !(pp_control & POWER_TARGET_ON));
 +	OUTREG(BLC_PWM_CTL,
 +	       (blc_pwm_ctl & ~BACKLIGHT_DUTY_CYCLE_MASK) |
 +	       pI830->backlight_duty_cycle);
 +    } else {
 +	OUTREG(BLC_PWM_CTL,
 +	       (blc_pwm_ctl & ~BACKLIGHT_DUTY_CYCLE_MASK));
 +	       
 +	OUTREG(PP_STATUS, INREG(PP_STATUS) & ~PP_ON);
 +	OUTREG(PP_CONTROL, INREG(PP_CONTROL) & ~POWER_TARGET_ON);
 +	do {
 +	    pp_status = INREG(PP_STATUS);
 +	    pp_control = INREG(PP_CONTROL);
 +	} while ((pp_status & PP_ON) || (pp_control & POWER_TARGET_ON));
 +    }
 +}
diff --cc src/i830_driver.c
index b4f5394,ffa93f8..d46fc1b
@@@ -161,9 -166,9 +166,10 @@@
  #endif
  
  #include <string.h>
+ #include <stdio.h>
  #include <unistd.h>
  #include <stdlib.h>
 +#include <stdio.h>
  
  #include "xf86.h"
  #include "xf86_OSproc.h"
@@@ -182,12 -188,12 +189,11 @@@
  #include "xf86xv.h"
  #include <X11/extensions/Xv.h>
  #include "vbe.h"
- #include "vbeModes.h"
  #include "shadow.h"
  #include "i830.h"
 -
 -#ifdef HAS_MTRR_SUPPORT
 -#include <asm/mtrr.h>
 -#endif
 +#include "i830_display.h"
 +#include "i830_debug.h"
 +#include "i830_bios.h"
  
  #ifdef XF86DRI
  #include "dri.h"
@@@ -248,10 -262,16 +262,10 @@@
     OPTION_CHECKDEVICES,
     OPTION_FIXEDPIPE,
     OPTION_ROTATE,
-    OPTION_LINEARALLOC
+    OPTION_LINEARALLOC,
 -   OPTION_MERGEDFB,
 -   OPTION_METAMODES,
 -   OPTION_SECONDHSYNC,
 -   OPTION_SECONDVREFRESH,
 -   OPTION_SECONDPOSITION,
 -   OPTION_INTELXINERAMA
  } I830Opts;
  
 -static OptionInfoRec I830BIOSOptions[] = {
 +static OptionInfoRec I830Options[] = {
     {OPTION_NOACCEL,	"NoAccel",	OPTV_BOOLEAN,	{0},	FALSE},
     {OPTION_SW_CURSOR,	"SWcursor",	OPTV_BOOLEAN,	{0},	FALSE},
     {OPTION_CACHE_LINES,	"CacheLines",	OPTV_INTEGER,	{0},	FALSE},
@@@ -298,7 -316,22 +312,6 @@@
 -static Bool 		I830noPanoramiXExtension = TRUE;
 -static int		I830XineramaNumScreens = 0;
 -static I830XineramaData	*I830XineramadataPtr = NULL;
 -static int		I830XineramaGeneration;
 -
 -static int I830ProcXineramaQueryVersion(ClientPtr client);
 -static int I830ProcXineramaGetState(ClientPtr client);
 -static int I830ProcXineramaGetScreenCount(ClientPtr client);
 -static int I830ProcXineramaGetScreenSize(ClientPtr client);
 -static int I830ProcXineramaIsActive(ClientPtr client);
 -static int I830ProcXineramaQueryScreens(ClientPtr client);
 -static int I830SProcXineramaDispatch(ClientPtr client);
 -
  /* temporary */
  extern void xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y);
  
- 
 -static const char *SecondMonitorName = "MergedFBMonitor";
 -
 -
  #ifdef I830DEBUG
  void
  I830DPRINTF_stub(const char *filename, int line, const char *function,
@@@ -353,7 -386,7 +366,6 @@@
  {
     I830Ptr pI830;
     VESAPtr pVesa;
--   DisplayModePtr mode;
  
     if (!pScrn)
        return;
@@@ -361,21 -394,19 +373,6 @@@
        return;
  
     pI830 = I830PTR(pScrn);
--   mode = pScrn->modes;
--
--   if (mode) {
--      do {
--	 if (mode->Private) {
- 	    VbeModeInfoData *data = (VbeModeInfoData *) mode->Private;
- 
- 	    if (data->block)
- 	       xfree(data->block);
- 	    xfree(data);
- 	    mode->Private = NULL;
- 	 }
- 	 mode = mode->next;
-       } while (mode && mode != pScrn->modes);
-    }
 -	    I830ModePrivatePtr mp = (I830ModePrivatePtr) mode->Private;
 -
 -	    xfree(mp);
 -	    mode->Private = NULL;
 -	 }
 -	 mode = mode->next;
 -      } while (mode && mode != pScrn->modes);
 -   }
  
     if (I830IsPrimary(pScrn)) {
        if (pI830->vbeInfo)
@@@ -395,224 -424,2664 +390,220 @@@
     pScrn->driverPrivate = NULL;
  }
  
 -static Bool
 -InRegion(int x, int y, region r)
 -{
 -    return (r.x0 <= x) && (x <= r.x1) && (r.y0 <= y) && (y <= r.y1);
 -}
 -
 -static int
 -I830StrToRanges(range *r, char *s, int max)
 +static void
 +I830ProbeDDC(ScrnInfoPtr pScrn, int index)
  {
 -   float num = 0.0;
 -   int rangenum = 0;
 -   Bool gotdash = FALSE;
 -   Bool nextdash = FALSE;
 -   char *strnum = NULL;
 -   do {
 -      switch(*s) {
 -      case '0':
 -      case '1':
 -      case '2':
 -      case '3':
 -      case '4':
 -      case '5':
 -      case '6':
 -      case '7':
 -      case '8':
 -      case '9':
 -      case '.':
 -         if(strnum == NULL) {
 -            strnum = s;
 -            gotdash = nextdash;
 -            nextdash = FALSE;
 -         }
 -         break;
 -      case '-':
 -      case ' ':
 -      case 0:
 -         if(strnum == NULL) break;
 -         sscanf(strnum, "%f", &num);
 -	 strnum = NULL;
 -         if(gotdash) {
 -            r[rangenum - 1].hi = num;
 -         } else {
 -            r[rangenum].lo = num;
 -            r[rangenum].hi = num;
 -            rangenum++;
 -         }
 -         if(*s == '-') nextdash = (rangenum != 0);
 -	 else if(rangenum >= max) return rangenum;
 -         break;
 -      default:
 -         return 0;
 -      }
 +   vbeInfoPtr pVbe;
  
 -   } while(*(s++) != 0);
 +   /* The vbe module gets loaded in PreInit(), so no need to load it here. */
  
 -   return rangenum;
 +   pVbe = VBEInit(NULL, index);
 +   ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
  }
  
 -/* Calculate the vertical refresh rate from a mode */
 -static float
 -I830CalcVRate(DisplayModePtr mode)
 -{
 -   float hsync, refresh = 0;
 -
 -   if(mode->HSync > 0.0)
 -       	hsync = mode->HSync;
 -   else if(mode->HTotal > 0)
 -       	hsync = (float)mode->Clock / (float)mode->HTotal;
 -   else
 -       	hsync = 0.0;
 -
 -   if(mode->VTotal > 0)
 -       	refresh = hsync * 1000.0 / mode->VTotal;
 -
 -   if(mode->Flags & V_INTERLACE)
 -       	refresh *= 2.0;
 -
 -   if(mode->Flags & V_DBLSCAN)
 -       	refresh /= 2.0;
 -
 -   if(mode->VScan > 1)
 -        refresh /= mode->VScan;
 -
 -   if(mode->VRefresh > 0.0)
 -	refresh = mode->VRefresh;
 -
 -   if(hsync == 0.0 || refresh == 0.0) return 0.0;
 +/* Various extended video BIOS functions. 
 + * 100 and 120Hz aren't really supported, they work but only get close
 + * to the requested refresh, and really not close enough.
 + * I've seen 100Hz come out at 104Hz, and 120Hz come out at 128Hz */
 +const int i830refreshes[] = {
 +   43, 56, 60, 70, 72, 75, 85 /* 100, 120 */
 +};
 +static const int nrefreshes = sizeof(i830refreshes) / sizeof(i830refreshes[0]);
  
 -   return refresh;
 +static Bool
 +Check5fStatus(ScrnInfoPtr pScrn, int func, int ax)
 +{
 +   if (ax == 0x005f)
 +      return TRUE;
 +   else if (ax == 0x015f) {
 +      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 +		 "Extended BIOS function 0x%04x failed.\n", func);
 +      return FALSE;
 +   } else if ((ax & 0xff) != 0x5f) {
 +      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 +		 "Extended BIOS function 0x%04x not supported.\n", func);
 +      return FALSE;
 +   } else {
 +      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 +		 "Extended BIOS function 0x%04x returns 0x%04x.\n",
 +		 func, ax & 0xffff);
 +      return FALSE;
 +   }
  }
  
 -/* Copy and link two modes (i, j) for mergedfb mode
 - * (Code base taken from mga driver)
 - *
 - * - Copy mode i, merge j to copy of i, link the result to dest
 - * - Link i and j in private record.
 - * - If dest is NULL, return value is copy of i linked to itself.
 - * - For mergedfb auto-config, we only check the dimension
 - *   against virtualX/Y, if they were user-provided.
 - * - No special treatment required for CRTxxOffs.
 - * - Provide fake dotclock in order to distinguish between similar
 - *   looking MetaModes (for RandR and VidMode extensions)
 - * - Set unique VRefresh of dest mode for RandR
 - */
 -static DisplayModePtr
 -I830CopyModeNLink(ScrnInfoPtr pScrn, DisplayModePtr dest,
 -                 DisplayModePtr i, DisplayModePtr j,
 -		 int pos)
 -{
 -    DisplayModePtr mode;
 -    int dx = 0,dy = 0;
 -
 -    if(!((mode = xalloc(sizeof(DisplayModeRec))))) return dest;
 -    memcpy(mode, i, sizeof(DisplayModeRec));
 -    if(!((mode->Private = xalloc(sizeof(I830ModePrivateRec))))) {
 -       xfree(mode);
 -       return dest;
 -    }
 -    ((I830ModePrivatePtr)mode->Private)->merged.First = i;
 -    ((I830ModePrivatePtr)mode->Private)->merged.Second = j;
 -    ((I830ModePrivatePtr)mode->Private)->merged.SecondPosition = pos;
 -    if (((I830ModePrivatePtr)i->Private)->vbeData.mode > 0x30) {
 -       ((I830ModePrivatePtr)mode->Private)->vbeData.mode = ((I830ModePrivatePtr)i->Private)->vbeData.mode;
 -       ((I830ModePrivatePtr)mode->Private)->vbeData.data = ((I830ModePrivatePtr)i->Private)->vbeData.data;
 -    } else {
 -       ((I830ModePrivatePtr)mode->Private)->vbeData.mode = ((I830ModePrivatePtr)j->Private)->vbeData.mode;
 -       ((I830ModePrivatePtr)mode->Private)->vbeData.data = ((I830ModePrivatePtr)j->Private)->vbeData.data;
 -    }
 -    mode->PrivSize = sizeof(I830ModePrivateRec);
 +struct panelid {
 +	short hsize;
 +	short vsize;
 +	short fptype;
 +	char redbpp;
 +	char greenbpp;
 +	char bluebpp;
 +	char reservedbpp;
 +	int rsvdoffscrnmemsize;
 +	int rsvdoffscrnmemptr;
 +	char reserved[14];
 +};
  
 -    switch(pos) {
 -    case PosLeftOf:
 -    case PosRightOf:
 -       if(!(pScrn->display->virtualX)) {
 -          dx = i->HDisplay + j->HDisplay;
 -       } else {
 -          dx = min(pScrn->virtualX, i->HDisplay + j->HDisplay);
 -       }
 -       dx -= mode->HDisplay;
 -       if(!(pScrn->display->virtualY)) {
 -          dy = max(i->VDisplay, j->VDisplay);
 -       } else {
 -          dy = min(pScrn->virtualY, max(i->VDisplay, j->VDisplay));
 -       }
 -       dy -= mode->VDisplay;
 -       break;
 -    case PosAbove:
 -    case PosBelow:
 -       if(!(pScrn->display->virtualY)) {
 -          dy = i->VDisplay + j->VDisplay;
 -       } else {
 -          dy = min(pScrn->virtualY, i->VDisplay + j->VDisplay);
 -       }
 -       dy -= mode->VDisplay;
 -       if(!(pScrn->display->virtualX)) {
 -          dx = max(i->HDisplay, j->HDisplay);
 -       } else {
 -          dx = min(pScrn->virtualX, max(i->HDisplay, j->HDisplay));
 -       }
 -       dx -= mode->HDisplay;
 -       break;
 -    }
 -    mode->HDisplay += dx;
 -    mode->HSyncStart += dx;
 -    mode->HSyncEnd += dx;
 -    mode->HTotal += dx;
 -    mode->VDisplay += dy;
 -    mode->VSyncStart += dy;
 -    mode->VSyncEnd += dy;
 -    mode->VTotal += dy;
 -
 -    mode->type = M_T_DEFAULT;
 -
 -    /* Set up as user defined (ie fake that the mode has been named in the
 -     * Modes-list in the screen section; corrects cycling with CTRL-ALT-[-+]
 -     * when source mode has not been listed there.)
 -     */
 -    mode->type |= M_T_USERDEF;
 -
 -    /* Set the VRefresh field (in order to make RandR use it for the rates). We
 -     * simply set this to the refresh rate for the First mode (since Second will
 -     * mostly be LCD or TV anyway).
 -     */
 -    mode->VRefresh = I830CalcVRate(i);
 -
 -    if( ((mode->HDisplay * ((pScrn->bitsPerPixel + 7) / 8) * mode->VDisplay) > (pScrn->videoRam * 1024)) ||
 -	(mode->HDisplay > 4088) ||
 -	(mode->VDisplay > 4096) ) {
 -
 -       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 -		"Skipped \"%s\" (%dx%d), not enough video RAM or beyond hardware specs\n",
 -		mode->name, mode->HDisplay, mode->VDisplay);
 -       xfree(mode->Private);
 -       xfree(mode);
 +static Bool
 +SetBIOSPipe(ScrnInfoPtr pScrn, int pipe)
 +{
 +   I830Ptr pI830 = I830PTR(pScrn);
 +   vbeInfoPtr pVbe = pI830->pVbe;
  
 -       return dest;
 -    }
 +   DPRINTF(PFX, "SetBIOSPipe: pipe 0x%x\n", pipe);
  
 -    /* Now see if the resulting mode would be discarded as a "size" by the
 -     * RandR extension, and increase its clock by 1000 in case it does.
 -     */
 -    if(dest) {
 -       DisplayModePtr t = dest;
 -       do {
 -          if((t->HDisplay == mode->HDisplay) &&
 -	     (t->VDisplay == mode->VDisplay) &&
 -	     ((int)(t->VRefresh + .5) == (int)(mode->VRefresh + .5))) {
 -	     mode->VRefresh += 1000.0;
 -	  }
 -	  t = t->next;
 -       } while((t) && (t != dest));
 -    }
 +   /* single pipe machines should always return TRUE */
 +   if (pI830->availablePipes == 1) return TRUE;
  
 -    /* Provide a fake but unique DotClock in order to trick the vidmode
 -     * extension to allow selecting among a number of modes whose merged result
 -     * looks identical but consists of different modes for First and Second
 -     */
 -    mode->Clock = (int)(mode->VRefresh * 1000.0);
 -
 -    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 -	"Merged \"%s\" (%dx%d) and \"%s\" (%dx%d) to %dx%d (%d)\n",
 -	i->name, i->HDisplay, i->VDisplay, j->name, j->HDisplay, j->VDisplay,
 -	mode->HDisplay, mode->VDisplay, (int)mode->VRefresh);
 -
 -    mode->next = mode;
 -    mode->prev = mode;
 -
 -    if(dest) {
 -       mode->next = dest->next; 	/* Insert node after "dest" */
 -       dest->next->prev = mode;
 -       mode->prev = dest;
 -       dest->next = mode;
 -    }
 +   pVbe->pInt10->num = 0x10;
 +   pVbe->pInt10->ax = 0x5f1c;
 +   if (pI830->newPipeSwitch) {
 +      pVbe->pInt10->bx = pipe;
 +      pVbe->pInt10->cx = 0;
 +   } else {
 +      pVbe->pInt10->bx = 0x0;
 +      pVbe->pInt10->cx = pipe << 8;
 +   }
  
 -    return mode;
 +   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
 +   if (Check5fStatus(pScrn, 0x5f1c, pVbe->pInt10->ax)) {
 +      return TRUE;
 +   }
 +	
 +   return FALSE;
  }
  
 -/* Helper function to find a mode from a given name
 - * (Code base taken from mga driver)
 - */
 -static DisplayModePtr
 -I830GetModeFromName(char* str, DisplayModePtr i)
 +static Bool
 +SetPipeAccess(ScrnInfoPtr pScrn)
  {
 -    DisplayModePtr c = i;
 -    if(!i) return NULL;
 -    do {
 -       if(strcmp(str, c->name) == 0) return c;
 -       c = c->next;
 -    } while(c != i);
 -    return NULL;
 -}
 -
 -static DisplayModePtr
 -I830FindWidestTallestMode(DisplayModePtr i, Bool tallest)
 -{
 -    DisplayModePtr c = i, d = NULL;
 -    int max = 0;
 -    if(!i) return NULL;
 -    do {
 -       if(tallest) {
 -          if(c->VDisplay > max) {
 -	     max = c->VDisplay;
 -	     d = c;
 -          }
 -       } else {
 -          if(c->HDisplay > max) {
 -	     max = c->HDisplay;
 -	     d = c;
 -          }
 -       }
 -       c = c->next;
 -    } while(c != i);
 -    return d;
 +   I830Ptr pI830 = I830PTR(pScrn);
 +
 +   /* Don't try messing with the pipe, unless we're dual head */
 +   if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone || pI830->origPipe != pI830->pipe) {
 +      if (!SetBIOSPipe(pScrn, pI830->pipe))
 +         return FALSE;
 +   }
 +   
 +   return TRUE;
  }
  
 -static void
 -I830FindWidestTallestCommonMode(DisplayModePtr i, DisplayModePtr j, Bool tallest,
 -				DisplayModePtr *a, DisplayModePtr *b)
 +static Bool
 +GetBIOSVersion(ScrnInfoPtr pScrn, unsigned int *version)
  {
 -    DisplayModePtr c = i, d;
 -    int max = 0;
 -    Bool foundone;
 -
 -    (*a) = (*b) = NULL;
 -
 -    if(!i || !j) return;
 -
 -    do {
 -       d = j;
 -       foundone = FALSE;
 -       do {
 -	  if( (c->HDisplay == d->HDisplay) &&
 -	      (c->VDisplay == d->VDisplay) ) {
 -	     foundone = TRUE;
 -	     break;
 -	  }
 -	  d = d->next;
 -       } while(d != j);
 -       if(foundone) {
 -	  if(tallest) {
 -	     if(c->VDisplay > max) {
 -		max = c->VDisplay;
 -		(*a) = c;
 -		(*b) = d;
 -	     }
 -	  } else {
 -	     if(c->HDisplay > max) {
 -		max = c->HDisplay;
 -		(*a) = c;
 -		(*b) = d;
 -	     }
 -	  }
 -       }
 -       c = c->next;
 -    } while(c != i);
 -}
 -
 -static DisplayModePtr
 -I830GenerateModeListFromLargestModes(ScrnInfoPtr pScrn,
 -		    DisplayModePtr i, DisplayModePtr j,
 -		    int pos)
 -{
 -    I830Ptr pI830 = I830PTR(pScrn);
 -    DisplayModePtr mode1 = NULL;
 -    DisplayModePtr mode2 = NULL;
 -    DisplayModePtr mode3 = NULL;
 -    DisplayModePtr mode4 = NULL;
 -    DisplayModePtr result = NULL;
 -
 -    /* Now build a default list of MetaModes.
 -     * - Non-clone: If the user enabled NonRectangular, we use the
 -     * largest mode for each First and Second. If not, we use the largest
 -     * common mode for First and Second (if available). Additionally, and
 -     * regardless if the above, we produce a clone mode consisting of
 -     * the largest common mode (if available) in order to use DGA.
 -     */
 -
 -    switch(pos) {
 -    case PosLeftOf:
 -    case PosRightOf:
 -       mode1 = I830FindWidestTallestMode(i, FALSE);
 -       mode2 = I830FindWidestTallestMode(j, FALSE);
 -       I830FindWidestTallestCommonMode(i, j, FALSE, &mode3, &mode4);
 -       break;
 -    case PosAbove:
 -    case PosBelow:
 -       mode1 = I830FindWidestTallestMode(i, TRUE);
 -       mode2 = I830FindWidestTallestMode(j, TRUE);
 -       I830FindWidestTallestCommonMode(i, j, TRUE, &mode3, &mode4);
 -       break;
 -    }
 +   vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
  
 -    if(mode3 && mode4 && !pI830->NonRect) {
 -       mode1 = mode3;
 -       mode2 = mode2;
 -    }
 +   DPRINTF(PFX, "GetBIOSVersion\n");
  
 -    if(mode1 && mode2) {
 -       result = I830CopyModeNLink(pScrn, result, mode1, mode2, pos);
 -    }
 +   pVbe->pInt10->num = 0x10;
 +   pVbe->pInt10->ax = 0x5f01;
 +
 +   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
 +   if (Check5fStatus(pScrn, 0x5f01, pVbe->pInt10->ax)) {
 +      *version = pVbe->pInt10->bx;
 +      return TRUE;
 +   }
  
 -    return result;
 +   *version = 0;
 +   return FALSE;
  }
  
 -/* Generate the merged-fb mode modelist
 - * (Taken from mga driver)
 +/*
 + * Returns a string matching the device corresponding to the first bit set
 + * in "device".  savedDevice is then set to device with that bit cleared.
 + * Subsequent calls with device == -1 will use savedDevice.
   */
 -static DisplayModePtr
 -I830GenerateModeListFromMetaModes(ScrnInfoPtr pScrn, char* str,
 -		    DisplayModePtr i, DisplayModePtr j,
 -		    int pos)
 -{
 -    char* strmode = str;
 -    char modename[256];
 -    Bool gotdash = FALSE;
 -    char gotsep = 0;
 -    int p; 
 -    DisplayModePtr mode1 = NULL;
 -    DisplayModePtr mode2 = NULL;
 -    DisplayModePtr result = NULL;
 -    int myslen;
 -
 -    do {
 -        switch(*str) {
 -        case 0:
 -        case '-':
 -	case '+':
 -        case ' ':
 -	case ',':
 -	case ';':
 -           if(strmode != str) {
 -
 -              myslen = str - strmode;
 -              if(myslen > 255) myslen = 255;
 -  	      strncpy(modename, strmode, myslen);
 -  	      modename[myslen] = 0;
 -
 -              if(gotdash) {
 -                 if(mode1 == NULL) {
 -  	             xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 -  	                        "Error parsing MetaModes parameter\n");
 -  	             return NULL;
 -  	         }
 -                 mode2 = I830GetModeFromName(modename, j);
 -                 if(!mode2) {
 -                    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -                        "Mode \"%s\" is not a supported mode for Second\n", modename);
 -                    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -                        "\t(Skipping metamode \"%s%c%s\")\n", mode1->name, gotsep, modename);
 -                    mode1 = NULL;
 -		    gotsep = 0;
 -                 }
 -              } else {
 -                 mode1 = I830GetModeFromName(modename, i);
 -                 if(!mode1) {
 -                    char* tmps = str;
 -                    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -                        "Mode \"%s\" is not a supported mode for First\n", modename);
 -                    while(*tmps == ' ' || *tmps == ';') tmps++;
 -                    /* skip the next mode */
 -  	            if(*tmps == '-' || *tmps == '+' || *tmps == ',') {
 -                       tmps++;
 -		       /* skip spaces */
 -		       while(*tmps == ' ' || *tmps == ';') tmps++;
 -		       /* skip modename */
 -		       while(*tmps && *tmps != ' ' && *tmps != ';' && *tmps != '-' && *tmps != '+' && *tmps != ',') tmps++;
 -  	               myslen = tmps - strmode;
 -  	               if(myslen > 255) myslen = 255;
 -  	               strncpy(modename,strmode,myslen);
 -  	               modename[myslen] = 0;
 -                       str = tmps - 1;
 -                    }
 -                    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -                        "\t(Skipping metamode \"%s\")\n", modename);
 -                    mode1 = NULL;
 -		    gotsep = 0;
 -                 }
 -              }
 -              gotdash = FALSE;
 -           }
 -           strmode = str + 1;
 -           gotdash |= (*str == '-' || *str == '+' || *str == ',');
 -	   if (*str == '-' || *str == '+' || *str == ',')
 -  	      gotsep = *str;
 -
 -           if(*str != 0) break;
 -	   /* Fall through otherwise */
 -
 -        default:
 -           if(!gotdash && mode1) {
 -              p = pos ;
 -              if(!mode2) {
 -                 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -                     "Mode \"%s\" is not a supported mode for Second\n", mode1->name);
 -                 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -                     "\t(Skipping metamode \"%s\")\n", modename);
 -                 mode1 = NULL;
 -              } else {
 -                 result = I830CopyModeNLink(pScrn, result, mode1, mode2, p);
 -                 mode1 = NULL;
 -                 mode2 = NULL;
 -              }
 -	      gotsep = 0;
 -           }
 -           break;
 -
 -        }
  
 -    } while(*(str++) != 0);
 -     
 -    return result;
 -}
 +static const char *displayDevices[] = {
 +   "CRT",
 +   "TV",
 +   "DFP (digital flat panel)",
 +   "LFP (local flat panel)",
 +   "CRT2 (second CRT)",
 +   "TV2 (second TV)",
 +   "DFP2 (second digital flat panel)",
 +   "LFP2 (second local flat panel)",
 +   NULL
 +};
  
 -static DisplayModePtr
 -I830GenerateModeList(ScrnInfoPtr pScrn, char* str,
 -		    DisplayModePtr i, DisplayModePtr j,
 -		    int pos)
 +static const char *
 +DeviceToString(int device)
  {
 -   I830Ptr pI830 = I830PTR(pScrn);
 +   static int savedDevice = -1;
 +   int bit = 0;
 +   const char *name;
  
 -   if(str != NULL) {
 -      return(I830GenerateModeListFromMetaModes(pScrn, str, i, j, pos));
 -   } else {
 -      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 -	"No MetaModes given, linking %s modes by default\n",
 -	   (pI830->NonRect ?
 -		(((pos == PosLeftOf) || (pos == PosRightOf)) ? "widest" :  "tallest")
 -		:
 -		(((pos == PosLeftOf) || (pos == PosRightOf)) ? "widest common" :  "tallest common")) );
 -      return(I830GenerateModeListFromLargestModes(pScrn, i, j, pos));
 +   if (device == -1) {
 +      device = savedDevice;
 +      bit = 0;
     }
 -}
  
 -static void
 -I830RecalcDefaultVirtualSize(ScrnInfoPtr pScrn)
 -{
 -    I830Ptr pI830 = I830PTR(pScrn);
 -    DisplayModePtr mode, bmode;
 -    int maxh, maxv;
 -    static const char *str = "MergedFB: Virtual %s %d\n";
 -    static const char *errstr = "Virtual %s to small for given SecondPosition offset\n";
 -
 -    mode = bmode = pScrn->modes;
 -    maxh = maxv = 0;
 -    do {
 -       if(mode->HDisplay > maxh) maxh = mode->HDisplay;
 -       if(mode->VDisplay > maxv) maxv = mode->VDisplay;
 -       mode = mode->next;
 -    } while(mode != bmode);
 -
 -    maxh += pI830->FirstXOffs + pI830->SecondXOffs;
 -    maxv += pI830->FirstYOffs + pI830->SecondYOffs;
 -
 -    if(!(pScrn->display->virtualX)) {
 -       if(maxh > 4088) {
 -	  xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 -		"Virtual width with SecondPosition offset beyond hardware specs\n");
 -	  pI830->FirstXOffs = pI830->SecondXOffs = 0;
 -	  maxh -= (pI830->FirstXOffs + pI830->SecondXOffs);
 -       }
 -       pScrn->virtualX = maxh;
 -       pScrn->displayWidth = maxh;
 -       xf86DrvMsg(pScrn->scrnIndex, X_PROBED, str, "width", maxh);
 -    } else {
 -       if(maxh < pScrn->display->virtualX) {
 -	  xf86DrvMsg(pScrn->scrnIndex, X_ERROR, errstr, "width");
 -	  pI830->FirstXOffs = pI830->SecondXOffs = 0;
 -       }
 -    }
 +   if (device == -1)
 +      return NULL;
  
 -    if(!(pScrn->display->virtualY)) {
 -       pScrn->virtualY = maxv;
 -       xf86DrvMsg(pScrn->scrnIndex, X_PROBED, str, "height", maxv);
 -    } else {
 -       if(maxv < pScrn->display->virtualY) {
 -	  xf86DrvMsg(pScrn->scrnIndex, X_ERROR, errstr, "height");
 -	  pI830->FirstYOffs = pI830->SecondYOffs = 0;
 -       }
 -    }
 +   while (displayDevices[bit]) {
 +      if (device & (1 << bit)) {
 +	 name = displayDevices[bit];
 +	 savedDevice = device & ~(1 << bit);
 +	 bit++;
 +	 return name;
 +      }
 +      bit++;
 +   }
 +   return NULL;
  }
  
 -#define SDMPTR(x) ((I830ModePrivatePtr)x->currentMode->Private)->merged
 -#define CDMPTR    ((I830ModePrivatePtr)pI830->currentMode->Private)->merged
 -
 -#define BOUND(test,low,hi) 			\
 -    {						\
 -	if((test) < (low)) (test) = (low);	\
 -	if((test) > (hi))  (test) = (hi);	\
 -    }
 -
 -#define REBOUND(low,hi,test)		\
 -    {					\
 -	if((test) < (low)) {		\
 -		(hi) += (test)-(low);	\
 -		(low) = (test); 	\
 -	}				\
 -	if((test) > (hi)) {		\
 -		(low) += (test)-(hi);	\
 -		(hi) = (test); 		\
 -	}				\
 -    }
 -
 -
  static void
 -I830MergedPointerMoved(int scrnIndex, int x, int y)
 +PrintDisplayDeviceInfo(ScrnInfoPtr pScrn)
  {
 -  ScrnInfoPtr	pScrn1 = xf86Screens[scrnIndex];
 -  I830Ptr	pI830 = I830PTR(pScrn1);
 -  ScrnInfoPtr	pScrn2 = pI830->pScrn_2;
 -  region	out, in1, in2, f2, f1;
 -  int		deltax, deltay;
 -  int		temp1, temp2;
 -  int		old1x0, old1y0, old2x0, old2y0;
 -  int		FirstXOffs = 0, FirstYOffs = 0, SecondXOffs = 0, SecondYOffs = 0;
 -  int		HVirt = pScrn1->virtualX;
 -  int		VVirt = pScrn1->virtualY;
 -  int		sigstate;
 -  Bool		doit = FALSE, HaveNonRect = FALSE, HaveOffsRegions = FALSE;
 -  int           pos = ((I830MergedDisplayModePtr)pI830->currentMode->Private)->SecondPosition;
 -
 -  if(pI830->DGAactive) {
 -     return;
 -     /* DGA: There is no cursor and no panning while DGA is active. */
 -  } else {
 -     FirstXOffs = pI830->FirstXOffs;
 -     FirstYOffs = pI830->FirstYOffs;
 -     SecondXOffs = pI830->SecondXOffs;
 -     SecondYOffs = pI830->SecondYOffs;
 -     HaveNonRect = pI830->HaveNonRect;
 -     HaveOffsRegions = pI830->HaveOffsRegions;
 -  }
 -
 -  /* Check if the pointer is inside our dead areas */
 -  if((pI830->MouseRestrictions) && !I830noPanoramiXExtension) {
 -     if(HaveNonRect) {
 -	if(InRegion(x, y, pI830->NonRectDead)) {
 -	   switch(pos) {
 -	   case PosLeftOf:
 -	   case PosRightOf: y = pI830->NonRectDead.y0 - 1;
 -			    doit = TRUE;
 -			    break;
 -	   case PosAbove:
 -	   case PosBelow:   x = pI830->NonRectDead.x0 - 1;
 -			    doit = TRUE;
 -	   default:	    break;
 -	   }
 -	}
 -     }
 -     if(HaveOffsRegions) {
 -	if(InRegion(x, y, pI830->OffDead1)) {
 -	   switch(pos) {
 -	   case PosLeftOf:
 -	   case PosRightOf: y = pI830->OffDead1.y1;
 -			    doit = TRUE;
 -			    break;
 -	   case PosAbove:
 -	   case PosBelow:   x = pI830->OffDead1.x1;
 -			    doit = TRUE;
 -	   default:	    break;
 -	   }
 -	} else if(InRegion(x, y, pI830->OffDead2)) {
 -	   switch(pos) {
 -	   case PosLeftOf:
 -	   case PosRightOf: y = pI830->OffDead2.y0 - 1;
 -			    doit = TRUE;
 -			    break;
 -	   case PosAbove:
 -	   case PosBelow:   x = pI830->OffDead2.x0 - 1;
 -			    doit = TRUE;
 -	   default:	    break;
 -	   }
 -	}
 -     }
 -     if(doit) {
 -	UpdateCurrentTime();
 -	sigstate = xf86BlockSIGIO();
 -	miPointerAbsoluteCursor(x, y, currentTime.milliseconds);
 -	xf86UnblockSIGIO(sigstate);
 -	return;
 -     }
 -  }
 +   I830Ptr pI830 = I830PTR(pScrn);
 +   int pipe, n;
 +   int displays;
  
 -  f1.x0 = old1x0 = pI830->FirstframeX0;
 -  f1.x1 = pI830->FirstframeX1;
 -  f1.y0 = old1y0 = pI830->FirstframeY0;
 -  f1.y1 = pI830->FirstframeY1;
 -  f2.x0 = old2x0 = pScrn2->frameX0;
 -  f2.x1 = pScrn2->frameX1;
 -  f2.y0 = old2y0 = pScrn2->frameY0;
 -  f2.y1 = pScrn2->frameY1;
 -
 -  /* Define the outer region. Crossing this causes all frames to move */
 -  out.x0 = pScrn1->frameX0;
 -  out.x1 = pScrn1->frameX1;
 -  out.y0 = pScrn1->frameY0;
 -  out.y1 = pScrn1->frameY1;
 -
 -  /*
 -   * Define the inner sliding window. Being outsize both frames but
 -   * inside the outer clipping window will slide corresponding frame
 -   */
 -  in1 = out;
 -  in2 = out;
 -  switch(pos) {
 -     case PosLeftOf:
 -        in1.x0 = f1.x0;
 -        in2.x1 = f2.x1;
 -        break;
 -     case PosRightOf:
 -        in1.x1 = f1.x1;
 -        in2.x0 = f2.x0;
 -        break;
 -     case PosBelow:
 -        in1.y1 = f1.y1;
 -        in2.y0 = f2.y0;
 -        break;
 -     case PosAbove:
 -        in1.y0 = f1.y0;
 -        in2.y1 = f2.y1;
 -        break;
 -  }
 +   DPRINTF(PFX, "PrintDisplayDeviceInfo\n");
  
 -  deltay = 0;
 -  deltax = 0;
 +   displays = pI830->operatingDevices;
 +   if (displays == -1) {
 +      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 +		 "No active display devices.\n");
 +      return;
 +   }
  
 -  if(InRegion(x, y, out)) {	/* inside outer region */
 +   /* Check for active devices connected to each display pipe. */
 +   for (n = 0; n < pI830->availablePipes; n++) {
 +      pipe = ((displays >> PIPE_SHIFT(n)) & PIPE_ACTIVE_MASK);
 +      if (pipe) {
 +	 const char *name;
  
 -     if(InRegion(x, y, in1) && !InRegion(x, y, f1)) {
 -	REBOUND(f1.x0, f1.x1, x);
 -	REBOUND(f1.y0, f1.y1, y);
 -	deltax = 1;
 -     }
 -     if(InRegion(x, y, in2) && !InRegion(x, y, f2)) {
 -	REBOUND(f2.x0, f2.x1, x);
 -	REBOUND(f2.y0, f2.y1, y);
 -	deltax = 1;
 -     }
 +	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 +		    "Currently active displays on Pipe %c:\n", PIPE_NAME(n));
 +	 name = DeviceToString(pipe);
 +	 do {
 +	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\t%s\n", name);
 +	    name = DeviceToString(-1);
 +	 } while (name);
  
- 	 if (pipe & PIPE_UNKNOWN_ACTIVE)
- 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- 		       "\tSome unknown display devices may also be present\n");
- 
 -  } else {			/* outside outer region */
 +      } else {
 +	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 +		    "No active displays on Pipe %c.\n", PIPE_NAME(n));
 +      }
 +   }
 +}
  
 -     if(out.x0 > x) {
 -	deltax = x - out.x0;
 -     }
 -     if(out.x1 < x) {
 -	deltax = x - out.x1;
 -     }
 -     if(deltax) {
 -	pScrn1->frameX0 += deltax;
 -	pScrn1->frameX1 += deltax;
 -	f1.x0 += deltax;
 -	f1.x1 += deltax;
 -	f2.x0 += deltax;
 -	f2.x1 += deltax;
 -     }
 +static int
 +I830DetectMemory(ScrnInfoPtr pScrn)
 +{
 +   I830Ptr pI830 = I830PTR(pScrn);
 +   PCITAG bridge;
 +   CARD16 gmch_ctrl;
 +   int memsize = 0;
 +   int range;
  
 -     if(out.y0 > y) {
 -	deltay = y - out.y0;
 -     }
 -     if(out.y1 < y) {
 -	deltay = y - out.y1;
 -     }
 -     if(deltay) {
 -	pScrn1->frameY0 += deltay;
 -	pScrn1->frameY1 += deltay;
 -	f1.y0 += deltay;
 -	f1.y1 += deltay;
 -	f2.y0 += deltay;
 -	f2.y1 += deltay;
 -     }
 -
 -     switch(pos) {
 -	case PosLeftOf:
 -	   if(x >= f1.x0) { REBOUND(f1.y0, f1.y1, y); }
 -	   if(x <= f2.x1) { REBOUND(f2.y0, f2.y1, y); }
 -	   break;
 -	case PosRightOf:
 -	   if(x <= f1.x1) { REBOUND(f1.y0, f1.y1, y); }
 -	   if(x >= f2.x0) { REBOUND(f2.y0, f2.y1, y); }
 -	   break;
 -	case PosBelow:
 -	   if(y <= f1.y1) { REBOUND(f1.x0, f1.x1, x); }
 -	   if(y >= f2.y0) { REBOUND(f2.x0, f2.x1, x); }
 -	   break;
 -	case PosAbove:
 -	   if(y >= f1.y0) { REBOUND(f1.x0, f1.x1, x); }
 -	   if(y <= f2.y1) { REBOUND(f2.x0, f2.x1, x); }
 -	   break;
 -     }
 -
 -  }
 -
 -  if(deltax || deltay) {
 -     pI830->FirstframeX0 = f1.x0;
 -     pI830->FirstframeY0 = f1.y0;
 -     pScrn2->frameX0 = f2.x0;
 -     pScrn2->frameY0 = f2.y0;
 -
 -     switch(pos) {
 -	case PosLeftOf:
 -	case PosRightOf:
 -	   if(FirstYOffs || SecondYOffs || HaveNonRect) {
 -	      if(pI830->FirstframeY0 != old1y0) {
 -	         if(pI830->FirstframeY0 < FirstYOffs)
 -	            pI830->FirstframeY0 = FirstYOffs;
 -
 -	         temp1 = pI830->FirstframeY0 + CDMPTR.First->VDisplay;
 -	         temp2 = min((VVirt - SecondYOffs), (FirstYOffs + pI830->MBXNR1YMAX));
 -	         if(temp1 > temp2)
 -	            pI830->FirstframeY0 -= (temp1 - temp2);
 -	      }
 -	      if(pScrn2->frameY0 != old2y0) {
 -	         if(pScrn2->frameY0 < SecondYOffs)
 -	            pScrn2->frameY0 = SecondYOffs;
 -
 -	         temp1 = pScrn2->frameY0 + CDMPTR.Second->VDisplay;
 -	         temp2 = min((VVirt - FirstYOffs), (SecondYOffs + pI830->MBXNR2YMAX));
 -	         if(temp1 > temp2)
 -	            pScrn2->frameY0 -= (temp1 - temp2);
 -	      }
 -	   }
 -	   break;
 -	case PosBelow:
 -	case PosAbove:
 -	   if(FirstXOffs || SecondXOffs || HaveNonRect) {
 -	      if(pI830->FirstframeX0 != old1x0) {
 -	         if(pI830->FirstframeX0 < FirstXOffs)
 -	            pI830->FirstframeX0 = FirstXOffs;
 -
 -	         temp1 = pI830->FirstframeX0 + CDMPTR.First->HDisplay;
 -	         temp2 = min((HVirt - SecondXOffs), (FirstXOffs + pI830->MBXNR1XMAX));
 -	         if(temp1 > temp2)
 -	            pI830->FirstframeX0 -= (temp1 - temp2);
 -	      }
 -	      if(pScrn2->frameX0 != old2x0) {
 -	         if(pScrn2->frameX0 < SecondXOffs)
 -	            pScrn2->frameX0 = SecondXOffs;
 -
 -	         temp1 = pScrn2->frameX0 + CDMPTR.Second->HDisplay;
 -	         temp2 = min((HVirt - FirstXOffs), (SecondXOffs + pI830->MBXNR2XMAX));
 -	         if(temp1 > temp2)
 -	            pScrn2->frameX0 -= (temp1 - temp2);
 -	      }
 -	   }
 -	   break;
 -     }
 -
 -     pI830->FirstframeX1 = pI830->FirstframeX0 + CDMPTR.First->HDisplay - 1;
 -     pI830->FirstframeY1 = pI830->FirstframeY0 + CDMPTR.First->VDisplay - 1;
 -     pScrn2->frameX1   = pScrn2->frameX0   + CDMPTR.Second->HDisplay - 1;
 -     pScrn2->frameY1   = pScrn2->frameY0   + CDMPTR.Second->VDisplay - 1;
 -
 -     /* No need to update pScrn1->frame?1, done above */
 -    if (pI830->pipe == 0) {
 -       OUTREG(DSPABASE, pI830->FrontBuffer.Start + ((pI830->FirstframeY0 * pScrn1->displayWidth + pI830->FirstframeX0) * pI830->cpp));
 -       OUTREG(DSPBBASE, pI830->FrontBuffer.Start + ((pScrn2->frameY0 * pScrn1->displayWidth + pScrn2->frameX0) * pI830->cpp));
 -    } else {
 -       OUTREG(DSPBBASE, pI830->FrontBuffer.Start + ((pI830->FirstframeY0 * pScrn1->displayWidth + pI830->FirstframeX0) * pI830->cpp));
 -       OUTREG(DSPABASE, pI830->FrontBuffer.Start + ((pScrn2->frameY0 * pScrn1->displayWidth + pScrn2->frameX0) * pI830->cpp));
 -    }
 -  }
 -}
 -
 -static void
 -I830AdjustFrameMerged(int scrnIndex, int x, int y, int flags)
 -{
 -    ScrnInfoPtr pScrn1 = xf86Screens[scrnIndex];
 -    I830Ptr pI830 = I830PTR(pScrn1);
 -    ScrnInfoPtr pScrn2 = pI830->pScrn_2;
 -    int HTotal = pI830->currentMode->HDisplay;
 -    int VTotal = pI830->currentMode->VDisplay;
 -    int HMax = HTotal;
 -    int VMax = VTotal;
 -    int HVirt = pScrn1->virtualX;
 -    int VVirt = pScrn1->virtualY;
 -    int x1 = x, x2 = x;
 -    int y1 = y, y2 = y;
 -    int FirstXOffs = 0, FirstYOffs = 0, SecondXOffs = 0, SecondYOffs = 0;
 -    int MBXNR1XMAX = 65536, MBXNR1YMAX = 65536, MBXNR2XMAX = 65536, MBXNR2YMAX = 65536;
 -
 -    if(pI830->DGAactive) {
 -       HVirt = pScrn1->displayWidth;
 -       VVirt = pScrn1->virtualY;
 -    } else {
 -       FirstXOffs = pI830->FirstXOffs;
 -       FirstYOffs = pI830->FirstYOffs;
 -       SecondXOffs = pI830->SecondXOffs;
 -       SecondYOffs = pI830->SecondYOffs;
 -       MBXNR1XMAX = pI830->MBXNR1XMAX;
 -       MBXNR1YMAX = pI830->MBXNR1YMAX;
 -       MBXNR2XMAX = pI830->MBXNR2XMAX;
 -       MBXNR2YMAX = pI830->MBXNR2YMAX;
 -    }
 -
 -    BOUND(x, 0, HVirt - HTotal);
 -    BOUND(y, 0, VVirt - VTotal);
 -    BOUND(x1, FirstXOffs, min(HVirt, MBXNR1XMAX + FirstXOffs) - min(HTotal, MBXNR1XMAX) - SecondXOffs);
 -    BOUND(y1, FirstYOffs, min(VVirt, MBXNR1YMAX + FirstYOffs) - min(VTotal, MBXNR1YMAX) - SecondYOffs);
 -    BOUND(x2, SecondXOffs, min(HVirt, MBXNR2XMAX + SecondXOffs) - min(HTotal, MBXNR2XMAX) - FirstXOffs);
 -    BOUND(y2, SecondYOffs, min(VVirt, MBXNR2YMAX + SecondYOffs) - min(VTotal, MBXNR2YMAX) - FirstYOffs);
 -
 -    switch(SDMPTR(pScrn1).SecondPosition) {
 -        case PosLeftOf:
 -            pScrn2->frameX0 = x2;
 -            BOUND(pScrn2->frameY0,   y2, y2 + min(VMax, MBXNR2YMAX) - CDMPTR.Second->VDisplay);
 -            pI830->FirstframeX0 = x1 + CDMPTR.Second->HDisplay;
 -            BOUND(pI830->FirstframeY0, y1, y1 + min(VMax, MBXNR1YMAX) - CDMPTR.First->VDisplay);
 -            break;
 -        case PosRightOf:
 -            pI830->FirstframeX0 = x1;
 -            BOUND(pI830->FirstframeY0, y1, y1 + min(VMax, MBXNR1YMAX) - CDMPTR.First->VDisplay);
 -            pScrn2->frameX0 = x2 + CDMPTR.First->HDisplay;
 -            BOUND(pScrn2->frameY0,   y2, y2 + min(VMax, MBXNR2YMAX) - CDMPTR.Second->VDisplay);
 -            break;
 -        case PosAbove:
 -            BOUND(pScrn2->frameX0,   x2, x2 + min(HMax, MBXNR2XMAX) - CDMPTR.Second->HDisplay);
 -            pScrn2->frameY0 = y2;
 -            BOUND(pI830->FirstframeX0, x1, x1 + min(HMax, MBXNR1XMAX) - CDMPTR.First->HDisplay);
 -            pI830->FirstframeY0 = y1 + CDMPTR.Second->VDisplay;
 -            break;
 -        case PosBelow:
 -            BOUND(pI830->FirstframeX0, x1, x1 + min(HMax, MBXNR1XMAX) - CDMPTR.First->HDisplay);
 -            pI830->FirstframeY0 = y1;
 -            BOUND(pScrn2->frameX0,   x2, x2 + min(HMax, MBXNR2XMAX) - CDMPTR.Second->HDisplay);
 -            pScrn2->frameY0 = y2 + CDMPTR.First->VDisplay;
 -            break;
 -    }
 -
 -    BOUND(pI830->FirstframeX0, 0, HVirt - CDMPTR.First->HDisplay);
 -    BOUND(pI830->FirstframeY0, 0, VVirt - CDMPTR.First->VDisplay);
 -    BOUND(pScrn2->frameX0,   0, HVirt - CDMPTR.Second->HDisplay);
 -    BOUND(pScrn2->frameY0,   0, VVirt - CDMPTR.Second->VDisplay);
 -
 -    pScrn1->frameX0 = x;
 -    pScrn1->frameY0 = y;
 -
 -    pI830->FirstframeX1 = pI830->FirstframeX0 + CDMPTR.First->HDisplay - 1;
 -    pI830->FirstframeY1 = pI830->FirstframeY0 + CDMPTR.First->VDisplay - 1;
 -    pScrn2->frameX1   = pScrn2->frameX0   + CDMPTR.Second->HDisplay - 1;
 -    pScrn2->frameY1   = pScrn2->frameY0   + CDMPTR.Second->VDisplay - 1;
 -
 -    pScrn1->frameX1   = pScrn1->frameX0   + pI830->currentMode->HDisplay  - 1;
 -    pScrn1->frameY1   = pScrn1->frameY0   + pI830->currentMode->VDisplay  - 1;
 -    pScrn1->frameX1 += FirstXOffs + SecondXOffs;
 -    pScrn1->frameY1 += FirstYOffs + SecondYOffs;
 -}
 -
 -/* Pseudo-Xinerama extension for MergedFB mode */
 -static void
 -I830UpdateXineramaScreenInfo(ScrnInfoPtr pScrn1)
 -{
 -    I830Ptr pI830 = I830PTR(pScrn1);
 -    int scrnnum1 = 0, scrnnum2 = 1;
 -    int x1=0, x2=0, y1=0, y2=0, h1=0, h2=0, w1=0, w2=0;
 -    int realvirtX, realvirtY;
 -    DisplayModePtr currentMode, firstMode;
 -    Bool infochanged = FALSE;
 -    Bool usenonrect = pI830->NonRect;
 -    const char *rectxine = "\t... setting up rectangular Xinerama layout\n";
 -
 -    pI830->MBXNR1XMAX = pI830->MBXNR1YMAX = pI830->MBXNR2XMAX = pI830->MBXNR2YMAX = 65536;
 -    pI830->HaveNonRect = pI830->HaveOffsRegions = FALSE;
 -
 -    if(!pI830->MergedFB) return;
 -
 -    if(I830noPanoramiXExtension) return;
 -
 -    if(!I830XineramadataPtr) return;
 -
 -    if(pI830->SecondIsScrn0) {
 -       scrnnum1 = 1;
 -       scrnnum2 = 0;
 -    }
 -
 -    /* Attention: Usage of RandR may lead to virtual X and Y dimensions
 -     * actually smaller than our MetaModes. To avoid this, we calculate
 -     * the max* fields here (and not somewhere else, like in CopyNLink)
 -     *
 -     * *** Note: RandR is disabled if one of CRTxxOffs is non-zero.
 -     */
 -
 -    /* "Real" virtual: Virtual without the Offset */
 -    realvirtX = pScrn1->virtualX - pI830->FirstXOffs - pI830->SecondXOffs;
 -    realvirtY = pScrn1->virtualY - pI830->FirstYOffs - pI830->SecondYOffs;
 -
 -    if((pI830->I830XineramaVX != pScrn1->virtualX) || (pI830->I830XineramaVY != pScrn1->virtualY)) {
 -
 -       if(!(pScrn1->modes)) return;
 -
 -       pI830->maxFirst_X1 = pI830->maxFirst_X2 = 0;
 -       pI830->maxFirst_Y1 = pI830->maxFirst_Y2 = 0;
 -       pI830->maxSecond_X1 = pI830->maxSecond_X2 = 0;
 -       pI830->maxSecond_Y1 = pI830->maxSecond_Y2 = 0;
 -
 -       currentMode = firstMode = pScrn1->modes;
 -
 -       do {
 -
 -          DisplayModePtr p = currentMode->next;
 -          DisplayModePtr i = ((I830ModePrivatePtr)currentMode->Private)->merged.First;
 -          DisplayModePtr j = ((I830ModePrivatePtr)currentMode->Private)->merged.Second;
 -
 -          if((currentMode->HDisplay <= realvirtX) && (currentMode->VDisplay <= realvirtY) &&
 -	     (i->HDisplay <= realvirtX) && (j->HDisplay <= realvirtX) &&
 -	     (i->VDisplay <= realvirtY) && (j->VDisplay <= realvirtY)) {
 -
 -		if(pI830->maxFirst_X1 == i->HDisplay) {
 -		   if(pI830->maxFirst_X2 < j->HDisplay) {
 -		      pI830->maxFirst_X2 = j->HDisplay;   /* Widest Second mode displayed with widest CRT1 mode */
 -		   }
 -		} else if(pI830->maxFirst_X1 < i->HDisplay) {
 -		   pI830->maxFirst_X1 = i->HDisplay;      /* Widest CRT1 mode */
 -		   pI830->maxFirst_X2 = j->HDisplay;
 -		}
 -		if(pI830->maxSecond_X2 == j->HDisplay) {
 -		   if(pI830->maxSecond_X1 < i->HDisplay) {
 -		      pI830->maxSecond_X1 = i->HDisplay;   /* Widest First mode displayed with widest Second mode */
 -		   }
 -		} else if(pI830->maxSecond_X2 < j->HDisplay) {
 -		   pI830->maxSecond_X2 = j->HDisplay;      /* Widest Second mode */
 -		   pI830->maxSecond_X1 = i->HDisplay;
 -		}
 -		if(pI830->maxFirst_Y1 == i->VDisplay) {   /* Same as above, but tallest instead of widest */
 -		   if(pI830->maxFirst_Y2 < j->VDisplay) {
 -		      pI830->maxFirst_Y2 = j->VDisplay;
 -		   }
 -		} else if(pI830->maxFirst_Y1 < i->VDisplay) {
 -		   pI830->maxFirst_Y1 = i->VDisplay;
 -		   pI830->maxFirst_Y2 = j->VDisplay;
 -		}
 -		if(pI830->maxSecond_Y2 == j->VDisplay) {
 -		   if(pI830->maxSecond_Y1 < i->VDisplay) {
 -		      pI830->maxSecond_Y1 = i->VDisplay;
 -		   }
 -		} else if(pI830->maxSecond_Y2 < j->VDisplay) {
 -		   pI830->maxSecond_Y2 = j->VDisplay;
 -		   pI830->maxSecond_Y1 = i->VDisplay;
 -		}
 -	  }
 -	  currentMode = p;
 -
 -       } while((currentMode) && (currentMode != firstMode));
 -
 -       pI830->I830XineramaVX = pScrn1->virtualX;
 -       pI830->I830XineramaVY = pScrn1->virtualY;
 -       infochanged = TRUE;
 -
 -    }
 -
 -    if((usenonrect) && pI830->maxFirst_X1) {
 -       switch(pI830->SecondPosition) {
 -       case PosLeftOf:
 -       case PosRightOf:
 -	  if((pI830->maxFirst_Y1 != realvirtY) && (pI830->maxSecond_Y2 != realvirtY)) {
 -	     usenonrect = FALSE;
 -	  }
 -	  break;
 -       case PosAbove:
 -       case PosBelow:
 -	  if((pI830->maxFirst_X1 != realvirtX) && (pI830->maxSecond_X2 != realvirtX)) {
 -	     usenonrect = FALSE;
 -	  }
 -	  break;
 -       }
 -       if(infochanged && !usenonrect) {
 -	  xf86DrvMsg(pScrn1->scrnIndex, X_INFO,
 -			"Virtual screen size does not match maximum display modes...\n");
 -	  xf86DrvMsg(pScrn1->scrnIndex, X_INFO, rectxine);
 -
 -       }
 -    } else if(infochanged && usenonrect) {
 -       usenonrect = FALSE;
 -       xf86DrvMsg(pScrn1->scrnIndex, X_INFO,
 -		"Only clone modes available for this virtual screen size...\n");
 -       xf86DrvMsg(pScrn1->scrnIndex, X_INFO, rectxine);
 -    }
 -
 -    if(pI830->maxFirst_X1) {		/* Means we have at least one non-clone mode */
 -       switch(pI830->SecondPosition) {
 -       case PosLeftOf:
 -	  x1 = min(pI830->maxFirst_X2, pScrn1->virtualX - pI830->maxFirst_X1);
 -	  if(x1 < 0) x1 = 0;
 -	  y1 = pI830->FirstYOffs;
 -	  w1 = pScrn1->virtualX - x1;
 -	  h1 = realvirtY;
 -	  if((usenonrect) && (pI830->maxFirst_Y1 != realvirtY)) {
 -	     h1 = pI830->MBXNR1YMAX = pI830->maxFirst_Y1;
 -	     pI830->NonRectDead.x0 = x1;
 -	     pI830->NonRectDead.x1 = x1 + w1 - 1;
 -	     pI830->NonRectDead.y0 = y1 + h1;
 -	     pI830->NonRectDead.y1 = pScrn1->virtualY - 1;
 -	     pI830->HaveNonRect = TRUE;
 -	  }
 -	  x2 = 0;
 -	  y2 = pI830->SecondYOffs;
 -	  w2 = max(pI830->maxSecond_X2, pScrn1->virtualX - pI830->maxSecond_X1);
 -	  if(w2 > pScrn1->virtualX) w2 = pScrn1->virtualX;
 -	  h2 = realvirtY;
 -	  if((usenonrect) && (pI830->maxSecond_Y2 != realvirtY)) {
 -	     h2 = pI830->MBXNR2YMAX = pI830->maxSecond_Y2;
 -	     pI830->NonRectDead.x0 = x2;
 -	     pI830->NonRectDead.x1 = x2 + w2 - 1;
 -	     pI830->NonRectDead.y0 = y2 + h2;
 -	     pI830->NonRectDead.y1 = pScrn1->virtualY - 1;
 -	     pI830->HaveNonRect = TRUE;
 -	  }
 -	  break;
 -       case PosRightOf:
 -	  x1 = 0;
 -	  y1 = pI830->FirstYOffs;
 -	  w1 = max(pI830->maxFirst_X1, pScrn1->virtualX - pI830->maxFirst_X2);
 -	  if(w1 > pScrn1->virtualX) w1 = pScrn1->virtualX;
 -	  h1 = realvirtY;
 -	  if((usenonrect) && (pI830->maxFirst_Y1 != realvirtY)) {
 -	     h1 = pI830->MBXNR1YMAX = pI830->maxFirst_Y1;
 -	     pI830->NonRectDead.x0 = x1;
 -	     pI830->NonRectDead.x1 = x1 + w1 - 1;
 -	     pI830->NonRectDead.y0 = y1 + h1;
 -	     pI830->NonRectDead.y1 = pScrn1->virtualY - 1;
 -	     pI830->HaveNonRect = TRUE;
 -	  }
 -	  x2 = min(pI830->maxSecond_X1, pScrn1->virtualX - pI830->maxSecond_X2);
 -	  if(x2 < 0) x2 = 0;
 -	  y2 = pI830->SecondYOffs;
 -	  w2 = pScrn1->virtualX - x2;
 -	  h2 = realvirtY;
 -	  if((usenonrect) && (pI830->maxSecond_Y2 != realvirtY)) {
 -	     h2 = pI830->MBXNR2YMAX = pI830->maxSecond_Y2;
 -	     pI830->NonRectDead.x0 = x2;
 -	     pI830->NonRectDead.x1 = x2 + w2 - 1;
 -	     pI830->NonRectDead.y0 = y2 + h2;
 -	     pI830->NonRectDead.y1 = pScrn1->virtualY - 1;
 -	     pI830->HaveNonRect = TRUE;
 -	  }
 -	  break;
 -       case PosAbove:
 -	  x1 = pI830->FirstXOffs;
 -	  y1 = min(pI830->maxFirst_Y2, pScrn1->virtualY - pI830->maxFirst_Y1);
 -	  if(y1 < 0) y1 = 0;
 -	  w1 = realvirtX;
 -	  h1 = pScrn1->virtualY - y1;
 -	  if((usenonrect) && (pI830->maxFirst_X1 != realvirtX)) {
 -	     w1 = pI830->MBXNR1XMAX = pI830->maxFirst_X1;
 -	     pI830->NonRectDead.x0 = x1 + w1;
 -	     pI830->NonRectDead.x1 = pScrn1->virtualX - 1;
 -	     pI830->NonRectDead.y0 = y1;
 -	     pI830->NonRectDead.y1 = y1 + h1 - 1;
 -	     pI830->HaveNonRect = TRUE;
 -	  }
 -	  x2 = pI830->SecondXOffs;
 -	  y2 = 0;
 -	  w2 = realvirtX;
 -	  h2 = max(pI830->maxSecond_Y2, pScrn1->virtualY - pI830->maxSecond_Y1);
 -	  if(h2 > pScrn1->virtualY) h2 = pScrn1->virtualY;
 -	  if((usenonrect) && (pI830->maxSecond_X2 != realvirtX)) {
 -	     w2 = pI830->MBXNR2XMAX = pI830->maxSecond_X2;
 -	     pI830->NonRectDead.x0 = x2 + w2;
 -	     pI830->NonRectDead.x1 = pScrn1->virtualX - 1;
 -	     pI830->NonRectDead.y0 = y2;
 -	     pI830->NonRectDead.y1 = y2 + h2 - 1;
 -	     pI830->HaveNonRect = TRUE;
 -	  }
 -	  break;
 -       case PosBelow:
 -	  x1 = pI830->FirstXOffs;
 -	  y1 = 0;
 -	  w1 = realvirtX;
 -	  h1 = max(pI830->maxFirst_Y1, pScrn1->virtualY - pI830->maxFirst_Y2);
 -	  if(h1 > pScrn1->virtualY) h1 = pScrn1->virtualY;
 -	  if((usenonrect) && (pI830->maxFirst_X1 != realvirtX)) {
 -	     w1 = pI830->MBXNR1XMAX = pI830->maxFirst_X1;
 -	     pI830->NonRectDead.x0 = x1 + w1;
 -	     pI830->NonRectDead.x1 = pScrn1->virtualX - 1;
 -	     pI830->NonRectDead.y0 = y1;
 -	     pI830->NonRectDead.y1 = y1 + h1 - 1;
 -	     pI830->HaveNonRect = TRUE;
 -	  }
 -	  x2 = pI830->SecondXOffs;
 -	  y2 = min(pI830->maxSecond_Y1, pScrn1->virtualY - pI830->maxSecond_Y2);
 -	  if(y2 < 0) y2 = 0;
 -	  w2 = realvirtX;
 -	  h2 = pScrn1->virtualY - y2;
 -	  if((usenonrect) && (pI830->maxSecond_X2 != realvirtX)) {
 -	     w2 = pI830->MBXNR2XMAX = pI830->maxSecond_X2;
 -	     pI830->NonRectDead.x0 = x2 + w2;
 -	     pI830->NonRectDead.x1 = pScrn1->virtualX - 1;
 -	     pI830->NonRectDead.y0 = y2;
 -	     pI830->NonRectDead.y1 = y2 + h2 - 1;
 -	     pI830->HaveNonRect = TRUE;
 -	  }
 -       default:
 -	  break;
 -       }
 -
 -       switch(pI830->SecondPosition) {
 -       case PosLeftOf:
 -       case PosRightOf:
 -	  if(pI830->FirstYOffs) {
 -	     pI830->OffDead1.x0 = x1;
 -	     pI830->OffDead1.x1 = x1 + w1 - 1;
 -	     pI830->OffDead1.y0 = 0;
 -	     pI830->OffDead1.y1 = y1 - 1;
 -	     pI830->OffDead2.x0 = x2;
 -	     pI830->OffDead2.x1 = x2 + w2 - 1;
 -	     pI830->OffDead2.y0 = y2 + h2;
 -	     pI830->OffDead2.y1 = pScrn1->virtualY - 1;
 -	     pI830->HaveOffsRegions = TRUE;
 -	  } else if(pI830->SecondYOffs) {
 -	     pI830->OffDead1.x0 = x2;
 -	     pI830->OffDead1.x1 = x2 + w2 - 1;
 -	     pI830->OffDead1.y0 = 0;
 -	     pI830->OffDead1.y1 = y2 - 1;
 -	     pI830->OffDead2.x0 = x1;
 -	     pI830->OffDead2.x1 = x1 + w1 - 1;
 -	     pI830->OffDead2.y0 = y1 + h1;
 -	     pI830->OffDead2.y1 = pScrn1->virtualY - 1;
 -	     pI830->HaveOffsRegions = TRUE;
 -	  }
 -	  break;
 -       case PosAbove:
 -       case PosBelow:
 -	  if(pI830->FirstXOffs) {
 -	     pI830->OffDead1.x0 = x2 + w2;
 -	     pI830->OffDead1.x1 = pScrn1->virtualX - 1;
 -	     pI830->OffDead1.y0 = y2;
 -	     pI830->OffDead1.y1 = y2 + h2 - 1;
 -	     pI830->OffDead2.x0 = 0;
 -	     pI830->OffDead2.x1 = x1 - 1;
 -	     pI830->OffDead2.y0 = y1;
 -	     pI830->OffDead2.y1 = y1 + h1 - 1;
 -	     pI830->HaveOffsRegions = TRUE;
 -	  } else if(pI830->SecondXOffs) {
 -	     pI830->OffDead1.x0 = x1 + w1;
 -	     pI830->OffDead1.x1 = pScrn1->virtualX - 1;
 -	     pI830->OffDead1.y0 = y1;
 -	     pI830->OffDead1.y1 = y1 + h1 - 1;
 -	     pI830->OffDead2.x0 = 0;
 -	     pI830->OffDead2.x1 = x2 - 1;
 -	     pI830->OffDead2.y0 = y2;
 -	     pI830->OffDead2.y1 = y2 + h2 - 1;
 -	     pI830->HaveOffsRegions = TRUE;
 -	  }
 -       default:
 -	  break;
 -       }
 -
 -    }
 -
 -    I830XineramadataPtr[scrnnum1].x = x1;
 -    I830XineramadataPtr[scrnnum1].y = y1;
 -    I830XineramadataPtr[scrnnum1].width = w1;
 -    I830XineramadataPtr[scrnnum1].height = h1;
 -    I830XineramadataPtr[scrnnum2].x = x2;
 -    I830XineramadataPtr[scrnnum2].y = y2;
 -    I830XineramadataPtr[scrnnum2].width = w2;
 -    I830XineramadataPtr[scrnnum2].height = h2;
 -
 -    if(infochanged) {
 -       xf86DrvMsg(pScrn1->scrnIndex, X_INFO,
 -	  "Pseudo-Xinerama: First (Screen %d) (%d,%d)-(%d,%d)\n",
 -	  scrnnum1, x1, y1, w1+x1-1, h1+y1-1);
 -       xf86DrvMsg(pScrn1->scrnIndex, X_INFO,
 -	  "Pseudo-Xinerama: Second (Screen %d) (%d,%d)-(%d,%d)\n",
 -	  scrnnum2, x2, y2, w2+x2-1, h2+y2-1);
 -       if(pI830->HaveNonRect) {
 -	  xf86DrvMsg(pScrn1->scrnIndex, X_INFO,
 -		"Pseudo-Xinerama: Inaccessible area (%d,%d)-(%d,%d)\n",
 -		pI830->NonRectDead.x0, pI830->NonRectDead.y0,
 -		pI830->NonRectDead.x1, pI830->NonRectDead.y1);
 -       }
 -       if(pI830->HaveOffsRegions) {
 -	  xf86DrvMsg(pScrn1->scrnIndex, X_INFO,
 -		"Pseudo-Xinerama: Inaccessible offset area (%d,%d)-(%d,%d)\n",
 -		pI830->OffDead1.x0, pI830->OffDead1.y0,
 -		pI830->OffDead1.x1, pI830->OffDead1.y1);
 -	  xf86DrvMsg(pScrn1->scrnIndex, X_INFO,
 -		"Pseudo-Xinerama: Inaccessible offset area (%d,%d)-(%d,%d)\n",
 -		pI830->OffDead2.x0, pI830->OffDead2.y0,
 -		pI830->OffDead2.x1, pI830->OffDead2.y1);
 -       }
 -       if(pI830->HaveNonRect || pI830->HaveOffsRegions) {
 -	  xf86DrvMsg(pScrn1->scrnIndex, X_INFO,
 -		"Mouse restriction for inaccessible areas is %s\n",
 -		pI830->MouseRestrictions ? "enabled" : "disabled");
 -       }
 -    }
 -}
 -
 -/* Proc */
 -
 -int
 -I830ProcXineramaQueryVersion(ClientPtr client)
 -{
 -    xPanoramiXQueryVersionReply	  rep;
 -    register int		  n;
 -
 -    REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq);
 -    rep.type = X_Reply;
 -    rep.length = 0;
 -    rep.sequenceNumber = client->sequence;
 -    rep.majorVersion = 1;
 -    rep.minorVersion = 0;
 -    if(client->swapped) {
 -        swaps(&rep.sequenceNumber, n);
 -        swapl(&rep.length, n);
 -        swaps(&rep.majorVersion, n);
 -        swaps(&rep.minorVersion, n);
 -    }
 -    WriteToClient(client, sizeof(xPanoramiXQueryVersionReply), (char *)&rep);
 -    return (client->noClientException);
 -}
 -
 -int
 -I830ProcXineramaGetState(ClientPtr client)
 -{
 -    REQUEST(xPanoramiXGetStateReq);
 -    WindowPtr			pWin;
 -    xPanoramiXGetStateReply	rep;
 -    register int		n;
 -
 -    REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
 -    pWin = LookupWindow(stuff->window, client);
 -    if(!pWin) return BadWindow;
 -
 -    rep.type = X_Reply;
 -    rep.length = 0;
 -    rep.sequenceNumber = client->sequence;
 -    rep.state = !I830noPanoramiXExtension;
 -    if(client->swapped) {
 -       swaps (&rep.sequenceNumber, n);
 -       swapl (&rep.length, n);
 -       swaps (&rep.state, n);
 -    }
 -    WriteToClient(client, sizeof(xPanoramiXGetStateReply), (char *)&rep);
 -    return client->noClientException;
 -}
 -
 -int
 -I830ProcXineramaGetScreenCount(ClientPtr client)
 -{
 -    REQUEST(xPanoramiXGetScreenCountReq);
 -    WindowPtr				pWin;
 -    xPanoramiXGetScreenCountReply	rep;
 -    register int			n;
 -
 -    REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
 -    pWin = LookupWindow(stuff->window, client);
 -    if(!pWin) return BadWindow;
 -
 -    rep.type = X_Reply;
 -    rep.length = 0;
 -    rep.sequenceNumber = client->sequence;
 -    rep.ScreenCount = I830XineramaNumScreens;
 -    if(client->swapped) {
 -       swaps(&rep.sequenceNumber, n);
 -       swapl(&rep.length, n);
 -       swaps(&rep.ScreenCount, n);
 -    }
 -    WriteToClient(client, sizeof(xPanoramiXGetScreenCountReply), (char *)&rep);
 -    return client->noClientException;
 -}
 -
 -int
 -I830ProcXineramaGetScreenSize(ClientPtr client)
 -{
 -    REQUEST(xPanoramiXGetScreenSizeReq);
 -    WindowPtr				pWin;
 -    xPanoramiXGetScreenSizeReply	rep;
 -    register int			n;
 -
 -    REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
 -    pWin = LookupWindow (stuff->window, client);
 -    if(!pWin)  return BadWindow;
 -
 -    rep.type = X_Reply;
 -    rep.length = 0;
 -    rep.sequenceNumber = client->sequence;
 -    rep.width  = I830XineramadataPtr[stuff->screen].width;
 -    rep.height = I830XineramadataPtr[stuff->screen].height;
 -    if(client->swapped) {
 -       swaps(&rep.sequenceNumber, n);
 -       swapl(&rep.length, n);
 -       swaps(&rep.width, n);
 -       swaps(&rep.height, n);
 -    }
 -    WriteToClient(client, sizeof(xPanoramiXGetScreenSizeReply), (char *)&rep);
 -    return client->noClientException;
 -}
 -
 -int
 -I830ProcXineramaIsActive(ClientPtr client)
 -{
 -    xXineramaIsActiveReply	rep;
 -
 -    REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
 -
 -    rep.type = X_Reply;
 -    rep.length = 0;
 -    rep.sequenceNumber = client->sequence;
 -    rep.state = !I830noPanoramiXExtension;
 -    if(client->swapped) {
 -	register int n;
 -	swaps(&rep.sequenceNumber, n);
 -	swapl(&rep.length, n);
 -	swapl(&rep.state, n);
 -    }
 -    WriteToClient(client, sizeof(xXineramaIsActiveReply), (char *) &rep);
 -    return client->noClientException;
 -}
 -
 -int
 -I830ProcXineramaQueryScreens(ClientPtr client)
 -{
 -    xXineramaQueryScreensReply	rep;
 -
 -    REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
 -
 -    rep.type = X_Reply;
 -    rep.sequenceNumber = client->sequence;
 -    rep.number = (I830noPanoramiXExtension) ? 0 : I830XineramaNumScreens;
 -    rep.length = rep.number * sz_XineramaScreenInfo >> 2;
 -    if(client->swapped) {
 -       register int n;
 -       swaps(&rep.sequenceNumber, n);
 -       swapl(&rep.length, n);
 -       swapl(&rep.number, n);
 -    }
 -    WriteToClient(client, sizeof(xXineramaQueryScreensReply), (char *)&rep);
 -
 -    if(!I830noPanoramiXExtension) {
 -       xXineramaScreenInfo scratch;
 -       int i;
 -
 -       for(i = 0; i < I830XineramaNumScreens; i++) {
 -	  scratch.x_org  = I830XineramadataPtr[i].x;
 -	  scratch.y_org  = I830XineramadataPtr[i].y;
 -	  scratch.width  = I830XineramadataPtr[i].width;
 -	  scratch.height = I830XineramadataPtr[i].height;
 -	  if(client->swapped) {
 -	     register int n;
 -	     swaps(&scratch.x_org, n);
 -	     swaps(&scratch.y_org, n);
 -	     swaps(&scratch.width, n);
 -	     swaps(&scratch.height, n);
 -	  }
 -	  WriteToClient(client, sz_XineramaScreenInfo, (char *)&scratch);
 -       }
 -    }
 -
 -    return client->noClientException;
 -}
 -
 -static int
 -I830ProcXineramaDispatch(ClientPtr client)
 -{
 -    REQUEST(xReq);
 -    switch (stuff->data) {
 -	case X_PanoramiXQueryVersion:
 -	     return I830ProcXineramaQueryVersion(client);
 -	case X_PanoramiXGetState:
 -	     return I830ProcXineramaGetState(client);
 -	case X_PanoramiXGetScreenCount:
 -	     return I830ProcXineramaGetScreenCount(client);
 -	case X_PanoramiXGetScreenSize:
 -	     return I830ProcXineramaGetScreenSize(client);
 -	case X_XineramaIsActive:
 -	     return I830ProcXineramaIsActive(client);
 -	case X_XineramaQueryScreens:
 -	     return I830ProcXineramaQueryScreens(client);
 -    }
 -    return BadRequest;
 -}
 -
 -/* SProc */
 -
 -static int
 -I830SProcXineramaQueryVersion (ClientPtr client)
 -{
 -    REQUEST(xPanoramiXQueryVersionReq);
 -    register int n;
 -    swaps(&stuff->length,n);
 -    REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq);
 -    return I830ProcXineramaQueryVersion(client);
 -}
 -
 -static int
 -I830SProcXineramaGetState(ClientPtr client)
 -{
 -    REQUEST(xPanoramiXGetStateReq);
 -    register int n;
 -    swaps (&stuff->length, n);
 -    REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
 -    return I830ProcXineramaGetState(client);
 -}
 -
 -static int
 -I830SProcXineramaGetScreenCount(ClientPtr client)
 -{
 -    REQUEST(xPanoramiXGetScreenCountReq);
 -    register int n;
 -    swaps (&stuff->length, n);
 -    REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
 -    return I830ProcXineramaGetScreenCount(client);
 -}
 -
 -static int
 -I830SProcXineramaGetScreenSize(ClientPtr client)
 -{
 -    REQUEST(xPanoramiXGetScreenSizeReq);
 -    register int n;
 -    swaps (&stuff->length, n);
 -    REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
 -    return I830ProcXineramaGetScreenSize(client);
 -}
 -
 -static int
 -I830SProcXineramaIsActive(ClientPtr client)
 -{
 -    REQUEST(xXineramaIsActiveReq);
 -    register int n;
 -    swaps (&stuff->length, n);
 -    REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
 -    return I830ProcXineramaIsActive(client);
 -}
 -
 -static int
 -I830SProcXineramaQueryScreens(ClientPtr client)
 -{
 -    REQUEST(xXineramaQueryScreensReq);
 -    register int n;
 -    swaps (&stuff->length, n);
 -    REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
 -    return I830ProcXineramaQueryScreens(client);
 -}
 -
 -int
 -I830SProcXineramaDispatch(ClientPtr client)
 -{
 -    REQUEST(xReq);
 -    switch (stuff->data) {
 -	case X_PanoramiXQueryVersion:
 -	     return I830SProcXineramaQueryVersion(client);
 -	case X_PanoramiXGetState:
 -	     return I830SProcXineramaGetState(client);
 -	case X_PanoramiXGetScreenCount:
 -	     return I830SProcXineramaGetScreenCount(client);
 -	case X_PanoramiXGetScreenSize:
 -	     return I830SProcXineramaGetScreenSize(client);
 -	case X_XineramaIsActive:
 -	     return I830SProcXineramaIsActive(client);
 -	case X_XineramaQueryScreens:
 -	     return I830SProcXineramaQueryScreens(client);
 -    }
 -    return BadRequest;
 -}
 -
 -static void
 -I830XineramaResetProc(ExtensionEntry* extEntry)
 -{
 -    /* Called by CloseDownExtensions() */
 -    if(I830XineramadataPtr) {
 -       Xfree(I830XineramadataPtr);
 -       I830XineramadataPtr = NULL;
 -    }
 -}
 -
 -static void
 -I830XineramaExtensionInit(ScrnInfoPtr pScrn)
 -{
 -    I830Ptr	pI830 = I830PTR(pScrn);
 -    Bool	success = FALSE;
 -
 -    if(!(I830XineramadataPtr)) {
 -
 -       if(!pI830->MergedFB) {
 -	  I830noPanoramiXExtension = TRUE;
 -	  pI830->MouseRestrictions = FALSE;
 -	  return;
 -       }
 -
 -#ifdef PANORAMIX
 -       if(!noPanoramiXExtension) {
 -	  xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 -	     "Xinerama active, not initializing Intel Pseudo-Xinerama\n");
 -	  I830noPanoramiXExtension = TRUE;
 -	  pI830->MouseRestrictions = FALSE;
 -	  return;
 -       }
 -#endif
 -
 -       if(I830noPanoramiXExtension) {
 -	  xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 -	      "Intel Pseudo-Xinerama disabled\n");
 -	  pI830->MouseRestrictions = FALSE;
 -	  return;
 -       }
 -
 -       I830XineramaNumScreens = 2;
 -
 -       while(I830XineramaGeneration != serverGeneration) {
 -
 -	  pI830->XineramaExtEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0,0,
 -					I830ProcXineramaDispatch,
 -					I830SProcXineramaDispatch,
 -					I830XineramaResetProc,
 -					StandardMinorOpcode);
 -
 -	  if(!pI830->XineramaExtEntry) break;
 -
 -	  if(!(I830XineramadataPtr = (I830XineramaData *)
 -	        xcalloc(I830XineramaNumScreens, sizeof(I830XineramaData)))) break;
 -
 -	  I830XineramaGeneration = serverGeneration;
 -	  success = TRUE;
 -       }
 -
 -       if(!success) {
 -          xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -	      "Failed to initialize Intel Pseudo-Xinerama extension\n");
 -	  I830noPanoramiXExtension = TRUE;
 -	  pI830->MouseRestrictions = FALSE;
 -	  return;
 -       }
 -
 -       xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 -	  "Intel Pseudo-Xinerama extension initialized\n");
 -
 -       pI830->I830XineramaVX = 0;
 -       pI830->I830XineramaVY = 0;
 -
 -    }
 -
 -    I830UpdateXineramaScreenInfo(pScrn);
 -
 -}
 -
 -static void
 -I830BIOSProbeDDC(ScrnInfoPtr pScrn, int index)
 -{
 -   vbeInfoPtr pVbe;
 -
 -   /* The vbe module gets loaded in PreInit(), so no need to load it here. */
 -
 -   pVbe = VBEInit(NULL, index);
 -   ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
 -}
 -
 -/* Various extended video BIOS functions. 
 - * 100 and 120Hz aren't really supported, they work but only get close
 - * to the requested refresh, and really not close enough.
 - * I've seen 100Hz come out at 104Hz, and 120Hz come out at 128Hz */
 -const int i830refreshes[] = {
 -   43, 56, 60, 70, 72, 75, 85 /* 100, 120 */
 -};
 -static const int nrefreshes = sizeof(i830refreshes) / sizeof(i830refreshes[0]);
 -
 -static Bool
 -Check5fStatus(ScrnInfoPtr pScrn, int func, int ax)
 -{
 -   if (ax == 0x005f)
 -      return TRUE;
 -   else if (ax == 0x015f) {
 -      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -		 "Extended BIOS function 0x%04x failed.\n", func);
 -      return FALSE;
 -   } else if ((ax & 0xff) != 0x5f) {
 -      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -		 "Extended BIOS function 0x%04x not supported.\n", func);
 -      return FALSE;
 -   } else {
 -      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -		 "Extended BIOS function 0x%04x returns 0x%04x.\n",
 -		 func, ax & 0xffff);
 -      return FALSE;
 -   }
 -}
 -
 -static int
 -GetToggleList(ScrnInfoPtr pScrn, int toggle)
 -{
 -   vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
 -
 -   DPRINTF(PFX, "GetToggleList\n");
 -
 -   pVbe->pInt10->num = 0x10;
 -   pVbe->pInt10->ax = 0x5f64;
 -   pVbe->pInt10->bx = 0x500;
 - 
 -   pVbe->pInt10->bx |= toggle;
 -
 -   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
 -   if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) {
 -      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Toggle (%d) 0x%x\n", toggle, pVbe->pInt10->cx);
 -      return pVbe->pInt10->cx & 0xffff;
 -   }
 -
 -   return 0;
 -}
 -
 -static int
 -GetNextDisplayDeviceList(ScrnInfoPtr pScrn, int toggle)
 -{
 -   vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
 -   int devices = 0;
 -   int pipe = 0;
 -   int i;
 -
 -   DPRINTF(PFX, "GetNextDisplayDeviceList\n");
 -
 -   pVbe->pInt10->num = 0x10;
 -   pVbe->pInt10->ax = 0x5f64;
 -   pVbe->pInt10->bx = 0xA00;
 -   pVbe->pInt10->bx |= toggle;
 -   pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base);
 -   pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base);
 -
 -   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
 -   if (!Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax))
 -      return 0;
 -
 -   for (i=0; i<(pVbe->pInt10->cx & 0xff); i++) {
 -      CARD32 VODA = (CARD32)((CARD32*)pVbe->memory)[i];
 -
 -      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Next ACPI _DGS [%d] 0x%lx\n",
 -		i, VODA);
 -
 -      /* Check if it's a custom Video Output Device Attribute */
 -      if (!(VODA & 0x80000000)) 
 -         continue;
 -
 -      pipe = (VODA & 0x000000F0) >> 4;
 -
 -      if (pipe != 0 && pipe != 1) {
 -         pipe = 0;
 -#if 0
 -         ErrorF("PIPE %d\n",pipe);
 -#endif
 -      }
 -
 -      switch ((VODA & 0x00000F00) >> 8) {
 -      case 0x0:
 -      case 0x1: /* CRT */
 -         devices |= PIPE_CRT << (pipe == 1 ? 8 : 0);
 -         break;
 -      case 0x2: /* TV/HDTV */
 -         devices |= PIPE_TV << (pipe == 1 ? 8 : 0);
 -         break;
 -      case 0x3: /* DFP */
 -         devices |= PIPE_DFP << (pipe == 1 ? 8 : 0);
 -         break;
 -      case 0x4: /* LFP */
 -         devices |= PIPE_LFP << (pipe == 1 ? 8 : 0);
 -         break;
 -      }
 -   }
 -
 -   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ACPI Toggle devices 0x%x\n", devices);
 -
 -   return devices;
 -}
 -
 -static int
 -GetAttachableDisplayDeviceList(ScrnInfoPtr pScrn)
 -{
 -   vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
 -   int i;
 -
 -   DPRINTF(PFX, "GetAttachableDisplayDeviceList\n");
 -
 -   pVbe->pInt10->num = 0x10;
 -   pVbe->pInt10->ax = 0x5f64;
 -   pVbe->pInt10->bx = 0x900;
 -   pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base);
 -   pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base);
 -
 -   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
 -   if (!Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax))
 -      return 0;
 -
 -   for (i=0; i<(pVbe->pInt10->cx & 0xff); i++)
 -        xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
 -		"Attachable device 0x%lx.\n", ((CARD32*)pVbe->memory)[i]);
 -
 -   return pVbe->pInt10->cx & 0xffff;
 -}
 -
 -static int
 -BitToRefresh(int bits)
 -{
 -   int i;
 -
 -   for (i = 0; i < nrefreshes; i++)
 -      if (bits & (1 << i))
 -	 return i830refreshes[i];
 -   return 0;
 -}
 -
 -static int
 -GetRefreshRate(ScrnInfoPtr pScrn, int mode, int *availRefresh)
 -{
 -   vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
 -
 -   DPRINTF(PFX, "GetRefreshRate\n");
 -
 -   /* Only 8-bit mode numbers are supported. */
 -   if (mode & 0x100)
 -      return 0;
 -
 -   pVbe->pInt10->num = 0x10;
 -   pVbe->pInt10->ax = 0x5f05;
 -   pVbe->pInt10->bx = (mode & 0xff) | 0x100;
 -
 -   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
 -   if (Check5fStatus(pScrn, 0x5f05, pVbe->pInt10->ax)) {
 -      if (availRefresh)
 -         *availRefresh = pVbe->pInt10->bx;
 -      return BitToRefresh(pVbe->pInt10->cx);
 -   } else
 -      return 0;
 -}
 -
 -struct panelid {
 -	short hsize;
 -	short vsize;
 -	short fptype;
 -	char redbpp;
 -	char greenbpp;
 -	char bluebpp;
 -	char reservedbpp;
 -	int rsvdoffscrnmemsize;
 -	int rsvdoffscrnmemptr;
 -	char reserved[14];
 -};
 -
 -static void
 -I830InterpretPanelID(int scrnIndex, unsigned char *tmp)
 -{
 -    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
 -    struct panelid *block = (struct panelid *)tmp;
 -
 -#define PANEL_DEFAULT_HZ 60
 -
 -   xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 -	 "PanelID returned panel resolution : %dx%d\n", 
 -						block->hsize, block->vsize);
 -
 -   /* If we get bogus values from this, don't accept it */
 -   if (block->hsize == 0 || block->vsize == 0) {
 -   	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 -	 "Bad Panel resolution - ignoring panelID\n");
 -	
 -	return;
 -   }
 -
 -   /* If we have monitor timings then don't overwrite them */
 -   if (pScrn->monitor->nHsync > 0 &&
 -	pScrn->monitor->nVrefresh > 0)
 -	return;
 -
 -   /* With panels, we're always assuming a refresh of 60Hz */
 -
 -   pScrn->monitor->nHsync = 1;
 -   pScrn->monitor->nVrefresh = 1;
 -
 -   /* Give a little tolerance for the selected panel */
 -   pScrn->monitor->hsync[0].lo = (float)((PANEL_DEFAULT_HZ/1.05)*block->vsize)/1000;
 -   pScrn->monitor->hsync[0].hi = (float)((PANEL_DEFAULT_HZ/0.95)*block->vsize)/1000;
 -   pScrn->monitor->vrefresh[0].lo = (float)PANEL_DEFAULT_HZ;
 -   pScrn->monitor->vrefresh[0].hi = (float)PANEL_DEFAULT_HZ;
 -}
 -
 -/* This should probably go into the VBE layer */
 -static unsigned char *
 -vbeReadPanelID(vbeInfoPtr pVbe)
 -{
 -    int RealOff = pVbe->real_mode_base;
 -    pointer page = pVbe->memory;
 -    unsigned char *tmp = NULL;
 -    int screen = pVbe->pInt10->scrnIndex;
 -
 -    pVbe->pInt10->ax = 0x4F11;
 -    pVbe->pInt10->bx = 0x01;
 -    pVbe->pInt10->cx = 0;
 -    pVbe->pInt10->dx = 0;
 -    pVbe->pInt10->es = SEG_ADDR(RealOff);
 -    pVbe->pInt10->di = SEG_OFF(RealOff);
 -    pVbe->pInt10->num = 0x10;
 -
 -    xf86ExecX86int10(pVbe->pInt10);
 -
 -    if ((pVbe->pInt10->ax & 0xff) != 0x4f) {
 -        xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID invalid\n");
 -	goto error;
 -    }
 -    switch (pVbe->pInt10->ax & 0xff00) {
 -    case 0x0:
 -	xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID read successfully\n");
 -  	tmp = (unsigned char *)xnfalloc(32); 
 -  	memcpy(tmp,page,32); 
 -	break;
 -    case 0x100:
 -	xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID read failed\n");	
 -	break;
 -    default:
 -	xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID unknown failure %i\n",
 -		       pVbe->pInt10->ax & 0xff00);
 -	break;
 -    }
 -
 - error:
 -    return tmp;
 -}
 -
 -static void
 -vbeDoPanelID(vbeInfoPtr pVbe)
 -{
 -    unsigned char *PanelID_data;
 -    
 -    if (!pVbe) return;
 -
 -    PanelID_data = vbeReadPanelID(pVbe);
 -
 -    if (!PanelID_data) 
 -	return;
 -    
 -    I830InterpretPanelID(pVbe->pInt10->scrnIndex, PanelID_data);
 -}
 -
 -int 
 -I830GetBestRefresh(ScrnInfoPtr pScrn, int refresh)
 -{
 -   int i;
 -
 -   for (i = nrefreshes - 1; i >= 0; i--) {
 -      /*
 -       * Look for the highest value that the requested (refresh + 2) is
 -       * greater than or equal to.
 -       */
 -      if (i830refreshes[i] <= (refresh + 2))
 -	 break;
 -   }
 -   /* i can be 0 if the requested refresh was higher than the max. */
 -   if (i == 0) {
 -      if (refresh >= i830refreshes[nrefreshes - 1])
 -         i = nrefreshes - 1;
 -   }
 -
 -   return i;
 -}
 -
 -static int
 -SetRefreshRate(ScrnInfoPtr pScrn, int mode, int refresh)
 -{
 -   vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
 -   int i = I830GetBestRefresh(pScrn, refresh);
 -
 -   DPRINTF(PFX, "SetRefreshRate: mode 0x%x, refresh: %d\n", mode, refresh);
 -
 -   DPRINTF(PFX, "Setting refresh rate to %dHz for mode 0x%02x\n",
 -	   i830refreshes[i], mode & 0xff);
 -
 -   /* Only 8-bit mode numbers are supported. */
 -   if (mode & 0x100)
 -      return 0;
 -
 -   pVbe->pInt10->num = 0x10;
 -   pVbe->pInt10->ax = 0x5f05;
 -   pVbe->pInt10->bx = mode & 0xff;
 -
 -   pVbe->pInt10->cx = 1 << i;
 -   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
 -   if (Check5fStatus(pScrn, 0x5f05, pVbe->pInt10->ax))
 -      return i830refreshes[i];
 -   else
 -      return 0;
 -}
 -
 -#if 0
 -static Bool
 -SetPowerStatus(ScrnInfoPtr pScrn, int mode)
 -{
 -   vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
 -
 -   pVbe->pInt10->num = 0x10;
 -   pVbe->pInt10->ax = 0x5f64;
 -   pVbe->pInt10->bx = 0x0800 | mode;
 -   pVbe->pInt10->cx = 0x0000;
 -
 -   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
 -   if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax))
 -      return TRUE;
 -  
 -   return FALSE;
 -}
 -#endif
 -
 -static Bool
 -GetModeSupport(ScrnInfoPtr pScrn, int modePipeA, int modePipeB,
 -	       int devicesPipeA, int devicesPipeB, int *maxBandwidth,
 -	       int *bandwidthPipeA, int *bandwidthPipeB)
 -{
 -   vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
 -
 -   DPRINTF(PFX, "GetModeSupport: modes 0x%x, 0x%x, devices: 0x%x, 0x%x\n",
 -	   modePipeA, modePipeB, devicesPipeA, devicesPipeB);
 -
 -   /* Only 8-bit mode numbers are supported. */
 -   if ((modePipeA & 0x100) || (modePipeB & 0x100))
 -      return FALSE;
 -
 -   pVbe->pInt10->num = 0x10;
 -   pVbe->pInt10->ax = 0x5f28;
 -   pVbe->pInt10->bx = (modePipeA & 0xff) | ((modePipeB & 0xff) << 8);
 -   if ((devicesPipeA & 0x80) || (devicesPipeB & 0x80))
 -      pVbe->pInt10->cx = 0x8000;
 -   else
 -      pVbe->pInt10->cx = (devicesPipeA & 0xff) | ((devicesPipeB & 0xff) << 8);
 -
 -   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
 -   if (Check5fStatus(pScrn, 0x5f28, pVbe->pInt10->ax)) {
 -      if (maxBandwidth)
 -	 *maxBandwidth = pVbe->pInt10->cx;
 -      if (bandwidthPipeA)
 -	 *bandwidthPipeA = pVbe->pInt10->dx & 0xffff;
 -      /* XXX For XFree86 4.2.0 and earlier, ->dx is truncated to 16 bits. */
 -      if (bandwidthPipeB)
 -	 *bandwidthPipeB = (pVbe->pInt10->dx >> 16) & 0xffff;
 -      return TRUE;
 -   } else
 -      return FALSE;
 -}
 -
 -#if 0
 -static int
 -GetLFPCompMode(ScrnInfoPtr pScrn)
 -{
 -   vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
 -
 -   DPRINTF(PFX, "GetLFPCompMode\n");
 -
 -   pVbe->pInt10->num = 0x10;
 -   pVbe->pInt10->ax = 0x5f61;
 -   pVbe->pInt10->bx = 0x100;
 -
 -   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
 -   if (Check5fStatus(pScrn, 0x5f61, pVbe->pInt10->ax))
 -      return pVbe->pInt10->cx & 0xffff;
 -   else
 -      return -1;
 -}
 -
 -static Bool
 -SetLFPCompMode(ScrnInfoPtr pScrn, int compMode)
 -{
 -   vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
 -
 -   DPRINTF(PFX, "SetLFPCompMode: compMode %d\n", compMode);
 -
 -   pVbe->pInt10->num = 0x10;
 -   pVbe->pInt10->ax = 0x5f61;
 -   pVbe->pInt10->bx = 0;
 -   pVbe->pInt10->cx = compMode;
 -
 -   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
 -   return Check5fStatus(pScrn, 0x5f61, pVbe->pInt10->ax);
 -}
 -#endif
 -
 -static int
 -GetDisplayDevices(ScrnInfoPtr pScrn)
 -{
 -   I830Ptr pI830 = I830PTR(pScrn);
 -   vbeInfoPtr pVbe = pI830->pVbe;
 -
 -   DPRINTF(PFX, "GetDisplayDevices\n");
 -
 -#if 0
 -   {
 -      CARD32 temp;
 -      ErrorF("ADPA is 0x%08x\n", INREG(ADPA));
 -      ErrorF("DVOA is 0x%08x\n", INREG(DVOA));
 -      ErrorF("DVOB is 0x%08x\n", INREG(DVOB));
 -      ErrorF("DVOC is 0x%08x\n", INREG(DVOC));
 -      ErrorF("LVDS is 0x%08x\n", INREG(LVDS));
 -      temp = INREG(DVOA_SRCDIM);
 -      ErrorF("DVOA_SRCDIM is 0x%08x (%d x %d)\n", temp,
 -	     (temp >> 12) & 0xfff, temp & 0xfff);
 -      temp = INREG(DVOB_SRCDIM);
 -      ErrorF("DVOB_SRCDIM is 0x%08x (%d x %d)\n", temp,
 -	     (temp >> 12) & 0xfff, temp & 0xfff);
 -      temp = INREG(DVOC_SRCDIM);
 -      ErrorF("DVOC_SRCDIM is 0x%08x (%d x %d)\n", temp,
 -	     (temp >> 12) & 0xfff, temp & 0xfff);
 -      ErrorF("SWF0 is 0x%08x\n", INREG(SWF0));
 -      ErrorF("SWF4 is 0x%08x\n", INREG(SWF4));
 -   }
 -#endif
 -
 -   pVbe->pInt10->num = 0x10;
 -   pVbe->pInt10->ax = 0x5f64;
 -   pVbe->pInt10->bx = 0x100;
 -
 -   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
 -   if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) {
 -      return pVbe->pInt10->cx & 0xffff;
 -   } else {
 -      if (pI830->PciInfo->chipType == PCI_CHIP_E7221_G) /* FIXED CONFIG */
 -         return PIPE_CRT;
 -      else
 -         return -1;
 -   }
 -}
 -
 -static int
 -GetBIOSPipe(ScrnInfoPtr pScrn)
 -{
 -   I830Ptr pI830 = I830PTR(pScrn);
 -   vbeInfoPtr pVbe = pI830->pVbe;
 -   int pipe;
 -
 -   DPRINTF(PFX, "GetBIOSPipe:\n");
 -
 -   /* single pipe machines should always return Pipe A */
 -   if (pI830->availablePipes == 1) return 0;
 -
 -   pVbe->pInt10->num = 0x10;
 -   pVbe->pInt10->ax = 0x5f1c;
 -   pVbe->pInt10->bx = 0x100;
 -
 -   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
 -   if (Check5fStatus(pScrn, 0x5f1c, pVbe->pInt10->ax)) {
 -      if (pI830->newPipeSwitch) {
 -         pipe = ((pVbe->pInt10->bx & 0x0001));
 -      } else {
 -         pipe = ((pVbe->pInt10->cx & 0x0100) >> 8);
 -      }
 -      return pipe;
 -   }
 -
 -   /* failed, assume pipe A */
 -   return 0;
 -}
 -
 -static Bool
 -SetBIOSPipe(ScrnInfoPtr pScrn, int pipe)
 -{
 -   I830Ptr pI830 = I830PTR(pScrn);
 -   vbeInfoPtr pVbe = pI830->pVbe;
 -
 -   DPRINTF(PFX, "SetBIOSPipe: pipe 0x%x\n", pipe);
 -
 -   /* single pipe machines should always return TRUE */
 -   if (pI830->availablePipes == 1) return TRUE;
 -
 -   pVbe->pInt10->num = 0x10;
 -   pVbe->pInt10->ax = 0x5f1c;
 -   if (pI830->newPipeSwitch) {
 -      pVbe->pInt10->bx = pipe;
 -      pVbe->pInt10->cx = 0;
 -   } else {
 -      pVbe->pInt10->bx = 0x0;
 -      pVbe->pInt10->cx = pipe << 8;
 -   }
 -
 -   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
 -   if (Check5fStatus(pScrn, 0x5f1c, pVbe->pInt10->ax)) {
 -      return TRUE;
 -   }
 -	
 -   return FALSE;
 -}
 -
 -static Bool
 -SetPipeAccess(ScrnInfoPtr pScrn)
 -{
 -   I830Ptr pI830 = I830PTR(pScrn);
 -
 -   /* Don't try messing with the pipe, unless we're dual head */
 -   if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone || pI830->MergedFB || pI830->origPipe != pI830->pipe) {
 -      if (!SetBIOSPipe(pScrn, pI830->pipe))
 -         return FALSE;
 -   }
 -   
 -   return TRUE;
 -}
 -
 -static Bool
 -I830Set640x480(ScrnInfoPtr pScrn)
 -{
 -   I830Ptr pI830 = I830PTR(pScrn);
 -   int m = 0x30; /* 640x480 8bpp */
 -
 -   switch (pScrn->depth) {
 -   case 15:
 -	 m = 0x40;
 -	 break;
 -   case 16:
 -	 m = 0x41;
 -	 break;
 -   case 24:
 -	 m = 0x50;
 -	 break;
 -   }
 -
 -   m |= (1 << 15) | (1 << 14);
 -   if (VBESetVBEMode(pI830->pVbe, m, NULL))
 -	   return TRUE;
 -
 -
 -   /* if the first failed, let's try the next - usually 800x600 */
 -   m = 0x32;
 -   switch (pScrn->depth) {
 -   case 15:
 -   case 16:
 -	 m = 0x42;
 -	 break;
 -   case 24:
 -	 m = 0x52;
 -	 break;
 -   }
 -   m |= (1 << 15) | (1 << 14);
 -
 -   if (VBESetVBEMode(pI830->pVbe, m, NULL))
 -	   return TRUE;
 -
 -   return FALSE;
 -}
 -
 -/* This is needed for SetDisplayDevices to work correctly on I915G.
 - * Enable for all chipsets now as it has no bad side effects, apart
 - * from slightly longer startup time.
 - */
 -#define I915G_WORKAROUND
 -
 -static Bool
 -SetDisplayDevices(ScrnInfoPtr pScrn, int devices)
 -{
 -   I830Ptr pI830 = I830PTR(pScrn);
 -   vbeInfoPtr pVbe = pI830->pVbe;
 -   CARD32 temp;
 -   int singlepipe = 0;
 -#ifdef I915G_WORKAROUND
 -   int getmode1;
 -   Bool setmode = FALSE;
 -#endif
 -
 -   DPRINTF(PFX, "SetDisplayDevices: devices 0x%x\n", devices);
 -
 -   if (!pI830->specifiedMonitor)
 -      return TRUE;
 -
 -#ifdef I915G_WORKAROUND
 -   if (pI830->preinit)
 -      setmode = TRUE;
 -   if (pI830->leaving)
 -      setmode = FALSE;
 -   if (pI830->closing)
 -      setmode = FALSE;
 -
 -   if (setmode) {
 -      VBEGetVBEMode(pVbe, &getmode1);
 -      I830Set640x480(pScrn);
 -   }
 -#endif
 -
 -   pVbe->pInt10->num = 0x10;
 -   pVbe->pInt10->ax = 0x5f64;
 -   pVbe->pInt10->bx = 0x1;
 -   pVbe->pInt10->cx = devices;
 -
 -   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
 -   if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) {
 -#ifdef I915G_WORKAROUND
 -      if (setmode) {
 -  	 VBESetVBEMode(pI830->pVbe, getmode1 | 1<<15, NULL);
 -      }
 -#endif
 -      pI830->pipeEnabled[0] = (devices & 0xff) ? TRUE : FALSE;
 -      pI830->pipeEnabled[1] = (devices & 0xff00) ? TRUE : FALSE;
 -
 -      return TRUE;
 -   }
 -
 -#ifdef I915G_WORKAROUND
 -   if (setmode)
 -      VBESetVBEMode(pI830->pVbe, getmode1 | 1<<15, NULL);
 -#endif
 -
 -   if (devices & 0xff) {
 -      pVbe->pInt10->num = 0x10;
 -      pVbe->pInt10->ax = 0x5f64;
 -      pVbe->pInt10->bx = 0x1;
 -      pVbe->pInt10->cx = devices & 0xff;
 -
 -      xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
 -      if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) {
 -         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -	 	"Successfully set display devices to 0x%x.\n",devices & 0xff);
 -         singlepipe = devices & 0xff00; /* set alternate */
 -      } else {
 -         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -	 	"Failed to set display devices to 0x%x.\n",devices & 0xff);
 -         singlepipe = devices;
 -      }
 -   } else
 -      singlepipe = devices; 
 -
 -   if (singlepipe == devices && devices & 0xff00) {
 -      pVbe->pInt10->num = 0x10;
 -      pVbe->pInt10->ax = 0x5f64;
 -      pVbe->pInt10->bx = 0x1;
 -      pVbe->pInt10->cx = devices & 0xff00;
 -
 -      xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
 -      if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) {
 -         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -	 	"Successfully set display devices to 0x%x.\n",devices & 0xff00);
 -         singlepipe = devices & 0xff; /* set alternate */
 -      } else {
 -         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -	 	"Failed to set display devices to 0x%x.\n",devices & 0xff00);
 -         singlepipe = devices;
 -      }
 -   } 
 -
 -   /* LVDS doesn't exist on these */
 -   if (IS_I830(pI830) || IS_845G(pI830) || IS_I865G(pI830) || IS_I915G(pI830) || IS_I945G(pI830) || IS_I965G(pI830))
 -      singlepipe &= ~(PIPE_LFP | (PIPE_LFP<<8));
 -
 -   if (pI830->availablePipes == 1) 
 -      singlepipe &= 0xFF;
 -
 -   /* Disable LVDS */
 -   if (singlepipe & PIPE_LFP)  {
 -      /* LFP on PipeA is unlikely! */
 -      OUTREG(0x61200, INREG(0x61200) & ~0x80000000);
 -      OUTREG(0x61204, INREG(0x61204) & ~0x00000001);
 -      while ((INREG(0x61200) & 0x80000000) || (INREG(0x61204) & 1));
 -      /* Fix up LVDS */
 -      OUTREG(LVDS, (INREG(LVDS) & ~1<<30) | 0x80000300);
 -      /* Enable LVDS */
 -      OUTREG(0x61200, INREG(0x61200) | 0x80000000);
 -      OUTREG(0x61204, INREG(0x61204) | 0x00000001);
 -      while (!(INREG(0x61200) & 0x80000000) && !(INREG(0x61204) & 1));
 -      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -	 	"Enabling LVDS directly. Pipe A.\n");
 -   } else
 -   if (singlepipe & (PIPE_LFP << 8))  {
 -      OUTREG(0x61200, INREG(0x61200) & ~0x80000000);
 -      OUTREG(0x61204, INREG(0x61204) & ~0x00000001);
 -      while ((INREG(0x61200) & 0x80000000) || (INREG(0x61204) & 1));
 -      /* Fix up LVDS */
 -      OUTREG(LVDS, (INREG(LVDS) | 1<<30) | 0x80000300);
 -      /* Enable LVDS */
 -      OUTREG(0x61200, INREG(0x61200) | 0x80000000);
 -      OUTREG(0x61204, INREG(0x61204) | 0x00000001);
 -      while (!(INREG(0x61200) & 0x80000000) && !(INREG(0x61204) & 1));
 -      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -	 	"Enabling LVDS directly. Pipe B.\n");
 -   }
 -   else if (!(IS_I830(pI830) || IS_845G(pI830) || IS_I865G(pI830))) {
 -      if (!(devices & (PIPE_LFP | PIPE_LFP<<8))) {
 -         OUTREG(0x61200, INREG(0x61200) & ~0x80000000);
 -         OUTREG(0x61204, INREG(0x61204) & ~0x00000001);
 -         while ((INREG(0x61200) & 0x80000000) || (INREG(0x61204) & 1));
 -         /* Fix up LVDS */
 -         OUTREG(LVDS, (INREG(LVDS) | 1<<30) & ~0x80000300);
 -         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -	 	"Disabling LVDS directly.\n");
 -      }
 -   }
 -
 -   /* Now try to program the registers directly if the BIOS failed. */
 -   temp = INREG(ADPA);
 -   temp &= ~(ADPA_DAC_ENABLE | ADPA_PIPE_SELECT_MASK);
 -   temp &= ~(ADPA_VSYNC_CNTL_DISABLE | ADPA_HSYNC_CNTL_DISABLE);
 -   /* Turn on ADPA */
 -   if (singlepipe & PIPE_CRT)  {
 -      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -	 	"Enabling ADPA directly. Pipe A.\n");
 -      temp |= ADPA_DAC_ENABLE | ADPA_PIPE_A_SELECT;
 -      OUTREG(ADPA, temp);
 -   } else
 -   if (singlepipe & (PIPE_CRT << 8)) {
 -      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -	 	"Enabling ADPA directly. Pipe B.\n");
 -      temp |= ADPA_DAC_ENABLE | ADPA_PIPE_B_SELECT;
 -      OUTREG(ADPA, temp);
 -   } 
 -   else {
 -      if (!(devices & (PIPE_CRT | PIPE_CRT<<8))) {
 -         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -	 	"Disabling ADPA directly.\n");
 -         temp |= ADPA_VSYNC_CNTL_DISABLE | ADPA_HSYNC_CNTL_DISABLE;
 -         OUTREG(ADPA, temp);
 -      }
 -   }
 -
 -   xf86DrvMsg(pScrn->scrnIndex, X_WARNING,"Writing config directly to SWF0.\n");
 -   temp = INREG(SWF0);
 -   OUTREG(SWF0, (temp & ~(0xffff)) | (devices & 0xffff));
 -
 -   if (GetDisplayDevices(pScrn) != devices) {
 -      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -		 "SetDisplayDevices failed with devices 0x%x instead of 0x%x\n",
 -	         GetDisplayDevices(pScrn), devices);
 -      return FALSE;
 -   }
 -
 -   pI830->pipeEnabled[0] = (devices & 0xff) ? TRUE : FALSE;
 -   pI830->pipeEnabled[1] = (devices & 0xff00) ? TRUE : FALSE;
 -
 -   return TRUE;
 -}
 -
 -static Bool
 -GetBIOSVersion(ScrnInfoPtr pScrn, unsigned int *version)
 -{
 -   vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
 -
 -   DPRINTF(PFX, "GetBIOSVersion\n");
 -
 -   pVbe->pInt10->num = 0x10;
 -   pVbe->pInt10->ax = 0x5f01;
 -
 -   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
 -   if (Check5fStatus(pScrn, 0x5f01, pVbe->pInt10->ax)) {
 -      *version = pVbe->pInt10->bx;
 -      return TRUE;
 -   }
 -
 -   *version = 0;
 -   return FALSE;
 -}
 -
 -static Bool
 -GetDevicePresence(ScrnInfoPtr pScrn, Bool *required, int *attached,
 -		  int *encoderPresent)
 -{
 -   vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
 -
 -   DPRINTF(PFX, "GetDevicePresence\n");
 -
 -   pVbe->pInt10->num = 0x10;
 -   pVbe->pInt10->ax = 0x5f64;
 -   pVbe->pInt10->bx = 0x200;
 -
 -   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
 -   if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) {
 -      if (required)
 -	 *required = ((pVbe->pInt10->bx & 0x1) == 0);
 -      if (attached)
 -	 *attached = (pVbe->pInt10->cx >> 8) & 0xff;
 -      if (encoderPresent)
 -	 *encoderPresent = pVbe->pInt10->cx & 0xff;
 -      return TRUE;
 -   } else
 -      return FALSE;
 -}
 -
 -static Bool
 -GetDisplayInfo(ScrnInfoPtr pScrn, int device, Bool *attached, Bool *present,
 -	       short *x, short *y)
 -{
 -   vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
 -
 -   DPRINTF(PFX, "GetDisplayInfo: device: 0x%x\n", device);
 -
 -   switch (device & 0xff) {
 -   case PIPE_CRT:
 -   case PIPE_TV:
 -   case PIPE_DFP:
 -   case PIPE_LFP:
 -   case PIPE_CRT2:
 -   case PIPE_TV2:
 -   case PIPE_DFP2:
 -   case PIPE_LFP2:
 -      break;
 -   default:
 -      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 -		 "GetDisplayInfo: invalid device: 0x%x\n", device & 0xff);
 -      return FALSE;
 -   }
 -
 -   pVbe->pInt10->num = 0x10;
 -   pVbe->pInt10->ax = 0x5f64;
 -   pVbe->pInt10->bx = 0x300;
 -   pVbe->pInt10->cx = device & 0xff;
 -
 -   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
 -   if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) {
 -      if (attached)
 -	 *attached = ((pVbe->pInt10->bx & 0x2) != 0);
 -      if (present)
 -	 *present = ((pVbe->pInt10->bx & 0x1) != 0);
 -      if (pVbe->pInt10->cx != (device & 0xff)) {
 -	 if (y) {
 -	    *y = pVbe->pInt10->cx & 0xffff;
 -	 }
 -	 if (x) {
 -	    *x = (pVbe->pInt10->cx >> 16) & 0xffff;
 -	 }
 -      }
 -      return TRUE;
 -   } else
 -      return FALSE;
 -}
 -
 -/*
 - * Returns a string matching the device corresponding to the first bit set
 - * in "device".  savedDevice is then set to device with that bit cleared.
 - * Subsequent calls with device == -1 will use savedDevice.
 - */
 -
 -static const char *displayDevices[] = {
 -   "CRT",
 -   "TV",
 -   "DFP (digital flat panel)",
 -   "LFP (local flat panel)",
 -   "Second (second CRT)",
 -   "TV2 (second TV)",
 -   "DFP2 (second digital flat panel)",
 -   "LFP2 (second local flat panel)",
 -   NULL
 -};
 -
 -static const char *
 -DeviceToString(int device)
 -{
 -   static int savedDevice = -1;
 -   int bit = 0;
 -   const char *name;
 -
 -   if (device == -1) {
 -      device = savedDevice;
 -      bit = 0;
 -   }
 -
 -   if (device == -1)
 -      return NULL;
 -
 -   while (displayDevices[bit]) {
 -      if (device & (1 << bit)) {
 -	 name = displayDevices[bit];
 -	 savedDevice = device & ~(1 << bit);
 -	 bit++;
 -	 return name;
 -      }
 -      bit++;
 -   }
 -   return NULL;
 -}
 -
 -static void
 -PrintDisplayDeviceInfo(ScrnInfoPtr pScrn)
 -{
 -   I830Ptr pI830 = I830PTR(pScrn);
 -   int pipe, n;
 -   int displays;
 -
 -   DPRINTF(PFX, "PrintDisplayDeviceInfo\n");
 -
 -   displays = pI830->operatingDevices;
 -   if (displays == -1) {
 -      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 -		 "No active display devices.\n");
 -      return;
 -   }
 -
 -   /* Check for active devices connected to each display pipe. */
 -   for (n = 0; n < pI830->availablePipes; n++) {
 -      pipe = ((displays >> PIPE_SHIFT(n)) & PIPE_ACTIVE_MASK);
 -      if (pipe) {
 -	 const char *name;
 -
 -	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 -		    "Currently active displays on Pipe %c:\n", PIPE_NAME(n));
 -	 name = DeviceToString(pipe);
 -	 do {
 -	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\t%s\n", name);
 -	    name = DeviceToString(-1);
 -	 } while (name);
 -
 -      } else {
 -	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 -		    "No active displays on Pipe %c.\n", PIPE_NAME(n));
 -      }
 -
 -      if (pI830->pipeDisplaySize[n].x2 != 0) {
 -	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 -		    "Lowest common panel size for pipe %c is %d x %d\n",
 -		    PIPE_NAME(n), pI830->pipeDisplaySize[n].x2,
 -		    pI830->pipeDisplaySize[n].y2);
 -      } else if (pI830->pipeEnabled[n] && pipe & ~PIPE_CRT_ACTIVE) {
 -	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 -		    "No display size information available for pipe %c.\n",
 -		    PIPE_NAME(n));
 -      }
 -   }
 -}
 -
 -static void
 -GetPipeSizes(ScrnInfoPtr pScrn)
 -{
 -   I830Ptr pI830 = I830PTR(pScrn);
 -   int pipe, n;
 -   DisplayType i;
 -
 -   DPRINTF(PFX, "GetPipeSizes\n");
 -
 -
 -   for (n = 0; n < pI830->availablePipes; n++) {
 -      pipe = (pI830->operatingDevices >> PIPE_SHIFT(n)) & PIPE_ACTIVE_MASK;
 -      pI830->pipeDisplaySize[n].x1 = pI830->pipeDisplaySize[n].y1 = 0;
 -      pI830->pipeDisplaySize[n].x2 = pI830->pipeDisplaySize[n].y2 = 4096;
 -      for (i = 0; i < NumDisplayTypes; i++) {
 -         if (pipe & (1 << i) & PIPE_SIZED_DISP_MASK) {
 -	    if (pI830->displaySize[i].x2 != 0) {
 -	       xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 -		          "Size of device %s is %d x %d\n",
 -		          displayDevices[i],
 -		          pI830->displaySize[i].x2,
 -		          pI830->displaySize[i].y2);
 -	       if (pI830->displaySize[i].x2 < pI830->pipeDisplaySize[n].x2)
 -	          pI830->pipeDisplaySize[n].x2 = pI830->displaySize[i].x2;
 -	       if (pI830->displaySize[i].y2 < pI830->pipeDisplaySize[n].y2)
 -	          pI830->pipeDisplaySize[n].y2 = pI830->displaySize[i].y2;
 -	    }
 -         }
 -      }
 -
 -      if (pI830->pipeDisplaySize[n].x2 == 4096)
 -         pI830->pipeDisplaySize[n].x2 = 0;
 -      if (pI830->pipeDisplaySize[n].y2 == 4096)
 -         pI830->pipeDisplaySize[n].y2 = 0;
 -   }
 -}
 -
 -static Bool
 -I830DetectDisplayDevice(ScrnInfoPtr pScrn)
 -{
 -   I830Ptr pI830 = I830PTR(pScrn);
 -   int pipe, n;
 -   DisplayType i;
 -   
 -   /* This seems to lockup some Dell BIOS'. So it's on option to turn on */
 -   if (pI830->displayInfo) {
 -       xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 -		  "Broken BIOSes cause the system to hang here.\n"
 -		  "\t      If you encounter this problem please add \n"
 -		  "\t\t Option \"DisplayInfo\" \"FALSE\"\n"
 -		  "\t      to the Device section of your XF86Config file.\n");
 -      for (i = 0; i < NumDisplayTypes; i++) {
 -         if (GetDisplayInfo(pScrn, 1 << i, &pI830->displayAttached[i],
 -			 &pI830->displayPresent[i],
 -			 &pI830->displaySize[i].x2,
 -			 &pI830->displaySize[i].y2)) {
 -	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 -		    "Display Info: %s: attached: %s, present: %s, size: "
 -		    "(%d,%d)\n", displayDevices[i],
 -		    BOOLTOSTRING(pI830->displayAttached[i]),
 -		    BOOLTOSTRING(pI830->displayPresent[i]),
 -		    pI830->displaySize[i].x2, pI830->displaySize[i].y2);
 -         }
 -      }
 -   }
 -
 -   /* Check for active devices connected to each display pipe. */
 -   for (n = 0; n < pI830->availablePipes; n++) {
 -      pipe = ((pI830->operatingDevices >> PIPE_SHIFT(n)) & PIPE_ACTIVE_MASK);
 -      if (pipe)
 -	 pI830->pipeEnabled[n] = TRUE;
 -      else
 -	 pI830->pipeEnabled[n] = FALSE;
 -   }
 -
 -   GetPipeSizes(pScrn);
 -
 -   return TRUE;
 -}
 -
 -static int
 -I830DetectMemory(ScrnInfoPtr pScrn)
 -{
 -   I830Ptr pI830 = I830PTR(pScrn);
 -   PCITAG bridge;
 -   CARD16 gmch_ctrl;
 -   int memsize = 0;
 -   int range;
 -
 -   bridge = pciTag(0, 0, 0);		/* This is always the host bridge */
 -   gmch_ctrl = pciReadWord(bridge, I830_GMCH_CTRL);
 +   bridge = pciTag(0, 0, 0);		/* This is always the host bridge */
 +   gmch_ctrl = pciReadWord(bridge, I830_GMCH_CTRL);
  
     /* We need to reduce the stolen size, by the GTT and the popup.
 -    * The GTT varying according the the FbMapSize and the popup is 4KB. */
 -   if (IS_I965G(pI830))
 -      range = 512 + 4; /* Fixed 512KB size for i965 */
 -   else
 -      range = (pI830->FbMapSize / MB(1)) + 4;
 +    * The GTT varying according the the FbMapSize and the popup is 4KB */
 +   range = (pI830->FbMapSize / (1024*1024)) + 4;
  
     if (IS_I85X(pI830) || IS_I865G(pI830) || IS_I9XX(pI830)) {
        switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
@@@ -653,85 -3122,378 +644,91 @@@
  	 break;
        case I830_GMCH_GMS_LOCAL:
  	 memsize = 0;
 -	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -		    "Local memory found, but won't be used.\n");
 -	 break;
 -      }
 -   }
 -
 -#if 0
 -   /* And 64KB page aligned */
 -   memsize &= ~0xFFFF;
 -#endif
 -
 -   if (memsize > 0) {
 -      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 -		 "detected %d kB stolen memory.\n", memsize / 1024);
 -   } else {
 -      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "no video memory detected.\n");
 -   }
 -   return memsize;
 -}
 -
 -static Bool
 -I830MapMMIO(ScrnInfoPtr pScrn)
 -{
 -   int mmioFlags;
 -   I830Ptr pI830 = I830PTR(pScrn);
 -
 -#if !defined(__alpha__)
 -   mmioFlags = VIDMEM_MMIO | VIDMEM_READSIDEEFFECT;
 -#else
 -   mmioFlags = VIDMEM_MMIO | VIDMEM_READSIDEEFFECT | VIDMEM_SPARSE;
 -#endif
 -
 -   pI830->MMIOBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags,
 -				   pI830->PciTag,
 -				   pI830->MMIOAddr, I810_REG_SIZE);
 -   if (!pI830->MMIOBase)
 -      return FALSE;
 -   return TRUE;
 -}
 -
 -static Bool
 -I830MapMem(ScrnInfoPtr pScrn)
 -{
 -   I830Ptr pI830 = I830PTR(pScrn);
 -   long i;
 -
 -   for (i = 2; i < pI830->FbMapSize; i <<= 1) ;
 -   pI830->FbMapSize = i;
 -
 -   if (!I830MapMMIO(pScrn))
 -      return FALSE;
 -
 -   pI830->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
 -				 pI830->PciTag,
 -				 pI830->LinearAddr, pI830->FbMapSize);
 -   if (!pI830->FbBase)
 -      return FALSE;
 -
 -   if (I830IsPrimary(pScrn))
 -   pI830->LpRing->virtual_start = pI830->FbBase + pI830->LpRing->mem.Start;
 -
 -   return TRUE;
 -}
 -
 -static void
 -I830UnmapMMIO(ScrnInfoPtr pScrn)
 -{
 -   I830Ptr pI830 = I830PTR(pScrn);
 -
 -   xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pI830->MMIOBase,
 -		   I810_REG_SIZE);
 -   pI830->MMIOBase = 0;
 -}
 -
 -static Bool
 -I830UnmapMem(ScrnInfoPtr pScrn)
 -{
 -   I830Ptr pI830 = I830PTR(pScrn);
 -
 -   xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pI830->FbBase,
 -		   pI830->FbMapSize);
 -   pI830->FbBase = 0;
 -   I830UnmapMMIO(pScrn);
 -   return TRUE;
 -}
 -
 -#ifndef HAVE_GET_PUT_BIOSMEMSIZE
 -#define HAVE_GET_PUT_BIOSMEMSIZE 1
 -#endif
 -
 -#if HAVE_GET_PUT_BIOSMEMSIZE
 -/*
 - * Tell the BIOS how much video memory is available.  The BIOS call used
 - * here won't always be available.
 - */
 -static Bool
 -PutBIOSMemSize(ScrnInfoPtr pScrn, int memSize)
 -{
 -   vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
 -
 -   DPRINTF(PFX, "PutBIOSMemSize: %d kB\n", memSize / 1024);
 -
 -   pVbe->pInt10->num = 0x10;
 -   pVbe->pInt10->ax = 0x5f11;
 -   pVbe->pInt10->bx = 0;
 -   pVbe->pInt10->cx = memSize / GTT_PAGE_SIZE;
 -
 -   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
 -   return Check5fStatus(pScrn, 0x5f11, pVbe->pInt10->ax);
 -}
 -
 -/*
 - * This reports what the previous VBEGetVBEInfo() found.  Be sure to call
 - * VBEGetVBEInfo() after changing the BIOS memory size view.  If
 - * a separate BIOS call is added for this, it can be put here.  Only
 - * return a valid value if the funtionality for PutBIOSMemSize()
 - * is available.
 - */
 -static int
 -GetBIOSMemSize(ScrnInfoPtr pScrn)
 -{
 -   I830Ptr pI830 = I830PTR(pScrn);
 -   int memSize = KB(pI830->vbeInfo->TotalMemory * 64);
 -
 -   DPRINTF(PFX, "GetBIOSMemSize\n");
 -
 -   if (PutBIOSMemSize(pScrn, memSize))
 -      return memSize;
 -   else
 -      return -1;
 -}
 -#endif
 -
 -/*
 - * These three functions allow the video BIOS's view of the available video
 - * memory to be changed.  This is currently implemented only for the 830
 - * and 845G, which can do this via a BIOS scratch register that holds the
 - * BIOS's view of the (pre-reserved) memory size.  If another mechanism
 - * is available in the future, it can be plugged in here.  
 - *
 - * The mapping used for the 830/845G scratch register's low 4 bits is:
 - *
 - *             320k => 0
 - *             832k => 1
 - *            8000k => 8
 - *
 - * The "unusual" values are the 512k, 1M, 8M pre-reserved memory, less
 - * overhead, rounded down to the BIOS-reported 64k granularity.
 - */
 -
 -static Bool
 -SaveBIOSMemSize(ScrnInfoPtr pScrn)
 -{
 -   I830Ptr pI830 = I830PTR(pScrn);
 -
 -   DPRINTF(PFX, "SaveBIOSMemSize\n");
 -
 -   if (!I830IsPrimary(pScrn))
 -      return FALSE;
 -
 -   pI830->useSWF1 = FALSE;
 -
 -#if HAVE_GET_PUT_BIOSMEMSIZE
 -   if ((pI830->saveBIOSMemSize = GetBIOSMemSize(pScrn)) != -1)
 -      return TRUE;
 -#endif
 -
 -   if (IS_I830(pI830) || IS_845G(pI830)) {
 -      pI830->useSWF1 = TRUE;
 -      pI830->saveSWF1 = INREG(SWF1) & 0x0f;
 -
 -      /*
 -       * This is for sample purposes only.  pI830->saveBIOSMemSize isn't used
 -       * when pI830->useSWF1 is TRUE.
 -       */
 -      switch (pI830->saveSWF1) {
 -      case 0:
 -	 pI830->saveBIOSMemSize = KB(320);
 -	 break;
 -      case 1:
 -	 pI830->saveBIOSMemSize = KB(832);
 -	 break;
 -      case 8:
 -	 pI830->saveBIOSMemSize = KB(8000);
 -	 break;
 -      default:
 -	 pI830->saveBIOSMemSize = 0;
 -	 break;
 -      }
 -      return TRUE;
 -   }
 -   return FALSE;
 -}
 -
 -/*
 - * TweakMemorySize() tweaks the BIOS image to set the correct size.
 - * Original implementation by Christian Zietz in a stand-alone tool.
 - */
 -static CARD32
 -TweakMemorySize(ScrnInfoPtr pScrn, CARD32 newsize, Bool preinit)
 -{
 -#define SIZE 0x10000
 -#define _855_IDOFFSET (-23)
 -#define _845_IDOFFSET (-19)
 -    
 -    const char *MAGICstring = "Total time for VGA POST:";
 -    const int len = strlen(MAGICstring);
 -    I830Ptr pI830 = I830PTR(pScrn);
 -    volatile char *position;
 -    char *biosAddr;
 -    CARD32 oldsize;
 -    CARD32 oldpermission;
 -    CARD32 ret = 0;
 -    int i,j = 0;
 -    int reg = (IS_845G(pI830) || IS_I865G(pI830)) ? _845_DRAM_RW_CONTROL
 -	: _855_DRAM_RW_CONTROL;
 -    
 -    PCITAG tag =pciTag(0,0,0);
 -
 -    if (!I830IsPrimary(pScrn))
 -       return 0;
 -
 -    if(!pI830->PciInfo 
 -       || !(IS_845G(pI830) || IS_I85X(pI830) || IS_I865G(pI830)))
 -	return 0;
 -
 -    if (!pI830->pVbe)
 -	return 0;
 -
 -    biosAddr = xf86int10Addr(pI830->pVbe->pInt10, 
 -				    pI830->pVbe->pInt10->BIOSseg << 4);
 -
 -    if (!pI830->BIOSMemSizeLoc) {
 -	if (!preinit)
 -	    return 0;
 -
 -	/* Search for MAGIC string */
 -	for (i = 0; i < SIZE; i++) {
 -	    if (biosAddr[i] == MAGICstring[j]) {
 -		if (++j == len)
 -		    break;
 -	    } else {
 -		i -= j;
 -		j = 0;
 -	    }
 -	}
 -	if (j < len) return 0;
 -
 -	pI830->BIOSMemSizeLoc =  (i - j + 1 + (IS_845G(pI830)
 -					    ? _845_IDOFFSET : _855_IDOFFSET));
 -    }
 -    
 -    position = biosAddr + pI830->BIOSMemSizeLoc;
 -    oldsize = *(CARD32 *)position;
 -
 -    ret = oldsize - 0x21000;
 -    
 -    /* verify that register really contains current size */
 -    if (preinit && ((ret >> 16) !=  pI830->vbeInfo->TotalMemory))
 -	return 0;
 -
 -    oldpermission = pciReadLong(tag, reg);
 -    pciWriteLong(tag, reg, DRAM_WRITE | (oldpermission & 0xffff)); 
 -    
 -    *(CARD32 *)position = newsize + 0x21000;
 -
 -    if (preinit) {
 -	/* reinitialize VBE for new size */
 -	if (I830IsPrimary(pScrn)) {
 -	   VBEFreeVBEInfo(pI830->vbeInfo);
 -	   vbeFree(pI830->pVbe);
 -	   pI830->pVbe = VBEInit(NULL, pI830->pEnt->index);
 -	   pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe);
 -	} else {
 -           I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
 -           pI830->pVbe = pI8301->pVbe;
 -           pI830->vbeInfo = pI8301->vbeInfo;
 -	}
 -	
 -	/* verify that change was successful */
 -	if (pI830->vbeInfo->TotalMemory != (newsize >> 16)){
 -	    ret = 0;
 -	    *(CARD32 *)position = oldsize;
 -	} else {
 -	    pI830->BIOSMemorySize = KB(pI830->vbeInfo->TotalMemory * 64);
 -	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
 -		       "Tweak BIOS image to %d kB VideoRAM\n",
 -		       (int)(pI830->BIOSMemorySize / 1024));
 -	}
 -    }
 +	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 +		    "Local memory found, but won't be used.\n");
 +	 break;
 +      }
 +   }
+ 
 -    pciWriteLong(tag, reg, oldpermission);
++#if 0
++   /* And 64KB page aligned */
++   memsize &= ~0xFFFF;
++#endif
+ 
 -     return ret;
 +   if (memsize > 0) {
 +      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 +		 "detected %d kB stolen memory.\n", memsize / 1024);
 +   } else {
 +      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "no video memory detected.\n");
 +   }
 +   return memsize;
  }
  
 -static void
 -RestoreBIOSMemSize(ScrnInfoPtr pScrn)
 +static Bool
 +I830MapMMIO(ScrnInfoPtr pScrn)
  {
 +   int mmioFlags;
     I830Ptr pI830 = I830PTR(pScrn);
 -   CARD32 swf1;
 -
 -   DPRINTF(PFX, "RestoreBIOSMemSize\n");
 -
 -   if (!I830IsPrimary(pScrn))
 -      return;
 -
 -   if (TweakMemorySize(pScrn, pI830->saveBIOSMemSize,FALSE))
 -      return;
 -
 -   if (!pI830->overrideBIOSMemSize)
 -      return;
  
 -#if HAVE_GET_PUT_BIOSMEMSIZE
 -   if (!pI830->useSWF1) {
 -      PutBIOSMemSize(pScrn, pI830->saveBIOSMemSize);
 -      return;
 -   }
 +#if !defined(__alpha__)
 +   mmioFlags = VIDMEM_MMIO | VIDMEM_READSIDEEFFECT;
 +#else
 +   mmioFlags = VIDMEM_MMIO | VIDMEM_READSIDEEFFECT | VIDMEM_SPARSE;
  #endif
  
 -   if ((IS_I830(pI830) || IS_845G(pI830)) && pI830->useSWF1) {
 -      swf1 = INREG(SWF1);
 -      swf1 &= ~0x0f;
 -      swf1 |= (pI830->saveSWF1 & 0x0f);
 -      OUTREG(SWF1, swf1);
 -   }
 +   pI830->MMIOBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags,
 +				   pI830->PciTag,
 +				   pI830->MMIOAddr, I810_REG_SIZE);
 +   if (!pI830->MMIOBase)
 +      return FALSE;
 +   return TRUE;
  }
  
 -static void
 -SetBIOSMemSize(ScrnInfoPtr pScrn, int newSize)
 +static Bool
 +I830MapMem(ScrnInfoPtr pScrn)
  {
     I830Ptr pI830 = I830PTR(pScrn);
 -   unsigned long swf1;
 -   Bool mapped;
 +   long i;
  
 -   DPRINTF(PFX, "SetBIOSMemSize: %d kB\n", newSize / 1024);
 +   for (i = 2; i < pI830->FbMapSize; i <<= 1) ;
 +   pI830->FbMapSize = i;
  
 -   if (!pI830->overrideBIOSMemSize)
 -      return;
 +   if (!I830MapMMIO(pScrn))
 +      return FALSE;
  
 -#if HAVE_GET_PUT_BIOSMEMSIZE
 -   if (!pI830->useSWF1) {
 -      PutBIOSMemSize(pScrn, newSize);
 -      return;
 -   }
 -#endif
 +   pI830->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
 +				 pI830->PciTag,
 +				 pI830->LinearAddr, pI830->FbMapSize);
 +   if (!pI830->FbBase)
 +      return FALSE;
  
 -   if ((IS_I830(pI830) || IS_845G(pI830)) && pI830->useSWF1) {
 -      unsigned long newSWF1;
 +   if (I830IsPrimary(pScrn))
 +   pI830->LpRing->virtual_start = pI830->FbBase + pI830->LpRing->mem.Start;
  
 -      /* Need MMIO access here. */
 -      mapped = (pI830->MMIOBase != NULL);
 -      if (!mapped)
 -	 I830MapMMIO(pScrn);
 +   return TRUE;
 +}
  
 -      if (newSize <= KB(832))
 -	 newSWF1 = 1;
 -      else
 -	 newSWF1 = 8;
 +static void
 +I830UnmapMMIO(ScrnInfoPtr pScrn)
 +{
 +   I830Ptr pI830 = I830PTR(pScrn);
  
 -      swf1 = INREG(SWF1);
 -      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Before: SWF1 is 0x%08lx\n", swf1);
 -      swf1 &= ~0x0f;
 -      swf1 |= (newSWF1 & 0x0f);
 -      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "After: SWF1 is 0x%08lx\n", swf1);
 -      OUTREG(SWF1, swf1);
 -      if (!mapped)
 -	 I830UnmapMMIO(pScrn);
 -   }
 +   xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pI830->MMIOBase,
 +		   I810_REG_SIZE);
 +   pI830->MMIOBase = 0;
  }
  
 -static CARD32 val8[256];
 +static Bool
 +I830UnmapMem(ScrnInfoPtr pScrn)
 +{
 +   I830Ptr pI830 = I830PTR(pScrn);
 +
 +   xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pI830->FbBase,
 +		   pI830->FbMapSize);
 +   pI830->FbBase = 0;
 +   I830UnmapMMIO(pScrn);
 +   return TRUE;
 +}
  
  static void
  I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
@@@ -742,8 -3504,7 +739,8 @@@
     unsigned char r, g, b;
     CARD32 val, temp;
     int palreg;
-    int dspreg, dspbase;
+    int dspreg, dspbase, dspsurf;
 +   int p;
  
     DPRINTF(PFX, "I830LoadPalette: numColors: %d\n", numColors);
     pI830 = I830PTR(pScrn);
@@@ -754,23 -3514,18 +751,27 @@@
           palreg = PALETTE_A;
           dspreg = DSPACNTR;
           dspbase = DSPABASE;
++	 dspsurf = DSPASURF;
        } else {
           palreg = PALETTE_B;
           dspreg = DSPBCNTR;
           dspbase = DSPBBASE;
++	 dspsurf = DSPBSURF;
        }
 -   
 +
 +      if (pI830->planeEnabled[p] == 0)
 +	 continue;  
 +
 +      pI830->gammaEnabled[p] = 1;
 +      
        /* To ensure gamma is enabled we need to turn off and on the plane */
        temp = INREG(dspreg);
        OUTREG(dspreg, temp & ~(1<<31));
        OUTREG(dspbase, INREG(dspbase));
        OUTREG(dspreg, temp | DISPPLANE_GAMMA_ENABLE);
        OUTREG(dspbase, INREG(dspbase));
++      if (IS_I965G(pI830))
++	 OUTREG(dspsurf, INREG(dspsurf));
  
        /* It seems that an initial read is needed. */
        temp = INREG(palreg);
@@@ -1339,9 -4044,10 +1350,10 @@@
        from = X_CONFIG;
        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
  		 pI830->pEnt->device->chipID);
+       pI830->PciInfo->chipType = pI830->pEnt->device->chipID;
     } else {
        from = X_PROBED;
 -      pScrn->chipset = (char *)xf86TokenToString(I830BIOSChipsets,
 +      pScrn->chipset = (char *)xf86TokenToString(I830Chipsets,
  						 pI830->PciInfo->chipType);
     }
  
@@@ -1516,10 -4222,13 +1528,13 @@@
  #endif
  
     pI830->LinearAlloc = 0;
 -   if (xf86GetOptValInteger(pI830->Options, OPTION_LINEARALLOC,
 +   if (xf86GetOptValULong(pI830->Options, OPTION_LINEARALLOC,
  			    &(pI830->LinearAlloc))) {
-       xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Allocating %luKbytes of memory\n",
+       if (pI830->LinearAlloc > 0)
 -         xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Allocating %dKbytes of memory\n",
++         xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Allocating %luKbytes of memory\n",
  		 pI830->LinearAlloc);
+       else 
+          pI830->LinearAlloc = 0;
     }
  
     pI830->fixedPipe = -1;
@@@ -1755,10 -4365,18 +1770,17 @@@
        return FALSE;
     }
  
 -   if ((pI830->entityPrivate && I830IsPrimary(pScrn)) || pI830->Clone ||
 -	pI830->MergedFB) {
 +   if ((pI830->entityPrivate && I830IsPrimary(pScrn)) || pI830->Clone) {
+       if ((!xf86GetOptValString(pI830->Options, OPTION_MONITOR_LAYOUT))) {
+ 	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "You must have a MonitorLayout "
+ 	 		"defined for use in a DualHead, Clone or MergedFB setup.\n");
+          PreInitCleanup(pScrn);
+          return FALSE;
+       }
 -         
++
        if (pI830->MonType1 == PIPE_NONE || pI830->MonType2 == PIPE_NONE) {
           xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Monitor 1 or Monitor 2 "
- 	 		"cannot be type NONE in Dual or Clone setup.\n");
 -	 		"cannot be type NONE in DualHead, Clone or MergedFB setup.\n");
++	 		"cannot be type NONE in DualHead or Clone setup.\n");
           PreInitCleanup(pScrn);
           return FALSE;
        }
@@@ -2394,205 -5661,451 +2430,220 @@@
     OUTREG(LP_RING + RING_START, 0);
    
     if (pI830->CursorInfoRec && pI830->CursorInfoRec->HideCursor)
 -      pI830->CursorInfoRec->HideCursor(pScrn);
 -}
 -
 -static void
 -SetFenceRegs(ScrnInfoPtr pScrn)
 -{
 -   I830Ptr pI830 = I830PTR(pScrn);
 -   int i;
 -
 -   DPRINTF(PFX, "SetFenceRegs\n");
 -
 -   if (!I830IsPrimary(pScrn)) return;
 -
 -   if (IS_I965G(pI830)) {
 -      for (i = 0; i < FENCE_NEW_NR; i++) {
 -         OUTREG(FENCE_NEW + i * 8, pI830->ModeReg.Fence[i]);
 -         OUTREG(FENCE_NEW + 4 + i * 8, pI830->ModeReg.Fence[i+FENCE_NEW_NR]);
 -         if (I810_DEBUG & DEBUG_VERBOSE_VGA) {
 -	    ErrorF("Fence Start Register : %x\n", pI830->ModeReg.Fence[i]);
 -	    ErrorF("Fence End Register : %x\n", pI830->ModeReg.Fence[i+FENCE_NEW_NR]);
 -         }
 -      }
 -   } else {
 -      for (i = 0; i < FENCE_NR; i++) {
 -         OUTREG(FENCE + i * 4, pI830->ModeReg.Fence[i]);
 -         if (I810_DEBUG & DEBUG_VERBOSE_VGA)
 -	    ErrorF("Fence Register : %x\n", pI830->ModeReg.Fence[i]);
 -      }
 -   }
 -}
 -
 -static void
 -SetRingRegs(ScrnInfoPtr pScrn)
 -{
 -   I830Ptr pI830 = I830PTR(pScrn);
 -   unsigned int itemp;
 -
 -   DPRINTF(PFX, "SetRingRegs\n");
 -
 -   if (pI830->noAccel)
 -      return;
 -
 -   if (!I830IsPrimary(pScrn)) return;
 -
 -   if (pI830->entityPrivate)
 -      pI830->entityPrivate->RingRunning = 1;
 -
 -   OUTREG(LP_RING + RING_LEN, 0);
 -   OUTREG(LP_RING + RING_TAIL, 0);
 -   OUTREG(LP_RING + RING_HEAD, 0);
 -
 -   if ((long)(pI830->LpRing->mem.Start & I830_RING_START_MASK) !=
 -       pI830->LpRing->mem.Start) {
 -      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 -		 "I830SetRingRegs: Ring buffer start (%lx) violates its "
 -		 "mask (%x)\n", pI830->LpRing->mem.Start, I830_RING_START_MASK);
 -   }
 -   /* Don't care about the old value.  Reserved bits must be zero anyway. */
 -   itemp = pI830->LpRing->mem.Start & I830_RING_START_MASK;
 -   OUTREG(LP_RING + RING_START, itemp);
 -
 -   if (((pI830->LpRing->mem.Size - 4096) & I830_RING_NR_PAGES) !=
 -       pI830->LpRing->mem.Size - 4096) {
 -      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 -		 "I830SetRingRegs: Ring buffer size - 4096 (%lx) violates its "
 -		 "mask (%x)\n", pI830->LpRing->mem.Size - 4096,
 -		 I830_RING_NR_PAGES);
 -   }
 -   /* Don't care about the old value.  Reserved bits must be zero anyway. */
 -   itemp = (pI830->LpRing->mem.Size - 4096) & I830_RING_NR_PAGES;
 -   itemp |= (RING_NO_REPORT | RING_VALID);
 -   OUTREG(LP_RING + RING_LEN, itemp);
 -   I830RefreshRing(pScrn);
 -}
 -
 -/*
 - * This should be called everytime the X server gains control of the screen,
 - * before any video modes are programmed (ScreenInit, EnterVT).
 - */
 -static void
 -SetHWOperatingState(ScrnInfoPtr pScrn)
 -{
 -   I830Ptr pI830 = I830PTR(pScrn);
 -
 -   DPRINTF(PFX, "SetHWOperatingState\n");
 -
 -   if (!pI830->noAccel)
 -      SetRingRegs(pScrn);
 -   SetFenceRegs(pScrn);
 -   if (!pI830->SWCursor)
 -      I830InitHWCursor(pScrn);
 -}
 -
 -static Bool
 -SaveHWState(ScrnInfoPtr pScrn)
 -{
 -   I830Ptr pI830 = I830PTR(pScrn);
 -   vbeInfoPtr pVbe = pI830->pVbe;
 -   vgaHWPtr hwp = VGAHWPTR(pScrn);
 -   vgaRegPtr vgaReg = &hwp->SavedReg;
 -   VbeModeInfoBlock *modeInfo;
 -   VESAPtr pVesa;
 -
 -   DPRINTF(PFX, "SaveHWState\n");
 -
 -   if (I830IsPrimary(pScrn) && pI830->pipe != pI830->origPipe)
 -      SetBIOSPipe(pScrn, pI830->origPipe);
 -   else
 -      SetPipeAccess(pScrn);
 -
 -   pVesa = pI830->vesa;
 -
 -   /* Make sure we save at least this information in case of failure. */
 -   VBEGetVBEMode(pVbe, &pVesa->stateMode);
 -   pVesa->stateRefresh = GetRefreshRate(pScrn, pVesa->stateMode, NULL);
 -   modeInfo = VBEGetModeInfo(pVbe, pVesa->stateMode);
 -   pVesa->savedScanlinePitch = 0;
 -   if (modeInfo) {
 -      if (VBE_MODE_GRAPHICS(modeInfo)) {
 -         VBEGetLogicalScanline(pVbe, &pVesa->savedScanlinePitch, NULL, NULL);
 -      }
 -      VBEFreeModeInfo(modeInfo);
 -   }
 -
 -   vgaHWUnlock(hwp);
 -   vgaHWSave(pScrn, vgaReg, VGA_SR_FONTS);
 -
 -   pVesa = pI830->vesa;
 -
 -   if (IS_I965G(pI830)) {
 -      pI830->savedAsurf = INREG(DSPASURF);
 -      pI830->savedBsurf = INREG(DSPBSURF);
 -   }
 -
 -   /*
 -    * This save/restore method doesn't work for 845G BIOS, or for some
 -    * other platforms.  Enable it in all cases.
 -    */
 -   /*
 -    * KW: This may have been because of the behaviour I've found on my
 -    * board: The 'save' command actually modifies the interrupt
 -    * registers, turning off the irq & breaking the kernel module
 -    * behaviour.
 -    */
 -   if (!pI830->vbeRestoreWorkaround) {
 -      CARD16 imr = INREG16(IMR);
 -      CARD16 ier = INREG16(IER);
 -      CARD16 hwstam = INREG16(HWSTAM);
 -
 -      if (!VBESaveRestore(pVbe, MODE_SAVE, &pVesa->state, &pVesa->stateSize,
 -			  &pVesa->statePage)) {
 -	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 -		    "SaveHWState: VBESaveRestore(MODE_SAVE) failed.\n");
 -	 return FALSE;
 -      }
 -
 -      OUTREG16(IMR, imr);
 -      OUTREG16(IER, ier);
 -      OUTREG16(HWSTAM, hwstam);
 -   }
 -
 -   pVesa->savedPal = VBESetGetPaletteData(pVbe, FALSE, 0, 256,
 -					     NULL, FALSE, FALSE);
 -   if (!pVesa->savedPal) {
 -      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 -		 "SaveHWState: VBESetGetPaletteData(GET) failed.\n");
 -      return FALSE;
 -   }
 -
 -   VBEGetDisplayStart(pVbe, &pVesa->x, &pVesa->y);
 -
 -   return TRUE;
 -}
 -
 -static Bool
 -RestoreHWState(ScrnInfoPtr pScrn)
 -{
 -   I830Ptr pI830 = I830PTR(pScrn);
 -   vbeInfoPtr pVbe = pI830->pVbe;
 -   vgaHWPtr hwp = VGAHWPTR(pScrn);
 -   vgaRegPtr vgaReg = &hwp->SavedReg;
 -   VESAPtr pVesa;
 -   Bool restored = FALSE;
 -
 -   DPRINTF(PFX, "RestoreHWState\n");
 -
 -   if (I830IsPrimary(pScrn) && pI830->pipe != pI830->origPipe)
 -      SetBIOSPipe(pScrn, pI830->origPipe);
 -   else
 -      SetPipeAccess(pScrn);
 -
 -   pVesa = pI830->vesa;
 -
 -   /*
 -    * Workaround for text mode restoration with some flat panels.
 -    * Temporarily program a 640x480 mode before switching back to
 -    * text mode.
 -    */
 -   if (pVesa->useDefaultRefresh)
 -      I830Set640x480(pScrn);
 -
 -   if (pVesa->state && pVesa->stateSize) {
 -      CARD16 imr = INREG16(IMR);
 -      CARD16 ier = INREG16(IER);
 -      CARD16 hwstam = INREG16(HWSTAM);
 -
 -      /* Make a copy of the state.  Don't rely on it not being touched. */
 -      if (!pVesa->pstate) {
 -	 pVesa->pstate = xalloc(pVesa->stateSize);
 -	 if (pVesa->pstate)
 -	    memcpy(pVesa->pstate, pVesa->state, pVesa->stateSize);
 -      }
 -      restored = VBESaveRestore(pVbe, MODE_RESTORE, &pVesa->state,
 -				   &pVesa->stateSize, &pVesa->statePage);
 -      if (!restored) {
 -	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -		    "RestoreHWState: VBESaveRestore failed.\n");
 -      }
 -      /* Copy back */
 -      if (pVesa->pstate)
 -	 memcpy(pVesa->state, pVesa->pstate, pVesa->stateSize);
 -
 -      OUTREG16(IMR, imr);
 -      OUTREG16(IER, ier);
 -      OUTREG16(HWSTAM, hwstam);
 -   }
 -   /* If that failed, restore the original mode. */
 -   if (!restored) {
 -      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -		 "Setting the original video mode instead of restoring\n\t"
 -		 "the saved state\n");
 -      I830VESASetVBEMode(pScrn, pVesa->stateMode, NULL);
 -      if (!pVesa->useDefaultRefresh && pI830->useExtendedRefresh) {
 -         SetRefreshRate(pScrn, pVesa->stateMode, pVesa->stateRefresh);
 -      }
 -   }
 -   if (pVesa->savedScanlinePitch)
 -       VBESetLogicalScanline(pVbe, pVesa->savedScanlinePitch);
 -
 -   if (pVesa->savedPal)
 -      VBESetGetPaletteData(pVbe, TRUE, 0, 256, pVesa->savedPal, FALSE, TRUE);
 -
 -   VBESetDisplayStart(pVbe, pVesa->x, pVesa->y, TRUE);
 -
 -   if (IS_I965G(pI830)) {
 -      OUTREG(DSPASURF, pI830->savedAsurf);
 -      OUTREG(DSPBSURF, pI830->savedBsurf);
 -   }
 -
 -   vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS);
 -   vgaHWLock(hwp);
 -
 -   return TRUE;
 +      pI830->CursorInfoRec->HideCursor(pScrn);
  }
  
 -static void I830SetCloneVBERefresh(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock * block, int refresh)
 +static void
 +SetFenceRegs(ScrnInfoPtr pScrn)
  {
     I830Ptr pI830 = I830PTR(pScrn);
 -   DisplayModePtr p = NULL;
 -   int RefreshRate;
 -   int clock;
 -
 -   /* Search for our mode and get a refresh to match */
 -   for (p = pScrn->monitor->Modes; p != NULL; p = p->next) {
 -      if ((p->HDisplay != pI830->CloneHDisplay) ||
 -          (p->VDisplay != pI830->CloneVDisplay) ||
 -          (p->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2)))
 -         continue;
 -      RefreshRate = ((double)(p->Clock * 1000) /
 -                     (double)(p->HTotal * p->VTotal)) * 100;
 -      /* we could probably do better here that 2Hz boundaries */
 -      if (RefreshRate > (refresh - 200) && RefreshRate < (refresh + 200)) {
 -         block->HorizontalTotal = p->HTotal;
 -         block->HorizontalSyncStart = p->HSyncStart;
 -         block->HorizontalSyncEnd = p->HSyncEnd;
 -         block->VerticalTotal = p->VTotal;
 -         block->VerticalSyncStart = p->VSyncStart;
 -         block->VerticalSyncEnd = p->VSyncEnd;
 -         block->Flags = ((p->Flags & V_NHSYNC) ? CRTC_NHSYNC : 0) |
 -                        ((p->Flags & V_NVSYNC) ? CRTC_NVSYNC : 0);
 -         block->PixelClock = p->Clock * 1000;
 -         /* XXX May not have this. */
 -         clock = VBEGetPixelClock(pI830->pVbe, mode, block->PixelClock);
 -#ifdef DEBUG
 -         ErrorF("Setting clock %.2fMHz, closest is %.2fMHz\n",
 -                    (double)data->block->PixelClock / 1000000.0, 
 -                    (double)clock / 1000000.0);
 -#endif
 -         if (clock)
 -            block->PixelClock = clock;
 -         block->RefreshRate = RefreshRate;
 -         return;
 +   int i;
 +
 +   DPRINTF(PFX, "SetFenceRegs\n");
 +
 +   if (!I830IsPrimary(pScrn)) return;
 +
-    for (i = 0; i < 8; i++) {
-       OUTREG(FENCE + i * 4, pI830->ModeReg.Fence[i]);
-       if (I810_DEBUG & DEBUG_VERBOSE_VGA)
- 	 ErrorF("Fence Register : %x\n", pI830->ModeReg.Fence[i]);
++   if (IS_I965G(pI830)) {
++      for (i = 0; i < FENCE_NEW_NR; i++) {
++         OUTREG(FENCE_NEW + i * 8, pI830->ModeReg.Fence[i]);
++         OUTREG(FENCE_NEW + 4 + i * 8, pI830->ModeReg.Fence[i+FENCE_NEW_NR]);
++         if (I810_DEBUG & DEBUG_VERBOSE_VGA) {
++	    ErrorF("Fence Start Register : %x\n", pI830->ModeReg.Fence[i]);
++	    ErrorF("Fence End Register : %x\n", pI830->ModeReg.Fence[i+FENCE_NEW_NR]);
++         }
++      }
++   } else {
++      for (i = 0; i < FENCE_NR; i++) {
++         OUTREG(FENCE + i * 4, pI830->ModeReg.Fence[i]);
++         if (I810_DEBUG & DEBUG_VERBOSE_VGA)
++	    ErrorF("Fence Register : %x\n", pI830->ModeReg.Fence[i]);
+       }
     }
  }
  
 -static Bool
 -I830VESASetVBEMode(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock * block)
 +static void
 +SetRingRegs(ScrnInfoPtr pScrn)
  {
     I830Ptr pI830 = I830PTR(pScrn);
 -   Bool ret = FALSE;
 -   int Mon;
 -
 -   DPRINTF(PFX, "Setting mode 0x%.8x\n", mode);
 -
 -#if 0
 -   /* Clear the framebuffer (could do this with VBIOS call) */
 -   if (I830IsPrimary(pScrn))
 -      memset(pI830->FbBase + pI830->FrontBuffer.Start, 0,
 -	  pScrn->virtualY * pI830->displayWidth * pI830->cpp);
 -   else
 -      memset(pI830->FbBase + pI830->FrontBuffer2.Start, 0,
 -	  pScrn->virtualY * pI830->displayWidth * pI830->cpp);
 -#endif
 -
 -   if (pI830->Clone && 
 -	pI830->CloneHDisplay && pI830->CloneVDisplay &&
 -       !pI830->preinit && !pI830->closing) {
 -      VbeCRTCInfoBlock newblock;
 -      int newmode = mode;
 -
 -      if (pI830->pipe == 1)
 -         Mon = pI830->MonType1;
 -      else
 -         Mon = pI830->MonType2;
 +   unsigned int itemp;
  
 -      SetBIOSPipe(pScrn, !pI830->pipe);
 +   DPRINTF(PFX, "SetRingRegs\n");
  
 -      /* Now recheck refresh operations we can use */
 -      pI830->useExtendedRefresh = FALSE;
 -      pI830->vesa->useDefaultRefresh = FALSE;
 +   if (pI830->noAccel)
 +      return;
  
 -      if (Mon != PIPE_CRT) {
 -	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 -		    "A non-CRT device is attached to Clone pipe %c.\n"
 -		    "\tNo refresh rate overrides will be attempted (0x%x).\n",
 -		    PIPE_NAME(!pI830->pipe), newmode);
 -	 pI830->vesa->useDefaultRefresh = TRUE;
 -      }
 -      /*
 -       * Some desktop platforms might not have 0x5f05, so useExtendedRefresh
 -       * would need to be set to FALSE for those cases.
 -       */
 -      if (!pI830->vesa->useDefaultRefresh) 
 -	 pI830->useExtendedRefresh = TRUE;
 +   if (!I830IsPrimary(pScrn)) return;
  
 -      newmode |= 1 << 11;
 -      if (pI830->vesa->useDefaultRefresh)
 -            newmode &= ~(1 << 11);
 +   if (pI830->entityPrivate)
 +      pI830->entityPrivate->RingRunning = 1;
  
 -      if (!SetRefreshRate(pScrn, newmode, 60)) {
 -	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 -		    "BIOS call 0x5f05 not supported on Clone Head, "
 -		    "setting refresh with VBE 3 method.\n");
 -	 pI830->useExtendedRefresh = FALSE;
 -      }
 +   OUTREG(LP_RING + RING_LEN, 0);
 +   OUTREG(LP_RING + RING_TAIL, 0);
 +   OUTREG(LP_RING + RING_HEAD, 0);
  
 -      if (!pI830->vesa->useDefaultRefresh) {
 -         I830SetCloneVBERefresh(pScrn, newmode, &newblock, pI830->CloneRefresh * 100);
 -
 -         if (!VBESetVBEMode(pI830->pVbe, newmode, &newblock)) {
 -            if (!VBESetVBEMode(pI830->pVbe, (newmode & ~(1 << 11)), NULL))
 -               xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -		 "Failed to set mode for Clone head.\n");
 -         } else {
 -            xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 -		 "Setting refresh on clone head with VBE 3 method.\n");
 -            pI830->useExtendedRefresh = FALSE;
 -         }
 -      } else {
 -         if (!VBESetVBEMode(pI830->pVbe, (newmode & ~(1 << 11)), NULL))
 -            xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -		 "Failed to set mode for Clone head.\n");
 -      }
 +   if ((long)(pI830->LpRing->mem.Start & I830_RING_START_MASK) !=
 +       pI830->LpRing->mem.Start) {
 +      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 +		 "I830SetRingRegs: Ring buffer start (%lx) violates its "
 +		 "mask (%x)\n", pI830->LpRing->mem.Start, I830_RING_START_MASK);
 +   }
 +   /* Don't care about the old value.  Reserved bits must be zero anyway. */
 +   itemp = pI830->LpRing->mem.Start & I830_RING_START_MASK;
 +   OUTREG(LP_RING + RING_START, itemp);
  
 -      if (pI830->useExtendedRefresh && !pI830->vesa->useDefaultRefresh) {
 -         if (!SetRefreshRate(pScrn, newmode, pI830->CloneRefresh))
 -	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -		    "Failed to set refresh rate to %dHz on Clone head.\n",
 -		    pI830->CloneRefresh);
 -         else
 -	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 -		    "Set refresh rate to %dHz on Clone head.\n",
 -		    pI830->CloneRefresh);
 -      }
 -      SetPipeAccess(pScrn);
 +   if (((pI830->LpRing->mem.Size - 4096) & I830_RING_NR_PAGES) !=
 +       pI830->LpRing->mem.Size - 4096) {
 +      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 +		 "I830SetRingRegs: Ring buffer size - 4096 (%lx) violates its "
 +		 "mask (%x)\n", pI830->LpRing->mem.Size - 4096,
 +		 I830_RING_NR_PAGES);
     }
 +   /* Don't care about the old value.  Reserved bits must be zero anyway. */
 +   itemp = (pI830->LpRing->mem.Size - 4096) & I830_RING_NR_PAGES;
 +   itemp |= (RING_NO_REPORT | RING_VALID);
 +   OUTREG(LP_RING + RING_LEN, itemp);
 +   I830RefreshRing(pScrn);
 +}
  
 -   if (pI830->pipe == 0)
 -      Mon = pI830->MonType1;
 -   else
 -      Mon = pI830->MonType2;
 +/*
 + * This should be called everytime the X server gains control of the screen,
 + * before any video modes are programmed (ScreenInit, EnterVT).
 + */
 +static void
 +SetHWOperatingState(ScrnInfoPtr pScrn)
 +{
 +   I830Ptr pI830 = I830PTR(pScrn);
  
 +   DPRINTF(PFX, "SetHWOperatingState\n");
  
 -   /* Now recheck refresh operations we can use */
 -   pI830->useExtendedRefresh = FALSE;
 -   pI830->vesa->useDefaultRefresh = FALSE;
 +   if (!pI830->noAccel)
 +      SetRingRegs(pScrn);
 +   SetFenceRegs(pScrn);
 +   if (!pI830->SWCursor)
 +      I830InitHWCursor(pScrn);
 +}
  
 -   if (Mon != PIPE_CRT) {
 -      xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
 -		    "A non-CRT device is attached to pipe %c.\n"
 -		    "\tNo refresh rate overrides will be attempted.\n",
 -		    PIPE_NAME(pI830->pipe));
 -      pI830->vesa->useDefaultRefresh = TRUE;
 -   }
 +static Bool
 +SaveHWState(ScrnInfoPtr pScrn)
 +{
 +   I830Ptr pI830 = I830PTR(pScrn);
 +   vgaHWPtr hwp = VGAHWPTR(pScrn);
 +   vgaRegPtr vgaReg = &hwp->SavedReg;
 +   CARD32 temp;
 +   int i;
  
 -   mode |= 1 << 11;
 -   if (pI830->vesa->useDefaultRefresh)
 -      mode &= ~(1 << 11);
     /*
 -    * Some desktop platforms might not have 0x5f05, so useExtendedRefresh
 -    * would need to be set to FALSE for those cases.
 +    * Print out the PIPEACONF and PIPEBCONF registers.
      */
 -   if (!pI830->vesa->useDefaultRefresh) 
 -      pI830->useExtendedRefresh = TRUE;
 -
 -   if (!SetRefreshRate(pScrn, mode, 60)) {
 -      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 -		    "BIOS call 0x5f05 not supported, "
 -		    "setting refresh with VBE 3 method.\n");
 -      pI830->useExtendedRefresh = FALSE;
 +   temp = INREG(PIPEACONF);
 +   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEACONF is 0x%08lx\n", 
 +	      (unsigned long) temp);
 +   if (pI830->availablePipes == 2) {
 +      temp = INREG(PIPEBCONF);
 +      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEBCONF is 0x%08lx\n", 
 +		 (unsigned long) temp);
     }
  
 -   if (!pI830->vesa->useDefaultRefresh && block) {
 -      ret = VBESetVBEMode(pI830->pVbe, mode, block);
 -      if (!ret)
 -         ret = VBESetVBEMode(pI830->pVbe, (mode & ~(1 << 11)), NULL);
 -      else {
 -         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 -		 "Setting refresh with VBE 3 method.\n");
 -	 pI830->useExtendedRefresh = FALSE;
 +   i830TakeRegSnapshot(pScrn);
 +
 +   /* Save video mode information for native mode-setting. */
 +   pI830->saveDSPACNTR = INREG(DSPACNTR);
 +   pI830->savePIPEACONF = INREG(PIPEACONF);
 +   pI830->savePIPEASRC = INREG(PIPEASRC);
 +   pI830->saveFPA0 = INREG(FPA0);
 +   pI830->saveFPA1 = INREG(FPA1);
 +   pI830->saveDPLL_A = INREG(DPLL_A);
 +   pI830->saveHTOTAL_A = INREG(HTOTAL_A);
 +   pI830->saveHBLANK_A = INREG(HBLANK_A);
 +   pI830->saveHSYNC_A = INREG(HSYNC_A);
 +   pI830->saveVTOTAL_A = INREG(VTOTAL_A);
 +   pI830->saveVBLANK_A = INREG(VBLANK_A);
 +   pI830->saveVSYNC_A = INREG(VSYNC_A);
 +   pI830->saveDSPASTRIDE = INREG(DSPASTRIDE);
 +   pI830->saveDSPASIZE = INREG(DSPASIZE);
 +   pI830->saveDSPAPOS = INREG(DSPAPOS);
 +   pI830->saveDSPABASE = INREG(DSPABASE);
 +
 +   for(i= 0; i < 256; i++) {
 +      pI830->savePaletteA[i] = INREG(PALETTE_A + (i << 2));
 +   }
 +
 +   if(pI830->availablePipes == 2) {
 +      pI830->savePIPEBCONF = INREG(PIPEBCONF);
 +      pI830->savePIPEBSRC = INREG(PIPEBSRC);
 +      pI830->saveDSPBCNTR = INREG(DSPBCNTR);
 +      pI830->saveFPB0 = INREG(FPB0);
 +      pI830->saveFPB1 = INREG(FPB1);
 +      pI830->saveDPLL_B = INREG(DPLL_B);
 +      pI830->saveHTOTAL_B = INREG(HTOTAL_B);
 +      pI830->saveHBLANK_B = INREG(HBLANK_B);
 +      pI830->saveHSYNC_B = INREG(HSYNC_B);
 +      pI830->saveVTOTAL_B = INREG(VTOTAL_B);
 +      pI830->saveVBLANK_B = INREG(VBLANK_B);
 +      pI830->saveVSYNC_B = INREG(VSYNC_B);
 +      pI830->saveDSPBSTRIDE = INREG(DSPBSTRIDE);
 +      pI830->saveDSPBSIZE = INREG(DSPBSIZE);
 +      pI830->saveDSPBPOS = INREG(DSPBPOS);
 +      pI830->saveDSPBBASE = INREG(DSPBBASE);
 +      for(i= 0; i < 256; i++) {
 +         pI830->savePaletteB[i] = INREG(PALETTE_B + (i << 2));
        }
 -   } else {
 -      ret = VBESetVBEMode(pI830->pVbe, (mode & ~(1 << 11)), NULL);
     }
  
 -   /* Might as well bail now if we've failed */
 -   if (!ret) return FALSE;
++   if (IS_I965G(pI830)) {
++      pI830->saveDSPASURF = INREG(DSPASURF);
++      pI830->saveDSPBSURF = INREG(DSPBSURF);
++   }
+ 
 -   if (pI830->useExtendedRefresh && !pI830->vesa->useDefaultRefresh && block) {
 -      if (!SetRefreshRate(pScrn, mode, block->RefreshRate / 100)) {
 -	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -		    "Failed to set refresh rate to %dHz.\n",
 -		    block->RefreshRate / 100);
 -	 pI830->useExtendedRefresh = FALSE;
 +   pI830->saveVCLK_DIVISOR_VGA0 = INREG(VCLK_DIVISOR_VGA0);
 +   pI830->saveVCLK_DIVISOR_VGA1 = INREG(VCLK_DIVISOR_VGA1);
 +   pI830->saveVCLK_POST_DIV = INREG(VCLK_POST_DIV);
 +   pI830->saveVGACNTRL = INREG(VGACNTRL);
 +
 +   pI830->saveADPA = INREG(ADPA);
 +
 +   pI830->savePFIT_CONTROL = INREG(PFIT_CONTROL);
 +   pI830->savePP_ON = INREG(LVDSPP_ON);
 +   pI830->savePP_OFF = INREG(LVDSPP_OFF);
 +   pI830->saveLVDS = INREG(LVDS);
 +   pI830->savePP_CONTROL = INREG(PP_CONTROL);
 +   pI830->savePP_CYCLE = INREG(PP_CYCLE);
 +   pI830->saveBLC_PWM_CTL = INREG(BLC_PWM_CTL);
 +   pI830->backlight_duty_cycle = (pI830->saveBLC_PWM_CTL & 
 +				  BACKLIGHT_DUTY_CYCLE_MASK);
 +   /*
 +    * If the light is off at server startup, just make it full brightness
 +    */
 +   if (!pI830->backlight_duty_cycle)
 +      pI830->backlight_duty_cycle = ((pI830->saveBLC_PWM_CTL &
 +				      BACKLIGHT_MODULATION_FREQ_MASK) >>
 +				     BACKLIGHT_MODULATION_FREQ_SHIFT);
-     
 +
 +   if (!IS_I9XX(pI830)) {
 +      pI830->saveDVOA = INREG(DVOA);
 +      pI830->saveDVOB = INREG(DVOB);
 +      pI830->saveDVOC = INREG(DVOC);
 +   }
 +
 +   for(i = 0; i < 7; i++) {
 +      pI830->saveSWF[i] = INREG(SWF0 + (i << 2));
 +      pI830->saveSWF[i+7] = INREG(SWF00 + (i << 2));
 +   }
 +   pI830->saveSWF[14] = INREG(SWF30);
 +   pI830->saveSWF[15] = INREG(SWF31);
 +   pI830->saveSWF[16] = INREG(SWF32);
 +
 +   for (i = 0; i < pI830->num_outputs; i++) {
 +      if (pI830->output[i].type == I830_OUTPUT_DVO &&
 +	  pI830->output[i].i2c_drv != NULL)
 +      {
 +	 pI830->output[i].i2c_drv->vid_rec->SaveRegs(
 +	    pI830->output[i].i2c_drv->dev_priv);
 +      }
 +      if (pI830->output[i].type == I830_OUTPUT_SDVO &&
 +	  pI830->output[i].sdvo_drv != NULL)
 +      {
 +	 i830SDVOSave(pScrn, i);
        }
     }
  
@@@ -2603,121 -6113,409 +2654,126 @@@
  }
  
  static Bool
 -I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
 +RestoreHWState(ScrnInfoPtr pScrn)
  {
     I830Ptr pI830 = I830PTR(pScrn);
 -   vbeInfoPtr pVbe = pI830->pVbe;
 -   I830ModePrivatePtr mp = (I830ModePrivatePtr) pMode->Private;
 -   int mode, i;
 -   CARD32 planeA, planeB, temp;
 -   int refresh = 60;
 -#ifdef XF86DRI
 -   Bool didLock = FALSE;
 -#endif
 -
 -   DPRINTF(PFX, "I830VESASetMode\n");
 +   vgaHWPtr hwp = VGAHWPTR(pScrn);
 +   vgaRegPtr vgaReg = &hwp->SavedReg;
 +   CARD32 temp;
 +   int i;
  
 -   /* Always Enable Linear Addressing */
 -   mode = mp->vbeData.mode | (1 << 15) | (1 << 14);
 +   DPRINTF(PFX, "RestoreHWState\n");
  
  #ifdef XF86DRI
 -   didLock = I830DRILock(pScrn);
 -#endif
 -
 -   if (pI830->Clone) {
 -      pI830->CloneHDisplay = pMode->HDisplay;
 -      pI830->CloneVDisplay = pMode->VDisplay;
 -   }
 -
 -#ifndef MODESWITCH_RESET_STATE
 -#define MODESWITCH_RESET_STATE 0
 -#endif
 -#if MODESWITCH_RESET_STATE
 -   ResetState(pScrn, TRUE);
 +   I830DRISetVBlankInterrupt (pScrn, FALSE);
  #endif
 +   vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS);
 +   vgaHWLock(hwp);
  
 -   SetPipeAccess(pScrn);
 -
 -   if (!pI830->MergedFB) {
 -      if (I830VESASetVBEMode(pScrn, mode, mp->vbeData.block) == FALSE) {
 -         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Set VBE Mode failed!\n");
 -         return FALSE;
 -      }
 -   }else {
 -      I830ModePrivatePtr s = (I830ModePrivatePtr)mp->merged.Second->Private;
 -      I830ModePrivatePtr f = (I830ModePrivatePtr)mp->merged.First->Private;
 -      int pipe = pI830->pipe; /* save current pipe */
 -
 -      SetBIOSPipe(pScrn, !pI830->pipe);
 -
 -      pI830->pipe = !pI830->pipe;
 -      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting mode on Pipe %s.\n", pI830->pipe ? "B" : "A");
 -
 -      if (I830VESASetVBEMode(pScrn, (s->vbeData.mode | 1<<15 | 1<<14), s->vbeData.block) == FALSE) {
 -         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Set VBE Mode failed!\n");
 -         return FALSE;
 -      }
 -
 -      pI830->pipe = pipe; /* restore current pipe */
 -      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting mode on Pipe %s.\n", pI830->pipe ? "B" : "A");
 -
 -      SetPipeAccess(pScrn);
 -
 -      if (I830VESASetVBEMode(pScrn, (f->vbeData.mode | 1<<15 | 1<<14), f->vbeData.block) == FALSE) {
 -         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Set VBE Mode failed!\n");
 -         return FALSE;
 -      }
 -   }
 -
 -#if 0
 -   { /* I965G ENABLE TILING */
 -      planeA = INREG(DSPACNTR) | 1<<10;
 -      OUTREG(DSPACNTR, planeA);
 -      /* flush the change. */
 -      temp = INREG(DSPABASE);
 -      OUTREG(DSPABASE, temp);
 -   }
 -#else
 -   { /* I965G DISABLE TILING */
 -      planeA = INREG(DSPACNTR) & ~1<<10;
 -      OUTREG(DSPACNTR, planeA);
 -      /* flush the change. */
 -      temp = INREG(DSPABASE);
 -      OUTREG(DSPABASE, temp);
 -      OUTREG(DSPASURF, INREG(DSPASURF));
 -   }
 -#endif
 +   /* First, disable display planes */
 +   temp = INREG(DSPACNTR);
 +   OUTREG(DSPACNTR, temp & ~DISPLAY_PLANE_ENABLE);
 +   temp = INREG(DSPBCNTR);
 +   OUTREG(DSPBCNTR, temp & ~DISPLAY_PLANE_ENABLE);
  
 -   /*
 -    * The BIOS may not set a scanline pitch that would require more video
 -    * memory than it's aware of.  We check for this later, and set it
 -    * explicitly if necessary.
 -    */
 -   if (mp->vbeData.data->XResolution != pI830->displayWidth) {
 -      if (pI830->Clone || pI830->MergedFB) {
 -         SetBIOSPipe(pScrn, !pI830->pipe);
 -         VBESetLogicalScanline(pVbe, pI830->displayWidth);
 +   /* Next, disable display pipes */
 +   temp = INREG(PIPEACONF);
 +   OUTREG(PIPEACONF, temp & ~PIPEACONF_ENABLE);
 +   temp = INREG(PIPEBCONF);
 +   OUTREG(PIPEBCONF, temp & ~PIPEBCONF_ENABLE);
 +
 +   /* XXX: Wait for a vblank */
 +   sleep(1);
 +
 +   i830SetLVDSPanelPower(pScrn, FALSE);
 +
 +   for (i = 0; i < pI830->num_outputs; i++) {
 +      if (pI830->output[i].type == I830_OUTPUT_SDVO &&
 +	  pI830->output[i].sdvo_drv != NULL)
 +      {
 +	 i830SDVOPreRestore(pScrn, i);
        }
 -      SetPipeAccess(pScrn);
 -      VBESetLogicalScanline(pVbe, pI830->displayWidth);
     }
  
 -   if (pScrn->bitsPerPixel >= 8 && pI830->vbeInfo->Capabilities[0] & 0x01) {
 -      if (pI830->Clone || pI830->MergedFB) {
 -         SetBIOSPipe(pScrn, !pI830->pipe);
 -         VBESetGetDACPaletteFormat(pVbe, 8);
 +   OUTREG(FPA0, pI830->saveFPA0);
 +   OUTREG(FPA1, pI830->saveFPA1);
 +   OUTREG(DPLL_A, pI830->saveDPLL_A);
 +   OUTREG(HTOTAL_A, pI830->saveHTOTAL_A);
 +   OUTREG(HBLANK_A, pI830->saveHBLANK_A);
 +   OUTREG(HSYNC_A, pI830->saveHSYNC_A);
 +   OUTREG(VTOTAL_A, pI830->saveVTOTAL_A);
 +   OUTREG(VBLANK_A, pI830->saveVBLANK_A);
 +   OUTREG(VSYNC_A, pI830->saveVSYNC_A);
 +   OUTREG(DSPASTRIDE, pI830->saveDSPASTRIDE);
 +   OUTREG(DSPASIZE, pI830->saveDSPASIZE);
 +   OUTREG(DSPAPOS, pI830->saveDSPAPOS);
 +   OUTREG(DSPABASE, pI830->saveDSPABASE);
 +   OUTREG(PIPEASRC, pI830->savePIPEASRC);
 +   for(i = 0; i < 256; i++) {
 +         OUTREG(PALETTE_A + (i << 2), pI830->savePaletteA[i]);
 +   }
 +
 +   if(pI830->availablePipes == 2) {
 +      OUTREG(FPB0, pI830->saveFPB0);
 +      OUTREG(FPB1, pI830->saveFPB1);
 +      OUTREG(DPLL_B, pI830->saveDPLL_B);
 +      OUTREG(HTOTAL_B, pI830->saveHTOTAL_B);
 +      OUTREG(HBLANK_B, pI830->saveHBLANK_B);
 +      OUTREG(HSYNC_B, pI830->saveHSYNC_B);
 +      OUTREG(VTOTAL_B, pI830->saveVTOTAL_B);
 +      OUTREG(VBLANK_B, pI830->saveVBLANK_B);
 +      OUTREG(VSYNC_B, pI830->saveVSYNC_B);
 +      OUTREG(DSPBSTRIDE, pI830->saveDSPBSTRIDE);
 +      OUTREG(DSPBSIZE, pI830->saveDSPBSIZE);
 +      OUTREG(DSPBPOS, pI830->saveDSPBPOS);
 +      OUTREG(DSPBBASE, pI830->saveDSPBBASE);
 +      OUTREG(PIPEBSRC, pI830->savePIPEBSRC);
 +      for(i= 0; i < 256; i++) {
 +         OUTREG(PALETTE_B + (i << 2), pI830->savePaletteB[i]);
        }
 -      SetPipeAccess(pScrn);
 -      VBESetGetDACPaletteFormat(pVbe, 8);
     }
  
 -   /* XXX Fix plane A with pipe A, and plane B with pipe B. */
 -   planeA = INREG(DSPACNTR);
 -   planeB = INREG(DSPBCNTR);
 -
 -   pI830->planeEnabled[0] = ((planeA & DISPLAY_PLANE_ENABLE) != 0);
 -   pI830->planeEnabled[1] = ((planeB & DISPLAY_PLANE_ENABLE) != 0);
 -
 -   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Display plane A is %s and connected to %s.\n",
 -	      pI830->planeEnabled[0] ? "enabled" : "disabled",
 -	      planeA & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A");
 -   if (pI830->availablePipes == 2)
 -      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Display plane B is %s and connected to %s.\n",
 -	      pI830->planeEnabled[1] ? "enabled" : "disabled",
 -	      planeB & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A");
 -   
 -   if (pI830->operatingDevices & 0xff) {
 -      pI830->planeEnabled[0] = 1;
 -   } else { 
 -      pI830->planeEnabled[0] = 0;
++   if (IS_I965G(pI830)) {
++      OUTREG(DSPASURF, pI830->saveDSPABASE);
++      OUTREG(DSPBSURF, pI830->saveDSPBBASE);
+    }
+ 
 -   if (pI830->operatingDevices & 0xff00) {
 -      pI830->planeEnabled[1] = 1;
 -   } else {
 -      pI830->planeEnabled[1] = 0;
 -   }
 +   OUTREG(BLC_PWM_CTL, pI830->saveBLC_PWM_CTL);
 +   OUTREG(LVDSPP_ON, pI830->savePP_ON);
 +   OUTREG(LVDSPP_OFF, pI830->savePP_OFF);
 +   OUTREG(PP_CYCLE, pI830->savePP_CYCLE);
 +   OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL);
     
 -   if (pI830->planeEnabled[0]) {
 -      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabling plane A.\n");
 -      planeA |= DISPLAY_PLANE_ENABLE;
 -      planeA &= ~DISPPLANE_SEL_PIPE_MASK;
 -      planeA |= DISPPLANE_SEL_PIPE_A;
 -      OUTREG(DSPACNTR, planeA);
 -      /* flush the change. */
 -      temp = INREG(DSPABASE);
 -      OUTREG(DSPABASE, temp);
 -      if (IS_I965G(pI830)) {
 -         temp = INREG(DSPASURF);
 -         OUTREG(DSPASURF, temp);
 -      }
 -   }
 -   if (pI830->planeEnabled[1]) {
 -      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabling plane B.\n");
 -      planeB |= DISPLAY_PLANE_ENABLE;
 -      planeB &= ~DISPPLANE_SEL_PIPE_MASK;
 -      planeB |= DISPPLANE_SEL_PIPE_B;
 -      OUTREG(DSPBCNTR, planeB);
 -      /* flush the change. */
 -      temp = INREG(DSPBADDR);
 -      OUTREG(DSPBADDR, temp);
 -      if (IS_I965G(pI830)) {
 -         temp = INREG(DSPBSURF);
 -         OUTREG(DSPBSURF, temp);
 -      }
 -   }
 +   OUTREG(VCLK_DIVISOR_VGA0, pI830->saveVCLK_DIVISOR_VGA0);
 +   OUTREG(VCLK_DIVISOR_VGA1, pI830->saveVCLK_DIVISOR_VGA1);
 +   OUTREG(VCLK_POST_DIV, pI830->saveVCLK_POST_DIV);
  
 -   planeA = INREG(DSPACNTR);
 -   planeB = INREG(DSPBCNTR);
 -   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Display plane A is now %s and connected to %s.\n",
 -	      pI830->planeEnabled[0] ? "enabled" : "disabled",
 -	      planeA & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A");
 -   if (pI830->availablePipes == 2)
 -      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Display plane B is now %s and connected to %s.\n",
 -	      pI830->planeEnabled[1] ? "enabled" : "disabled",
 -	      planeB & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A");
 +   OUTREG(PIPEACONF, pI830->savePIPEACONF);
 +   OUTREG(PIPEBCONF, pI830->savePIPEBCONF);
  
 -   /* XXX Plane C is ignored for now (overlay). */
 +   OUTREG(VGACNTRL, pI830->saveVGACNTRL);
 +   OUTREG(DSPACNTR, pI830->saveDSPACNTR);
 +   OUTREG(DSPBCNTR, pI830->saveDSPBCNTR);
  
 -   /*
 -    * Print out the PIPEACONF and PIPEBCONF registers.
 -    */
 -   temp = INREG(PIPEACONF);
 -   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEACONF is 0x%08lx\n", 
 -	      (unsigned long) temp);
 -   if (pI830->availablePipes == 2) {
 -      temp = INREG(PIPEBCONF);
 -      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEBCONF is 0x%08lx\n", 
 -		 (unsigned long) temp);
 +   OUTREG(ADPA, pI830->saveADPA);
 +   OUTREG(LVDS, pI830->saveLVDS);
 +   if (!IS_I9XX(pI830)) {
 +      OUTREG(DVOA, pI830->saveDVOA);
 +      OUTREG(DVOB, pI830->saveDVOB);
 +      OUTREG(DVOC, pI830->saveDVOC);
     }
  
 -   if (xf86IsEntityShared(pScrn->entityList[0])) {
 -      /* Clean this up !! */
 -      if (I830IsPrimary(pScrn)) {
 -         CARD32 stridereg = !pI830->pipe ? DSPASTRIDE : DSPBSTRIDE;
 -         CARD32 basereg = !pI830->pipe ? DSPABASE : DSPBBASE;
 -         CARD32 sizereg = !pI830->pipe ? DSPASIZE : DSPBSIZE;
 -         CARD32 surfreg = !pI830->pipe ? DSPASURF : DSPBSURF;
 -         I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
 -
 -         temp = INREG(stridereg);
 -         if (temp / pI8301->cpp != (CARD32)(pI830->displayWidth)) {
 -            xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -		    "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(!pI830->pipe),
 -		    (int)(temp / pI8301->cpp), pI830->displayWidth);
 -	    OUTREG(stridereg, pI830->displayWidth * pI8301->cpp);
 -         }
 -         OUTREG(sizereg, (pMode->HDisplay - 1) | ((pMode->VDisplay - 1) << 16));
 -         /* Trigger update */
 -         temp = INREG(basereg);
 -         OUTREG(basereg, temp);
 -         if (IS_I965G(pI830)) {
 -            temp = INREG(surfreg);
 -            OUTREG(surfreg, temp);
 -         }
 -
 -         if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) {
 -            I830Ptr pI8302 = I830PTR(pI830->entityPrivate->pScrn_2);
 -            stridereg = pI830->pipe ? DSPASTRIDE : DSPBSTRIDE;
 -            basereg = pI830->pipe ? DSPABASE : DSPBBASE;
 -            sizereg = pI830->pipe ? DSPASIZE : DSPBSIZE;
 -            surfreg = pI830->pipe ? DSPASURF : DSPBSURF;
 -
 -            temp = INREG(stridereg);
 -            if (temp / pI8302->cpp != (CARD32)(pI8302->displayWidth)) {
 -	       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -		    "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(pI830->pipe),
 -		    (int)(temp / pI8302->cpp), pI8302->displayWidth);
 -	       OUTREG(stridereg, pI8302->displayWidth * pI8302->cpp);
 -            }
 -            OUTREG(sizereg, (pI830->entityPrivate->pScrn_2->currentMode->HDisplay - 1) | ((pI830->entityPrivate->pScrn_2->currentMode->VDisplay - 1) << 16));
 -            /* Trigger update */
 -            temp = INREG(basereg);
 -            OUTREG(basereg, temp);
 -            if (IS_I965G(pI830)) {
 -               temp = INREG(surfreg);
 -               OUTREG(surfreg, temp);
 -            }
 -         }
 -      } else {
 -         CARD32 stridereg = pI830->pipe ? DSPASTRIDE : DSPBSTRIDE;
 -         CARD32 basereg = pI830->pipe ? DSPABASE : DSPBBASE;
 -         CARD32 sizereg = pI830->pipe ? DSPASIZE : DSPBSIZE;
 -         CARD32 surfreg = pI830->pipe ? DSPASURF : DSPBSURF;
 -         I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
 -         I830Ptr pI8302 = I830PTR(pI830->entityPrivate->pScrn_2);
 -
 -         temp = INREG(stridereg);
 -         if (temp / pI8301->cpp != (CARD32)(pI8301->displayWidth)) {
 -	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -		    "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(pI830->pipe),
 -		    (int)(temp / pI8301->cpp), pI8301->displayWidth);
 -	    OUTREG(stridereg, pI8301->displayWidth * pI8301->cpp);
 -         }
 -         OUTREG(sizereg, (pI830->entityPrivate->pScrn_1->currentMode->HDisplay - 1) | ((pI830->entityPrivate->pScrn_1->currentMode->VDisplay - 1) << 16));
 -         /* Trigger update */
 -         temp = INREG(basereg);
 -         OUTREG(basereg, temp);
 -         if (IS_I965G(pI830)) {
 -            temp = INREG(surfreg);
 -            OUTREG(surfreg, temp);
 -         }
 -
 -         stridereg = !pI830->pipe ? DSPASTRIDE : DSPBSTRIDE;
 -         basereg = !pI830->pipe ? DSPABASE : DSPBBASE;
 -         sizereg = !pI830->pipe ? DSPASIZE : DSPBSIZE;
 -         surfreg = !pI830->pipe ? DSPASURF : DSPBSURF;
 -
 -         temp = INREG(stridereg);
 -         if (temp / pI8302->cpp != ((CARD32)pI8302->displayWidth)) {
 -	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -		    "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(!pI830->pipe),
 -		    (int)(temp / pI8302->cpp), pI8302->displayWidth);
 -	    OUTREG(stridereg, pI8302->displayWidth * pI8302->cpp);
 -         }
 -         OUTREG(sizereg, (pMode->HDisplay - 1) | ((pMode->VDisplay - 1) << 16));
 -         /* Trigger update */
 -         temp = INREG(basereg);
 -         OUTREG(basereg, temp);
 -         if (IS_I965G(pI830)) {
 -            temp = INREG(surfreg);
 -            OUTREG(surfreg, temp);
 -         }
 -      }
 -   } else {
 -      for (i = 0; i < pI830->availablePipes; i++) {
 -         CARD32 stridereg = i ? DSPBSTRIDE : DSPASTRIDE;
 -         CARD32 basereg = i ? DSPBBASE : DSPABASE;
 -         CARD32 sizereg = i ? DSPBSIZE : DSPASIZE;
 -         CARD32 surfreg = i ? DSPBSURF : DSPASURF;
 -
 -         if (!pI830->planeEnabled[i])
 -	    continue;
 -
 -         temp = INREG(stridereg);
 -         if (temp / pI830->cpp != (CARD32)pI830->displayWidth) {
 -	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -		    "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(i),
 -		    (int)(temp / pI830->cpp), pI830->displayWidth);
 -	    OUTREG(stridereg, pI830->displayWidth * pI830->cpp);
 -         }
 -
 -	 if (pI830->MergedFB) {
 -	    switch (pI830->SecondPosition) {
 -	       case PosRightOf:
 -	       case PosBelow:
 -                  OUTREG(DSPABASE, (CDMPTR.First->HDisplay - 1) | ((CDMPTR.First->VDisplay - 1) << 16));
 -                  OUTREG(DSPBBASE, (CDMPTR.Second->HDisplay - 1) | ((CDMPTR.Second->VDisplay - 1) << 16));
 -	          break;
 -	       case PosLeftOf:
 -	       case PosAbove:
 -                  OUTREG(DSPABASE, (CDMPTR.Second->HDisplay - 1) | ((CDMPTR.Second->VDisplay - 1) << 16));
 -                  OUTREG(DSPBBASE, (CDMPTR.First->HDisplay - 1) | ((CDMPTR.First->VDisplay - 1) << 16));
 -	          break;
 -	    }
 -         } else
 -            OUTREG(sizereg, (pMode->HDisplay - 1) | ((pMode->VDisplay - 1) << 16));
 -	 /* Trigger update */
 -	 temp = INREG(basereg);
 -	 OUTREG(basereg, temp);
 -         if (IS_I965G(pI830)) {
 -            temp = INREG(surfreg);
 -            OUTREG(surfreg, temp);
 -         }
 +   for (i = 0; i < pI830->num_outputs; i++) {
 +      if (pI830->output[i].type == I830_OUTPUT_DVO &&
 +	  pI830->output[i].i2c_drv != NULL)
 +      {
 +	 pI830->output[i].i2c_drv->vid_rec->RestoreRegs(
 +	    pI830->output[i].i2c_drv->dev_priv);
        }
 -   }
 -
 -#if 0
 -   /* Print out some CRTC/display information. */
 -   temp = INREG(HTOTAL_A);
 -   ErrorF("Horiz active: %d, Horiz total: %d\n", temp & 0x7ff,
 -	  (temp >> 16) & 0xfff);
 -   temp = INREG(HBLANK_A);
 -   ErrorF("Horiz blank start: %d, Horiz blank end: %d\n", temp & 0xfff,
 -	  (temp >> 16) & 0xfff);
 -   temp = INREG(HSYNC_A);
 -   ErrorF("Horiz sync start: %d, Horiz sync end: %d\n", temp & 0xfff,
 -	  (temp >> 16) & 0xfff);
 -   temp = INREG(VTOTAL_A);
 -   ErrorF("Vert active: %d, Vert total: %d\n", temp & 0x7ff,
 -	  (temp >> 16) & 0xfff);
 -   temp = INREG(VBLANK_A);
 -   ErrorF("Vert blank start: %d, Vert blank end: %d\n", temp & 0xfff,
 -	  (temp >> 16) & 0xfff);
 -   temp = INREG(VSYNC_A);
 -   ErrorF("Vert sync start: %d, Vert sync end: %d\n", temp & 0xfff,
 -	  (temp >> 16) & 0xfff);
 -   temp = INREG(PIPEASRC);
 -   ErrorF("Image size: %dx%d (%dx%d)\n",
 -          (temp >> 16) & 0x7ff, temp & 0x7ff,
 -	  (((temp >> 16) & 0x7ff) + 1), ((temp & 0x7ff) + 1));
 -   ErrorF("Pixel multiply is %d\n", (planeA >> 20) & 0x3);
 -   temp = INREG(DSPABASE);
 -   ErrorF("Plane A start offset is %d\n", temp);
 -   temp = INREG(DSPASTRIDE);
 -   ErrorF("Plane A stride is %d bytes (%d pixels)\n", temp, temp / pI830->cpp);
 -   temp = INREG(DSPAPOS);
 -   ErrorF("Plane A position %d %d\n", temp & 0xffff, (temp & 0xffff0000) >> 16);
 -   temp = INREG(DSPASIZE);
 -   ErrorF("Plane A size %d %d\n", temp & 0xffff, (temp & 0xffff0000) >> 16);
 -
 -   /* Print out some CRTC/display information. */
 -   temp = INREG(HTOTAL_B);
 -   ErrorF("Horiz active: %d, Horiz total: %d\n", temp & 0x7ff,
 -	  (temp >> 16) & 0xfff);
 -   temp = INREG(HBLANK_B);
 -   ErrorF("Horiz blank start: %d, Horiz blank end: %d\n", temp & 0xfff,
 -	  (temp >> 16) & 0xfff);
 -   temp = INREG(HSYNC_B);
 -   ErrorF("Horiz sync start: %d, Horiz sync end: %d\n", temp & 0xfff,
 -	  (temp >> 16) & 0xfff);
 -   temp = INREG(VTOTAL_B);
 -   ErrorF("Vert active: %d, Vert total: %d\n", temp & 0x7ff,
 -	  (temp >> 16) & 0xfff);
 -   temp = INREG(VBLANK_B);
 -   ErrorF("Vert blank start: %d, Vert blank end: %d\n", temp & 0xfff,
 -	  (temp >> 16) & 0xfff);
 -   temp = INREG(VSYNC_B);
 -   ErrorF("Vert sync start: %d, Vert sync end: %d\n", temp & 0xfff,
 -	  (temp >> 16) & 0xfff);
 -   temp = INREG(PIPEBSRC);
 -   ErrorF("Image size: %dx%d (%dx%d)\n",
 -          (temp >> 16) & 0x7ff, temp & 0x7ff,
 -	  (((temp >> 16) & 0x7ff) + 1), ((temp & 0x7ff) + 1));
 -   ErrorF("Pixel multiply is %d\n", (planeA >> 20) & 0x3);
 -   temp = INREG(DSPBBASE);
 -   ErrorF("Plane B start offset is %d\n", temp);
 -   temp = INREG(DSPBSTRIDE);
 -   ErrorF("Plane B stride is %d bytes (%d pixels)\n", temp, temp / pI830->cpp);
 -   temp = INREG(DSPBPOS);
 -   ErrorF("Plane B position %d %d\n", temp & 0xffff, (temp & 0xffff0000) >> 16);
 -   temp = INREG(DSPBSIZE);
 -   ErrorF("Plane B size %d %d\n", temp & 0xffff, (temp & 0xffff0000) >> 16);
 -#endif
 -
 -   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Mode bandwidth is %d Mpixel/s\n",
 -	      pMode->HDisplay * pMode->VDisplay * refresh / 1000000);
 -
 -   {
 -      int maxBandwidth, bandwidthA, bandwidthB;
 -
 -      if (GetModeSupport(pScrn, 0x80, 0x80, 0x80, 0x80,
 -			&maxBandwidth, &bandwidthA, &bandwidthB)) {
 -	 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "maxBandwidth is %d Mbyte/s, "
 -		    "pipe bandwidths are %d Mbyte/s, %d Mbyte/s\n",
 -		    maxBandwidth, bandwidthA, bandwidthB);
 +      if (pI830->output[i].type == I830_OUTPUT_SDVO &&
 +	  pI830->output[i].sdvo_drv != NULL)
 +      {
 +	 i830SDVOPostRestore(pScrn, i);
        }
     }
  
@@@ -3053,8 -6953,40 +3175,40 @@@
     return ret;
  }
  
+ /* Initialize the first context */
+ void
+ IntelEmitInvarientState(ScrnInfoPtr pScrn)
+ {
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD32 ctx_addr;
+ 
+    if (pI830->noAccel)
+       return;
+ 
+    ctx_addr = pI830->ContextMem.Start;
+    /* Align to a 2k boundry */
+    ctx_addr = ((ctx_addr + 2048 - 1) / 2048) * 2048;
+ 
+    {
+       BEGIN_LP_RING(2);
+       OUT_RING(MI_SET_CONTEXT);
+       OUT_RING(ctx_addr |
+ 	       CTXT_NO_RESTORE |
+ 	       CTXT_PALETTE_SAVE_DISABLE | CTXT_PALETTE_RESTORE_DISABLE);
+       ADVANCE_LP_RING();
+    }
+ 
+    if (!IS_I965G(pI830))
+    {
+       if (IS_I9XX(pI830))
+          I915EmitInvarientState(pScrn);
+       else
+          I830EmitInvarientState(pScrn);
+    }
+ }
+ 
  static Bool
 -I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
 +I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
  {
     ScrnInfoPtr pScrn;
     vgaHWPtr hwp;
@@@ -3479,14 -7493,18 +3694,12 @@@
  }
  
  static void
 -I830AdjustFrame(int scrnIndex, int x, int y, int flags)
 +i830AdjustFrame(int scrnIndex, int x, int y, int flags)
  {
 -   ScrnInfoPtr pScrn;
 -   I830Ptr pI830;
 -   vbeInfoPtr pVbe;
 -   unsigned long Start;
 -
 -   pScrn = xf86Screens[scrnIndex];
 -   pI830 = I830PTR(pScrn);
 -   pVbe = pI830->pVbe;
 +   ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
-    I830Ptr pI830;
- 
-    pI830 = I830PTR(pScrn);
++   I830Ptr pI830 = I830PTR(pScrn);
  
 -   DPRINTF(PFX, "I830AdjustFrame: y = %d (+ %d), x = %d (+ %d)\n",
 +   DPRINTF(PFX, "i830AdjustFrame: y = %d (+ %d), x = %d (+ %d)\n",
  	   x, pI830->xoffset, y, pI830->yoffset);
  
     /* Sync the engine before adjust frame */
@@@ -3582,20 -7712,32 +3798,17 @@@
  
     /* Re-read EDID */
     pDDCModule = xf86LoadSubModule(pScrn, "ddc");
-    if (pI830->vesa->monitor)
-       xfree(pI830->vesa->monitor);
-    pI830->vesa->monitor = vbeDoEDID(pI830->pVbe, pDDCModule);
+ 
 -   if (pI830->MergedFB) {
 -      pI830->pVbe->ddc = DDC_UNCHECKED;
 -      SetBIOSPipe(pScrn, !pI830->pipe);
 -      monitor = vbeDoEDID(pI830->pVbe, pDDCModule);
 -      if ((pI830->pScrn_2->monitor->DDC = monitor) != NULL) {
 -         xf86PrintEDID(monitor);
 -         xf86SetDDCproperties(pScrn, monitor);
 -      } 
 -      SetPipeAccess(pScrn);
 -   }
 -
+    pI830->pVbe->ddc = DDC_UNCHECKED;
+    monitor = vbeDoEDID(pI830->pVbe, pDDCModule);
     xf86UnloadSubModule(pDDCModule);
-    if ((pScrn->monitor->DDC = pI830->vesa->monitor) != NULL) {
-       xf86PrintEDID(pI830->vesa->monitor);
-       xf86SetDDCproperties(pScrn, pI830->vesa->monitor);
-    } else 
-       /* No DDC, so get out of here, and continue to use the current settings */
-       return FALSE; 
+    if ((pScrn->monitor->DDC = monitor) != NULL) {
+       xf86PrintEDID(monitor);
+       xf86SetDDCproperties(pScrn, monitor);
+    } 
  
-    if (!(DDCclock = I830UseDDC(pScrn)))
-       return FALSE;
+    DDCclock = I830UseDDC(pScrn);
  
 -   /* Check if DDC exists on the second head, if not don't abort. */
 -   if (pI830->MergedFB)
 -      DDCclock2 = I830UseDDC(pI830->pScrn_2);
 -
     /* Revalidate the modes */
  
     /*
@@@ -3612,8 -7756,24 +3827,7 @@@
        return FALSE;
     }
  
-    SetPipeAccess(pScrn);
 -   if (pI830->MergedFB) {
 -      SetBIOSPipe(pScrn, !pI830->pipe);
 -      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 -		 "Retrieving mode pool for second head.\n");
 -      pI830->pScrn_2->modePool = I830GetModePool(pI830->pScrn_2, pI830->pVbe, pI830->vbeInfo);
 -
 -      if (!pI830->pScrn_2->modePool) {
 -         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 -		 "No Video BIOS modes for chosen depth.\n");
 -         PreInitCleanup(pScrn);
 -         return FALSE;
 -      }
 -      SetPipeAccess(pScrn);
 -   }
 -
     VBESetModeNames(pScrn->modePool);
 -   if (pI830->MergedFB)
 -      VBESetModeNames(pI830->pScrn_2->modePool);
  
     if (pScrn->videoRam > (pI830->vbeInfo->TotalMemory * 64))
        memsize = pI830->vbeInfo->TotalMemory * 64;
@@@ -3657,10 -7827,64 +3881,39 @@@
        } while (p != NULL && p != pScrn->modes);
     }
  
-    pScrn->displayWidth = displayWidth; /* restore old displayWidth */
+    /* Only use this if we've got DDC available */
+    if (pI830->MergedFB && DDCclock2 > 0) {
+       p = pI830->pScrn_2->modes;
+       if (p == NULL)
+          return FALSE;
+       do {
+          int Clock = 100000000; /* incredible value */
+ 
+ 	 if (p->status == MODE_OK) {
+             for (pMon = pI830->pScrn_2->monitor->Modes; pMon != NULL; pMon = pMon->next) {
+                if ((pMon->HDisplay != p->HDisplay) ||
+                    (pMon->VDisplay != p->VDisplay) ||
+                    (pMon->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2)))
+                    continue;
+ 
+                /* Find lowest supported Clock for this resolution */
+                if (Clock > pMon->Clock)
+                   Clock = pMon->Clock;
+             } 
+ 
+             if (Clock != 100000000 && DDCclock2 < 2550 && Clock / 1000.0 > DDCclock2) {
+                ErrorF("(%s,%s) mode clock %gMHz exceeds DDC maximum %dMHz\n",
+ 		   p->name, pI830->pScrn_2->monitor->id,
+ 		   Clock/1000.0, DDCclock2);
+                p->status = MODE_BAD;
+             } 
+  	 }
+          p = p->next;
+       } while (p != NULL && p != pI830->pScrn_2->modes);
+    }
  
     xf86PruneDriverModes(pScrn);
 -
 -   if (pI830->MergedFB)
 -      xf86PruneDriverModes(pI830->pScrn_2);
 -
 -   if (pI830->MergedFB) {
 -      DisplayModePtr old_modes, cur_mode;
 -
 -      old_modes = pScrn->modes;
 -      cur_mode = pScrn->currentMode;
 -
 -      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MergedFB: Generating mode list\n");
 -
 -      pScrn->modes = I830GenerateModeList(pScrn, pI830->MetaModes,
 -					  old_modes, pI830->pScrn_2->modes,
 -					  pI830->SecondPosition);
 -
 -      if(!pScrn->modes) {
 -          xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes. Disabling MergedFB.\n");
 -	  pScrn->modes = old_modes;
 -	  pScrn->currentMode = cur_mode;
 -	  pI830->MergedFB = FALSE;
 -      }
 -   }
 -
 -   if (!pI830->vesa->useDefaultRefresh)
 -      I830SetModeParameters(pScrn, pI830->pVbe);
 +   I830PrintModes(pScrn);
  
     /* Now check if the previously used mode is o.k. for the current monitor.
      * This allows VT switching to continue happily when not disconnecting
@@@ -3704,10 -7945,38 +3974,13 @@@
        }
     }
  
+    if (pI830->MergedFB)
+       I830AdjustFrameMerged(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
+ 
     return TRUE;
 +#endif /* 0 */
  }
  
 -Bool
 -I830CheckModeSupport(ScrnInfoPtr pScrn, int x, int y, int mode)
 -{
 -   I830Ptr pI830 = I830PTR(pScrn);
 -   Bool ret = TRUE;
 -
 -   if (pI830->Clone) {
 -      if (pI830->pipeDisplaySize[0].x2 != 0) {
 -	 if (x > pI830->pipeDisplaySize[0].x2 ||
 -             y > pI830->pipeDisplaySize[0].y2) {
 -	 	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Bad Clone Mode removing\n");
 -		return FALSE;
 -         }
 -      }
 -      if (pI830->pipeDisplaySize[1].x2 != 0) {
 -	 if (x > pI830->pipeDisplaySize[1].x2 ||
 -             y > pI830->pipeDisplaySize[1].y2) {
 -	 	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Bad Clone Mode removing\n");
 -		return FALSE;
 -         }
 -      }
 -   }
 -
 -   return ret;
 -}
 -		
  /*
   * This gets called when gaining control of the VT, and from ScreenInit().
   */
@@@ -3764,12 -8072,22 +4037,18 @@@
  
     pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
  
 -#if SAVERESTORE_HWSTATE
 -   RestoreHWOperatingState(pScrn);
 -#endif
 -
  #ifdef XF86DRI
     if (pI830->directRenderingEnabled) {
+ 
+       I830DRISetVBlankInterrupt (pScrn, TRUE);
+ 
        if (!pI830->starting) {
+          ScreenPtr pScreen = pScrn->pScreen;
+          drmI830Sarea *sarea = (drmI830Sarea *) DRIGetSAREAPrivate(pScreen);
+          int i;
+ 
  	 I830DRIResume(screenInfo.screens[scrnIndex]);
        
- 	 I830EmitInvarientState(pScrn);
  	 I830RefreshRing(pScrn);
  	 I830Sync(pScrn);
  	 DO_RING_IDLE();
@@@ -3781,13 -8103,9 +4064,16 @@@
     }
  #endif
  
 +   /* Set the hotkey to just notify us.  We can check its results periodically
 +    * in the CheckDevicesTimer.  Eventually we want the kernel to just hand us
 +    * an input event when someone presses the button, but for now we just have
 +    * to poll.
 +    */
 +   i830SetHotkeyControl(pScrn, HOTKEY_DRIVER_NOTIFY);
 +
+    /* Needed for rotation */
+    IntelEmitInvarientState(pScrn);
+ 
     if (pI830->checkDevices)
        pI830->devicesTimer = TimerSet(NULL, 0, 1000, I830CheckDevicesTimer, pScrn);
  
@@@ -3873,31 -8199,34 +4160,37 @@@
     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
     Bool on = xf86IsUnblank(mode);
-    CARD32 temp, ctrl, base;
+    CARD32 temp, ctrl, base, surf;
 +   int i;
  
 -   DPRINTF(PFX, "I830BIOSSaveScreen: %d, on is %s\n", mode, BOOLTOSTRING(on));
 +   DPRINTF(PFX, "I830SaveScreen: %d, on is %s\n", mode, BOOLTOSTRING(on));
  
     if (pScrn->vtSema) {
 -      if (pI830->pipe == 0) {
 -	 ctrl = DSPACNTR;
 -	 base = DSPABASE;
 -	 surf = DSPASURF;
 -      } else {
 -	 ctrl = DSPBCNTR;
 -	 base = DSPBADDR;
 -	 surf = DSPBSURF;
 -      }
 -      if (pI830->planeEnabled[pI830->pipe]) {
 -	 temp = INREG(ctrl);
 -	 if (on)
 -	    temp |= DISPLAY_PLANE_ENABLE;
 -	 else
 -	    temp &= ~DISPLAY_PLANE_ENABLE;
 -	 OUTREG(ctrl, temp);
 -	 /* Flush changes */
 -	 temp = INREG(base);
 -	 OUTREG(base, temp);
 -	 if (IS_I965G(pI830)) {
 -            temp = INREG(surf);
 -            OUTREG(surf, temp);
 -         }
 +      for (i = 0; i < pI830->availablePipes; i++) {
 +        if (i == 0) {
 +	    ctrl = DSPACNTR;
 +	    base = DSPABASE;
++	    surf = DSPASURF;
 +        } else {
 +	    ctrl = DSPBCNTR;
 +	    base = DSPBADDR;
++	    surf = DSPBSURF;
 +        }
 +        if (pI830->planeEnabled[i]) {
 +	   temp = INREG(ctrl);
 +	   if (on)
 +	      temp |= DISPLAY_PLANE_ENABLE;
 +	   else
 +	      temp &= ~DISPLAY_PLANE_ENABLE;
 +	   OUTREG(ctrl, temp);
 +	   /* Flush changes */
 +	   temp = INREG(base);
 +	   OUTREG(base, temp);
++	   if (IS_I965G(pI830)) {
++	      temp = INREG(surf);
++	      OUTREG(surf, temp);
++	   }
 +        }
        }
  
        if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn) {
diff --cc src/i830_memory.c
index 2d8610a,2d09b2d..a14027d
@@@ -822,7 -854,8 +846,8 @@@
  	 alignflags = 0;
        }
  
+ #if 1 /* ROTATION */
 -      if (!pI830->MergedFB && pScrn->virtualX > pScrn->virtualY)
 +      if (pScrn->virtualX > pScrn->virtualY)
           size = lineSize * (pScrn->virtualX + cacheLines);
        else 
           size = lineSize * (pScrn->virtualY + cacheLines);
diff --cc src/i830_video.c
index 05f7f46,bbf1df7..83c032b
@@@ -114,9 -121,12 +121,12 @@@
  
  static void I830BlockHandler(int, pointer, pointer, pointer);
  
+ static FBLinearPtr
+ I830AllocateMemory(ScrnInfoPtr pScrn, FBLinearPtr linear, int size);
+ 
  #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
  
 -static Atom xvBrightness, xvContrast, xvColorKey, xvPipe, xvDoubleBuffer;
 +static Atom xvBrightness, xvContrast, xvSaturation, xvColorKey, xvPipe, xvDoubleBuffer;
  static Atom xvGamma0, xvGamma1, xvGamma2, xvGamma3, xvGamma4, xvGamma5;
  
  #define IMAGE_MAX_WIDTH		1920
@@@ -502,9 -511,11 +512,11 @@@
     overlay->SWIDTHSW = 0;
     overlay->SHEIGHT = 0;
     overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff);
 -   overlay->OCLRC1 = 0x00000080;	/* saturation: bypass */
 +   overlay->OCLRC1 = pPriv->saturation;
+ #if 0
     overlay->AWINPOS = 0;
     overlay->AWINSZ = 0;
+ #endif
     overlay->FASTHSCALE = 0;
  
     /*
@@@ -1427,21 -1573,24 +1589,12 @@@
     CompareOverlay(pI830, (CARD32 *) overlay, 0x100);
  #endif
  
-    /* When in dual head with different bpp setups we need to refresh the
-     * color key, so let's reset the video parameters and refresh here */
-    if (pI830->entityPrivate)
-       I830ResetVideo(pScrn);
- 
-    /* Ensure overlay is turned on with OVERLAY_ENABLE at 0 */
-    if (!*pI830->overlayOn)
-       OVERLAY_UPDATE;
- 
     switch (pI830->rotation) {
  	case RR_Rotate_0:
 -                if (pI830->MergedFB) {
 -		   memcpy(&dstBox2, dstBox, sizeof(BoxRec));
 -		   dstBox->x1 -= pI830->FirstframeX0;
 -		   dstBox->x2 -= pI830->FirstframeX0;
 -		   dstBox->y1 -= pI830->FirstframeY0;
 -		   dstBox->y2 -= pI830->FirstframeY0;
 -		   dstBox2.x1 -= pI830->pScrn_2->frameX0;
 -		   dstBox2.x2 -= pI830->pScrn_2->frameX0;
 -		   dstBox2.y1 -= pI830->pScrn_2->frameY0;
 -		   dstBox2.y2 -= pI830->pScrn_2->frameY0;
 -                } else {
 -		   dstBox->x1 -= pScrn->frameX0;
 -		   dstBox->x2 -= pScrn->frameX0;
 -		   dstBox->y1 -= pScrn->frameY0;
 -		   dstBox->y2 -= pScrn->frameY0;
 -                }
 +		dstBox->x1 -= pScrn->frameX0;
 +		dstBox->x2 -= pScrn->frameX0;
 +		dstBox->y1 -= pScrn->frameY0;
 +		dstBox->y2 -= pScrn->frameY0;
  		break;
  	case RR_Rotate_90:
  		tmp = dstBox->x1;
@@@ -1475,6 -1624,72 +1628,16 @@@
  		break;
     }
  
 -   if (pI830->MergedFB) {
 -      I830ModePrivatePtr mp = (I830ModePrivatePtr)pScrn->currentMode->Private;
 -      int w1, h1, w2, h2;
 -
 -      /* Clip the video to the independent modes of the merged screens */
 -      if (dstBox->x1 > mp->merged.First->HDisplay) dstBox->x1 = mp->merged.First->HDisplay - 1;
 -      if (dstBox->x2 > mp->merged.First->HDisplay) dstBox->x2 = mp->merged.First->HDisplay - 1;
 -      if (dstBox2.x1 > mp->merged.Second->HDisplay) dstBox2.x1 = mp->merged.Second->HDisplay - 1;
 -      if (dstBox2.x2 > mp->merged.Second->HDisplay) dstBox2.x2 = mp->merged.Second->HDisplay - 1;
 -      if (dstBox->y1 > mp->merged.First->VDisplay) dstBox->y1 = mp->merged.First->VDisplay - 1;
 -      if (dstBox->y2 > mp->merged.First->VDisplay) dstBox->y2 = mp->merged.First->VDisplay - 1;
 -      if (dstBox2.y1 > mp->merged.Second->VDisplay) dstBox2.y1 = mp->merged.Second->VDisplay - 1;
 -      if (dstBox2.y2 > mp->merged.Second->VDisplay) dstBox2.y2 = mp->merged.Second->VDisplay - 1;
 -      if (dstBox->y1 < 0) dstBox->y1 = 0;
 -      if (dstBox->y2 < 0) dstBox->y2 = 0;
 -      if (dstBox->x1 < 0) dstBox->x1 = 0;
 -      if (dstBox->x2 < 0) dstBox->x2 = 0;
 -      if (dstBox2.y1 < 0) dstBox2.y1 = 0;
 -      if (dstBox2.y2 < 0) dstBox2.y2 = 0;
 -      if (dstBox2.x1 < 0) dstBox2.x1 = 0;
 -      if (dstBox2.x2 < 0) dstBox2.x2 = 0;
 -
 -      w1 = dstBox->x2 - dstBox->x1;
 -      w2 = dstBox2.x2 - dstBox2.x1;
 -      h1 = dstBox->y2 - dstBox->y1;
 -      h2 = dstBox2.y2 - dstBox2.y1;
 -
 -      switch (pI830->SecondPosition) {
 -         case PosRightOf:
 -         case PosBelow:
 -            if ((w2 > 0 && w1 == 0) ||
 -                (h2 > 0 && h1 == 0)) {
 -               pPriv->pipe = !pI830->pipe;
 -               dstBox->x1 = dstBox2.x1;
 -               dstBox->y1 = dstBox2.y1;
 -               dstBox->x2 = dstBox2.x2;
 -               dstBox->y2 = dstBox2.y2;
 -            } else 
 -               pPriv->pipe = pI830->pipe;
 -            break;
 -         case PosLeftOf:
 -         case PosAbove:
 -            if ((w1 > 0 && w2 == 0) ||
 -                (h1 > 0 && h2 == 0)) { 
 -               pPriv->pipe = pI830->pipe;
 -            } else {
 -               pPriv->pipe = !pI830->pipe;
 -               dstBox->x1 = dstBox2.x1;
 -               dstBox->y1 = dstBox2.y1;
 -               dstBox->x2 = dstBox2.x2;
 -               dstBox->y2 = dstBox2.y2;
 -            }
 -            break;
 -      }
 -   }
 -
+    /* When in dual head with different bpp setups we need to refresh the
+     * color key, so let's reset the video parameters and refresh here.
+     * In MergedFB mode, we may need to flip pipes too. */
 -   if (pI830->entityPrivate || pI830->MergedFB)
++   if (pI830->entityPrivate)
+       I830ResetVideo(pScrn);
+ 
+    /* Ensure overlay is turned on with OVERLAY_ENABLE at 0 */
+    if (!*pI830->overlayOn)
+       OVERLAY_UPDATE;
+ 
     /* Fix up the dstBox if outside the visible screen */
     {
        int offset_x = (dstBox->x1 < 0) ? -dstBox->x1 : 0;
diff --cc src/i830_video.h
index 0000000,9e11641..6a09a25
mode 000000,100644..100644
@@@ -1,0 -1,76 +1,77 @@@
+ /***************************************************************************
+  
+ Copyright 2000 Intel Corporation.  All Rights Reserved. 
+ 
+ Permission is hereby granted, free of charge, to any person obtaining a 
+ copy of this software and associated documentation files (the 
+ "Software"), to deal in the Software without restriction, including 
+ without limitation the rights to use, copy, modify, merge, publish, 
+ distribute, sub license, and/or sell copies of the Software, and to 
+ permit persons to whom the Software is furnished to do so, subject to 
+ the following conditions: 
+ 
+ The above copyright notice and this permission notice (including the 
+ next paragraph) shall be included in all copies or substantial portions 
+ of the Software. 
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 
+ IN NO EVENT SHALL INTEL, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
+ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 
+ THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ 
+ **************************************************************************/
+ 
+ #include "xf86.h"
+ #include "xf86_OSproc.h"
+ 
+ typedef struct {
+    CARD32 YBuf0offset;
+    CARD32 UBuf0offset;
+    CARD32 VBuf0offset;
+ 
+    CARD32 YBuf1offset;
+    CARD32 UBuf1offset;
+    CARD32 VBuf1offset;
+ 
+    unsigned char currentBuf;
+ 
+    int brightness;
+    int contrast;
++   int saturation;
+    int pipe;
+    int doubleBuffer;
+ 
+    RegionRec clip;
+    CARD32 colorKey;
+ 
+    CARD32 gamma0;
+    CARD32 gamma1;
+    CARD32 gamma2;
+    CARD32 gamma3;
+    CARD32 gamma4;
+    CARD32 gamma5;
+ 
+    CARD32 videoStatus;
+    Time offTime;
+    Time freeTime;
+    FBLinearPtr linear;
+ 
+    Bool overlayOK;
+    int oneLineMode;
+    int scaleRatio;
+    Bool textured;
+ } I830PortPrivRec, *I830PortPrivPtr;
+ 
+ #define GET_PORT_PRIVATE(pScrn) \
+    (I830PortPrivPtr)((I830PTR(pScrn))->adaptor->pPortPrivates[0].ptr)
+ 
+ void I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv,
+ 			      int id, RegionPtr dstRegion, short width,
+ 			      short height, int video_pitch,
+ 			      int x1, int y1, int x2, int y2,
+ 			      short src_w, short src_h,
+ 			      short drw_w, short drw_h,
+ 			      DrawablePtr pDraw);
diff-tree fdb6de663579d3b9f31bf9e8a93430b8505ca73f (from 1407a42c7378706644fd8be554b43b0e7b581011)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Sep 27 13:59:41 2006 -0700

    Re-disable broken load-based CRT detection.

diff --git a/src/i830_display.c b/src/i830_display.c
index 88280bb..24ce50f 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -1081,7 +1081,7 @@ i830DetectCRT(ScrnInfoPtr pScrn, Bool al
      * pipe, as it seems having other outputs on that pipe will result in a
      * false positive.
      */
-    if (1 && (allow_disturb || !(INREG(ADPA) & !ADPA_DAC_ENABLE))) {
+    if (0 && (allow_disturb || !(INREG(ADPA) & !ADPA_DAC_ENABLE))) {
 	return i830LoadDetectCRT(pScrn);
     }
 
diff-tree 1407a42c7378706644fd8be554b43b0e7b581011 (from parents)
Merge: 25890ecda9fd00fad9bc53dea83fc58e0013fcdf 4bd3b89c73b6c5aa9b0eb553ad5d553ee0e8a489
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Sep 27 13:33:23 2006 -0700

    Merge branch 'randr-1.2' into modesetting

diff --cc src/i830_driver.c
index 5b98bfd,bc9b71a..b4f5394
@@@ -3342,11 -3498,17 +3328,14 @@@
     if (!vgaHWMapMem(pScrn))
        return FALSE;
  
 -   /* Clear SavedReg */
 -   memset(&pI830->SavedReg, 0, sizeof(pI830->SavedReg));
 -
 -   DPRINTF(PFX, "assert( if(!I830BIOSEnterVT(scrnIndex, 0)) )\n");
 +   DPRINTF(PFX, "assert( if(!I830EnterVT(scrnIndex, 0)) )\n");
  
 -   if (!I830BIOSEnterVT(scrnIndex, 0))
 +   if (!I830EnterVT(scrnIndex, 0))
        return FALSE;
  
+     if (pScrn->virtualX > pScrn->displayWidth)
+ 	pScrn->displayWidth = pScrn->virtualX;
+ 
     DPRINTF(PFX, "assert( if(!fbScreenInit(pScreen, ...) )\n");
     if (!fbScreenInit(pScreen, pI830->FbBase + pScrn->fbOffset, 
                       pScrn->virtualX, pScrn->virtualY,
diff-tree 25890ecda9fd00fad9bc53dea83fc58e0013fcdf (from parents)
Merge: 965609f6fa63e28e5a28128f5bc44f8c4d7b9f68 117ff04b504578a24dff70659e2db1b81aaa1177
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Sep 27 13:33:17 2006 -0700

    Merge branch 'acpi-hotkey' into modesetting
    
    Conflicts:
    
    	src/i830.h
    	src/i830_driver.c

diff --cc src/i830.h
index 92c9111,4a95441..19bdd74
@@@ -392,11 -393,12 +392,8 @@@
     CARD32 saveSWF4;
  
     Bool checkDevices;
-    int monitorSwitch;
     int operatingDevices;
-    int toggleDevices;
-    int lastDevice0, lastDevice1, lastDevice2;
  
 -   /* These are indexed by the display types */
 -   Bool displayAttached[NumDisplayTypes];
 -   Bool displayPresent[NumDisplayTypes];
 -
     /* [0] is Pipe A, [1] is Pipe B. */
     int availablePipes;
     /* [0] is display plane A, [1] is display plane B. */
diff --cc src/i830_driver.c
index 31e3b17,c3ae8c3..5b98bfd
@@@ -1190,8 -1107,33 +1080,33 @@@
     return TRUE;
  }
  
+ #define HOTKEY_BIOS_SWITCH	0
+ #define HOTKEY_DRIVER_NOTIFY	1
+ 
+ /**
+  * Controls the BIOS's behavior on hotkey switch.
+  *
+  * If the mode is HOTKEY_BIOS_SWITCH, the BIOS will be set to do a mode switch
+  * on its own and update the state in the scratch register.
+  * If the mode is HOTKEY_DRIVER_NOTIFY, the BIOS won't do a mode switch and
+  * will just update the state to represent what it would have been switched to.
+  */
+ static void
+ i830SetHotkeyControl(ScrnInfoPtr pScrn, int mode)
+ {
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD8 gr18;
+ 
+    gr18 = pI830->readControl(pI830, GRX, 0x18);
+    if (mode == HOTKEY_BIOS_SWITCH)
+       gr18 &= ~HOTKEY_VBIOS_SWITCH_BLOCK;
+    else
+       gr18 |= HOTKEY_VBIOS_SWITCH_BLOCK;
+    pI830->writeControl(pI830, GRX, 0x18, gr18);
+ }
+ 
  static Bool
 -I830BIOSPreInit(ScrnInfoPtr pScrn, int flags)
 +I830PreInit(ScrnInfoPtr pScrn, int flags)
  {
     vgaHWPtr hwp;
     I830Ptr pI830;
diff-tree 117ff04b504578a24dff70659e2db1b81aaa1177 (from daade50ca271d1cdf236bbe84afade85d4111ac9)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Sep 21 17:03:34 2006 -0700

    Attempt to make the ACPI hotkey support a little more modesetting-compatible.
    
    Previously, we watched for the BIOS to have changed the layout, and repaired
    the resulting configuration.  Now, we request that the BIOS make no changes,
    but leave a note in a register for when the key has been pressed.  When we
    notice this, we reprobe monitors and turn on/off the things we find.
    
    This is a temporary solution until we can get the hotkey hooked up as an
    input key to external applications to control the change using RandR 1.2.  It
    is also untested as neither of my laptops do anything with the hotkey.
    However, this code does result in many fewer BIOS calls.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index 275d858..3a15a46 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -94,6 +94,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define LINEAR_MODE_ENABLE     0x02
 #define PAGE_MAPPING_ENABLE    0x01
 
+#define HOTKEY_VBIOS_SWITCH_BLOCK	0x80
+#define HOTKEY_SWITCH			0x20
+#define HOTKEY_TOGGLE			0x10
+
 /* Blitter control, p378
  */
 #define BITBLT_CNTL        0x7000c
diff --git a/src/i830.h b/src/i830.h
index 3a93931..4a95441 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -393,10 +393,7 @@ typedef struct _I830Rec {
    CARD32 saveSWF4;
 
    Bool checkDevices;
-   int monitorSwitch;
    int operatingDevices;
-   int toggleDevices;
-   int lastDevice0, lastDevice1, lastDevice2;
 
    /* These are indexed by the display types */
    Bool displayAttached[NumDisplayTypes];
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 75ea480..c3ae8c3 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -438,116 +438,6 @@ Check5fStatus(ScrnInfoPtr pScrn, int fun
    }
 }
 
-static int
-GetToggleList(ScrnInfoPtr pScrn, int toggle)
-{
-   vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
-
-   DPRINTF(PFX, "GetToggleList\n");
-
-   pVbe->pInt10->num = 0x10;
-   pVbe->pInt10->ax = 0x5f64;
-   pVbe->pInt10->bx = 0x500;
- 
-   pVbe->pInt10->bx |= toggle;
-
-   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
-   if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) {
-      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Toggle (%d) 0x%x\n", toggle, pVbe->pInt10->cx);
-      return pVbe->pInt10->cx & 0xffff;
-   }
-
-   return 0;
-}
-
-static int
-GetNextDisplayDeviceList(ScrnInfoPtr pScrn, int toggle)
-{
-   vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
-   int devices = 0;
-   int pipe = 0;
-   int i;
-
-   DPRINTF(PFX, "GetNextDisplayDeviceList\n");
-
-   pVbe->pInt10->num = 0x10;
-   pVbe->pInt10->ax = 0x5f64;
-   pVbe->pInt10->bx = 0xA00;
-   pVbe->pInt10->bx |= toggle;
-   pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base);
-   pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base);
-
-   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
-   if (!Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax))
-      return 0;
-
-   for (i=0; i<(pVbe->pInt10->cx & 0xff); i++) {
-      CARD32 VODA = (CARD32)((CARD32*)pVbe->memory)[i];
-
-      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Next ACPI _DGS [%d] 0x%lx\n",
-		 i, (unsigned long) VODA);
-
-      /* Check if it's a custom Video Output Device Attribute */
-      if (!(VODA & 0x80000000)) 
-         continue;
-
-      pipe = (VODA & 0x000000F0) >> 4;
-
-      if (pipe != 0 && pipe != 1) {
-         pipe = 0;
-#if 0
-         ErrorF("PIPE %d\n",pipe);
-#endif
-      }
-
-      switch ((VODA & 0x00000F00) >> 8) {
-      case 0x0:
-      case 0x1: /* CRT */
-         devices |= PIPE_CRT << (pipe == 1 ? 8 : 0);
-         break;
-      case 0x2: /* TV/HDTV */
-         devices |= PIPE_TV << (pipe == 1 ? 8 : 0);
-         break;
-      case 0x3: /* DFP */
-         devices |= PIPE_DFP << (pipe == 1 ? 8 : 0);
-         break;
-      case 0x4: /* LFP */
-         devices |= PIPE_LFP << (pipe == 1 ? 8 : 0);
-         break;
-      }
-   }
-
-   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ACPI Toggle devices 0x%x\n", devices);
-
-   return devices;
-}
-
-static int
-GetAttachableDisplayDeviceList(ScrnInfoPtr pScrn)
-{
-   vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
-   int i;
-
-   DPRINTF(PFX, "GetAttachableDisplayDeviceList\n");
-
-   pVbe->pInt10->num = 0x10;
-   pVbe->pInt10->ax = 0x5f64;
-   pVbe->pInt10->bx = 0x900;
-   pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base);
-   pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base);
-
-   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
-   if (!Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax))
-      return 0;
-
-   for (i=0; i<(pVbe->pInt10->cx & 0xff); i++)
-        xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
-		"Attachable device 0x%lx.\n", 
-		   (unsigned long) ((CARD32*)pVbe->memory)[i]);
-
-   return pVbe->pInt10->cx & 0xffff;
-}
-
 struct panelid {
 	short hsize;
 	short vsize;
@@ -1217,6 +1107,31 @@ I830IsPrimary(ScrnInfoPtr pScrn)
    return TRUE;
 }
 
+#define HOTKEY_BIOS_SWITCH	0
+#define HOTKEY_DRIVER_NOTIFY	1
+
+/**
+ * Controls the BIOS's behavior on hotkey switch.
+ *
+ * If the mode is HOTKEY_BIOS_SWITCH, the BIOS will be set to do a mode switch
+ * on its own and update the state in the scratch register.
+ * If the mode is HOTKEY_DRIVER_NOTIFY, the BIOS won't do a mode switch and
+ * will just update the state to represent what it would have been switched to.
+ */
+static void
+i830SetHotkeyControl(ScrnInfoPtr pScrn, int mode)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+   CARD8 gr18;
+
+   gr18 = pI830->readControl(pI830, GRX, 0x18);
+   if (mode == HOTKEY_BIOS_SWITCH)
+      gr18 &= ~HOTKEY_VBIOS_SWITCH_BLOCK;
+   else
+      gr18 |= HOTKEY_VBIOS_SWITCH_BLOCK;
+   pI830->writeControl(pI830, GRX, 0x18, gr18);
+}
+
 static Bool
 I830BIOSPreInit(ScrnInfoPtr pScrn, int flags)
 {
@@ -2179,28 +2094,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
 	      "Maximum frambuffer space: %d kByte\n", pScrn->videoRam);
 
-   /* XXX Move this to a header. */
-#define VIDEO_BIOS_SCRATCH 0x18
-
-#if 1
-   /*
-    * XXX This should be in ScreenInit/EnterVT.  PreInit should not leave the
-    * state changed.
-    */
-   /* Enable hot keys by writing the proper value to GR18 */
-   {
-      CARD8 gr18;
-
-      gr18 = pI830->readControl(pI830, GRX, VIDEO_BIOS_SCRATCH);
-      gr18 &= ~0x80;			/*
-					 * Clear Hot key bit so that Video
-					 * BIOS performs the hot key
-					 * servicing
-					 */
-      pI830->writeControl(pI830, GRX, VIDEO_BIOS_SCRATCH, gr18);
-   }
-#endif
-
    /*
     * Limit videoram available for mode selection to what the video
     * BIOS can see.
@@ -3734,6 +3627,8 @@ I830BIOSLeaveVT(int scrnIndex, int flags
       TimerCancel(pI830->devicesTimer);
    pI830->devicesTimer = NULL;
 
+   i830SetHotkeyControl(pScrn, HOTKEY_BIOS_SWITCH);
+
 #ifdef I830_XV
    /* Give the video overlay code a chance to shutdown. */
    I830VideoSwitchModeBefore(pScrn, NULL);
@@ -3951,9 +3846,6 @@ I830BIOSEnterVT(int scrnIndex, int flags
 	  pScrn->virtualY * pScrn->displayWidth * pI830->cpp);
 #endif
 
-   /* Setup for device monitoring status */
-   pI830->monitorSwitch = pI830->toggleDevices = INREG(SWF0) & 0x0000FFFF;
-
    if (I830IsPrimary(pScrn))
       if (!I830BindAGPMemory(pScrn))
          return FALSE;
@@ -4003,6 +3895,13 @@ I830BIOSEnterVT(int scrnIndex, int flags
    }
 #endif
 
+   /* Set the hotkey to just notify us.  We can check its results periodically
+    * in the CheckDevicesTimer.  Eventually we want the kernel to just hand us
+    * an input event when someone presses the button, but for now we just have
+    * to poll.
+    */
+   i830SetHotkeyControl(pScrn, HOTKEY_DRIVER_NOTIFY);
+
    if (pI830->checkDevices)
       pI830->devicesTimer = TimerSet(NULL, 0, 1000, I830CheckDevicesTimer, pScrn);
 
@@ -4367,15 +4266,6 @@ I830PMEvent(int scrnIndex, pmEvent event
 
       ErrorF("I830PMEvent: Capability change\n");
 
-      /* ACPI Toggle */
-      pI830->toggleDevices = GetNextDisplayDeviceList(pScrn, 1);
-      if (xf86IsEntityShared(pScrn->entityList[0])) {
-         I830Ptr pI8302 = I830PTR(pI830->entityPrivate->pScrn_2);
-         pI8302->toggleDevices = pI830->toggleDevices;
-      }
-
-      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ACPI Toggle to 0x%x\n",pI830->toggleDevices);
-
       I830CheckDevicesTimer(NULL, 0, pScrn);
       SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset);
       break;
@@ -4385,27 +4275,16 @@ I830PMEvent(int scrnIndex, pmEvent event
    return TRUE;
 }
 
-static int CountBits(int a)
-{
-   int i;
-   int b = 0;
-
-   for (i=0;i<8;i++) {
-     if (a & (1<<i))
-        b+=1;
-   }
-
-   return b;
-}
-
-static CARD32
-I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg)
-{
-   ScrnInfoPtr pScrn = (ScrnInfoPtr) arg;
-   I830Ptr pI830 = I830PTR(pScrn);
-   int cloned = 0;
 #if 0
+/**
+ * This function is used for testing of the screen detect functions from the
+ * periodic timer.
+ */
+static void
+i830MonitorDetectDebugger(ScrnInfoPtr pScrn)
+{
    Bool found_crt;
+   I830Ptr pI830 = I830PTR(pScrn);
    int start, finish, i;
 
    if (!pScrn->vtSema)
@@ -4431,303 +4310,41 @@ I830CheckDevicesTimer(OsTimerPtr timer, 
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Detected SDVO as %s in %dms\n",
 		 found_sdvo ? "connected" : "disconnected", finish - start);
    }
+}
 #endif
 
-   if (pScrn->vtSema) {
-      /* Check for monitor lid being closed/opened and act accordingly */
-      CARD32 adjust;
-      CARD32 temp = INREG(SWF0) & 0x0000FFFF;
-      int fixup = 0;
-      I830Ptr pI8301;
-      I830Ptr pI8302 = NULL;
-
-      if (I830IsPrimary(pScrn))
-         pI8301 = pI830;
-      else 
-         pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
-
-      if (xf86IsEntityShared(pScrn->entityList[0]))
-         pI8302 = I830PTR(pI830->entityPrivate->pScrn_2);
-
-      /* this avoids several BIOS calls if possible */
-      if (pI830->monitorSwitch != temp || pI830->monitorSwitch != pI830->toggleDevices) {
-         xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
-		    "Hotkey switch to 0x%lx.\n", (unsigned long) temp);
-
-         if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
-            (*pI830->AccelInfoRec->Sync)(pScrn);
-            pI830->AccelInfoRec->NeedToSync = FALSE;
-            if (xf86IsEntityShared(pScrn->entityList[0]))
-               pI8302->AccelInfoRec->NeedToSync = FALSE;
-         }
-
-         GetAttachableDisplayDeviceList(pScrn);
-         
-	 pI8301->lastDevice0 = pI8301->lastDevice1;
-         pI8301->lastDevice1 = pI8301->lastDevice2;
-         pI8301->lastDevice2 = pI8301->monitorSwitch;
-
-	 if (temp != pI8301->lastDevice1 && 
-	     temp != pI8301->lastDevice2) {
-            xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
-			"Detected three device configs.\n");
-	 } else
-         if (CountBits(temp & 0xff) > 1) {
-            xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
-			"Detected cloned pipe mode (A).\n");
-            if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone)
-	       temp = pI8301->MonType2 << 8 | pI8301->MonType1;
-         } else
-         if (CountBits((temp & 0xff00) >> 8) > 1) {
-            xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
-			"Detected cloned pipe mode (B).\n");
-            if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone)
-	       temp = pI8301->MonType2 << 8 | pI8301->MonType1;
-         } else
-         if (pI8301->lastDevice1 && pI8301->lastDevice2) {
-            if ( ((pI8301->lastDevice1 & 0xFF00) == 0) && 
-                 ((pI8301->lastDevice2 & 0x00FF) == 0) ) {
-               xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
-			"Detected last devices (1).\n");
-	       cloned = 1;
-            } else if ( ((pI8301->lastDevice2 & 0xFF00) == 0) && 
-                 ((pI8301->lastDevice1 & 0x00FF) == 0) ) {
-               xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
-			"Detected last devices (2).\n");
-	       cloned = 1;
-            } else
-               cloned = 0;
-         }
-
-         if (cloned &&
-             ((CountBits(pI8301->lastDevice1 & 0xff) > 1) ||
-             ((CountBits((pI8301->lastDevice1 & 0xff00) >> 8) > 1))) ) {
-               xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
-			"Detected duplicate (1).\n");
-               cloned = 0;
-         } else
-         if (cloned &&
-             ((CountBits(pI8301->lastDevice2 & 0xff) > 1) ||
-             ((CountBits((pI8301->lastDevice2 & 0xff00) >> 8) > 1))) ) {
-               xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
-			"Detected duplicate (2).\n");
-               cloned = 0;
-         } 
-
-         xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
-			"Requested display devices 0x%lx.\n", 
-		    (unsigned long) temp);
-
-
-         /* If the BIOS doesn't flip between CRT, LFP and CRT+LFP we fake
-          * it here as it seems some just flip between CRT and LFP. Ugh!
-          *
-          * So this pushes them onto Pipe B and clones the displays, which
-          * is what most BIOS' should be doing.
-          *
-          * Cloned pipe mode should only be done when running single head.
-          */
-         if (xf86IsEntityShared(pScrn->entityList[0])) {
-            cloned = 0;
-
-	    /* Some BIOS' don't realize we may be in true dual head mode.
-	     * And only display the primary output on both when switching.
-	     * We detect this here and cycle back to both pipes.
-	     */
-	    if ((pI830->lastDevice0 == temp) &&
-                ((CountBits(pI8301->lastDevice2 & 0xff) > 1) ||
-                ((CountBits((pI8301->lastDevice2 & 0xff00) >> 8) > 1))) ) {
-               xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
-			"Detected cloned pipe mode when dual head on previous switch. (0x%x -> 0x%x)\n", (int)temp, pI8301->MonType2 << 8 | pI8301->MonType1);
-	       temp = pI8301->MonType2 << 8 | pI8301->MonType1;
-	    }
-	    
-	 }
-
-         if (cloned) { 
-            if (pI830->Clone)
-               temp = pI8301->MonType2 << 8 | pI8301->MonType1;
-	    else if (pI8301->lastDevice1 & 0xFF)
-	       temp = pI8301->lastDevice1 << 8 | pI8301->lastDevice2;
-            else
-	       temp = pI8301->lastDevice2 << 8 | pI8301->lastDevice1;
-         } 
-
-         /* Jump to our next mode if we detect we've been here before */
-         if (temp == pI8301->lastDevice1 || temp == pI8301->lastDevice2) {
-             temp = GetToggleList(pScrn, 1);
-             xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
-			"Detected duplicate devices. Toggling (0x%lx)\n", 
-			(unsigned long) temp);
-         }
-
-         xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
-		"Detected display change operation (0x%x, 0x%x, 0x%lx).\n", 
-                pI8301->lastDevice1, pI8301->lastDevice2, 
-		    (unsigned long) temp);
-
-         /* So that if we close on the wrong config, we restore correctly */
-         pI830->specifiedMonitor = TRUE;
-
-         if (!xf86IsEntityShared(pScrn->entityList[0])) {
-            if ((temp & 0xFF00) && (temp & 0x00FF)) {
-               pI830->Clone = TRUE;
-               xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting Clone mode\n");
-            } else {
-               pI830->Clone = FALSE;
-               xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clearing Clone mode\n");
-            }
-         }
-
-         {
-            /* Turn Cursor off before switching */
-            Bool on = pI830->cursorOn;
-            if (pI830->CursorInfoRec && pI830->CursorInfoRec->HideCursor)
-               pI830->CursorInfoRec->HideCursor(pScrn);
-            pI830->cursorOn = on;
-         }
-
-#if 0 /* Disable -- I'll need to look at this whole function later. */
-         /* double check the display devices are what's configured and try
-          * not to do it twice because of dual heads with the code above */
-         if (!SetDisplayDevices(pScrn, temp)) {
-            if ( cloned &&
-                    ((CountBits(temp & 0xff) > 1) ||
-                     (CountBits((temp & 0xff00) >> 8) > 1)) ) {
-	       temp = pI8301->lastDevice2 | pI8301->lastDevice1;
-               xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Cloning failed, "
-			  "trying dual pipe clone mode (0x%lx)\n", 
-			  (unsigned long) temp);
-               if (!SetDisplayDevices(pScrn, temp))
-                    xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Failed to switch "
- 		    "to configured display devices (0x%lx).\n", 
-			       (unsigned long) temp);
-               else {
-                 pI830->Clone = TRUE;
-                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting Clone mode\n");
-               }
-            }
-         }
-#endif
-
-         pI8301->monitorSwitch = temp;
-	 pI8301->operatingDevices = temp;
-	 pI8301->toggleDevices = temp;
-
-         if (xf86IsEntityShared(pScrn->entityList[0])) {
-	    pI8302->operatingDevices = pI8301->operatingDevices;
-            pI8302->monitorSwitch = pI8301->monitorSwitch;
-	    pI8302->toggleDevices = pI8301->toggleDevices;
-         }
+static CARD32
+I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg)
+{
+   ScrnInfoPtr pScrn = (ScrnInfoPtr) arg;
+   I830Ptr pI830 = I830PTR(pScrn);
+   CARD8 gr18;
 
-         fixup = 1;
+   if (!pScrn->vtSema)
+      return 1000;
 
 #if 0
-         xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
-			"ACPI _DGS queried devices is 0x%x, but probed is 0x%x monitorSwitch=0x%x\n", 
-			pI830->toggleDevices, INREG(SWF0), pI830->monitorSwitch);
+   i830MonitorDetectDebugger(pScrn);
 #endif
-      } else {
-         int offset = -1;
-         if (I830IsPrimary(pScrn))
-            offset = pI8301->FrontBuffer.Start + ((pScrn->frameY0 * pI830->displayWidth + pScrn->frameX0) * pI830->cpp);
-         else {
-            offset = pI8301->FrontBuffer2.Start + ((pScrn->frameY0 * pI830->displayWidth + pScrn->frameX0) * pI830->cpp);
-	 }
-
-         if (pI830->pipe == 0)
-            adjust = INREG(DSPABASE);
-         else 
-            adjust = INREG(DSPBBASE);
-
-         if (adjust != offset) {
-            xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-			                       "Fixing display offsets.\n");
-
-            i830AdjustFrame(pScrn->pScreen->myNum, pScrn->frameX0, pScrn->frameY0, 0);
-         }
-      }
-
-      if (fixup) {
-         ScreenPtr   pCursorScreen;
-         int x = 0, y = 0;
-
 
-         pCursorScreen = miPointerCurrentScreen();
-         if (pScrn->pScreen == pCursorScreen)
-            miPointerPosition(&x, &y);
-
-         /* Now, when we're single head, make sure we switch pipes */
-         if (!(xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone) || cloned) {
-            if (temp & 0xFF00)
-               pI830->pipe = 1;
-            else 
-               pI830->pipe = 0;
-	       xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-			 "Primary pipe is now %s.\n", pI830->pipe ? "B" : "A");
-         } 
-
-         pI830->currentMode = NULL;
-         I830BIOSSwitchMode(pScrn->pScreen->myNum, pScrn->currentMode, 0);
-         i830AdjustFrame(pScrn->pScreen->myNum, pScrn->frameX0, pScrn->frameY0, 0);
-
-         if (xf86IsEntityShared(pScrn->entityList[0])) {
-	    ScrnInfoPtr pScrn2;
-            I830Ptr pI8302;
-
-            if (I830IsPrimary(pScrn)) {
-	       pScrn2 = pI830->entityPrivate->pScrn_2;
-               pI8302 = I830PTR(pI830->entityPrivate->pScrn_2);
-            } else {
-	       pScrn2 = pI830->entityPrivate->pScrn_1;
-               pI8302 = I830PTR(pI830->entityPrivate->pScrn_1);
-            }
-
-            if (pScrn2->pScreen == pCursorScreen)
-               miPointerPosition(&x, &y);
-
-            pI8302->currentMode = NULL;
-            I830BIOSSwitchMode(pScrn2->pScreen->myNum, pScrn2->currentMode, 0);
-            i830AdjustFrame(pScrn2->pScreen->myNum, pScrn2->frameX0, pScrn2->frameY0, 0);
-
- 	    (*pScrn2->EnableDisableFBAccess) (pScrn2->pScreen->myNum, FALSE);
- 	    (*pScrn2->EnableDisableFBAccess) (pScrn2->pScreen->myNum, TRUE);
-
-            if (pScrn2->pScreen == pCursorScreen) {
-               int sigstate = xf86BlockSIGIO ();
-               miPointerWarpCursor(pScrn2->pScreen,x,y);
-
-               /* xf86Info.currentScreen = pScrn->pScreen; */
-               xf86UnblockSIGIO (sigstate);
-               if (pI8302->CursorInfoRec && !pI8302->SWCursor && pI8302->cursorOn) {
-                  pI8302->CursorInfoRec->HideCursor(pScrn);
-	          xf86SetCursor(pScrn2->pScreen, pI830->pCurs, x, y);
-                  pI8302->CursorInfoRec->ShowCursor(pScrn);
-                  pI8302->cursorOn = TRUE;
-               }
-            }
-	 }
-
- 	 (*pScrn->EnableDisableFBAccess) (pScrn->pScreen->myNum, FALSE);
- 	 (*pScrn->EnableDisableFBAccess) (pScrn->pScreen->myNum, TRUE);
+   /* Check for a hotkey press report from the BIOS. */
+   gr18 = pI830->readControl(pI830, GRX, 0x18);
+   if ((gr18 & (HOTKEY_TOGGLE | HOTKEY_SWITCH)) != 0) {
+      /* The user has pressed the hotkey requesting a toggle or switch.
+       * Re-probe our connected displays and turn on whatever we find.
+       *
+       * In the future, we want the hotkey to dump down to a user app which
+       * implements a sensible policy using RandR-1.2.  For now, all we get
+       * is this.
+       */
+      I830ValidateXF86ModeList(pScrn, FALSE);
+      xf86SwitchMode(pScrn->pScreen, pScrn->currentMode);
 
-         if (pScrn->pScreen == pCursorScreen) {
-            int sigstate = xf86BlockSIGIO ();
-            miPointerWarpCursor(pScrn->pScreen,x,y);
-
-            /* xf86Info.currentScreen = pScrn->pScreen; */
-            xf86UnblockSIGIO (sigstate);
-            if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn) {
-               pI830->CursorInfoRec->HideCursor(pScrn);
-	       xf86SetCursor(pScrn->pScreen, pI830->pCurs, x, y);
-               pI830->CursorInfoRec->ShowCursor(pScrn);
-               pI830->cursorOn = TRUE;
-            }
-         }
-      }
+      /* Clear the BIOS's hotkey press flags */
+      gr18 &= ~(HOTKEY_TOGGLE | HOTKEY_SWITCH);
+      pI830->writeControl(pI830, GRX, 0x18, gr18);
    }
 
-  
    return 1000;
 }
 
diff-tree f272f0d811f9ee059e8f8617a516e6c8bff917a1 (from parents)
Merge: ff202f8e2ae4117b464c94047001023d5d0531cc b3ddcf3348365873aed4a2b8b2750b330fb4cf26
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Mon Sep 25 14:15:21 2006 +0800

    Merge branch 'master' into exa

diff --cc src/Makefile.am
index e58350c,ce7b40e..163cc3f
@@@ -64,12 -65,15 +65,19 @@@
  	 i915_3d.c \
  	 i915_3d.h \
  	 i915_reg.h \
 -	 i915_video.c
 +	 i915_video.c \
 +	 i830_exa.c \
 +	 i830_xaa.c \
 +	 i830_exa_render.c \
 +	 i915_exa_render.c
  
+ if HAVE_GEN4ASM
+ sf_prog.h: packed_yuv_sf.g4a
+ 	intel-gen4asm -o sf_prog.h packed_yuv_sf.g4a
+ wm_prog.h: packed_yuv_wm.g4a
+ 	intel-gen4asm -o wm_prog.h packed_yuv_wm.g4a
+ endif
+ 
  if DRI
  i810_drv_la_SOURCES += \
           i810_dri.c \
diff-tree 4bd3b89c73b6c5aa9b0eb553ad5d553ee0e8a489 (from c34490bbda6604a21809d15c798607806fa6c725)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Sat Sep 23 16:41:38 2006 +0100

    Oops, duplicated CRT-redetect code.

diff --git a/src/i830_randr.c b/src/i830_randr.c
index d86911c..d973173 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -776,12 +776,6 @@ I830RandRGetInfo12 (ScreenPtr pScreen, R
     I830Ptr		pI830 = I830PTR(pScrn);
     int			found_crt;
 
-    /* Re-probe the outputs for new monitors or modes */
-    pI830->operatingDevices = pI830->operatingDevices & ~PIPE_CRT;
-    found_crt = i830DetectCRT(pScrn, FALSE);
-    if (found_crt)
-        pI830->operatingDevices = pI830->operatingDevices | PIPE_CRT;
-
     I830ValidateXF86ModeList(pScrn, FALSE);
     return I830RandRSetInfo12 (pScreen);
 }
diff-tree c34490bbda6604a21809d15c798607806fa6c725 (from 4820caf46e050761d9b347b8a440381e1b1f4727)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Sat Sep 23 12:00:43 2006 +0100

    Construct default monitor description for hotplug non-DDC monitor.
    
    When detecting a monitor that doesn't support DDC, construct a default
    monitor with "sensible" values instead of using whatever the builtin LCD
    screen uses. Clearly we need a way to set the monitor parameters when we
    cannot detect them.

diff --git a/src/i830_display.c b/src/i830_display.c
index 24ce50f..88280bb 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -1081,7 +1081,7 @@ i830DetectCRT(ScrnInfoPtr pScrn, Bool al
      * pipe, as it seems having other outputs on that pipe will result in a
      * false positive.
      */
-    if (0 && (allow_disturb || !(INREG(ADPA) & !ADPA_DAC_ENABLE))) {
+    if (1 && (allow_disturb || !(INREG(ADPA) & !ADPA_DAC_ENABLE))) {
 	return i830LoadDetectCRT(pScrn);
     }
 
diff --git a/src/i830_modes.c b/src/i830_modes.c
index 3b70d5d..3d2b8f3 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -685,6 +685,36 @@ i830GetConfiguredMonitor(ScrnInfoPtr pSc
     return mon;
 }
 
+static MonPtr
+i830GetDefaultMonitor(ScrnInfoPtr pScrn)
+{
+    MonPtr mon;
+
+    mon = xnfcalloc(1, sizeof(*mon));
+
+    mon->id = xnfstrdup("Unknown Id");
+    mon->vendor = xnfstrdup("Unknown Vendor");
+    mon->model = xnfstrdup("Unknown Model");
+
+    mon->nHsync = 1;
+    mon->hsync[0].lo = 31.0;
+    mon->hsync[0].hi = 100.0;
+    mon->nVrefresh = 1;
+    mon->vrefresh[0].lo = 50.0;
+    mon->vrefresh[0].hi = 70.0;
+    mon->widthmm = 400;
+    mon->heightmm = 300;
+    /* Use VESA standard and user modelines, and do additional validation
+     * on them beyond what pipe config will do (x/y/pitch, clocks, flags)
+     */
+    mon->Modes = i830DuplicateModes(pScrn, pScrn->monitor->Modes);
+    i830xf86ValidateModesSync(pScrn, mon->Modes, mon);
+    i830xf86PruneInvalidModes(pScrn, &mon->Modes, TRUE);
+    mon->Last = i830GetModeListTail(mon->Modes);
+
+    return mon;
+}
+
 static void
 i830FreeMonitor(ScrnInfoPtr pScrn, MonPtr mon)
 {
@@ -771,8 +801,12 @@ I830ReprobePipeModeList(ScrnInfoPtr pScr
 	     * know if a monitor is attached, and this detect process should be
 	     * infrequent.
 	     */
-	    if (i830DetectCRT(pScrn, TRUE))
-		pI830->pipeMon[pipe] = i830GetConfiguredMonitor(pScrn);
+	    if (i830DetectCRT(pScrn, TRUE)) {
+/*		if (pipe == pI830->pipe)
+		    pI830->pipeMon[pipe] = i830GetConfiguredMonitor(pScrn);
+		else */
+		    pI830->pipeMon[pipe] = i830GetDefaultMonitor(pScrn);
+	    }
 	    break;
 	default:
 	    pI830->pipeMon[pipe] = i830GetConfiguredMonitor(pScrn);
diff --git a/src/i830_randr.c b/src/i830_randr.c
index 7c67aea..d86911c 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -773,7 +773,15 @@ static Bool
 I830RandRGetInfo12 (ScreenPtr pScreen, Rotation *rotations)
 {
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+    I830Ptr		pI830 = I830PTR(pScrn);
+    int			found_crt;
+
     /* Re-probe the outputs for new monitors or modes */
+    pI830->operatingDevices = pI830->operatingDevices & ~PIPE_CRT;
+    found_crt = i830DetectCRT(pScrn, FALSE);
+    if (found_crt)
+        pI830->operatingDevices = pI830->operatingDevices | PIPE_CRT;
+
     I830ValidateXF86ModeList(pScrn, FALSE);
     return I830RandRSetInfo12 (pScreen);
 }
diff-tree 965609f6fa63e28e5a28128f5bc44f8c4d7b9f68 (from c52242c22779a51aa12b18a7a589080ce44c8484)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Sep 22 09:51:45 2006 -0700

    Restructure i830_bios.c so we don't leak a copy of the BIOS per generation.

diff --git a/src/i830.h b/src/i830.h
index 53302ee..92c9111 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -442,8 +442,6 @@ typedef struct _I830Rec {
    
    Bool panel_wants_dither;
 
-   unsigned char *VBIOS;
-
    CARD32 saveDSPACNTR;
    CARD32 saveDSPBCNTR;
    CARD32 savePIPEACONF;
diff --git a/src/i830_bios.c b/src/i830_bios.c
index 14e354e..07dd67d 100644
--- a/src/i830_bios.c
+++ b/src/i830_bios.c
@@ -38,21 +38,20 @@
 #include "i830_bios.h"
 #include "edid.h"
 
-#define INTEL_BIOS_8(_addr)	(pI830->VBIOS[_addr])
-#define INTEL_BIOS_16(_addr)	(pI830->VBIOS[_addr] | \
-				 (pI830->VBIOS[_addr + 1] << 8))
-#define INTEL_BIOS_32(_addr)	(pI830->VBIOS[_addr] | \
-				 (pI830->VBIOS[_addr + 1] << 8) \
-				 (pI830->VBIOS[_addr + 2] << 16) \
-				 (pI830->VBIOS[_addr + 3] << 24))
+#define INTEL_BIOS_8(_addr)	(bios[_addr])
+#define INTEL_BIOS_16(_addr)	(bios[_addr] | \
+				 (bios[_addr + 1] << 8))
+#define INTEL_BIOS_32(_addr)	(bios[_addr] | \
+				 (bios[_addr + 1] << 8) \
+				 (bios[_addr + 2] << 16) \
+				 (bios[_addr + 3] << 24))
 
 /* XXX */
 #define INTEL_VBIOS_SIZE (64 * 1024)
 
 static void
-i830DumpBIOSToFile(ScrnInfoPtr pScrn)
+i830DumpBIOSToFile(ScrnInfoPtr pScrn, unsigned char *bios)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
     const char *filename = "/tmp/xf86-video-intel-VBIOS";
     FILE *f;
 
@@ -61,7 +60,7 @@ i830DumpBIOSToFile(ScrnInfoPtr pScrn)
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Couldn't open %s\n", filename);
 	return;
     }
-    if (fwrite(pI830->VBIOS, INTEL_VBIOS_SIZE, 1, f) != 1) {
+    if (fwrite(bios, INTEL_VBIOS_SIZE, 1, f) != 1) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Couldn't write BIOS data\n");
     }
 
@@ -78,48 +77,46 @@ i830DumpBIOSToFile(ScrnInfoPtr pScrn)
  * feed an updated VBT back through that, compared to what we'll fetch using
  * this method of groping around in the BIOS data.
  */
-static Bool
+static unsigned char *
 i830GetBIOS(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     struct vbt_header *vbt;
     int vbt_off;
+    unsigned char *bios;
 
-    if (pI830->VBIOS != NULL)
-	return TRUE;
-
-    pI830->VBIOS = xalloc(INTEL_VBIOS_SIZE);
-    if (pI830->VBIOS == NULL)
-	return FALSE;
+    bios = xalloc(INTEL_VBIOS_SIZE);
+    if (bios == NULL)
+	return NULL;
 
     if (pI830->pVbe != NULL) {
-	memcpy(pI830->VBIOS, xf86int10Addr(pI830->pVbe->pInt10,
+	memcpy(bios, xf86int10Addr(pI830->pVbe->pInt10,
 					   pI830->pVbe->pInt10->BIOSseg << 4),
 	       INTEL_VBIOS_SIZE);
     } else {
-	xf86ReadPciBIOS(0, pI830->PciTag, 0, pI830->VBIOS, INTEL_VBIOS_SIZE);
+	xf86ReadPciBIOS(0, pI830->PciTag, 0, bios, INTEL_VBIOS_SIZE);
     }
 
     if (0)
-	i830DumpBIOSToFile(pScrn);
+	i830DumpBIOSToFile(pScrn, bios);
 
     vbt_off = INTEL_BIOS_16(0x1a);
     if (vbt_off >= INTEL_VBIOS_SIZE) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Bad VBT offset: 0x%x\n",
 		   vbt_off);
-	xfree(pI830->VBIOS);
-	return FALSE;
+	xfree(bios);
+	return NULL;
     }
 
-    vbt = (struct vbt_header *)(pI830->VBIOS + vbt_off);
+    vbt = (struct vbt_header *)(bios + vbt_off);
 
     if (memcmp(vbt->signature, "$VBT", 4) != 0) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Bad VBT signature\n");
-	xfree(pI830->VBIOS);
-	return FALSE;
+	xfree(bios);
+	return NULL;
     }
 
-    return TRUE;
+    return bios;
 }
 
 Bool
@@ -130,18 +127,22 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScr
     struct bdb_header *bdb;
     int vbt_off, bdb_off, bdb_block_off, block_size;
     int panel_type = -1;
+    unsigned char *bios;
     Bool found_panel_info = FALSE;
 
-    if (!i830GetBIOS(pScrn))
+    bios = i830GetBIOS(pScrn);
+
+    if (bios == NULL)
 	return FALSE;
 
     vbt_off = INTEL_BIOS_16(0x1a);
-    vbt = (struct vbt_header *)(pI830->VBIOS + vbt_off);
+    vbt = (struct vbt_header *)(bios + vbt_off);
     bdb_off = vbt_off + vbt->bdb_offset;
-    bdb = (struct bdb_header *)(pI830->VBIOS + bdb_off);
+    bdb = (struct bdb_header *)(bios + bdb_off);
 
     if (memcmp(bdb->signature, "BIOS_DATA_BLOCK ", 16) != 0) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Bad BDB signature\n");
+	xfree(bios);
 	return FALSE;
     }
 
@@ -161,7 +162,7 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScr
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found BDB block type %d\n", id);
 	switch (id) {
 	case 40:
-	    lvds1 = (struct lvds_bdb_1 *)(pI830->VBIOS + start);
+	    lvds1 = (struct lvds_bdb_1 *)(bios + start);
 	    panel_type = lvds1->panel_type;
 	    if (lvds1->caps & LVDS_CAP_DITHER)
 		pI830->panel_wants_dither = TRUE;
@@ -170,23 +171,23 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScr
 	    if (panel_type == -1)
 		break;
 
-	    lvds2 = (struct lvds_bdb_2 *)(pI830->VBIOS + start);
-	    fpparam = (struct lvds_bdb_2_fp_params *)(pI830->VBIOS +
+	    lvds2 = (struct lvds_bdb_2 *)(bios + start);
+	    fpparam = (struct lvds_bdb_2_fp_params *)(bios +
 		bdb_off + lvds2->panels[panel_type].fp_params_offset);
-	    fptiming = (struct lvds_bdb_2_fp_edid_dtd *)(pI830->VBIOS +
+	    fptiming = (struct lvds_bdb_2_fp_edid_dtd *)(bios +
 		bdb_off + lvds2->panels[panel_type].fp_edid_dtd_offset);
-	    timing_ptr = pI830->VBIOS + bdb_off +
+	    timing_ptr = bios + bdb_off +
 	        lvds2->panels[panel_type].fp_edid_dtd_offset;
 
 	    if (fpparam->terminator != 0xffff) {
 		/* Apparently the offsets are wrong for some BIOSes, so we
 		 * try the other offsets if we find a bad terminator.
 		 */
-		fpparam = (struct lvds_bdb_2_fp_params *)(pI830->VBIOS +
+		fpparam = (struct lvds_bdb_2_fp_params *)(bios +
 		    bdb_off + lvds2->panels[panel_type].fp_params_offset + 8);
-		fptiming = (struct lvds_bdb_2_fp_edid_dtd *)(pI830->VBIOS +
+		fptiming = (struct lvds_bdb_2_fp_edid_dtd *)(bios +
 		    bdb_off + lvds2->panels[panel_type].fp_edid_dtd_offset + 8);
-		timing_ptr = pI830->VBIOS + bdb_off +
+		timing_ptr = bios + bdb_off +
 	            lvds2->panels[panel_type].fp_edid_dtd_offset + 8;
 
 		if (fpparam->terminator != 0xffff)
@@ -218,5 +219,6 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScr
 	}
     }
 
+    xfree(bios);
     return found_panel_info;
 }
diff-tree c52242c22779a51aa12b18a7a589080ce44c8484 (from c2446be9b444b16c95f78dab17bf130f9f491ee2)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Sep 22 09:41:07 2006 -0700

    Remove some dead code related to clock ranges.

diff --git a/src/i830.h b/src/i830.h
index 9fc6712..53302ee 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -418,7 +418,6 @@ typedef struct _I830Rec {
    unsigned int SaveGeneration;
 
    OsTimerPtr devicesTimer;
-   int MaxClock;
 
    int ddc2;
    int num_outputs;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index fd3bf2e..31e3b17 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2161,8 +2161,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
 	      "Maximum space available for video modes: %d kByte\n", memsize);
 
-     pI830->MaxClock = 300000;
-
    n = I830ValidateXF86ModeList(pScrn, TRUE);
    if (n <= 0) {
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
diff --git a/src/i830_modes.c b/src/i830_modes.c
index 6bff1d0..f1cdbe1 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -1025,20 +1025,6 @@ I830ValidateXF86ModeList(ScrnInfoPtr pSc
     last->next = pScrn->modes;
     pScrn->modes->prev = last;
 
-#if 0
-    /* XXX: do I need this any more?  Maybe XF86VidMode uses it?
-     * Set up the ClockRanges, which describe what clock ranges are available,
-     * and what sort of modes they can be used for.
-     */
-    clockRanges = xnfcalloc(sizeof(ClockRange), 1);
-    clockRanges->next = NULL;
-    clockRanges->minClock = 25000;
-    clockRanges->maxClock = pI830->MaxClock;
-    clockRanges->clockIndex = -1;		/* programmable */
-    clockRanges->interlaceAllowed = TRUE;	/* XXX check this */
-    clockRanges->doubleScanAllowed = FALSE;	/* XXX check this */
-#endif
-
 #if DEBUG_REPROBE
     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Modes post revalidate\n");
     do {
diff-tree c2446be9b444b16c95f78dab17bf130f9f491ee2 (from b6ba268d0d5f22c6a18ce45416452fce83438620)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Sep 22 09:38:11 2006 -0700

    Remove the GetDevicePresence BIOS call which just printed BIOS information.
    
    Because we aren't using the BIOS to set modes any more, what the BIOS thinks is
    present is probably even less important than before.

diff --git a/man/i810.man b/man/i810.man
index 3aaa165..59766a6 100644
--- a/man/i810.man
+++ b/man/i810.man
@@ -172,13 +172,6 @@ NOTE: Using this option may cause text m
 and thus should be used with caution.
 Default: disabled.
 .TP
-.BI "Option \*qDevicePresence\*q \*q" boolean \*q
-Tell the driver to perform an active detect of the currently connected
-monitors. This option is useful if the monitor was not connected when
-the machine has booted, but unfortunately it doesn't always work and
-is extremely dependent upon the Video BIOS.
-Default: disabled
-.TP
 .BI "Option \*qRotate\*q \*q90\*q"
 Rotate the desktop 90 degrees counterclockwise. Other valid options are
 0, 90, 180 and 270 degrees. The RandR extension is used for rotation 
diff --git a/src/i830.h b/src/i830.h
index 35e0391..9fc6712 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -416,7 +416,6 @@ typedef struct _I830Rec {
    int yoffset;
 
    unsigned int SaveGeneration;
-   Bool devicePresence;
 
    OsTimerPtr devicesTimer;
    int MaxClock;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 5e0cff6..fd3bf2e 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -260,7 +260,6 @@ static OptionInfoRec I830Options[] = {
    {OPTION_XVIDEO,	"XVideo",	OPTV_BOOLEAN,	{0},	TRUE},
    {OPTION_COLOR_KEY,	"ColorKey",	OPTV_INTEGER,	{0},	FALSE},
    {OPTION_VIDEO_KEY,	"VideoKey",	OPTV_INTEGER,	{0},	FALSE},
-   {OPTION_DEVICE_PRESENCE,"DevicePresence",OPTV_BOOLEAN,{0},	FALSE},
    {OPTION_MONITOR_LAYOUT, "MonitorLayout", OPTV_ANYSTR,{0},	FALSE},
    {OPTION_CLONE,	"Clone",	OPTV_BOOLEAN,	{0},	FALSE},
    {OPTION_CLONE_REFRESH,"CloneRefresh",OPTV_INTEGER,	{0},	FALSE},
@@ -623,31 +622,6 @@ GetBIOSVersion(ScrnInfoPtr pScrn, unsign
    return FALSE;
 }
 
-static Bool
-GetDevicePresence(ScrnInfoPtr pScrn, Bool *required, int *attached,
-		  int *encoderPresent)
-{
-   vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
-
-   DPRINTF(PFX, "GetDevicePresence\n");
-
-   pVbe->pInt10->num = 0x10;
-   pVbe->pInt10->ax = 0x5f64;
-   pVbe->pInt10->bx = 0x200;
-
-   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
-   if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) {
-      if (required)
-	 *required = ((pVbe->pInt10->bx & 0x1) == 0);
-      if (attached)
-	 *attached = (pVbe->pInt10->cx >> 8) & 0xff;
-      if (encoderPresent)
-	 *encoderPresent = pVbe->pInt10->cx & 0xff;
-      return TRUE;
-   } else
-      return FALSE;
-}
-
 /*
  * Returns a string matching the device corresponding to the first bit set
  * in "device".  savedDevice is then set to device with that bit cleared.
@@ -2071,30 +2045,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    } else
       pI830->newPipeSwitch = FALSE;
 
-   pI830->devicePresence = FALSE;
-   from = X_DEFAULT;
-   if (xf86ReturnOptValBool(pI830->Options, OPTION_DEVICE_PRESENCE, FALSE)) {
-      pI830->devicePresence = TRUE;
-      from = X_CONFIG;
-   }
-   xf86DrvMsg(pScrn->scrnIndex, from, "Device Presence: %s.\n",
-	      pI830->devicePresence ? "enabled" : "disabled");
-
-   /* This performs an active detect of the currently attached monitors
-    * or, at least it's meant to..... alas it doesn't seem to always work.
-    */
-   if (pI830->devicePresence) {
-      int req=0, att=0, enc=0;
-      GetDevicePresence(pScrn, &req, &att, &enc);
-      for (i = 0; i < NumDisplayTypes; i++) {
-         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-	    "Display Presence: %s: attached: %s, encoder: %s\n",
-	    displayDevices[i],
-	    BOOLTOSTRING(((1<<i) & att)>>i),
-	    BOOLTOSTRING(((1<<i) & enc)>>i));
-      }
-   }
-
    PrintDisplayDeviceInfo(pScrn);
 
    if (xf86IsEntityShared(pScrn->entityList[0])) {
diff-tree b6ba268d0d5f22c6a18ce45416452fce83438620 (from 20956a5d6f1eb518717a680e58938f31461ca5e4)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Sep 22 09:31:37 2006 -0700

    Remove the no-longer-connected VBERestore option.

diff --git a/man/i810.man b/man/i810.man
index f6b7368..3aaa165 100644
--- a/man/i810.man
+++ b/man/i810.man
@@ -117,13 +117,6 @@ The following driver
 .B Options
 are supported for the 830M and later chipsets:
 .TP
-.BI "Option \*qVBERestore\*q \*q" boolean \*q
-Enable or disable the use of VBE save/restore for saving and restoring
-the initial text mode.  This is disabled by default because it causes
-lockups on some platforms.  However, there are some cases where it must
-enabled for the correct restoration of the initial video mode.  If you are
-having a problem with that, try enabling this option.  Default: Disabled.
-.TP
 .BI "Option \*qVideoKey\*q \*q" integer \*q
 This is the same as the
 .B \*qColorKey\*q
diff --git a/src/i830.h b/src/i830.h
index 3460c70..35e0391 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -416,7 +416,6 @@ typedef struct _I830Rec {
    int yoffset;
 
    unsigned int SaveGeneration;
-   Bool vbeRestoreWorkaround;
    Bool devicePresence;
 
    OsTimerPtr devicesTimer;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 6000300..5e0cff6 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -260,7 +260,6 @@ static OptionInfoRec I830Options[] = {
    {OPTION_XVIDEO,	"XVideo",	OPTV_BOOLEAN,	{0},	TRUE},
    {OPTION_COLOR_KEY,	"ColorKey",	OPTV_INTEGER,	{0},	FALSE},
    {OPTION_VIDEO_KEY,	"VideoKey",	OPTV_INTEGER,	{0},	FALSE},
-   {OPTION_VBE_RESTORE,	"VBERestore",	OPTV_BOOLEAN,	{0},	FALSE},
    {OPTION_DEVICE_PRESENCE,"DevicePresence",OPTV_BOOLEAN,{0},	FALSE},
    {OPTION_MONITOR_LAYOUT, "MonitorLayout", OPTV_ANYSTR,{0},	FALSE},
    {OPTION_CLONE,	"Clone",	OPTV_BOOLEAN,	{0},	FALSE},
@@ -2426,16 +2425,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    pI830->pVbe = NULL;
 #endif
 
-   /* Use the VBE mode restore workaround by default. */
-   pI830->vbeRestoreWorkaround = TRUE;
-   from = X_DEFAULT;
-   if (xf86ReturnOptValBool(pI830->Options, OPTION_VBE_RESTORE, FALSE)) {
-      pI830->vbeRestoreWorkaround = FALSE;
-      from = X_CONFIG;
-   }
-   xf86DrvMsg(pScrn->scrnIndex, from, "VBE Restore workaround: %s.\n",
-	      pI830->vbeRestoreWorkaround ? "enabled" : "disabled");
-      
 #if defined(XF86DRI)
    /* Load the dri module if requested. */
    if (xf86ReturnOptValBool(pI830->Options, OPTION_DRI, FALSE) &&
diff-tree 20956a5d6f1eb518717a680e58938f31461ca5e4 (from 2cd28be71472d67956f47c7d49283ebabefa089a)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Sep 22 09:27:30 2006 -0700

    Remove unused display{Attached,Present} fields.

diff --git a/src/i830.h b/src/i830.h
index 9f65f88..3460c70 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -397,10 +397,6 @@ typedef struct _I830Rec {
    int toggleDevices;
    int lastDevice0, lastDevice1, lastDevice2;
 
-   /* These are indexed by the display types */
-   Bool displayAttached[NumDisplayTypes];
-   Bool displayPresent[NumDisplayTypes];
-
    /* [0] is Pipe A, [1] is Pipe B. */
    int availablePipes;
    /* [0] is display plane A, [1] is display plane B. */
diff-tree 2cd28be71472d67956f47c7d49283ebabefa089a (from d87d1f5bb0475c6f651fcb7e2cab2a7d46edcc69)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Sep 22 08:55:55 2006 -0700

    Remove empty SAVERESTORE_HWSTATE code.

diff --git a/src/i830.h b/src/i830.h
index 57d6506..9f65f88 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -337,7 +337,6 @@ typedef struct _I830Rec {
    int NumScanlineColorExpandBuffers;
    int nextColorExpandBuf;
 
-   I830RegRec SavedReg;
    I830RegRec ModeReg;
 
    Bool noAccel;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index d21bf9f..6000300 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3512,9 +3512,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    if (!vgaHWMapMem(pScrn))
       return FALSE;
 
-   /* Clear SavedReg */
-   memset(&pI830->SavedReg, 0, sizeof(pI830->SavedReg));
-
    DPRINTF(PFX, "assert( if(!I830EnterVT(scrnIndex, 0)) )\n");
 
    if (!I830EnterVT(scrnIndex, 0))
@@ -3692,34 +3689,6 @@ I830FreeScreen(int scrnIndex, int flags)
       vgaHWFreeHWRec(xf86Screens[scrnIndex]);
 }
 
-#ifndef SAVERESTORE_HWSTATE
-#define SAVERESTORE_HWSTATE 0
-#endif
-
-#if SAVERESTORE_HWSTATE
-static void
-SaveHWOperatingState(ScrnInfoPtr pScrn)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   I830RegPtr save = &pI830->SavedReg;
-
-   DPRINTF(PFX, "SaveHWOperatingState\n");
-
-   return;
-}
-
-static void
-RestoreHWOperatingState(ScrnInfoPtr pScrn)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   I830RegPtr save = &pI830->SavedReg;
-
-   DPRINTF(PFX, "RestoreHWOperatingState\n");
-
-   return;
-}
-#endif
-
 static void
 I830LeaveVT(int scrnIndex, int flags)
 {
@@ -3760,11 +3729,6 @@ I830LeaveVT(int scrnIndex, int flags)
    }
 #endif
 
-#if SAVERESTORE_HWSTATE
-   if (!pI830->closing)
-      SaveHWOperatingState(pScrn);
-#endif
-
    if (pI830->CursorInfoRec && pI830->CursorInfoRec->HideCursor)
       pI830->CursorInfoRec->HideCursor(pScrn);
 
@@ -3982,10 +3946,6 @@ I830EnterVT(int scrnIndex, int flags)
 
    pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
 
-#if SAVERESTORE_HWSTATE
-   RestoreHWOperatingState(pScrn);
-#endif
-
 #ifdef XF86DRI
    if (pI830->directRenderingEnabled) {
       if (!pI830->starting) {
diff-tree ff202f8e2ae4117b464c94047001023d5d0531cc (from 1681fe6bb041385e5aefb11baa9afd1f614abc5b)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Fri Sep 22 15:02:19 2006 +0800

    Fix a typo to mark sync for XAA.
    
    This should fix the scrolling screen corrupt in
    XAA method.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 10a329c..4d9de0c 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -8900,7 +8900,7 @@ i830MarkSync(ScrnInfoPtr pScrn)
 
 #ifdef I830_USE_XAA
    if (!pI830->useEXA && pI830->AccelInfoRec)
-      pI830->AccelInfoRec->NeedToSync = FALSE;
+      pI830->AccelInfoRec->NeedToSync = TRUE;
 #endif
 #ifdef I830_USE_EXA
    if (pI830->useEXA && pI830->EXADriverPtr) {
diff-tree d87d1f5bb0475c6f651fcb7e2cab2a7d46edcc69 (from daade50ca271d1cdf236bbe84afade85d4111ac9)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Fri Sep 22 02:20:35 2006 +0100

    Remove BIOS from non-BIOS related names.
    
    Lots of names included BIOS for no apparent reason; as we try to eliminate
    BIOS calls from the driver, these only serve to confuse us.
    (cherry picked from 8e5d280d94ad3d3ba3c75871c17abec9da62ed34 commit)

diff --git a/src/common.h b/src/common.h
index 21977af..6a55bfd 100644
--- a/src/common.h
+++ b/src/common.h
@@ -68,7 +68,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #endif
 
 /* I830 hooks for the I810 driver setup/probe. */
-extern const OptionInfoRec *I830BIOSAvailableOptions(int chipid, int busid);
+extern const OptionInfoRec *I830AvailableOptions(int chipid, int busid);
 extern void I830InitpScrn(ScrnInfoPtr pScrn);
 
 /* Symbol lists shared by the i810 and i830 parts. */
diff --git a/src/i810_driver.c b/src/i810_driver.c
index b87601e..c8cb607 100644
--- a/src/i810_driver.c
+++ b/src/i810_driver.c
@@ -477,11 +477,11 @@ I810AvailableOptions(int chipid, int bus
 #ifndef I830_ONLY
    const OptionInfoRec *pOptions;
 
-   if ((pOptions = I830BIOSAvailableOptions(chipid, busid)))
+   if ((pOptions = I830AvailableOptions(chipid, busid)))
       return pOptions;
    return I810Options;
 #else
-   return I830BIOSAvailableOptions(chipid, busid);
+   return I830AvailableOptions(chipid, busid);
 #endif
 }
 
diff --git a/src/i830.h b/src/i830.h
index 3a93931..57d6506 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -72,7 +72,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "i830_sdvo.h"
 #include "i2c_vid.h"
 
-/* I830 Video BIOS support */
+/* I830 Video support */
 
 /*
  * The mode handling is based upon the VESA driver written by
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 75ea480..d21bf9f 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -198,7 +198,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define NB_OF(x) (sizeof (x) / sizeof (*x))
 
 /* *INDENT-OFF* */
-static SymTabRec I830BIOSChipsets[] = {
+static SymTabRec I830Chipsets[] = {
    {PCI_CHIP_I830_M,		"i830"},
    {PCI_CHIP_845_G,		"845G"},
    {PCI_CHIP_I855_GM,		"852GM/855GM"},
@@ -211,7 +211,7 @@ static SymTabRec I830BIOSChipsets[] = {
    {-1,				NULL}
 };
 
-static PciChipsets I830BIOSPciChipsets[] = {
+static PciChipsets I830PciChipsets[] = {
    {PCI_CHIP_I830_M,		PCI_CHIP_I830_M,	RES_SHARED_VGA},
    {PCI_CHIP_845_G,		PCI_CHIP_845_G,		RES_SHARED_VGA},
    {PCI_CHIP_I855_GM,		PCI_CHIP_I855_GM,	RES_SHARED_VGA},
@@ -251,7 +251,7 @@ typedef enum {
    OPTION_LINEARALLOC
 } I830Opts;
 
-static OptionInfoRec I830BIOSOptions[] = {
+static OptionInfoRec I830Options[] = {
    {OPTION_NOACCEL,	"NoAccel",	OPTV_BOOLEAN,	{0},	FALSE},
    {OPTION_SW_CURSOR,	"SWcursor",	OPTV_BOOLEAN,	{0},	FALSE},
    {OPTION_CACHE_LINES,	"CacheLines",	OPTV_INTEGER,	{0},	FALSE},
@@ -285,9 +285,9 @@ static const char *output_type_names[] =
 static void I830DisplayPowerManagementSet(ScrnInfoPtr pScrn,
 					  int PowerManagementMode, int flags);
 static void i830AdjustFrame(int scrnIndex, int x, int y, int flags);
-static Bool I830BIOSCloseScreen(int scrnIndex, ScreenPtr pScreen);
-static Bool I830BIOSSaveScreen(ScreenPtr pScreen, int unblack);
-static Bool I830BIOSEnterVT(int scrnIndex, int flags);
+static Bool I830CloseScreen(int scrnIndex, ScreenPtr pScreen);
+static Bool I830SaveScreen(ScreenPtr pScreen, int unblack);
+static Bool I830EnterVT(int scrnIndex, int flags);
 #if 0
 static Bool I830VESASetVBEMode(ScrnInfoPtr pScrn, int mode,
 			       VbeCRTCInfoBlock *block);
@@ -325,21 +325,21 @@ I830DPRINTF_stub(const char *filename, i
 }
 #endif /* #ifdef I830DEBUG */
 
-/* XXX Check if this is still needed. */
+/* Export I830 options to i830 driver where necessary */
 const OptionInfoRec *
-I830BIOSAvailableOptions(int chipid, int busid)
+I830AvailableOptions(int chipid, int busid)
 {
    int i;
 
-   for (i = 0; I830BIOSPciChipsets[i].PCIid > 0; i++) {
-      if (chipid == I830BIOSPciChipsets[i].PCIid)
-	 return I830BIOSOptions;
+   for (i = 0; I830PciChipsets[i].PCIid > 0; i++) {
+      if (chipid == I830PciChipsets[i].PCIid)
+	 return I830Options;
    }
    return NULL;
 }
 
 static Bool
-I830BIOSGetRec(ScrnInfoPtr pScrn)
+I830GetRec(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830;
 
@@ -351,7 +351,7 @@ I830BIOSGetRec(ScrnInfoPtr pScrn)
 }
 
 static void
-I830BIOSFreeRec(ScrnInfoPtr pScrn)
+I830FreeRec(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830;
    VESAPtr pVesa;
@@ -398,7 +398,7 @@ I830BIOSFreeRec(ScrnInfoPtr pScrn)
 }
 
 static void
-I830BIOSProbeDDC(ScrnInfoPtr pScrn, int index)
+I830ProbeDDC(ScrnInfoPtr pScrn, int index)
 {
    vbeInfoPtr pVbe;
 
@@ -1201,7 +1201,7 @@ PreInitCleanup(ScrnInfoPtr pScrn)
    }
    if (pI830->MMIOBase)
       I830UnmapMMIO(pScrn);
-   I830BIOSFreeRec(pScrn);
+   I830FreeRec(pScrn);
 }
 
 Bool
@@ -1218,7 +1218,7 @@ I830IsPrimary(ScrnInfoPtr pScrn)
 }
 
 static Bool
-I830BIOSPreInit(ScrnInfoPtr pScrn, int flags)
+I830PreInit(ScrnInfoPtr pScrn, int flags)
 {
    vgaHWPtr hwp;
    I830Ptr pI830;
@@ -1252,7 +1252,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
    pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
 
    if (flags & PROBE_DETECT) {
-      I830BIOSProbeDDC(pScrn, pEnt->index);
+      I830ProbeDDC(pScrn, pEnt->index);
       return TRUE;
    }
 
@@ -1266,7 +1266,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
       return FALSE;
 
    /* Allocate driverPrivate */
-   if (!I830BIOSGetRec(pScrn))
+   if (!I830GetRec(pScrn))
       return FALSE;
 
    pI830 = I830PTR(pScrn);
@@ -1355,9 +1355,9 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
 
    /* Process the options */
    xf86CollectOptions(pScrn, NULL);
-   if (!(pI830->Options = xalloc(sizeof(I830BIOSOptions))))
+   if (!(pI830->Options = xalloc(sizeof(I830Options))))
       return FALSE;
-   memcpy(pI830->Options, I830BIOSOptions, sizeof(I830BIOSOptions));
+   memcpy(pI830->Options, I830Options, sizeof(I830Options));
    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pI830->Options);
 
    /* We have to use PIO to probe, because we haven't mapped yet. */
@@ -1446,14 +1446,14 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
       pScrn->chipset = pI830->pEnt->device->chipset;
       from = X_CONFIG;
    } else if (pI830->pEnt->device->chipID >= 0) {
-      pScrn->chipset = (char *)xf86TokenToString(I830BIOSChipsets,
+      pScrn->chipset = (char *)xf86TokenToString(I830Chipsets,
 						 pI830->pEnt->device->chipID);
       from = X_CONFIG;
       xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
 		 pI830->pEnt->device->chipID);
    } else {
       from = X_PROBED;
-      pScrn->chipset = (char *)xf86TokenToString(I830BIOSChipsets,
+      pScrn->chipset = (char *)xf86TokenToString(I830Chipsets,
 						 pI830->PciInfo->chipType);
    }
 
@@ -3238,7 +3238,7 @@ I830InitFBManager(
 }
 
 static Bool
-I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
+I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
 {
    ScrnInfoPtr pScrn;
    vgaHWPtr hwp;
@@ -3515,9 +3515,9 @@ I830BIOSScreenInit(int scrnIndex, Screen
    /* Clear SavedReg */
    memset(&pI830->SavedReg, 0, sizeof(pI830->SavedReg));
 
-   DPRINTF(PFX, "assert( if(!I830BIOSEnterVT(scrnIndex, 0)) )\n");
+   DPRINTF(PFX, "assert( if(!I830EnterVT(scrnIndex, 0)) )\n");
 
-   if (!I830BIOSEnterVT(scrnIndex, 0))
+   if (!I830EnterVT(scrnIndex, 0))
       return FALSE;
 
    DPRINTF(PFX, "assert( if(!fbScreenInit(pScreen, ...) )\n");
@@ -3628,9 +3628,9 @@ I830BIOSScreenInit(int scrnIndex, Screen
    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering: Not available\n");
 #endif
 
-   pScreen->SaveScreen = I830BIOSSaveScreen;
+   pScreen->SaveScreen = I830SaveScreen;
    pI830->CloseScreen = pScreen->CloseScreen;
-   pScreen->CloseScreen = I830BIOSCloseScreen;
+   pScreen->CloseScreen = I830CloseScreen;
 
    if (pI830->shadowReq.minorversion >= 1) {
       /* Rotation */
@@ -3685,9 +3685,9 @@ i830AdjustFrame(int scrnIndex, int x, in
 }
 
 static void
-I830BIOSFreeScreen(int scrnIndex, int flags)
+I830FreeScreen(int scrnIndex, int flags)
 {
-   I830BIOSFreeRec(xf86Screens[scrnIndex]);
+   I830FreeRec(xf86Screens[scrnIndex]);
    if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
       vgaHWFreeHWRec(xf86Screens[scrnIndex]);
 }
@@ -3721,7 +3721,7 @@ RestoreHWOperatingState(ScrnInfoPtr pScr
 #endif
 
 static void
-I830BIOSLeaveVT(int scrnIndex, int flags)
+I830LeaveVT(int scrnIndex, int flags)
 {
    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
    I830Ptr pI830 = I830PTR(pScrn);
@@ -3927,7 +3927,7 @@ I830DetectMonitorChange(ScrnInfoPtr pScr
  * This gets called when gaining control of the VT, and from ScreenInit().
  */
 static Bool
-I830BIOSEnterVT(int scrnIndex, int flags)
+I830EnterVT(int scrnIndex, int flags)
 {
    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
    I830Ptr pI830 = I830PTR(pScrn);
@@ -4015,7 +4015,7 @@ I830BIOSEnterVT(int scrnIndex, int flags
 }
 
 static Bool
-I830BIOSSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
+I830SwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
 {
 
    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
@@ -4023,7 +4023,7 @@ I830BIOSSwitchMode(int scrnIndex, Displa
    Bool ret = TRUE;
    PixmapPtr pspix = (*pScrn->pScreen->GetScreenPixmap) (pScrn->pScreen);
 
-   DPRINTF(PFX, "I830BIOSSwitchMode: mode == %p\n", mode);
+   DPRINTF(PFX, "I830SwitchMode: mode == %p\n", mode);
 
 #ifdef I830_XV
    /* Give the video overlay code a chance to see the new mode. */
@@ -4083,7 +4083,7 @@ I830BIOSSwitchMode(int scrnIndex, Displa
 }
 
 static Bool
-I830BIOSSaveScreen(ScreenPtr pScreen, int mode)
+I830SaveScreen(ScreenPtr pScreen, int mode)
 {
    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
    I830Ptr pI830 = I830PTR(pScrn);
@@ -4091,7 +4091,7 @@ I830BIOSSaveScreen(ScreenPtr pScreen, in
    CARD32 temp, ctrl, base;
    int i;
 
-   DPRINTF(PFX, "I830BIOSSaveScreen: %d, on is %s\n", mode, BOOLTOSTRING(on));
+   DPRINTF(PFX, "I830SaveScreen: %d, on is %s\n", mode, BOOLTOSTRING(on));
 
    if (pScrn->vtSema) {
       for (i = 0; i < pI830->availablePipes; i++) {
@@ -4215,7 +4215,7 @@ I830DisplayPowerManagementSet(ScrnInfoPt
 }
 
 static Bool
-I830BIOSCloseScreen(int scrnIndex, ScreenPtr pScreen)
+I830CloseScreen(int scrnIndex, ScreenPtr pScreen)
 {
    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
    I830Ptr pI830 = I830PTR(pScrn);
@@ -4230,7 +4230,7 @@ I830BIOSCloseScreen(int scrnIndex, Scree
 #endif
 
    if (pScrn->vtSema == TRUE) {
-      I830BIOSLeaveVT(scrnIndex, 0);
+      I830LeaveVT(scrnIndex, 0);
    }
 
    if (pI830->devicesTimer)
@@ -4668,7 +4668,7 @@ I830CheckDevicesTimer(OsTimerPtr timer, 
          } 
 
          pI830->currentMode = NULL;
-         I830BIOSSwitchMode(pScrn->pScreen->myNum, pScrn->currentMode, 0);
+         I830SwitchMode(pScrn->pScreen->myNum, pScrn->currentMode, 0);
          i830AdjustFrame(pScrn->pScreen->myNum, pScrn->frameX0, pScrn->frameY0, 0);
 
          if (xf86IsEntityShared(pScrn->entityList[0])) {
@@ -4687,7 +4687,7 @@ I830CheckDevicesTimer(OsTimerPtr timer, 
                miPointerPosition(&x, &y);
 
             pI8302->currentMode = NULL;
-            I830BIOSSwitchMode(pScrn2->pScreen->myNum, pScrn2->currentMode, 0);
+            I830SwitchMode(pScrn2->pScreen->myNum, pScrn2->currentMode, 0);
             i830AdjustFrame(pScrn2->pScreen->myNum, pScrn2->frameX0, pScrn2->frameY0, 0);
 
  	    (*pScrn2->EnableDisableFBAccess) (pScrn2->pScreen->myNum, FALSE);
@@ -4734,13 +4734,13 @@ I830CheckDevicesTimer(OsTimerPtr timer, 
 void
 I830InitpScrn(ScrnInfoPtr pScrn)
 {
-   pScrn->PreInit = I830BIOSPreInit;
-   pScrn->ScreenInit = I830BIOSScreenInit;
-   pScrn->SwitchMode = I830BIOSSwitchMode;
+   pScrn->PreInit = I830PreInit;
+   pScrn->ScreenInit = I830ScreenInit;
+   pScrn->SwitchMode = I830SwitchMode;
    pScrn->AdjustFrame = i830AdjustFrame;
-   pScrn->EnterVT = I830BIOSEnterVT;
-   pScrn->LeaveVT = I830BIOSLeaveVT;
-   pScrn->FreeScreen = I830BIOSFreeScreen;
+   pScrn->EnterVT = I830EnterVT;
+   pScrn->LeaveVT = I830LeaveVT;
+   pScrn->FreeScreen = I830FreeScreen;
    pScrn->ValidMode = I830ValidMode;
    pScrn->PMEvent = I830PMEvent;
 }
diff-tree 4820caf46e050761d9b347b8a440381e1b1f4727 (from c11c445bdeac34253b48192a5d406b55ff8b2be7)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Sep 21 01:47:27 2006 -0700

    Make planeEnabled track pipes controlled by randr.
    
    Also add code to deal with disabling pipes.

diff --git a/src/i830_display.c b/src/i830_display.c
index 3bd662d..24ce50f 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -719,7 +719,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     return TRUE;
 }
 
-static void
+void
 i830DisableUnusedFunctions(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
diff --git a/src/i830_display.h b/src/i830_display.h
index e5bca1c..2b808ad 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -27,6 +27,7 @@
 
 /* i830_display.c */
 Bool i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe);
+void i830DisableUnusedFunctions(ScrnInfoPtr pScrn);
 Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
 Bool i830DetectCRT(ScrnInfoPtr pScrn, Bool allow_disturb);
 void i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on);
diff --git a/src/i830_randr.c b/src/i830_randr.c
index 4132eb2..7c67aea 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -548,7 +548,7 @@ I830RandRCrtcSet (ScreenPtr	pScreen,
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
     I830Ptr		pI830 = I830PTR(pScrn);
     int			pipe = (int) (crtc->devPrivate);
-    DisplayModePtr	display_mode = mode->devPrivate;
+    DisplayModePtr	display_mode = mode ? mode->devPrivate : NULL;
     
     /* Sync the engine before adjust mode */
     if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
@@ -558,8 +558,24 @@ I830RandRCrtcSet (ScreenPtr	pScreen,
 
     if (display_mode != randrp->modes[pipe])
     {
-	if (!i830PipeSetMode (pScrn, display_mode, pipe))
-	    return FALSE;
+	pI830->planeEnabled[pipe] = mode != NULL;
+	if (display_mode)
+	{
+	    if (!i830PipeSetMode (pScrn, display_mode, pipe))
+		return FALSE;
+	    /* XXX need I830SDVOPostSetMode here */
+	}
+	else
+	{
+	    CARD32  operatingDevices = pI830->operatingDevices;
+
+	    if (pipe == 0)
+		pI830->operatingDevices &= ~0xff;
+	    else
+		pI830->operatingDevices &= ~0xff00;
+	    i830DisableUnusedFunctions (pScrn);
+	    pI830->operatingDevices = operatingDevices;
+	}
 	randrp->modes[pipe] = display_mode;
     }
     i830PipeSetBase(pScrn, pipe, x, y);
diff-tree c11c445bdeac34253b48192a5d406b55ff8b2be7 (from 4a8b9515e914369e1faf1dca6b11204b233c73ee)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Sep 21 01:23:10 2006 -0700

    Consistently use Cursor A on Pipe 0 and Cursor B on Pipe 1.
    
    Mixing random cursors and pipes didn't work very well. I'm left wondering
    whether the palette stuff will work on pre-9xx series hardware though; it is
    special cased everwhere else.

diff --git a/src/i830.h b/src/i830.h
index fcd03ef..a0ded02 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -534,7 +534,7 @@ extern void I830SetMMIOAccess(I830Ptr pI
 extern void I830PrintErrorState(ScrnInfoPtr pScrn);
 extern void I830Sync(ScrnInfoPtr pScrn);
 extern void I830InitHWCursor(ScrnInfoPtr pScrn);
-extern void I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe);
+extern void I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe, Bool force);
 extern Bool I830CursorInit(ScreenPtr pScreen);
 extern void I830EmitInvarientState(ScrnInfoPtr pScrn);
 extern void I830SelectBuffer(ScrnInfoPtr pScrn, int buffer);
diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index 1e7beef..7389b66 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -80,7 +80,7 @@ static Bool I830UseHWCursorARGB(ScreenPt
 #endif
 
 void
-I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe)
+I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe, Bool force)
 {
    I830Ptr pI830 = I830PTR(pScrn);
    CARD32 temp;
@@ -90,7 +90,7 @@ I830SetPipeCursor (ScrnInfoPtr pScrn, in
 	return;
 
     show = pI830->cursorOn && pI830->cursorInRange[pipe];
-    if (show && !pI830->cursorShown[pipe])
+    if (show && (force || !pI830->cursorShown[pipe]))
     {
 	if (IS_MOBILE(pI830) || IS_I9XX(pI830)) {
 	    int	cursor_control, cursor_base;
@@ -138,7 +138,7 @@ I830SetPipeCursor (ScrnInfoPtr pScrn, in
 	}
 	pI830->cursorShown[pipe] = TRUE;
     }
-    else if (!show && pI830->cursorShown[pipe])
+    else if (!show && (force || pI830->cursorShown[pipe]))
     {
 	if (IS_MOBILE(pI830) || IS_I9XX(pI830)) 
 	{
@@ -182,25 +182,22 @@ I830InitHWCursor(ScrnInfoPtr pScrn)
    for (i = 0; i < MAX_DISPLAY_PIPES; i++) pI830->cursorShown[i] = FALSE;
    /* Initialise the HW cursor registers, leaving the cursor hidden. */
    if (IS_MOBILE(pI830) || IS_I9XX(pI830)) {
-      temp = INREG(CURSOR_A_CONTROL);
-      temp &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE | MCURSOR_MEM_TYPE_LOCAL |
-		MCURSOR_PIPE_SELECT);
-      temp |= CURSOR_MODE_DISABLE;
-      temp |= (pI830->pipe << 28);
-      /* Need to set control, then address. */
-      OUTREG(CURSOR_A_CONTROL, temp);
-      if (pI830->CursorIsARGB)
-         OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical);
-      else
-         OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical);
-      if (pI830->Clone) {
-         temp &= ~MCURSOR_PIPE_SELECT;
-         temp |= (!pI830->pipe << 28);
-         OUTREG(CURSOR_B_CONTROL, temp);
-         if (pI830->CursorIsARGB)
-            OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical);
-         else
-            OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical);
+      for (i = 0; i < MAX_DISPLAY_PIPES; i++)
+      {
+	 int   cursor_control = i == 0 ? CURSOR_A_CONTROL : CURSOR_B_CONTROL;
+	 int   cursor_base = i == 0 ? CURSOR_A_BASE : CURSOR_B_BASE;
+	 temp = INREG(cursor_control);
+	 temp &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE |
+		   MCURSOR_MEM_TYPE_LOCAL |
+		   MCURSOR_PIPE_SELECT);
+	 temp |= CURSOR_MODE_DISABLE;
+	 temp |= (i << 28);
+	 /* Need to set control, then address. */
+	 OUTREG(cursor_control, temp);
+	 if (pI830->CursorIsARGB)
+	    OUTREG(cursor_base, pI830->CursorMemARGB->Physical);
+	 else
+	    OUTREG(cursor_base, pI830->CursorMem->Physical);
       }
    } else {
       temp = INREG(CURSOR_CONTROL);
@@ -530,20 +527,15 @@ I830SetCursorPosition(ScrnInfoPtr pScrn,
 
 	pI830->cursorInRange[pipe] = inrange;
 	
-        I830SetPipeCursor (pScrn, pipe);
-    }
+        I830SetPipeCursor (pScrn, pipe, FALSE);
 
-    /* have to upload the base for the new position */
-    if (IS_I9XX(pI830)) {
-	if (pI830->CursorIsARGB)
-	    OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical);
-	else
-	    OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical);
-	if (pI830->Clone) {
+	/* have to upload the base for the new position */
+	if (IS_I9XX(pI830)) {
+	    int base = pipe == 0 ? CURSOR_A_BASE : CURSOR_B_BASE;
 	    if (pI830->CursorIsARGB)
-		OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical);
+		OUTREG(base, pI830->CursorMemARGB->Physical);
 	    else
-		OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical);
+		OUTREG(base, pI830->CursorMem->Physical);
 	}
     }
 }
@@ -566,7 +558,7 @@ I830ShowCursor(ScrnInfoPtr pScrn)
 
     pI830->cursorOn = TRUE;
     for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++)
-	I830SetPipeCursor (pScrn, pipe);
+	I830SetPipeCursor (pScrn, pipe, TRUE);
 }
 
 static void
@@ -579,7 +571,7 @@ I830HideCursor(ScrnInfoPtr pScrn)
 
    pI830->cursorOn = FALSE;
     for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++)
-	I830SetPipeCursor (pScrn, pipe);
+	I830SetPipeCursor (pScrn, pipe, TRUE);
 }
 
 static void
@@ -595,11 +587,15 @@ I830SetCursorColors(ScrnInfoPtr pScrn, i
 
    DPRINTF(PFX, "I830SetCursorColors\n");
 
-   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->Clone) {
+   if (pI830->planeEnabled[0])
+   {
+       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->planeEnabled[1])
+   {
       OUTREG(CURSOR_B_PALETTE0, bg & 0x00ffffff);
       OUTREG(CURSOR_B_PALETTE1, fg & 0x00ffffff);
       OUTREG(CURSOR_B_PALETTE2, fg & 0x00ffffff);
diff-tree 4a8b9515e914369e1faf1dca6b11204b233c73ee (from parents)
Merge: 18a510bf9af2f288c0e94359f672775d6e9c9ab2 bdca8697cc6ac5a98e0548b2ce2e0032e9bcfa52
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Wed Sep 20 22:46:55 2006 -0700

    Merge branch 'modesetting' into randr-1.2

diff-tree bdca8697cc6ac5a98e0548b2ce2e0032e9bcfa52 (from parents)
Merge: d9db5ec6866555ec13ba3ddabb1516eb45637afa daade50ca271d1cdf236bbe84afade85d4111ac9
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Wed Sep 20 22:46:42 2006 -0700

    Merge branch 'modesetting-origin' into modesetting

diff-tree 18a510bf9af2f288c0e94359f672775d6e9c9ab2 (from parents)
Merge: f6500e94fec0d6db8c1f1350bee1d137bf06a09e d9db5ec6866555ec13ba3ddabb1516eb45637afa
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Wed Sep 20 22:45:48 2006 -0700

    Merge branch 'modesetting' into randr-1.2

diff-tree f6500e94fec0d6db8c1f1350bee1d137bf06a09e (from cbaf3cf74bd420533d299c4113761ec536097e33)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Wed Sep 20 22:38:55 2006 -0700

    Update driver for RandR 1.2 X server API.
    
    This is not entirely what I'd like to see, but it's at least functional.
    
    Limitations:
    	Can't disable/enable crtcs
    	Can't move outputs on/off crtcs
    
    But, it does handle monitor hot-plug, detecting changes in VGA and SDVO
    status on-the fly. Which makes for good demo material.

diff --git a/configure.ac b/configure.ac
index 5c9291b..3375fa9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -99,8 +99,6 @@ if test "x$GCC" = "xyes"; then
 	-Wnested-externs -fno-strict-aliasing"
 fi
 
-CFLAGS="$CFLAGS $WARN_CFLAGS"
-
 AM_CONDITIONAL(DRI, test x$DRI = xyes)
 if test "$DRI" = yes; then
         PKG_CHECK_MODULES(DRI, [libdrm >= 2.0 xf86driproto])
@@ -110,6 +108,7 @@ fi
 
 AC_SUBST([DRI_CFLAGS])
 AC_SUBST([XORG_CFLAGS])
+AC_SUBST([WARN_CFLAGS])
 AC_SUBST([moduledir])
 
 DRIVER_NAME=i810
diff --git a/src/Makefile.am b/src/Makefile.am
index 50d0ad1..03b5fe6 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -24,7 +24,7 @@ SUBDIRS = xvmc bios_reader ch7xxx sil164
 # -avoid-version prevents gratuitous .0.0.0 version numbers on the end
 # _ladir passes a dummy rpath to libtool so the thing will actually link
 # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
-AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ -DI830_XV
+AM_CFLAGS = @WARN_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@ -DI830_XV
 
 i810_drv_la_LTLIBRARIES = i810_drv.la
 i810_drv_la_LDFLAGS = -module -avoid-version
diff --git a/src/i830.h b/src/i830.h
index 3a93931..fcd03ef 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -79,6 +79,16 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * Paulo César Pereira de Andrade <pcpa at conectiva.com.br>.
  */
 
+#define PIPE_CRT_ID	0
+#define PIPE_TV_ID    	1
+#define PIPE_DFP_ID	2
+#define PIPE_LFP_ID	3
+#define PIPE_CRT2_ID	4
+#define PIPE_TV2_ID	5
+#define PIPE_DFP2_ID	6
+#define PIPE_LFP2_ID	7
+#define PIPE_NUM_ID	8
+
 #define PIPE_NONE	0<<0
 #define PIPE_CRT	1<<0
 #define PIPE_TV		1<<1
@@ -201,10 +211,12 @@ typedef struct _I830SDVODriver {
    CARD32 save_SDVOX;
 } I830SDVORec, *I830SDVOPtr;
 
+extern const char *i830_output_type_names[];
+
 struct _I830OutputRec {
    int type;
-   int pipe;
-   int flags;
+/*   int pipe;
+   int flags;*/
    xf86MonPtr MonInfo;
    I2CBusPtr pI2CBus;
    I2CBusPtr pDDCBus;
@@ -233,6 +245,10 @@ typedef struct _I830Rec {
 
    Bool gammaEnabled[MAX_DISPLAY_PIPES];
 
+   int pipeX[MAX_DISPLAY_PIPES];
+   int pipeY[MAX_DISPLAY_PIPES];
+   Bool cursorInRange[MAX_DISPLAY_PIPES];
+   Bool cursorShown[MAX_DISPLAY_PIPES];
    Bool Clone;
    int CloneRefresh;
    int CloneHDisplay;
@@ -518,6 +534,7 @@ extern void I830SetMMIOAccess(I830Ptr pI
 extern void I830PrintErrorState(ScrnInfoPtr pScrn);
 extern void I830Sync(ScrnInfoPtr pScrn);
 extern void I830InitHWCursor(ScrnInfoPtr pScrn);
+extern void I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe);
 extern Bool I830CursorInit(ScreenPtr pScreen);
 extern void I830EmitInvarientState(ScrnInfoPtr pScrn);
 extern void I830SelectBuffer(ScrnInfoPtr pScrn, int buffer);
@@ -610,6 +627,7 @@ DisplayModePtr i830GetGTF(int h_pixels, 
 int I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time);
 
 /* i830_randr.c */
+Bool I830RandRCreateScreenResources (ScreenPtr pScreen);
 Bool I830RandRInit(ScreenPtr pScreen, int rotation);
 Bool I830RandRSetConfig(ScreenPtr pScreen, Rotation rotation, int rate,
 			RRScreenSizePtr pSize);
diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index 2cb069c..1e7beef 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -80,12 +80,106 @@ static Bool I830UseHWCursorARGB(ScreenPt
 #endif
 
 void
+I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+   CARD32 temp;
+    Bool show;
+    
+    if (!pI830->planeEnabled[pipe])
+	return;
+
+    show = pI830->cursorOn && pI830->cursorInRange[pipe];
+    if (show && !pI830->cursorShown[pipe])
+    {
+	if (IS_MOBILE(pI830) || IS_I9XX(pI830)) {
+	    int	cursor_control, cursor_base;
+	    if (pipe == 0)
+	    {
+		cursor_control = CURSOR_A_CONTROL;
+		cursor_base = CURSOR_A_BASE;
+	    }
+	    else
+	    {
+		cursor_control = CURSOR_B_CONTROL;
+		cursor_base = CURSOR_B_BASE;
+	    }
+	    temp = INREG(cursor_control);
+	    temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
+	    if (pI830->CursorIsARGB) {
+		temp |= CURSOR_MODE_64_ARGB_AX;
+		if (pI830->gammaEnabled[pipe])
+		    temp |= MCURSOR_GAMMA_ENABLE;
+	    } else
+		temp |= CURSOR_MODE_64_4C_AX;
+	    
+	    temp |= (pipe << 28); /* Connect to correct pipe */
+	    /* Need to set mode, then address. */
+	    OUTREG(cursor_control, temp);
+	    if (pI830->CursorIsARGB)
+		OUTREG(cursor_base, pI830->CursorMemARGB->Physical);
+	    else
+		OUTREG(cursor_base, pI830->CursorMem->Physical);
+	} else {
+	    temp = INREG(CURSOR_CONTROL);
+	    temp &= ~(CURSOR_FORMAT_MASK);
+	    temp |= CURSOR_ENABLE;
+	    if (pI830->CursorIsARGB) {
+		temp |= CURSOR_FORMAT_ARGB;
+		if (pI830->gammaEnabled[pipe])
+		    temp |= CURSOR_GAMMA_ENABLE;
+	    } else
+		temp |= CURSOR_FORMAT_3C;
+	    OUTREG(CURSOR_CONTROL, temp);
+	    if (pI830->CursorIsARGB)
+		OUTREG(CURSOR_BASEADDR, pI830->CursorMemARGB->Start);
+	    else
+		OUTREG(CURSOR_BASEADDR, pI830->CursorMem->Start);
+	}
+	pI830->cursorShown[pipe] = TRUE;
+    }
+    else if (!show && pI830->cursorShown[pipe])
+    {
+	if (IS_MOBILE(pI830) || IS_I9XX(pI830)) 
+	{
+	    int	cursor_control, cursor_base;
+	    if (pipe == 0)
+	    {
+		cursor_control = CURSOR_A_CONTROL;
+		cursor_base = CURSOR_A_BASE;
+	    }
+	    else
+	    {
+		cursor_control = CURSOR_B_CONTROL;
+		cursor_base = CURSOR_B_BASE;
+	    }
+	    temp = INREG(cursor_control);
+	    temp &= ~(CURSOR_MODE|MCURSOR_GAMMA_ENABLE);
+	    temp |= CURSOR_MODE_DISABLE;
+	    OUTREG(cursor_control, temp);
+	    /* This is needed to flush the above change. */
+	    if (pI830->CursorIsARGB)
+		OUTREG(cursor_base, pI830->CursorMemARGB->Physical);
+	    else
+		OUTREG(cursor_base, pI830->CursorMem->Physical);
+	} else {
+	    temp = INREG(CURSOR_CONTROL);
+	    temp &= ~(CURSOR_ENABLE|CURSOR_GAMMA_ENABLE);
+	    OUTREG(CURSOR_CONTROL, temp);
+	}
+	pI830->cursorShown[pipe] = FALSE;
+    }
+}
+
+void
 I830InitHWCursor(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
    CARD32 temp;
+   int i;
 
    DPRINTF(PFX, "I830InitHWCursor\n");
+   for (i = 0; i < MAX_DISPLAY_PIPES; i++) pI830->cursorShown[i] = FALSE;
    /* Initialise the HW cursor registers, leaving the cursor hidden. */
    if (IS_MOBILE(pI830) || IS_I9XX(pI830)) {
       temp = INREG(CURSOR_A_CONTROL);
@@ -356,121 +450,109 @@ static void I830LoadCursorARGB (ScrnInfo
 static void
 I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
-   CARD32 temp = 0;
-   Bool hide = FALSE, show = FALSE;
-   int oldx = x, oldy = y;
-   int hotspotx = 0, hotspoty = 0;
-#if 0
-   static Bool outsideViewport = FALSE;
-#endif
-
-   oldx += pScrn->frameX0; /* undo what xf86HWCurs did */
-   oldy += pScrn->frameY0;
-
-   switch (pI830->rotation) {
-      case RR_Rotate_0:
-         x = oldx;
-         y = oldy;
-         break;
-      case RR_Rotate_90:
-         x = oldy;
-         y = pScrn->pScreen->width - oldx;
-         hotspoty = I810_CURSOR_X;
-         break;
-      case RR_Rotate_180:
-         x = pScrn->pScreen->width - oldx;
-         y = pScrn->pScreen->height - oldy;
-         hotspotx = I810_CURSOR_X;
-         hotspoty = I810_CURSOR_Y;
-         break;
-      case RR_Rotate_270:
-         x = pScrn->pScreen->height - oldy;
-         y = oldx;
-         hotspotx = I810_CURSOR_Y;
-         break;
-   }
-
-   x -= hotspotx;
-   y -= hotspoty;
-
-   /* Now, readjust */
-   x -= pScrn->frameX0;
-   y -= pScrn->frameY0;
-
-   /* Clamp the cursor position to the visible screen area.  Ignore this if we
-    * are doing motion (with SilkenMouse) while the currentMode being changed.
-    */
-   if (pScrn->currentMode != NULL) {
-     if (x >= pScrn->currentMode->HDisplay)
-       x = pScrn->currentMode->HDisplay - 1;
-     if (y >= pScrn->currentMode->VDisplay)
-       y = pScrn->currentMode->VDisplay - 1;
-   }
-   if (x <= -I810_CURSOR_X) x = -I810_CURSOR_X + 1;
-   if (y <= -I810_CURSOR_Y) y = -I810_CURSOR_Y + 1;
-
-#if 0
-   /*
-    * There is a screen display problem when the cursor position is set
-    * wholely outside of the viewport.  We trap that here, turning the
-    * cursor off when that happens, and back on when it comes back into
-    * the viewport.
-    */
-   if (x >= pScrn->currentMode->HDisplay ||
-       y >= pScrn->currentMode->VDisplay ||
-       x <= -I810_CURSOR_X || y <= -I810_CURSOR_Y) {
-      hide = TRUE;
-      outsideViewport = TRUE;
-   } else if (outsideViewport) {
-      show = TRUE;
-      outsideViewport = FALSE;
-   }
-#endif
-
-   if (x < 0) {
-      temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
-      x = -x;
-   }
-   if (y < 0) {
-      temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT);
-      y = -y;
-   }
-   temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
-   temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
-
-   OUTREG(CURSOR_A_POSITION, temp);
-   if (pI830->Clone)
-      OUTREG(CURSOR_B_POSITION, temp);
-
-   if (pI830->cursorOn) {
-      if (hide)
-	 pI830->CursorInfoRec->HideCursor(pScrn);
-      else if (show)
-	 pI830->CursorInfoRec->ShowCursor(pScrn);
-      pI830->cursorOn = TRUE;
-   }
-
-   /* have to upload the base for the new position */
-   if (IS_I9XX(pI830)) {
-      if (pI830->CursorIsARGB)
-         OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical);
-      else
-         OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical);
-      if (pI830->Clone) {
-         if (pI830->CursorIsARGB)
-            OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical);
-         else
-            OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical);
-      }
-   }
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD32 temp;
+    Bool inrange;
+    int oldx = x, oldy = y;
+    int hotspotx = 0, hotspoty = 0;
+    int pipe;
+
+    oldx += pScrn->frameX0; /* undo what xf86HWCurs did */
+    oldy += pScrn->frameY0;
+
+    switch (pI830->rotation) {
+    case RR_Rotate_0:
+	x = oldx;
+	y = oldy;
+	break;
+    case RR_Rotate_90:
+	x = oldy;
+	y = pScrn->pScreen->width - oldx;
+	hotspoty = I810_CURSOR_X;
+	break;
+    case RR_Rotate_180:
+	x = pScrn->pScreen->width - oldx;
+	y = pScrn->pScreen->height - oldy;
+	hotspotx = I810_CURSOR_X;
+	hotspoty = I810_CURSOR_Y;
+	break;
+    case RR_Rotate_270:
+	x = pScrn->pScreen->height - oldy;
+	y = oldx;
+	hotspotx = I810_CURSOR_Y;
+	break;
+    }
+
+    x -= hotspotx;
+    y -= hotspoty;
+
+    for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++)
+    {
+	DisplayModePtr	mode = &pI830->pipeCurMode[pipe];
+	int		thisx = x - pI830->pipeX[pipe];
+	int		thisy = y - pI830->pipeY[pipe];
+
+	if (!pI830->planeEnabled[pipe])
+	    continue;
+
+	/*
+	 * There is a screen display problem when the cursor position is set
+	 * wholely outside of the viewport.  We trap that here, turning the
+	 * cursor off when that happens, and back on when it comes back into
+	 * the viewport.
+	 */
+	inrange = TRUE;
+	if (thisx >= mode->HDisplay ||
+	    thisy >= mode->VDisplay ||
+	    thisx <= -I810_CURSOR_X || thisy <= -I810_CURSOR_Y) 
+	{
+	    inrange = FALSE;
+	    thisx = 0;
+	    thisy = 0;
+	}
+
+	temp = 0;
+	if (thisx < 0) {
+	    temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
+	    thisx = -thisx;
+	}
+	if (thisy < 0) {
+	    temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT);
+	    thisy = -thisy;
+	}
+	temp |= ((thisx & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
+	temp |= ((thisy & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
+
+	if (pipe == 0)
+	    OUTREG(CURSOR_A_POSITION, temp);
+	if (pipe == 1)
+	    OUTREG(CURSOR_B_POSITION, temp);
+
+	pI830->cursorInRange[pipe] = inrange;
+	
+        I830SetPipeCursor (pScrn, pipe);
+    }
+
+    /* have to upload the base for the new position */
+    if (IS_I9XX(pI830)) {
+	if (pI830->CursorIsARGB)
+	    OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical);
+	else
+	    OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical);
+	if (pI830->Clone) {
+	    if (pI830->CursorIsARGB)
+		OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical);
+	    else
+		OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical);
+	}
+    }
 }
 
 static void
 I830ShowCursor(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
-   CARD32 temp;
+    int pipe;
 
    DPRINTF(PFX, "I830ShowCursor\n");
    DPRINTF(PFX,
@@ -482,81 +564,22 @@ I830ShowCursor(ScrnInfoPtr pScrn)
 	   " Value of CursorMemARGB->Start is %x ",
 	   pI830->CursorMemARGB->Physical, pI830->CursorMemARGB->Start);
 
-   pI830->cursorOn = TRUE;
-   if (IS_MOBILE(pI830) || IS_I9XX(pI830)) {
-      temp = INREG(CURSOR_A_CONTROL);
-      temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
-      if (pI830->CursorIsARGB) {
-         temp |= CURSOR_MODE_64_ARGB_AX;
-	 if (pI830->gammaEnabled[pI830->pipe])
-	    temp |= MCURSOR_GAMMA_ENABLE;
-      } else
-         temp |= CURSOR_MODE_64_4C_AX;
-      temp |= (pI830->pipe << 28); /* Connect to correct pipe */
-      /* Need to set mode, then address. */
-      OUTREG(CURSOR_A_CONTROL, temp);
-      if (pI830->CursorIsARGB)
-         OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical);
-      else
-         OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical);
-      if (pI830->Clone) {
-         temp &= ~MCURSOR_PIPE_SELECT;
-         temp |= (!pI830->pipe << 28);
-         OUTREG(CURSOR_B_CONTROL, temp);
-         if (pI830->CursorIsARGB)
-            OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical);
-         else
-            OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical);
-      }
-   } else {
-      temp = INREG(CURSOR_CONTROL);
-      temp &= ~(CURSOR_FORMAT_MASK);
-      temp |= CURSOR_ENABLE;
-      if (pI830->CursorIsARGB) {
-         temp |= CURSOR_FORMAT_ARGB;
-	 if (pI830->gammaEnabled[pI830->pipe])
-	    temp |= CURSOR_GAMMA_ENABLE;
-      } else
-         temp |= CURSOR_FORMAT_3C;
-      OUTREG(CURSOR_CONTROL, temp);
-      if (pI830->CursorIsARGB)
-         OUTREG(CURSOR_BASEADDR, pI830->CursorMemARGB->Start);
-      else
-         OUTREG(CURSOR_BASEADDR, pI830->CursorMem->Start);
-   }
+    pI830->cursorOn = TRUE;
+    for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++)
+	I830SetPipeCursor (pScrn, pipe);
 }
 
 static void
 I830HideCursor(ScrnInfoPtr pScrn)
 {
-   CARD32 temp;
    I830Ptr pI830 = I830PTR(pScrn);
+    int pipe;
 
    DPRINTF(PFX, "I830HideCursor\n");
 
    pI830->cursorOn = FALSE;
-   if (IS_MOBILE(pI830) || IS_I9XX(pI830)) {
-      temp = INREG(CURSOR_A_CONTROL);
-      temp &= ~(CURSOR_MODE|MCURSOR_GAMMA_ENABLE);
-      temp |= CURSOR_MODE_DISABLE;
-      OUTREG(CURSOR_A_CONTROL, temp);
-      /* This is needed to flush the above change. */
-      if (pI830->CursorIsARGB)
-         OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical);
-      else
-         OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical);
-      if (pI830->Clone) {
-         OUTREG(CURSOR_B_CONTROL, temp);
-         if (pI830->CursorIsARGB)
-            OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical);
-         else
-            OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical);
-      }
-   } else {
-      temp = INREG(CURSOR_CONTROL);
-      temp &= ~(CURSOR_ENABLE|CURSOR_GAMMA_ENABLE);
-      OUTREG(CURSOR_CONTROL, temp);
-   }
+    for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++)
+	I830SetPipeCursor (pScrn, pipe);
 }
 
 static void
diff --git a/src/i830_display.c b/src/i830_display.c
index 6eb2a33..52d488a 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -245,13 +245,15 @@ i830PipeSetBase(ScrnInfoPtr pScrn, int p
 	OUTREG(DSPABASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
     else
 	OUTREG(DSPBBASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
+    pI830->pipeX[pipe] = x;
+    pI830->pipeY[pipe] = y;
 }
 
 /**
  * Sets the given video mode on the given pipe.  Assumes that plane A feeds
  * pipe A, and plane B feeds pipe B.  Should not affect the other planes/pipes.
  */
-static Bool
+Bool
 i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe)
 {
     I830Ptr pI830 = I830PTR(pScrn);
@@ -608,7 +610,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	OUTREG(DSPASTRIDE, pScrn->displayWidth * pI830->cpp);
 	OUTREG(DSPASIZE, dspsize);
 	OUTREG(DSPAPOS, 0);
-	i830PipeSetBase(pScrn, pipe, pScrn->frameX0, pScrn->frameY0);
+	i830PipeSetBase(pScrn, pipe, pI830->pipeX[pipe], pI830->pipeX[pipe]);
 	OUTREG(PIPEASRC, pipesrc);
 
 	/* Then, turn the pipe on first */
@@ -656,7 +658,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	OUTREG(DSPBSTRIDE, pScrn->displayWidth * pI830->cpp);
 	OUTREG(DSPBSIZE, dspsize);
 	OUTREG(DSPBPOS, 0);
-	i830PipeSetBase(pScrn, pipe, pScrn->frameX0, pScrn->frameY0);
+	i830PipeSetBase(pScrn, pipe, pI830->pipeX[pipe], pI830->pipeY[pipe]);
 	OUTREG(PIPEBSRC, pipesrc);
 
 	if (outputs & PIPE_LCD_ACTIVE) {
diff --git a/src/i830_display.h b/src/i830_display.h
index 2e61afc..e5bca1c 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -26,6 +26,7 @@
  */
 
 /* i830_display.c */
+Bool i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe);
 Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
 Bool i830DetectCRT(ScrnInfoPtr pScrn, Bool allow_disturb);
 void i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 8464b39..dc136a3 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -273,7 +273,7 @@ static OptionInfoRec I830BIOSOptions[] =
 };
 /* *INDENT-ON* */
 
-static const char *output_type_names[] = {
+const char *i830_output_type_names[] = {
    "Unused",
    "Analog",
    "DVO",
@@ -1133,7 +1133,7 @@ I830DetectMonitors(ScrnInfoPtr pScrn)
 						    pI830->output[i].pDDCBus);
 
 	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC %s %d, %08lX\n",
-		    output_type_names[pI830->output[i].type], i,
+		    i830_output_type_names[pI830->output[i].type], i,
 		    pI830->output[i].pDDCBus->DriverPrivate.uval);
 	 xf86PrintEDID(pI830->output[i].MonInfo);
 	 break;
@@ -3164,22 +3164,8 @@ I830CreateScreenResources (ScreenPtr pSc
    if (!(*pScreen->CreateScreenResources)(pScreen))
       return FALSE;
 
-   if (pI830->rotation != RR_Rotate_0) {
-      RRScreenSize p;
-      Rotation requestedRotation = pI830->rotation;
-
-      pI830->rotation = RR_Rotate_0;
-
-      /* Just setup enough for an initial rotate */
-      p.width = pScreen->width;
-      p.height = pScreen->height;
-      p.mmWidth = pScreen->mmWidth;
-      p.mmHeight = pScreen->mmHeight;
-
-      pI830->starting = TRUE; /* abuse this for dual head & rotation */
-      I830RandRSetConfig (pScreen, requestedRotation, 0, &p);
-      pI830->starting = FALSE;
-   } 
+   if (!I830RandRCreateScreenResources (pScreen))
+      return FALSE;
 
    return TRUE;
 }
@@ -3507,6 +3493,9 @@ I830BIOSScreenInit(int scrnIndex, Screen
    if (!I830BIOSEnterVT(scrnIndex, 0))
       return FALSE;
 
+    if (pScrn->virtualX > pScrn->displayWidth)
+	pScrn->displayWidth = pScrn->virtualX;
+
    DPRINTF(PFX, "assert( if(!fbScreenInit(pScreen, ...) )\n");
    if (!fbScreenInit(pScreen, pI830->FbBase + pScrn->fbOffset, 
                      pScrn->virtualX, pScrn->virtualY,
diff --git a/src/i830_modes.c b/src/i830_modes.c
index 6bff1d0..3b70d5d 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -954,6 +954,11 @@ I830ValidateXF86ModeList(ScrnInfoPtr pSc
 		    maxY = mode->VDisplay;
 	    }
 	}
+	/* let the user specify a bigger virtual size if they like */
+	if (pScrn->display->virtualX > maxX)
+	    maxX = pScrn->display->virtualX;
+	if (pScrn->display->virtualY > maxY)
+	    maxY = pScrn->display->virtualY;
 	pScrn->virtualX = maxX;
 	pScrn->virtualY = maxY;
 	pScrn->displayWidth = (maxX + 63) & ~63;
diff --git a/src/i830_randr.c b/src/i830_randr.c
index 4c7c087..4132eb2 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -23,6 +23,10 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include "xf86.h"
 #include "os.h"
 #include "mibank.h"
@@ -33,9 +37,11 @@
 #include "mipointer.h"
 #include "windowstr.h"
 #include <randrstr.h>
+#include <X11/extensions/render.h>
 
 #include "i830.h"
 #include "i830_xf86Modes.h"
+#include "i830_display.h"
 
 typedef struct _i830RandRInfo {
     int				    virtualX;
@@ -46,8 +52,18 @@ typedef struct _i830RandRInfo {
     int				    maxY;
     Rotation			    rotation; /* current mode */
     Rotation                        supported_rotations; /* driver supported */
+#ifdef RANDR_12_INTERFACE
+    RRCrtcPtr			    crtcs[MAX_DISPLAY_PIPES];
+    RROutputPtr			    outputs[MAX_OUTPUTS];
+    DisplayModePtr  		    modes[MAX_DISPLAY_PIPES];
+#endif
 } XF86RandRInfoRec, *XF86RandRInfoPtr;
     
+#ifdef RANDR_12_INTERFACE
+static Bool I830RandRInit12 (ScreenPtr pScreen);
+static Bool I830RandRCreateScreenResources12 (ScreenPtr pScreen);
+#endif
+
 static int	    i830RandRIndex;
 static int	    i830RandRGeneration;
 
@@ -317,6 +333,40 @@ I830GetRotation(ScreenPtr pScreen)
 }
 
 Bool
+I830RandRCreateScreenResources (ScreenPtr pScreen)
+{
+    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+#ifdef PANORAMIX
+    /* XXX disable RandR when using Xinerama */
+    if (!noPanoramiXExtension)
+	return TRUE;
+#endif
+#if RANDR_12_INTERFACE
+    if (I830RandRCreateScreenResources12 (pScreen))
+	return TRUE;
+#endif
+    if (pI830->rotation != RR_Rotate_0) {
+	RRScreenSize p;
+	Rotation requestedRotation = pI830->rotation;
+
+	pI830->rotation = RR_Rotate_0;
+
+	/* Just setup enough for an initial rotate */
+	p.width = pScreen->width;
+	p.height = pScreen->height;
+	p.mmWidth = pScreen->mmWidth;
+	p.mmHeight = pScreen->mmHeight;
+
+	pI830->starting = TRUE; /* abuse this for dual head & rotation */
+	I830RandRSetConfig (pScreen, requestedRotation, 0, &p);
+	pI830->starting = FALSE;
+    } 
+    return TRUE;
+}
+    
+    
+Bool
 I830RandRInit (ScreenPtr    pScreen, int rotation)
 {
     rrScrPrivPtr	rp;
@@ -359,6 +409,10 @@ I830RandRInit (ScreenPtr    pScreen, int
 
     pScreen->devPrivates[i830RandRIndex].ptr = randrp;
 
+#if RANDR_12_INTERFACE
+    if (!I830RandRInit12 (pScreen))
+	return FALSE;
+#endif
     return TRUE;
 }
 
@@ -379,3 +433,399 @@ I830GetOriginalVirtualSize(ScrnInfoPtr p
 	*y = randrp->virtualY;
     }
 }
+
+#if RANDR_12_INTERFACE
+static Bool
+I830RandRScreenSetSize (ScreenPtr	pScreen,
+			CARD16		width,
+			CARD16		height,
+			CARD32		mmWidth,
+			CARD32		mmHeight)
+{
+    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
+    ScrnInfoPtr		pScrn = XF86SCRNINFO(pScreen);
+    WindowPtr		pRoot = WindowTable[pScreen->myNum];
+    Bool 		ret = TRUE;
+    
+    if (randrp->virtualX == -1 || randrp->virtualY == -1) 
+    {
+	randrp->virtualX = pScrn->virtualX;
+	randrp->virtualY = pScrn->virtualY;
+    }
+    if (pRoot)
+	(*pScrn->EnableDisableFBAccess) (pScreen->myNum, FALSE);
+    pScrn->virtualX = width;
+    pScrn->virtualY = height;
+
+    pScreen->width = pScrn->virtualX;
+    pScreen->height = pScrn->virtualY;
+    pScreen->mmWidth = mmWidth;
+    pScreen->mmHeight = mmHeight;
+    
+    xf86SetViewport (pScreen, pScreen->width, pScreen->height);
+    xf86SetViewport (pScreen, 0, 0);
+    if (pRoot)
+	(*pScrn->EnableDisableFBAccess) (pScreen->myNum, TRUE);
+    if (WindowTable[pScreen->myNum])
+	RRScreenSizeNotify (pScreen);
+    return ret;
+}
+
+static Bool
+I830RandRCrtcNotify (RRCrtcPtr	crtc)
+{
+    ScreenPtr		pScreen = crtc->pScreen;
+    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
+    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+    I830Ptr		pI830 = I830PTR(pScrn);
+    RRModePtr		mode = NULL;
+    int			x;
+    int			y;
+    Rotation		rotation;
+    int			numOutputs;
+    RROutputPtr		outputs[MAX_OUTPUTS];
+    struct _I830OutputRec   *output;
+    RROutputPtr		rrout;
+    int			pipe = (int) crtc->devPrivate;
+    int			i, j;
+    DisplayModePtr	pipeMode = &pI830->pipeCurMode[pipe];
+    int			pipe_type;
+    
+    x = pI830->pipeX[pipe];
+    y = pI830->pipeY[pipe];
+    rotation = RR_Rotate_0;
+    numOutputs = 0;
+    for (i = 0; i < pI830->num_outputs; i++)
+    {
+	output = &pI830->output[i];
+	/*
+	 * Valid crtcs
+	 */
+	switch (output->type) {
+	case I830_OUTPUT_DVO:
+	case I830_OUTPUT_SDVO:
+	    pipe_type = PIPE_DFP;
+	    break;
+	case I830_OUTPUT_ANALOG:
+	    pipe_type = PIPE_CRT;
+	    break;
+	case I830_OUTPUT_LVDS:
+	    pipe_type = PIPE_LFP;
+	    break;
+	case I830_OUTPUT_TVOUT:
+	    pipe_type = PIPE_TV;
+	    break;
+	default:
+	    pipe_type = PIPE_NONE;
+	    break;
+	}
+	if (pI830->operatingDevices & (pipe_type << (pipe << 3)))
+	{
+	    rrout = randrp->outputs[i];
+	    outputs[numOutputs++] = rrout;
+	    for (j = 0; j < rrout->numModes; j++)
+	    {
+		DisplayModePtr	outMode = rrout->modes[j]->devPrivate;
+		if (I830ModesEqual(pipeMode, outMode))
+		    mode = rrout->modes[j];
+	    }
+	}
+    }
+    return RRCrtcNotify (crtc, mode, x, y, rotation, numOutputs, outputs);
+}
+    
+static Bool
+I830RandRCrtcSet (ScreenPtr	pScreen,
+		  RRCrtcPtr	crtc,
+		  RRModePtr	mode,
+		  int		x,
+		  int		y,
+		  Rotation	rotation,
+		  int		numOutputs,
+		  RROutputPtr	*outputs)
+{
+    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
+    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+    I830Ptr		pI830 = I830PTR(pScrn);
+    int			pipe = (int) (crtc->devPrivate);
+    DisplayModePtr	display_mode = mode->devPrivate;
+    
+    /* Sync the engine before adjust mode */
+    if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
+	(*pI830->AccelInfoRec->Sync)(pScrn);
+	pI830->AccelInfoRec->NeedToSync = FALSE;
+    }
+
+    if (display_mode != randrp->modes[pipe])
+    {
+	if (!i830PipeSetMode (pScrn, display_mode, pipe))
+	    return FALSE;
+	randrp->modes[pipe] = display_mode;
+    }
+    i830PipeSetBase(pScrn, pipe, x, y);
+    return I830RandRCrtcNotify (crtc);
+}
+
+static Bool
+I830RandRCrtcSetGamma (ScreenPtr    pScreen,
+		       RRCrtcPtr    crtc)
+{
+    return FALSE;
+}
+
+/*
+ * Mirror the current mode configuration to RandR
+ */
+static Bool
+I830RandRSetInfo12 (ScreenPtr pScreen)
+{
+    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
+    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+    I830Ptr		pI830 = I830PTR(pScrn);
+    RROutputPtr		clones[MAX_OUTPUTS];
+    RRCrtcPtr		crtc;
+    int			nclone;
+    RRCrtcPtr		crtcs[MAX_DISPLAY_PIPES];
+    int			ncrtc;
+    RRModePtr		*modes;
+    int			nmode;
+    struct _I830OutputRec   *output;
+    int			i;
+    int			j;
+    int			clone_types;
+    int			crtc_types;
+    int			connection;
+    int			pipe_type;
+    int			pipe;
+    int			subpixel;
+    
+    if (randrp->virtualX == -1 || randrp->virtualY == -1) 
+    {
+	randrp->virtualX = pScrn->virtualX;
+	randrp->virtualY = pScrn->virtualY;
+    }
+    RRScreenSetSizeRange (pScreen, 320, 240, 
+			  randrp->virtualX, randrp->virtualY);
+    for (i = 0; i < pI830->num_outputs; i++)
+    {
+	output = &pI830->output[i];
+	/*
+	 * Valid crtcs
+	 */
+	switch (output->type) {
+	case I830_OUTPUT_DVO:
+	case I830_OUTPUT_SDVO:
+	    crtc_types = ((1 << 0)|
+			  (1 << 1));
+	    clone_types = ((1 << I830_OUTPUT_ANALOG) |
+			   (1 << I830_OUTPUT_DVO) |
+			   (1 << I830_OUTPUT_SDVO));
+	    pipe_type = PIPE_DFP;
+	    subpixel = SubPixelHorizontalRGB;
+	    break;
+	case I830_OUTPUT_ANALOG:
+	    crtc_types = (1 << 0);
+	    clone_types = ((1 << I830_OUTPUT_ANALOG) |
+			   (1 << I830_OUTPUT_DVO) |
+			   (1 << I830_OUTPUT_SDVO));
+	    pipe_type = PIPE_CRT;
+	    subpixel = SubPixelNone;
+	    break;
+	case I830_OUTPUT_LVDS:
+	    crtc_types = (1 << 1);
+	    clone_types = (1 << I830_OUTPUT_LVDS);
+	    pipe_type = PIPE_LFP;
+	    subpixel = SubPixelHorizontalRGB;
+	    break;
+	case I830_OUTPUT_TVOUT:
+	    crtc_types = ((1 << 0) |
+			  (1 << 1));
+	    clone_types = (1 << I830_OUTPUT_TVOUT);
+	    pipe_type = PIPE_TV;
+	    subpixel = SubPixelNone;
+	    break;
+	default:
+	    crtc_types = 0;
+	    clone_types = 0;
+	    pipe_type = PIPE_NONE;
+	    subpixel = SubPixelUnknown;
+	    break;
+	}
+	ncrtc = 0;
+	pipe = -1;
+	crtc = NULL;
+	for (j = 0; j < MAX_DISPLAY_PIPES; j++)
+	{
+#if 0
+	     /* Can't flip outputs among crtcs yet */
+	    if (crtc_types & (1 << j))
+		crtcs[ncrtc++] = randrp->crtcs[j];
+#endif
+	    if (pI830->operatingDevices & (pipe_type << (j << 3)))
+	    {
+		pipe = j;
+		crtc = randrp->crtcs[j];
+		crtcs[ncrtc++] = crtc;
+	    }
+	}
+	if (!RROutputSetCrtcs (randrp->outputs[i], crtcs, ncrtc))
+	    return FALSE;
+
+	RROutputSetCrtc (randrp->outputs[i], crtc);
+    
+	if (pipe >= 0)
+	{
+	    MonPtr	    mon = pI830->pipeMon[pipe];
+	    DisplayModePtr  mode;
+	    xRRModeInfo	    modeInfo;
+	    RRModePtr	    rrmode;
+	    
+	    nmode = 0;
+	    for (mode = mon->Modes; mode; mode = mode->next)
+		nmode++;
+	    
+	    if (nmode)
+	    {
+		modes = xalloc (nmode * sizeof (RRModePtr));
+		if (!modes)
+		    return FALSE;
+		nmode = 0;
+		for (mode = mon->Modes; mode; mode = mode->next)
+		{
+		    modeInfo.nameLength = strlen (mode->name);
+		    modeInfo.mmWidth = mon->widthmm;
+		    modeInfo.mmHeight = mon->heightmm;
+
+		    modeInfo.width = mode->HDisplay;
+		    modeInfo.dotClock = mode->Clock * 1000;
+		    modeInfo.hSyncStart = mode->HSyncStart;
+		    modeInfo.hSyncEnd = mode->HSyncEnd;
+		    modeInfo.hTotal = mode->HTotal;
+		    modeInfo.hSkew = mode->HSkew;
+
+		    modeInfo.height = mode->VDisplay;
+		    modeInfo.vSyncStart = mode->VSyncStart;
+		    modeInfo.vSyncEnd = mode->VSyncEnd;
+		    modeInfo.vTotal = mode->VTotal;
+		    modeInfo.modeFlags = mode->Flags;
+
+		    rrmode = RRModeGet (pScreen, &modeInfo, mode->name);
+		    rrmode->devPrivate = mode;
+		    if (rrmode)
+			modes[nmode++] = rrmode;
+		}
+		if (!RROutputSetModes (randrp->outputs[i], modes, nmode))
+		{
+		    xfree (modes);
+		    return FALSE;
+		}
+
+		xfree (modes);
+	    }
+	}
+	connection = RR_Disconnected;
+	if (pipe >= 0)
+	    connection = RR_Connected;
+
+	RROutputSetConnection (randrp->outputs[i], connection);
+	    
+	RROutputSetSubpixelOrder (randrp->outputs[i], subpixel);
+
+	/*
+	 * Valid clones
+	 */
+	nclone = 0;
+	for (j = 0; j < pI830->num_outputs; j++)
+	{
+	    if (i != j && ((1 << pI830->output[j].type) & clone_types))
+		clones[nclone++] = randrp->outputs[j];
+	}
+	if (!RROutputSetClones (randrp->outputs[i], clones, nclone))
+	    return FALSE;
+    }
+    for (i = 0; i < MAX_DISPLAY_PIPES; i++)
+	I830RandRCrtcNotify (randrp->crtcs[i]);
+    return TRUE;
+}
+
+    
+/*
+ * Query the hardware for the current state, then mirror
+ * that to RandR
+ */
+static Bool
+I830RandRGetInfo12 (ScreenPtr pScreen, Rotation *rotations)
+{
+    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+    /* Re-probe the outputs for new monitors or modes */
+    I830ValidateXF86ModeList(pScrn, FALSE);
+    return I830RandRSetInfo12 (pScreen);
+}
+
+static Bool
+I830RandRCreateScreenResources12 (ScreenPtr pScreen)
+{
+    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
+    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+    I830Ptr		pI830 = I830PTR(pScrn);
+    struct _I830OutputRec   *output;
+    const char		*name;
+    int			i;
+    DisplayModePtr	mode;
+
+    /*
+     * Create RandR resources, then probe them
+     */
+    for (i = 0; i < MAX_DISPLAY_PIPES; i++)
+    {
+	randrp->crtcs[i] = RRCrtcCreate (pScreen, (void *) i);
+	RRCrtcGammaSetSize (randrp->crtcs[i], 256);
+    }
+
+    for (i = 0; i < pI830->num_outputs; i++)
+    {
+	output = &pI830->output[i];
+	name = i830_output_type_names[output->type];
+	randrp->outputs[i] = RROutputCreate (pScreen,
+					     name, strlen (name),
+					     (void *) i);
+    }
+    
+    mode = pScrn->currentMode;
+    if (mode)
+    {
+	I830RandRScreenSetSize (pScreen,
+				mode->HDisplay,
+				mode->VDisplay,
+				pScreen->mmWidth,
+				pScreen->mmHeight);
+	
+    }
+			    
+    for (i = 0; i < MAX_DISPLAY_PIPES; i++)
+	i830PipeSetBase(pScrn, i, 0, 0);
+	
+    return I830RandRSetInfo12 (pScreen);
+}
+
+static void
+I830RandRPointerMoved (int scrnIndex, int x, int y)
+{
+}
+
+static Bool
+I830RandRInit12 (ScreenPtr pScreen)
+{
+    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+    rrScrPrivPtr	rp = rrGetScrPriv(pScreen);
+
+    rp->rrGetInfo = I830RandRGetInfo12;
+    rp->rrScreenSetSize = I830RandRScreenSetSize;
+    rp->rrCrtcSet = I830RandRCrtcSet;
+    rp->rrCrtcSetGamma = I830RandRCrtcSetGamma;
+    rp->rrSetConfig = NULL;
+    memset (rp->modes, '\0', sizeof (rp->modes));
+    pScrn->PointerMoved = I830RandRPointerMoved;
+    return TRUE;
+}
+#endif
diff-tree daade50ca271d1cdf236bbe84afade85d4111ac9 (from e3f4caf40708478ef327b029d0a75944c51ea905)
Author: Linus Torvals <torvalds at osdl.org>
Date:   Wed Sep 20 12:07:09 2006 -0700

    Add standard C headers to fix build on some systems after xf86_ansic.h removal.
    
    This appears to have been hidden for others by header pollution in X Server
    headers.

diff --git a/src/i830_bios.c b/src/i830_bios.c
index 556f57b..14e354e 100644
--- a/src/i830_bios.c
+++ b/src/i830_bios.c
@@ -29,6 +29,9 @@
 #undef VERSION	/* XXX edid.h has a VERSION too */
 #endif
 
+#include <stdio.h>
+#include <string.h>
+
 #define _PARSE_EDID_
 #include "xf86.h"
 #include "i830.h"
diff --git a/src/i830_display.c b/src/i830_display.c
index 2fb918a..ef7e832 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -31,6 +31,10 @@
 #endif
 
 #include <unistd.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <math.h>
 
 #include "xf86.h"
 #include "i830.h"
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index cbc9c6b..c762541 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -26,6 +26,9 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
+
+#include <string.h>
+
 #include "xf86.h"
 #include "xf86_OSproc.h"
 #include "compiler.h"
diff-tree 1681fe6bb041385e5aefb11baa9afd1f614abc5b (from 5adb05f0b82ee3a168142d803ab3434f75cf15a3)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Sep 20 09:36:02 2006 +0800

    Revert "fix default tex wrap mode with clamp"
    
    oops, we've set border color to all zero, which should
    give us transparent in RepeatNone case.

diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
index 55d5c94..3bc2c0b 100644
--- a/src/i915_exa_render.c
+++ b/src/i915_exa_render.c
@@ -255,7 +255,7 @@ I915TextureSetup(PicturePtr pPict, Pixma
     I830Ptr pI830 = I830PTR(pScrn);
     CARD32 format, offset, pitch, filter;
     int w, h, i;
-    CARD32 wrap_mode = TEXCOORDMODE_CLAMP_EDGE;
+    CARD32 wrap_mode = TEXCOORDMODE_CLAMP_BORDER;
 
     offset = exaGetPixmapOffset(pPix);
     pitch = exaGetPixmapPitch(pPix);
diff-tree d9db5ec6866555ec13ba3ddabb1516eb45637afa (from parents)
Merge: cbaf3cf74bd420533d299c4113761ec536097e33 e3f4caf40708478ef327b029d0a75944c51ea905
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Tue Sep 19 16:03:04 2006 -0700

    Merge branch 'modesetting-origin' into modesetting

diff-tree 5adb05f0b82ee3a168142d803ab3434f75cf15a3 (from e3ab89b0327ef6ff790ab53bba29c721aef032cd)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Tue Sep 19 17:14:05 2006 +0800

    fix default tex wrap mode with clamp
    
    we don't set any 'default' border color,
    default tex wrap mode should be clamp to edge.

diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
index 3bc2c0b..55d5c94 100644
--- a/src/i915_exa_render.c
+++ b/src/i915_exa_render.c
@@ -255,7 +255,7 @@ I915TextureSetup(PicturePtr pPict, Pixma
     I830Ptr pI830 = I830PTR(pScrn);
     CARD32 format, offset, pitch, filter;
     int w, h, i;
-    CARD32 wrap_mode = TEXCOORDMODE_CLAMP_BORDER;
+    CARD32 wrap_mode = TEXCOORDMODE_CLAMP_EDGE;
 
     offset = exaGetPixmapOffset(pPix);
     pitch = exaGetPixmapPitch(pPix);
diff-tree e3ab89b0327ef6ff790ab53bba29c721aef032cd (from 37429c3ecb97df8faf0f3f56128d7a2b22eb8a5e)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Sep 19 10:27:36 2006 +0800

    shader program fix for component alpha set
    
    If CA is set and blend op needs src alpha, the src
    value is not needed and should be (src.A * mask.X).
    This is found in handling exa magic two pass composite.

diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
index 62b2507..3bc2c0b 100644
--- a/src/i915_exa_render.c
+++ b/src/i915_exa_render.c
@@ -473,15 +473,23 @@ I915EXAPrepareComposite(int op, PictureP
 	if (PICT_FORMAT_A(pMaskPicture->format) == 0)
 	    i915_fs_mov_masked(FS_R1, MASK_W, i915_fs_operand_one());
 
-	/* If component alpha is set in the mask, then we need to provide
-	 * the source alpha component (channelwise multiplication) as the
-	 * output color.  If it isn't set, then we need to provide the
-	 * source value component, which is the multipliction of the source
-	 * by the mask alpha.
+	/* If component alpha is set in the mask and the blend operation
+	 * uses the source alpha, then we know we don't need the source
+	 * value (otherwise we would have hit a fallback earlier), so we
+	 * provide the source alpha (src.A * mask.X) as output color.
+	 * Conversely, if CA is set and we don't need the source alpha, then
+	 * we produce the source value (src.X * mask.X) and the source alpha
+	 * is unused..  Otherwise, we provide the non-CA source value
+	 * (src.X * mask.A).
 	 */
-	if (pMaskPicture->componentAlpha && pDstPicture->format != PICT_a8) {
-	    i915_fs_mul(FS_OC, i915_fs_operand_reg(FS_R0),
-			i915_fs_operand_reg(FS_R1));
+	if (pMaskPicture->componentAlpha) {
+	    if (I915BlendOp[op].src_alpha) {
+		i915_fs_mul(FS_OC, i915_fs_operand(FS_R0, W, W, W, W),
+			    i915_fs_operand_reg(FS_R1));
+	    } else {
+		i915_fs_mul(FS_OC, i915_fs_operand_reg(FS_R0),
+			    i915_fs_operand_reg(FS_R1));
+	    }
 	} else {
 	    i915_fs_mul(FS_OC, i915_fs_operand_reg(FS_R0),
 			i915_fs_operand(FS_R1, W, W, W, W));
diff-tree 37429c3ecb97df8faf0f3f56128d7a2b22eb8a5e (from bd758030a6a59af32f9d73655cb691e018e94a7d)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Tue Sep 19 10:08:31 2006 +0800

    misc cleanup

diff --git a/src/i830_exa.c b/src/i830_exa.c
index c633747..a1c7546 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -197,8 +197,8 @@ I830EXASolid(PixmapPtr pPixmap, int x1, 
 	    OUT_RING(XY_COLOR_BLT_CMD);
 
 	OUT_RING(pI830->BR[13]);
-	OUT_RING((y1 << 16) | x1);
-	OUT_RING((y2 << 16) | x2);
+	OUT_RING((y1 << 16) | (x1 & 0xffff));
+	OUT_RING((y2 << 16) | (x2 & 0xffff));
 	OUT_RING(offset);
 	OUT_RING(pI830->BR[16]);
 	ADVANCE_LP_RING();
@@ -255,12 +255,11 @@ I830EXACopy(PixmapPtr pDstPixmap, int sr
     ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
     int dst_x2, dst_y2;
-    unsigned int src_off, dst_off;
+    unsigned int dst_off;
 
     dst_x2 = dst_x1 + w;
     dst_y2 = dst_y1 + h;
 
-    src_off = pI830->copy_src_off;
     dst_off = exaGetPixmapOffset(pDstPixmap);
 
     {
@@ -278,7 +277,7 @@ I830EXACopy(PixmapPtr pDstPixmap, int sr
 	OUT_RING(dst_off);
 	OUT_RING((src_y1 << 16) | (src_x1 & 0xffff));
 	OUT_RING(pI830->copy_src_pitch);
-	OUT_RING(src_off);
+	OUT_RING(pI830->copy_src_off);
 
 	ADVANCE_LP_RING();
     }
@@ -298,7 +297,6 @@ static void
 IntelEXAComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
 		 int dstX, int dstY, int w, int h)
 {
-	/* should be same like I830Composite */
     ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
     int srcXend, srcYend, maskXend, maskYend;
diff-tree e3f4caf40708478ef327b029d0a75944c51ea905 (from 2b9c87bbf8ee5f7f56631114eb98303cd80e4a48)
Author: Adam Jackson <ajax at benzedrine.nwnk.net>
Date:   Fri Sep 15 13:51:18 2006 -0400

    Add model-specific tweaks for some funky 945GM boards.
    
    For the Aopen Mini-PC, ignore the claimed attached 800x600 LVDS panel.
    Likewise for the Apple Mac Mini, but done slightly differently since it
    shares PCI IDs with the Macbook Pro.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 8464b39..75ea480 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1231,7 +1231,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
    int i, n;
    char *s;
    pointer pVBEModule = NULL;
-   Bool enable, has_lvds;
+   Bool enable, has_lvds, is_apple_945gm = FALSE;
    const char *chipname;
    unsigned int ver;
    char v[5];
@@ -1672,16 +1672,15 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
    if (!i830GetLVDSInfoFromBIOS(pScrn))
       has_lvds = FALSE;
 
-   /* If the panel sequencing, status, and control registers are all zero,
-    * assume there's no panel attached.  This is the case on the Mac mini,
-    * which is an i945GM but has no LVDS.  If we tried to power something on
-    * with zeroed panel sequencing registers, it probably wouldn't be a good
-    * thing anyway.
-    */
-   if (INREG(PP_STATUS) == 0 && INREG(PP_CONTROL) == 0 &&
-       INREG(LVDSPP_ON) == 0 && INREG(LVDSPP_OFF) == 0)
-   {
-      has_lvds = FALSE;
+   /* Blacklist machines with known broken BIOSes */
+   if (pI830->PciInfo->chipType == PCI_CHIP_I945_GM) {
+	if ((pI830->PciInfo->subsysVendor == 0xa0a0) &&
+	    (pI830->PciInfo->subsysCard == 0x0589))  /* aopen mini pc */
+	    has_lvds = FALSE;
+
+	if ((pI830->PciInfo->subsysVendor == 0x8086) &&
+	    (pI830->PciInfo->subsysCard == 0x7270)) /* mini, macbook pro... */
+	    is_apple_945gm = TRUE;
    }
 
    if ((s = xf86GetOptValString(pI830->Options, OPTION_MONITOR_LAYOUT)) &&
@@ -1772,6 +1771,20 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
       pI830->specifiedMonitor = TRUE;
    } else if (I830IsPrimary(pScrn)) {
       /* Choose a default set of outputs to use based on what we've detected. */
+
+      /*
+       * Apple hardware is out to get us.  The macbook pro has a real LVDS
+       * panel, but the mac mini does not, and they have the same device IDs.
+       * We'll distinguish by panel size, on the assumption that Apple isn't
+       * about to make any machines with an 800x600 display.
+       */
+      if (is_apple_945gm && pI830->PanelXRes == 800 && pI830->PanelYRes == 600)
+      {
+	  xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		     "Suspected Mac Mini, ignoring the LFP\n");
+	  has_lvds = FALSE;
+      }
+
       if (has_lvds) {
 	 pI830->MonType2 |= PIPE_LFP;
       }
diff-tree bd758030a6a59af32f9d73655cb691e018e94a7d (from f46c70e877a3432ba23696e1a16d5906183876af)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Sep 14 11:12:03 2006 -0700

    Add a compile flag to enable syncing after each operation in EXA.
    
    This replaces other debug sync options sprinkled around the EXA code.  It
    doesn't change the mis-rendering of text on the 915.

diff --git a/src/i830_exa.c b/src/i830_exa.c
index 6a7028f..c633747 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -41,6 +41,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define DEBUG_I830FALLBACK 1
 #endif
 
+#define ALWAYS_SYNC		1
+
 #ifdef DEBUG_I830FALLBACK
 #define I830FALLBACK(s, arg...)				\
 do {							\
@@ -206,7 +208,11 @@ I830EXASolid(PixmapPtr pPixmap, int x1, 
 static void
 I830EXADoneSolid(PixmapPtr pPixmap)
 {
-    return;
+#if ALWAYS_SYNC
+    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
+
+    I830Sync(pScrn);
+#endif
 }
 
 /**
@@ -281,7 +287,11 @@ I830EXACopy(PixmapPtr pDstPixmap, int sr
 static void
 I830EXADoneCopy(PixmapPtr pDstPixmap)
 {
-    	return;
+#if ALWAYS_SYNC
+    ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
+
+    I830Sync(pScrn);
+#endif
 }
 
 static void
@@ -399,17 +409,16 @@ IntelEXAComposite(PixmapPtr pDst, int sr
 	}
 	ADVANCE_LP_RING();
     }
-#ifdef I830DEBUG
-    ErrorF("sync after 3dprimitive");
-    I830Sync(pScrn);
-#endif
-
 }
 
 static void
 IntelEXADoneComposite(PixmapPtr pDst)
 {
-    return; 
+#if ALWAYS_SYNC
+    ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
+
+    I830Sync(pScrn);
+#endif
 }
 /*
  * TODO:
diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
index cb96898..62b2507 100644
--- a/src/i915_exa_render.c
+++ b/src/i915_exa_render.c
@@ -312,11 +312,6 @@ I915TextureSetup(PicturePtr pPict, Pixma
         is_transform[unit] = FALSE;
     }
 
-#ifdef I830DEBUG
-    ErrorF("try to sync to show any errors...");
-    I830Sync(pScrn);
-#endif
-
     return TRUE;
 }
 
@@ -494,10 +489,5 @@ I915EXAPrepareComposite(int op, PictureP
     }
     FS_END();
 
-#ifdef I830DEBUG
-    ErrorF("try to sync to show any errors...");
-    I830Sync(pScrn);
-#endif
-
     return TRUE;
 }
diff-tree f46c70e877a3432ba23696e1a16d5906183876af (from ce00db054bf0b7f62ff0be312d7e3470141922dc)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Sep 14 10:05:51 2006 -0700

    Add a note on maxX/maxY for the 2D rendering.

diff --git a/src/i830_exa.c b/src/i830_exa.c
index a2382ba..6a7028f 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -452,6 +452,8 @@ I830EXAInit(ScreenPtr pScreen)
 
     pI830->EXADriverPtr->pixmapOffsetAlign = 256;
     pI830->EXADriverPtr->pixmapPitchAlign = 64;
+
+    /* i845 and i945 2D limits rendering to 65536 lines and pitch of 32768. */
     pI830->EXADriverPtr->maxX = 4095;
     pI830->EXADriverPtr->maxY = 4095;
 
diff-tree ce00db054bf0b7f62ff0be312d7e3470141922dc (from 71c2dd63361be9616c77db80a93445307d63dd41)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Sep 14 10:00:06 2006 -0700

    Replace a couple of mis-uses of the screen's bpp when the pixmap's was needed.

diff --git a/src/i830_exa.c b/src/i830_exa.c
index 4009327..a2382ba 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -229,7 +229,7 @@ I830EXAPrepareCopy(PixmapPtr pSrcPixmap,
     pI830->BR[13] = exaGetPixmapPitch(pDstPixmap);
     pI830->BR[13] |= I830CopyROP[alu] << 16;
 
-    switch (pScrn->bitsPerPixel) {
+    switch (pSrcPixmap->drawable.bitsPerPixel) {
     case 8:
 	break;
     case 16:
@@ -260,7 +260,7 @@ I830EXACopy(PixmapPtr pDstPixmap, int sr
     {
 	BEGIN_LP_RING(8);
 
-	if (pScrn->bitsPerPixel == 32)
+	if (pDstPixmap->drawable.bitsPerPixel == 32)
 	    OUT_RING(XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
 		     XY_SRC_COPY_BLT_WRITE_RGB);
 	else
diff-tree 71c2dd63361be9616c77db80a93445307d63dd41 (from 59ce4180b95270432540624a1fdf7ae8dd18a7f3)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Sep 14 09:54:19 2006 -0700

    Replace duplicated sync code in exa with a call to I830Sync.
    
    The I830Sync version has additional code for the 965.

diff --git a/src/i830_exa.c b/src/i830_exa.c
index 2bab0c7..4009327 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -123,38 +123,16 @@ extern Bool I915EXAPrepareComposite(int,
  * @pScreen: current screen
  * @marker: marker command to wait for
  *
- * Wait for the command specified by @marker to finish, then return.
+ * Wait for the command specified by @marker to finish, then return.  We don't
+ * actually do marker waits, though we might in the future.  For now, just
+ * wait for a full idle.
  */
 static void
 I830EXASync(ScreenPtr pScreen, int marker)
 {
     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-    I830Ptr pI830 = I830PTR(pScrn);
-
-#ifdef XF86DRI
-    /* VT switching tries to do this. */
-    if (!pI830->LockHeld && pI830->directRenderingEnabled)
-	return;
-#endif
-
-    if (pI830->entityPrivate && !pI830->entityPrivate->RingRunning)
-	return;
-
-    /* Send a flush instruction and then wait till the ring is empty.
-     * This is stronger than waiting for the blitter to finish as it also
-     * flushes the internal graphics caches.
-     */
-    {
-	BEGIN_LP_RING(2);
-	OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
-	OUT_RING(MI_NOOP);		/* pad to quadword */
-	ADVANCE_LP_RING();
-    }
 
-    I830WaitLpRing(pScrn, pI830->LpRing->mem.Size - 8, 0);
-
-    pI830->LpRing->space = pI830->LpRing->mem.Size - 8;
-    pI830->nextColorExpandBuf = 0;
+    I830Sync(pScrn);
 }
 
 /**
diff-tree 59ce4180b95270432540624a1fdf7ae8dd18a7f3 (from 2b7602847aa7ae9b4e88fbea070710695d2cb8a4)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Mon Sep 11 22:57:23 2006 +0800

    reimplement Solid function
    
    Replace COLOR_BLT_CMD with XY_COLOR_BLT_CMD, by which
    device would care for direction and provide a (x,y) coord
    interface. This fixes pixmap artifacts even in no composite
    case.

diff --git a/src/i830_exa.c b/src/i830_exa.c
index 2544760..2bab0c7 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -159,9 +159,6 @@ I830EXASync(ScreenPtr pScreen, int marke
 
 /**
  * I830EXAPrepareSolid - prepare for a Solid operation, if possible
- *
- * TODO:
- *   - support planemask using FILL_MONO_SRC_BLT_CMD?
  */
 static Bool
 I830EXAPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
@@ -173,6 +170,9 @@ I830EXAPrepareSolid(PixmapPtr pPixmap, i
     if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planemask))
 	I830FALLBACK("planemask is not solid");
 
+    if (pPixmap->drawable.bitsPerPixel == 24)
+	I830FALLBACK("solid 24bpp unsupported!\n");
+
     offset = exaGetPixmapOffset(pPixmap);
     pitch = exaGetPixmapPitch(pPixmap);
 
@@ -181,25 +181,21 @@ I830EXAPrepareSolid(PixmapPtr pPixmap, i
     if ( pitch % pI830->EXADriverPtr->pixmapPitchAlign != 0)
 	I830FALLBACK("pixmap pitch not aligned");
 
-    pI830->BR[13] = pitch;
-    pI830->BR[13] |= I830PatternROP[alu] << 16;
-
-    pI830->BR[16] = fg;
-
-    /*
-     * Depth: 00 - 8 bit, 01 - 16 bit, 10 - 24 bit, 11 - 32 bit
-     */
-    switch (pScrn->bitsPerPixel) {
-    case 8:
-	pI830->BR[13] |= ((0 << 25) | (0 << 24));
-	break;
-    case 16:
-	pI830->BR[13] |= ((0 << 25) | (1 << 24));
-	break;
-    case 32:
-	pI830->BR[13] |= ((1 << 25) | (1 << 24));
-	break;
+    pI830->BR[13] = (pitch & 0xffff);
+    switch (pPixmap->drawable.bitsPerPixel) {
+	case 8:
+	    break;
+	case 16:
+	    /* RGB565 */
+	    pI830->BR[13] |= (1 << 24);
+	    break;
+	case 32:
+	    /* RGB8888 */
+	    pI830->BR[13] |= ((1 << 24) | (1 << 25));
+	    break;
     }
+    pI830->BR[13] |= (I830PatternROP[alu] & 0xff) << 16 ;
+    pI830->BR[16] = fg;
     return TRUE;
 }
 
@@ -208,32 +204,23 @@ I830EXASolid(PixmapPtr pPixmap, int x1, 
 {
     ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
-    int h, w;
     unsigned long offset;
 
-    /* pixmap's offset and pitch is aligned, 
-       otherwise it falls back in PrepareSolid */
-    offset = exaGetPixmapOffset(pPixmap) + y1 * exaGetPixmapPitch(pPixmap) +
-	x1 * (pPixmap->drawable.bitsPerPixel / 8);
+    offset = exaGetPixmapOffset(pPixmap);  
     
-    h = y2 - y1;
-    w = x2 - x1;
-
     {
 	BEGIN_LP_RING(6);
-
-	if (pScrn->bitsPerPixel == 32)
-	    OUT_RING(COLOR_BLT_CMD | COLOR_BLT_WRITE_ALPHA |
-		     COLOR_BLT_WRITE_RGB);
+	if (pPixmap->drawable.bitsPerPixel == 32)
+	    OUT_RING(XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA
+			| XY_COLOR_BLT_WRITE_RGB);
 	else
-	    OUT_RING(COLOR_BLT_CMD);
+	    OUT_RING(XY_COLOR_BLT_CMD);
 
 	OUT_RING(pI830->BR[13]);
-	OUT_RING((h << 16) | (w * (pPixmap->drawable.bitsPerPixel/8)));
+	OUT_RING((y1 << 16) | x1);
+	OUT_RING((y2 << 16) | x2);
 	OUT_RING(offset);
 	OUT_RING(pI830->BR[16]);
-	OUT_RING(0);
-
 	ADVANCE_LP_RING();
     }
 }
diff-tree 2b9c87bbf8ee5f7f56631114eb98303cd80e4a48 (from 6f0d352b83fc9f39dd86edbda9af83243b50c764)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Sep 8 11:14:05 2006 -0700

    Remove xf86_ansic.h usage.

diff --git a/src/i830_bios.c b/src/i830_bios.c
index 4b87351..556f57b 100644
--- a/src/i830_bios.c
+++ b/src/i830_bios.c
@@ -31,7 +31,6 @@
 
 #define _PARSE_EDID_
 #include "xf86.h"
-#include "xf86_ansic.h"
 #include "i830.h"
 #include "i830_bios.h"
 #include "edid.h"
diff --git a/src/i830_debug.c b/src/i830_debug.c
index e2a28b2..a48e9f2 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -30,7 +30,6 @@
 #endif
 
 #include "xf86.h"
-#include "xf86_ansic.h"
 #include "i830.h"
 #include "i830_debug.h"
 
diff --git a/src/i830_display.c b/src/i830_display.c
index 6eb2a33..2fb918a 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -30,8 +30,9 @@
 #include "config.h"
 #endif
 
+#include <unistd.h>
+
 #include "xf86.h"
-#include "xf86_ansic.h"
 #include "i830.h"
 #include "i830_bios.h"
 #include "i830_display.h"
diff --git a/src/i830_i2c.c b/src/i830_i2c.c
index fa0ca30..cee7bb5 100644
--- a/src/i830_i2c.c
+++ b/src/i830_i2c.c
@@ -30,7 +30,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #endif
 
 #include "xf86.h"
-#include "xf86_ansic.h"
 #include "xf86_OSproc.h"
 #include "xf86Resources.h"
 #include "xf86RAC.h"
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index fe0c41a..cbc9c6b 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -27,7 +27,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "config.h"
 #endif
 #include "xf86.h"
-#include "xf86_ansic.h"
 #include "xf86_OSproc.h"
 #include "compiler.h"
 #include "i830.h"
diff-tree 2b7602847aa7ae9b4e88fbea070710695d2cb8a4 (from parents)
Merge: e4cdc42a98dd1be74e5c2bf5d9566f7449523b14 b45f4b54b189a496255ddae12af38fc4c4408a51
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Sep 8 11:02:41 2006 -0700

    Merge branch 'exa-origin' into exa
    
    Conflicts:
    
    	src/i915_exa_render.c

diff-tree e4cdc42a98dd1be74e5c2bf5d9566f7449523b14 (from 099be52a3bb52516fb5e8d56c154a4d6b6707e09)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Sep 7 10:32:02 2006 -0700

    Remove another debug printf.

diff --git a/src/i830_exa.c b/src/i830_exa.c
index 1074649..230c8a7 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -339,7 +339,6 @@ IntelEXAComposite(PixmapPtr pDst, int sr
 	    scale_units[1][0], scale_units[1][1]);
 
     if (scale_units[1][0] == -1 || scale_units[1][1] == -1) {
-	ErrorF("mask is null\n");
 	pMask = 0;
     }
 
diff-tree 099be52a3bb52516fb5e8d56c154a4d6b6707e09 (from 4ad577f83f7190df4d64e66fbf7c515ee6f411ce)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Sep 7 10:28:09 2006 -0700

    Re-remove xf86_ansic.h, and move copyright to the top of the file.

diff --git a/src/i830_exa.c b/src/i830_exa.c
index 0829c34..1074649 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -31,7 +31,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "config.h"
 #endif
 
-#include "xf86_ansic.h"
 #include "xf86.h"
 #include "xaarop.h"
 #include "i830.h"
diff --git a/src/i830_xaa.c b/src/i830_xaa.c
index 9f3a391..d4cc743 100644
--- a/src/i830_xaa.c
+++ b/src/i830_xaa.c
@@ -1,17 +1,3 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "xf86_ansic.h"
-#include "xf86.h"
-#include "xaarop.h"
-#include "i830.h"
-#include "i810_reg.h"
-
-#ifndef DO_SCANLINE_IMAGE_WRITE
-#define DO_SCANLINE_IMAGE_WRITE 0
-#endif
-
 /**************************************************************************
 
 Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
@@ -58,6 +44,19 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
  *
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "xaarop.h"
+#include "i830.h"
+#include "i810_reg.h"
+
+#ifndef DO_SCANLINE_IMAGE_WRITE
+#define DO_SCANLINE_IMAGE_WRITE 0
+#endif
+
 /* I830 Accel Functions */
 static void I830SetupForMono8x8PatternFill(ScrnInfoPtr pScrn,
 					   int pattx, int patty,
diff-tree 4ad577f83f7190df4d64e66fbf7c515ee6f411ce (from c378328ece701756ddca966eb108e2b1f5c3ed6c)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Sep 7 10:24:23 2006 -0700

    Remove the UTS/DFS implementations that just match the fallback versions.

diff --git a/src/i830_exa.c b/src/i830_exa.c
index bb75b24..0829c34 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -112,11 +112,6 @@ union intfloat {
 Bool is_transform[2];
 PictTransform *transform[2];
 
-Bool i830UploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, 
-			    char *src, int src_pitch);
-Bool i830DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h,
-			    char *dst, int dst_pitch);
-
 extern Bool I830EXACheckComposite(int, PicturePtr, PicturePtr, PicturePtr);
 extern Bool I830EXAPrepareComposite(int, PicturePtr, PicturePtr, PicturePtr, 
 				PixmapPtr, PixmapPtr, PixmapPtr);
@@ -325,61 +320,6 @@ I830EXADoneCopy(PixmapPtr pDstPixmap)
     	return;
 }
 
-static Bool
-I830EXAUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, 
-		char *src, int src_pitch)
-{
-    ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
-    I830Ptr pI830 = I830PTR(pScrn);
-    int dst_pitch = exaGetPixmapPitch(pDst);
-    int dst_offset = exaGetPixmapOffset(pDst);
-    unsigned char *dst;
-
-    I830Sync(pScrn);
-
-#ifdef I830DEBUG
-    ErrorF("Up->Screen: dst offset 0x%x, dst pitch %d, x %d, y %d, src %p, src pitch %d\n",
-		dst_offset, dst_pitch, x, y, src, src_pitch);
-#endif
-    dst = pI830->FbBase + dst_offset + y*dst_pitch + 
-		x* (pDst->drawable.bitsPerPixel/8);
-    w *= pDst->drawable.bitsPerPixel/8;
-    while(h--) {
-	memcpy(dst, src, w);
-	src += src_pitch;
-	dst += dst_pitch;
-    }
-
-    return TRUE;
-}
-
-static Bool
-I830EXADownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h,
-			  char *dst, int dst_pitch)
-{
-    ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum];
-    I830Ptr pI830 = I830PTR(pScrn);
-    int src_pitch = exaGetPixmapPitch(pSrc);
-    int src_offset = exaGetPixmapOffset(pSrc);
-    unsigned char *src = pI830->FbBase + src_offset + y*src_pitch +
-		x*(pSrc->drawable.bitsPerPixel/8);
-
-    I830Sync(pScrn);
-
-#ifdef I830DEBUG
-    ErrorF("Screen->Mem: src offset 0x%x, src %p, src pitch %d, x %d, y %d, dst %p, dst_pitch %d\n",
-	src_offset, src, src_pitch, x, y, dst, dst_pitch);
-#endif
-    w *= pSrc->drawable.bitsPerPixel/8;
-    while(h--) {
-	memcpy(dst, src, w);
-	src += src_pitch;
-	dst += dst_pitch;
-    }
-
-    return TRUE;
-}
-
 static void
 IntelEXAComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
 		 int dstX, int dstY, int w, int h)
@@ -578,10 +518,6 @@ I830EXAInit(ScreenPtr pScreen)
     	pI830->EXADriverPtr->DoneComposite = IntelEXADoneComposite;
     }
 
-    /* Upload, download to/from Screen, experimental!! */
-    pI830->EXADriverPtr->UploadToScreen = I830EXAUploadToScreen;
-    pI830->EXADriverPtr->DownloadFromScreen = I830EXADownloadFromScreen;
-
     if(!exaDriverInit(pScreen, pI830->EXADriverPtr)) {
 	xfree(pI830->EXADriverPtr);
 	pI830->noAccel = TRUE;
diff-tree c378328ece701756ddca966eb108e2b1f5c3ed6c (from 7458a6adb5ea62f56bb3d4ab19ad7d1aa6ad2d19)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Sep 6 11:15:17 2006 -0700

    Remove a debug printf.

diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
index 90240b8..ef3cf2a 100644
--- a/src/i915_exa_render.c
+++ b/src/i915_exa_render.c
@@ -330,8 +330,6 @@ I915EXAPrepareComposite(int op, PictureP
     CARD32 dst_format, dst_offset, dst_pitch;
     CARD32 blendctl;
 
-    ErrorF("i915 prepareComposite\n");
-
     I915GetDestFormat(pDstPicture, &dst_format);
     dst_offset = exaGetPixmapOffset(pDst);
     dst_pitch = exaGetPixmapPitch(pDst);
diff-tree cbaf3cf74bd420533d299c4113761ec536097e33 (from 421b415e23c1ddc78837cd222167d6ed71a3ef88)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Aug 31 18:25:21 2006 -0700

    verbose debug message for panel sync data

diff --git a/src/i830_bios.c b/src/i830_bios.c
index 4b87351..b68c467 100644
--- a/src/i830_bios.c
+++ b/src/i830_bios.c
@@ -210,7 +210,13 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScr
 	    pI830->panel_fixed_vblank = _V_BLANK(timing_ptr);
 	    pI830->panel_fixed_vsyncoff = _V_SYNC_OFF(timing_ptr);
 	    pI830->panel_fixed_vsyncwidth = _V_SYNC_WIDTH(timing_ptr);
-
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		       "Panel mode h active %d blank %d rate %f v active %d blank %d rate %f\n",
+		       pI830->panel_fixed_hactive, pI830->panel_fixed_hblank,
+		       (double) pI830->panel_fixed_clock / (pI830->panel_fixed_hactive + pI830->panel_fixed_hblank),
+		       pI830->panel_fixed_vactive, pI830->panel_fixed_vblank,
+		       (double) pI830->panel_fixed_clock / 
+		       ((pI830->panel_fixed_hactive + pI830->panel_fixed_hblank) * (pI830->panel_fixed_vactive + pI830->panel_fixed_vblank)));
 	    found_panel_info = TRUE;
 	    break;
 	}
diff-tree b45f4b54b189a496255ddae12af38fc4c4408a51 (from cc79b3ec19a7e858972228a270ef774041eb8946)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Fri Aug 25 16:23:18 2006 +0800

    Making render log a little quiet in normal

diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
index 90240b8..cb96898 100644
--- a/src/i915_exa_render.c
+++ b/src/i915_exa_render.c
@@ -330,7 +330,9 @@ I915EXAPrepareComposite(int op, PictureP
     CARD32 dst_format, dst_offset, dst_pitch;
     CARD32 blendctl;
 
-    ErrorF("i915 prepareComposite\n");
+#ifdef I830DEBUG
+    ErrorF("Enter i915 prepareComposite\n");
+#endif
 
     I915GetDestFormat(pDstPicture, &dst_format);
     dst_offset = exaGetPixmapOffset(pDst);
diff-tree 6f0d352b83fc9f39dd86edbda9af83243b50c764 (from 421b415e23c1ddc78837cd222167d6ed71a3ef88)
Author: Ross Burton <ross at burtonini.com>
Date:   Thu Aug 24 18:16:42 2006 -0700

    Bug #7957: Fix distcheck.

diff --git a/src/Makefile.am b/src/Makefile.am
index 50d0ad1..71ae2f2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -32,6 +32,7 @@ i810_drv_ladir = @moduledir@/drivers
 
 i810_drv_la_SOURCES = \
          common.h \
+	 i2c_vid.h \
          i810_accel.c \
          i810_common.h \
          i810_cursor.c \
@@ -65,6 +66,8 @@ i810_drv_la_SOURCES = \
          i830_rotate.c \
 	 i830_randr.c \
 	 i830_sdvo.c \
+	 i830_sdvo.h \
+	 i830_sdvo_regs.h \
 	 i830_xf86Modes.h \
 	 i830_xf86Modes.c
 if DRI
diff-tree cc79b3ec19a7e858972228a270ef774041eb8946 (from 078af29fa65653c5322b006404f7ad29aec24cce)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Thu Aug 24 10:28:59 2006 +0800

    Current 915 render operations for 915G/945G only

diff --git a/src/i830_exa.c b/src/i830_exa.c
index bb75b24..c2d3303 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -566,12 +566,14 @@ I830EXAInit(ScreenPtr pScreen)
     pI830->EXADriverPtr->DoneCopy = I830EXADoneCopy;
 
     /* Composite */
-    if (IS_I9XX(pI830)) {   		
+    if (IS_I915G(pI830) || IS_I915GM(pI830) || 
+	IS_I945G(pI830) || IS_I945GM(pI830)) {   		
 	pI830->EXADriverPtr->CheckComposite = I915EXACheckComposite;
    	pI830->EXADriverPtr->PrepareComposite = I915EXAPrepareComposite;
     	pI830->EXADriverPtr->Composite = IntelEXAComposite;
     	pI830->EXADriverPtr->DoneComposite = IntelEXADoneComposite;
-    } else if (IS_I865G(pI830) || IS_I855(pI830) || IS_845G(pI830) || IS_I830(pI830)) { 
+    } else if (IS_I865G(pI830) || IS_I855(pI830) || 
+	IS_845G(pI830) || IS_I830(pI830)) { 
     	pI830->EXADriverPtr->CheckComposite = I830EXACheckComposite;
     	pI830->EXADriverPtr->PrepareComposite = I830EXAPrepareComposite;
     	pI830->EXADriverPtr->Composite = IntelEXAComposite;
diff-tree 078af29fa65653c5322b006404f7ad29aec24cce (from parents)
Merge: 7458a6adb5ea62f56bb3d4ab19ad7d1aa6ad2d19 ea63e82ef417a9918e7d7105910a8ddeba2994f6
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Thu Aug 24 10:23:22 2006 +0800

    Merge branch 'master' into exa
    
    Conflicts:
    
    	man/i810.man
    	src/Makefile.am
    	src/i830_accel.c
    	src/i830_dga.c
    	src/i830_driver.c

diff --cc src/Makefile.am
index c2e49ac,63370ab..e58350c
@@@ -60,10 -64,7 +64,11 @@@
  	 i915_3d.c \
  	 i915_3d.h \
  	 i915_reg.h \
 -	 i915_video.c
++	 i915_video.c \
 +	 i830_exa.c \
 +	 i830_xaa.c \
 +	 i830_exa_render.c \
 +	 i915_exa_render.c
  
  if DRI
  i810_drv_la_SOURCES += \
diff --cc src/i830.h
index 777ffd3,38a880f..df1c171
@@@ -68,17 -70,13 +70,22 @@@
  #include "i830_dri.h"
  #endif
  
 +#ifdef I830_USE_EXA
 +#include "exa.h"
 +Bool I830EXAInit(ScreenPtr pScreen);
 +#endif
 +
 +#ifdef I830_USE_XAA
 +Bool I830XAAInit(ScreenPtr pScreen);
 +#endif
 +
  #include "common.h"
  
+ #define NEED_REPLIES				/* ? */
+ #define EXTENSION_PROC_ARGS void *
+ #include "extnsionst.h" 			/* required */
+ #include <X11/extensions/panoramiXproto.h> 	/* required */
+ 
  /* I830 Video BIOS support */
  
  /*
diff --cc src/i830_driver.c
index ed85585,c0d9672..10a329c
@@@ -3712,27 -5638,25 +5711,34 @@@
        pI830->entityPrivate->RingRunning = 0;
  
     /* Reset the fence registers to 0 */
-    for (i = 0; i < 8; i++)
-       OUTREG(FENCE + i * 4, 0);
+    if (IS_I965G(pI830)) {
+       for (i = 0; i < FENCE_NEW_NR; i++) {
+ 	 OUTREG(FENCE_NEW + i * 8, 0);
+ 	 OUTREG(FENCE_NEW + 4 + i * 8, 0);
+       }
+    } else {
+       for (i = 0; i < FENCE_NR; i++)
+          OUTREG(FENCE + i * 4, 0);
+    }
 -
     /* Flush the ring buffer (if enabled), then disable it. */
 -   if (pI830->AccelInfoRec != NULL && flush) {
 -      temp = INREG(LP_RING + RING_LEN);
 -      if (temp & 1) {
 -	 I830RefreshRing(pScrn);
 -	 I830Sync(pScrn);
 -	 DO_RING_IDLE();
 -      }
 -   }
 +   /* God this is ugly */
 +#define flush_ring() do { \
 +      temp = INREG(LP_RING + RING_LEN); \
 +      if (temp & 1) { \
 +	 I830RefreshRing(pScrn); \
 +	 I830Sync(pScrn); \
 +	 DO_RING_IDLE(); \
 +      } \
 +   } while(0)
 +#ifdef I830_USE_XAA
 +   if (!pI830->useEXA && flush && pI830->AccelInfoRec)
 +       flush_ring();
 +#endif
 +#ifdef I830_USE_XAA
 +   if (pI830->useEXA && flush && pI830->EXADriverPtr)
 +       flush_ring();
 +#endif
 +
     OUTREG(LP_RING + RING_LEN, 0);
     OUTREG(LP_RING + RING_HEAD, 0);
     OUTREG(LP_RING + RING_TAIL, 0);
@@@ -5311,8 -7509,25 +7591,22 @@@
  	   x, pI830->xoffset, y, pI830->yoffset);
  
     /* Sync the engine before adjust frame */
 -   if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
 -      (*pI830->AccelInfoRec->Sync)(pScrn);
 -      pI830->AccelInfoRec->NeedToSync = FALSE;
 -   }
 +   i830WaitSync(pScrn);
  
+    if (pI830->MergedFB) {
+       I830AdjustFrameMerged(scrnIndex, x, y, flags);
+ 
+       if (pI830->pipe == 0) {
+          OUTREG(DSPABASE, pI830->FrontBuffer.Start + ((pI830->FirstframeY0 * pScrn->displayWidth + pI830->FirstframeX0) * pI830->cpp));
+          OUTREG(DSPBBASE, pI830->FrontBuffer.Start + ((pI830->pScrn_2->frameY0 * pScrn->displayWidth + pI830->pScrn_2->frameX0) * pI830->cpp));
+       } else {
+          OUTREG(DSPBBASE, pI830->FrontBuffer.Start + ((pI830->FirstframeY0 * pScrn->displayWidth + pI830->FirstframeX0) * pI830->cpp));
+          OUTREG(DSPABASE, pI830->FrontBuffer.Start + ((pI830->pScrn_2->frameY0 * pScrn->displayWidth + pI830->pScrn_2->frameX0) * pI830->cpp));
+       }
+ 
+       return;
+    }
+ 
     if (I830IsPrimary(pScrn))
        Start = pI830->FrontBuffer.Start;
     else {
diff --cc src/i830_xaa.c
index 9f3a391,0000000..6948be0
mode 100644,000000..100644
@@@ -1,658 -1,0 +1,712 @@@
 +#ifdef HAVE_CONFIG_H
 +#include "config.h"
 +#endif
 +
 +#include "xf86_ansic.h"
 +#include "xf86.h"
 +#include "xaarop.h"
 +#include "i830.h"
 +#include "i810_reg.h"
 +
 +#ifndef DO_SCANLINE_IMAGE_WRITE
 +#define DO_SCANLINE_IMAGE_WRITE 0
 +#endif
 +
 +/**************************************************************************
 +
 +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
 +All Rights Reserved.
 +
 +Permission is hereby granted, free of charge, to any person obtaining a
 +copy of this software and associated documentation files (the
 +"Software"), to deal in the Software without restriction, including
 +without limitation the rights to use, copy, modify, merge, publish,
 +distribute, sub license, and/or sell copies of the Software, and to
 +permit persons to whom the Software is furnished to do so, subject to
 +the following conditions:
 +
 +The above copyright notice and this permission notice (including the
 +next paragraph) shall be included in all copies or substantial portions
 +of the Software.
 +
 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
 +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
 +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 +
 +**************************************************************************/
 +
 +/*
 + * Reformatted with GNU indent (2.2.8), using the following options:
 + *
 + *    -bad -bap -c41 -cd0 -ncdb -ci6 -cli0 -cp0 -ncs -d0 -di3 -i3 -ip3 -l78
 + *    -lp -npcs -psl -sob -ss -br -ce -sc -hnl
 + *
 + * This provides a good match with the original i810 code and preferred
 + * XFree86 formatting conventions.
 + *
 + * When editing this driver, please follow the existing formatting, and edit
 + * with <TAB> characters expanded at 8-column intervals.
 + */
 +
 +/*
 + * Authors:
 + *   Keith Whitwell <keith at tungstengraphics.com>
 + *
 + */
 +
 +/* I830 Accel Functions */
 +static void I830SetupForMono8x8PatternFill(ScrnInfoPtr pScrn,
 +					   int pattx, int patty,
 +					   int fg, int bg, int rop,
 +					   unsigned int planemask);
 +static void I830SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn,
 +						 int pattx, int patty,
 +						 int x, int y, int w, int h);
 +
 +static void I830SetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
 +							   int fg, int bg,
 +							   int rop,
 +							   unsigned int mask);
 +
 +static void I830SubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr
 +							     pScrn, int x,
 +							     int y, int w,
 +							     int h,
 +							     int skipleft);
 +
 +static void I830SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno);
 +
 +#if DO_SCANLINE_IMAGE_WRITE
 +static void I830SetupForScanlineImageWrite(ScrnInfoPtr pScrn, int rop,
 +					   unsigned int planemask,
 +					   int trans_color, int bpp,
 +					   int depth);
 +static void I830SubsequentScanlineImageWriteRect(ScrnInfoPtr pScrn,
 +						 int x, int y, int w, int h,
 +						 int skipleft);
 +static void I830SubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno);
 +#endif
 +static void I830RestoreAccelState(ScrnInfoPtr pScrn);
 +
 +#ifdef I830_USE_EXA
 +extern const int I830PatternROP[16];
 +extern const int I830CopyROP[16];
 +#endif
 +
 +Bool
 +I830XAAInit(ScreenPtr pScreen)
 +{
 +    XAAInfoRecPtr infoPtr;
 +    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
 +    I830Ptr pI830 = I830PTR(pScrn);
 +    int i;
 +    int width = 0;
 +    int nr_buffers = 0;
 +    unsigned char *ptr = NULL;
 +
 +    if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
 +	ErrorF("I830XAAInit\n");
 +
 +    pI830->AccelInfoRec = infoPtr = XAACreateInfoRec();
 +    if (!infoPtr)
 +	return FALSE;
 +
 +    pI830->bufferOffset = 0;
 +    infoPtr->Flags = LINEAR_FRAMEBUFFER | OFFSCREEN_PIXMAPS | PIXMAP_CACHE;
 +
 +    /* Use the same sync function as the I830.
 +     */
 +    infoPtr->Sync = I830Sync;
 +
 +    /* Everything else is different enough to justify different functions */
 +    {
 +	infoPtr->SolidFillFlags = NO_PLANEMASK;
 +	infoPtr->SetupForSolidFill = I830SetupForSolidFill;
 +	infoPtr->SubsequentSolidFillRect = I830SubsequentSolidFillRect;
 +    }
 +
 +    {
 +	infoPtr->ScreenToScreenCopyFlags = (NO_PLANEMASK | NO_TRANSPARENCY);
 +
 +	infoPtr->SetupForScreenToScreenCopy = I830SetupForScreenToScreenCopy;
 +	infoPtr->SubsequentScreenToScreenCopy =
 +	    I830SubsequentScreenToScreenCopy;
 +    }
 +
 +    {
 +	infoPtr->SetupForMono8x8PatternFill = I830SetupForMono8x8PatternFill;
 +	infoPtr->SubsequentMono8x8PatternFillRect =
 +	    I830SubsequentMono8x8PatternFillRect;
 +
 +	infoPtr->Mono8x8PatternFillFlags = (HARDWARE_PATTERN_PROGRAMMED_BITS |
 +					    HARDWARE_PATTERN_SCREEN_ORIGIN |
 +					    HARDWARE_PATTERN_PROGRAMMED_ORIGIN|
 +					    BIT_ORDER_IN_BYTE_MSBFIRST |
 +					    NO_PLANEMASK);
 +
 +    }
 +
 +    /* On the primary screen */
 +    if (pI830->init == 0) {
 +	if (pI830->Scratch.Size != 0) {
 +	    width = ((pScrn->displayWidth + 31) & ~31) / 8;
 +	    nr_buffers = pI830->Scratch.Size / width;
 +	    ptr = pI830->FbBase + pI830->Scratch.Start;
 +	}
 +    } else {
 +	/* On the secondary screen */
 +	I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
 +	if (pI8301->Scratch2.Size != 0) {
 +	    width = ((pScrn->displayWidth + 31) & ~31) / 8;
 +	    nr_buffers = pI8301->Scratch2.Size / width;
 +	    /* We have to use the primary screen's FbBase, as that's where
 +	     * we allocated Scratch2, so we get the correct pointer */
 +	    ptr = pI8301->FbBase + pI8301->Scratch2.Start;
 +	}
 +    }
 +
 +    if (nr_buffers) {
 +	pI830->NumScanlineColorExpandBuffers = nr_buffers;
 +	pI830->ScanlineColorExpandBuffers = (unsigned char **)
 +	    xnfcalloc(nr_buffers, sizeof(unsigned char *));
 +
 +	for (i = 0; i < nr_buffers; i++, ptr += width)
 +	    pI830->ScanlineColorExpandBuffers[i] = ptr;
 +
 +	infoPtr->ScanlineCPUToScreenColorExpandFillFlags =
 +	    (NO_PLANEMASK | ROP_NEEDS_SOURCE | BIT_ORDER_IN_BYTE_MSBFIRST);
 +
 +	infoPtr->ScanlineColorExpandBuffers = (unsigned char **)
 +	    xnfcalloc(1, sizeof(unsigned char *));
 +	infoPtr->NumScanlineColorExpandBuffers = 1;
 +
 +	infoPtr->ScanlineColorExpandBuffers[0] =
 +	    pI830->ScanlineColorExpandBuffers[0];
 +	pI830->nextColorExpandBuf = 0;
 +
 +	infoPtr->SetupForScanlineCPUToScreenColorExpandFill =
 +	    I830SetupForScanlineCPUToScreenColorExpandFill;
 +
 +	infoPtr->SubsequentScanlineCPUToScreenColorExpandFill =
 +	    I830SubsequentScanlineCPUToScreenColorExpandFill;
 +
 +	infoPtr->SubsequentColorExpandScanline =
 +	    I830SubsequentColorExpandScanline;
 +
 +#if DO_SCANLINE_IMAGE_WRITE
 +	infoPtr->NumScanlineImageWriteBuffers = 1;
 +	infoPtr->ScanlineImageWriteBuffers =
 +	    infoPtr->ScanlineColorExpandBuffers;
 +	infoPtr->SetupForScanlineImageWrite = I830SetupForScanlineImageWrite;
 +	infoPtr->SubsequentScanlineImageWriteRect =
 +	    I830SubsequentScanlineImageWriteRect;
 +	infoPtr->SubsequentImageWriteScanline =
 +	    I830SubsequentImageWriteScanline;
 +	infoPtr->ScanlineImageWriteFlags = NO_GXCOPY |
 +	    NO_PLANEMASK |
 +	    ROP_NEEDS_SOURCE |
 +	    SCANLINE_PAD_DWORD;
 +#endif
 +    }
 +
 +    {
 +	Bool shared_accel = FALSE;
 +	int i;
 +
 +	for(i = 0; i < pScrn->numEntities; i++) {
 +	    if(xf86IsEntityShared(pScrn->entityList[i]))
 +		shared_accel = TRUE;
 +	}
 +	if(shared_accel == TRUE)
 +	    infoPtr->RestoreAccelState = I830RestoreAccelState;
 +    }
 +
 +    I830SelectBuffer(pScrn, I830_SELECT_FRONT);
 +
 +    return XAAInit(pScreen, infoPtr);
 +}
 +
++#ifdef XF86DRI
++static unsigned int
++CheckTiling(ScrnInfoPtr pScrn)
++{
++   I830Ptr pI830 = I830PTR(pScrn);
++   unsigned int tiled = 0;
++
++    /* Check tiling */
++   if (IS_I965G(pI830)) {
++      if (pI830->bufferOffset == pScrn->fbOffset && pI830->front_tiled == FENCE_XMAJOR)
++         tiled = 1;
++      if (pI830->bufferOffset == pI830->RotatedMem.Start && pI830->rotated_tiled == FENCE_XMAJOR)
++         tiled = 1;
++      if (pI830->bufferOffset == pI830->BackBuffer.Start && pI830->back_tiled == FENCE_XMAJOR)
++         tiled = 1;
++      /* not really supported as it's always YMajor tiled */
++      if (pI830->bufferOffset == pI830->DepthBuffer.Start && pI830->depth_tiled == FENCE_XMAJOR)
++         tiled = 1;
++   }
++
++   return tiled;
++}
++#else
++#define CheckTiling(pScrn) 0
++#endif
++
 +void
 +I830SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
 +		      unsigned int planemask)
 +{
 +    I830Ptr pI830 = I830PTR(pScrn);
 +
 +    if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
 +	ErrorF("I830SetupForFillRectSolid color: %x rop: %x mask: %x\n",
 +	       color, rop, planemask);
 +
 +#ifdef I830_USE_EXA
 +    /* This function gets used by I830DRIInitBuffers(), and we might not have
 +     * XAAGetPatternROP() available.  So just use the ROPs from our EXA code
 +     * if available.
 +     */
 +    pI830->BR[13] = ((I830PatternROP[rop] << 16) |
 +		     (pScrn->displayWidth * pI830->cpp));
 +#else
 +    pI830->BR[13] = ((XAAGetPatternROP(rop) << 16) |
 +		     (pScrn->displayWidth * pI830->cpp));
 +#endif
 +
 +    pI830->BR[16] = color;
 +
 +    switch (pScrn->bitsPerPixel) {
 +    case 8:
 +	break;
 +    case 16:
 +	pI830->BR[13] |= (1 << 24);
 +	break;
 +    case 32:
 +	pI830->BR[13] |= ((1 << 25) | (1 << 24));
 +	break;
 +    }
 +}
 +
 +void
 +I830SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h)
 +{
 +    I830Ptr pI830 = I830PTR(pScrn);
 +
 +    if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
 +	ErrorF("I830SubsequentFillRectSolid %d,%d %dx%d\n", x, y, w, h);
 +
 +    {
 +	BEGIN_LP_RING(6);
 +
 +	if (pScrn->bitsPerPixel == 32) {
 +	    OUT_RING(COLOR_BLT_CMD | COLOR_BLT_WRITE_ALPHA |
 +		     COLOR_BLT_WRITE_RGB);
 +	} else {
 +	    OUT_RING(COLOR_BLT_CMD);
 +	}
 +	OUT_RING(pI830->BR[13]);
 +	OUT_RING((h << 16) | (w * pI830->cpp));
 +	OUT_RING(pI830->bufferOffset + (y * pScrn->displayWidth + x) *
 +		 pI830->cpp);
 +	OUT_RING(pI830->BR[16]);
 +	OUT_RING(0);
 +
 +	ADVANCE_LP_RING();
 +    }
++
++    if (IS_I965G(pI830))
++      I830EmitFlush(pScrn);
 +}
 +
 +void
 +I830SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop,
 +			       unsigned int planemask, int transparency_color)
 +{
 +    I830Ptr pI830 = I830PTR(pScrn);
 +
 +    if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
 +	ErrorF("I830SetupForScreenToScreenCopy %d %d %x %x %d\n",
 +	       xdir, ydir, rop, planemask, transparency_color);
 +
 +    pI830->BR[13] = (pScrn->displayWidth * pI830->cpp);
 +#ifdef I830_USE_EXA
 +    /* This function gets used by I830DRIInitBuffers(), and we might not have
 +     * XAAGetCopyROP() available.  So just use the ROPs from our EXA code
 +     * if available.
 +     */
 +    pI830->BR[13] |= I830CopyROP[rop] << 16;
 +#else
 +    pI830->BR[13] |= XAAGetCopyROP(rop) << 16;
 +#endif
 +
 +    switch (pScrn->bitsPerPixel) {
 +    case 8:
 +	break;
 +    case 16:
 +	pI830->BR[13] |= (1 << 24);
 +	break;
 +    case 32:
 +	pI830->BR[13] |= ((1 << 25) | (1 << 24));
 +	break;
 +    }
 +
 +}
 +
 +void
 +I830SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int src_x1, int src_y1,
 +				 int dst_x1, int dst_y1, int w, int h)
 +{
 +    I830Ptr pI830 = I830PTR(pScrn);
 +    int dst_x2, dst_y2;
++    unsigned int tiled = CheckTiling(pScrn);
 +
 +    if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
 +	ErrorF("I830SubsequentScreenToScreenCopy %d,%d - %d,%d %dx%d\n",
 +	       src_x1, src_y1, dst_x1, dst_y1, w, h);
 +
 +    dst_x2 = dst_x1 + w;
 +    dst_y2 = dst_y1 + h;
 +
++    if (tiled)
++        pI830->BR[13] = ((pI830->BR[13] & 0xFFFF) >> 2) | 
++					(pI830->BR[13] & 0xFFFF0000);
++
 +    {
 +	BEGIN_LP_RING(8);
 +
 +	if (pScrn->bitsPerPixel == 32) {
 +	    OUT_RING(XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
- 		     XY_SRC_COPY_BLT_WRITE_RGB);
++		     XY_SRC_COPY_BLT_WRITE_RGB | tiled << 15 | tiled << 11);
 +	} else {
- 	    OUT_RING(XY_SRC_COPY_BLT_CMD);
++	    OUT_RING(XY_SRC_COPY_BLT_CMD | tiled << 15 | tiled << 11);
 +	}
 +	OUT_RING(pI830->BR[13]);
 +	OUT_RING((dst_y1 << 16) | (dst_x1 & 0xffff));
 +	OUT_RING((dst_y2 << 16) | (dst_x2 & 0xffff));
 +	OUT_RING(pI830->bufferOffset);
 +	OUT_RING((src_y1 << 16) | (src_x1 & 0xffff));
 +	OUT_RING(pI830->BR[13] & 0xFFFF);
 +	OUT_RING(pI830->bufferOffset);
 +
 +	ADVANCE_LP_RING();
 +    }
++
++    if (IS_I965G(pI830))
++      I830EmitFlush(pScrn);
 +}
 +
 +static void
 +I830SetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int pattx, int patty,
 +			       int fg, int bg, int rop,
 +			       unsigned int planemask)
 +{
 +    I830Ptr pI830 = I830PTR(pScrn);
 +
 +    if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
 +	ErrorF("I830SetupForMono8x8PatternFill\n");
 +
 +    pI830->BR[16] = pattx;
 +    pI830->BR[17] = patty;
 +    pI830->BR[18] = bg;
 +    pI830->BR[19] = fg;
 +
 +    pI830->BR[13] = (pScrn->displayWidth * pI830->cpp);	/* In bytes */
 +    pI830->BR[13] |= XAAGetPatternROP(rop) << 16;
 +    if (bg == -1)
 +	pI830->BR[13] |= (1 << 28);
 +
 +    switch (pScrn->bitsPerPixel) {
 +    case 8:
 +	break;
 +    case 16:
 +	pI830->BR[13] |= (1 << 24);
 +	break;
 +    case 32:
 +	pI830->BR[13] |= ((1 << 25) | (1 << 24));
 +	break;
 +    }
 +
 +}
 +
 +static void
 +I830SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int pattx, int patty,
 +				     int x, int y, int w, int h)
 +{
 +    I830Ptr pI830 = I830PTR(pScrn);
 +    int x1, x2, y1, y2;
++    unsigned int tiled = CheckTiling(pScrn);
 +
 +    x1 = x;
 +    x2 = x + w;
 +    y1 = y;
 +    y2 = y + h;
 +
 +    if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
 +	ErrorF("I830SubsequentMono8x8PatternFillRect\n");
 +
++    if (tiled)
++        pI830->BR[13] = ((pI830->BR[13] & 0xFFFF) >> 2) | 
++					(pI830->BR[13] & 0xFFFF0000);
++
 +    {
 +	BEGIN_LP_RING(10);
 +
 +	if (pScrn->bitsPerPixel == 32) {
 +	    OUT_RING(XY_MONO_PAT_BLT_CMD | XY_MONO_PAT_BLT_WRITE_ALPHA |
- 		     XY_MONO_PAT_BLT_WRITE_RGB |
++		     XY_MONO_PAT_BLT_WRITE_RGB | tiled << 11 |
 +		     ((patty << 8) & XY_MONO_PAT_VERT_SEED) |
 +		     ((pattx << 12) & XY_MONO_PAT_HORT_SEED));
 +	} else {
- 	    OUT_RING(XY_MONO_PAT_BLT_CMD |
++	    OUT_RING(XY_MONO_PAT_BLT_CMD | tiled << 11 |
 +		     ((patty << 8) & XY_MONO_PAT_VERT_SEED) |
 +		     ((pattx << 12) & XY_MONO_PAT_HORT_SEED));
 +	}
 +	OUT_RING(pI830->BR[13]);
 +	OUT_RING((y1 << 16) | x1);
 +	OUT_RING((y2 << 16) | x2);
 +	OUT_RING(pI830->bufferOffset);
 +	OUT_RING(pI830->BR[18]);		/* bg */
 +	OUT_RING(pI830->BR[19]);		/* fg */
 +	OUT_RING(pI830->BR[16]);		/* pattern data */
 +	OUT_RING(pI830->BR[17]);
 +	OUT_RING(0);
 +	ADVANCE_LP_RING();
 +    }
++
++    if (IS_I965G(pI830))
++      I830EmitFlush(pScrn);
 +}
 +
 +static void
 +I830GetNextScanlineColorExpandBuffer(ScrnInfoPtr pScrn)
 +{
 +    I830Ptr pI830 = I830PTR(pScrn);
 +    XAAInfoRecPtr infoPtr = pI830->AccelInfoRec;
 +
 +    if (pI830->nextColorExpandBuf == pI830->NumScanlineColorExpandBuffers)
 +	I830Sync(pScrn);
 +
 +    infoPtr->ScanlineColorExpandBuffers[0] =
 +	pI830->ScanlineColorExpandBuffers[pI830->nextColorExpandBuf];
 +
 +    if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
 +	ErrorF("using color expand buffer %d\n", pI830->nextColorExpandBuf);
 +
 +    pI830->nextColorExpandBuf++;
 +}
 +
 +static void
 +I830SetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
 +					       int fg, int bg, int rop,
 +					       unsigned int planemask)
 +{
 +    I830Ptr pI830 = I830PTR(pScrn);
 +
 +    if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
 +	ErrorF("I830SetupForScanlineScreenToScreenColorExpand %d %d %x %x\n",
 +	       fg, bg, rop, planemask);
 +
 +    /* Fill out register values */
 +    pI830->BR[13] = (pScrn->displayWidth * pI830->cpp);
 +    pI830->BR[13] |= XAAGetCopyROP(rop) << 16;
 +    if (bg == -1)
 +	pI830->BR[13] |= (1 << 29);
 +
 +    switch (pScrn->bitsPerPixel) {
 +    case 8:
 +	break;
 +    case 16:
 +	pI830->BR[13] |= (1 << 24);
 +	break;
 +    case 32:
 +	pI830->BR[13] |= ((1 << 25) | (1 << 24));
 +	break;
 +    }
 +
 +    pI830->BR[18] = bg;
 +    pI830->BR[19] = fg;
 +
 +    I830GetNextScanlineColorExpandBuffer(pScrn);
 +}
 +
 +static void
 +I830SubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
 +						 int x, int y,
 +						 int w, int h, int skipleft)
 +{
 +    I830Ptr pI830 = I830PTR(pScrn);
 +
 +    if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
 +	ErrorF("I830SubsequentScanlineCPUToScreenColorExpandFill "
 +	       "%d,%d %dx%x %d\n", x, y, w, h, skipleft);
 +
 +    /* Fill out register values */
 +    pI830->BR[9] = (pI830->bufferOffset +
 +		    (y * pScrn->displayWidth + x) * pI830->cpp);
 +    pI830->BR[11] = ((1 << 16) | w);
 +}
 +
 +static void
 +I830SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno)
 +{
 +    I830Ptr pI830 = I830PTR(pScrn);
++    unsigned int tiled = CheckTiling(pScrn);
 +
 +    if (pI830->init == 0) {
 +	pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] -
 +			 pI830->FbBase);
 +    } else {
 +	I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
 +
 +	/* We have to use the primary screen's FbBase, as that's where
 +	 * we allocated Scratch2, so we get the correct pointer */
 +	pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] -
 +			 pI8301->FbBase);
 +    }
 +
 +    if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
 +	ErrorF("I830SubsequentColorExpandScanline %d (addr %x)\n",
 +	       bufno, pI830->BR[12]);
 +
++    if (tiled)
++        pI830->BR[13] = ((pI830->BR[13] & 0xFFFF) >> 2) | 
++					(pI830->BR[13] & 0xFFFF0000);
++
 +    {
 +	BEGIN_LP_RING(8);
 +
 +	if (pScrn->bitsPerPixel == 32) {
 +	    OUT_RING(XY_MONO_SRC_BLT_CMD | XY_MONO_SRC_BLT_WRITE_ALPHA |
- 		     XY_MONO_SRC_BLT_WRITE_RGB);
++		     tiled << 11 | XY_MONO_SRC_BLT_WRITE_RGB);
 +	} else {
- 	    OUT_RING(XY_MONO_SRC_BLT_CMD);
++	    OUT_RING(XY_MONO_SRC_BLT_CMD | tiled << 11);
 +	}
 +	OUT_RING(pI830->BR[13]);
 +	OUT_RING(0);			/* x1 = 0, y1 = 0 */
 +	OUT_RING(pI830->BR[11]);		/* x2 = w, y2 = 1 */
 +	OUT_RING(pI830->BR[9]);		/* dst addr */
 +	OUT_RING(pI830->BR[12]);		/* src addr */
 +	OUT_RING(pI830->BR[18]);		/* bg */
 +	OUT_RING(pI830->BR[19]);		/* fg */
 +
 +	ADVANCE_LP_RING();
 +    }
 +
 +    /* Advance to next scanline.
 +     */
 +    pI830->BR[9] += pScrn->displayWidth * pI830->cpp;
 +    I830GetNextScanlineColorExpandBuffer(pScrn);
++
++    if (IS_I965G(pI830))
++      I830EmitFlush(pScrn);
 +}
 +
 +#if DO_SCANLINE_IMAGE_WRITE
 +static void
 +I830SetupForScanlineImageWrite(ScrnInfoPtr pScrn, int rop,
 +			       unsigned int planemask, int trans_color,
 +			       int bpp, int depth)
 +{
 +    I830Ptr pI830 = I830PTR(pScrn);
 +
 +    if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
 +	ErrorF("I830SetupForScanlineImageWrite %x %x\n", rop, planemask);
 +
 +    /* Fill out register values */
 +    pI830->BR[13] = (pScrn->displayWidth * pI830->cpp);
 +    pI830->BR[13] |= XAAGetCopyROP(rop) << 16;
 +
 +    switch (pScrn->bitsPerPixel) {
 +    case 8:
 +	break;
 +    case 16:
 +	pI830->BR[13] |= (1 << 24);
 +	break;
 +    case 32:
 +	pI830->BR[13] |= ((1 << 25) | (1 << 24));
 +	break;
 +    }
 +
 +    I830GetNextScanlineColorExpandBuffer(pScrn);
 +}
 +
 +static void
 +I830SubsequentScanlineImageWriteRect(ScrnInfoPtr pScrn, int x, int y,
 +				     int w, int h, int skipleft)
 +{
 +    I830Ptr pI830 = I830PTR(pScrn);
 +
 +    if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
 +	ErrorF("I830SubsequentScanlineImageWriteRect "
 +	       "%d,%d %dx%x %d\n", x, y, w, h, skipleft);
 +
 +    /* Fill out register values */
 +    pI830->BR[9] = (pI830->bufferOffset +
 +		    (y * pScrn->displayWidth + x) * pI830->cpp);
 +    pI830->BR[11] = ((1 << 16) | w);
 +}
 +
 +static void
 +I830SubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno)
 +{
 +    I830Ptr pI830 = I830PTR(pScrn);
++    unsigned int tiled = CheckTiling(pScrn);
 +
 +    if (pI830->init == 0) {
 +	pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] -
 +			 pI830->FbBase);
 +    } else {
 +	I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
 +
 +	/* We have to use the primary screen's FbBase, as that's where
 +	 * we allocated Scratch2, so we get the correct pointer */
 +	pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] -
 +			 pI8301->FbBase);
 +    }
 +
 +    if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
 +	ErrorF("I830SubsequentImageWriteScanline %d (addr %x)\n",
 +	       bufno, pI830->BR[12]);
 +
 +    {
 +	BEGIN_LP_RING(8);
 +
 +	if (pScrn->bitsPerPixel == 32) {
 +	    OUT_RING(XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
- 		     XY_SRC_COPY_BLT_WRITE_RGB);
++		     tiled << 11 | XY_SRC_COPY_BLT_WRITE_RGB);
 +	} else {
- 	    OUT_RING(XY_SRC_COPY_BLT_CMD);
++	    OUT_RING(XY_SRC_COPY_BLT_CMD | tiled << 11);
 +	}
 +	OUT_RING(pI830->BR[13]);
- 	OUT_RING(0);			/* x1 = 0, y1 = 0 */
++	OUT_RING(0);				/* x1 = 0, y1 = 0 */
 +	OUT_RING(pI830->BR[11]);		/* x2 = w, y2 = 1 */
- 	OUT_RING(pI830->BR[9]);		/* dst addr */
- 	OUT_RING(0);			/* source origin (0,0) */
++	OUT_RING(pI830->BR[9]);			/* dst addr */
++	OUT_RING(0);				/* source origin (0,0) */
 +	OUT_RING(pI830->BR[11] & 0xffff);	/* source pitch */
 +	OUT_RING(pI830->BR[12]);		/* src addr */
 +
 +	ADVANCE_LP_RING();
 +    }
 +
 +    /* Advance to next scanline.
 +     */
 +    pI830->BR[9] += pScrn->displayWidth * pI830->cpp;
 +    I830GetNextScanlineColorExpandBuffer(pScrn);
 +}
 +#endif /* DO_SCANLINE_IMAGE_WRITE */
 +/* Support for multiscreen */
 +
 +static void
 +I830RestoreAccelState(ScrnInfoPtr pScrn)
 +{
 +#if 0
 +   /* might be needed, but everything is on a ring, so I don't think so */
 +   I830Sync(pScrn);
 +#endif
 +}
 +
diff-tree 421b415e23c1ddc78837cd222167d6ed71a3ef88 (from 71e3e2d4e3b2a2c538fe6f1cea41f442fdb8d756)
Author: Alan Hourihane <alanh at fairlite.demon.co.uk>
Date:   Tue Aug 8 11:28:42 2006 +0100

    Fix a build problem.

diff --git a/src/ch7xxx/ch7xxx.c b/src/ch7xxx/ch7xxx.c
index 77c49b5..fdc96d0 100644
--- a/src/ch7xxx/ch7xxx.c
+++ b/src/ch7xxx/ch7xxx.c
@@ -25,6 +25,7 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF 
 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 **************************************************************************/
+#include <string.h>
 #include "xf86.h"
 #include "xf86_OSproc.h"
 #include "xf86Resources.h"
@@ -32,7 +33,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "miscstruct.h"
 #include "xf86i2c.h"
 
-#include <string.h>
 
 #include "../i2c_vid.h"
 #include "ch7xxx.h"
diff-tree 71e3e2d4e3b2a2c538fe6f1cea41f442fdb8d756 (from e5c572f841b626b8b6f21a6966a33956d3b0b35b)
Author: Alan Hourihane <alanh at fairlite.demon.co.uk>
Date:   Fri Aug 4 20:39:50 2006 +0100

    Fix a problem creating the I2C bus for the SDVOC
    interface, due to a name match with SDVOB.
    
    Bus names must be unique.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 9a18f57..fe0c41a 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -858,7 +858,10 @@ I830SDVOInit(ScrnInfoPtr pScrn, int outp
 	xfree(sdvo);
 	return NULL;
     }
-    ddcbus->BusName = "SDVO DDC Bus";
+    if (output_device == SDVOB)
+        ddcbus->BusName = "SDVOB DDC Bus";
+    else
+        ddcbus->BusName = "SDVOC DDC Bus";
     ddcbus->scrnIndex = i2cbus->scrnIndex;
     ddcbus->I2CGetByte = I830SDVODDCI2CGetByte;
     ddcbus->I2CPutByte = I830SDVODDCI2CPutByte;
diff-tree e5c572f841b626b8b6f21a6966a33956d3b0b35b (from a6d438ebe3cf141a0331e0cd55eb9b5e137a5e37)
Author: Adam Jackson <ajax at benzedrine.nwnk.net>
Date:   Wed Aug 2 20:47:12 2006 -0400

    Fix a braino in mode list pruning.
    
    Interpreting the size of the display in centimeters as the size in pixels,
    and then clipping the modes list based on that, rarely does what you want.

diff --git a/src/i830_modes.c b/src/i830_modes.c
index 1c5e7eb..6bff1d0 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -638,10 +638,6 @@ i830GetDDCMonitor(ScrnInfoPtr pScrn, I2C
     userModes = i830DuplicateModes(pScrn, pScrn->monitor->Modes);
 
     i830xf86ValidateModesSync(pScrn, userModes, mon);
-    if (ddc->features.hsize > 0 && ddc->features.vsize > 0) {
-	i830xf86ValidateModesSize(pScrn, userModes, ddc->features.hsize,
-				  ddc->features.vsize, -1);
-    }
     i830xf86PruneInvalidModes(pScrn, &userModes, TRUE);
 
     i830AppendModes(pScrn, &mon->Modes, userModes);
diff-tree 7458a6adb5ea62f56bb3d4ab19ad7d1aa6ad2d19 (from 7ea74843bbdbf54b6804727be9b41d26832c8f76)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Jul 31 10:09:17 2006 -0700

    Move MAPSURF_XBIT settings into the texture formats structure.

diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
index 24b5752..90240b8 100644
--- a/src/i915_exa_render.c
+++ b/src/i915_exa_render.c
@@ -109,14 +109,14 @@ static struct blendinfo I915BlendOp[] = 
 };
 
 static struct formatinfo I915TexFormats[] = {
-        {PICT_a8r8g8b8, MT_32BIT_ARGB8888 },
-        {PICT_x8r8g8b8, MT_32BIT_XRGB8888 },
-        {PICT_a8b8g8r8, MT_32BIT_ABGR8888 },
-        {PICT_x8b8g8r8, MT_32BIT_XBGR8888 },
-        {PICT_r5g6b5,   MT_16BIT_RGB565   },
-        {PICT_a1r5g5b5, MT_16BIT_ARGB1555 },
-        {PICT_x1r5g5b5, MT_16BIT_ARGB1555 },
-        {PICT_a8,       MT_8BIT_A8 	  },
+        {PICT_a8r8g8b8, MAPSURF_32BIT | MT_32BIT_ARGB8888 },
+        {PICT_x8r8g8b8, MAPSURF_32BIT | MT_32BIT_XRGB8888 },
+        {PICT_a8b8g8r8, MAPSURF_32BIT | MT_32BIT_ABGR8888 },
+        {PICT_x8b8g8r8, MAPSURF_32BIT | MT_32BIT_XBGR8888 },
+        {PICT_r5g6b5,   MAPSURF_16BIT | MT_16BIT_RGB565   },
+        {PICT_a1r5g5b5, MAPSURF_16BIT | MT_16BIT_ARGB1555 },
+        {PICT_x1r5g5b5, MAPSURF_16BIT | MT_16BIT_ARGB1555 },
+        {PICT_a8,       MAPSURF_8BIT | MT_8BIT_A8 	  },
 };
 
 static CARD32 I915GetBlendCntl(int op, PicturePtr pMask, CARD32 dst_format)
@@ -289,13 +289,6 @@ I915TextureSetup(PicturePtr pPict, Pixma
         I830FALLBACK("Bad filter 0x%x\n", pPict->filter);
     }
 
-    if (pPix->drawable.bitsPerPixel == 8)
-	format |= MAPSURF_8BIT;
-    else if (pPix->drawable.bitsPerPixel == 16)
-	format |= MAPSURF_16BIT;
-    else
-	format |= MAPSURF_32BIT;
-
     mapstate[unit * 3 + 0] = offset;
     mapstate[unit * 3 + 1] = format |
 	((pPix->drawable.height - 1) << MS3_HEIGHT_SHIFT) |
diff-tree 7ea74843bbdbf54b6804727be9b41d26832c8f76 (from 30952e58ed83e2e18d1007f662d2cc9a773c876c)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Jul 31 10:06:34 2006 -0700

    Whitespace cleanup.

diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
index 9769765..24b5752 100644
--- a/src/i915_exa_render.c
+++ b/src/i915_exa_render.c
@@ -49,7 +49,7 @@ do {							\
 #define I830FALLBACK(s, arg...) 			\
 do { 							\
 	return FALSE;					\
-} while(0) 
+} while(0)
 #endif
 
 extern float scale_units[2][2];
@@ -79,7 +79,7 @@ I915EXAPrepareComposite(int op, PictureP
 			PicturePtr pMaskPicture, PicturePtr pDstPicture,
 			PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst);
 
-static struct blendinfo I915BlendOp[] = { 
+static struct blendinfo I915BlendOp[] = {
     /* Clear */
     {0, 0, BLENDFACT_ZERO,          BLENDFACT_ZERO},
     /* Src */
@@ -148,8 +148,8 @@ static CARD32 I915GetBlendCntl(int op, P
         }
     }
 
-    return (sblend <<S6_CBUF_SRC_BLEND_FACT_SHIFT) |
-	(dblend <<S6_CBUF_DST_BLEND_FACT_SHIFT);
+    return (sblend << S6_CBUF_SRC_BLEND_FACT_SHIFT) |
+	(dblend << S6_CBUF_DST_BLEND_FACT_SHIFT);
 }
 
 static Bool I915GetDestFormat(PicturePtr pDstPicture, CARD32 *dst_format)
@@ -193,7 +193,7 @@ static Bool I915CheckCompositeTexture(Pi
     int w = pPict->pDrawable->width;
     int h = pPict->pDrawable->height;
     int i;
-                                                                                                                                                            
+
     if ((w > 0x7ff) || (h > 0x7ff))
         I830FALLBACK("Picture w/h too large (%dx%d)\n", w, h);
 
@@ -222,11 +222,10 @@ I915EXACheckComposite(int op, PicturePtr
 		      PicturePtr pDstPicture)
 {
     CARD32 tmp1;
-    
+
     /* Check for unsupported compositing operations. */
     if (op >= sizeof(I915BlendOp) / sizeof(I915BlendOp[0]))
         I830FALLBACK("Unsupported Composite op 0x%x\n", op);
-                                                                                                                                                            
     if (pMaskPicture != NULL && pMaskPicture->componentAlpha) {
         /* Check if it's component alpha that relies on a source alpha and on
          * the source value.  We can only get one of those into the single
@@ -243,7 +242,7 @@ I915EXACheckComposite(int op, PicturePtr
     if (pMaskPicture != NULL && !I915CheckCompositeTexture(pMaskPicture, 1))
         I830FALLBACK("Check Mask picture texture\n");
 
-    if (!I915GetDestFormat(pDstPicture, &tmp1)) 
+    if (!I915GetDestFormat(pDstPicture, &tmp1))
 	I830FALLBACK("Get Color buffer format\n");
 
     return TRUE;
@@ -269,20 +268,20 @@ I915TextureSetup(PicturePtr pPict, Pixma
         if (I915TexFormats[i].fmt == pPict->format)
 	    break;
     }
-    if ( i == sizeof(I915TexFormats)/ sizeof(I915TexFormats[0]) )
+    if (i == sizeof(I915TexFormats)/ sizeof(I915TexFormats[0]))
 	I830FALLBACK("unknown texture format\n");
     format = I915TexFormats[i].card_fmt;
 
-    if (pPict->repeat) 
+    if (pPict->repeat)
 	wrap_mode = TEXCOORDMODE_WRAP;
 
     switch (pPict->filter) {
     case PictFilterNearest:
-        filter = (FILTER_NEAREST << SS2_MAG_FILTER_SHIFT) | 
+        filter = (FILTER_NEAREST << SS2_MAG_FILTER_SHIFT) |
 			(FILTER_NEAREST << SS2_MIN_FILTER_SHIFT);
         break;
     case PictFilterBilinear:
-        filter = (FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) | 
+        filter = (FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) |
 			(FILTER_LINEAR << SS2_MIN_FILTER_SHIFT);
         break;
     default:
@@ -305,7 +304,8 @@ I915TextureSetup(PicturePtr pPict, Pixma
 	samplerstate[unit * 3 + 1] |= MS3_USE_FENCE_REGS;
     mapstate[unit * 3 + 2] = ((pitch / 4) - 1) << MS4_PITCH_SHIFT;
 
-    samplerstate[unit * 3 + 0] = (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT) | filter;
+    samplerstate[unit * 3 + 0] = (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT);
+    samplerstate[unit * 3 + 0] |= filter;
     samplerstate[unit * 3 + 1] = SS3_NORMALIZED_COORDS;
     samplerstate[unit * 3 + 1] |= wrap_mode << SS3_TCX_ADDR_MODE_SHIFT;
     samplerstate[unit * 3 + 1] |= wrap_mode << SS3_TCY_ADDR_MODE_SHIFT;
@@ -323,7 +323,7 @@ I915TextureSetup(PicturePtr pPict, Pixma
     ErrorF("try to sync to show any errors...");
     I830Sync(pScrn);
 #endif
-	
+
     return TRUE;
 }
 
@@ -337,7 +337,7 @@ I915EXAPrepareComposite(int op, PictureP
     CARD32 dst_format, dst_offset, dst_pitch;
     CARD32 blendctl;
 
-ErrorF("i915 prepareComposite\n");
+    ErrorF("i915 prepareComposite\n");
 
     I915GetDestFormat(pDstPicture, &dst_format);
     dst_offset = exaGetPixmapOffset(pDst);
@@ -345,7 +345,7 @@ ErrorF("i915 prepareComposite\n");
     scale_units[2][0] = pDst->drawable.width;
     scale_units[2][1] = pDst->drawable.height;
     FS_LOCALS(20);
-    
+
     if (!I915TextureSetup(pSrcPicture, pSrc, 0))
 	I830FALLBACK("fail to setup src texture\n");
     if (pMask != NULL) {
@@ -396,12 +396,15 @@ ErrorF("i915 prepareComposite\n");
 	CARD32 ss2;
 
 	BEGIN_LP_RING(26);
-	/*color buffer*/
+	/* color buffer
+	 * XXX: Need to add USE_FENCE if we ever tile the X Server's pixmaps or
+	 * visible screen.
+	 */
 	OUT_RING(_3DSTATE_BUF_INFO_CMD);
-	OUT_RING(BUF_3D_ID_COLOR_BACK| BUF_3D_PITCH(dst_pitch)); /* fence, tile? */
+	OUT_RING(BUF_3D_ID_COLOR_BACK| BUF_3D_PITCH(dst_pitch));
 	OUT_RING(BUF_3D_ADDR(dst_offset));
 	OUT_RING(MI_NOOP);
-	
+
 	OUT_RING(_3DSTATE_DST_BUF_VARS_CMD);
 	OUT_RING(dst_format);
 
@@ -414,9 +417,8 @@ ErrorF("i915 prepareComposite\n");
 
 	OUT_RING(_3DSTATE_DFLT_SPEC_CMD);
 	OUT_RING(0x00000000);
-	
-	/* XXX:S3? define vertex format with tex coord sets number*/
-	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) | 
+
+	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) |
 		 I1_LOAD_S(3) | I1_LOAD_S(4) | I1_LOAD_S(5) | I1_LOAD_S(6) | 4);
 	ss2 = S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D);
 	if (pMask)
@@ -431,8 +433,8 @@ ErrorF("i915 prepareComposite\n");
 	ss2 |= S2_TEXCOORD_FMT(7, TEXCOORDFMT_NOT_PRESENT);
 	OUT_RING(ss2);
 	OUT_RING(0x00000000); /* Disable texture coordinate wrap-shortest */
-	OUT_RING((1<<S4_POINT_WIDTH_SHIFT)|S4_LINE_WIDTH_ONE| 
-		S4_CULLMODE_NONE| S4_VFMT_XY);  
+	OUT_RING((1 << S4_POINT_WIDTH_SHIFT) | S4_LINE_WIDTH_ONE |
+		 S4_CULLMODE_NONE| S4_VFMT_XY);
 	blendctl = I915GetBlendCntl(op, pMaskPicture, pDstPicture->format);
 	OUT_RING(0x00000000); /* Disable stencil buffer */
 	OUT_RING(S6_CBUF_BLEND_ENABLE | S6_COLOR_WRITE_ENABLE |
diff-tree 30952e58ed83e2e18d1007f662d2cc9a773c876c (from cffd2cd36d0437b38ac8164d66ea71be50b19330)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Wed Jul 26 13:42:12 2006 -0700

    Limit drawing to the destination pixmap's boundaries, not the screen's.
    
    This shouldn't matter, as miComputeCompositeRegion shouldn't giving us
    anything that would draw outside the bounds, anyway.

diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
index 7b2eada..9769765 100644
--- a/src/i915_exa_render.c
+++ b/src/i915_exa_render.c
@@ -446,7 +446,8 @@ ErrorF("i915 prepareComposite\n");
 	OUT_RING(_3DSTATE_DRAW_RECT_CMD);
 	OUT_RING(0x00000000);
 	OUT_RING(0x00000000);  /* ymin, xmin*/
-	OUT_RING(DRAW_YMAX(pScrn->virtualY-1) | DRAW_XMAX(pScrn->virtualX-1));
+	OUT_RING(DRAW_YMAX(pDst->drawable.height - 1) |
+		 DRAW_XMAX(pDst->drawable.width - 1));
 	OUT_RING(0x00000000);  /* yorig, xorig (relate to color buffer?)*/
 	OUT_RING(MI_NOOP);
 	ADVANCE_LP_RING();
diff-tree cffd2cd36d0437b38ac8164d66ea71be50b19330 (from 96754b822df7ac110a70b2d08dda2ebb299772be)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Wed Jul 26 13:22:51 2006 -0700

    Fix hangs when compositing with a mask.
    
    The modify bits in the mask field for sampler/map state appear to actually
    be enable bits.  So, prepare the state values in I915TextureSetup,
    then write the sampler/map state out all at once in PrepareComposite.

diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
index 74c85e0..7b2eada 100644
--- a/src/i915_exa_render.c
+++ b/src/i915_exa_render.c
@@ -55,6 +55,8 @@ do { 							\
 extern float scale_units[2][2];
 extern Bool is_transform[2];
 extern PictTransform *transform[2];
+static CARD32 mapstate[6];
+static CARD32 samplerstate[6];
 
 struct formatinfo {
     int fmt;
@@ -288,50 +290,27 @@ I915TextureSetup(PicturePtr pPict, Pixma
         I830FALLBACK("Bad filter 0x%x\n", pPict->filter);
     }
 
-    {
-	CARD32 ms3;
-	if (pPix->drawable.bitsPerPixel == 8)
-		format |= MAPSURF_8BIT;
-	else if (pPix->drawable.bitsPerPixel == 16)
-		format |= MAPSURF_16BIT;
-	else
-		format |= MAPSURF_32BIT;
-
-	BEGIN_LP_RING(6);
-	OUT_RING(_3DSTATE_MAP_STATE | 3);
-	OUT_RING(1<<unit);
-	OUT_RING(offset); /* Must be 4-byte aligned */
-	ms3 = ((pPix->drawable.height - 1) << MS3_HEIGHT_SHIFT) | 
-		((pPix->drawable.width - 1) << MS3_WIDTH_SHIFT) | format;
-	if (!pI830->disableTiling)
-		ms3 |= MS3_USE_FENCE_REGS;
-	OUT_RING(ms3); 
-	OUT_RING(((pitch / 4) - 1) << MS4_PITCH_SHIFT);
-	OUT_RING(MI_NOOP);
-	ADVANCE_LP_RING();
-     }
-
-     {
-	CARD32 ss2, ss3;
-	BEGIN_LP_RING(6);
-	/* max & min mip level ? or base mip level? */
-
-	OUT_RING(_3DSTATE_SAMPLER_STATE | 3);
-	OUT_RING(1<<unit);
-	ss2 = (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT);
-	ss2 |= filter;
-	OUT_RING(ss2);
-	/* repeat? */
-	ss3 = wrap_mode << SS3_TCX_ADDR_MODE_SHIFT;
-	ss3 |= wrap_mode << SS3_TCY_ADDR_MODE_SHIFT;
-	ss3 |= SS3_NORMALIZED_COORDS;
-	ss3 |= (unit << SS3_TEXTUREMAP_INDEX_SHIFT);
-	OUT_RING(ss3);
-	OUT_RING(0x00000000); /* border color */
-	OUT_RING(MI_NOOP);
-
-	ADVANCE_LP_RING();
-    }
+    if (pPix->drawable.bitsPerPixel == 8)
+	format |= MAPSURF_8BIT;
+    else if (pPix->drawable.bitsPerPixel == 16)
+	format |= MAPSURF_16BIT;
+    else
+	format |= MAPSURF_32BIT;
+
+    mapstate[unit * 3 + 0] = offset;
+    mapstate[unit * 3 + 1] = format |
+	((pPix->drawable.height - 1) << MS3_HEIGHT_SHIFT) |
+	((pPix->drawable.width - 1) << MS3_WIDTH_SHIFT);
+    if (!pI830->disableTiling)
+	samplerstate[unit * 3 + 1] |= MS3_USE_FENCE_REGS;
+    mapstate[unit * 3 + 2] = ((pitch / 4) - 1) << MS4_PITCH_SHIFT;
+
+    samplerstate[unit * 3 + 0] = (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT) | filter;
+    samplerstate[unit * 3 + 1] = SS3_NORMALIZED_COORDS;
+    samplerstate[unit * 3 + 1] |= wrap_mode << SS3_TCX_ADDR_MODE_SHIFT;
+    samplerstate[unit * 3 + 1] |= wrap_mode << SS3_TCY_ADDR_MODE_SHIFT;
+    samplerstate[unit * 3 + 1] |= unit << SS3_TEXTUREMAP_INDEX_SHIFT;
+    samplerstate[unit * 3 + 2] = 0x00000000; /* border color */
 
     if (pPict->transform != 0) {
         is_transform[unit] = TRUE;
@@ -378,6 +357,41 @@ ErrorF("i915 prepareComposite\n");
 	scale_units[1][1] = -1;
     }
 
+    if (pMask == NULL) {
+	BEGIN_LP_RING(10);
+	OUT_RING(_3DSTATE_MAP_STATE | 3);
+	OUT_RING(0x00000001); /* map 0 */
+	OUT_RING(mapstate[0]);
+	OUT_RING(mapstate[1]);
+	OUT_RING(mapstate[2]);
+
+	OUT_RING(_3DSTATE_SAMPLER_STATE | 3);
+	OUT_RING(0x00000001); /* sampler 0 */
+	OUT_RING(samplerstate[0]);
+	OUT_RING(samplerstate[1]);
+	OUT_RING(samplerstate[2]);
+	ADVANCE_LP_RING();
+    } else {
+	BEGIN_LP_RING(16);
+	OUT_RING(_3DSTATE_MAP_STATE | 6);
+	OUT_RING(0x00000003); /* map 0,1 */
+	OUT_RING(mapstate[0]);
+	OUT_RING(mapstate[1]);
+	OUT_RING(mapstate[2]);
+	OUT_RING(mapstate[3]);
+	OUT_RING(mapstate[4]);
+	OUT_RING(mapstate[5]);
+
+	OUT_RING(_3DSTATE_SAMPLER_STATE | 6);
+	OUT_RING(0x00000003); /* sampler 0,1 */
+	OUT_RING(samplerstate[0]);
+	OUT_RING(samplerstate[1]);
+	OUT_RING(samplerstate[2]);
+	OUT_RING(samplerstate[3]);
+	OUT_RING(samplerstate[4]);
+	OUT_RING(samplerstate[5]);
+	ADVANCE_LP_RING();
+    }
     {
 	CARD32 ss2;
 
diff-tree 96754b822df7ac110a70b2d08dda2ebb299772be (from 9c93d1498fa2363c52ef7fbe97d781560f67acf5)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Wed Jul 26 13:19:12 2006 -0700

    Fix a couple of typos from code review.

diff --git a/src/i915_3d.h b/src/i915_3d.h
index c116200..1090218 100644
--- a/src/i915_3d.h
+++ b/src/i915_3d.h
@@ -33,7 +33,7 @@
 #define MASK_Y			0x2
 #define MASK_Z			0x4
 #define MASK_W			0x8
-#define MASK_XYZ		(MASK_X | MASK_Y | MASK_W)
+#define MASK_XYZ		(MASK_X | MASK_Y | MASK_Z)
 #define MASK_XYZW		(MASK_XYZ | MASK_W)
 #define MASK_SATURATE		0x10
 
@@ -398,7 +398,7 @@ do {									\
 do {									\
     struct i915_fs_op op;						\
 									\
-    op = i915_fs_arith(DP3, dest_reg, operand0, i915_fs_operand_none(),	\
+    op = i915_fs_arith(DP3, dest_reg, operand0, operand1,		\
 		       i915_fs_operand_none());				\
     op.ui[0] &= ~A0_DEST_CHANNEL_ALL;					\
     op.ui[0] |= ((dest_mask) & ~MASK_SATURATE) << A0_DEST_CHANNEL_SHIFT; \
diff-tree 9c93d1498fa2363c52ef7fbe97d781560f67acf5 (from 38d1a5e0dbe059f5c01bd5120a108a386ff10718)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Tue Jul 25 21:17:05 2006 -0700

    Oops, partial revert of last commit.  Some were obviously not NOOPS.

diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
index 7555b41..74c85e0 100644
--- a/src/i915_exa_render.c
+++ b/src/i915_exa_render.c
@@ -393,13 +393,13 @@ ErrorF("i915 prepareComposite\n");
 
 	/* XXX: defaults */
 	OUT_RING(_3DSTATE_DFLT_Z_CMD);
-	OUT_RING(MI_NOOP);
+	OUT_RING(0x00000000);
 
 	OUT_RING(_3DSTATE_DFLT_DIFFUSE_CMD);
-	OUT_RING(MI_NOOP);
+	OUT_RING(0x00000000);
 
 	OUT_RING(_3DSTATE_DFLT_SPEC_CMD);
-	OUT_RING(MI_NOOP);
+	OUT_RING(0x00000000);
 	
 	/* XXX:S3? define vertex format with tex coord sets number*/
 	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) | 
diff-tree 38d1a5e0dbe059f5c01bd5120a108a386ff10718 (from aec88cf4c66833f89afa5f8fa4f8bcf30b2b6b4b)
Author: Eric Anholt <anholt at leguin.anholt.net>
Date:   Tue Jul 25 21:09:12 2006 -0700

    Replace some OUT_RING(0)s with OUT_RING(MI_NOOP) to remind me why they're there.

diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
index 08736cc..7555b41 100644
--- a/src/i915_exa_render.c
+++ b/src/i915_exa_render.c
@@ -307,7 +307,7 @@ I915TextureSetup(PicturePtr pPict, Pixma
 		ms3 |= MS3_USE_FENCE_REGS;
 	OUT_RING(ms3); 
 	OUT_RING(((pitch / 4) - 1) << MS4_PITCH_SHIFT);
-	OUT_RING(0);
+	OUT_RING(MI_NOOP);
 	ADVANCE_LP_RING();
      }
 
@@ -328,7 +328,7 @@ I915TextureSetup(PicturePtr pPict, Pixma
 	ss3 |= (unit << SS3_TEXTUREMAP_INDEX_SHIFT);
 	OUT_RING(ss3);
 	OUT_RING(0x00000000); /* border color */
-	OUT_RING(0);
+	OUT_RING(MI_NOOP);
 
 	ADVANCE_LP_RING();
     }
@@ -393,13 +393,13 @@ ErrorF("i915 prepareComposite\n");
 
 	/* XXX: defaults */
 	OUT_RING(_3DSTATE_DFLT_Z_CMD);
-	OUT_RING(0);
+	OUT_RING(MI_NOOP);
 
 	OUT_RING(_3DSTATE_DFLT_DIFFUSE_CMD);
-	OUT_RING(0);
+	OUT_RING(MI_NOOP);
 
 	OUT_RING(_3DSTATE_DFLT_SPEC_CMD);
-	OUT_RING(0);
+	OUT_RING(MI_NOOP);
 	
 	/* XXX:S3? define vertex format with tex coord sets number*/
 	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) | 
@@ -426,7 +426,7 @@ ErrorF("i915 prepareComposite\n");
 
 	/* issue a flush */
 	OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
-	OUT_RING(0);
+	OUT_RING(MI_NOOP);
 
 	/* draw rect is unconditional */
 	OUT_RING(_3DSTATE_DRAW_RECT_CMD);
@@ -434,7 +434,7 @@ ErrorF("i915 prepareComposite\n");
 	OUT_RING(0x00000000);  /* ymin, xmin*/
 	OUT_RING(DRAW_YMAX(pScrn->virtualY-1) | DRAW_XMAX(pScrn->virtualX-1));
 	OUT_RING(0x00000000);  /* yorig, xorig (relate to color buffer?)*/
-	OUT_RING(0);
+	OUT_RING(MI_NOOP);
 	ADVANCE_LP_RING();
     }
 
diff-tree aec88cf4c66833f89afa5f8fa4f8bcf30b2b6b4b (from 02c5c4cd1dd44058d80ec23cccfd45a13bc3bb2c)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Mon Jul 24 15:46:19 2006 +0800

    remove crap blit in UploadToScreen, we should find a more
    efficent way and implement blit correctly.

diff --git a/src/i830_exa.c b/src/i830_exa.c
index de12c33..bb75b24 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -325,8 +325,6 @@ I830EXADoneCopy(PixmapPtr pDstPixmap)
     	return;
 }
 
-//#define UPLOAD_USE_BLIT 1
-
 static Bool
 I830EXAUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, 
 		char *src, int src_pitch)
@@ -343,7 +341,6 @@ I830EXAUploadToScreen(PixmapPtr pDst, in
     ErrorF("Up->Screen: dst offset 0x%x, dst pitch %d, x %d, y %d, src %p, src pitch %d\n",
 		dst_offset, dst_pitch, x, y, src, src_pitch);
 #endif
-#ifndef UPLOAD_USE_BLIT
     dst = pI830->FbBase + dst_offset + y*dst_pitch + 
 		x* (pDst->drawable.bitsPerPixel/8);
     w *= pDst->drawable.bitsPerPixel/8;
@@ -352,41 +349,6 @@ I830EXAUploadToScreen(PixmapPtr pDst, in
 	src += src_pitch;
 	dst += dst_pitch;
     }
-#else
-    /* setup blit engine to copy one pixel data by one */
-    {
-	int x1, x2, y1, y2, i, j;
-	CARD32 d, len, *srcp;
-	x1 = x;
-	y1 = y;
-	x2 = x + w;
-	y2 = y + h;
-
-	len = (w * (pDst->drawable.bitsPerPixel/8)) >> 2;
-
-	pI830->BR[13] = (1 << 24) | (1 << 25);
-	pI830->BR[13] |= I830CopyROP[GXcopy]<<16;
-	pI830->BR[13] |= dst_pitch & 0xffff;
-	for (i = 0; i < h; i++) {
-		srcp = (CARD32*)src;
-		for ( j = len; j > 0; j--) {
-			d = *srcp;
-			BEGIN_LP_RING(6);
-			OUT_RING(XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA | 
-				XY_COLOR_BLT_WRITE_RGB);
-			OUT_RING(pI830->BR[13]);
-			OUT_RING((y1 << 16) | x1);
-			OUT_RING((y2 << 16) | x2);
-			OUT_RING(dst_offset);
-			OUT_RING(d);
-			ADVANCE_LP_RING();
-			srcp++;
-		}
-		src += src_pitch;
-	}
-
-    }
-#endif
 
     return TRUE;
 }
diff-tree 02c5c4cd1dd44058d80ec23cccfd45a13bc3bb2c (from 4f0ad337098eb0bacb1c11bc61d780ac18041e1d)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Fri Jul 21 12:54:06 2006 +0800

    add copyright info

diff --git a/src/i830_exa_render.c b/src/i830_exa_render.c
index 23a3c43..86e11d2 100644
--- a/src/i830_exa_render.c
+++ b/src/i830_exa_render.c
@@ -1,3 +1,31 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Wang Zhenyu <zhenyu.z.wang at intel.com>
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
index 36e6c80..08736cc 100644
--- a/src/i915_exa_render.c
+++ b/src/i915_exa_render.c
@@ -1,4 +1,30 @@
-/* -*- c-basic-offset: 4 -*- */
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Wang Zhenyu <zhenyu.z.wang at intel.com>
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
diff-tree 4f0ad337098eb0bacb1c11bc61d780ac18041e1d (from 914327f40d07a3f7c069752ce005bf8e21352b03)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Fri Jul 21 11:59:04 2006 +0800

    fixup segfault in xaa when xaa not initialized in i830WaitSync.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index b7a8097..ed85585 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -6425,7 +6425,8 @@ i830WaitSync(ScrnInfoPtr pScrn)
    I830Ptr pI830 = I830PTR(pScrn);
 
 #ifdef I830_USE_XAA
-   if (!pI830->noAccel && !pI830->useEXA && pI830->AccelInfoRec->NeedToSync) {
+   if (!pI830->noAccel && !pI830->useEXA && pI830->AccelInfoRec 
+	&& pI830->AccelInfoRec->NeedToSync) {
       (*pI830->AccelInfoRec->Sync)(pScrn);
       pI830->AccelInfoRec->NeedToSync = FALSE;
    }
diff-tree 914327f40d07a3f7c069752ce005bf8e21352b03 (from 45cb032e2b7ac1e4c765fc29a2e4dd0cef19066d)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Thu Jul 20 17:58:07 2006 -0400

    Disable drawing to PICT_a8, and turn on support for non-extended repeats.
    
    We don't know what COLOR_BUF_8BIT does, so it's disabled for now while we're
    stabilizing the code.
    
    The non-extended repeats appear to be working according to the rendercheck
    tests on a8 and a8r8g8b8 sources.  Masks continue to hang the card, as before
    this change.

diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
index 795c076..36e6c80 100644
--- a/src/i915_exa_render.c
+++ b/src/i915_exa_render.c
@@ -138,9 +138,16 @@ static Bool I915GetDestFormat(PicturePtr
     case PICT_x1r5g5b5:
         *dst_format = COLR_BUF_ARGB1555;
         break;
+    /* COLR_BUF_8BIT is special for YUV surfaces.  While we may end up being
+     * able to use it depending on how the hardware implements it, disable it
+     * for now while we don't know what exactly it does (what channel does it
+     * read from?
+     */
+    /*
     case PICT_a8:
         *dst_format = COLR_BUF_8BIT;
         break;
+    */
     case PICT_a4r4g4b4:
     case PICT_x4r4g4b4:
 	*dst_format = COLR_BUF_ARGB4444;
@@ -171,9 +178,9 @@ static Bool I915CheckCompositeTexture(Pi
         I830FALLBACK("Unsupported picture format 0x%x\n",
                          (int)pPict->format);
 
-    /* FIXME: fix repeat support */
-    if (pPict->repeat) 
-	I830FALLBACK("repeat not support now!\n");
+    if (pPict->repeat && pPict->repeatType != RepeatNormal)
+	I830FALLBACK("extended repeat (%d) not supported\n",
+		     pPict->repeatType);
 
     if (pPict->filter != PictFilterNearest &&
         pPict->filter != PictFilterBilinear)
diff-tree 45cb032e2b7ac1e4c765fc29a2e4dd0cef19066d (from fd6d825ae0780f3daf436f4224bf5f177cb8630e)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Thu Jul 20 17:34:50 2006 -0400

    Use MT_8BIT_A8 so PICT_a8 expands to (0,0,0,a) not (a,a,a,a)

diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
index a063d8f..795c076 100644
--- a/src/i915_exa_render.c
+++ b/src/i915_exa_render.c
@@ -88,7 +88,7 @@ static struct formatinfo I915TexFormats[
         {PICT_r5g6b5,   MT_16BIT_RGB565   },
         {PICT_a1r5g5b5, MT_16BIT_ARGB1555 },
         {PICT_x1r5g5b5, MT_16BIT_ARGB1555 },
-        {PICT_a8,       MT_8BIT_I8 	  },
+        {PICT_a8,       MT_8BIT_A8 	  },
 };
 
 static CARD32 I915GetBlendCntl(int op, PicturePtr pMask, CARD32 dst_format)
diff-tree fd6d825ae0780f3daf436f4224bf5f177cb8630e (from d6d6a44c66446f34b57394e5ea9a8e32917f7569)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Thu Jul 20 17:25:31 2006 -0400

    Move ss6 setting with other immediate state, and ensure that stencil is off.

diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
index deeac4a..a063d8f 100644
--- a/src/i915_exa_render.c
+++ b/src/i915_exa_render.c
@@ -348,7 +348,7 @@ ErrorF("i915 prepareComposite\n");
     {
 	CARD32 ss2;
 
-	BEGIN_LP_RING(24);
+	BEGIN_LP_RING(26);
 	/*color buffer*/
 	OUT_RING(_3DSTATE_BUF_INFO_CMD);
 	OUT_RING(BUF_3D_ID_COLOR_BACK| BUF_3D_PITCH(dst_pitch)); /* fence, tile? */
@@ -369,8 +369,8 @@ ErrorF("i915 prepareComposite\n");
 	OUT_RING(0);
 	
 	/* XXX:S3? define vertex format with tex coord sets number*/
-	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) |
-		 I1_LOAD_S(3) | I1_LOAD_S(4) | 2);
+	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) | 
+		 I1_LOAD_S(3) | I1_LOAD_S(4) | I1_LOAD_S(5) | I1_LOAD_S(6) | 4);
 	ss2 = S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D);
 	if (pMask)
 		ss2 |= S2_TEXCOORD_FMT(1, TEXCOORDFMT_2D);
@@ -383,9 +383,13 @@ ErrorF("i915 prepareComposite\n");
 	ss2 |= S2_TEXCOORD_FMT(6, TEXCOORDFMT_NOT_PRESENT);
 	ss2 |= S2_TEXCOORD_FMT(7, TEXCOORDFMT_NOT_PRESENT);
 	OUT_RING(ss2);
-	OUT_RING(0x00000000); /*XXX: does ss3 needed? */
+	OUT_RING(0x00000000); /* Disable texture coordinate wrap-shortest */
 	OUT_RING((1<<S4_POINT_WIDTH_SHIFT)|S4_LINE_WIDTH_ONE| 
 		S4_CULLMODE_NONE| S4_VFMT_XY);  
+	blendctl = I915GetBlendCntl(op, pMaskPicture, pDstPicture->format);
+	OUT_RING(0x00000000); /* Disable stencil buffer */
+	OUT_RING(S6_CBUF_BLEND_ENABLE | S6_COLOR_WRITE_ENABLE |
+		 (BLENDFUNC_ADD << S6_CBUF_BLEND_FUNC_SHIFT) | blendctl);
 
 	/* issue a flush */
 	OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
@@ -445,17 +449,6 @@ ErrorF("i915 prepareComposite\n");
     }
     FS_END();
 
-    {
-	CARD32 ss6;
-	blendctl = I915GetBlendCntl(op, pMaskPicture, pDstPicture->format);
-
-	BEGIN_LP_RING(2);
-	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(6) | 0);
-	ss6 = S6_CBUF_BLEND_ENABLE | S6_COLOR_WRITE_ENABLE;
-	OUT_RING(ss6 | (0 << S6_CBUF_BLEND_FUNC_SHIFT) | blendctl);
-	ADVANCE_LP_RING();
-    }
-
 #ifdef I830DEBUG
     ErrorF("try to sync to show any errors...");
     I830Sync(pScrn);
diff-tree d6d6a44c66446f34b57394e5ea9a8e32917f7569 (from 2b2173c618c080b1678990d65fe49b52bd8001b4)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Thu Jul 20 11:23:05 2006 -0400

    Try to fix up the basic RepeatNormal and RepeatNone support.
    
    With RepeatNone, access outside of the drawable should return 0 alpha values,
    which is done by using the border color.  For RepeatNormal, we use the wrap
    mode (which requires that we use normalized texture coordinates).

diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
index 6246136..deeac4a 100644
--- a/src/i915_exa_render.c
+++ b/src/i915_exa_render.c
@@ -221,7 +221,7 @@ I915TextureSetup(PicturePtr pPict, Pixma
     I830Ptr pI830 = I830PTR(pScrn);
     CARD32 format, offset, pitch, filter;
     int w, h, i;
-    CARD32 wrap_mode = TEXCOORDMODE_CLAMP_EDGE; 
+    CARD32 wrap_mode = TEXCOORDMODE_CLAMP_BORDER;
 
     offset = exaGetPixmapOffset(pPix);
     pitch = exaGetPixmapPitch(pPix);
@@ -239,8 +239,8 @@ I915TextureSetup(PicturePtr pPict, Pixma
     format = I915TexFormats[i].card_fmt;
 
     if (pPict->repeat) 
-	wrap_mode = TEXCOORDMODE_WRAP; /* XXX:correct ? */
-    
+	wrap_mode = TEXCOORDMODE_WRAP;
+
     switch (pPict->filter) {
     case PictFilterNearest:
         filter = (FILTER_NEAREST << SS2_MAG_FILTER_SHIFT) | 
@@ -289,12 +289,12 @@ I915TextureSetup(PicturePtr pPict, Pixma
 	ss2 |= filter;
 	OUT_RING(ss2);
 	/* repeat? */
-	ss3 = TEXCOORDMODE_WRAP << SS3_TCX_ADDR_MODE_SHIFT;
-	ss3 |= (TEXCOORDMODE_WRAP << SS3_TCY_ADDR_MODE_SHIFT);
+	ss3 = wrap_mode << SS3_TCX_ADDR_MODE_SHIFT;
+	ss3 |= wrap_mode << SS3_TCY_ADDR_MODE_SHIFT;
 	ss3 |= SS3_NORMALIZED_COORDS;
 	ss3 |= (unit << SS3_TEXTUREMAP_INDEX_SHIFT);
 	OUT_RING(ss3);
-	OUT_RING(0x00000000); /* default color */
+	OUT_RING(0x00000000); /* border color */
 	OUT_RING(0);
 
 	ADVANCE_LP_RING();
diff-tree 2b2173c618c080b1678990d65fe49b52bd8001b4 (from 9f1cec83e0aef36c7d3482e62e8f01595f1fd076)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Thu Jul 20 11:15:18 2006 -0400

    The pixmap's drawable x/y coordinates are always 0, so don't bother using them.

diff --git a/src/i830_exa.c b/src/i830_exa.c
index f7c79c2..de12c33 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -56,7 +56,6 @@ do { 							\
 #endif
 
 float scale_units[2][2];
-int draw_coords[3][2];
 
 const int I830CopyROP[16] =
 {
@@ -431,13 +430,12 @@ IntelEXAComposite(PixmapPtr pDst, int sr
     int pMask = 1;
 
     DPRINTF(PFX, "Composite: srcX %d, srcY %d\n\t maskX %d, maskY %d\n\t"
-	     "dstX %d, dstY %d\n\twidth %d, height %d\n\t"
-	     "src_scale_x %f, src_scale_y %f, mask_scale_x %f, mask_scale_y %f\n""\tdx0 %d, dy0 %x, dx1 %d dy1 %x\n", 
-		srcX, srcY, maskX, maskY, dstX, dstY, w, h,
-		scale_units[0][0], scale_units[0][1], 
-		scale_units[1][0], scale_units[1][1],
-		draw_coords[0][0], draw_coords[0][1], 
-		draw_coords[1][0], draw_coords[1][1]);
+	    "dstX %d, dstY %d\n\twidth %d, height %d\n\t"
+	    "src_scale_x %f, src_scale_y %f, "
+	    "mask_scale_x %f, mask_scale_y %f\n",
+	    srcX, srcY, maskX, maskY, dstX, dstY, w, h,
+	    scale_units[0][0], scale_units[0][1],
+	    scale_units[1][0], scale_units[1][1]);
 
     if (scale_units[1][0] == -1 || scale_units[1][1] == -1) {
 	ErrorF("mask is null\n");
@@ -481,13 +479,6 @@ IntelEXAComposite(PixmapPtr pDst, int sr
 		"dstX %d, dstY %d\n", srcX, srcY, srcXend, srcYend,
 		maskX, maskY, maskXend, maskYend, dstX, dstY);
 
-    draw_coords[0][0] -= draw_coords[2][0];
-    draw_coords[0][1] -= draw_coords[2][1];
-    if (pMask) {
-	draw_coords[1][0] -= draw_coords[2][0];
-	draw_coords[1][1] -= draw_coords[2][1];
-    }
-
     {
 	int vertex_count; 
 
@@ -508,38 +499,38 @@ IntelEXAComposite(PixmapPtr pDst, int sr
 
 	OUT_RING_F(dstX);
 	OUT_RING_F(dstY);
-	OUT_RING_F(((srcX - draw_coords[0][0]) / scale_units[0][0]));
-	OUT_RING_F(((srcY - draw_coords[0][1]) / scale_units[0][1]));
+	OUT_RING_F(srcX / scale_units[0][0]);
+	OUT_RING_F(srcY / scale_units[0][1]);
 	if (pMask) {
-		OUT_RING_F(((maskX - draw_coords[1][0]) / scale_units[1][0]));
-		OUT_RING_F(((maskY - draw_coords[1][1]) / scale_units[1][1]));
+		OUT_RING_F(maskX / scale_units[1][0]);
+		OUT_RING_F(maskY / scale_units[1][1]);
 	}
 
 	OUT_RING_F(dstX);
-	OUT_RING_F((dstY+h));
-	OUT_RING_F(((srcX - draw_coords[0][0]) / scale_units[0][0]));
-	OUT_RING_F(((srcYend - draw_coords[0][1]) / scale_units[0][1]));
+	OUT_RING_F(dstY + h);
+	OUT_RING_F(srcX / scale_units[0][0]);
+	OUT_RING_F(srcYend / scale_units[0][1]);
 	if (pMask) {
-		OUT_RING_F(((maskX - draw_coords[1][0]) / scale_units[1][0]));
-		OUT_RING_F(((maskYend - draw_coords[1][1]) / scale_units[1][1]));
+		OUT_RING_F(maskX / scale_units[1][0]);
+		OUT_RING_F(maskYend / scale_units[1][1]);
 	}
 
-	OUT_RING_F((dstX+w));
-	OUT_RING_F((dstY+h));
-	OUT_RING_F(((srcXend - draw_coords[0][0]) / scale_units[0][0]));
-	OUT_RING_F(((srcYend - draw_coords[0][1]) / scale_units[0][1]));
+	OUT_RING_F(dstX + w);
+	OUT_RING_F(dstY + h);
+	OUT_RING_F(srcXend / scale_units[0][0]);
+	OUT_RING_F(srcYend / scale_units[0][1]);
 	if (pMask) {
-		OUT_RING_F(((maskXend - draw_coords[1][0]) / scale_units[1][0]));
-		OUT_RING_F(((maskYend - draw_coords[1][1]) / scale_units[1][1]));
+		OUT_RING_F(maskXend / scale_units[1][0]);
+		OUT_RING_F(maskYend / scale_units[1][1]);
 	}
 
-	OUT_RING_F((dstX+w));
-	OUT_RING_F((dstY));
-	OUT_RING_F(((srcXend - draw_coords[0][0]) / scale_units[0][0]));
-	OUT_RING_F(((srcY - draw_coords[0][1]) / scale_units[0][1]));
+	OUT_RING_F(dstX + w);
+	OUT_RING_F(dstY);
+	OUT_RING_F(srcXend / scale_units[0][0]);
+	OUT_RING_F(srcY / scale_units[0][1]);
 	if (pMask) {
-		OUT_RING_F(((maskXend - draw_coords[1][0]) / scale_units[1][0]));
-		OUT_RING_F(((maskY - draw_coords[1][1]) / scale_units[1][1]));
+		OUT_RING_F(maskXend / scale_units[1][0]);
+		OUT_RING_F(maskY / scale_units[1][1]);
 	}
 	ADVANCE_LP_RING();
     }
diff --git a/src/i830_exa_render.c b/src/i830_exa_render.c
index 7a22e7d..23a3c43 100644
--- a/src/i830_exa_render.c
+++ b/src/i830_exa_render.c
@@ -24,7 +24,6 @@ do { 							\
 #endif
 
 extern float scale_units[2][2];
-extern int draw_coords[3][2];
 extern Bool is_transform[2];
 extern PictTransform *transform[2];
 
@@ -249,8 +248,6 @@ I830TextureSetup(PicturePtr pPict, Pixma
     h = pPict->pDrawable->height;
     scale_units[unit][0] = pPix->drawable.width;
     scale_units[unit][1] = pPix->drawable.height;
-    draw_coords[unit][0] = pPix->drawable.x;
-    draw_coords[unit][1] = pPix->drawable.y;
 
     for (i = 0; i < sizeof(I830TexFormats) / sizeof(I830TexFormats[0]); i++) {
         if (I830TexFormats[i].fmt == pPict->format)
@@ -378,9 +375,7 @@ I830EXAPrepareComposite(int op, PictureP
     I830GetDestFormat(pDstPicture, &dst_format);
     dst_offset = exaGetPixmapOffset(pDst);
     dst_pitch = exaGetPixmapPitch(pDst);
-    draw_coords[2][0] = pDst->drawable.x;
-    draw_coords[2][1] = pDst->drawable.y;
-    
+
     if (!I830TextureSetup(pSrcPicture, pSrc, 0))
 	I830FALLBACK("fail to setup src texture\n");
     if (pMask != NULL) {
diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
index ba54d53..6246136 100644
--- a/src/i915_exa_render.c
+++ b/src/i915_exa_render.c
@@ -27,7 +27,6 @@ do { 							\
 #endif
 
 extern float scale_units[2][2];
-extern int draw_coords[3][2];
 extern Bool is_transform[2];
 extern PictTransform *transform[2];
 
@@ -230,8 +229,6 @@ I915TextureSetup(PicturePtr pPict, Pixma
     h = pPict->pDrawable->height;
     scale_units[unit][0] = pPix->drawable.width;
     scale_units[unit][1] = pPix->drawable.height;
-    draw_coords[unit][0] = pPix->drawable.x;
-    draw_coords[unit][1] = pPix->drawable.y;
 
     for (i = 0; i < sizeof(I915TexFormats) / sizeof(I915TexFormats[0]); i++) {
         if (I915TexFormats[i].fmt == pPict->format)
@@ -333,8 +330,6 @@ ErrorF("i915 prepareComposite\n");
     I915GetDestFormat(pDstPicture, &dst_format);
     dst_offset = exaGetPixmapOffset(pDst);
     dst_pitch = exaGetPixmapPitch(pDst);
-    draw_coords[2][0] = pDst->drawable.x;
-    draw_coords[2][1] = pDst->drawable.y;
     scale_units[2][0] = pDst->drawable.width;
     scale_units[2][1] = pDst->drawable.height;
     FS_LOCALS(20);
diff-tree 9f1cec83e0aef36c7d3482e62e8f01595f1fd076 (from 4737955a62c39177e7a7ce7749a2f20e111afc68)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Thu Jul 20 11:05:49 2006 -0400

    The vertex data are all floats, so write the dest coords as floats.

diff --git a/src/i830_exa.c b/src/i830_exa.c
index 40f6868..f7c79c2 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -506,8 +506,8 @@ IntelEXAComposite(PixmapPtr pDst, int sr
 
 	OUT_RING(PRIM3D_INLINE | PRIM3D_TRIFAN | (vertex_count-1));
 
-	OUT_RING(dstX);
-	OUT_RING(dstY);
+	OUT_RING_F(dstX);
+	OUT_RING_F(dstY);
 	OUT_RING_F(((srcX - draw_coords[0][0]) / scale_units[0][0]));
 	OUT_RING_F(((srcY - draw_coords[0][1]) / scale_units[0][1]));
 	if (pMask) {
@@ -515,8 +515,8 @@ IntelEXAComposite(PixmapPtr pDst, int sr
 		OUT_RING_F(((maskY - draw_coords[1][1]) / scale_units[1][1]));
 	}
 
-	OUT_RING(dstX);
-	OUT_RING((dstY+h));
+	OUT_RING_F(dstX);
+	OUT_RING_F((dstY+h));
 	OUT_RING_F(((srcX - draw_coords[0][0]) / scale_units[0][0]));
 	OUT_RING_F(((srcYend - draw_coords[0][1]) / scale_units[0][1]));
 	if (pMask) {
@@ -524,8 +524,8 @@ IntelEXAComposite(PixmapPtr pDst, int sr
 		OUT_RING_F(((maskYend - draw_coords[1][1]) / scale_units[1][1]));
 	}
 
-	OUT_RING((dstX+w));
-	OUT_RING((dstY+h));
+	OUT_RING_F((dstX+w));
+	OUT_RING_F((dstY+h));
 	OUT_RING_F(((srcXend - draw_coords[0][0]) / scale_units[0][0]));
 	OUT_RING_F(((srcYend - draw_coords[0][1]) / scale_units[0][1]));
 	if (pMask) {
@@ -533,8 +533,8 @@ IntelEXAComposite(PixmapPtr pDst, int sr
 		OUT_RING_F(((maskYend - draw_coords[1][1]) / scale_units[1][1]));
 	}
 
-	OUT_RING((dstX+w));
-	OUT_RING((dstY));
+	OUT_RING_F((dstX+w));
+	OUT_RING_F((dstY));
 	OUT_RING_F(((srcXend - draw_coords[0][0]) / scale_units[0][0]));
 	OUT_RING_F(((srcY - draw_coords[0][1]) / scale_units[0][1]));
 	if (pMask) {
diff-tree 4737955a62c39177e7a7ce7749a2f20e111afc68 (from a7e30bb051bc03063fe699473610a57054a64973)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Fri Jul 21 01:02:38 2006 +0800

    move i830 default coord set into I830EmitInvarientState

diff --git a/src/i830_3d.c b/src/i830_3d.c
index 0efd6e4..214beb6 100644
--- a/src/i830_3d.c
+++ b/src/i830_3d.c
@@ -33,13 +33,11 @@
 
 #include "i830_reg.h"
 
-#define CMD_3D (0x3<<29)
-
 void I830EmitInvarientState( ScrnInfoPtr pScrn )
 {
    I830Ptr pI830 = I830PTR(pScrn);
 
-   BEGIN_LP_RING(38);
+   BEGIN_LP_RING(40);
 
    OUT_RING(_3DSTATE_MAP_CUBE | MAP_UNIT(0));
    OUT_RING(_3DSTATE_MAP_CUBE | MAP_UNIT(1));
@@ -98,6 +96,12 @@ void I830EmitInvarientState( ScrnInfoPtr
    OUT_RING(_3DSTATE_MAP_COORD_TRANSFORM);
    OUT_RING(DISABLE_TEX_TRANSFORM | TEXTURE_SET(3));
 
+   OUT_RING(_3DSTATE_MAP_COORD_SETBIND_CMD);
+   OUT_RING(TEXBIND_SET3(TEXCOORDSRC_VTXSET_3) |
+   	TEXBIND_SET2(TEXCOORDSRC_VTXSET_2) |
+   	TEXBIND_SET1(TEXCOORDSRC_VTXSET_1) |
+   	TEXBIND_SET0(TEXCOORDSRC_VTXSET_0));
+	
    OUT_RING(_3DSTATE_RASTER_RULES_CMD |
 	     ENABLE_POINT_RASTER_RULE |
 	     OGL_POINT_RASTER_RULE |
diff --git a/src/i830_exa_render.c b/src/i830_exa_render.c
index f51e6a4..7a22e7d 100644
--- a/src/i830_exa_render.c
+++ b/src/i830_exa_render.c
@@ -365,25 +365,6 @@ I830EXACheckComposite(int op, PicturePtr
     return TRUE;
 }
 
-
-static void
-I830DefCtxSetup(ScrnInfoPtr pScrn)
-{
-	/* coord binding */
-	CARD32 mcb;
-    	I830Ptr pI830 = I830PTR(pScrn);
-
-	BEGIN_LP_RING(2);
-	OUT_RING(_3DSTATE_MAP_COORD_SETBIND_CMD);
-	mcb = TEXBIND_SET3(TEXCOORDSRC_VTXSET_3);
-	mcb |= TEXBIND_SET2(TEXCOORDSRC_VTXSET_2);
-	mcb |= TEXBIND_SET1(TEXCOORDSRC_VTXSET_1);
-	mcb |= TEXBIND_SET0(TEXCOORDSRC_VTXSET_0);
-	OUT_RING(mcb);
-	ADVANCE_LP_RING();
-}
-
-
 Bool
 I830EXAPrepareComposite(int op, PicturePtr pSrcPicture,
 			PicturePtr pMaskPicture, PicturePtr pDstPicture,
@@ -400,8 +381,6 @@ I830EXAPrepareComposite(int op, PictureP
     draw_coords[2][0] = pDst->drawable.x;
     draw_coords[2][1] = pDst->drawable.y;
     
-    I830DefCtxSetup(pScrn);
-
     if (!I830TextureSetup(pSrcPicture, pSrc, 0))
 	I830FALLBACK("fail to setup src texture\n");
     if (pMask != NULL) {
diff-tree a7e30bb051bc03063fe699473610a57054a64973 (from ac34a37cb60d763cbd99b6e2f6fdcb639592b99b)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Fri Jul 21 00:56:58 2006 +0800

    Take from i915, blend ctl code cleanup.

diff --git a/src/i830_exa_render.c b/src/i830_exa_render.c
index cd5e69c..f51e6a4 100644
--- a/src/i830_exa_render.c
+++ b/src/i830_exa_render.c
@@ -31,7 +31,8 @@ extern PictTransform *transform[2];
 struct blendinfo {
     Bool dst_alpha;
     Bool src_alpha;
-    CARD32 blend_cntl;
+    CARD32 src_blend;
+    CARD32 dst_blend;
 };
 
 struct formatinfo {
@@ -48,41 +49,6 @@ I830EXAPrepareComposite(int op, PictureP
 			PicturePtr pMaskPicture, PicturePtr pDstPicture,
 			PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst);
 
-/* I830's Blend factor definition, LOAD_STATE_IMMEDIATE_1 */
-/* move to header...*/
-#define I830_SRC_BLENDFACTOR_ZERO 		(1 << 4)
-#define I830_SRC_BLENDFACTOR_ONE 		(2 << 4)
-#define I830_SRC_BLENDFACTOR_SRC_COLOR		(3 << 4)
-#define I830_SRC_BLENDFACTOR_INV_SRC_COLOR	(4 << 4)
-#define I830_SRC_BLENDFACTOR_SRC_ALPHA		(5 << 4)
-#define I830_SRC_BLENDFACTOR_INV_SRC_ALPHA	(6 << 4)
-#define I830_SRC_BLENDFACTOR_DST_ALPHA		(7 << 4)
-#define I830_SRC_BLENDFACTOR_INV_DST_ALPHA	(8 << 4)
-#define I830_SRC_BLENDFACTOR_DST_COLOR		(9 << 4)
-#define I830_SRC_BLENDFACTOR_INV_DST_COLOR	(0xa << 4)
-#define I830_SRC_BLENDFACTOR_SRC_ALPHA_SATURATE (0xb << 4)
-#define I830_SRC_BLENDFACTOR_CONST_COLOR	(0xc << 4)
-#define I830_SRC_BLENDFACTOR_INV_CONST_COLOR	(0xd << 4)
-#define I830_SRC_BLENDFACTOR_CONST_ALPHA	(0xe << 4)
-#define I830_SRC_BLENDFACTOR_INV_CONST_ALPHA	(0xf << 4)
-#define I830_SRC_BLENDFACTOR_MASK		(0xf << 4)
-
-#define I830_DST_BLENDFACTOR_ZERO 		(1)
-#define I830_DST_BLENDFACTOR_ONE 		(2)
-#define I830_DST_BLENDFACTOR_SRC_COLOR		(3)
-#define I830_DST_BLENDFACTOR_INV_SRC_COLOR	(4)
-#define I830_DST_BLENDFACTOR_SRC_ALPHA		(5)
-#define I830_DST_BLENDFACTOR_INV_SRC_ALPHA	(6)
-#define I830_DST_BLENDFACTOR_DST_ALPHA		(7)
-#define I830_DST_BLENDFACTOR_INV_DST_ALPHA	(8)
-#define I830_DST_BLENDFACTOR_DST_COLOR		(9)
-#define I830_DST_BLENDFACTOR_INV_DST_COLOR	(0xa)
-#define I830_DST_BLENDFACTOR_SRC_ALPHA_SATURATE (0xb)
-#define I830_DST_BLENDFACTOR_CONST_COLOR	(0xc)
-#define I830_DST_BLENDFACTOR_INV_CONST_COLOR	(0xd)
-#define I830_DST_BLENDFACTOR_CONST_ALPHA	(0xe)
-#define I830_DST_BLENDFACTOR_INV_CONST_ALPHA	(0xf)
-#define I830_DST_BLENDFACTOR_MASK		(0xf)
 
 #define TB0C_LAST_STAGE	(1 << 31)
 #define TB0C_RESULT_SCALE_1X		(0 << 29)
@@ -132,38 +98,34 @@ I830EXAPrepareComposite(int op, PictureP
 #define TB0A_ARG1_SEL_TEXEL1		(7 << 6)
 #define TB0A_ARG1_SEL_TEXEL2		(8 << 6)
 #define TB0A_ARG1_SEL_TEXEL3		(9 << 6)
-#define TB0A_ARG0_SEL_XXX
-
-/* end */
-
 
 static struct blendinfo I830BlendOp[] = { 
     /* Clear */
-    {0, 0, I830_SRC_BLENDFACTOR_ZERO           | I830_DST_BLENDFACTOR_ZERO},
+    {0, 0, BLENDFACTOR_ZERO, 		BLENDFACTOR_ZERO},
     /* Src */
-    {0, 0, I830_SRC_BLENDFACTOR_ONE            | I830_DST_BLENDFACTOR_ZERO},
+    {0, 0, BLENDFACTOR_ONE, 		BLENDFACTOR_ZERO},
     /* Dst */
-    {0, 0, I830_SRC_BLENDFACTOR_ZERO           | I830_DST_BLENDFACTOR_ONE},
+    {0, 0, BLENDFACTOR_ZERO,		BLENDFACTOR_ONE},
     /* Over */
-    {0, 1, I830_SRC_BLENDFACTOR_ONE            | I830_DST_BLENDFACTOR_INV_SRC_ALPHA},
+    {0, 1, BLENDFACTOR_ONE,		BLENDFACTOR_INV_SRC_ALPHA},
     /* OverReverse */
-    {1, 0, I830_SRC_BLENDFACTOR_INV_DST_ALPHA | I830_DST_BLENDFACTOR_ONE},
+    {1, 0, BLENDFACTOR_INV_DST_ALPHA,	BLENDFACTOR_ONE},
     /* In */
-    {1, 0, I830_SRC_BLENDFACTOR_DST_ALPHA     | I830_DST_BLENDFACTOR_ZERO},
+    {1, 0, BLENDFACTOR_DST_ALPHA,	BLENDFACTOR_ZERO},
     /* InReverse */
-    {0, 1, I830_SRC_BLENDFACTOR_ZERO           | I830_DST_BLENDFACTOR_SRC_ALPHA},
+    {0, 1, BLENDFACTOR_ZERO,		BLENDFACTOR_SRC_ALPHA},
     /* Out */
-    {1, 0, I830_SRC_BLENDFACTOR_INV_DST_ALPHA | I830_DST_BLENDFACTOR_ZERO},
+    {1, 0, BLENDFACTOR_INV_DST_ALPHA,	BLENDFACTOR_ZERO},
     /* OutReverse */
-    {0, 1, I830_SRC_BLENDFACTOR_ZERO           | I830_DST_BLENDFACTOR_INV_SRC_ALPHA},
+    {0, 1, BLENDFACTOR_ZERO,		BLENDFACTOR_INV_SRC_ALPHA},
     /* Atop */
-    {1, 1, I830_SRC_BLENDFACTOR_DST_ALPHA     | I830_DST_BLENDFACTOR_INV_SRC_ALPHA},
+    {1, 1, BLENDFACTOR_DST_ALPHA,	BLENDFACTOR_INV_SRC_ALPHA},
     /* AtopReverse */
-    {1, 1, I830_SRC_BLENDFACTOR_INV_DST_ALPHA | I830_DST_BLENDFACTOR_SRC_ALPHA},
+    {1, 1, BLENDFACTOR_INV_DST_ALPHA,	BLENDFACTOR_SRC_ALPHA},
     /* Xor */
-    {1, 1, I830_SRC_BLENDFACTOR_INV_DST_ALPHA | I830_DST_BLENDFACTOR_INV_SRC_ALPHA},
+    {1, 1, BLENDFACTOR_INV_DST_ALPHA,	BLENDFACTOR_INV_SRC_ALPHA},
     /* Add */
-    {0, 0, I830_SRC_BLENDFACTOR_ONE            | I830_DST_BLENDFACTOR_ONE},
+    {0, 0, BLENDFACTOR_ONE, 		BLENDFACTOR_ONE},
 };
 
 
@@ -213,17 +175,17 @@ static CARD32 I830GetBlendCntl(int op, P
 {
     CARD32 sblend, dblend;
 
-    sblend = I830BlendOp[op].blend_cntl & I830_SRC_BLENDFACTOR_MASK;
-    dblend = I830BlendOp[op].blend_cntl & I830_DST_BLENDFACTOR_MASK;
+    sblend = I830BlendOp[op].src_blend;
+    dblend = I830BlendOp[op].dst_blend;
 
     /* If there's no dst alpha channel, adjust the blend op so that we'll treat
      * it as always 1.
      */
     if (PICT_FORMAT_A(dst_format) == 0 && I830BlendOp[op].dst_alpha) {
-        if (sblend == I830_SRC_BLENDFACTOR_DST_ALPHA)
-            sblend = I830_SRC_BLENDFACTOR_ONE;
-        else if (sblend == I830_SRC_BLENDFACTOR_INV_DST_ALPHA)
-            sblend = I830_SRC_BLENDFACTOR_ZERO;
+        if (sblend == BLENDFACTOR_DST_ALPHA)
+            sblend = BLENDFACTOR_ONE;
+        else if (sblend == BLENDFACTOR_INV_DST_ALPHA)
+            sblend = BLENDFACTOR_ZERO;
     }
 
     /* If the source alpha is being used, then we should only be in a case where
@@ -231,14 +193,15 @@ static CARD32 I830GetBlendCntl(int op, P
      * channels multiplied by the source picture's alpha.
      */
     if (pMask && pMask->componentAlpha && I830BlendOp[op].src_alpha) {
-        if (dblend == I830_DST_BLENDFACTOR_SRC_ALPHA) {
-            dblend = I830_DST_BLENDFACTOR_SRC_COLOR;
-        } else if (dblend == I830_DST_BLENDFACTOR_INV_SRC_ALPHA) {
-            dblend = I830_DST_BLENDFACTOR_INV_SRC_COLOR;
+        if (dblend == BLENDFACTOR_SRC_ALPHA) {
+            dblend = BLENDFACTOR_SRC_COLR;
+        } else if (dblend == BLENDFACTOR_INV_SRC_ALPHA) {
+            dblend = BLENDFACTOR_INV_SRC_COLR;
         }
     }
 
-    return sblend | dblend;
+    return (sblend << S8_SRC_BLEND_FACTOR_SHIFT) | 
+		(dblend << S8_DST_BLEND_FACTOR_SHIFT);
 }
 
 static Bool I830CheckCompositeTexture(PicturePtr pPict, int unit)
@@ -386,8 +349,7 @@ I830EXACheckComposite(int op, PicturePtr
          * source value that we get to blend with.
          */
         if (I830BlendOp[op].src_alpha &&
-            (I830BlendOp[op].blend_cntl & I830_SRC_BLENDFACTOR_MASK) !=
-             I830_SRC_BLENDFACTOR_ZERO)
+            (I830BlendOp[op].src_blend != BLENDFACTOR_ZERO))
             	I830FALLBACK("Component alpha not supported with source "
                             "alpha and source value blending.\n");
     }
diff --git a/src/i830_reg.h b/src/i830_reg.h
index ae68a2e..f9c1df9 100644
--- a/src/i830_reg.h
+++ b/src/i830_reg.h
@@ -221,6 +221,22 @@
 #define ENABLE_DST_ABLEND_FACTOR	(1<<5)
 #define DST_ABLEND_FACT(x)		(x)
 
+#define BLENDFACTOR_ZERO		0x01
+#define BLENDFACTOR_ONE 		0x02
+#define BLENDFACTOR_SRC_COLR		0x03
+#define BLENDFACTOR_INV_SRC_COLR	0x04
+#define BLENDFACTOR_SRC_ALPHA		0x05
+#define BLENDFACTOR_INV_SRC_ALPHA	0x06
+#define BLENDFACTOR_DST_ALPHA		0x07
+#define BLENDFACTOR_INV_DST_ALPHA	0x08
+#define BLENDFACTOR_DST_COLR		0x09
+#define BLENDFACTOR_INV_DST_COLR	0x0a
+#define BLENDFACTOR_SRC_ALPHA_SATURATE	0x0b
+#define BLENDFACTOR_CONST_COLOR		0x0c
+#define BLENDFACTOR_INV_CONST_COLOR	0x0d
+#define BLENDFACTOR_CONST_ALPHA		0x0e
+#define BLENDFACTOR_INV_CONST_ALPHA	0x0f
+#define BLENDFACTOR_MASK		0x0f
 
 /* _3DSTATE_MAP_BLEND_ARG, p152 */
 #define _3DSTATE_MAP_BLEND_ARG_CMD(stage)	(CMD_3D|(0x0e<<24)|((stage)<<20))
diff-tree ac34a37cb60d763cbd99b6e2f6fdcb639592b99b (from 3e86bf4273241daa23645f5a8104913e4205a74b)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Fri Jul 21 00:52:59 2006 +0800

    Take instruction fixes into i830, with indent changes.

diff --git a/src/i830_exa_render.c b/src/i830_exa_render.c
index 9b4835b..cd5e69c 100644
--- a/src/i830_exa_render.c
+++ b/src/i830_exa_render.c
@@ -315,9 +315,9 @@ I830TextureSetup(PicturePtr pPict, Pixma
     }
 
     {
-	if (pI830->cpp == 1)
+	if (pPix->drawable.bitsPerPixel == 8)
 		format |= MAP_SURFACE_8BIT;
-	else if (pI830->cpp == 2)
+	else if (pPix->drawable.bitsPerPixel == 16)
 		format |= MAP_SURFACE_16BIT;
 	else
 		format |= MAP_SURFACE_32BIT;
@@ -325,9 +325,10 @@ I830TextureSetup(PicturePtr pPict, Pixma
 	BEGIN_LP_RING(6);
 	OUT_RING(_3DSTATE_MAP_INFO_CMD);
 	OUT_RING(format | TEXMAP_INDEX(unit) | MAP_FORMAT_2D);
-	OUT_RING((pPix->drawable.height<<16)|pPix->drawable.width); /* height, width */
-	OUT_RING(offset<<2); /* map address */
-	OUT_RING(pitch<<2); /* map pitch */
+	OUT_RING(((pPix->drawable.height - 1) << 16) |
+		(pPix->drawable.width - 1)); /* height, width */
+	OUT_RING(offset); /* map address */
+	OUT_RING(((pitch / 4) - 1) << 2); /* map pitch */
 	OUT_RING(0);
 	ADVANCE_LP_RING();
      }
@@ -336,8 +337,9 @@ I830TextureSetup(PicturePtr pPict, Pixma
 	BEGIN_LP_RING(2);
 	/* coord sets */
 	OUT_RING(_3DSTATE_MAP_COORD_SET_CMD | TEXCOORD_SET(unit) | 
-		ENABLE_TEXCOORD_PARAMS | TEXCOORDS_ARE_NORMAL | /*XXX, check this, and fix vertex tex coord*/
-		TEXCOORDTYPE_CARTESIAN | ENABLE_ADDR_V_CNTL | TEXCOORD_ADDR_V_MODE(wrap_mode) |
+		ENABLE_TEXCOORD_PARAMS | TEXCOORDS_ARE_NORMAL | 
+		TEXCOORDTYPE_CARTESIAN | ENABLE_ADDR_V_CNTL | 
+		TEXCOORD_ADDR_V_MODE(wrap_mode) |
 		ENABLE_ADDR_U_CNTL | TEXCOORD_ADDR_U_MODE(wrap_mode));
 	OUT_RING(MI_NOOP);
 
@@ -453,7 +455,7 @@ I830EXAPrepareComposite(int op, PictureP
 
 	CARD32 cblend, ablend, blendctl, vf2;
 
-	BEGIN_LP_RING(22);
+	BEGIN_LP_RING(22+6);
 	
 	/*color buffer*/
 	OUT_RING(_3DSTATE_BUF_INFO_CMD);
@@ -464,6 +466,8 @@ I830EXAPrepareComposite(int op, PictureP
 	OUT_RING(_3DSTATE_DST_BUF_VARS_CMD);
 	OUT_RING(dst_format);
 
+      	OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
+      	OUT_RING(MI_NOOP);		/* pad to quadword */
 	/* defaults */
 	OUT_RING(_3DSTATE_DFLT_Z_CMD);
 	OUT_RING(0);
@@ -474,18 +478,19 @@ I830EXAPrepareComposite(int op, PictureP
 	OUT_RING(_3DSTATE_DFLT_SPEC_CMD);
 	OUT_RING(0);
 	
-	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1|I1_LOAD_S(3)|0);
-	OUT_RING((1<<S3_POINT_WIDTH_SHIFT) | (2<<S3_LINE_WIDTH_SHIFT) | S3_CULLMODE_NONE| S3_VERTEXHAS_XY);  
-	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1|I1_LOAD_S(2)|0);
+	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | 0);
+	OUT_RING((1 << S3_POINT_WIDTH_SHIFT) | (2 << S3_LINE_WIDTH_SHIFT) | 
+		S3_CULLMODE_NONE | S3_VERTEXHAS_XY);  
+	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) | 0);
 	if (pMask)
-		vf2 = 2 << 12; /* 2 texture coord sets */
+	    vf2 = 2 << 12; /* 2 texture coord sets */
 	else
-		vf2 = 1 << 12;
+	    vf2 = 1 << 12;
 	vf2 |= (TEXCOORDFMT_2D << 16);
 	if (pMask)
-		vf2 |= (TEXCOORDFMT_2D << 18);
+	    vf2 |= (TEXCOORDFMT_2D << 18);
 	else
-		vf2 |= (TEXCOORDFMT_1D << 18);
+	    vf2 |= (TEXCOORDFMT_1D << 18);
 		
 	vf2 |= (TEXCOORDFMT_1D << 20);
 	vf2 |= (TEXCOORDFMT_1D << 22);
@@ -495,21 +500,24 @@ I830EXAPrepareComposite(int op, PictureP
 	vf2 |= (TEXCOORDFMT_1D << 30);
 	OUT_RING(vf2);
 
+      	OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
+      	OUT_RING(MI_NOOP);		/* pad to quadword */
 	/* For (src In mask) operation */
 	/* IN operator: Multiply src by mask components or mask alpha.*/
 	/* TEXBLENDOP_MODULE: arg1*arg2 */
 	cblend = TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OP_MODULE |
 		 TB0C_OUTPUT_WRITE_CURRENT;  
-	ablend = TB0A_RESULT_SCALE_1X | TB0A_OP_MODULE | TB0A_OUTPUT_WRITE_CURRENT;
+	ablend = TB0A_RESULT_SCALE_1X | TB0A_OP_MODULE | 
+		 TB0A_OUTPUT_WRITE_CURRENT;
 	
 	cblend |= TB0C_ARG1_SEL_TEXEL0;
 	ablend |= TB0A_ARG1_SEL_TEXEL0;
 	if (pMask) {
-		if (pMaskPicture->componentAlpha && pDstPicture->format != PICT_a8)
-			cblend |= TB0C_ARG2_SEL_TEXEL1;
-		else
-			cblend |= (TB0C_ARG2_SEL_TEXEL1 | TB0C_ARG2_REPLICATE_ALPHA);
-		ablend |= TB0A_ARG2_SEL_TEXEL1;
+	    if (pMaskPicture->componentAlpha && pDstPicture->format != PICT_a8)
+		cblend |= TB0C_ARG2_SEL_TEXEL1;
+	    else
+		cblend |= (TB0C_ARG2_SEL_TEXEL1 | TB0C_ARG2_REPLICATE_ALPHA);
+	    ablend |= TB0A_ARG2_SEL_TEXEL1;
 	} else {
 		cblend |= TB0C_ARG2_SEL_ONE;
 		ablend |= TB0A_ARG2_SEL_ONE;		
@@ -520,6 +528,9 @@ I830EXAPrepareComposite(int op, PictureP
 	OUT_RING(ablend);
 	OUT_RING(0);
 
+      	OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
+      	OUT_RING(MI_NOOP);		/* pad to quadword */
+
 	blendctl = I830GetBlendCntl(op, pMaskPicture, pDstPicture->format);
 	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(8) | 0);
 	OUT_RING(S8_ENABLE_COLOR_BLEND | S8_BLENDFUNC_ADD |(blendctl<<4) |
diff-tree 3e86bf4273241daa23645f5a8104913e4205a74b (from 5c945bf9eb9f5bedd34d98dcc7abc3f1ea3cb962)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Thu Jul 20 13:43:27 2006 +0800

    remove i915 default ctx setup.

diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
index 4912d97..ba54d53 100644
--- a/src/i915_exa_render.c
+++ b/src/i915_exa_render.c
@@ -318,20 +318,6 @@ I915TextureSetup(PicturePtr pPict, Pixma
     return TRUE;
 }
 
-static void
-I915DefCtxSetup(ScrnInfoPtr pScrn)
-{
-    I830Ptr pI830 = I830PTR(pScrn);
-
-    BEGIN_LP_RING(2);
-    /* set default texture binding, may be in prepare better */
-    OUT_RING(_3DSTATE_COORD_SET_BINDINGS | CSB_TCB(0,0) | CSB_TCB(1,1) |
-	CSB_TCB(2,2) | CSB_TCB(3,3) | CSB_TCB(4,4) | CSB_TCB(5,5) |
-	CSB_TCB(6,6) | CSB_TCB(7,7));
-    OUT_RING(0);
-    ADVANCE_LP_RING();
-}
-
 Bool
 I915EXAPrepareComposite(int op, PicturePtr pSrcPicture,
 			PicturePtr pMaskPicture, PicturePtr pDstPicture,
@@ -353,8 +339,6 @@ ErrorF("i915 prepareComposite\n");
     scale_units[2][1] = pDst->drawable.height;
     FS_LOCALS(20);
     
-    I915DefCtxSetup(pScrn);
-
     if (!I915TextureSetup(pSrcPicture, pSrc, 0))
 	I830FALLBACK("fail to setup src texture\n");
     if (pMask != NULL) {
diff-tree 5c945bf9eb9f5bedd34d98dcc7abc3f1ea3cb962 (from d5243d1b35ab1db608c81889819e4d4d87048154)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Thu Jul 20 13:40:39 2006 +0800

    Revert "Fix several size error with STATE3D_LOAD_STATE_IMMEDIATE cmd."
    
    This reverts commit 433cb6ba82698676f6f72e09834aba4d64611d54.

diff --git a/src/i830_exa.c b/src/i830_exa.c
index 3975e6d..40f6868 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -55,7 +55,7 @@ do { 							\
 } while(0) 
 #endif
 
-float scale_units[3][2];
+float scale_units[2][2];
 int draw_coords[3][2];
 
 const int I830CopyROP[16] =
@@ -101,7 +101,7 @@ const int I830PatternROP[16] =
 /* move to common.h */
 union intfloat {
 	float f;
-	CARD32 ui;
+	unsigned int ui;
 };
 
 #define OUT_RING_F(x) do {			\
@@ -429,7 +429,6 @@ IntelEXAComposite(PixmapPtr pDst, int sr
     int srcXend, srcYend, maskXend, maskYend;
     PictVector v;
     int pMask = 1;
-    float src_scale_x, src_scale_y, mask_scale_x, mask_scale_y;
 
     DPRINTF(PFX, "Composite: srcX %d, srcY %d\n\t maskX %d, maskY %d\n\t"
 	     "dstX %d, dstY %d\n\twidth %d, height %d\n\t"
@@ -484,14 +483,9 @@ IntelEXAComposite(PixmapPtr pDst, int sr
 
     draw_coords[0][0] -= draw_coords[2][0];
     draw_coords[0][1] -= draw_coords[2][1];
-    src_scale_x = (float)scale_units[0][0] / (float)scale_units[2][0];
-    src_scale_y = (float)scale_units[0][1] / (float)scale_units[2][1];
-
     if (pMask) {
 	draw_coords[1][0] -= draw_coords[2][0];
 	draw_coords[1][1] -= draw_coords[2][1];
-	mask_scale_x = (float)scale_units[1][0] / (float)scale_units[2][0];
-	mask_scale_y = (float)scale_units[1][1] / (float)scale_units[2][1];
     }
 
     {
@@ -512,40 +506,40 @@ IntelEXAComposite(PixmapPtr pDst, int sr
 
 	OUT_RING(PRIM3D_INLINE | PRIM3D_TRIFAN | (vertex_count-1));
 
-	OUT_RING_F(dstX);
-	OUT_RING_F(dstY);
-	OUT_RING_F(((srcX - draw_coords[0][0]) * src_scale_x));
-	OUT_RING_F(((srcY - draw_coords[0][1]) * src_scale_y));
+	OUT_RING(dstX);
+	OUT_RING(dstY);
+	OUT_RING_F(((srcX - draw_coords[0][0]) / scale_units[0][0]));
+	OUT_RING_F(((srcY - draw_coords[0][1]) / scale_units[0][1]));
 	if (pMask) {
-		OUT_RING_F(((maskX - draw_coords[1][0]) * mask_scale_x));
-		OUT_RING_F(((maskY - draw_coords[1][1]) * mask_scale_y));
+		OUT_RING_F(((maskX - draw_coords[1][0]) / scale_units[1][0]));
+		OUT_RING_F(((maskY - draw_coords[1][1]) / scale_units[1][1]));
 	}
 
-	OUT_RING_F(dstX);
-	OUT_RING_F((dstY+h));
-	OUT_RING_F(((srcX - draw_coords[0][0]) * src_scale_x));
-	OUT_RING_F(((srcYend - draw_coords[0][1]) * src_scale_y));
+	OUT_RING(dstX);
+	OUT_RING((dstY+h));
+	OUT_RING_F(((srcX - draw_coords[0][0]) / scale_units[0][0]));
+	OUT_RING_F(((srcYend - draw_coords[0][1]) / scale_units[0][1]));
 	if (pMask) {
-		OUT_RING_F(((maskX - draw_coords[1][0]) * mask_scale_x));
-		OUT_RING_F(((maskYend - draw_coords[1][1]) * mask_scale_y));
+		OUT_RING_F(((maskX - draw_coords[1][0]) / scale_units[1][0]));
+		OUT_RING_F(((maskYend - draw_coords[1][1]) / scale_units[1][1]));
 	}
 
-	OUT_RING_F((dstX+w));
-	OUT_RING_F((dstY+h));
-	OUT_RING_F(((srcXend - draw_coords[0][0]) * src_scale_x));
-	OUT_RING_F(((srcYend - draw_coords[0][1]) * src_scale_y));
+	OUT_RING((dstX+w));
+	OUT_RING((dstY+h));
+	OUT_RING_F(((srcXend - draw_coords[0][0]) / scale_units[0][0]));
+	OUT_RING_F(((srcYend - draw_coords[0][1]) / scale_units[0][1]));
 	if (pMask) {
-		OUT_RING_F(((maskXend - draw_coords[1][0]) * mask_scale_x));
-		OUT_RING_F(((maskYend - draw_coords[1][1]) * mask_scale_y));
+		OUT_RING_F(((maskXend - draw_coords[1][0]) / scale_units[1][0]));
+		OUT_RING_F(((maskYend - draw_coords[1][1]) / scale_units[1][1]));
 	}
 
-	OUT_RING_F((dstX+w));
-	OUT_RING_F((dstY));
-	OUT_RING_F(((srcXend - draw_coords[0][0]) * src_scale_x));
-	OUT_RING_F(((srcY - draw_coords[0][1]) * src_scale_y));
+	OUT_RING((dstX+w));
+	OUT_RING((dstY));
+	OUT_RING_F(((srcXend - draw_coords[0][0]) / scale_units[0][0]));
+	OUT_RING_F(((srcY - draw_coords[0][1]) / scale_units[0][1]));
 	if (pMask) {
-		OUT_RING_F(((maskXend - draw_coords[1][0]) * mask_scale_x));
-		OUT_RING_F(((maskY - draw_coords[1][1]) * mask_scale_y));
+		OUT_RING_F(((maskXend - draw_coords[1][0]) / scale_units[1][0]));
+		OUT_RING_F(((maskY - draw_coords[1][1]) / scale_units[1][1]));
 	}
 	ADVANCE_LP_RING();
     }
diff-tree d5243d1b35ab1db608c81889819e4d4d87048154 (from 13e372c2095fde94ae41bea959fba0ad95a59c08)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Wed Jul 19 19:27:53 2006 -0400

    The height and width of texture maps are one more than the programmed values.

diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
index 4cc9e54..4912d97 100644
--- a/src/i915_exa_render.c
+++ b/src/i915_exa_render.c
@@ -271,8 +271,8 @@ I915TextureSetup(PicturePtr pPict, Pixma
 	OUT_RING(_3DSTATE_MAP_STATE | 3);
 	OUT_RING(1<<unit);
 	OUT_RING(offset); /* Must be 4-byte aligned */
-	ms3 = (pPix->drawable.height << MS3_HEIGHT_SHIFT) | 
-		(pPix->drawable.width << MS3_WIDTH_SHIFT) | format;
+	ms3 = ((pPix->drawable.height - 1) << MS3_HEIGHT_SHIFT) | 
+		((pPix->drawable.width - 1) << MS3_WIDTH_SHIFT) | format;
 	if (!pI830->disableTiling)
 		ms3 |= MS3_USE_FENCE_REGS;
 	OUT_RING(ms3); 
diff-tree 13e372c2095fde94ae41bea959fba0ad95a59c08 (from da5efb09d55291ce5bcabff7db8d1490bb5e838b)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Wed Jul 19 16:42:57 2006 -0400

    Fix the texture map pitch setting as documented, and as used by the 3d driver.

diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
index a570382..4cc9e54 100644
--- a/src/i915_exa_render.c
+++ b/src/i915_exa_render.c
@@ -270,13 +270,13 @@ I915TextureSetup(PicturePtr pPict, Pixma
 	BEGIN_LP_RING(6);
 	OUT_RING(_3DSTATE_MAP_STATE | 3);
 	OUT_RING(1<<unit);
-	OUT_RING(offset&MS2_ADDRESS_MASK);
+	OUT_RING(offset); /* Must be 4-byte aligned */
 	ms3 = (pPix->drawable.height << MS3_HEIGHT_SHIFT) | 
 		(pPix->drawable.width << MS3_WIDTH_SHIFT) | format;
 	if (!pI830->disableTiling)
 		ms3 |= MS3_USE_FENCE_REGS;
 	OUT_RING(ms3); 
-	OUT_RING(pitch<<MS4_PITCH_SHIFT);
+	OUT_RING(((pitch / 4) - 1) << MS4_PITCH_SHIFT);
 	OUT_RING(0);
 	ADVANCE_LP_RING();
      }
diff --git a/src/i915_reg.h b/src/i915_reg.h
index b9f7ef8..6751de6 100644
--- a/src/i915_reg.h
+++ b/src/i915_reg.h
@@ -688,7 +688,9 @@
 
 
 
-/* p207 */
+/* p207.
+ * The DWORD count is 3 times the number of bits set in MS1_MAPMASK_MASK
+ */
 #define _3DSTATE_MAP_STATE               (CMD_3D|(0x1d<<24)|(0x0<<16))
 
 #define MS1_MAPMASK_SHIFT               0
@@ -755,6 +757,7 @@
 #define MS3_TILED_SURFACE             (1<<1)
 #define MS3_TILE_WALK                 (1<<0)
 
+/* The pitch is the pitch measured in DWORDS, minus 1 */
 #define MS4_PITCH_SHIFT                 21
 #define MS4_CUBE_FACE_ENA_NEGX          (1<<20)
 #define MS4_CUBE_FACE_ENA_POSX          (1<<19)
@@ -771,7 +774,9 @@
 #define MS4_VOLUME_DEPTH_SHIFT          0    
 #define MS4_VOLUME_DEPTH_MASK           (0xff<<0)
 
-/* p244 */
+/* p244.
+ * The DWORD count is 3 times the number of bits set in SS1_MAPMASK_MASK.
+ */
 #define _3DSTATE_SAMPLER_STATE         (CMD_3D|(0x1d<<24)|(0x1<<16))
 
 #define SS1_MAPMASK_SHIFT               0
diff-tree da5efb09d55291ce5bcabff7db8d1490bb5e838b (from 36aa43bf73ee1268f0a250788eb637a4123f08eb)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Wed Jul 19 16:36:52 2006 -0400

    Fix the alignment padding fix (didn't bump BEGIN_LP_RING count).

diff --git a/src/i915_3d.h b/src/i915_3d.h
index 5a45882..c116200 100644
--- a/src/i915_3d.h
+++ b/src/i915_3d.h
@@ -436,13 +436,13 @@ do {									\
 
 #define FS_END()							\
 do {									\
-    int _i;								\
-    BEGIN_LP_RING(_cur_shader_commands * 3 + 1);			\
+    int _i, _pad = (_cur_shader_commands & 0x1) ? 0 : 1;		\
+    BEGIN_LP_RING(_cur_shader_commands * 3 + 1 + _pad);			\
     OUT_RING(_3DSTATE_PIXEL_SHADER_PROGRAM |				\
 	     (_cur_shader_commands * 3 - 1));				\
     for (_i = 0; _i < _cur_shader_commands * 3; _i++)			\
 	OUT_RING(_shader_buf[_i]);					\
-    if ((_cur_shader_commands & 0x1) == 0)				\
+    if (_pad != 0)							\
 	OUT_RING(MI_NOOP);						\
     ADVANCE_LP_RING();							\
 } while (0);
diff-tree 36aa43bf73ee1268f0a250788eb637a4123f08eb (from adce6bd0fc9533156da09da7d029ba0d76606b4f)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Wed Jul 19 16:22:46 2006 -0400

    Force texture alpha channels to 1 if not present.

diff --git a/src/i915_3d.h b/src/i915_3d.h
index e9b0194..5a45882 100644
--- a/src/i915_3d.h
+++ b/src/i915_3d.h
@@ -350,8 +350,16 @@ _i915_fs_arith(int cmd, int dest_reg,
     return op;
 }
 
+/** Move operand0 to dest_reg */
+#define i915_fs_mov(dest_reg, operand0)					\
+do {									\
+    FS_OUT(i915_fs_arith(MOV, dest_reg, operand0,			\
+			 i915_fs_operand_none(),			\
+			 i915_fs_operand_none()));			\
+} while (0)
+
 /**
- * Move the values in operand0 to the dest reg with the masking/saturation
+ * Move the value in operand0 to the dest reg with the masking/saturation
  * specified.
  */
 #define i915_fs_mov_masked(dest_reg, dest_mask, operand0)		\
diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
index 0b20e66..a570382 100644
--- a/src/i915_exa_render.c
+++ b/src/i915_exa_render.c
@@ -422,36 +422,40 @@ ErrorF("i915 prepareComposite\n");
 	ADVANCE_LP_RING();
     }
 
-	/* For (src In mask) operation */
-	/* IN operator: Multiply src by mask components or mask alpha.*/
-	/* TEXBLENDOP_MODULE: arg1*arg2 */
-
-	/* LOAD_IMMEDIATE_1 ss6 ??*/
-
-	/****
-	   shader program prototype:
-		dcl t0.xy
-		dcl t1.xy
-		dcl_2d s0   
-		dcl_2d s1
-		texld t0, s0
-		texld t1, s1
-		mul oC, t0, t1 ()
-	***/
     FS_BEGIN();
 
-    if (!pMask) {
-	i915_fs_dcl(FS_S0);
-	i915_fs_dcl(FS_T0);
-	i915_fs_texld(FS_OC, FS_S0, FS_T0);
-    } else {
-	i915_fs_dcl(FS_S0);
+    /* Declare the registers necessary for our program.  I don't think the
+     * S then T ordering is necessary.
+     */
+    i915_fs_dcl(FS_S0);
+    if (pMask)
 	i915_fs_dcl(FS_S1);
-	i915_fs_dcl(FS_T0);
+    i915_fs_dcl(FS_T0);
+    if (pMask)
 	i915_fs_dcl(FS_T1);
-	i915_fs_texld(FS_R0, FS_S0, FS_T0);
-	i915_fs_texld(FS_R1, FS_S1, FS_T1);
 
+    /* Load the pSrcPicture texel */
+    i915_fs_texld(FS_R0, FS_S0, FS_T0);
+    /* If the texture lacks an alpha channel, force the alpha to 1. */
+    if (PICT_FORMAT_A(pSrcPicture->format) == 0)
+	i915_fs_mov_masked(FS_R0, MASK_W, i915_fs_operand_one());
+
+    if (!pMask) {
+	/* No mask, so move to output color */
+	i915_fs_mov(FS_OC, i915_fs_operand_reg(FS_R0));
+    } else {
+	/* Load the pMaskPicture texel */
+	i915_fs_texld(FS_R1, FS_S1, FS_T1);
+	/* If the texture lacks an alpha channel, force the alpha to 1. */
+	if (PICT_FORMAT_A(pMaskPicture->format) == 0)
+	    i915_fs_mov_masked(FS_R1, MASK_W, i915_fs_operand_one());
+
+	/* If component alpha is set in the mask, then we need to provide
+	 * the source alpha component (channelwise multiplication) as the
+	 * output color.  If it isn't set, then we need to provide the
+	 * source value component, which is the multipliction of the source
+	 * by the mask alpha.
+	 */
 	if (pMaskPicture->componentAlpha && pDstPicture->format != PICT_a8) {
 	    i915_fs_mul(FS_OC, i915_fs_operand_reg(FS_R0),
 			i915_fs_operand_reg(FS_R1));
diff-tree adce6bd0fc9533156da09da7d029ba0d76606b4f (from 4e409ea44180f7ef2780d70c9d2f54629bbd0fc3)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Wed Jul 19 16:21:49 2006 -0400

    Add a trailing MI_NOOP to frag shader output for alignment if necessary.

diff --git a/src/i915_3d.h b/src/i915_3d.h
index f254c86..e9b0194 100644
--- a/src/i915_3d.h
+++ b/src/i915_3d.h
@@ -434,5 +434,7 @@ do {									\
 	     (_cur_shader_commands * 3 - 1));				\
     for (_i = 0; _i < _cur_shader_commands * 3; _i++)			\
 	OUT_RING(_shader_buf[_i]);					\
+    if ((_cur_shader_commands & 0x1) == 0)				\
+	OUT_RING(MI_NOOP);						\
     ADVANCE_LP_RING();							\
 } while (0);
diff-tree 4e409ea44180f7ef2780d70c9d2f54629bbd0fc3 (from 449e4be503c8b938d5bd46ee810244f8bcf54ceb)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Wed Jul 19 15:57:09 2006 -0400

    The map bits per pixel must come from the drawable, not the visible screen.

diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
index 181fb89..0b20e66 100644
--- a/src/i915_exa_render.c
+++ b/src/i915_exa_render.c
@@ -260,9 +260,9 @@ I915TextureSetup(PicturePtr pPict, Pixma
 
     {
 	CARD32 ms3;
-	if (pI830->cpp == 1)
+	if (pPix->drawable.bitsPerPixel == 8)
 		format |= MAPSURF_8BIT;
-	else if (pI830->cpp == 2)
+	else if (pPix->drawable.bitsPerPixel == 16)
 		format |= MAPSURF_16BIT;
 	else
 		format |= MAPSURF_32BIT;
diff-tree 449e4be503c8b938d5bd46ee810244f8bcf54ceb (from f1b62d890ca22e12d61f7ef67bc4e35d68cde019)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Wed Jul 19 13:34:06 2006 -0400

    Correct the DWORD count of several 3D instructions.

diff --git a/src/i915_3d.c b/src/i915_3d.c
index d8edb18..942dbd1 100644
--- a/src/i915_3d.c
+++ b/src/i915_3d.c
@@ -77,9 +77,7 @@ void I915EmitInvarientState( ScrnInfoPtr
 
    /* Need to initialize this to zero.
     */
-   OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | 
-	     I1_LOAD_S(3) |
-	     (1));
+   OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | 0);
    OUT_RING(0);
  
    /* XXX: Use this */
diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
index 4249869..181fb89 100644
--- a/src/i915_exa_render.c
+++ b/src/i915_exa_render.c
@@ -268,7 +268,7 @@ I915TextureSetup(PicturePtr pPict, Pixma
 		format |= MAPSURF_32BIT;
 
 	BEGIN_LP_RING(6);
-	OUT_RING(_3DSTATE_MAP_STATE | (3 * (1 << unit)));
+	OUT_RING(_3DSTATE_MAP_STATE | 3);
 	OUT_RING(1<<unit);
 	OUT_RING(offset&MS2_ADDRESS_MASK);
 	ms3 = (pPix->drawable.height << MS3_HEIGHT_SHIFT) | 
@@ -286,7 +286,7 @@ I915TextureSetup(PicturePtr pPict, Pixma
 	BEGIN_LP_RING(6);
 	/* max & min mip level ? or base mip level? */
 
-	OUT_RING(_3DSTATE_SAMPLER_STATE | (3*(1<<unit)));
+	OUT_RING(_3DSTATE_SAMPLER_STATE | 3);
 	OUT_RING(1<<unit);
 	ss2 = (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT);
 	ss2 |= filter;
@@ -390,8 +390,8 @@ ErrorF("i915 prepareComposite\n");
 	OUT_RING(0);
 	
 	/* XXX:S3? define vertex format with tex coord sets number*/
-	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1|I1_LOAD_S(2)|I1_LOAD_S(3)|
-		I1_LOAD_S(4)|3);
+	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) |
+		 I1_LOAD_S(3) | I1_LOAD_S(4) | 2);
 	ss2 = S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D);
 	if (pMask)
 		ss2 |= S2_TEXCOORD_FMT(1, TEXCOORDFMT_2D);
@@ -467,7 +467,7 @@ ErrorF("i915 prepareComposite\n");
 	blendctl = I915GetBlendCntl(op, pMaskPicture, pDstPicture->format);
 
 	BEGIN_LP_RING(2);
-	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(6) | 1);
+	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(6) | 0);
 	ss6 = S6_CBUF_BLEND_ENABLE | S6_COLOR_WRITE_ENABLE;
 	OUT_RING(ss6 | (0 << S6_CBUF_BLEND_FUNC_SHIFT) | blendctl);
 	ADVANCE_LP_RING();
diff-tree f1b62d890ca22e12d61f7ef67bc4e35d68cde019 (from 76a316d0cec92a04c8735926a76e76c21f960d7e)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Wed Jul 19 13:02:24 2006 -0400

    Replace hand register setting with new i915 fragmet program API.

diff --git a/src/i915_3d.h b/src/i915_3d.h
index fc4ca60..f254c86 100644
--- a/src/i915_3d.h
+++ b/src/i915_3d.h
@@ -375,6 +375,13 @@ do {									\
 			 i915_fs_operand_none()));			\
 } while (0)
 
+/** Add operand0 and operand1 and put the result in dest_reg */
+#define i915_fs_mul(dest_reg, operand0, operand1)			\
+do {									\
+    FS_OUT(i915_fs_arith(MUL, dest_reg, operand0, operand1,		\
+			 i915_fs_operand_none()));			\
+} while (0)
+
 /**
  * Perform a 3-component dot-product of operand0 and operand1 and put the
  * resulting scalar in the channels of dest_reg specified by the dest_mask.
diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
index 60b8125..4249869 100644
--- a/src/i915_exa_render.c
+++ b/src/i915_exa_render.c
@@ -1,3 +1,5 @@
+/* -*- c-basic-offset: 4 -*- */
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
@@ -5,6 +7,7 @@
 #include "xf86.h"
 #include "i830.h"
 #include "i915_reg.h"
+#include "i915_3d.h"
 
 #ifdef I830DEBUG
 #define DEBUG_I830FALLBACK 1
@@ -36,7 +39,8 @@ struct formatinfo {
 struct blendinfo {
     Bool dst_alpha;
     Bool src_alpha;
-    CARD32 blend_cntl;
+    CARD32 src_blend;
+    CARD32 dst_blend;
 };
 
 extern Bool
@@ -48,96 +52,33 @@ I915EXAPrepareComposite(int op, PictureP
 			PicturePtr pMaskPicture, PicturePtr pDstPicture,
 			PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst);
 
-/* copy from Eric's texture-video branch, move to header.. */
-#define OUT_DCL(type, nr) do {                                          \
-   CARD32 chans = 0;                                                    \
-   if (REG_TYPE_##type == REG_TYPE_T)                                   \
-      chans = D0_CHANNEL_ALL;                                           \
-   else if (REG_TYPE_##type != REG_TYPE_S)                              \
-      FatalError("wrong reg type %d to declare\n", REG_TYPE_##type);    \
-   OUT_RING(D0_DCL |                                                    \
-            (REG_TYPE_##type << D0_TYPE_SHIFT) | (nr << D0_NR_SHIFT) |  \
-            chans);                                                     \
-   OUT_RING(0x00000000);                                                \
-   OUT_RING(0x00000000);                                                \
-} while (0)
-
-#define OUT_TEXLD(dest_type, dest_nr, sampler_nr, addr_type, addr_nr)   \
-do {                                                                    \
-      OUT_RING(T0_TEXLD |                                               \
-               (REG_TYPE_##dest_type << T0_DEST_TYPE_SHIFT) |           \
-               (dest_nr << T0_DEST_NR_SHIFT) |                          \
-               (sampler_nr << T0_SAMPLER_NR_SHIFT));                    \
-      OUT_RING((REG_TYPE_##addr_type << T1_ADDRESS_REG_TYPE_SHIFT) |    \
-               (addr_nr << T1_ADDRESS_REG_NR_SHIFT));                   \
-      OUT_RING(0x00000000);                                             \
-} while (0)
-
-/* XXX: It seems that offset of 915's blendfactor in Load_immediate_1
-   is _different_ with i830, so I should just define plain value
-   and use it with shift bits*/
-
-#define I915_SRC_BLENDFACTOR_ZERO 		(1 << 8)
-#define I915_SRC_BLENDFACTOR_ONE 		(2 << 8)
-#define I915_SRC_BLENDFACTOR_SRC_COLOR		(3 << 8)
-#define I915_SRC_BLENDFACTOR_INV_SRC_COLOR	(4 << 8)
-#define I915_SRC_BLENDFACTOR_SRC_ALPHA		(5 << 8)
-#define I915_SRC_BLENDFACTOR_INV_SRC_ALPHA	(6 << 8)
-#define I915_SRC_BLENDFACTOR_DST_ALPHA		(7 << 8)
-#define I915_SRC_BLENDFACTOR_INV_DST_ALPHA	(8 << 8)
-#define I915_SRC_BLENDFACTOR_DST_COLOR		(9 << 8)
-#define I915_SRC_BLENDFACTOR_INV_DST_COLOR	(0xa << 8)
-#define I915_SRC_BLENDFACTOR_SRC_ALPHA_SATURATE (0xb << 8)
-#define I915_SRC_BLENDFACTOR_CONST_COLOR	(0xc << 8)
-#define I915_SRC_BLENDFACTOR_INV_CONST_COLOR	(0xd << 8)
-#define I915_SRC_BLENDFACTOR_CONST_ALPHA	(0xe << 8)
-#define I915_SRC_BLENDFACTOR_INV_CONST_ALPHA	(0xf << 8)
-#define I915_SRC_BLENDFACTOR_MASK		(0xf << 8)
-
-#define I915_DST_BLENDFACTOR_ZERO 		(1 << 4)
-#define I915_DST_BLENDFACTOR_ONE 		(2 << 4)
-#define I915_DST_BLENDFACTOR_SRC_COLOR		(3 << 4)
-#define I915_DST_BLENDFACTOR_INV_SRC_COLOR	(4 << 4)
-#define I915_DST_BLENDFACTOR_SRC_ALPHA		(5 << 4)
-#define I915_DST_BLENDFACTOR_INV_SRC_ALPHA	(6 << 4)
-#define I915_DST_BLENDFACTOR_DST_ALPHA		(7 << 4)
-#define I915_DST_BLENDFACTOR_INV_DST_ALPHA	(8 << 4)
-#define I915_DST_BLENDFACTOR_DST_COLOR		(9 << 4)
-#define I915_DST_BLENDFACTOR_INV_DST_COLOR	(0xa << 4)
-#define I915_DST_BLENDFACTOR_SRC_ALPHA_SATURATE (0xb << 4)
-#define I915_DST_BLENDFACTOR_CONST_COLOR	(0xc << 4)
-#define I915_DST_BLENDFACTOR_INV_CONST_COLOR	(0xd << 4)
-#define I915_DST_BLENDFACTOR_CONST_ALPHA	(0xe << 4)
-#define I915_DST_BLENDFACTOR_INV_CONST_ALPHA	(0xf << 4)
-#define I915_DST_BLENDFACTOR_MASK		(0xf << 4)
-
 static struct blendinfo I915BlendOp[] = { 
     /* Clear */
-    {0, 0, I915_SRC_BLENDFACTOR_ZERO           | I915_DST_BLENDFACTOR_ZERO},
+    {0, 0, BLENDFACT_ZERO,          BLENDFACT_ZERO},
     /* Src */
-    {0, 0, I915_SRC_BLENDFACTOR_ONE            | I915_DST_BLENDFACTOR_ZERO},
+    {0, 0, BLENDFACT_ONE,           BLENDFACT_ZERO},
     /* Dst */
-    {0, 0, I915_SRC_BLENDFACTOR_ZERO           | I915_DST_BLENDFACTOR_ONE},
+    {0, 0, BLENDFACT_ZERO,          BLENDFACT_ONE},
     /* Over */
-    {0, 1, I915_SRC_BLENDFACTOR_ONE            | I915_DST_BLENDFACTOR_INV_SRC_ALPHA},
+    {0, 1, BLENDFACT_ONE,           BLENDFACT_INV_SRC_ALPHA},
     /* OverReverse */
-    {1, 0, I915_SRC_BLENDFACTOR_INV_DST_ALPHA | I915_DST_BLENDFACTOR_ONE},
+    {1, 0, BLENDFACT_INV_DST_ALPHA, BLENDFACT_ONE},
     /* In */
-    {1, 0, I915_SRC_BLENDFACTOR_DST_ALPHA     | I915_DST_BLENDFACTOR_ZERO},
+    {1, 0, BLENDFACT_DST_ALPHA,     BLENDFACT_ZERO},
     /* InReverse */
-    {0, 1, I915_SRC_BLENDFACTOR_ZERO           | I915_DST_BLENDFACTOR_SRC_ALPHA},
+    {0, 1, BLENDFACT_ZERO,          BLENDFACT_SRC_ALPHA},
     /* Out */
-    {1, 0, I915_SRC_BLENDFACTOR_INV_DST_ALPHA | I915_DST_BLENDFACTOR_ZERO},
+    {1, 0, BLENDFACT_INV_DST_ALPHA, BLENDFACT_ZERO},
     /* OutReverse */
-    {0, 1, I915_SRC_BLENDFACTOR_ZERO           | I915_DST_BLENDFACTOR_INV_SRC_ALPHA},
+    {0, 1, BLENDFACT_ZERO,          BLENDFACT_INV_SRC_ALPHA},
     /* Atop */
-    {1, 1, I915_SRC_BLENDFACTOR_DST_ALPHA     | I915_DST_BLENDFACTOR_INV_SRC_ALPHA},
+    {1, 1, BLENDFACT_DST_ALPHA,     BLENDFACT_INV_SRC_ALPHA},
     /* AtopReverse */
-    {1, 1, I915_SRC_BLENDFACTOR_INV_DST_ALPHA | I915_DST_BLENDFACTOR_SRC_ALPHA},
+    {1, 1, BLENDFACT_INV_DST_ALPHA, BLENDFACT_SRC_ALPHA},
     /* Xor */
-    {1, 1, I915_SRC_BLENDFACTOR_INV_DST_ALPHA | I915_DST_BLENDFACTOR_INV_SRC_ALPHA},
+    {1, 1, BLENDFACT_INV_DST_ALPHA, BLENDFACT_INV_SRC_ALPHA},
     /* Add */
-    {0, 0, I915_SRC_BLENDFACTOR_ONE            | I915_DST_BLENDFACTOR_ONE},
+    {0, 0, BLENDFACT_ONE,           BLENDFACT_ONE},
 };
 
 static struct formatinfo I915TexFormats[] = {
@@ -155,17 +96,17 @@ static CARD32 I915GetBlendCntl(int op, P
 {
     CARD32 sblend, dblend;
 
-    sblend = I915BlendOp[op].blend_cntl & I915_SRC_BLENDFACTOR_MASK;
-    dblend = I915BlendOp[op].blend_cntl & I915_DST_BLENDFACTOR_MASK;
+    sblend = I915BlendOp[op].src_blend;
+    dblend = I915BlendOp[op].dst_blend;
 
     /* If there's no dst alpha channel, adjust the blend op so that we'll treat
      * it as always 1.
      */
     if (PICT_FORMAT_A(dst_format) == 0 && I915BlendOp[op].dst_alpha) {
-        if (sblend == I915_SRC_BLENDFACTOR_DST_ALPHA)
-            sblend = I915_SRC_BLENDFACTOR_ONE;
-        else if (sblend == I915_SRC_BLENDFACTOR_INV_DST_ALPHA)
-            sblend = I915_SRC_BLENDFACTOR_ZERO;
+        if (sblend == BLENDFACT_DST_ALPHA)
+            sblend = BLENDFACT_ONE;
+        else if (sblend == BLENDFACT_INV_DST_ALPHA)
+            sblend = BLENDFACT_ZERO;
     }
 
     /* If the source alpha is being used, then we should only be in a case where
@@ -173,14 +114,15 @@ static CARD32 I915GetBlendCntl(int op, P
      * channels multiplied by the source picture's alpha.
      */
     if (pMask && pMask->componentAlpha && I915BlendOp[op].src_alpha) {
-        if (dblend == I915_DST_BLENDFACTOR_SRC_ALPHA) {
-            dblend = I915_DST_BLENDFACTOR_SRC_COLOR;
-        } else if (dblend == I915_DST_BLENDFACTOR_INV_SRC_ALPHA) {
-            dblend = I915_DST_BLENDFACTOR_INV_SRC_COLOR;
+        if (dblend == BLENDFACT_SRC_ALPHA) {
+	    dblend = BLENDFACT_SRC_COLR;
+        } else if (dblend == BLENDFACT_INV_SRC_ALPHA) {
+	    dblend = BLENDFACT_INV_SRC_COLR;
         }
     }
 
-    return sblend | dblend;
+    return (sblend <<S6_CBUF_SRC_BLEND_FACT_SHIFT) |
+	(dblend <<S6_CBUF_DST_BLEND_FACT_SHIFT);
 }
 
 static Bool I915GetDestFormat(PicturePtr pDstPicture, CARD32 *dst_format)
@@ -257,8 +199,7 @@ I915EXACheckComposite(int op, PicturePtr
          * source value that we get to blend with.
          */
         if (I915BlendOp[op].src_alpha &&
-            (I915BlendOp[op].blend_cntl & I915_SRC_BLENDFACTOR_MASK) !=
-             I915_SRC_BLENDFACTOR_ZERO)
+            (I915BlendOp[op].src_blend != BLENDFACT_ZERO))
             	I830FALLBACK("Component alpha not supported with source "
                             "alpha and source value blending.\n");
     }
@@ -410,6 +351,7 @@ ErrorF("i915 prepareComposite\n");
     draw_coords[2][1] = pDst->drawable.y;
     scale_units[2][0] = pDst->drawable.width;
     scale_units[2][1] = pDst->drawable.height;
+    FS_LOCALS(20);
     
     I915DefCtxSetup(pScrn);
 
@@ -426,6 +368,7 @@ ErrorF("i915 prepareComposite\n");
 
     {
 	CARD32 ss2;
+
 	BEGIN_LP_RING(24);
 	/*color buffer*/
 	OUT_RING(_3DSTATE_BUF_INFO_CMD);
@@ -495,46 +438,30 @@ ErrorF("i915 prepareComposite\n");
 		texld t1, s1
 		mul oC, t0, t1 ()
 	***/
+    FS_BEGIN();
+
     if (!pMask) {
-	BEGIN_LP_RING(1+3+3+3);
-	OUT_RING(_3DSTATE_PIXEL_SHADER_PROGRAM |(3*3-1));
-	OUT_DCL(S, 0);
-	OUT_DCL(T, 0);
-	OUT_TEXLD(OC, 0, 0, T, 0);
-	ADVANCE_LP_RING();
+	i915_fs_dcl(FS_S0);
+	i915_fs_dcl(FS_T0);
+	i915_fs_texld(FS_OC, FS_S0, FS_T0);
     } else {
-	BEGIN_LP_RING(1+3*6+3);
-	OUT_RING(_3DSTATE_PIXEL_SHADER_PROGRAM |(3*7-1));
-	OUT_DCL(S, 0);
-	OUT_DCL(S, 1);
-	OUT_DCL(T, 0);
-	OUT_DCL(T, 1);
-	OUT_TEXLD(R, 0, 0, T, 0);
-	OUT_TEXLD(R, 1, 1, T, 1);
+	i915_fs_dcl(FS_S0);
+	i915_fs_dcl(FS_S1);
+	i915_fs_dcl(FS_T0);
+	i915_fs_dcl(FS_T1);
+	i915_fs_texld(FS_R0, FS_S0, FS_T0);
+	i915_fs_texld(FS_R1, FS_S1, FS_T1);
+
 	if (pMaskPicture->componentAlpha && pDstPicture->format != PICT_a8) {
-		/* then just mul */
-		OUT_RING(A0_MUL | (REG_TYPE_OC << A0_DEST_TYPE_SHIFT) | 
-			(0 << A0_DEST_NR_SHIFT) | A0_DEST_CHANNEL_ALL | 
-			(REG_TYPE_R << A0_SRC0_TYPE_SHIFT) | (0 << A0_SRC0_NR_SHIFT));
-		OUT_RING((SRC_X << A1_SRC0_CHANNEL_X_SHIFT)|(SRC_Y << A1_SRC0_CHANNEL_Y_SHIFT)|
-			(SRC_Z << A1_SRC0_CHANNEL_Z_SHIFT)|(SRC_W << A1_SRC0_CHANNEL_W_SHIFT)|
-			(REG_TYPE_R << A1_SRC1_TYPE_SHIFT) | (1 << A1_SRC1_NR_SHIFT) |
-			(SRC_X << A1_SRC1_CHANNEL_X_SHIFT) | (SRC_Y << A1_SRC1_CHANNEL_Y_SHIFT));
-		OUT_RING((SRC_Z << A2_SRC1_CHANNEL_Z_SHIFT) | (SRC_W << A2_SRC1_CHANNEL_W_SHIFT));
+	    i915_fs_mul(FS_OC, i915_fs_operand_reg(FS_R0),
+			i915_fs_operand_reg(FS_R1));
 	} else {
-		/* we should duplicate R1's w for all channel, Arithemic can choose channel to use! */
-		OUT_RING(A0_MUL | (REG_TYPE_OC << A0_DEST_TYPE_SHIFT) |
-			(0 << A0_DEST_NR_SHIFT) | A0_DEST_CHANNEL_ALL |
-			(REG_TYPE_R << A0_SRC0_TYPE_SHIFT) | (0 << A0_SRC0_NR_SHIFT));
-		OUT_RING((SRC_X << A1_SRC0_CHANNEL_X_SHIFT) | (SRC_Y << A1_SRC0_CHANNEL_Y_SHIFT) |
-			(SRC_Z << A1_SRC0_CHANNEL_Z_SHIFT) | (SRC_W << A1_SRC0_CHANNEL_W_SHIFT) |
-			(REG_TYPE_R << A1_SRC1_TYPE_SHIFT) | (1 << A1_SRC1_NR_SHIFT) |
-			(SRC_W << A1_SRC1_CHANNEL_X_SHIFT) | (SRC_W << A1_SRC1_CHANNEL_Y_SHIFT));
-		OUT_RING((SRC_W << A2_SRC1_CHANNEL_Z_SHIFT) | (SRC_W << A2_SRC1_CHANNEL_W_SHIFT));
+	    i915_fs_mul(FS_OC, i915_fs_operand_reg(FS_R0),
+			i915_fs_operand(FS_R1, W, W, W, W));
 	}
-	ADVANCE_LP_RING();
     }
-		
+    FS_END();
+
     {
 	CARD32 ss6;
 	blendctl = I915GetBlendCntl(op, pMaskPicture, pDstPicture->format);
diff-tree 76a316d0cec92a04c8735926a76e76c21f960d7e (from parents)
Merge: 433cb6ba82698676f6f72e09834aba4d64611d54 84805167ab8a422966355b9753bfcb4dad802413
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Wed Jul 19 12:31:36 2006 -0400

    Merge branch 'master' into exa
    
    Conflicts:
    
    	src/Makefile.am

diff --cc src/Makefile.am
index 9c2a5c2,f97dc52..c2e49ac
@@@ -58,11 -58,8 +58,12 @@@
  	 i830_3d.c \
  	 i830_reg.h \
  	 i915_3d.c \
+ 	 i915_3d.h \
 -	 i915_reg.h
 +	 i915_reg.h \
 +	 i830_exa.c \
 +	 i830_xaa.c \
 +	 i830_exa_render.c \
 +	 i915_exa_render.c
  
  if DRI
  i810_drv_la_SOURCES += \
diff-tree 433cb6ba82698676f6f72e09834aba4d64611d54 (from 855a9f13cb7fd4f6c489ff280bf389475bbd9bbe)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Tue Jul 18 17:00:50 2006 +0800

    Fix several size error with STATE3D_LOAD_STATE_IMMEDIATE cmd.
    Issue texture coord set with proper scale value.

diff --git a/src/i830_exa.c b/src/i830_exa.c
index 40f6868..3975e6d 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -55,7 +55,7 @@ do { 							\
 } while(0) 
 #endif
 
-float scale_units[2][2];
+float scale_units[3][2];
 int draw_coords[3][2];
 
 const int I830CopyROP[16] =
@@ -101,7 +101,7 @@ const int I830PatternROP[16] =
 /* move to common.h */
 union intfloat {
 	float f;
-	unsigned int ui;
+	CARD32 ui;
 };
 
 #define OUT_RING_F(x) do {			\
@@ -429,6 +429,7 @@ IntelEXAComposite(PixmapPtr pDst, int sr
     int srcXend, srcYend, maskXend, maskYend;
     PictVector v;
     int pMask = 1;
+    float src_scale_x, src_scale_y, mask_scale_x, mask_scale_y;
 
     DPRINTF(PFX, "Composite: srcX %d, srcY %d\n\t maskX %d, maskY %d\n\t"
 	     "dstX %d, dstY %d\n\twidth %d, height %d\n\t"
@@ -483,9 +484,14 @@ IntelEXAComposite(PixmapPtr pDst, int sr
 
     draw_coords[0][0] -= draw_coords[2][0];
     draw_coords[0][1] -= draw_coords[2][1];
+    src_scale_x = (float)scale_units[0][0] / (float)scale_units[2][0];
+    src_scale_y = (float)scale_units[0][1] / (float)scale_units[2][1];
+
     if (pMask) {
 	draw_coords[1][0] -= draw_coords[2][0];
 	draw_coords[1][1] -= draw_coords[2][1];
+	mask_scale_x = (float)scale_units[1][0] / (float)scale_units[2][0];
+	mask_scale_y = (float)scale_units[1][1] / (float)scale_units[2][1];
     }
 
     {
@@ -506,40 +512,40 @@ IntelEXAComposite(PixmapPtr pDst, int sr
 
 	OUT_RING(PRIM3D_INLINE | PRIM3D_TRIFAN | (vertex_count-1));
 
-	OUT_RING(dstX);
-	OUT_RING(dstY);
-	OUT_RING_F(((srcX - draw_coords[0][0]) / scale_units[0][0]));
-	OUT_RING_F(((srcY - draw_coords[0][1]) / scale_units[0][1]));
+	OUT_RING_F(dstX);
+	OUT_RING_F(dstY);
+	OUT_RING_F(((srcX - draw_coords[0][0]) * src_scale_x));
+	OUT_RING_F(((srcY - draw_coords[0][1]) * src_scale_y));
 	if (pMask) {
-		OUT_RING_F(((maskX - draw_coords[1][0]) / scale_units[1][0]));
-		OUT_RING_F(((maskY - draw_coords[1][1]) / scale_units[1][1]));
+		OUT_RING_F(((maskX - draw_coords[1][0]) * mask_scale_x));
+		OUT_RING_F(((maskY - draw_coords[1][1]) * mask_scale_y));
 	}
 
-	OUT_RING(dstX);
-	OUT_RING((dstY+h));
-	OUT_RING_F(((srcX - draw_coords[0][0]) / scale_units[0][0]));
-	OUT_RING_F(((srcYend - draw_coords[0][1]) / scale_units[0][1]));
+	OUT_RING_F(dstX);
+	OUT_RING_F((dstY+h));
+	OUT_RING_F(((srcX - draw_coords[0][0]) * src_scale_x));
+	OUT_RING_F(((srcYend - draw_coords[0][1]) * src_scale_y));
 	if (pMask) {
-		OUT_RING_F(((maskX - draw_coords[1][0]) / scale_units[1][0]));
-		OUT_RING_F(((maskYend - draw_coords[1][1]) / scale_units[1][1]));
+		OUT_RING_F(((maskX - draw_coords[1][0]) * mask_scale_x));
+		OUT_RING_F(((maskYend - draw_coords[1][1]) * mask_scale_y));
 	}
 
-	OUT_RING((dstX+w));
-	OUT_RING((dstY+h));
-	OUT_RING_F(((srcXend - draw_coords[0][0]) / scale_units[0][0]));
-	OUT_RING_F(((srcYend - draw_coords[0][1]) / scale_units[0][1]));
+	OUT_RING_F((dstX+w));
+	OUT_RING_F((dstY+h));
+	OUT_RING_F(((srcXend - draw_coords[0][0]) * src_scale_x));
+	OUT_RING_F(((srcYend - draw_coords[0][1]) * src_scale_y));
 	if (pMask) {
-		OUT_RING_F(((maskXend - draw_coords[1][0]) / scale_units[1][0]));
-		OUT_RING_F(((maskYend - draw_coords[1][1]) / scale_units[1][1]));
+		OUT_RING_F(((maskXend - draw_coords[1][0]) * mask_scale_x));
+		OUT_RING_F(((maskYend - draw_coords[1][1]) * mask_scale_y));
 	}
 
-	OUT_RING((dstX+w));
-	OUT_RING((dstY));
-	OUT_RING_F(((srcXend - draw_coords[0][0]) / scale_units[0][0]));
-	OUT_RING_F(((srcY - draw_coords[0][1]) / scale_units[0][1]));
+	OUT_RING_F((dstX+w));
+	OUT_RING_F((dstY));
+	OUT_RING_F(((srcXend - draw_coords[0][0]) * src_scale_x));
+	OUT_RING_F(((srcY - draw_coords[0][1]) * src_scale_y));
 	if (pMask) {
-		OUT_RING_F(((maskXend - draw_coords[1][0]) / scale_units[1][0]));
-		OUT_RING_F(((maskY - draw_coords[1][1]) / scale_units[1][1]));
+		OUT_RING_F(((maskXend - draw_coords[1][0]) * mask_scale_x));
+		OUT_RING_F(((maskY - draw_coords[1][1]) * mask_scale_y));
 	}
 	ADVANCE_LP_RING();
     }
diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
index acec69f..60b8125 100644
--- a/src/i915_exa_render.c
+++ b/src/i915_exa_render.c
@@ -408,6 +408,8 @@ ErrorF("i915 prepareComposite\n");
     dst_pitch = exaGetPixmapPitch(pDst);
     draw_coords[2][0] = pDst->drawable.x;
     draw_coords[2][1] = pDst->drawable.y;
+    scale_units[2][0] = pDst->drawable.width;
+    scale_units[2][1] = pDst->drawable.height;
     
     I915DefCtxSetup(pScrn);
 
@@ -446,7 +448,7 @@ ErrorF("i915 prepareComposite\n");
 	
 	/* XXX:S3? define vertex format with tex coord sets number*/
 	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1|I1_LOAD_S(2)|I1_LOAD_S(3)|
-		I1_LOAD_S(4)|1);
+		I1_LOAD_S(4)|3);
 	ss2 = S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D);
 	if (pMask)
 		ss2 |= S2_TEXCOORD_FMT(1, TEXCOORDFMT_2D);
@@ -538,7 +540,7 @@ ErrorF("i915 prepareComposite\n");
 	blendctl = I915GetBlendCntl(op, pMaskPicture, pDstPicture->format);
 
 	BEGIN_LP_RING(2);
-	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(6) | 0);
+	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(6) | 1);
 	ss6 = S6_CBUF_BLEND_ENABLE | S6_COLOR_WRITE_ENABLE;
 	OUT_RING(ss6 | (0 << S6_CBUF_BLEND_FUNC_SHIFT) | blendctl);
 	ADVANCE_LP_RING();
diff-tree 855a9f13cb7fd4f6c489ff280bf389475bbd9bbe (from 04d1584737fd0d14e99608a97281fd7b1549ae0e)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Tue Jul 18 10:02:47 2006 +0800

    fallback in 'repeat' case for now

diff --git a/src/i830_exa.c b/src/i830_exa.c
index 83601dc..40f6868 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -340,8 +340,10 @@ I830EXAUploadToScreen(PixmapPtr pDst, in
 
     I830Sync(pScrn);
 
+#ifdef I830DEBUG
     ErrorF("Up->Screen: dst offset 0x%x, dst pitch %d, x %d, y %d, src %p, src pitch %d\n",
 		dst_offset, dst_pitch, x, y, src, src_pitch);
+#endif
 #ifndef UPLOAD_USE_BLIT
     dst = pI830->FbBase + dst_offset + y*dst_pitch + 
 		x* (pDst->drawable.bitsPerPixel/8);
@@ -403,8 +405,10 @@ I830EXADownloadFromScreen(PixmapPtr pSrc
 
     I830Sync(pScrn);
 
+#ifdef I830DEBUG
     ErrorF("Screen->Mem: src offset 0x%x, src %p, src pitch %d, x %d, y %d, dst %p, dst_pitch %d\n",
 	src_offset, src, src_pitch, x, y, dst, dst_pitch);
+#endif
     w *= pSrc->drawable.bitsPerPixel/8;
     while(h--) {
 	memcpy(dst, src, w);
@@ -426,7 +430,7 @@ IntelEXAComposite(PixmapPtr pDst, int sr
     PictVector v;
     int pMask = 1;
 
-ErrorF("Composite: srcX %d, srcY %d\n\t maskX %d, maskY %d\n\t"
+    DPRINTF(PFX, "Composite: srcX %d, srcY %d\n\t maskX %d, maskY %d\n\t"
 	     "dstX %d, dstY %d\n\twidth %d, height %d\n\t"
 	     "src_scale_x %f, src_scale_y %f, mask_scale_x %f, mask_scale_y %f\n""\tdx0 %d, dy0 %x, dx1 %d dy1 %x\n", 
 		srcX, srcY, maskX, maskY, dstX, dstY, w, h,
@@ -472,7 +476,7 @@ ErrorF("Composite: srcX %d, srcY %d\n\t 
         maskXend = xFixedToInt(v.vector[0]);
         maskYend = xFixedToInt(v.vector[1]);
     }
-DPRINTF(PFX, "After transform: srcX %d, srcY %d,srcXend %d, srcYend %d\n\t"
+    DPRINTF(PFX, "After transform: srcX %d, srcY %d,srcXend %d, srcYend %d\n\t"
 		"maskX %d, maskY %d, maskXend %d, maskYend %d\n\t"
 		"dstX %d, dstY %d\n", srcX, srcY, srcXend, srcYend,
 		maskX, maskY, maskXend, maskYend, dstX, dstY);
diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
index 68c929e..acec69f 100644
--- a/src/i915_exa_render.c
+++ b/src/i915_exa_render.c
@@ -231,8 +231,8 @@ static Bool I915CheckCompositeTexture(Pi
                          (int)pPict->format);
 
     /* FIXME: fix repeat support */
-    if (pPict->repeat && ((w&(w-1)) != 0) && ((h&(h-1)) != 0))
-	I830FALLBACK("repeat non log2 aligned!\n");
+    if (pPict->repeat) 
+	I830FALLBACK("repeat not support now!\n");
 
     if (pPict->filter != PictFilterNearest &&
         pPict->filter != PictFilterBilinear)
diff-tree a6d438ebe3cf141a0331e0cd55eb9b5e137a5e37 (from c7083a267209c93b2a91ef00dea2ca840400d160)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Mon Jul 17 14:11:19 2006 -0400

    Disable spread spectrum clock usage.
    
    The spread spectrum clock generator that improves EMI characteristics for
    laptop screens lives in an external chip that is programmed over an i2c bus.
    Without correct programming, attempts to use this mode for the LVDS can
    result in a DC signal being sent to the panel.
    
    Until we find programming information for this external chip, we should
    leave this mode disabled.

diff --git a/src/i830_display.c b/src/i830_display.c
index 1496c3a..6eb2a33 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -476,8 +476,10 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 
     if (outputs & (PIPE_TV_ACTIVE | PIPE_TV2_ACTIVE))
 	dpll |= PLL_REF_INPUT_TVCLKINBC;
+#if 0    
     else if (outputs & (PIPE_LCD_ACTIVE))
 	dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
+#endif
     else	
 	dpll |= PLL_REF_INPUT_DREFCLK;
 
diff-tree c7083a267209c93b2a91ef00dea2ca840400d160 (from 49b827605628d3e1a6d4d41447cf46c5f38cc0c2)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Fri Jul 14 13:23:40 2006 -0700

    Bug #7404: Only save/restore VGA fonts and not other VGA regs.
    
    This fixes a hang on the i945 during restore.  It appears that saving/restoring
    the VGA registers is not important, as we're correctly saving/restoring the
    registers we touch within the driver anyway.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 396685a..8464b39 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2754,7 +2754,7 @@ SaveHWState(ScrnInfoPtr pScrn)
    }
 
    vgaHWUnlock(hwp);
-   vgaHWSave(pScrn, vgaReg, VGA_SR_ALL);
+   vgaHWSave(pScrn, vgaReg, VGA_SR_FONTS);
 
    return TRUE;
 }
@@ -2773,7 +2773,7 @@ RestoreHWState(ScrnInfoPtr pScrn)
 #ifdef XF86DRI
    I830DRISetVBlankInterrupt (pScrn, FALSE);
 #endif
-   vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL);
+   vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS);
    vgaHWLock(hwp);
 
    /* First, disable display planes */
diff-tree 49b827605628d3e1a6d4d41447cf46c5f38cc0c2 (from 6a92a779646ec03a03a3b1f45170b2e705ce8934)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Fri Jul 14 14:23:04 2006 -0700

    Add a register restore implementation so we don't crash on LeaveVT.
    
    We shouldn't ever need to save/restore the hi/lo frequency regs, as they're
    read-only.

diff --git a/src/sil164/sil164.c b/src/sil164/sil164.c
index a274262..0a68d69 100644
--- a/src/sil164/sil164.c
+++ b/src/sil164/sil164.c
@@ -197,12 +197,6 @@ sil164SaveRegs(I2CDevPtr d)
 {
     SIL164Ptr sil = SILPTR(d);
 
-    if (!sil164ReadByte(sil, SIL164_FREQ_LO, &sil->SavedReg.freq_lo))
-	return;
-
-    if (!sil164ReadByte(sil, SIL164_FREQ_HI, &sil->SavedReg.freq_hi))
-	return;
-
     if (!sil164ReadByte(sil, SIL164_REG8, &sil->SavedReg.reg8))
 	return;
 
@@ -215,6 +209,20 @@ sil164SaveRegs(I2CDevPtr d)
     return;
 }
 
+static void
+sil164RestoreRegs(I2CDevPtr d)
+{
+    SIL164Ptr sil = SILPTR(d);
+
+    /* Restore it powered down initially */
+    sil164WriteByte(sil, SIL164_REG8, sil->SavedReg.reg8 & ~0x1);
+
+    sil164WriteByte(sil, SIL164_REG9, sil->SavedReg.reg9);
+    sil164WriteByte(sil, SIL164_REGC, sil->SavedReg.regc);
+    sil164WriteByte(sil, SIL164_REG8, sil->SavedReg.reg8);
+}
+
+
 I830I2CVidOutputRec SIL164VidOutput = {
     sil164Detect,
     sil164Init,
@@ -223,5 +231,5 @@ I830I2CVidOutputRec SIL164VidOutput = {
     sil164Power,
     sil164PrintRegs,
     sil164SaveRegs,
-    NULL,
+    sil164RestoreRegs,
 };
diff --git a/src/sil164/sil164_reg.h b/src/sil164/sil164_reg.h
index dc2abba..ebfcb8c 100644
--- a/src/sil164/sil164_reg.h
+++ b/src/sil164/sil164_reg.h
@@ -58,8 +58,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define SIL164_REGC 0x0c
 
 typedef struct _Sil164SaveRec {
-    CARD8 freq_lo;
-    CARD8 freq_hi;
     CARD8 reg8;
     CARD8 reg9;
     CARD8 regc;
diff-tree 6a92a779646ec03a03a3b1f45170b2e705ce8934 (from de470aaf5c47f4d2b0f477ac678039ef43af773d)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Fri Jul 14 14:20:41 2006 -0700

    Don't try to probe on more pipes than we really have.

diff --git a/src/i830_modes.c b/src/i830_modes.c
index 1965c39..1c5e7eb 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -895,7 +895,7 @@ I830ValidateXF86ModeList(ScrnInfoPtr pSc
     Bool pipes_reconfigured = FALSE;
     int originalVirtualX, originalVirtualY;
 
-    for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++) {
+    for (pipe = 0; pipe < pI830->availablePipes; pipe++) {
 	I830ReprobePipeModeList(pScrn, pipe);
     }
 
@@ -944,7 +944,7 @@ I830ValidateXF86ModeList(ScrnInfoPtr pSc
 	/* Set up a virtual size that will cover any clone mode we'd want to set
 	 * for either of the two pipes.
 	 */
-	for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++) {
+	for (pipe = 0; pipe < pI830->availablePipes; pipe++) {
 	    MonPtr mon = pI830->pipeMon[pipe];
 	    DisplayModePtr mode;
 
@@ -969,7 +969,7 @@ I830ValidateXF86ModeList(ScrnInfoPtr pSc
      * initially.
      */
     if (!first_time) {
-	for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++) {
+	for (pipe = 0; pipe < pI830->availablePipes; pipe++) {
 	    MonPtr mon = pI830->pipeMon[pipe];
 	    DisplayModePtr mode;
 
diff-tree 04d1584737fd0d14e99608a97281fd7b1549ae0e (from b85f268051a785f90e4c55bd1cac80d673388f16)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Fri Jul 14 16:14:18 2006 +0800

    Current exa render implement for i830 and i915, test on
    865GM and 915G. There is issue in picture 'repeat' support.
    And also stop recursive behavior in I830WaitLpRing to allow
    server to abort instead of system hang.

diff --git a/src/Makefile.am b/src/Makefile.am
index c9e8780..9c2a5c2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -60,7 +60,9 @@ i810_drv_la_SOURCES = \
 	 i915_3d.c \
 	 i915_reg.h \
 	 i830_exa.c \
-	 i830_xaa.c
+	 i830_xaa.c \
+	 i830_exa_render.c \
+	 i915_exa_render.c
 
 if DRI
 i810_drv_la_SOURCES += \
diff --git a/src/i830_accel.c b/src/i830_accel.c
index f299398..6b33887 100644
--- a/src/i830_accel.c
+++ b/src/i830_accel.c
@@ -110,6 +110,9 @@ I830WaitLpRing(ScrnInfoPtr pScrn, int n,
 #ifdef I830_USE_XAA
 	 pI830->AccelInfoRec = NULL;	/* Stops recursive behavior */
 #endif
+#ifdef I830_USE_EXA
+	 pI830->EXADriverPtr = NULL;
+#endif
 	 FatalError("lockup\n");
       }
 
diff --git a/src/i830_exa.c b/src/i830_exa.c
index 665c4d7..83601dc 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -36,9 +36,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "xaarop.h"
 #include "i830.h"
 #include "i810_reg.h"
+#include "i830_reg.h"
 
 #ifdef I830DEBUG
-#define DEBUG_I830FALLBACK 0
+#define DEBUG_I830FALLBACK 1
 #endif
 
 #ifdef DEBUG_I830FALLBACK
@@ -48,9 +49,15 @@ do {							\
 	return FALSE;					\
 } while(0)
 #else
-#define I830FALLBACK(s, arg...) { return FALSE; }
+#define I830FALLBACK(s, arg...) 			\
+do { 							\
+	return FALSE;					\
+} while(0) 
 #endif
 
+float scale_units[2][2];
+int draw_coords[3][2];
+
 const int I830CopyROP[16] =
 {
    ROP_0,               /* GXclear */
@@ -91,12 +98,33 @@ const int I830PatternROP[16] =
     ROP_1
 };
 
-void i830ScratchSave(ScreenPtr pScreen, ExaOffscreenArea *area);
-Bool i830UploadToScreen(PixmapPtr pDst, char *src, int src_pitch);
-Bool i830UploadToScratch(PixmapPtr pSrc, PixmapPtr pDst);
+/* move to common.h */
+union intfloat {
+	float f;
+	unsigned int ui;
+};
+
+#define OUT_RING_F(x) do {			\
+	union intfloat tmp;			\
+	tmp.f = (float)(x);			\
+	OUT_RING(tmp.ui);			\
+} while(0)				
+
+Bool is_transform[2];
+PictTransform *transform[2];
+
+Bool i830UploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, 
+			    char *src, int src_pitch);
 Bool i830DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h,
 			    char *dst, int dst_pitch);
 
+extern Bool I830EXACheckComposite(int, PicturePtr, PicturePtr, PicturePtr);
+extern Bool I830EXAPrepareComposite(int, PicturePtr, PicturePtr, PicturePtr, 
+				PixmapPtr, PixmapPtr, PixmapPtr);
+extern Bool I915EXACheckComposite(int, PicturePtr, PicturePtr, PicturePtr);
+extern Bool I915EXAPrepareComposite(int, PicturePtr, PicturePtr, PicturePtr, 
+				PixmapPtr, PixmapPtr, PixmapPtr);
+
 /**
  * I830EXASync - wait for a command to finish
  * @pScreen: current screen
@@ -295,27 +323,69 @@ I830EXACopy(PixmapPtr pDstPixmap, int sr
 static void
 I830EXADoneCopy(PixmapPtr pDstPixmap)
 {
-    return;
+    	return;
 }
 
-#if 0 /* Not done (or even started for that matter) */
+//#define UPLOAD_USE_BLIT 1
+
 static Bool
-I830EXAUploadToScreen(PixmapPtr pDst, char *src, int src_pitch)
+I830EXAUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, 
+		char *src, int src_pitch)
 {
     ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
-    unsigned char *dst = pDst->devPrivate.ptr;
     int dst_pitch = exaGetPixmapPitch(pDst);
-    int size = src_pitch < dst_pitch ? src_pitch : dst_pitch;
-    int h = pDst->drawable.height;
+    int dst_offset = exaGetPixmapOffset(pDst);
+    unsigned char *dst;
 
     I830Sync(pScrn);
 
+    ErrorF("Up->Screen: dst offset 0x%x, dst pitch %d, x %d, y %d, src %p, src pitch %d\n",
+		dst_offset, dst_pitch, x, y, src, src_pitch);
+#ifndef UPLOAD_USE_BLIT
+    dst = pI830->FbBase + dst_offset + y*dst_pitch + 
+		x* (pDst->drawable.bitsPerPixel/8);
+    w *= pDst->drawable.bitsPerPixel/8;
     while(h--) {
-	i830MemCopyToVideoRam(pI830, dst, (unsigned char *)src, size);
+	memcpy(dst, src, w);
 	src += src_pitch;
 	dst += dst_pitch;
     }
+#else
+    /* setup blit engine to copy one pixel data by one */
+    {
+	int x1, x2, y1, y2, i, j;
+	CARD32 d, len, *srcp;
+	x1 = x;
+	y1 = y;
+	x2 = x + w;
+	y2 = y + h;
+
+	len = (w * (pDst->drawable.bitsPerPixel/8)) >> 2;
+
+	pI830->BR[13] = (1 << 24) | (1 << 25);
+	pI830->BR[13] |= I830CopyROP[GXcopy]<<16;
+	pI830->BR[13] |= dst_pitch & 0xffff;
+	for (i = 0; i < h; i++) {
+		srcp = (CARD32*)src;
+		for ( j = len; j > 0; j--) {
+			d = *srcp;
+			BEGIN_LP_RING(6);
+			OUT_RING(XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA | 
+				XY_COLOR_BLT_WRITE_RGB);
+			OUT_RING(pI830->BR[13]);
+			OUT_RING((y1 << 16) | x1);
+			OUT_RING((y2 << 16) | x2);
+			OUT_RING(dst_offset);
+			OUT_RING(d);
+			ADVANCE_LP_RING();
+			srcp++;
+		}
+		src += src_pitch;
+	}
+
+    }
+#endif
 
     return TRUE;
 }
@@ -326,14 +396,18 @@ I830EXADownloadFromScreen(PixmapPtr pSrc
 {
     ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
-    unsigned char *src = pSrc->devPrivate.ptr;
     int src_pitch = exaGetPixmapPitch(pSrc);
-    int size = src_pitch < dst_pitch ? src_pitch : dst_pitch;
+    int src_offset = exaGetPixmapOffset(pSrc);
+    unsigned char *src = pI830->FbBase + src_offset + y*src_pitch +
+		x*(pSrc->drawable.bitsPerPixel/8);
 
     I830Sync(pScrn);
 
+    ErrorF("Screen->Mem: src offset 0x%x, src %p, src pitch %d, x %d, y %d, dst %p, dst_pitch %d\n",
+	src_offset, src, src_pitch, x, y, dst, dst_pitch);
+    w *= pSrc->drawable.bitsPerPixel/8;
     while(h--) {
-	i830MemCopyFromVideoRam(pI830, (unsigned char *)dst, src, size);
+	memcpy(dst, src, w);
 	src += src_pitch;
 	dst += dst_pitch;
     }
@@ -341,40 +415,145 @@ I830EXADownloadFromScreen(PixmapPtr pSrc
     return TRUE;
 }
 
-static Bool
-I830EXACheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
-		      PicturePtr pDstPicture)
+static void
+IntelEXAComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
+		 int dstX, int dstY, int w, int h)
 {
-    return FALSE; /* no Composite yet */
-}
+	/* should be same like I830Composite */
+    ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+    int srcXend, srcYend, maskXend, maskYend;
+    PictVector v;
+    int pMask = 1;
+
+ErrorF("Composite: srcX %d, srcY %d\n\t maskX %d, maskY %d\n\t"
+	     "dstX %d, dstY %d\n\twidth %d, height %d\n\t"
+	     "src_scale_x %f, src_scale_y %f, mask_scale_x %f, mask_scale_y %f\n""\tdx0 %d, dy0 %x, dx1 %d dy1 %x\n", 
+		srcX, srcY, maskX, maskY, dstX, dstY, w, h,
+		scale_units[0][0], scale_units[0][1], 
+		scale_units[1][0], scale_units[1][1],
+		draw_coords[0][0], draw_coords[0][1], 
+		draw_coords[1][0], draw_coords[1][1]);
+
+    if (scale_units[1][0] == -1 || scale_units[1][1] == -1) {
+	ErrorF("mask is null\n");
+	pMask = 0;
+    }
 
-static Bool
-I830EXAPrepareComposite(int op, PicturePtr pSrcPicture,
-			PicturePtr pMaskPicture, PicturePtr pDstPicture,
-			PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
-{
-    return FALSE; /* no Composite yet */
-}
+    srcXend = srcX + w;
+    srcYend = srcY + h;
+    maskXend = maskX + w;
+    maskYend = maskY + h;
+    if (is_transform[0]) {
+        v.vector[0] = IntToxFixed(srcX);
+        v.vector[1] = IntToxFixed(srcY);
+        v.vector[2] = xFixed1;
+        PictureTransformPoint(transform[0], &v);
+        srcX = xFixedToInt(v.vector[0]);
+        srcY = xFixedToInt(v.vector[1]);
+        v.vector[0] = IntToxFixed(srcXend);
+        v.vector[1] = IntToxFixed(srcYend);
+        v.vector[2] = xFixed1;
+        PictureTransformPoint(transform[0], &v);
+        srcXend = xFixedToInt(v.vector[0]);
+        srcYend = xFixedToInt(v.vector[1]);
+    }
+    if (is_transform[1]) {
+        v.vector[0] = IntToxFixed(maskX);
+        v.vector[1] = IntToxFixed(maskY);
+        v.vector[2] = xFixed1;
+        PictureTransformPoint(transform[1], &v);
+        maskX = xFixedToInt(v.vector[0]);
+        maskY = xFixedToInt(v.vector[1]);
+        v.vector[0] = IntToxFixed(maskXend);
+        v.vector[1] = IntToxFixed(maskYend);
+        v.vector[2] = xFixed1;
+        PictureTransformPoint(transform[1], &v);
+        maskXend = xFixedToInt(v.vector[0]);
+        maskYend = xFixedToInt(v.vector[1]);
+    }
+DPRINTF(PFX, "After transform: srcX %d, srcY %d,srcXend %d, srcYend %d\n\t"
+		"maskX %d, maskY %d, maskXend %d, maskYend %d\n\t"
+		"dstX %d, dstY %d\n", srcX, srcY, srcXend, srcYend,
+		maskX, maskY, maskXend, maskYend, dstX, dstY);
+
+    draw_coords[0][0] -= draw_coords[2][0];
+    draw_coords[0][1] -= draw_coords[2][1];
+    if (pMask) {
+	draw_coords[1][0] -= draw_coords[2][0];
+	draw_coords[1][1] -= draw_coords[2][1];
+    }
+
+    {
+	int vertex_count; 
+
+	if (pMask)
+		vertex_count = 4*6;
+	else
+		vertex_count = 4*4;
+
+	BEGIN_LP_RING(6+vertex_count);
+
+	OUT_RING(MI_NOOP);
+	OUT_RING(MI_NOOP);
+	OUT_RING(MI_NOOP);
+	OUT_RING(MI_NOOP);
+	OUT_RING(MI_NOOP);
+
+	OUT_RING(PRIM3D_INLINE | PRIM3D_TRIFAN | (vertex_count-1));
+
+	OUT_RING(dstX);
+	OUT_RING(dstY);
+	OUT_RING_F(((srcX - draw_coords[0][0]) / scale_units[0][0]));
+	OUT_RING_F(((srcY - draw_coords[0][1]) / scale_units[0][1]));
+	if (pMask) {
+		OUT_RING_F(((maskX - draw_coords[1][0]) / scale_units[1][0]));
+		OUT_RING_F(((maskY - draw_coords[1][1]) / scale_units[1][1]));
+	}
+
+	OUT_RING(dstX);
+	OUT_RING((dstY+h));
+	OUT_RING_F(((srcX - draw_coords[0][0]) / scale_units[0][0]));
+	OUT_RING_F(((srcYend - draw_coords[0][1]) / scale_units[0][1]));
+	if (pMask) {
+		OUT_RING_F(((maskX - draw_coords[1][0]) / scale_units[1][0]));
+		OUT_RING_F(((maskYend - draw_coords[1][1]) / scale_units[1][1]));
+	}
+
+	OUT_RING((dstX+w));
+	OUT_RING((dstY+h));
+	OUT_RING_F(((srcXend - draw_coords[0][0]) / scale_units[0][0]));
+	OUT_RING_F(((srcYend - draw_coords[0][1]) / scale_units[0][1]));
+	if (pMask) {
+		OUT_RING_F(((maskXend - draw_coords[1][0]) / scale_units[1][0]));
+		OUT_RING_F(((maskYend - draw_coords[1][1]) / scale_units[1][1]));
+	}
+
+	OUT_RING((dstX+w));
+	OUT_RING((dstY));
+	OUT_RING_F(((srcXend - draw_coords[0][0]) / scale_units[0][0]));
+	OUT_RING_F(((srcY - draw_coords[0][1]) / scale_units[0][1]));
+	if (pMask) {
+		OUT_RING_F(((maskXend - draw_coords[1][0]) / scale_units[1][0]));
+		OUT_RING_F(((maskY - draw_coords[1][1]) / scale_units[1][1]));
+	}
+	ADVANCE_LP_RING();
+    }
+#ifdef I830DEBUG
+    ErrorF("sync after 3dprimitive");
+    I830Sync(pScrn);
+#endif
 
-static void
-I830EXAComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
-		 int dstX, int dstY, int width, int height)
-{
-    return; /* no Composite yet */
 }
 
 static void
-I830EXADoneComposite(PixmapPtr pDst)
+IntelEXADoneComposite(PixmapPtr pDst)
 {
-    return; /* no Composite yet */
+    return; 
 }
-#endif
-
 /*
  * TODO:
  *   - Dual head?
- *   - Upload/Download
- *   - Composite
  */
 Bool
 I830EXAInit(ScreenPtr pScreen)
@@ -396,6 +575,12 @@ I830EXAInit(ScreenPtr pScreen)
     pI830->EXADriverPtr->offScreenBase = pI830->Offscreen.Start;
     pI830->EXADriverPtr->memorySize = pI830->Offscreen.End;
 	   
+    DPRINTF(PFX, "EXA Mem: memoryBase 0x%x, end 0x%x, offscreen base 0x%x, memorySize 0x%x\n",
+		pI830->EXADriverPtr->memoryBase,
+		pI830->EXADriverPtr->memoryBase + pI830->EXADriverPtr->memorySize,
+		pI830->EXADriverPtr->offScreenBase,
+		pI830->EXADriverPtr->memorySize);
+
     if(pI830->EXADriverPtr->memorySize >
        pI830->EXADriverPtr->offScreenBase)
 	pI830->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS;
@@ -422,17 +607,23 @@ I830EXAInit(ScreenPtr pScreen)
     pI830->EXADriverPtr->PrepareCopy = I830EXAPrepareCopy;
     pI830->EXADriverPtr->Copy = I830EXACopy;
     pI830->EXADriverPtr->DoneCopy = I830EXADoneCopy;
-#if 0
-    /* Upload, download to/from Screen */
-    pI830->EXADriverPtr->UploadToScreen = I830EXAUploadToScreen;
-    pI830->EXADriverPtr->DownloadFromScreen = I830EXADownloadFromScreen;
 
     /* Composite */
-    pI830->EXADriverPtr->CheckComposite = I830EXACheckComposite;
-    pI830->EXADriverPtr->PrepareComposite = I830EXAPrepareComposite;
-    pI830->EXADriverPtr->Composite = I830EXAComposite;
-    pI830->EXADriverPtr->DoneComposite = I830EXADoneComposite;
-#endif
+    if (IS_I9XX(pI830)) {   		
+	pI830->EXADriverPtr->CheckComposite = I915EXACheckComposite;
+   	pI830->EXADriverPtr->PrepareComposite = I915EXAPrepareComposite;
+    	pI830->EXADriverPtr->Composite = IntelEXAComposite;
+    	pI830->EXADriverPtr->DoneComposite = IntelEXADoneComposite;
+    } else if (IS_I865G(pI830) || IS_I855(pI830) || IS_845G(pI830) || IS_I830(pI830)) { 
+    	pI830->EXADriverPtr->CheckComposite = I830EXACheckComposite;
+    	pI830->EXADriverPtr->PrepareComposite = I830EXAPrepareComposite;
+    	pI830->EXADriverPtr->Composite = IntelEXAComposite;
+    	pI830->EXADriverPtr->DoneComposite = IntelEXADoneComposite;
+    }
+
+    /* Upload, download to/from Screen, experimental!! */
+    pI830->EXADriverPtr->UploadToScreen = I830EXAUploadToScreen;
+    pI830->EXADriverPtr->DownloadFromScreen = I830EXADownloadFromScreen;
 
     if(!exaDriverInit(pScreen, pI830->EXADriverPtr)) {
 	xfree(pI830->EXADriverPtr);
diff --git a/src/i830_exa_render.c b/src/i830_exa_render.c
new file mode 100644
index 0000000..9b4835b
--- /dev/null
+++ b/src/i830_exa_render.c
@@ -0,0 +1,537 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "i830.h"
+#include "i830_reg.h"
+
+#ifdef I830DEBUG
+#define DEBUG_I830FALLBACK 1
+#endif
+
+#ifdef DEBUG_I830FALLBACK
+#define I830FALLBACK(s, arg...)				\
+do {							\
+	DPRINTF(PFX, "EXA fallback: " s "\n", ##arg); 	\
+	return FALSE;					\
+} while(0)
+#else
+#define I830FALLBACK(s, arg...) 			\
+do { 							\
+	return FALSE;					\
+} while(0) 
+#endif
+
+extern float scale_units[2][2];
+extern int draw_coords[3][2];
+extern Bool is_transform[2];
+extern PictTransform *transform[2];
+
+struct blendinfo {
+    Bool dst_alpha;
+    Bool src_alpha;
+    CARD32 blend_cntl;
+};
+
+struct formatinfo {
+    int fmt;
+    CARD32 card_fmt;
+};
+
+extern Bool
+I830EXACheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+		      PicturePtr pDstPicture);
+
+extern Bool
+I830EXAPrepareComposite(int op, PicturePtr pSrcPicture,
+			PicturePtr pMaskPicture, PicturePtr pDstPicture,
+			PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst);
+
+/* I830's Blend factor definition, LOAD_STATE_IMMEDIATE_1 */
+/* move to header...*/
+#define I830_SRC_BLENDFACTOR_ZERO 		(1 << 4)
+#define I830_SRC_BLENDFACTOR_ONE 		(2 << 4)
+#define I830_SRC_BLENDFACTOR_SRC_COLOR		(3 << 4)
+#define I830_SRC_BLENDFACTOR_INV_SRC_COLOR	(4 << 4)
+#define I830_SRC_BLENDFACTOR_SRC_ALPHA		(5 << 4)
+#define I830_SRC_BLENDFACTOR_INV_SRC_ALPHA	(6 << 4)
+#define I830_SRC_BLENDFACTOR_DST_ALPHA		(7 << 4)
+#define I830_SRC_BLENDFACTOR_INV_DST_ALPHA	(8 << 4)
+#define I830_SRC_BLENDFACTOR_DST_COLOR		(9 << 4)
+#define I830_SRC_BLENDFACTOR_INV_DST_COLOR	(0xa << 4)
+#define I830_SRC_BLENDFACTOR_SRC_ALPHA_SATURATE (0xb << 4)
+#define I830_SRC_BLENDFACTOR_CONST_COLOR	(0xc << 4)
+#define I830_SRC_BLENDFACTOR_INV_CONST_COLOR	(0xd << 4)
+#define I830_SRC_BLENDFACTOR_CONST_ALPHA	(0xe << 4)
+#define I830_SRC_BLENDFACTOR_INV_CONST_ALPHA	(0xf << 4)
+#define I830_SRC_BLENDFACTOR_MASK		(0xf << 4)
+
+#define I830_DST_BLENDFACTOR_ZERO 		(1)
+#define I830_DST_BLENDFACTOR_ONE 		(2)
+#define I830_DST_BLENDFACTOR_SRC_COLOR		(3)
+#define I830_DST_BLENDFACTOR_INV_SRC_COLOR	(4)
+#define I830_DST_BLENDFACTOR_SRC_ALPHA		(5)
+#define I830_DST_BLENDFACTOR_INV_SRC_ALPHA	(6)
+#define I830_DST_BLENDFACTOR_DST_ALPHA		(7)
+#define I830_DST_BLENDFACTOR_INV_DST_ALPHA	(8)
+#define I830_DST_BLENDFACTOR_DST_COLOR		(9)
+#define I830_DST_BLENDFACTOR_INV_DST_COLOR	(0xa)
+#define I830_DST_BLENDFACTOR_SRC_ALPHA_SATURATE (0xb)
+#define I830_DST_BLENDFACTOR_CONST_COLOR	(0xc)
+#define I830_DST_BLENDFACTOR_INV_CONST_COLOR	(0xd)
+#define I830_DST_BLENDFACTOR_CONST_ALPHA	(0xe)
+#define I830_DST_BLENDFACTOR_INV_CONST_ALPHA	(0xf)
+#define I830_DST_BLENDFACTOR_MASK		(0xf)
+
+#define TB0C_LAST_STAGE	(1 << 31)
+#define TB0C_RESULT_SCALE_1X		(0 << 29)
+#define TB0C_RESULT_SCALE_2X		(1 << 29)
+#define TB0C_RESULT_SCALE_4X		(2 << 29)
+#define TB0C_OP_MODULE			(3 << 25)
+#define TB0C_OUTPUT_WRITE_CURRENT	(0 << 24)
+#define TB0C_OUTPUT_WRITE_ACCUM		(1 << 24)
+#define TB0C_ARG3_REPLICATE_ALPHA 	(1<<23)
+#define TB0C_ARG3_INVERT		(1<<22)
+#define TB0C_ARG3_SEL_XXX
+#define TB0C_ARG2_REPLICATE_ALPHA 	(1<<17)
+#define TB0C_ARG2_INVERT		(1<<16)
+#define TB0C_ARG2_SEL_ONE		(0 << 12)
+#define TB0C_ARG2_SEL_FACTOR		(1 << 12)
+#define TB0C_ARG2_SEL_TEXEL0		(6 << 12)
+#define TB0C_ARG2_SEL_TEXEL1		(7 << 12)
+#define TB0C_ARG2_SEL_TEXEL2		(8 << 12)
+#define TB0C_ARG2_SEL_TEXEL3		(9 << 12)
+#define TB0C_ARG1_REPLICATE_ALPHA 	(1<<11)
+#define TB0C_ARG1_INVERT		(1<<10)
+#define TB0C_ARG1_SEL_TEXEL0		(6 << 6)
+#define TB0C_ARG1_SEL_TEXEL1		(7 << 6)
+#define TB0C_ARG1_SEL_TEXEL2		(8 << 6)
+#define TB0C_ARG1_SEL_TEXEL3		(9 << 6)
+#define TB0C_ARG0_REPLICATE_ALPHA 	(1<<5)
+#define TB0C_ARG0_SEL_XXX
+
+#define TB0A_CTR_STAGE_ENABLE 		(1<<31)
+#define TB0A_RESULT_SCALE_1X		(0 << 29)
+#define TB0A_RESULT_SCALE_2X		(1 << 29)
+#define TB0A_RESULT_SCALE_4X		(2 << 29)
+#define TB0A_OP_MODULE			(3 << 25)
+#define TB0A_OUTPUT_WRITE_CURRENT	(0<<24)
+#define TB0A_OUTPUT_WRITE_ACCUM		(1<<24)
+#define TB0A_CTR_STAGE_SEL_BITS_XXX
+#define TB0A_ARG3_SEL_XXX
+#define TB0A_ARG3_INVERT		(1<<17)
+#define TB0A_ARG2_INVERT		(1<<16)
+#define TB0A_ARG2_SEL_ONE		(0 << 12)
+#define TB0A_ARG2_SEL_TEXEL0		(6 << 12)
+#define TB0A_ARG2_SEL_TEXEL1		(7 << 12)
+#define TB0A_ARG2_SEL_TEXEL2		(8 << 12)
+#define TB0A_ARG2_SEL_TEXEL3		(9 << 12)
+#define TB0A_ARG1_INVERT		(1<<10)
+#define TB0A_ARG1_SEL_TEXEL0		(6 << 6)
+#define TB0A_ARG1_SEL_TEXEL1		(7 << 6)
+#define TB0A_ARG1_SEL_TEXEL2		(8 << 6)
+#define TB0A_ARG1_SEL_TEXEL3		(9 << 6)
+#define TB0A_ARG0_SEL_XXX
+
+/* end */
+
+
+static struct blendinfo I830BlendOp[] = { 
+    /* Clear */
+    {0, 0, I830_SRC_BLENDFACTOR_ZERO           | I830_DST_BLENDFACTOR_ZERO},
+    /* Src */
+    {0, 0, I830_SRC_BLENDFACTOR_ONE            | I830_DST_BLENDFACTOR_ZERO},
+    /* Dst */
+    {0, 0, I830_SRC_BLENDFACTOR_ZERO           | I830_DST_BLENDFACTOR_ONE},
+    /* Over */
+    {0, 1, I830_SRC_BLENDFACTOR_ONE            | I830_DST_BLENDFACTOR_INV_SRC_ALPHA},
+    /* OverReverse */
+    {1, 0, I830_SRC_BLENDFACTOR_INV_DST_ALPHA | I830_DST_BLENDFACTOR_ONE},
+    /* In */
+    {1, 0, I830_SRC_BLENDFACTOR_DST_ALPHA     | I830_DST_BLENDFACTOR_ZERO},
+    /* InReverse */
+    {0, 1, I830_SRC_BLENDFACTOR_ZERO           | I830_DST_BLENDFACTOR_SRC_ALPHA},
+    /* Out */
+    {1, 0, I830_SRC_BLENDFACTOR_INV_DST_ALPHA | I830_DST_BLENDFACTOR_ZERO},
+    /* OutReverse */
+    {0, 1, I830_SRC_BLENDFACTOR_ZERO           | I830_DST_BLENDFACTOR_INV_SRC_ALPHA},
+    /* Atop */
+    {1, 1, I830_SRC_BLENDFACTOR_DST_ALPHA     | I830_DST_BLENDFACTOR_INV_SRC_ALPHA},
+    /* AtopReverse */
+    {1, 1, I830_SRC_BLENDFACTOR_INV_DST_ALPHA | I830_DST_BLENDFACTOR_SRC_ALPHA},
+    /* Xor */
+    {1, 1, I830_SRC_BLENDFACTOR_INV_DST_ALPHA | I830_DST_BLENDFACTOR_INV_SRC_ALPHA},
+    /* Add */
+    {0, 0, I830_SRC_BLENDFACTOR_ONE            | I830_DST_BLENDFACTOR_ONE},
+};
+
+
+static struct formatinfo I830TexFormats[] = {
+        {PICT_a8r8g8b8, MT_32BIT_ARGB8888 },
+        {PICT_x8r8g8b8, MT_32BIT_ARGB8888 },
+        {PICT_a8b8g8r8, MT_32BIT_ABGR8888 },
+        {PICT_x8b8g8r8, MT_32BIT_ABGR8888 },
+        {PICT_r5g6b5,   MT_16BIT_RGB565	  },
+        {PICT_a1r5g5b5, MT_16BIT_ARGB1555 },
+        {PICT_x1r5g5b5, MT_16BIT_ARGB1555 },
+        {PICT_a8,       MT_8BIT_I8       },
+};
+
+static Bool I830GetDestFormat(PicturePtr pDstPicture, CARD32 *dst_format)
+{
+	/* XXX: color buffer format for i830 */
+    switch (pDstPicture->format) {
+    case PICT_a8r8g8b8:
+    case PICT_x8r8g8b8:
+        *dst_format = COLR_BUF_ARGB8888;
+        break;
+    case PICT_r5g6b5:
+        *dst_format = COLR_BUF_RGB565;
+        break;
+    case PICT_a1r5g5b5:
+    case PICT_x1r5g5b5:
+        *dst_format = COLR_BUF_ARGB1555;
+        break;
+    case PICT_a8:
+        *dst_format = COLR_BUF_8BIT;
+        break;
+    case PICT_a4r4g4b4:
+    case PICT_x4r4g4b4:
+	*dst_format = COLR_BUF_ARGB4444;
+	break;
+    default:
+        I830FALLBACK("Unsupported dest format 0x%x\n",
+                        (int)pDstPicture->format);
+    }
+
+    return TRUE;
+}
+
+
+static CARD32 I830GetBlendCntl(int op, PicturePtr pMask, CARD32 dst_format)
+{
+    CARD32 sblend, dblend;
+
+    sblend = I830BlendOp[op].blend_cntl & I830_SRC_BLENDFACTOR_MASK;
+    dblend = I830BlendOp[op].blend_cntl & I830_DST_BLENDFACTOR_MASK;
+
+    /* If there's no dst alpha channel, adjust the blend op so that we'll treat
+     * it as always 1.
+     */
+    if (PICT_FORMAT_A(dst_format) == 0 && I830BlendOp[op].dst_alpha) {
+        if (sblend == I830_SRC_BLENDFACTOR_DST_ALPHA)
+            sblend = I830_SRC_BLENDFACTOR_ONE;
+        else if (sblend == I830_SRC_BLENDFACTOR_INV_DST_ALPHA)
+            sblend = I830_SRC_BLENDFACTOR_ZERO;
+    }
+
+    /* If the source alpha is being used, then we should only be in a case where
+     * the source blend factor is 0, and the source blend value is the mask
+     * channels multiplied by the source picture's alpha.
+     */
+    if (pMask && pMask->componentAlpha && I830BlendOp[op].src_alpha) {
+        if (dblend == I830_DST_BLENDFACTOR_SRC_ALPHA) {
+            dblend = I830_DST_BLENDFACTOR_SRC_COLOR;
+        } else if (dblend == I830_DST_BLENDFACTOR_INV_SRC_ALPHA) {
+            dblend = I830_DST_BLENDFACTOR_INV_SRC_COLOR;
+        }
+    }
+
+    return sblend | dblend;
+}
+
+static Bool I830CheckCompositeTexture(PicturePtr pPict, int unit)
+{
+    int w = pPict->pDrawable->width;
+    int h = pPict->pDrawable->height;
+    int i;
+                                                                                                                                                            
+    if ((w > 0x7ff) || (h > 0x7ff))
+        I830FALLBACK("Picture w/h too large (%dx%d)\n", w, h);
+
+    for (i = 0; i < sizeof(I830TexFormats) / sizeof(I830TexFormats[0]); i++)
+    {
+        if (I830TexFormats[i].fmt == pPict->format)
+            break;
+    }
+    if (i == sizeof(I830TexFormats) / sizeof(I830TexFormats[0]))
+        I830FALLBACK("Unsupported picture format 0x%x\n",
+                         (int)pPict->format);
+
+    /* FIXME: fix repeat support */
+    if (pPict->repeat)
+	I830FALLBACK("repeat unsupport now\n");
+
+    if (pPict->filter != PictFilterNearest &&
+        pPict->filter != PictFilterBilinear)
+        I830FALLBACK("Unsupported filter 0x%x\n", pPict->filter);
+
+    return TRUE;
+}
+
+static Bool
+I830TextureSetup(PicturePtr pPict, PixmapPtr pPix, int unit)
+{
+
+    ScrnInfoPtr pScrn = xf86Screens[pPict->pDrawable->pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD32 format, offset, pitch, filter;
+    int w, h, i;
+    CARD32 wrap_mode = TEXCOORDMODE_CLAMP; 
+
+    offset = exaGetPixmapOffset(pPix);
+    pitch = exaGetPixmapPitch(pPix);
+    w = pPict->pDrawable->width;
+    h = pPict->pDrawable->height;
+    scale_units[unit][0] = pPix->drawable.width;
+    scale_units[unit][1] = pPix->drawable.height;
+    draw_coords[unit][0] = pPix->drawable.x;
+    draw_coords[unit][1] = pPix->drawable.y;
+
+    for (i = 0; i < sizeof(I830TexFormats) / sizeof(I830TexFormats[0]); i++) {
+        if (I830TexFormats[i].fmt == pPict->format)
+	    break;
+    }
+    if ( i == sizeof(I830TexFormats)/ sizeof(I830TexFormats[0]) )
+	I830FALLBACK("unknown texture format\n");
+    format = I830TexFormats[i].card_fmt;
+
+    if (pPict->repeat) 
+	wrap_mode = TEXCOORDMODE_WRAP; /* XXX: correct ? */
+    
+    switch (pPict->filter) {
+    case PictFilterNearest:
+        filter = ((FILTER_NEAREST<<TM0S3_MAG_FILTER_SHIFT) | 
+			(FILTER_NEAREST<<TM0S3_MIN_FILTER_SHIFT));
+        break;
+    case PictFilterBilinear:
+        filter = ((FILTER_LINEAR<<TM0S3_MAG_FILTER_SHIFT) | 
+			(FILTER_LINEAR<<TM0S3_MIN_FILTER_SHIFT));
+        break;
+    default:
+	filter = 0;
+        I830FALLBACK("Bad filter 0x%x\n", pPict->filter);
+    }
+
+    {
+	if (pI830->cpp == 1)
+		format |= MAP_SURFACE_8BIT;
+	else if (pI830->cpp == 2)
+		format |= MAP_SURFACE_16BIT;
+	else
+		format |= MAP_SURFACE_32BIT;
+
+	BEGIN_LP_RING(6);
+	OUT_RING(_3DSTATE_MAP_INFO_CMD);
+	OUT_RING(format | TEXMAP_INDEX(unit) | MAP_FORMAT_2D);
+	OUT_RING((pPix->drawable.height<<16)|pPix->drawable.width); /* height, width */
+	OUT_RING(offset<<2); /* map address */
+	OUT_RING(pitch<<2); /* map pitch */
+	OUT_RING(0);
+	ADVANCE_LP_RING();
+     }
+
+     {
+	BEGIN_LP_RING(2);
+	/* coord sets */
+	OUT_RING(_3DSTATE_MAP_COORD_SET_CMD | TEXCOORD_SET(unit) | 
+		ENABLE_TEXCOORD_PARAMS | TEXCOORDS_ARE_NORMAL | /*XXX, check this, and fix vertex tex coord*/
+		TEXCOORDTYPE_CARTESIAN | ENABLE_ADDR_V_CNTL | TEXCOORD_ADDR_V_MODE(wrap_mode) |
+		ENABLE_ADDR_U_CNTL | TEXCOORD_ADDR_U_MODE(wrap_mode));
+	OUT_RING(MI_NOOP);
+
+	/* XXX: filter seems hang engine...*/
+#if 0
+	OUT_RING(I830_STATE3D_MAP_FILTER | FILTER_MAP_INDEX(unit) | ENABLE_KEYS| DISABLE_COLOR_KEY | DISABLE_CHROMA_KEY | DISABLE_KILL_PIXEL |ENABLE_MIP_MODE_FILTER | MIPFILTER_NONE | filter);
+	OUT_RING(0);
+#endif
+
+	/* max & min mip level ? or base mip level? */
+
+	ADVANCE_LP_RING();
+    }
+
+	/* XXX */
+    if (pPict->transform != 0) {
+        is_transform[unit] = TRUE;
+        transform[unit] = pPict->transform;
+    } else {
+        is_transform[unit] = FALSE;
+    }
+
+#ifdef I830DEBUG
+    ErrorF("try to sync to show any errors...");
+    I830Sync(pScrn);
+#endif
+	
+    return TRUE;
+}
+
+Bool
+I830EXACheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+		      PicturePtr pDstPicture)
+{
+    CARD32 tmp1;
+    
+    /* Check for unsupported compositing operations. */
+    if (op >= sizeof(I830BlendOp) / sizeof(I830BlendOp[0]))
+        I830FALLBACK("Unsupported Composite op 0x%x\n", op);
+                                                                                                                                                            
+    if (pMaskPicture != NULL && pMaskPicture->componentAlpha) {
+        /* Check if it's component alpha that relies on a source alpha and on
+         * the source value.  We can only get one of those into the single
+         * source value that we get to blend with.
+         */
+        if (I830BlendOp[op].src_alpha &&
+            (I830BlendOp[op].blend_cntl & I830_SRC_BLENDFACTOR_MASK) !=
+             I830_SRC_BLENDFACTOR_ZERO)
+            	I830FALLBACK("Component alpha not supported with source "
+                            "alpha and source value blending.\n");
+    }
+
+    if (!I830CheckCompositeTexture(pSrcPicture, 0))
+        I830FALLBACK("Check Src picture texture\n");
+    if (pMaskPicture != NULL && !I830CheckCompositeTexture(pMaskPicture, 1))
+        I830FALLBACK("Check Mask picture texture\n");
+
+    if (!I830GetDestFormat(pDstPicture, &tmp1)) 
+	I830FALLBACK("Get Color buffer format\n");
+
+    return TRUE;
+}
+
+
+static void
+I830DefCtxSetup(ScrnInfoPtr pScrn)
+{
+	/* coord binding */
+	CARD32 mcb;
+    	I830Ptr pI830 = I830PTR(pScrn);
+
+	BEGIN_LP_RING(2);
+	OUT_RING(_3DSTATE_MAP_COORD_SETBIND_CMD);
+	mcb = TEXBIND_SET3(TEXCOORDSRC_VTXSET_3);
+	mcb |= TEXBIND_SET2(TEXCOORDSRC_VTXSET_2);
+	mcb |= TEXBIND_SET1(TEXCOORDSRC_VTXSET_1);
+	mcb |= TEXBIND_SET0(TEXCOORDSRC_VTXSET_0);
+	OUT_RING(mcb);
+	ADVANCE_LP_RING();
+}
+
+
+Bool
+I830EXAPrepareComposite(int op, PicturePtr pSrcPicture,
+			PicturePtr pMaskPicture, PicturePtr pDstPicture,
+			PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
+{
+/* XXX: setup texture map from pixmap, vertex format, blend cntl */
+    ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD32 dst_format, dst_offset, dst_pitch;
+
+    I830GetDestFormat(pDstPicture, &dst_format);
+    dst_offset = exaGetPixmapOffset(pDst);
+    dst_pitch = exaGetPixmapPitch(pDst);
+    draw_coords[2][0] = pDst->drawable.x;
+    draw_coords[2][1] = pDst->drawable.y;
+    
+    I830DefCtxSetup(pScrn);
+
+    if (!I830TextureSetup(pSrcPicture, pSrc, 0))
+	I830FALLBACK("fail to setup src texture\n");
+    if (pMask != NULL) {
+	if (!I830TextureSetup(pMaskPicture, pMask, 1))
+		I830FALLBACK("fail to setup mask texture\n");
+    } else {
+	is_transform[1] = FALSE;
+	scale_units[1][0] = -1;
+	scale_units[1][1] = -1;
+    }
+
+    {
+
+	CARD32 cblend, ablend, blendctl, vf2;
+
+	BEGIN_LP_RING(22);
+	
+	/*color buffer*/
+	OUT_RING(_3DSTATE_BUF_INFO_CMD);
+	OUT_RING(BUF_3D_ID_COLOR_BACK| BUF_3D_PITCH(dst_pitch));
+	OUT_RING(BUF_3D_ADDR(dst_offset));
+	OUT_RING(MI_NOOP);
+	
+	OUT_RING(_3DSTATE_DST_BUF_VARS_CMD);
+	OUT_RING(dst_format);
+
+	/* defaults */
+	OUT_RING(_3DSTATE_DFLT_Z_CMD);
+	OUT_RING(0);
+
+	OUT_RING(_3DSTATE_DFLT_DIFFUSE_CMD);
+	OUT_RING(0);
+
+	OUT_RING(_3DSTATE_DFLT_SPEC_CMD);
+	OUT_RING(0);
+	
+	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1|I1_LOAD_S(3)|0);
+	OUT_RING((1<<S3_POINT_WIDTH_SHIFT) | (2<<S3_LINE_WIDTH_SHIFT) | S3_CULLMODE_NONE| S3_VERTEXHAS_XY);  
+	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1|I1_LOAD_S(2)|0);
+	if (pMask)
+		vf2 = 2 << 12; /* 2 texture coord sets */
+	else
+		vf2 = 1 << 12;
+	vf2 |= (TEXCOORDFMT_2D << 16);
+	if (pMask)
+		vf2 |= (TEXCOORDFMT_2D << 18);
+	else
+		vf2 |= (TEXCOORDFMT_1D << 18);
+		
+	vf2 |= (TEXCOORDFMT_1D << 20);
+	vf2 |= (TEXCOORDFMT_1D << 22);
+	vf2 |= (TEXCOORDFMT_1D << 24);
+	vf2 |= (TEXCOORDFMT_1D << 26);
+	vf2 |= (TEXCOORDFMT_1D << 28);
+	vf2 |= (TEXCOORDFMT_1D << 30);
+	OUT_RING(vf2);
+
+	/* For (src In mask) operation */
+	/* IN operator: Multiply src by mask components or mask alpha.*/
+	/* TEXBLENDOP_MODULE: arg1*arg2 */
+	cblend = TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OP_MODULE |
+		 TB0C_OUTPUT_WRITE_CURRENT;  
+	ablend = TB0A_RESULT_SCALE_1X | TB0A_OP_MODULE | TB0A_OUTPUT_WRITE_CURRENT;
+	
+	cblend |= TB0C_ARG1_SEL_TEXEL0;
+	ablend |= TB0A_ARG1_SEL_TEXEL0;
+	if (pMask) {
+		if (pMaskPicture->componentAlpha && pDstPicture->format != PICT_a8)
+			cblend |= TB0C_ARG2_SEL_TEXEL1;
+		else
+			cblend |= (TB0C_ARG2_SEL_TEXEL1 | TB0C_ARG2_REPLICATE_ALPHA);
+		ablend |= TB0A_ARG2_SEL_TEXEL1;
+	} else {
+		cblend |= TB0C_ARG2_SEL_ONE;
+		ablend |= TB0A_ARG2_SEL_ONE;		
+	}
+		
+	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | LOAD_TEXTURE_BLEND_STAGE(0)|1);
+	OUT_RING(cblend);
+	OUT_RING(ablend);
+	OUT_RING(0);
+
+	blendctl = I830GetBlendCntl(op, pMaskPicture, pDstPicture->format);
+	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(8) | 0);
+	OUT_RING(S8_ENABLE_COLOR_BLEND | S8_BLENDFUNC_ADD |(blendctl<<4) |
+		S8_ENABLE_COLOR_BUFFER_WRITE);	
+	ADVANCE_LP_RING();
+    }
+
+#ifdef I830DEBUG
+   Error("try to sync to show any errors...");
+   I830Sync(pScrn);
+#endif
+
+    return TRUE;
+}
+
diff --git a/src/i830_reg.h b/src/i830_reg.h
index be12e76..ae68a2e 100644
--- a/src/i830_reg.h
+++ b/src/i830_reg.h
@@ -31,6 +31,23 @@
 
 #define I830_SET_FIELD( var, mask, value ) (var &= ~(mask), var |= value)
 
+#define CMD_3D (0x3<<29)
+
+#define PRIM3D_INLINE		(CMD_3D | (0x1f<<24))
+#define PRIM3D_TRILIST		(0x0<<18)
+#define PRIM3D_TRISTRIP 	(0x1<<18)
+#define PRIM3D_TRISTRIP_RVRSE	(0x2<<18)
+#define PRIM3D_TRIFAN		(0x3<<18)
+#define PRIM3D_POLY		(0x4<<18)
+#define PRIM3D_LINELIST 	(0x5<<18)
+#define PRIM3D_LINESTRIP	(0x6<<18)
+#define PRIM3D_RECTLIST 	(0x7<<18)
+#define PRIM3D_POINTLIST	(0x8<<18)
+#define PRIM3D_DIB		(0x9<<18)
+#define PRIM3D_CLEAR_RECT	(0xa<<18)
+#define PRIM3D_ZONE_INIT	(0xd<<18)
+#define PRIM3D_MASK		(0x1f<<18)
+
 #define _3DSTATE_AA_CMD			(CMD_3D | (0x06<<24))
 #define AA_LINE_ECAAR_WIDTH_ENABLE	(1<<16)
 #define AA_LINE_ECAAR_WIDTH_0_5 	0
@@ -85,6 +102,8 @@
 #define COLR_BUF_RGB555 		(1<<8)
 #define COLR_BUF_RGB565 		(2<<8)
 #define COLR_BUF_ARGB8888		(3<<8)
+#define COLR_BUF_ARGB4444		(8<<8)
+#define COLR_BUF_ARGB1555		(9<<8)
 #define DEPTH_IS_Z			0
 #define DEPTH_IS_W			(1<<6)
 #define DEPTH_FRMT_16_FIXED		0
@@ -301,6 +320,7 @@
 
 /* _3DSTATE_MAP_COORD_SETS, p164 */
 #define _3DSTATE_MAP_COORD_SET_CMD	(CMD_3D|(0x1c<<24)|(0x01<<19))
+#define TEXCOORD_SET(n)			((n)<<16)
 #define ENABLE_TEXCOORD_PARAMS		(1<<15)
 #define TEXCOORDS_ARE_NORMAL		(1<<14)
 #define TEXCOORDS_ARE_IN_TEXELUNITS	0
@@ -329,6 +349,13 @@
 #define CUBE_NEGZ_ENABLE                (1<<1)
 #define CUBE_POSZ_ENABLE                (1<<0)
 
+#define _3DSTATE_MAP_INFO_CMD		(CMD_3D|(0x1d<<24)|(0x0<<16)|3)
+#define TEXMAP_INDEX(x)			((x)<<28)
+#define MAP_SURFACE_8BIT		(1<<24)
+#define MAP_SURFACE_16BIT		(2<<24)
+#define MAP_SURFACE_32BIT		(3<<24)
+#define MAP_FORMAT_2D			(0)
+#define MAP_FORMAT_3D_CUBE		(1<<11)
 
 /* _3DSTATE_MODES_1, p190 */
 #define _3DSTATE_MODES_1_CMD		(CMD_3D|(0x08<<24))
@@ -523,14 +550,57 @@
 
 /* Stipple command, carried over from the i810, apparently:
  */
-#define _3DSTATE_STIPPLE           ((0x3<<29)|(0x1d<<24)|(0x83<<16))
+#define _3DSTATE_STIPPLE           (CMD_3D|(0x1d<<24)|(0x83<<16))
 #define ST1_ENABLE               (1<<16)
 #define ST1_MASK                 (0xffff)
 
-
-
-#define _3DSTATE_LOAD_STATE_IMMEDIATE_2      ((0x3<<29)|(0x1d<<24)|(0x03<<16))
-#define LOAD_TEXTURE_MAP0                   (1<<11)
+#define _3DSTATE_LOAD_STATE_IMMEDIATE_1	     (CMD_3D|(0x1d<<24)|(0x04<<16))
+#define I1_LOAD_S(n)			     (1<<((n)+4))
+#define S3_POINT_WIDTH_SHIFT		     23
+#define S3_LINE_WIDTH_SHIFT		     19
+#define S3_ALPHA_SHADE_MODE_SHIFT	     18
+#define S3_FOG_SHADE_MODE_SHIFT		     17
+#define S3_SPEC_SHADE_MODE_SHIFT	     16
+#define S3_COLOR_SHADE_MODE_SHIFT	     15
+#define S3_CULL_MODE_SHIFT		     13
+#define    S3_CULLMODE_BOTH		     (0)
+#define    S3_CULLMODE_NONE		     (1<<13)
+#define    S3_CULLMODE_CW		     (2<<13)
+#define    S3_CULLMODE_CCW		     (3<<13)
+#define S3_POINT_WIDTH_PRESENT		     (1<<12)
+#define S3_SPEC_FOG_PRESENT		     (1<<11)
+#define S3_DIFFUSE_PRESENT		     (1<<10)
+#define S3_DEPTH_OFFSET_PRESENT		     (1<<9)
+#define S3_POSITION_SHIFT		     6
+#define    S3_VERTEXHAS_XYZ		     (1<<6)
+#define    S3_VERTEXHAS_XYZW		     (2<<6)
+#define    S3_VERTEXHAS_XY		     (3<<6)
+#define    S3_VERTEXHAS_XYW		     (4<<6)
+#define S3_ENABLE_SPEC_ADD		     (1<<5)
+#define S3_ENABLE_FOG			     (1<<4)
+#define S3_ENABLE_LOCAL_DEPTH_BIAS	     (1<<3)
+#define S3_ENABLE_SPRITE_POINT		     (1<<1)
+#define S3_ENABLE_ANTIALIASING		     1
+#define S8_ENABLE_ALPHA_TEST		     (1<<31)
+#define S8_ALPHA_TEST_FUNC_SHIFT	     28
+#define S8_ALPHA_REFVALUE_SHIFT		     20
+#define S8_ENABLE_DEPTH_TEST		     (1<<19)
+#define S8_DEPTH_TEST_FUNC_SHIFT	     16
+#define S8_ENABLE_COLOR_BLEND		     (1<<15)
+#define S8_COLOR_BLEND_FUNC_SHIFT	     12
+#define    S8_BLENDFUNC_ADD		     (0)
+#define    S8_BLENDFUNC_SUB		     (1<<12)
+#define    S8_BLENDFUNC_RVRSE_SUB	     (2<<12)
+#define    S8_BLENDFUNC_MIN		     (3<<12)
+#define    S8_BLENDFUNC_MAX			     (4<<12)
+#define S8_SRC_BLEND_FACTOR_SHIFT	     8
+#define S8_DST_BLEND_FACTOR_SHIFT	     4
+#define S8_ENABLE_DEPTH_BUFFER_WRITE	     (1<<3)
+#define S8_ENABLE_COLOR_BUFFER_WRITE	     (1<<2)
+
+#define _3DSTATE_LOAD_STATE_IMMEDIATE_2      (CMD_3D|(0x1d<<24)|(0x03<<16))
+#define LOAD_TEXTURE_MAP(x)                   (1<<((x)+11))
+#define LOAD_TEXTURE_BLEND_STAGE(x)	      (1<<((x)+7))
 #define LOAD_GLOBAL_COLOR_FACTOR            (1<<6)
 
 #define TM0S0_ADDRESS_MASK              0xfffffffc
@@ -591,6 +661,8 @@
 #define TM0S2_CUBE_FACE_ENA_SHIFT       15
 #define TM0S2_CUBE_FACE_ENA_MASK        (1<<15)
 #define TM0S2_MAP_FORMAT                (1<<14)
+#define    TM0S2_MAP_2D			(0<<14)
+#define    TM0S2_MAP_3D_CUBE		(1<<14)
 #define TM0S2_VERTICAL_LINE_STRIDE      (1<<13)
 #define TM0S2_VERITCAL_LINE_STRIDE_OFF  (1<<12)
 #define TM0S2_OUTPUT_CHAN_SHIFT         10
@@ -634,4 +706,23 @@
 
 #define FLUSH_MAP_CACHE    (1<<0)
 
+#define _3DSTATE_MAP_FILTER_CMD    (CMD_3D|(0x1c<<24)|(0x02<<19))
+#define FILTER_TEXMAP_INDEX(x) ((x) << 16)
+#define MAG_MODE_FILTER_ENABLE (1 << 5) 
+#define MIN_MODE_FILTER_ENABLE (1 << 2) 
+#define MAG_MAPFILTER_NEAREST (0 << 3)
+#define MAG_MAPFILTER_LINEAR  (1 << 3)
+#define MAG_MAPFILTER_ANISOTROPIC (2 << 3)
+#define MIN_MAPFILTER_NEAREST (0)
+#define MIN_MAPFILTER_LINEAR  (1)
+#define MIN_MAPFILTER_ANISOTROPIC (2)
+#define ENABLE_KEYS	(1<<15)
+#define DISABLE_COLOR_KEY	0 
+#define DISABLE_CHROMA_KEY	0
+#define DISABLE_KILL_PIXEL	0
+#define ENABLE_MIP_MODE_FILTER	(1 << 9)
+#define MIPFILTER_NONE		0
+#define MIPFILTER_NEAREST	1
+#define MIPFILTER_LINEAR	3
+
 #endif
diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
new file mode 100644
index 0000000..68c929e
--- /dev/null
+++ b/src/i915_exa_render.c
@@ -0,0 +1,553 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "i830.h"
+#include "i915_reg.h"
+
+#ifdef I830DEBUG
+#define DEBUG_I830FALLBACK 1
+#endif
+
+#ifdef DEBUG_I830FALLBACK
+#define I830FALLBACK(s, arg...)				\
+do {							\
+	DPRINTF(PFX, "EXA fallback: " s "\n", ##arg); 	\
+	return FALSE;					\
+} while(0)
+#else
+#define I830FALLBACK(s, arg...) 			\
+do { 							\
+	return FALSE;					\
+} while(0) 
+#endif
+
+extern float scale_units[2][2];
+extern int draw_coords[3][2];
+extern Bool is_transform[2];
+extern PictTransform *transform[2];
+
+struct formatinfo {
+    int fmt;
+    CARD32 card_fmt;
+};
+
+struct blendinfo {
+    Bool dst_alpha;
+    Bool src_alpha;
+    CARD32 blend_cntl;
+};
+
+extern Bool
+I915EXACheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+		      PicturePtr pDstPicture);
+
+extern Bool
+I915EXAPrepareComposite(int op, PicturePtr pSrcPicture,
+			PicturePtr pMaskPicture, PicturePtr pDstPicture,
+			PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst);
+
+/* copy from Eric's texture-video branch, move to header.. */
+#define OUT_DCL(type, nr) do {                                          \
+   CARD32 chans = 0;                                                    \
+   if (REG_TYPE_##type == REG_TYPE_T)                                   \
+      chans = D0_CHANNEL_ALL;                                           \
+   else if (REG_TYPE_##type != REG_TYPE_S)                              \
+      FatalError("wrong reg type %d to declare\n", REG_TYPE_##type);    \
+   OUT_RING(D0_DCL |                                                    \
+            (REG_TYPE_##type << D0_TYPE_SHIFT) | (nr << D0_NR_SHIFT) |  \
+            chans);                                                     \
+   OUT_RING(0x00000000);                                                \
+   OUT_RING(0x00000000);                                                \
+} while (0)
+
+#define OUT_TEXLD(dest_type, dest_nr, sampler_nr, addr_type, addr_nr)   \
+do {                                                                    \
+      OUT_RING(T0_TEXLD |                                               \
+               (REG_TYPE_##dest_type << T0_DEST_TYPE_SHIFT) |           \
+               (dest_nr << T0_DEST_NR_SHIFT) |                          \
+               (sampler_nr << T0_SAMPLER_NR_SHIFT));                    \
+      OUT_RING((REG_TYPE_##addr_type << T1_ADDRESS_REG_TYPE_SHIFT) |    \
+               (addr_nr << T1_ADDRESS_REG_NR_SHIFT));                   \
+      OUT_RING(0x00000000);                                             \
+} while (0)
+
+/* XXX: It seems that offset of 915's blendfactor in Load_immediate_1
+   is _different_ with i830, so I should just define plain value
+   and use it with shift bits*/
+
+#define I915_SRC_BLENDFACTOR_ZERO 		(1 << 8)
+#define I915_SRC_BLENDFACTOR_ONE 		(2 << 8)
+#define I915_SRC_BLENDFACTOR_SRC_COLOR		(3 << 8)
+#define I915_SRC_BLENDFACTOR_INV_SRC_COLOR	(4 << 8)
+#define I915_SRC_BLENDFACTOR_SRC_ALPHA		(5 << 8)
+#define I915_SRC_BLENDFACTOR_INV_SRC_ALPHA	(6 << 8)
+#define I915_SRC_BLENDFACTOR_DST_ALPHA		(7 << 8)
+#define I915_SRC_BLENDFACTOR_INV_DST_ALPHA	(8 << 8)
+#define I915_SRC_BLENDFACTOR_DST_COLOR		(9 << 8)
+#define I915_SRC_BLENDFACTOR_INV_DST_COLOR	(0xa << 8)
+#define I915_SRC_BLENDFACTOR_SRC_ALPHA_SATURATE (0xb << 8)
+#define I915_SRC_BLENDFACTOR_CONST_COLOR	(0xc << 8)
+#define I915_SRC_BLENDFACTOR_INV_CONST_COLOR	(0xd << 8)
+#define I915_SRC_BLENDFACTOR_CONST_ALPHA	(0xe << 8)
+#define I915_SRC_BLENDFACTOR_INV_CONST_ALPHA	(0xf << 8)
+#define I915_SRC_BLENDFACTOR_MASK		(0xf << 8)
+
+#define I915_DST_BLENDFACTOR_ZERO 		(1 << 4)
+#define I915_DST_BLENDFACTOR_ONE 		(2 << 4)
+#define I915_DST_BLENDFACTOR_SRC_COLOR		(3 << 4)
+#define I915_DST_BLENDFACTOR_INV_SRC_COLOR	(4 << 4)
+#define I915_DST_BLENDFACTOR_SRC_ALPHA		(5 << 4)
+#define I915_DST_BLENDFACTOR_INV_SRC_ALPHA	(6 << 4)
+#define I915_DST_BLENDFACTOR_DST_ALPHA		(7 << 4)
+#define I915_DST_BLENDFACTOR_INV_DST_ALPHA	(8 << 4)
+#define I915_DST_BLENDFACTOR_DST_COLOR		(9 << 4)
+#define I915_DST_BLENDFACTOR_INV_DST_COLOR	(0xa << 4)
+#define I915_DST_BLENDFACTOR_SRC_ALPHA_SATURATE (0xb << 4)
+#define I915_DST_BLENDFACTOR_CONST_COLOR	(0xc << 4)
+#define I915_DST_BLENDFACTOR_INV_CONST_COLOR	(0xd << 4)
+#define I915_DST_BLENDFACTOR_CONST_ALPHA	(0xe << 4)
+#define I915_DST_BLENDFACTOR_INV_CONST_ALPHA	(0xf << 4)
+#define I915_DST_BLENDFACTOR_MASK		(0xf << 4)
+
+static struct blendinfo I915BlendOp[] = { 
+    /* Clear */
+    {0, 0, I915_SRC_BLENDFACTOR_ZERO           | I915_DST_BLENDFACTOR_ZERO},
+    /* Src */
+    {0, 0, I915_SRC_BLENDFACTOR_ONE            | I915_DST_BLENDFACTOR_ZERO},
+    /* Dst */
+    {0, 0, I915_SRC_BLENDFACTOR_ZERO           | I915_DST_BLENDFACTOR_ONE},
+    /* Over */
+    {0, 1, I915_SRC_BLENDFACTOR_ONE            | I915_DST_BLENDFACTOR_INV_SRC_ALPHA},
+    /* OverReverse */
+    {1, 0, I915_SRC_BLENDFACTOR_INV_DST_ALPHA | I915_DST_BLENDFACTOR_ONE},
+    /* In */
+    {1, 0, I915_SRC_BLENDFACTOR_DST_ALPHA     | I915_DST_BLENDFACTOR_ZERO},
+    /* InReverse */
+    {0, 1, I915_SRC_BLENDFACTOR_ZERO           | I915_DST_BLENDFACTOR_SRC_ALPHA},
+    /* Out */
+    {1, 0, I915_SRC_BLENDFACTOR_INV_DST_ALPHA | I915_DST_BLENDFACTOR_ZERO},
+    /* OutReverse */
+    {0, 1, I915_SRC_BLENDFACTOR_ZERO           | I915_DST_BLENDFACTOR_INV_SRC_ALPHA},
+    /* Atop */
+    {1, 1, I915_SRC_BLENDFACTOR_DST_ALPHA     | I915_DST_BLENDFACTOR_INV_SRC_ALPHA},
+    /* AtopReverse */
+    {1, 1, I915_SRC_BLENDFACTOR_INV_DST_ALPHA | I915_DST_BLENDFACTOR_SRC_ALPHA},
+    /* Xor */
+    {1, 1, I915_SRC_BLENDFACTOR_INV_DST_ALPHA | I915_DST_BLENDFACTOR_INV_SRC_ALPHA},
+    /* Add */
+    {0, 0, I915_SRC_BLENDFACTOR_ONE            | I915_DST_BLENDFACTOR_ONE},
+};
+
+static struct formatinfo I915TexFormats[] = {
+        {PICT_a8r8g8b8, MT_32BIT_ARGB8888 },
+        {PICT_x8r8g8b8, MT_32BIT_XRGB8888 },
+        {PICT_a8b8g8r8, MT_32BIT_ABGR8888 },
+        {PICT_x8b8g8r8, MT_32BIT_XBGR8888 },
+        {PICT_r5g6b5,   MT_16BIT_RGB565   },
+        {PICT_a1r5g5b5, MT_16BIT_ARGB1555 },
+        {PICT_x1r5g5b5, MT_16BIT_ARGB1555 },
+        {PICT_a8,       MT_8BIT_I8 	  },
+};
+
+static CARD32 I915GetBlendCntl(int op, PicturePtr pMask, CARD32 dst_format)
+{
+    CARD32 sblend, dblend;
+
+    sblend = I915BlendOp[op].blend_cntl & I915_SRC_BLENDFACTOR_MASK;
+    dblend = I915BlendOp[op].blend_cntl & I915_DST_BLENDFACTOR_MASK;
+
+    /* If there's no dst alpha channel, adjust the blend op so that we'll treat
+     * it as always 1.
+     */
+    if (PICT_FORMAT_A(dst_format) == 0 && I915BlendOp[op].dst_alpha) {
+        if (sblend == I915_SRC_BLENDFACTOR_DST_ALPHA)
+            sblend = I915_SRC_BLENDFACTOR_ONE;
+        else if (sblend == I915_SRC_BLENDFACTOR_INV_DST_ALPHA)
+            sblend = I915_SRC_BLENDFACTOR_ZERO;
+    }
+
+    /* If the source alpha is being used, then we should only be in a case where
+     * the source blend factor is 0, and the source blend value is the mask
+     * channels multiplied by the source picture's alpha.
+     */
+    if (pMask && pMask->componentAlpha && I915BlendOp[op].src_alpha) {
+        if (dblend == I915_DST_BLENDFACTOR_SRC_ALPHA) {
+            dblend = I915_DST_BLENDFACTOR_SRC_COLOR;
+        } else if (dblend == I915_DST_BLENDFACTOR_INV_SRC_ALPHA) {
+            dblend = I915_DST_BLENDFACTOR_INV_SRC_COLOR;
+        }
+    }
+
+    return sblend | dblend;
+}
+
+static Bool I915GetDestFormat(PicturePtr pDstPicture, CARD32 *dst_format)
+{
+    switch (pDstPicture->format) {
+    case PICT_a8r8g8b8:
+    case PICT_x8r8g8b8:
+        *dst_format = COLR_BUF_ARGB8888;
+        break;
+    case PICT_r5g6b5:
+        *dst_format = COLR_BUF_RGB565;
+        break;
+    case PICT_a1r5g5b5:
+    case PICT_x1r5g5b5:
+        *dst_format = COLR_BUF_ARGB1555;
+        break;
+    case PICT_a8:
+        *dst_format = COLR_BUF_8BIT;
+        break;
+    case PICT_a4r4g4b4:
+    case PICT_x4r4g4b4:
+	*dst_format = COLR_BUF_ARGB4444;
+	break;
+    default:
+        I830FALLBACK("Unsupported dest format 0x%x\n",
+                        (int)pDstPicture->format);
+    }
+
+    return TRUE;
+}
+
+static Bool I915CheckCompositeTexture(PicturePtr pPict, int unit)
+{
+    int w = pPict->pDrawable->width;
+    int h = pPict->pDrawable->height;
+    int i;
+                                                                                                                                                            
+    if ((w > 0x7ff) || (h > 0x7ff))
+        I830FALLBACK("Picture w/h too large (%dx%d)\n", w, h);
+
+    for (i = 0; i < sizeof(I915TexFormats) / sizeof(I915TexFormats[0]); i++)
+    {
+        if (I915TexFormats[i].fmt == pPict->format)
+            break;
+    }
+    if (i == sizeof(I915TexFormats) / sizeof(I915TexFormats[0]))
+        I830FALLBACK("Unsupported picture format 0x%x\n",
+                         (int)pPict->format);
+
+    /* FIXME: fix repeat support */
+    if (pPict->repeat && ((w&(w-1)) != 0) && ((h&(h-1)) != 0))
+	I830FALLBACK("repeat non log2 aligned!\n");
+
+    if (pPict->filter != PictFilterNearest &&
+        pPict->filter != PictFilterBilinear)
+        I830FALLBACK("Unsupported filter 0x%x\n", pPict->filter);
+
+    return TRUE;
+}
+
+Bool
+I915EXACheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+		      PicturePtr pDstPicture)
+{
+    CARD32 tmp1;
+    
+    /* Check for unsupported compositing operations. */
+    if (op >= sizeof(I915BlendOp) / sizeof(I915BlendOp[0]))
+        I830FALLBACK("Unsupported Composite op 0x%x\n", op);
+                                                                                                                                                            
+    if (pMaskPicture != NULL && pMaskPicture->componentAlpha) {
+        /* Check if it's component alpha that relies on a source alpha and on
+         * the source value.  We can only get one of those into the single
+         * source value that we get to blend with.
+         */
+        if (I915BlendOp[op].src_alpha &&
+            (I915BlendOp[op].blend_cntl & I915_SRC_BLENDFACTOR_MASK) !=
+             I915_SRC_BLENDFACTOR_ZERO)
+            	I830FALLBACK("Component alpha not supported with source "
+                            "alpha and source value blending.\n");
+    }
+
+    if (!I915CheckCompositeTexture(pSrcPicture, 0))
+        I830FALLBACK("Check Src picture texture\n");
+    if (pMaskPicture != NULL && !I915CheckCompositeTexture(pMaskPicture, 1))
+        I830FALLBACK("Check Mask picture texture\n");
+
+    if (!I915GetDestFormat(pDstPicture, &tmp1)) 
+	I830FALLBACK("Get Color buffer format\n");
+
+    return TRUE;
+}
+
+static Bool
+I915TextureSetup(PicturePtr pPict, PixmapPtr pPix, int unit)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pPict->pDrawable->pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD32 format, offset, pitch, filter;
+    int w, h, i;
+    CARD32 wrap_mode = TEXCOORDMODE_CLAMP_EDGE; 
+
+    offset = exaGetPixmapOffset(pPix);
+    pitch = exaGetPixmapPitch(pPix);
+    w = pPict->pDrawable->width;
+    h = pPict->pDrawable->height;
+    scale_units[unit][0] = pPix->drawable.width;
+    scale_units[unit][1] = pPix->drawable.height;
+    draw_coords[unit][0] = pPix->drawable.x;
+    draw_coords[unit][1] = pPix->drawable.y;
+
+    for (i = 0; i < sizeof(I915TexFormats) / sizeof(I915TexFormats[0]); i++) {
+        if (I915TexFormats[i].fmt == pPict->format)
+	    break;
+    }
+    if ( i == sizeof(I915TexFormats)/ sizeof(I915TexFormats[0]) )
+	I830FALLBACK("unknown texture format\n");
+    format = I915TexFormats[i].card_fmt;
+
+    if (pPict->repeat) 
+	wrap_mode = TEXCOORDMODE_WRAP; /* XXX:correct ? */
+    
+    switch (pPict->filter) {
+    case PictFilterNearest:
+        filter = (FILTER_NEAREST << SS2_MAG_FILTER_SHIFT) | 
+			(FILTER_NEAREST << SS2_MIN_FILTER_SHIFT);
+        break;
+    case PictFilterBilinear:
+        filter = (FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) | 
+			(FILTER_LINEAR << SS2_MIN_FILTER_SHIFT);
+        break;
+    default:
+	filter = 0;
+        I830FALLBACK("Bad filter 0x%x\n", pPict->filter);
+    }
+
+    {
+	CARD32 ms3;
+	if (pI830->cpp == 1)
+		format |= MAPSURF_8BIT;
+	else if (pI830->cpp == 2)
+		format |= MAPSURF_16BIT;
+	else
+		format |= MAPSURF_32BIT;
+
+	BEGIN_LP_RING(6);
+	OUT_RING(_3DSTATE_MAP_STATE | (3 * (1 << unit)));
+	OUT_RING(1<<unit);
+	OUT_RING(offset&MS2_ADDRESS_MASK);
+	ms3 = (pPix->drawable.height << MS3_HEIGHT_SHIFT) | 
+		(pPix->drawable.width << MS3_WIDTH_SHIFT) | format;
+	if (!pI830->disableTiling)
+		ms3 |= MS3_USE_FENCE_REGS;
+	OUT_RING(ms3); 
+	OUT_RING(pitch<<MS4_PITCH_SHIFT);
+	OUT_RING(0);
+	ADVANCE_LP_RING();
+     }
+
+     {
+	CARD32 ss2, ss3;
+	BEGIN_LP_RING(6);
+	/* max & min mip level ? or base mip level? */
+
+	OUT_RING(_3DSTATE_SAMPLER_STATE | (3*(1<<unit)));
+	OUT_RING(1<<unit);
+	ss2 = (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT);
+	ss2 |= filter;
+	OUT_RING(ss2);
+	/* repeat? */
+	ss3 = TEXCOORDMODE_WRAP << SS3_TCX_ADDR_MODE_SHIFT;
+	ss3 |= (TEXCOORDMODE_WRAP << SS3_TCY_ADDR_MODE_SHIFT);
+	ss3 |= SS3_NORMALIZED_COORDS;
+	ss3 |= (unit << SS3_TEXTUREMAP_INDEX_SHIFT);
+	OUT_RING(ss3);
+	OUT_RING(0x00000000); /* default color */
+	OUT_RING(0);
+
+	ADVANCE_LP_RING();
+    }
+
+    if (pPict->transform != 0) {
+        is_transform[unit] = TRUE;
+        transform[unit] = pPict->transform;
+    } else {
+        is_transform[unit] = FALSE;
+    }
+
+#ifdef I830DEBUG
+    ErrorF("try to sync to show any errors...");
+    I830Sync(pScrn);
+#endif
+	
+    return TRUE;
+}
+
+static void
+I915DefCtxSetup(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    BEGIN_LP_RING(2);
+    /* set default texture binding, may be in prepare better */
+    OUT_RING(_3DSTATE_COORD_SET_BINDINGS | CSB_TCB(0,0) | CSB_TCB(1,1) |
+	CSB_TCB(2,2) | CSB_TCB(3,3) | CSB_TCB(4,4) | CSB_TCB(5,5) |
+	CSB_TCB(6,6) | CSB_TCB(7,7));
+    OUT_RING(0);
+    ADVANCE_LP_RING();
+}
+
+Bool
+I915EXAPrepareComposite(int op, PicturePtr pSrcPicture,
+			PicturePtr pMaskPicture, PicturePtr pDstPicture,
+			PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD32 dst_format, dst_offset, dst_pitch;
+    CARD32 blendctl;
+
+ErrorF("i915 prepareComposite\n");
+
+    I915GetDestFormat(pDstPicture, &dst_format);
+    dst_offset = exaGetPixmapOffset(pDst);
+    dst_pitch = exaGetPixmapPitch(pDst);
+    draw_coords[2][0] = pDst->drawable.x;
+    draw_coords[2][1] = pDst->drawable.y;
+    
+    I915DefCtxSetup(pScrn);
+
+    if (!I915TextureSetup(pSrcPicture, pSrc, 0))
+	I830FALLBACK("fail to setup src texture\n");
+    if (pMask != NULL) {
+	if (!I915TextureSetup(pMaskPicture, pMask, 1))
+		I830FALLBACK("fail to setup mask texture\n");
+    } else {
+	is_transform[1] = FALSE;
+	scale_units[1][0] = -1;
+	scale_units[1][1] = -1;
+    }
+
+    {
+	CARD32 ss2;
+	BEGIN_LP_RING(24);
+	/*color buffer*/
+	OUT_RING(_3DSTATE_BUF_INFO_CMD);
+	OUT_RING(BUF_3D_ID_COLOR_BACK| BUF_3D_PITCH(dst_pitch)); /* fence, tile? */
+	OUT_RING(BUF_3D_ADDR(dst_offset));
+	OUT_RING(MI_NOOP);
+	
+	OUT_RING(_3DSTATE_DST_BUF_VARS_CMD);
+	OUT_RING(dst_format);
+
+	/* XXX: defaults */
+	OUT_RING(_3DSTATE_DFLT_Z_CMD);
+	OUT_RING(0);
+
+	OUT_RING(_3DSTATE_DFLT_DIFFUSE_CMD);
+	OUT_RING(0);
+
+	OUT_RING(_3DSTATE_DFLT_SPEC_CMD);
+	OUT_RING(0);
+	
+	/* XXX:S3? define vertex format with tex coord sets number*/
+	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1|I1_LOAD_S(2)|I1_LOAD_S(3)|
+		I1_LOAD_S(4)|1);
+	ss2 = S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D);
+	if (pMask)
+		ss2 |= S2_TEXCOORD_FMT(1, TEXCOORDFMT_2D);
+	else
+		ss2 |= S2_TEXCOORD_FMT(1, TEXCOORDFMT_NOT_PRESENT);
+	ss2 |= S2_TEXCOORD_FMT(2, TEXCOORDFMT_NOT_PRESENT);
+	ss2 |= S2_TEXCOORD_FMT(3, TEXCOORDFMT_NOT_PRESENT);
+	ss2 |= S2_TEXCOORD_FMT(4, TEXCOORDFMT_NOT_PRESENT);
+	ss2 |= S2_TEXCOORD_FMT(5, TEXCOORDFMT_NOT_PRESENT);
+	ss2 |= S2_TEXCOORD_FMT(6, TEXCOORDFMT_NOT_PRESENT);
+	ss2 |= S2_TEXCOORD_FMT(7, TEXCOORDFMT_NOT_PRESENT);
+	OUT_RING(ss2);
+	OUT_RING(0x00000000); /*XXX: does ss3 needed? */
+	OUT_RING((1<<S4_POINT_WIDTH_SHIFT)|S4_LINE_WIDTH_ONE| 
+		S4_CULLMODE_NONE| S4_VFMT_XY);  
+
+	/* issue a flush */
+	OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
+	OUT_RING(0);
+
+	/* draw rect is unconditional */
+	OUT_RING(_3DSTATE_DRAW_RECT_CMD);
+	OUT_RING(0x00000000);
+	OUT_RING(0x00000000);  /* ymin, xmin*/
+	OUT_RING(DRAW_YMAX(pScrn->virtualY-1) | DRAW_XMAX(pScrn->virtualX-1));
+	OUT_RING(0x00000000);  /* yorig, xorig (relate to color buffer?)*/
+	OUT_RING(0);
+	ADVANCE_LP_RING();
+    }
+
+	/* For (src In mask) operation */
+	/* IN operator: Multiply src by mask components or mask alpha.*/
+	/* TEXBLENDOP_MODULE: arg1*arg2 */
+
+	/* LOAD_IMMEDIATE_1 ss6 ??*/
+
+	/****
+	   shader program prototype:
+		dcl t0.xy
+		dcl t1.xy
+		dcl_2d s0   
+		dcl_2d s1
+		texld t0, s0
+		texld t1, s1
+		mul oC, t0, t1 ()
+	***/
+    if (!pMask) {
+	BEGIN_LP_RING(1+3+3+3);
+	OUT_RING(_3DSTATE_PIXEL_SHADER_PROGRAM |(3*3-1));
+	OUT_DCL(S, 0);
+	OUT_DCL(T, 0);
+	OUT_TEXLD(OC, 0, 0, T, 0);
+	ADVANCE_LP_RING();
+    } else {
+	BEGIN_LP_RING(1+3*6+3);
+	OUT_RING(_3DSTATE_PIXEL_SHADER_PROGRAM |(3*7-1));
+	OUT_DCL(S, 0);
+	OUT_DCL(S, 1);
+	OUT_DCL(T, 0);
+	OUT_DCL(T, 1);
+	OUT_TEXLD(R, 0, 0, T, 0);
+	OUT_TEXLD(R, 1, 1, T, 1);
+	if (pMaskPicture->componentAlpha && pDstPicture->format != PICT_a8) {
+		/* then just mul */
+		OUT_RING(A0_MUL | (REG_TYPE_OC << A0_DEST_TYPE_SHIFT) | 
+			(0 << A0_DEST_NR_SHIFT) | A0_DEST_CHANNEL_ALL | 
+			(REG_TYPE_R << A0_SRC0_TYPE_SHIFT) | (0 << A0_SRC0_NR_SHIFT));
+		OUT_RING((SRC_X << A1_SRC0_CHANNEL_X_SHIFT)|(SRC_Y << A1_SRC0_CHANNEL_Y_SHIFT)|
+			(SRC_Z << A1_SRC0_CHANNEL_Z_SHIFT)|(SRC_W << A1_SRC0_CHANNEL_W_SHIFT)|
+			(REG_TYPE_R << A1_SRC1_TYPE_SHIFT) | (1 << A1_SRC1_NR_SHIFT) |
+			(SRC_X << A1_SRC1_CHANNEL_X_SHIFT) | (SRC_Y << A1_SRC1_CHANNEL_Y_SHIFT));
+		OUT_RING((SRC_Z << A2_SRC1_CHANNEL_Z_SHIFT) | (SRC_W << A2_SRC1_CHANNEL_W_SHIFT));
+	} else {
+		/* we should duplicate R1's w for all channel, Arithemic can choose channel to use! */
+		OUT_RING(A0_MUL | (REG_TYPE_OC << A0_DEST_TYPE_SHIFT) |
+			(0 << A0_DEST_NR_SHIFT) | A0_DEST_CHANNEL_ALL |
+			(REG_TYPE_R << A0_SRC0_TYPE_SHIFT) | (0 << A0_SRC0_NR_SHIFT));
+		OUT_RING((SRC_X << A1_SRC0_CHANNEL_X_SHIFT) | (SRC_Y << A1_SRC0_CHANNEL_Y_SHIFT) |
+			(SRC_Z << A1_SRC0_CHANNEL_Z_SHIFT) | (SRC_W << A1_SRC0_CHANNEL_W_SHIFT) |
+			(REG_TYPE_R << A1_SRC1_TYPE_SHIFT) | (1 << A1_SRC1_NR_SHIFT) |
+			(SRC_W << A1_SRC1_CHANNEL_X_SHIFT) | (SRC_W << A1_SRC1_CHANNEL_Y_SHIFT));
+		OUT_RING((SRC_W << A2_SRC1_CHANNEL_Z_SHIFT) | (SRC_W << A2_SRC1_CHANNEL_W_SHIFT));
+	}
+	ADVANCE_LP_RING();
+    }
+		
+    {
+	CARD32 ss6;
+	blendctl = I915GetBlendCntl(op, pMaskPicture, pDstPicture->format);
+
+	BEGIN_LP_RING(2);
+	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(6) | 0);
+	ss6 = S6_CBUF_BLEND_ENABLE | S6_COLOR_WRITE_ENABLE;
+	OUT_RING(ss6 | (0 << S6_CBUF_BLEND_FUNC_SHIFT) | blendctl);
+	ADVANCE_LP_RING();
+    }
+
+#ifdef I830DEBUG
+    ErrorF("try to sync to show any errors...");
+    I830Sync(pScrn);
+#endif
+
+    return TRUE;
+}
diff --git a/src/i915_reg.h b/src/i915_reg.h
index 886ae81..e2d7b9d 100644
--- a/src/i915_reg.h
+++ b/src/i915_reg.h
@@ -161,6 +161,9 @@
 #define COLR_BUF_RGB555 		(1<<8)
 #define COLR_BUF_RGB565 		(2<<8)
 #define COLR_BUF_ARGB8888		(3<<8)
+#define COLR_BUF_ARGB4444		(8<<8)
+#define COLR_BUF_ARGB1555		(9<<8)
+#define COLR_BUF_ARGB2AAA		(0xa<<8)
 #define DEPTH_FRMT_16_FIXED		0
 #define DEPTH_FRMT_16_FLOAT		(1<<2)
 #define DEPTH_FRMT_24_FIXED_8_OTHER	(2<<2)
diff-tree de470aaf5c47f4d2b0f477ac678039ef43af773d (from 22843830ebdd14247aa76d19f89494a56e2ac887)
Author: Adam Jackson <ajax at benzedrine.nwnk.net>
Date:   Thu Jul 13 19:10:11 2006 -0400

    In I830xf86SortModes, catch cases where two modes are equal in only one
    dimension, by comparing the areas of the modes.  Otherwise, 800x600 would
    sort before 1024x600 if it was added later.

diff --git a/src/i830_modes.c b/src/i830_modes.c
index bf480a6..1965c39 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -198,6 +198,7 @@ I830xf86SortModes(DisplayModePtr new, Di
     while (p) {
 	if (((new->HDisplay < p->HDisplay) &&
 	     (new->VDisplay < p->VDisplay)) ||
+	    ((new->HDisplay * new->VDisplay) < (p->HDisplay * p->VDisplay)) ||
 	    ((new->HDisplay == p->HDisplay) &&
 	     (new->VDisplay == p->VDisplay) &&
 	     (new->Clock < p->Clock))) {
diff-tree 22843830ebdd14247aa76d19f89494a56e2ac887 (from 05bcbadd130524694e11e372d54cb419cea566cc)
Author: Adam Jackson <ajax at benzedrine.nwnk.net>
Date:   Thu Jul 13 17:20:17 2006 -0400

    Fix a thinko; would only inject the FP native mode if a mode list was already
    found, which is never the case when there's no xorg.conf.

diff --git a/src/i830_modes.c b/src/i830_modes.c
index 90bd093..bf480a6 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -493,7 +493,7 @@ i830GetLVDSModes(ScrnInfoPtr pScrn, char
    /* If the user hasn't specified modes, add the native mode */
    if (!count) {
       new = i830FPNativeMode(pScrn);
-      if (first) {
+      if (new) {
 	 I830xf86SortModes(new, &first, &last);
 	 count = 1;
       }
diff-tree 05bcbadd130524694e11e372d54cb419cea566cc (from b65f18b05a5fba506b71293b495cab95197037ac)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Tue Jul 11 14:05:38 2006 -0700

    Avoid NULL dereference if cursor position changes during a mode change.

diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index b373649..2cb069c 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -1,4 +1,4 @@
-
+/* -*- c-basic-offset: 3 -*- */
 /**************************************************************************
 
 Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
@@ -398,9 +398,15 @@ I830SetCursorPosition(ScrnInfoPtr pScrn,
    x -= pScrn->frameX0;
    y -= pScrn->frameY0;
 
-   /* Clamp the cursor position to the visible screen area */
-   if (x >= pScrn->currentMode->HDisplay) x = pScrn->currentMode->HDisplay - 1;
-   if (y >= pScrn->currentMode->VDisplay) y = pScrn->currentMode->VDisplay - 1;
+   /* Clamp the cursor position to the visible screen area.  Ignore this if we
+    * are doing motion (with SilkenMouse) while the currentMode being changed.
+    */
+   if (pScrn->currentMode != NULL) {
+     if (x >= pScrn->currentMode->HDisplay)
+       x = pScrn->currentMode->HDisplay - 1;
+     if (y >= pScrn->currentMode->VDisplay)
+       y = pScrn->currentMode->VDisplay - 1;
+   }
    if (x <= -I810_CURSOR_X) x = -I810_CURSOR_X + 1;
    if (y <= -I810_CURSOR_Y) y = -I810_CURSOR_Y + 1;
 
diff-tree b65f18b05a5fba506b71293b495cab95197037ac (from 5a2e04bd1b700a8a6e26136b8831ef5e4d11b565)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Tue Jul 11 13:29:57 2006 -0700

    Bug #7443: Respect the user's Modes configuration, and make it more useful.
    
    Now, mode names generated by DDC get names of the form "WIDTHxHEIGHTxREFRESH".
    The matching for user Modes lines takes the user Modes as the prefix that
    needs to match, rather than an exact string match or "WIDTHxHEIGHT" match.  So
    one can, for example, specify "1024x768" to get any old 1024x768, or
    1024x768x60 to get one of the modes named 1024x768x60.

diff --git a/src/i830_gtf.c b/src/i830_gtf.c
index 2eff46a..663a2f4 100644
--- a/src/i830_gtf.c
+++ b/src/i830_gtf.c
@@ -45,6 +45,7 @@
 #include "vbe.h"
 #include "vbeModes.h"
 #include "i830.h"
+#include "i830_xf86Modes.h"
 
 #include <math.h>
 
@@ -97,7 +98,6 @@ i830GetGTF(int h_pixels, int v_lines, fl
     float h_sync;
     float h_front_porch;
     float v_odd_front_porch_lines;
-    char modename[20];
     DisplayModePtr m;
 
     m = xnfcalloc(sizeof(DisplayModeRec), 1);
@@ -349,8 +349,7 @@ i830GetGTF(int h_pixels, int v_lines, fl
     m->HSync = h_freq;
     m->VRefresh = v_frame_rate /* freq */;
 
-    snprintf(modename, sizeof(modename), "%dx%d", m->HDisplay,m->VDisplay);
-    m->name = xnfstrdup(modename);
+    i830xf86SetModeDefaultName(m);
 
     return (m);
 }
diff --git a/src/i830_modes.c b/src/i830_modes.c
index ac25864..90bd093 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -176,7 +176,11 @@ I830DuplicateMode(DisplayModePtr pMode)
     *pNew = *pMode;
     pNew->next = NULL;
     pNew->prev = NULL;
-    pNew->name = xnfstrdup(pMode->name);
+    if (pNew->name == NULL) {
+	i830xf86SetModeDefaultName(pMode);
+    } else {
+	pNew->name = xnfstrdup(pMode->name);
+    }
 
     return pNew;
 }
@@ -242,6 +246,7 @@ I830GetVESAEstablishedMode(ScrnInfoPtr p
 	    fabs(i830xf86ModeVRefresh(pMode) - est_timings[i].refresh) < 1.0)
 	{
 	    DisplayModePtr pNew = I830DuplicateMode(pMode);
+	    i830xf86SetModeDefaultName(pNew);
 	    pNew->VRefresh = i830xf86ModeVRefresh(pMode);
 	    return pNew;
 	}
@@ -257,7 +262,6 @@ i830GetDDCModes(ScrnInfoPtr pScrn, xf86M
     DisplayModePtr  first = NULL;
     int             count = 0;
     int             j, tmp;
-    char            stmp[32];
 
     if (ddc == NULL)
 	return NULL;
@@ -276,10 +280,6 @@ i830GetDDCModes(ScrnInfoPtr pScrn, xf86M
 	    new->HDisplay   = d_timings->h_active;
 	    new->VDisplay   = d_timings->v_active;
 
-	    sprintf(stmp, "%dx%d", new->HDisplay, new->VDisplay);
-	    new->name       = xnfalloc(strlen(stmp) + 1);
-	    strcpy(new->name, stmp);
-
 	    new->HTotal     = new->HDisplay + d_timings->h_blanking;
 	    new->HSyncStart = new->HDisplay + d_timings->h_sync_off;
 	    new->HSyncEnd   = new->HSyncStart + d_timings->h_sync_width;
@@ -291,6 +291,8 @@ i830GetDDCModes(ScrnInfoPtr pScrn, xf86M
 	    new->status     = MODE_OK;
 	    new->type       = M_T_DEFAULT;
 
+	    i830xf86SetModeDefaultName(new);
+
 	    if (d_timings->sync == 3) {
 		switch (d_timings->misc) {
 		case 0: new->Flags |= V_NHSYNC | V_NVSYNC; break;
@@ -806,6 +808,11 @@ I830ReprobePipeModeList(ScrnInfoPtr pScr
 
 	i830xf86PruneInvalidModes(pScrn, &pI830->pipeMon[pipe]->Modes, TRUE);
 
+	/* silently prune modes down to ones matching the user's configuration.
+	 */
+	i830xf86ValidateModesUserConfig(pScrn, pI830->pipeMon[pipe]->Modes);
+	i830xf86PruneInvalidModes(pScrn, &pI830->pipeMon[pipe]->Modes, FALSE);
+
 	for (pMode = pI830->pipeMon[pipe]->Modes; pMode != NULL;
 	     pMode = pMode->next)
 	{
diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c
index 4c5de4d..8c34053 100644
--- a/src/i830_xf86Modes.c
+++ b/src/i830_xf86Modes.c
@@ -1,3 +1,4 @@
+/* -*- c-basic-offset: 4 -*- */
 /* $XdotOrg: xserver/xorg/hw/xfree86/common/xf86Mode.c,v 1.10 2006/03/07 16:00:57 libv Exp $ */
 /* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Mode.c,v 1.69 2003/10/08 14:58:28 dawes Exp $ */
 /*
@@ -87,6 +88,22 @@ i830xf86ModeVRefresh(DisplayModePtr mode
     return refresh;
 }
 
+/**
+ * Sets a default mode name of <width>x<height>x<refresh> on a mode.
+ *
+ * The refresh rate doesn't contain decimals, as that's expected to be
+ * unimportant from the user's perspective for non-custom modelines.
+ */
+void
+i830xf86SetModeDefaultName(DisplayModePtr mode)
+{
+    if (mode->name != NULL)
+	xfree(mode->name);
+
+    mode->name = XNFprintf("%dx%dx%.0f", mode->HDisplay, mode->VDisplay,
+			   i830xf86ModeVRefresh(mode));
+}
+
 /*
  * I830xf86SetModeCrtc
  *
@@ -386,6 +403,45 @@ i830xf86ValidateModesClocks(ScrnInfoPtr 
 }
 
 /**
+ * If the user has specified a set of mode names to use, mark as bad any modes
+ * not listed.
+ *
+ * The user mode names specified are prefixes to names of modes, so "1024x768"
+ * will match modes named "1024x768", "1024x768x75", "1024x768-good", but
+ * "1024x768x75" would only match "1024x768x75" from that list.
+ *
+ * MODE_BAD is used as the rejection flag, for lack of a better flag.
+ *
+ * \param modeList doubly-linked or circular list of modes.
+ *
+ * This is not in xf86Modes.c, but would be part of the proposed new API.
+ */
+void
+i830xf86ValidateModesUserConfig(ScrnInfoPtr pScrn, DisplayModePtr modeList)
+{
+    DisplayModePtr mode;
+
+    if (pScrn->display->modes[0] == NULL)
+	return;
+
+    for (mode = modeList; mode != NULL; mode = mode->next) {
+	int i;
+	Bool good = FALSE;
+
+	for (i = 0; pScrn->display->modes[i] != NULL; i++) {
+	    if (strncmp(pScrn->display->modes[i], mode->name,
+			strlen(pScrn->display->modes[i])) == 0) {
+		good = TRUE;
+		break;
+	    }
+	}
+	if (!good)
+	    mode->status = MODE_BAD;
+    }
+}
+
+
+/**
  * Frees any modes from the list with a status other than MODE_OK.
  *
  * \param modeList pointer to a doubly-linked or circular list of modes.
diff --git a/src/i830_xf86Modes.h b/src/i830_xf86Modes.h
index 855aa46..0cba887 100644
--- a/src/i830_xf86Modes.h
+++ b/src/i830_xf86Modes.h
@@ -32,6 +32,9 @@ double
 i830xf86ModeVRefresh(DisplayModePtr mode);
 
 void
+i830xf86SetModeDefaultName(DisplayModePtr mode);
+
+void
 I830xf86SetModeCrtc(DisplayModePtr p, int adjustFlags);
 
 Bool
@@ -62,6 +65,9 @@ i830xf86ValidateModesFlags(ScrnInfoPtr p
 			    int flags);
 
 void
+i830xf86ValidateModesUserConfig(ScrnInfoPtr pScrn, DisplayModePtr modeList);
+
+void
 PrintModeline(int scrnIndex,DisplayModePtr mode);
 
 extern DisplayModeRec I830xf86DefaultModes[];
diff-tree 5a2e04bd1b700a8a6e26136b8831ef5e4d11b565 (from f9499a68da0ce459fed0b29b998678fd81898a51)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Tue Jul 11 10:21:51 2006 -0700

    Fix crash with DDC when there are no user modes to add.

diff --git a/src/i830_modes.c b/src/i830_modes.c
index 1a572d1..ac25864 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -1,3 +1,4 @@
+/* -*- c-basic-offset: 4 -*- */
 
 #define DEBUG_VERB 2
 /*
@@ -548,6 +549,9 @@ i830AppendModes(ScrnInfoPtr pScrn, Displ
     DisplayModePtr first = *modeList;
     DisplayModePtr last = i830GetModeListTail(first);
 
+    if (addModes == NULL)
+      return;
+
     if (first == NULL) {
 	*modeList = addModes;
     } else {
diff-tree f9499a68da0ce459fed0b29b998678fd81898a51 (from 7068468ac1951bfca0071bb9b1a99df4f37368a0)
Author: Luká\u0161 Hejtmánek <xhejtman at mail.muni.cz>
Date:   Tue Jul 11 10:13:18 2006 -0700

    Make gamma settings apply to the cursor as well, and fix clone-mode gamma.

diff --git a/src/i830.h b/src/i830.h
index 1123001..3a93931 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -231,6 +231,8 @@ typedef struct _I830Rec {
     */
    DisplayModePtr savedCurrentMode;
 
+   Bool gammaEnabled[MAX_DISPLAY_PIPES];
+
    Bool Clone;
    int CloneRefresh;
    int CloneHDisplay;
diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index 79d950e..b373649 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -93,8 +93,6 @@ I830InitHWCursor(ScrnInfoPtr pScrn)
 		MCURSOR_PIPE_SELECT);
       temp |= CURSOR_MODE_DISABLE;
       temp |= (pI830->pipe << 28);
-/*      if(pI830->CursorIsARGB)
-         temp |= MCURSOR_GAMMA_ENABLE; */
       /* Need to set control, then address. */
       OUTREG(CURSOR_A_CONTROL, temp);
       if (pI830->CursorIsARGB)
@@ -115,8 +113,6 @@ I830InitHWCursor(ScrnInfoPtr pScrn)
       temp &= ~(CURSOR_FORMAT_MASK | CURSOR_GAMMA_ENABLE |
 		CURSOR_ENABLE  | CURSOR_STRIDE_MASK);
       temp |= (CURSOR_FORMAT_3C);
-/*      if (pI830->CursorIsARGB)
-         temp |= CURSOR_GAMMA_ENABLE;*/
       /* This initialises the format and leave the cursor disabled. */
       OUTREG(CURSOR_CONTROL, temp);
       /* Need to set address and size after disabling. */
@@ -484,9 +480,11 @@ I830ShowCursor(ScrnInfoPtr pScrn)
    if (IS_MOBILE(pI830) || IS_I9XX(pI830)) {
       temp = INREG(CURSOR_A_CONTROL);
       temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
-      if (pI830->CursorIsARGB)
-         temp |= CURSOR_MODE_64_ARGB_AX /* | MCURSOR_GAMMA_ENABLE*/;
-      else
+      if (pI830->CursorIsARGB) {
+         temp |= CURSOR_MODE_64_ARGB_AX;
+	 if (pI830->gammaEnabled[pI830->pipe])
+	    temp |= MCURSOR_GAMMA_ENABLE;
+      } else
          temp |= CURSOR_MODE_64_4C_AX;
       temp |= (pI830->pipe << 28); /* Connect to correct pipe */
       /* Need to set mode, then address. */
@@ -508,9 +506,11 @@ I830ShowCursor(ScrnInfoPtr pScrn)
       temp = INREG(CURSOR_CONTROL);
       temp &= ~(CURSOR_FORMAT_MASK);
       temp |= CURSOR_ENABLE;
-      if (pI830->CursorIsARGB)
-         temp |= CURSOR_FORMAT_ARGB /* | CURSOR_GAMMA_ENABLE*/;
-      else 
+      if (pI830->CursorIsARGB) {
+         temp |= CURSOR_FORMAT_ARGB;
+	 if (pI830->gammaEnabled[pI830->pipe])
+	    temp |= CURSOR_GAMMA_ENABLE;
+      } else
          temp |= CURSOR_FORMAT_3C;
       OUTREG(CURSOR_CONTROL, temp);
       if (pI830->CursorIsARGB)
diff --git a/src/i830_display.c b/src/i830_display.c
index e8c8509..1496c3a 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -476,7 +476,9 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 
     if (outputs & (PIPE_TV_ACTIVE | PIPE_TV2_ACTIVE))
 	dpll |= PLL_REF_INPUT_TVCLKINBC;
-    else
+    else if (outputs & (PIPE_LCD_ACTIVE))
+	dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
+    else	
 	dpll |= PLL_REF_INPUT_DREFCLK;
 
     if (is_dvo) {
@@ -556,6 +558,10 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	FatalError("unknown display bpp\n");
     }
 
+    if (pI830->gammaEnabled[pipe]) {
+ 	dspcntr |= DISPPLANE_GAMMA_ENABLE;
+    }
+
     if (is_sdvo)
 	adpa = ADPA_DAC_DISABLE;
     else
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 7815c57..396685a 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -870,8 +870,6 @@ I830UnmapMem(ScrnInfoPtr pScrn)
    return TRUE;
 }
 
-static CARD32 val8[256];
-
 static void
 I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
 		LOCO * colors, VisualPtr pVisual)
@@ -882,33 +880,41 @@ I830LoadPalette(ScrnInfoPtr pScrn, int n
    CARD32 val, temp;
    int palreg;
    int dspreg, dspbase;
+   int p;
 
    DPRINTF(PFX, "I830LoadPalette: numColors: %d\n", numColors);
    pI830 = I830PTR(pScrn);
 
-   if (pI830->pipe == 0) {
-      palreg = PALETTE_A;
-      dspreg = DSPACNTR;
-      dspbase = DSPABASE;
-   } else {
-      palreg = PALETTE_B;
-      dspreg = DSPBCNTR;
-      dspbase = DSPBBASE;
-   }
-
-   /* To ensure gamma is enabled we need to turn off and on the plane */
-   temp = INREG(dspreg);
-   OUTREG(dspreg, temp & ~(1<<31));
-   OUTREG(dspbase, INREG(dspbase));
-   OUTREG(dspreg, temp | DISPPLANE_GAMMA_ENABLE);
-   OUTREG(dspbase, INREG(dspbase));
+   for(p=0; p < pI830->availablePipes; p++) {
+
+      if (p == 0) {
+         palreg = PALETTE_A;
+         dspreg = DSPACNTR;
+         dspbase = DSPABASE;
+      } else {
+         palreg = PALETTE_B;
+         dspreg = DSPBCNTR;
+         dspbase = DSPBBASE;
+      }
 
-   /* It seems that an initial read is needed. */
-   temp = INREG(palreg);
+      if (pI830->planeEnabled[p] == 0)
+	 continue;  
 
-   switch(pScrn->depth) {
-   case 15:
-      for (i = 0; i < numColors; i++) {
+      pI830->gammaEnabled[p] = 1;
+      
+      /* To ensure gamma is enabled we need to turn off and on the plane */
+      temp = INREG(dspreg);
+      OUTREG(dspreg, temp & ~(1<<31));
+      OUTREG(dspbase, INREG(dspbase));
+      OUTREG(dspreg, temp | DISPPLANE_GAMMA_ENABLE);
+      OUTREG(dspbase, INREG(dspbase));
+
+      /* It seems that an initial read is needed. */
+      temp = INREG(palreg);
+
+      switch(pScrn->depth) {
+      case 15:
+        for (i = 0; i < numColors; i++) {
          index = indices[i];
          r = colors[index].red;
          g = colors[index].green;
@@ -917,10 +923,10 @@ I830LoadPalette(ScrnInfoPtr pScrn, int n
          for (j = 0; j < 8; j++) {
 	    OUTREG(palreg + index * 32 + (j * 4), val);
          }
-      }
+        }
       break;
-   case 16:
-      for (i = 0; i < numColors; i++) {
+      case 16:
+        for (i = 0; i < numColors; i++) {
          index = indices[i];
 	 r   = colors[index / 2].red;
 	 g   = colors[index].green;
@@ -943,42 +949,24 @@ I830LoadPalette(ScrnInfoPtr pScrn, int n
 	    OUTREG(palreg + index * 32 + 8, val);
 	    OUTREG(palreg + index * 32 + 12, val);
 	 }
-      }
-      break;
-   default:
-#if 1
-      /* Dual head 8bpp modes seem to squish the primary's cmap - reload */
-      if (I830IsPrimary(pScrn) && xf86IsEntityShared(pScrn->entityList[0]) &&
-          pScrn->depth == 8) {
-         for(i = 0; i < numColors; i++) {
-	    index = indices[i];
-	    r = colors[index].red;
-	    g = colors[index].green;
-	    b = colors[index].blue;
-	    val8[index] = (r << 16) | (g << 8) | b;
         }
-      }
-#endif
-      for(i = 0; i < numColors; i++) {
+        break;
+      default:
+        for(i = 0; i < numColors; i++) {
 	 index = indices[i];
 	 r = colors[index].red;
 	 g = colors[index].green;
 	 b = colors[index].blue;
 	 val = (r << 16) | (g << 8) | b;
 	 OUTREG(palreg + index * 4, val);
-#if 1
-         /* Dual head 8bpp modes seem to squish the primary's cmap - reload */
-         if (!I830IsPrimary(pScrn) && xf86IsEntityShared(pScrn->entityList[0]) &&
-             pScrn->depth == 8) {
-  	    if (palreg == PALETTE_A)
-	       OUTREG(PALETTE_B + index * 4, val8[index]);
-	    else
-	       OUTREG(PALETTE_A + index * 4, val8[index]);
-         }
-#endif
-      }
-      break;
+        }
+        break;
+     }
    }
+   
+   /* Enable gamma for Cursor if ARGB */
+   if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn)
+      pI830->CursorInfoRec->ShowCursor(pScrn);
 }
 
 #if 0
diff-tree 7068468ac1951bfca0071bb9b1a99df4f37368a0 (from b912bf5673e38e03b0b25c2f5d05fe7e26994ba1)
Author: Luká\u0161 Hejtmánek <xhejtman at mail.muni.cz>
Date:   Tue Jul 11 09:51:26 2006 -0700

    Add support for adjusting saturation value of overlay video.

diff --git a/src/i830_video.c b/src/i830_video.c
index a608a7e..05f7f46 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -116,7 +116,7 @@ static void I830BlockHandler(int, pointe
 
 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
 
-static Atom xvBrightness, xvContrast, xvColorKey, xvPipe, xvDoubleBuffer;
+static Atom xvBrightness, xvContrast, xvSaturation, xvColorKey, xvPipe, xvDoubleBuffer;
 static Atom xvGamma0, xvGamma1, xvGamma2, xvGamma3, xvGamma4, xvGamma5;
 
 #define IMAGE_MAX_WIDTH		1920
@@ -278,11 +278,12 @@ static XF86AttributeRec CloneAttributes[
    {XvSettable | XvGettable, 0, 1, "XV_PIPE"}
 };
 
-#define NUM_ATTRIBUTES 4
+#define NUM_ATTRIBUTES 5
 static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = {
    {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
    {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"},
    {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"},
+   {XvSettable | XvGettable, 0, 1023, "XV_SATURATION"},
    {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"}
 };
 
@@ -373,6 +374,7 @@ typedef struct {
 
    int brightness;
    int contrast;
+   int saturation;
    int pipe;
    int doubleBuffer;
 
@@ -500,7 +502,7 @@ I830ResetVideo(ScrnInfoPtr pScrn)
    overlay->SWIDTHSW = 0;
    overlay->SHEIGHT = 0;
    overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff);
-   overlay->OCLRC1 = 0x00000080;	/* saturation: bypass */
+   overlay->OCLRC1 = pPriv->saturation;
    overlay->AWINPOS = 0;
    overlay->AWINSZ = 0;
    overlay->FASTHSCALE = 0;
@@ -709,6 +711,7 @@ I830SetupImageVideo(ScreenPtr pScreen)
    pPriv->videoStatus = 0;
    pPriv->brightness = 0;
    pPriv->contrast = 64;
+   pPriv->saturation = 128;
    pPriv->pipe = pI830->pipe; /* default to current pipe */
    pPriv->linear = NULL;
    pPriv->currentBuf = 0;
@@ -744,6 +747,7 @@ I830SetupImageVideo(ScreenPtr pScreen)
    xvColorKey = MAKE_ATOM("XV_COLORKEY");
    xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
    xvContrast = MAKE_ATOM("XV_CONTRAST");
+   xvSaturation = MAKE_ATOM("XV_SATURATION");
    xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER");
 
    /* Allow the pipe to be switched from pipe A to B when in clone mode */
@@ -864,6 +868,16 @@ I830SetPortAttribute(ScrnInfoPtr pScrn,
 #if 1
       OVERLAY_OFF;
 #endif
+   } else if (attribute == xvSaturation) {
+      if ((value < 0) || (value > 1023))
+	 return BadValue;
+      pPriv->saturation = value;
+      overlay->OCLRC1 = pPriv->saturation;
+      overlay->OCMD &= ~OVERLAY_ENABLE;
+      OVERLAY_UPDATE;
+#if 1
+      OVERLAY_OFF;
+#endif
    } else if (pI830->Clone && attribute == xvPipe) {
       if ((value < 0) || (value > 1))
          return BadValue;
@@ -953,6 +967,8 @@ I830GetPortAttribute(ScrnInfoPtr pScrn,
       *value = pPriv->brightness;
    } else if (attribute == xvContrast) {
       *value = pPriv->contrast;
+   } else if (attribute == xvSaturation) {
+      *value = pPriv->saturation;
    } else if (pI830->Clone && attribute == xvPipe) {
       *value = pPriv->pipe;
    } else if (attribute == xvGamma0 && (IS_I9XX(pI830))) {
diff-tree b912bf5673e38e03b0b25c2f5d05fe7e26994ba1 (from d75490701cdbf2ab6eab82eaa078790a5fe0aea0)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Jul 10 18:35:20 2006 -0700

    Clean up warnings in sil164 module.

diff --git a/src/sil164/sil164.c b/src/sil164/sil164.c
index 93640ae..a274262 100644
--- a/src/sil164/sil164.c
+++ b/src/sil164/sil164.c
@@ -124,8 +124,6 @@ out:
 static Bool
 sil164Init(I2CDevPtr d)
 {
-    SIL164Ptr sil = SILPTR(d);
-
     /* not much to do */
     return TRUE;
 }
@@ -133,16 +131,12 @@ sil164Init(I2CDevPtr d)
 static ModeStatus
 sil164ModeValid(I2CDevPtr d, DisplayModePtr mode)
 {
-    SIL164Ptr sil = SILPTR(d);
-
     return MODE_OK;
 }
 
 static void
 sil164Mode(I2CDevPtr d, DisplayModePtr mode)
 {
-    SIL164Ptr sil = SILPTR(d);
-
     sil164Power(d, TRUE);
     sil164PrintRegs(d);
 
diff-tree d75490701cdbf2ab6eab82eaa078790a5fe0aea0 (from 426d26ea446d646fa8f561ea0e03c8e4a2c0c315)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Jul 10 18:21:04 2006 -0700

    Hook up SiI164 mode setting (just a matter of turning the chip on).
    
    Also adds register dumping in case this turns out to not be enough, and fixes
    a couple of prototypes.

diff --git a/src/i830_display.c b/src/i830_display.c
index 7b96b3a..e8c8509 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -1,3 +1,4 @@
+/* -*- c-basic-offset: 4 -*- */
 /*
  * Copyright © 2006 Intel Corporation
  *
@@ -843,8 +844,14 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
     }
 
     for (i = 0; i < pI830->num_outputs; i++) {
-	if (pI830->output[i].sdvo_drv)
-	    I830SDVOPreSetMode(pI830->output[i].sdvo_drv, pMode);
+	struct _I830OutputRec *output = &pI830->output[i];
+
+	if (output->sdvo_drv)
+	    I830SDVOPreSetMode(output->sdvo_drv, pMode);
+
+	if (output->i2c_drv != NULL)
+	    output->i2c_drv->vid_rec->Mode(output->i2c_drv->dev_priv,
+					   pMode);
     }
 
     if (pI830->planeEnabled[0]) {
diff --git a/src/sil164/sil164.c b/src/sil164/sil164.c
index 77a7a00..93640ae 100644
--- a/src/sil164/sil164.c
+++ b/src/sil164/sil164.c
@@ -37,8 +37,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "sil164.h"
 #include "sil164_reg.h"
 
+static void
+sil164PrintRegs(I2CDevPtr d);
+static void
+sil164Power(I2CDevPtr d, Bool On);
+
 static Bool
-sil164ReadByte(SIL164Ptr sil, int addr, unsigned char *ch)
+sil164ReadByte(SIL164Ptr sil, int addr, CARD8 *ch)
 {
     if (!xf86I2CReadByte(&(sil->d), addr, ch)) {
 	xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR,
@@ -50,7 +55,7 @@ sil164ReadByte(SIL164Ptr sil, int addr, 
 }
 
 static Bool
-sil164WriteByte(SIL164Ptr sil, int addr, unsigned char ch)
+sil164WriteByte(SIL164Ptr sil, int addr, CARD8 ch)
 {
     if (!xf86I2CWriteByte(&(sil->d), addr, ch)) {
 	xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR,
@@ -138,6 +143,15 @@ sil164Mode(I2CDevPtr d, DisplayModePtr m
 {
     SIL164Ptr sil = SILPTR(d);
 
+    sil164Power(d, TRUE);
+    sil164PrintRegs(d);
+
+    /* recommended programming sequence from doc */
+    /*sil164WriteByte(sil, 0x08, 0x30);
+      sil164WriteByte(sil, 0x09, 0x00);
+      sil164WriteByte(sil, 0x0a, 0x90);
+      sil164WriteByte(sil, 0x0c, 0x89);
+      sil164WriteByte(sil, 0x08, 0x31);*/
     /* don't do much */
     return;
 }
@@ -168,6 +182,20 @@ static void
 sil164PrintRegs(I2CDevPtr d)
 {
     SIL164Ptr sil = SILPTR(d);
+    CARD8 val;
+
+    sil164ReadByte(sil, SIL164_FREQ_LO, &val);
+    xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_INFO, "SIL164_FREQ_LO: 0x%02x\n",
+	       val);
+    sil164ReadByte(sil, SIL164_FREQ_HI, &val);
+    xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_INFO, "SIL164_FREQ_HI: 0x%02x\n",
+	       val);
+    sil164ReadByte(sil, SIL164_REG8, &val);
+    xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_INFO, "SIL164_REG8: 0x%02x\n", val);
+    sil164ReadByte(sil, SIL164_REG9, &val);
+    xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_INFO, "SIL164_REG9: 0x%02x\n", val);
+    sil164ReadByte(sil, SIL164_REGC, &val);
+    xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_INFO, "SIL164_REGC: 0x%02x\n", val);
 }
 
 static void
diff-tree 426d26ea446d646fa8f561ea0e03c8e4a2c0c315 (from 8d7987d00242020d29a2574ac0c8b6e55cc22112)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Jul 10 18:19:51 2006 -0700

    Fix prototype for SaveRegs.

diff --git a/src/i2c_vid.h b/src/i2c_vid.h
index fbf7284..5a743d2 100644
--- a/src/i2c_vid.h
+++ b/src/i2c_vid.h
@@ -9,7 +9,7 @@ typedef struct _I830I2CVidOutputRec {
   void (*Mode)(I2CDevPtr d, DisplayModePtr mode);
   void (*Power)(I2CDevPtr d, Bool On);
   void (*PrintRegs)(I2CDevPtr d);
-  void (*SaveRegs)(void *d);
+  void (*SaveRegs)(I2CDevPtr d);
   void (*RestoreRegs)(I2CDevPtr d);
 } I830I2CVidOutputRec, *I830I2CVidOutputPtr;
 
diff-tree 8d7987d00242020d29a2574ac0c8b6e55cc22112 (from f5a01a2ef02125611d5fb74c20d53d52e544701a)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Jul 10 17:34:57 2006 -0700

    Move to 4-space indents in sil164.

diff --git a/src/sil164/sil164.c b/src/sil164/sil164.c
index 5e35323..77a7a00 100644
--- a/src/sil164/sil164.c
+++ b/src/sil164/sil164.c
@@ -1,3 +1,4 @@
+/* -*- c-basic-offset: 4 -*- */
 /**************************************************************************
 
 Copyright © 2006 Dave Airlie
@@ -36,157 +37,169 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "sil164.h"
 #include "sil164_reg.h"
 
-static Bool sil164ReadByte(SIL164Ptr sil, int addr, unsigned char *ch)
+static Bool
+sil164ReadByte(SIL164Ptr sil, int addr, unsigned char *ch)
 {
-  if (!xf86I2CReadByte(&(sil->d), addr, ch)) {
-    xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, "Unable to read from %s Slave %d.\n", sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
-    return FALSE;
-  }
-  return TRUE;
-}
-
-static Bool sil164WriteByte(SIL164Ptr sil, int addr, unsigned char ch)
-{
-  if (!xf86I2CWriteByte(&(sil->d), addr, ch)) {
-    xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, "Unable to write to %s Slave %d.\n", sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
-    return FALSE;
-  }
-  return TRUE;
+    if (!xf86I2CReadByte(&(sil->d), addr, ch)) {
+	xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR,
+		   "Unable to read from %s Slave %d.\n",
+		   sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
+	return FALSE;
+    }
+    return TRUE;
+}
+
+static Bool
+sil164WriteByte(SIL164Ptr sil, int addr, unsigned char ch)
+{
+    if (!xf86I2CWriteByte(&(sil->d), addr, ch)) {
+	xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR,
+		   "Unable to write to %s Slave %d.\n",
+		   sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
+	return FALSE;
+    }
+    return TRUE;
 }
 
 /* Silicon Image 164 driver for chip on i2c bus */
-static void *sil164Detect(I2CBusPtr b, I2CSlaveAddr addr)
+static void *
+sil164Detect(I2CBusPtr b, I2CSlaveAddr addr)
 {
-  /* this will detect the SIL164 chip on the specified i2c bus */
-  SIL164Ptr sil;
-  unsigned char ch;
-
-  xf86DrvMsg(b->scrnIndex, X_ERROR, "detecting sil164\n");
-  
-  sil = xcalloc(1, sizeof(SIL164Rec));
-  if (sil == NULL)
-    return NULL;
-
-  sil->d.DevName = "SIL164 TMDS Controller";
-  sil->d.SlaveAddr = addr;
-  sil->d.pI2CBus = b;
-  sil->d.StartTimeout = b->StartTimeout;
-  sil->d.BitTimeout = b->BitTimeout;
-  sil->d.AcknTimeout = b->AcknTimeout;
-  sil->d.ByteTimeout = b->ByteTimeout;
-  sil->d.DriverPrivate.ptr = sil;
-
-  if (!sil164ReadByte(sil, SIL164_VID_LO, &ch))
-    goto out;
-
-  if (ch!=(SIL164_VID & 0xFF))
-  {
-    xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, "sil164 not detected got %d: from %s Slave %d.\n", ch, sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
-    goto out;
-  }
-
+    /* this will detect the SIL164 chip on the specified i2c bus */
+    SIL164Ptr sil;
+    unsigned char ch;
+
+    xf86DrvMsg(b->scrnIndex, X_ERROR, "detecting sil164\n");
+
+    sil = xcalloc(1, sizeof(SIL164Rec));
+    if (sil == NULL)
+	return NULL;
+
+    sil->d.DevName = "SIL164 TMDS Controller";
+    sil->d.SlaveAddr = addr;
+    sil->d.pI2CBus = b;
+    sil->d.StartTimeout = b->StartTimeout;
+    sil->d.BitTimeout = b->BitTimeout;
+    sil->d.AcknTimeout = b->AcknTimeout;
+    sil->d.ByteTimeout = b->ByteTimeout;
+    sil->d.DriverPrivate.ptr = sil;
+
+    if (!sil164ReadByte(sil, SIL164_VID_LO, &ch))
+	goto out;
+
+    if (ch!=(SIL164_VID & 0xFF)) {
+	xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR,
+		   "sil164 not detected got %d: from %s Slave %d.\n",
+		   ch, sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
+	goto out;
+    }
+
+    if (!sil164ReadByte(sil, SIL164_DID_LO, &ch))
+	goto out;
+
+    if (ch!=(SIL164_DID & 0xFF)) {
+	xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR,
+		   "sil164 not detected got %d: from %s Slave %d.\n",
+		   ch, sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
+	goto out;
+    }
+
+    if (!xf86I2CDevInit(&(sil->d))) {
+	goto out;
+    }
 
-  if (!sil164ReadByte(sil, SIL164_DID_LO, &ch))
-    goto out;
+    return sil;
 
-  if (ch!=(SIL164_DID & 0xFF))
-  {
-    xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, "sil164 not detected got %d: from %s Slave %d.\n", ch, sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
-    goto out;
-  }
-
-
-  if (!xf86I2CDevInit(&(sil->d)))
-  {
-    goto out;
-  }
-
-  return sil;
-  
- out:
-  xfree(sil);
-  return NULL;
+out:
+    xfree(sil);
+    return NULL;
 }
 
 
-static Bool sil164Init(I2CDevPtr d)
+static Bool
+sil164Init(I2CDevPtr d)
 {
-  SIL164Ptr sil = SILPTR(d);
+    SIL164Ptr sil = SILPTR(d);
 
-  /* not much to do */
-  return TRUE;
+    /* not much to do */
+    return TRUE;
 }
 
-static ModeStatus sil164ModeValid(I2CDevPtr d, DisplayModePtr mode)
+static ModeStatus
+sil164ModeValid(I2CDevPtr d, DisplayModePtr mode)
 {
-  SIL164Ptr sil = SILPTR(d);
-  
-  return MODE_OK;
+    SIL164Ptr sil = SILPTR(d);
+
+    return MODE_OK;
 }
 
-static void sil164Mode(I2CDevPtr d, DisplayModePtr mode)
+static void
+sil164Mode(I2CDevPtr d, DisplayModePtr mode)
 {
-  SIL164Ptr sil = SILPTR(d);
+    SIL164Ptr sil = SILPTR(d);
 
-  /* don't do much */
-  return;
+    /* don't do much */
+    return;
 }
 
 /* set the SIL164 power state */
-static void sil164Power(I2CDevPtr d, Bool On)
+static void
+sil164Power(I2CDevPtr d, Bool On)
 {
-  SIL164Ptr sil = SILPTR(d);
-  int ret;
-  unsigned char ch;
-  
-  ret = sil164ReadByte(sil, SIL164_REG8, &ch);
-  if (ret == FALSE)
-    return;
+    SIL164Ptr sil = SILPTR(d);
+    int ret;
+    unsigned char ch;
+
+    ret = sil164ReadByte(sil, SIL164_REG8, &ch);
+    if (ret == FALSE)
+	return;
+
+    if (On)
+	ch |= SIL164_8_PD;
+    else
+	ch &= ~SIL164_8_PD;
 
-  if (On)
-    ch |= SIL164_8_PD;
-  else
-    ch &= ~SIL164_8_PD;
+    sil164WriteByte(sil, SIL164_REG8, ch);
 
-  sil164WriteByte(sil, SIL164_REG8, ch);
-  return;
+    return;
 }
 
-static void sil164PrintRegs(I2CDevPtr d)
+static void
+sil164PrintRegs(I2CDevPtr d)
 {
-  SIL164Ptr sil = SILPTR(d);
+    SIL164Ptr sil = SILPTR(d);
 }
 
-static void sil164SaveRegs(I2CDevPtr d)
+static void
+sil164SaveRegs(I2CDevPtr d)
 {
-  SIL164Ptr sil = SILPTR(d);
-  
-  if (!sil164ReadByte(sil, SIL164_FREQ_LO, &sil->SavedReg.freq_lo))
-      return;
+    SIL164Ptr sil = SILPTR(d);
 
-  if (!sil164ReadByte(sil, SIL164_FREQ_HI, &sil->SavedReg.freq_hi))
-      return;
+    if (!sil164ReadByte(sil, SIL164_FREQ_LO, &sil->SavedReg.freq_lo))
+	return;
 
-  if (!sil164ReadByte(sil, SIL164_REG8, &sil->SavedReg.reg8))
-    return;
-  
-  if (!sil164ReadByte(sil, SIL164_REG9, &sil->SavedReg.reg9))
-    return;
+    if (!sil164ReadByte(sil, SIL164_FREQ_HI, &sil->SavedReg.freq_hi))
+	return;
 
-  if (!sil164ReadByte(sil, SIL164_REGC, &sil->SavedReg.regc))
-    return;
-  
-  return;
+    if (!sil164ReadByte(sil, SIL164_REG8, &sil->SavedReg.reg8))
+	return;
+
+    if (!sil164ReadByte(sil, SIL164_REG9, &sil->SavedReg.reg9))
+	return;
 
+    if (!sil164ReadByte(sil, SIL164_REGC, &sil->SavedReg.regc))
+	return;
+
+    return;
 }
 
 I830I2CVidOutputRec SIL164VidOutput = {
-  sil164Detect,
-  sil164Init,
-  sil164ModeValid,
-  sil164Mode,
-  sil164Power,
-  sil164PrintRegs,
-  sil164SaveRegs,
-  NULL,
+    sil164Detect,
+    sil164Init,
+    sil164ModeValid,
+    sil164Mode,
+    sil164Power,
+    sil164PrintRegs,
+    sil164SaveRegs,
+    NULL,
 };
diff --git a/src/sil164/sil164_module.c b/src/sil164/sil164_module.c
index 6778e6a..d3bda81 100644
--- a/src/sil164/sil164_module.c
+++ b/src/sil164/sil164_module.c
@@ -1,3 +1,5 @@
+/* -*- c-basic-offset: 4 -*- */
+
 #ifdef HAVE_XORG_CONFIG_H
 #include <xorg-config.h>
 #endif
@@ -10,8 +12,7 @@
 
 static MODULESETUPPROTO(sil164Setup);
 
-static XF86ModuleVersionInfo sil164VersRec = 
-  {
+static XF86ModuleVersionInfo sil164VersRec = {
     "sil164",
     MODULEVENDORSTRING,
     MODINFOSTRING1,
@@ -22,15 +23,16 @@ static XF86ModuleVersionInfo sil164VersR
     ABI_VIDEODRV_VERSION,
     MOD_CLASS_NONE,
     { 0,0,0,0 }
-  };
+};
 
 _X_EXPORT XF86ModuleData sil164ModuleData = {
-  &sil164VersRec,
-  sil164Setup,
-  NULL
+    &sil164VersRec,
+    sil164Setup,
+    NULL
 };
 
 static pointer
-sil164Setup(pointer module, pointer opts, int *errmaj, int *errmin) {
-  return (pointer)1;
+sil164Setup(pointer module, pointer opts, int *errmaj, int *errmin)
+{
+    return (pointer)1;
 }
diff --git a/src/sil164/sil164_reg.h b/src/sil164/sil164_reg.h
index 879363c..dc2abba 100644
--- a/src/sil164/sil164_reg.h
+++ b/src/sil164/sil164_reg.h
@@ -1,3 +1,4 @@
+/* -*- c-basic-offset: 4 -*- */
 /**************************************************************************
 
  Copyright 2006 Dave Airlie <airlied at linux.ie>
@@ -57,17 +58,17 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define SIL164_REGC 0x0c
 
 typedef struct _Sil164SaveRec {
-  CARD8 freq_lo;
-  CARD8 freq_hi;
-  CARD8 reg8;
-  CARD8 reg9;
-  CARD8 regc;
+    CARD8 freq_lo;
+    CARD8 freq_hi;
+    CARD8 reg8;
+    CARD8 reg9;
+    CARD8 regc;
 } SIL164SaveRec;
 
 typedef struct {
-  I2CDevRec d;
-  SIL164SaveRec SavedReg;
-  SIL164SaveRec ModeReg;
+    I2CDevRec d;
+    SIL164SaveRec SavedReg;
+    SIL164SaveRec ModeReg;
 } SIL164Rec, *SIL164Ptr;
 
 #define SILPTR(d) ((SIL164Ptr)(d->DriverPrivate.ptr))
diff-tree f5a01a2ef02125611d5fb74c20d53d52e544701a (from 23a0ee73bce12f9e0b881af420413aeec4c0517f)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Jul 10 17:17:51 2006 -0700

    Make DVO code light up my sil164-based DVI output, when already set up by BIOS.

diff --git a/src/i830_display.c b/src/i830_display.c
index b26c09f..7b96b3a 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -482,8 +482,9 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	dpll |= DPLL_DVO_HIGH_SPEED;
 
 	/* Save the data order, since I don't know what it should be set to. */
-	dvo = INREG(DVOB) & (DVO_PRESERVE_MASK | DVO_DATA_ORDER_GBRG);
-	dvo |= DVO_DATA_ORDER_FP | DVO_BORDER_ENABLE;
+	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 (pipe == 1)
 	    dvo |= DVO_PIPE_B_SELECT;
@@ -493,10 +494,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	if (pMode->Flags & V_PVSYNC)
 	    dvo |= DVO_VSYNC_ACTIVE_HIGH;
 
-	if (IS_I865G(pI830))
-	    dvo |= DVO_OUTPUT_SOURCE_SIZE_PIXELS;
-
-	OUTREG(DVOB, dvo & ~DVO_ENABLE);
+	OUTREG(DVOC, dvo & ~DVO_ENABLE);
     }
 
     if (is_sdvo) {
@@ -683,12 +681,12 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	OUTREG(ADPA, adpa);
 
     if (is_dvo) {
-	OUTREG(DVOB_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
+	/*OUTREG(DVOB_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
+	    (pMode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));*/
+	OUTREG(DVOC_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
 	    (pMode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));
-	/* OUTREG(DVOC_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
-	    (pMode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT)); */
-	OUTREG(DVOB, dvo);
-	/* OUTREG(DVOC, dvoc); */
+	/*OUTREG(DVOB, dvo);*/
+	OUTREG(DVOC, dvo);
     }
 
     if (is_sdvo) {
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 0f472b1..7815c57 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1087,18 +1087,12 @@ I830SetupOutputBusses(ScrnInfoPtr pScrn)
       I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOD, "DVODDC_D");
       I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "DVOI2C_E");
 
-      /* if we are on an i2C bus > 0 and we see a monitor - try to
-       * find a controller chip
-       */
-      if (pI830->output[i].MonInfo) {
-	int ret;
-	ret = I830I2CDetectDVOControllers(pScrn, pI830->output[i].pI2CBus,
-					  &pI830->output[i].i2c_drv);
-	if (ret==TRUE) {
-	  xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08lX\n",
-		     pI830->output[i].i2c_drv->modulename,
-		     pI830->output[i].pI2CBus->DriverPrivate.uval);
-	}
+      ret = I830I2CDetectDVOControllers(pScrn, pI830->output[i].pI2CBus,
+					&pI830->output[i].i2c_drv);
+      if (ret == TRUE) {
+	 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08lX\n",
+		    pI830->output[i].i2c_drv->modulename,
+		    pI830->output[i].pI2CBus->DriverPrivate.uval);
       }
 
       i++;
diff --git a/src/i830_modes.c b/src/i830_modes.c
index e1d8570..1a572d1 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -729,6 +729,11 @@ I830ReprobePipeModeList(ScrnInfoPtr pScr
 		output_index = i;
 	    }
 	    break;
+	case I830_OUTPUT_DVO:
+	    if (outputs & PIPE_DFP && pI830->output[i].i2c_drv != NULL) {
+		output_index = i;
+	    }
+	    break;
 	case I830_OUTPUT_SDVO:
 	    if (outputs & PIPE_DFP &&
 		pI830->output[i].sdvo_drv != NULL)
diff-tree 23a0ee73bce12f9e0b881af420413aeec4c0517f (from 48ba9273ddfb36d3525e19238b94b18c56667c4d)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Jul 10 17:16:18 2006 -0700

    Fix modelist with a configured monitor to not begin with all unvalidated modes.

diff --git a/src/i830_modes.c b/src/i830_modes.c
index bb097b8..e1d8570 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -1,3 +1,4 @@
+
 #define DEBUG_VERB 2
 /*
  * Copyright © 2002 David Dawes
@@ -659,7 +660,6 @@ static MonPtr
 i830GetConfiguredMonitor(ScrnInfoPtr pScrn)
 {
     MonPtr mon;
-    DisplayModePtr userModes;
 
     mon = xnfcalloc(1, sizeof(*mon));
     memcpy(mon, pScrn->monitor, sizeof(*mon));
@@ -671,15 +671,12 @@ i830GetConfiguredMonitor(ScrnInfoPtr pSc
     if (pScrn->monitor->model != NULL)
 	mon->model = xnfstrdup(pScrn->monitor->model);
 
-    /* Add in VESA standard and user modelines, and do additional validation
+    /* Use VESA standard and user modelines, and do additional validation
      * on them beyond what pipe config will do (x/y/pitch, clocks, flags)
      */
-    userModes = i830DuplicateModes(pScrn, pScrn->monitor->Modes);
-    i830xf86ValidateModesSync(pScrn, userModes, mon);
-    i830xf86PruneInvalidModes(pScrn, &userModes, FALSE);
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "prune 1\n");
-    i830AppendModes(pScrn, &mon->Modes, userModes);
-
+    mon->Modes = i830DuplicateModes(pScrn, pScrn->monitor->Modes);
+    i830xf86ValidateModesSync(pScrn, mon->Modes, mon);
+    i830xf86PruneInvalidModes(pScrn, &mon->Modes, TRUE);
     mon->Last = i830GetModeListTail(mon->Modes);
 
     return mon;
diff-tree 48ba9273ddfb36d3525e19238b94b18c56667c4d (from 3924ffb7d7b71cb9c6ab9eeb12d0f1b2c26244c0)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Jul 10 15:01:51 2006 -0700

    Fix validation when the first mode is thrown out, and print hsync in modelines.

diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c
index 09f6b34..4c5de4d 100644
--- a/src/i830_xf86Modes.c
+++ b/src/i830_xf86Modes.c
@@ -249,11 +249,12 @@ PrintModeline(int scrnIndex,DisplayModeP
     if (mode->Flags & V_CLKDIV2) add(&flags, "vclk/2");
 #endif
     xf86DrvMsg(scrnIndex, X_ERROR,
-		   "Modeline \"%s\"x%.01f  %6.2f  %i %i %i %i  %i %i %i %i%s\n",
+		   "Modeline \"%s\"x%.01f  %6.2f  %i %i %i %i  %i %i %i %i%s "
+		   "(%.01f kHz)\n",
 		   mode->name, mode->VRefresh, mode->Clock/1000., mode->HDisplay,
 		   mode->HSyncStart, mode->HSyncEnd, mode->HTotal,
 		   mode->VDisplay, mode->VSyncStart, mode->VSyncEnd,
-		   mode->VTotal, flags);
+		   mode->VTotal, flags, i830xf86ModeHSync(mode));
     xfree(flags);
 }
 
@@ -400,7 +401,7 @@ i830xf86PruneInvalidModes(ScrnInfoPtr pS
     DisplayModePtr mode;
 
     for (mode = *modeList; mode != NULL;) {
-	DisplayModePtr next = mode->next;
+	DisplayModePtr next = mode->next, first = *modeList;
 
 	if (mode->status != MODE_OK) {
 	    if (verbose) {
@@ -416,7 +417,7 @@ i830xf86PruneInvalidModes(ScrnInfoPtr pS
 	    xf86DeleteMode(modeList, mode);
 	}
 
-	if (next == *modeList)
+	if (next == first)
 	    break;
 	mode = next;
     }
diff-tree 3924ffb7d7b71cb9c6ab9eeb12d0f1b2c26244c0 (from parents)
Merge: 5a8f6a486d79f50d2d659e615283289d59f9caa4 f76f94a743505da16e121992eb789c1f74eb7673
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Jul 10 12:12:38 2006 -0700

    Merge branch 'dvo-merge' into modesetting
    
    Conflicts:
    
    	src/i830_driver.c

diff --cc src/i830_driver.c
index 5615f4b,501580d..0f472b1
@@@ -1080,12 -1104,7 +1081,27 @@@
        pI830->output[i].pI2CBus = pI830->output[i-1].pI2CBus;
        I830SDVOInit(pScrn, i, SDVOC);
        i++;
 -      break;
 +   } else {
 +      /* set up DVO */
 +      pI830->output[i].type = I830_OUTPUT_DVO;
 +      I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOD, "DVODDC_D");
 +      I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "DVOI2C_E");
++
++      /* if we are on an i2C bus > 0 and we see a monitor - try to
++       * find a controller chip
++       */
++      if (pI830->output[i].MonInfo) {
++	int ret;
++	ret = I830I2CDetectDVOControllers(pScrn, pI830->output[i].pI2CBus,
++					  &pI830->output[i].i2c_drv);
++	if (ret==TRUE) {
++	  xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08lX\n",
++		     pI830->output[i].i2c_drv->modulename,
++		     pI830->output[i].pI2CBus->DriverPrivate.uval);
++	}
++      }
++
 +      i++;
     }
     pI830->num_outputs = i;
  }
diff-tree f76f94a743505da16e121992eb789c1f74eb7673 (from df333cc9a848bc2299a52a7613fe4ffdff8038a2)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Jul 10 12:04:09 2006 -0700

    Supply proper NULL-terminated symbol lists to avoid crashing.

diff --git a/src/ch7xxx/ch7xxx.h b/src/ch7xxx/ch7xxx.h
index 5ae0ab8..679c531 100644
--- a/src/ch7xxx/ch7xxx.h
+++ b/src/ch7xxx/ch7xxx.h
@@ -28,6 +28,4 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #define CH7xxx_ADDR_1 0x76
 
-#define CH7xxx_SYMBOL_LIST "CH7xxxVidOutput"
-
 #endif
diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index b82eaee..242e3dd 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -35,10 +35,12 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "ch7xxx/ch7xxx.h"
 
 static const char *SIL164Symbols[] = {
-    SIL164_SYMBOL_LIST
+    "Sil164VidOutput",
+    NULL
 };
 static const char *CH7xxxSymbols[] = {
-    CH7xxx_SYMBOL_LIST
+    "CH7xxxVidOutput",
+    NULL
 };
 
 /* driver list */
diff --git a/src/sil164/sil164.h b/src/sil164/sil164.h
index ea5c4c9..9f823d6 100644
--- a/src/sil164/sil164.h
+++ b/src/sil164/sil164.h
@@ -28,6 +28,4 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #define SIL164_ADDR_1 0x38
 
-#define SIL164_SYMBOL_LIST "SIL164VidOutput"
-
 #endif
diff-tree 5a8f6a486d79f50d2d659e615283289d59f9caa4 (from e1064f52b0ff69ea7937897b8c951cc3e32cd752)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Sat Jul 8 15:26:19 2006 -0700

    Improve output bus setup to include LVDS setup for pre-i915.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index ca87951..5615f4b 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1061,30 +1061,14 @@ I830SetupOutputBusses(ScrnInfoPtr pScrn)
    I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOA, "CRTDDC_A");
    i++;
 
-   /* need to add the output busses for each device 
-    * - this function is very incomplete
-    * - i915GM has LVDS and TVOUT for example
-    */
-   switch(pI830->PciInfo->chipType) {
-   case PCI_CHIP_I830_M:
-   case PCI_CHIP_845_G:
-   case PCI_CHIP_I855_GM:
-   case PCI_CHIP_I865_G:
-      pI830->output[i].type = I830_OUTPUT_DVO;
-      I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOD, "DVODDC_D");
-      I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "DVOI2C_E");
-      i++;
-      break;
-   case PCI_CHIP_E7221_G:
-      /* ??? */
-      break;
-   case PCI_CHIP_I915_GM:
-   case PCI_CHIP_I945_GM:
+   if (IS_MOBILE(pI830) && !IS_I830(pI830)) {
+      /* Set up integrated LVDS */
       pI830->output[i].type = I830_OUTPUT_LVDS;
       I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOC, "LVDSDDC_C");
       i++;
-   case PCI_CHIP_I915_G:
-   case PCI_CHIP_I945_G:
+   }
+
+   if (IS_I9XX(pI830)) {
       /* Set up SDVOB */
       pI830->output[i].type = I830_OUTPUT_SDVO;
       I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "SDVOCTRL_E");
@@ -1096,7 +1080,12 @@ I830SetupOutputBusses(ScrnInfoPtr pScrn)
       pI830->output[i].pI2CBus = pI830->output[i-1].pI2CBus;
       I830SDVOInit(pScrn, i, SDVOC);
       i++;
-      break;
+   } else {
+      /* set up DVO */
+      pI830->output[i].type = I830_OUTPUT_DVO;
+      I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOD, "DVODDC_D");
+      I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "DVOI2C_E");
+      i++;
    }
    pI830->num_outputs = i;
 }
diff-tree df333cc9a848bc2299a52a7613fe4ffdff8038a2 (from e1064f52b0ff69ea7937897b8c951cc3e32cd752)
Author: Eric Anholt <anholt at leguin.anholt.net>
Date:   Fri Jul 7 13:41:33 2006 -0700

    Initial add of DVO support code.  Probes my sil164.
    
    This is a mostly-untested merge of airlied's work.  The I2C modules are intended
    to be moved into the core server or a separate driver module when they're
    functional and we're happy with the API.

diff --git a/configure.ac b/configure.ac
index deb99c2..5c9291b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -125,5 +125,7 @@ AC_OUTPUT([
 	src/Makefile
 	src/xvmc/Makefile
 	src/bios_reader/Makefile
+	src/ch7xxx/Makefile
+	src/sil164/Makefile
 	man/Makefile
 ])
diff --git a/src/Makefile.am b/src/Makefile.am
index f8aaad1..50d0ad1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -18,7 +18,7 @@
 #  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 #  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
-SUBDIRS = xvmc bios_reader
+SUBDIRS = xvmc bios_reader ch7xxx sil164
 # this is obnoxious:
 # -module lets us name the module exactly how we want
 # -avoid-version prevents gratuitous .0.0.0 version numbers on the end
@@ -54,6 +54,7 @@ i810_drv_la_SOURCES = \
 	 i830_display.c \
 	 i830_display.h \
          i830_driver.c \
+	 i830_dvo.c \
          i830.h \
          i830_gtf.c \
          i830_i2c.c \
diff --git a/src/ch7xxx/Makefile.am b/src/ch7xxx/Makefile.am
new file mode 100644
index 0000000..645ac69
--- /dev/null
+++ b/src/ch7xxx/Makefile.am
@@ -0,0 +1,16 @@
+# this is obnoxious:
+# -module lets us name the module exactly how we want
+# -avoid-version prevents gratuitous .0.0.0 version numbers on the end
+# _ladir passes a dummy rpath to libtool so the thing will actually link
+# TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
+AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@
+
+ch7xxx_la_LTLIBRARIES = ch7xxx.la
+ch7xxx_la_LDFLAGS = -module -avoid-version
+ch7xxx_ladir = @moduledir@/drivers
+
+ch7xxx_la_SOURCES = \
+	ch7xxx.c \
+	ch7xxx_module.c \
+	ch7xxx.h \
+	ch7xxx_reg.h
diff --git a/src/ch7xxx/ch7xxx.c b/src/ch7xxx/ch7xxx.c
new file mode 100644
index 0000000..77c49b5
--- /dev/null
+++ b/src/ch7xxx/ch7xxx.c
@@ -0,0 +1,272 @@
+/**************************************************************************
+
+Copyright © 2006 Dave Airlie
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86Resources.h"
+#include "compiler.h"
+#include "miscstruct.h"
+#include "xf86i2c.h"
+
+#include <string.h>
+
+#include "../i2c_vid.h"
+#include "ch7xxx.h"
+#include "ch7xxx_reg.h"
+
+static void ch7xxxSaveRegs(void *d);
+
+static CARD8 ch7xxxFreqRegs[][7] =
+  { { 0, 0x23, 0x08, 0x16, 0x30, 0x60, 0x00 },
+    { 0, 0x23, 0x04, 0x26, 0x30, 0x60, 0x00 },
+    { 0, 0x2D, 0x07, 0x26, 0x30, 0xE0, 0x00 } };
+
+
+static Bool ch7xxxReadByte(CH7xxxPtr ch7xxx, int addr, unsigned char *ch)
+{
+  if (!xf86I2CReadByte(&(ch7xxx->d), addr, ch)) {
+    xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "Unable to read from %s Slave %d.\n", ch7xxx->d.pI2CBus->BusName, ch7xxx->d.SlaveAddr);
+    return FALSE;
+  }
+  return TRUE;
+}
+
+static Bool ch7xxxWriteByte(CH7xxxPtr ch7xxx, int addr, unsigned char ch)
+{
+  if (!xf86I2CWriteByte(&(ch7xxx->d), addr, ch)) {
+    xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "Unable to write to %s Slave %d.\n", ch7xxx->d.pI2CBus->BusName, ch7xxx->d.SlaveAddr);
+    return FALSE;
+  }
+  return TRUE;
+}
+
+/* Ch7xxxicon Image 164 driver for chip on i2c bus */
+static void *ch7xxxDetect(I2CBusPtr b, I2CSlaveAddr addr)
+{
+  /* this will detect the CH7xxx chip on the specified i2c bus */
+  CH7xxxPtr ch7xxx;
+  unsigned char ch;
+
+  xf86DrvMsg(b->scrnIndex, X_ERROR, "detecting ch7xxx\n");
+  
+  ch7xxx = xcalloc(1, sizeof(CH7xxxRec));
+  if (ch7xxx == NULL)
+    return NULL;
+
+  ch7xxx->d.DevName = "CH7xxx TMDS Controller";
+  ch7xxx->d.SlaveAddr = addr;
+  ch7xxx->d.pI2CBus = b;
+  ch7xxx->d.StartTimeout = b->StartTimeout;
+  ch7xxx->d.BitTimeout = b->BitTimeout;
+  ch7xxx->d.AcknTimeout = b->AcknTimeout;
+  ch7xxx->d.ByteTimeout = b->ByteTimeout;
+  ch7xxx->d.DriverPrivate.ptr = ch7xxx;
+
+  if (!ch7xxxReadByte(ch7xxx, CH7xxx_REG_VID, &ch))
+    goto out;
+
+  ErrorF("VID is %02X", ch);
+  if (ch!=(CH7xxx_VID & 0xFF))
+  {
+    xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "ch7xxx not detected got %d: from %s Slave %d.\n", ch, ch7xxx->d.pI2CBus->BusName, ch7xxx->d.SlaveAddr);
+    goto out;
+  }
+
+
+  if (!ch7xxxReadByte(ch7xxx, CH7xxx_REG_DID, &ch))
+    goto out;
+
+  ErrorF("DID is %02X", ch);
+  if (ch!=(CH7xxx_DID & 0xFF))
+  {
+    xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "ch7xxx not detected got %d: from %s Slave %d.\n", ch, ch7xxx->d.pI2CBus->BusName, ch7xxx->d.SlaveAddr);
+    goto out;
+  }
+
+
+  if (!xf86I2CDevInit(&(ch7xxx->d)))
+  {
+    goto out;
+  }
+
+  return ch7xxx;
+  
+ out:
+  xfree(ch7xxx);
+  return NULL;
+}
+
+
+static Bool ch7xxxInit(I2CDevPtr d)
+{
+  CH7xxxPtr ch7xxx = CH7PTR(d);
+
+  /* not much to do */
+  return TRUE;
+}
+
+static ModeStatus ch7xxxModeValid(I2CDevPtr d, DisplayModePtr mode)
+{
+  CH7xxxPtr ch7xxx = CH7PTR(d);
+  
+  return MODE_OK;
+}
+
+static void ch7xxxMode(I2CDevPtr d, DisplayModePtr mode)
+{
+  CH7xxxPtr ch7xxx = CH7PTR(d);
+  int ret;
+  unsigned char pm, idf;
+  unsigned char tpcp, tpd, tpf, cm;
+  CARD8 *freq_regs;
+  int i;
+  ErrorF("Clock is %d\n", mode->Clock);
+
+  if (mode->Clock < 75000)
+    freq_regs = ch7xxxFreqRegs[0];
+  else if (mode->Clock < 125000)
+    freq_regs = ch7xxxFreqRegs[1];
+  else
+    freq_regs = ch7xxxFreqRegs[2];
+
+  for (i = 0x31; i < 0x37; i++) {
+    ch7xxx->ModeReg.regs[i] = freq_regs[i - 0x31];
+    ch7xxxWriteByte(ch7xxx, i, ch7xxx->ModeReg.regs[i]);
+  }
+    
+#if 0
+
+  xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "ch7xxx idf is 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", idf, tpcp, tpd, tpf);
+
+  xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "ch7xxx pm is %02X\n", pm);
+
+  if (mode->Clock < 65000) {
+    tpcp = 0x08;
+    tpd = 0x16;
+    tpf = 0x60;
+  } else {
+    tpcp = 0x06;
+    tpd = 0x26;
+    tpf = 0xa0;
+  }
+
+  idf &= ~(CH7xxx_IDF_HSP | CH7xxx_IDF_VSP);
+  if (mode->Flags & V_PHSYNC)
+    idf |= CH7xxx_IDF_HSP;
+
+  if (mode->Flags & V_PVSYNC)
+    idf |= CH7xxx_IDF_HSP;
+  
+  /* setup PM Registers */
+  pm &= ~CH7xxx_PM_FPD;
+  pm |= CH7xxx_PM_DVIL | CH7xxx_PM_DVIP;
+
+  //  cm |= 1;
+
+  ch7xxxWriteByte(ch7xxx, CH7xxx_CM, cm);
+  ch7xxxWriteByte(ch7xxx, CH7xxx_TPCP, tpcp);
+  ch7xxxWriteByte(ch7xxx, CH7xxx_TPD, tpd);
+  ch7xxxWriteByte(ch7xxx, CH7xxx_TPF, tpf);
+  ch7xxxWriteByte(ch7xxx, CH7xxx_TPF, idf);
+  ch7xxxWriteByte(ch7xxx, CH7xxx_PM, pm);
+
+#endif
+  /* don't do much */
+  return;
+}
+
+/* set the CH7xxx power state */
+static void ch7xxxPower(I2CDevPtr d, Bool On)
+{
+  CH7xxxPtr ch7xxx = CH7PTR(d);
+  int ret;
+  unsigned char ch;
+
+
+  ret = ch7xxxReadByte(ch7xxx, CH7xxx_PM, &ch);
+  if (ret == FALSE)
+    return;
+  
+  xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "ch7xxx pm is %02X\n", ch);
+  
+#if 0  
+  ret = ch7xxxReadByte(ch7xxx, CH7xxx_REG8, &ch);
+  if (ret)
+    return;
+
+  if (On)
+    ch |= CH7xxx_8_PD;
+  else
+    ch &= ~CH7xxx_8_PD;
+
+  ch7xxxWriteByte(ch7xxx, CH7xxx_REG8, ch);
+#endif
+  return;
+}
+
+static void ch7xxxPrintRegs(I2CDevPtr d)
+{
+  CH7xxxPtr ch7xxx = CH7PTR(d);
+  int i;
+
+  ch7xxxSaveRegs(d);
+
+  for (i = 0; i < CH7xxx_NUM_REGS; i++) {
+    if (( i % 8 ) == 0 )
+      ErrorF("\n %02X: ", i);
+    ErrorF("%02X ", ch7xxx->ModeReg.regs[i]);
+
+  }
+}
+
+static void ch7xxxSaveRegs(void *d)
+{
+  CH7xxxPtr ch7xxx = CH7PTR(((I2CDevPtr)d));
+  int ret;
+  int i;
+
+  for (i = 0; i < CH7xxx_NUM_REGS; i++) {
+    ret = ch7xxxReadByte(ch7xxx, i, &ch7xxx->SavedReg.regs[i]);
+    if (ret == FALSE)
+      break;
+  }
+
+  memcpy(ch7xxx->ModeReg.regs, ch7xxx->SavedReg.regs, CH7xxx_NUM_REGS);
+
+  return;
+}
+
+I830I2CVidOutputRec CH7xxxVidOutput = {
+  ch7xxxDetect,
+  ch7xxxInit,
+  ch7xxxModeValid,
+  ch7xxxMode,
+  ch7xxxPower,
+  ch7xxxPrintRegs,
+  ch7xxxSaveRegs,
+  NULL,
+};
diff --git a/src/ch7xxx/ch7xxx.h b/src/ch7xxx/ch7xxx.h
new file mode 100644
index 0000000..5ae0ab8
--- /dev/null
+++ b/src/ch7xxx/ch7xxx.h
@@ -0,0 +1,33 @@
+/**************************************************************************
+
+ Copyright 2006 Dave Airlie <airlied at linux.ie>
+ 
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifndef CH7xxx_H
+#define CH7xxx_H
+
+#define CH7xxx_ADDR_1 0x76
+
+#define CH7xxx_SYMBOL_LIST "CH7xxxVidOutput"
+
+#endif
diff --git a/src/ch7xxx/ch7xxx_module.c b/src/ch7xxx/ch7xxx_module.c
new file mode 100644
index 0000000..19dc6cd
--- /dev/null
+++ b/src/ch7xxx/ch7xxx_module.c
@@ -0,0 +1,36 @@
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86Module.h"
+
+static MODULESETUPPROTO(ch7xxxSetup);
+
+static XF86ModuleVersionInfo ch7xxxVersRec = 
+  {
+    "ch7xxx",
+    MODULEVENDORSTRING,
+    MODINFOSTRING1,
+    MODINFOSTRING2,
+    XORG_VERSION_CURRENT,
+    1, 0, 0,
+    ABI_CLASS_VIDEODRV,
+    ABI_VIDEODRV_VERSION,
+    MOD_CLASS_NONE,
+    { 0,0,0,0 }
+  };
+
+_X_EXPORT XF86ModuleData ch7xxxModuleData = {
+  &ch7xxxVersRec,
+  ch7xxxSetup,
+  NULL
+};
+
+static pointer
+ch7xxxSetup(pointer module, pointer opts, int *errmaj, int *errmin) {
+  return (pointer)1;
+}
diff --git a/src/ch7xxx/ch7xxx_reg.h b/src/ch7xxx/ch7xxx_reg.h
new file mode 100644
index 0000000..59de13b
--- /dev/null
+++ b/src/ch7xxx/ch7xxx_reg.h
@@ -0,0 +1,91 @@
+/**************************************************************************
+
+ Copyright 2006 Dave Airlie <airlied at linux.ie>
+ 
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifndef CH7xxx_REG_H
+#define CH7xxx_REG_H
+
+#define CH7xxx_REG_VID 0x4a
+#define CH7xxx_REG_DID 0x4b
+
+
+#define CH7011_VID 0x83
+#define CH7009A_VID 0x84
+#define CH7009B_VID 0x85
+#define CH7301_VID 0x95
+
+#define CH7xxx_VID 0x84
+#define CH7xxx_DID 0x17
+
+#define CH7xxx_NUM_REGS 0x4c
+
+typedef struct _CH7xxxSaveRec {
+  CARD8 regs[CH7xxx_NUM_REGS];
+} CH7xxxSaveRec;
+
+typedef struct {
+  I2CDevRec d;
+  CH7xxxSaveRec SavedReg;
+  CH7xxxSaveRec ModeReg;
+} CH7xxxRec, *CH7xxxPtr;
+
+#define CH7PTR(d) ((CH7xxxPtr)(d->DriverPrivate.ptr))
+
+#define CH7xxx_CM 0x1C
+#define CH7xxx_CM_XCM (1<<0)
+#define CH7xxx_CM_MCP (1<<2)
+#define CH7xxx_INPUT_CLOCK 0x1D
+#define CH7xxx_GPIO 0x1E
+#define CH7xxx_IDF 0x1F
+
+#define CH7xxx_IDF_HSP (1<<3)
+#define CH7xxx_IDF_VSP (1<<4)
+
+#define CH7301_CONNECTION_DETECT 0x20
+#define CH7301_DAC_CNTL 0x21
+#define CH7301_HOTPLUG 0x23
+#define CH7xxx_TCTL 0x31
+#define CH7xxx_TPCP 0x33
+#define CH7xxx_TPD 0x34
+#define CH7xxx_TPVT 0x35
+#define CH7xxx_TPF 0x36
+#define CH7301_TCT 0x37
+#define CH7301_TEST_PATTERN 0x48
+#define CH7xxx_PM 0x49
+
+#define CH7xxx_PM_FPD (1<<0)
+#define CH7301_PM_DACPD0 (1<<1)
+#define CH7301_PM_DACPD1 (1<<2)
+#define CH7301_PM_DACPD2 (1<<3)
+#define CH7xxx_PM_DVIL (1<<6)
+#define CH7xxx_PM_DVIP (1<<7)
+
+#define CH7301_SYNC_POLARITY 0x56
+
+#define CH7301_SYNC_RGB_YUV (1<<0)
+#define CH7301_SYNC_POL_DVI (1<<5)
+
+
+
+#endif
diff --git a/src/i2c_vid.h b/src/i2c_vid.h
new file mode 100644
index 0000000..fbf7284
--- /dev/null
+++ b/src/i2c_vid.h
@@ -0,0 +1,16 @@
+/* this needs to go in the server */
+#ifndef I2C_VID_H
+#define I2C_VID_H
+
+typedef struct _I830I2CVidOutputRec {
+  void *(*Detect)(I2CBusPtr b, I2CSlaveAddr addr);
+  Bool (*Init)(I2CDevPtr d);
+  ModeStatus (*ModeValid)(I2CDevPtr d, DisplayModePtr mode);
+  void (*Mode)(I2CDevPtr d, DisplayModePtr mode);
+  void (*Power)(I2CDevPtr d, Bool On);
+  void (*PrintRegs)(I2CDevPtr d);
+  void (*SaveRegs)(void *d);
+  void (*RestoreRegs)(I2CDevPtr d);
+} I830I2CVidOutputRec, *I830I2CVidOutputPtr;
+
+#endif
diff --git a/src/i810_reg.h b/src/i810_reg.h
index e8462f9..275d858 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -823,11 +823,35 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define DVOA			0x61120
 #define DVOB			0x61140
 #define DVOC			0x61160
-#define DVO_ENABLE		(1<<31)
+#define DVO_ENABLE			(1 << 31)
+#define DVO_PIPE_B_SELECT		(1 << 30)
+#define DVO_PIPE_STALL_UNUSED		(0 << 28)
+#define DVO_PIPE_STALL			(1 << 28)
+#define DVO_PIPE_STALL_TV		(2 << 28)
+#define DVO_USE_VGA_SYNC		(1 << 15)
+#define DVO_DATA_ORDER_I740		(0 << 14)
+#define DVO_DATA_ORDER_FP		(1 << 14)
+#define DVO_VSYNC_DISABLE		(1 << 11)
+#define DVO_HSYNC_DISABLE		(1 << 10)
+#define DVO_VSYNC_TRISTATE		(1 << 9)
+#define DVO_HSYNC_TRISTATE		(1 << 8)
+#define DVO_BORDER_ENABLE		(1 << 7)
+#define DVO_DATA_ORDER_GBRG		(1 << 6)
+#define DVO_DATA_ORDER_RGGB		(0 << 6)
+#define DVO_DATA_ORDER_GBRG_ERRATA	(0 << 6)
+#define DVO_DATA_ORDER_RGGB_ERRATA	(1 << 6)
+#define DVO_VSYNC_ACTIVE_HIGH		(1 << 4)
+#define DVO_HSYNC_ACTIVE_HIGH		(1 << 3)
+#define DVO_BLANK_ACTIVE_HIGH		(1 << 2)
+#define DVO_OUTPUT_CSTATE_PIXELS	(1 << 1)	/* SDG only */
+#define DVO_OUTPUT_SOURCE_SIZE_PIXELS	(1 << 0)	/* SDG only */
+#define DVO_PRESERVE_MASK	(0x7<<24)
 
 #define DVOA_SRCDIM		0x61124
 #define DVOB_SRCDIM		0x61144
 #define DVOC_SRCDIM		0x61164
+#define DVO_SRCDIM_HORIZONTAL_SHIFT	12
+#define DVO_SRCDIM_VERTICAL_SHIFT	0
 
 #define LVDS			0x61180
 # define LVDS_PORT_EN			(1 << 31)
diff --git a/src/i830.h b/src/i830.h
index f1b9774..1123001 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -70,6 +70,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 #include "common.h"
 #include "i830_sdvo.h"
+#include "i2c_vid.h"
 
 /* I830 Video BIOS support */
 
@@ -182,10 +183,8 @@ struct _I830DVODriver {
    char *fntablename;
    int address;
    const char **symbols;
-#if 0
    I830I2CVidOutputRec *vid_rec;
-#endif
-   void *devpriv;
+   void *dev_priv;
    pointer modhandle;
 };
 
@@ -593,6 +592,10 @@ extern Bool I830FixOffset(ScrnInfoPtr pS
 extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg,
 			char *name);
 
+/* i830_dvo.c */
+Bool I830I2CDetectDVOControllers(ScrnInfoPtr pScrn, I2CBusPtr pI2CBus,
+				 struct _I830DVODriver **retdrv);
+
 /* i830_memory.c */
 Bool I830BindAGPMemory(ScrnInfoPtr pScrn);
 Bool I830UnbindAGPMemory(ScrnInfoPtr pScrn);
diff --git a/src/i830_display.c b/src/i830_display.c
index d31c100..b26c09f 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -258,8 +258,8 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     CARD32 dpll = 0, fp = 0, temp;
     CARD32 htot, hblank, hsync, vtot, vblank, vsync, dspcntr;
     CARD32 pipesrc, dspsize, adpa;
-    CARD32 sdvob = 0, sdvoc= 0;
-    Bool ok, is_sdvo;
+    CARD32 sdvob = 0, sdvoc = 0, dvo = 0;
+    Bool ok, is_sdvo, is_dvo;
     int refclk, pixel_clock, sdvo_pixel_multiply;
     int outputs;
     DisplayModePtr pMasterMode = pMode;
@@ -359,9 +359,16 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	/* We'll change how we control outputs soon, but to get the SDVO code up
 	 * and running, just check for these two possibilities.
 	 */
-	is_sdvo = TRUE;
+	if (IS_I9XX(pI830)) {
+	    is_sdvo = TRUE;
+	    is_dvo = FALSE;
+	} else {
+	    is_dvo = TRUE;
+	    is_sdvo = FALSE;
+	}
     } else {
 	is_sdvo = FALSE;
+	is_dvo = FALSE;
     }
 
     htot = (pMode->CrtcHDisplay - 1) | ((pMode->CrtcHTotal - 1) << 16);
@@ -471,6 +478,27 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     else
 	dpll |= PLL_REF_INPUT_DREFCLK;
 
+    if (is_dvo) {
+	dpll |= DPLL_DVO_HIGH_SPEED;
+
+	/* Save the data order, since I don't know what it should be set to. */
+	dvo = INREG(DVOB) & (DVO_PRESERVE_MASK | DVO_DATA_ORDER_GBRG);
+	dvo |= DVO_DATA_ORDER_FP | DVO_BORDER_ENABLE;
+
+	if (pipe == 1)
+	    dvo |= DVO_PIPE_B_SELECT;
+
+	if (pMode->Flags & V_PHSYNC)
+	    dvo |= DVO_HSYNC_ACTIVE_HIGH;
+	if (pMode->Flags & V_PVSYNC)
+	    dvo |= DVO_VSYNC_ACTIVE_HIGH;
+
+	if (IS_I865G(pI830))
+	    dvo |= DVO_OUTPUT_SOURCE_SIZE_PIXELS;
+
+	OUTREG(DVOB, dvo & ~DVO_ENABLE);
+    }
+
     if (is_sdvo) {
 	dpll |= DPLL_DVO_HIGH_SPEED;
 
@@ -654,6 +682,15 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     if (outputs & PIPE_CRT_ACTIVE)
 	OUTREG(ADPA, adpa);
 
+    if (is_dvo) {
+	OUTREG(DVOB_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
+	    (pMode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));
+	/* OUTREG(DVOC_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
+	    (pMode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT)); */
+	OUTREG(DVOB, dvo);
+	/* OUTREG(DVOC, dvoc); */
+    }
+
     if (is_sdvo) {
 	OUTREG(SDVOB, sdvob);
 	OUTREG(SDVOC, sdvoc);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index ca87951..501580d 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1053,6 +1053,7 @@ I830SetupOutputBusses(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
    int i = 0;
+   Bool ret;
 
    /* everyone has at least a single analog output */
    pI830->output[i].type = I830_OUTPUT_ANALOG;
@@ -1073,6 +1074,13 @@ I830SetupOutputBusses(ScrnInfoPtr pScrn)
       pI830->output[i].type = I830_OUTPUT_DVO;
       I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOD, "DVODDC_D");
       I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "DVOI2C_E");
+      ret = I830I2CDetectDVOControllers(pScrn, pI830->output[i].pI2CBus,
+					&pI830->output[i].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);
+      }
       i++;
       break;
    case PCI_CHIP_E7221_G:
@@ -1158,22 +1166,6 @@ I830DetectMonitors(ScrnInfoPtr pScrn)
 	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC DVO %d, %08lX\n", i,
 		    pI830->output[i].pDDCBus->DriverPrivate.uval);
 	 xf86PrintEDID(pI830->output[i].MonInfo);
-
-#if 0      
-	 /* if we are on an i2C bus > 0 and we see a monitor - try to
-	  * find a controller chip
-	  */
-	 if (pI830->output[i].MonInfo) {
-	    int ret;
-	    ret = I830I2CDetectDVOControllers(pScrn, pI830->output[i].pI2CBus,
-					      &pI830->output[i].i2c_drv);
-	    if (ret==TRUE) {
-	       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08lX\n",
-			  pI830->output[i].i2c_drv->modulename,
-			  pI830->output[i].pI2CBus->DriverPrivate.uval);
-	    }
-	 }
-#endif
       break;
       case I830_OUTPUT_SDVO:
 	 if (pI830->output[i].sdvo_drv != NULL) {
@@ -2769,6 +2761,12 @@ SaveHWState(ScrnInfoPtr pScrn)
    pI830->saveSWF[16] = INREG(SWF32);
 
    for (i = 0; i < pI830->num_outputs; i++) {
+      if (pI830->output[i].type == I830_OUTPUT_DVO &&
+	  pI830->output[i].i2c_drv != NULL)
+      {
+	 pI830->output[i].i2c_drv->vid_rec->SaveRegs(
+	    pI830->output[i].i2c_drv->dev_priv);
+      }
       if (pI830->output[i].type == I830_OUTPUT_SDVO &&
 	  pI830->output[i].sdvo_drv != NULL)
       {
@@ -2888,6 +2886,12 @@ RestoreHWState(ScrnInfoPtr pScrn)
    }
 
    for (i = 0; i < pI830->num_outputs; i++) {
+      if (pI830->output[i].type == I830_OUTPUT_DVO &&
+	  pI830->output[i].i2c_drv != NULL)
+      {
+	 pI830->output[i].i2c_drv->vid_rec->RestoreRegs(
+	    pI830->output[i].i2c_drv->dev_priv);
+      }
       if (pI830->output[i].type == I830_OUTPUT_SDVO &&
 	  pI830->output[i].sdvo_drv != NULL)
       {
diff --git a/src/i830_dvo.c b/src/i830_dvo.c
new file mode 100644
index 0000000..b82eaee
--- /dev/null
+++ b/src/i830_dvo.c
@@ -0,0 +1,84 @@
+/**************************************************************************
+
+Copyright 2006 Dave Airlie <airlied at linux.ie>
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "i830.h"
+
+#include "sil164/sil164.h"
+#include "ch7xxx/ch7xxx.h"
+
+static const char *SIL164Symbols[] = {
+    SIL164_SYMBOL_LIST
+};
+static const char *CH7xxxSymbols[] = {
+    CH7xxx_SYMBOL_LIST
+};
+
+/* driver list */
+struct _I830DVODriver i830_dvo_drivers[] =
+{
+	{ I830_DVO_CHIP_TMDS, "sil164", "SIL164VidOutput",
+		(SIL164_ADDR_1<<1), SIL164Symbols, NULL , NULL, NULL},
+	{ I830_DVO_CHIP_TMDS | I830_DVO_CHIP_TVOUT, "ch7xxx", "CH7xxxVidOutput",
+		(CH7xxx_ADDR_1<<1), CH7xxxSymbols, NULL , NULL, NULL}
+};
+
+#define I830_NUM_DVO_DRIVERS (sizeof(i830_dvo_drivers)/sizeof(struct _I830DVODriver))
+
+Bool
+I830I2CDetectDVOControllers(ScrnInfoPtr pScrn, I2CBusPtr pI2CBus,
+			    struct _I830DVODriver **retdrv)
+{
+    int i;
+    void *ret_ptr;
+    struct _I830DVODriver *drv;
+
+    for (i = 0; i < I830_NUM_DVO_DRIVERS; i++) {
+	drv = &i830_dvo_drivers[i];
+	drv->modhandle = xf86LoadSubModule(pScrn, drv->modulename);
+	if (drv->modhandle == NULL)
+	    continue;
+
+	xf86LoaderReqSymLists(drv->symbols, NULL);
+
+	ret_ptr = NULL;
+	drv->vid_rec = LoaderSymbol(drv->fntablename);
+	if (drv->vid_rec != NULL)
+	    ret_ptr = drv->vid_rec->Detect(pI2CBus, drv->address);
+
+	if (ret_ptr != NULL) {
+	    drv->dev_priv = ret_ptr;
+	    *retdrv = drv;
+	    return TRUE;
+	}
+	xf86UnloadSubModule(drv->modhandle);
+    }
+    return FALSE;
+}
diff --git a/src/sil164/Makefile.am b/src/sil164/Makefile.am
new file mode 100644
index 0000000..bb84d03
--- /dev/null
+++ b/src/sil164/Makefile.am
@@ -0,0 +1,16 @@
+# this is obnoxious:
+# -module lets us name the module exactly how we want
+# -avoid-version prevents gratuitous .0.0.0 version numbers on the end
+# _ladir passes a dummy rpath to libtool so the thing will actually link
+# TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
+AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@
+
+sil164_la_LTLIBRARIES = sil164.la
+sil164_la_LDFLAGS = -module -avoid-version
+sil164_ladir = @moduledir@/drivers
+
+sil164_la_SOURCES = \
+	sil164.c \
+	sil164_module.c \
+	sil164.h \
+	sil164_reg.h
diff --git a/src/sil164/sil164.c b/src/sil164/sil164.c
new file mode 100644
index 0000000..5e35323
--- /dev/null
+++ b/src/sil164/sil164.c
@@ -0,0 +1,192 @@
+/**************************************************************************
+
+Copyright © 2006 Dave Airlie
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86Resources.h"
+#include "compiler.h"
+#include "miscstruct.h"
+#include "xf86i2c.h"
+
+#include "../i2c_vid.h"
+#include "sil164.h"
+#include "sil164_reg.h"
+
+static Bool sil164ReadByte(SIL164Ptr sil, int addr, unsigned char *ch)
+{
+  if (!xf86I2CReadByte(&(sil->d), addr, ch)) {
+    xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, "Unable to read from %s Slave %d.\n", sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
+    return FALSE;
+  }
+  return TRUE;
+}
+
+static Bool sil164WriteByte(SIL164Ptr sil, int addr, unsigned char ch)
+{
+  if (!xf86I2CWriteByte(&(sil->d), addr, ch)) {
+    xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, "Unable to write to %s Slave %d.\n", sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
+    return FALSE;
+  }
+  return TRUE;
+}
+
+/* Silicon Image 164 driver for chip on i2c bus */
+static void *sil164Detect(I2CBusPtr b, I2CSlaveAddr addr)
+{
+  /* this will detect the SIL164 chip on the specified i2c bus */
+  SIL164Ptr sil;
+  unsigned char ch;
+
+  xf86DrvMsg(b->scrnIndex, X_ERROR, "detecting sil164\n");
+  
+  sil = xcalloc(1, sizeof(SIL164Rec));
+  if (sil == NULL)
+    return NULL;
+
+  sil->d.DevName = "SIL164 TMDS Controller";
+  sil->d.SlaveAddr = addr;
+  sil->d.pI2CBus = b;
+  sil->d.StartTimeout = b->StartTimeout;
+  sil->d.BitTimeout = b->BitTimeout;
+  sil->d.AcknTimeout = b->AcknTimeout;
+  sil->d.ByteTimeout = b->ByteTimeout;
+  sil->d.DriverPrivate.ptr = sil;
+
+  if (!sil164ReadByte(sil, SIL164_VID_LO, &ch))
+    goto out;
+
+  if (ch!=(SIL164_VID & 0xFF))
+  {
+    xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, "sil164 not detected got %d: from %s Slave %d.\n", ch, sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
+    goto out;
+  }
+
+
+  if (!sil164ReadByte(sil, SIL164_DID_LO, &ch))
+    goto out;
+
+  if (ch!=(SIL164_DID & 0xFF))
+  {
+    xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, "sil164 not detected got %d: from %s Slave %d.\n", ch, sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
+    goto out;
+  }
+
+
+  if (!xf86I2CDevInit(&(sil->d)))
+  {
+    goto out;
+  }
+
+  return sil;
+  
+ out:
+  xfree(sil);
+  return NULL;
+}
+
+
+static Bool sil164Init(I2CDevPtr d)
+{
+  SIL164Ptr sil = SILPTR(d);
+
+  /* not much to do */
+  return TRUE;
+}
+
+static ModeStatus sil164ModeValid(I2CDevPtr d, DisplayModePtr mode)
+{
+  SIL164Ptr sil = SILPTR(d);
+  
+  return MODE_OK;
+}
+
+static void sil164Mode(I2CDevPtr d, DisplayModePtr mode)
+{
+  SIL164Ptr sil = SILPTR(d);
+
+  /* don't do much */
+  return;
+}
+
+/* set the SIL164 power state */
+static void sil164Power(I2CDevPtr d, Bool On)
+{
+  SIL164Ptr sil = SILPTR(d);
+  int ret;
+  unsigned char ch;
+  
+  ret = sil164ReadByte(sil, SIL164_REG8, &ch);
+  if (ret == FALSE)
+    return;
+
+  if (On)
+    ch |= SIL164_8_PD;
+  else
+    ch &= ~SIL164_8_PD;
+
+  sil164WriteByte(sil, SIL164_REG8, ch);
+  return;
+}
+
+static void sil164PrintRegs(I2CDevPtr d)
+{
+  SIL164Ptr sil = SILPTR(d);
+}
+
+static void sil164SaveRegs(I2CDevPtr d)
+{
+  SIL164Ptr sil = SILPTR(d);
+  
+  if (!sil164ReadByte(sil, SIL164_FREQ_LO, &sil->SavedReg.freq_lo))
+      return;
+
+  if (!sil164ReadByte(sil, SIL164_FREQ_HI, &sil->SavedReg.freq_hi))
+      return;
+
+  if (!sil164ReadByte(sil, SIL164_REG8, &sil->SavedReg.reg8))
+    return;
+  
+  if (!sil164ReadByte(sil, SIL164_REG9, &sil->SavedReg.reg9))
+    return;
+
+  if (!sil164ReadByte(sil, SIL164_REGC, &sil->SavedReg.regc))
+    return;
+  
+  return;
+
+}
+
+I830I2CVidOutputRec SIL164VidOutput = {
+  sil164Detect,
+  sil164Init,
+  sil164ModeValid,
+  sil164Mode,
+  sil164Power,
+  sil164PrintRegs,
+  sil164SaveRegs,
+  NULL,
+};
diff --git a/src/sil164/sil164.h b/src/sil164/sil164.h
new file mode 100644
index 0000000..ea5c4c9
--- /dev/null
+++ b/src/sil164/sil164.h
@@ -0,0 +1,33 @@
+/**************************************************************************
+
+ Copyright 2006 Dave Airlie <airlied at linux.ie>
+ 
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifndef SIL164_H
+#define SIL164_H
+
+#define SIL164_ADDR_1 0x38
+
+#define SIL164_SYMBOL_LIST "SIL164VidOutput"
+
+#endif
diff --git a/src/sil164/sil164_module.c b/src/sil164/sil164_module.c
new file mode 100644
index 0000000..6778e6a
--- /dev/null
+++ b/src/sil164/sil164_module.c
@@ -0,0 +1,36 @@
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86Module.h"
+
+static MODULESETUPPROTO(sil164Setup);
+
+static XF86ModuleVersionInfo sil164VersRec = 
+  {
+    "sil164",
+    MODULEVENDORSTRING,
+    MODINFOSTRING1,
+    MODINFOSTRING2,
+    XORG_VERSION_CURRENT,
+    1, 0, 0,
+    ABI_CLASS_VIDEODRV,
+    ABI_VIDEODRV_VERSION,
+    MOD_CLASS_NONE,
+    { 0,0,0,0 }
+  };
+
+_X_EXPORT XF86ModuleData sil164ModuleData = {
+  &sil164VersRec,
+  sil164Setup,
+  NULL
+};
+
+static pointer
+sil164Setup(pointer module, pointer opts, int *errmaj, int *errmin) {
+  return (pointer)1;
+}
diff --git a/src/sil164/sil164_reg.h b/src/sil164/sil164_reg.h
new file mode 100644
index 0000000..879363c
--- /dev/null
+++ b/src/sil164/sil164_reg.h
@@ -0,0 +1,75 @@
+/**************************************************************************
+
+ Copyright 2006 Dave Airlie <airlied at linux.ie>
+ 
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifndef SIL164_REG_H
+#define SIL164_REG_H
+
+#define SIL164_VID 0x0001
+#define SIL164_DID 0x0006
+
+#define SIL164_VID_LO 0x00
+#define SIL164_VID_HI 0x01
+#define SIL164_DID_LO 0x02
+#define SIL164_DID_HI 0x03
+#define SIL164_REV    0x04
+#define SIL164_RSVD   0x05
+#define SIL164_FREQ_LO 0x06
+#define SIL164_FREQ_HI 0x07
+
+#define SIL164_REG8 0x08
+#define SIL164_8_VEN (1<<5)
+#define SIL164_8_HEN (1<<4)
+#define SIL164_8_DSEL (1<<3)
+#define SIL164_8_BSEL (1<<2)
+#define SIL164_8_EDGE (1<<1)
+#define SIL164_8_PD   (1<<0)
+
+#define SIL164_REG9 0x09
+#define SIL164_9_VLOW (1<<7)
+#define SIL164_9_MSEL_MASK (0x7<<4)
+#define SIL164_9_TSEL (1<<3)
+#define SIL164_9_RSEN (1<<2)
+#define SIL164_9_HTPLG (1<<1)
+#define SIL164_9_MDI (1<<0)
+
+#define SIL164_REGC 0x0c
+
+typedef struct _Sil164SaveRec {
+  CARD8 freq_lo;
+  CARD8 freq_hi;
+  CARD8 reg8;
+  CARD8 reg9;
+  CARD8 regc;
+} SIL164SaveRec;
+
+typedef struct {
+  I2CDevRec d;
+  SIL164SaveRec SavedReg;
+  SIL164SaveRec ModeReg;
+} SIL164Rec, *SIL164Ptr;
+
+#define SILPTR(d) ((SIL164Ptr)(d->DriverPrivate.ptr))
+
+#endif
diff-tree e1064f52b0ff69ea7937897b8c951cc3e32cd752 (from ffa6ecc18bc54151061d9956f1d12575fc057da3)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Wed Jul 5 16:00:03 2006 -0700

    Don't try to probe modes on an SDVO device with NULL sdvo_drv.

diff --git a/src/i830_modes.c b/src/i830_modes.c
index cb50523..bb097b8 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -733,7 +733,9 @@ I830ReprobePipeModeList(ScrnInfoPtr pScr
 	    }
 	    break;
 	case I830_OUTPUT_SDVO:
-	    if (outputs & PIPE_DFP) {
+	    if (outputs & PIPE_DFP &&
+		pI830->output[i].sdvo_drv != NULL)
+	    {
 		output_index = i;
 	    }
 	    break;
diff-tree ffa6ecc18bc54151061d9956f1d12575fc057da3 (from dfd7fef457c048c9f0d826e37d91453d9e1485b9)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Wed Jul 5 14:41:08 2006 -0700

    More fixes to "choose closest mode for the pipe" code to select correct refresh.

diff --git a/src/i830_display.c b/src/i830_display.c
index b5461c2..d31c100 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -275,12 +275,19 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	for (pScan = pI830->pipeMon[pipe]->Modes; pScan != NULL;
 	     pScan = pScan->next)
 	{
+	    /* If there's an exact match, we're done. */
+	    if (I830ModesEqual(pScan, pMode)) {
+		pBest = pMode;
+		break;
+	    }
+
 	    /* Reject if it's larger than the desired mode. */
 	    if (pScan->HDisplay > pMode->HDisplay ||
 		pScan->VDisplay > pMode->VDisplay)
 	    {
 		continue;
 	    }
+
 	    if (pBest == NULL) {
 		pBest = pScan;
 	        continue;
@@ -288,8 +295,10 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	    /* Find if it's closer to the right size than the current best
 	     * option.
 	     */
-	    if (pScan->HDisplay >= pBest->HDisplay && 
-		pScan->VDisplay >= pBest->VDisplay)
+	    if ((pScan->HDisplay > pBest->HDisplay && 
+		pScan->VDisplay >= pBest->VDisplay) ||
+	        (pScan->HDisplay >= pBest->HDisplay && 
+		pScan->VDisplay > pBest->VDisplay))
 	    {
 		pBest = pScan;
 		continue;
diff-tree dfd7fef457c048c9f0d826e37d91453d9e1485b9 (from 5d07ebdf4f23e16fb8f60eafeadc947701e7877c)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Jul 3 12:01:57 2006 -0700

    Bug #7375: Don't double-free the current XF86 mode after a randr reprobe.

diff --git a/src/i830_display.c b/src/i830_display.c
index e63800d..b5461c2 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -828,6 +828,7 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
 	 */
 	xfree(pI830->savedCurrentMode->name);
 	xfree(pI830->savedCurrentMode);
+	pI830->savedCurrentMode = NULL;
 	    
 	/* If we might have enabled/disabled some pipes, we need to reset
 	 * cloning mode support.
diff-tree 5d07ebdf4f23e16fb8f60eafeadc947701e7877c (from 48f27ac62128251640a9b1ca54f63376676b47eb)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Jul 3 11:59:21 2006 -0700

    Only override display size with the XFree86 mode's for actual panel scaling.

diff --git a/src/i830_display.c b/src/i830_display.c
index 24103cb..e63800d 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -361,8 +361,8 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     vtot = (pMode->CrtcVDisplay - 1) | ((pMode->CrtcVTotal - 1) << 16);
     vblank = (pMode->CrtcVBlankStart - 1) | ((pMode->CrtcVBlankEnd - 1) << 16);
     vsync = (pMode->CrtcVSyncStart - 1) | ((pMode->CrtcVSyncEnd - 1) << 16);
-    pipesrc = ((pMasterMode->HDisplay - 1) << 16) | (pMasterMode->VDisplay - 1);
-    dspsize = ((pMasterMode->VDisplay - 1) << 16) | (pMasterMode->HDisplay - 1);
+    pipesrc = ((pMode->HDisplay - 1) << 16) | (pMode->VDisplay - 1);
+    dspsize = ((pMode->VDisplay - 1) << 16) | (pMode->HDisplay - 1);
     pixel_clock = pMode->Clock;
     if (outputs & PIPE_LCD_ACTIVE && pI830->panel_fixed_hactive != 0)
     {
@@ -390,6 +390,15 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 		((pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff +
 		  pI830->panel_fixed_vsyncwidth - 1) << 16);
 	pixel_clock = pI830->panel_fixed_clock;
+
+	if (pMasterMode->HDisplay <= pI830->panel_fixed_hactive &&
+	    pMasterMode->HDisplay <= pI830->panel_fixed_vactive)
+	{
+	    pipesrc = ((pMasterMode->HDisplay - 1) << 16) |
+		       (pMasterMode->VDisplay - 1);
+	    dspsize = ((pMasterMode->VDisplay - 1) << 16) |
+		       (pMasterMode->HDisplay - 1);
+	}
     }
 
     if (pMode->Clock >= 100000)
diff-tree 48f27ac62128251640a9b1ca54f63376676b47eb (from ce5bd108c55d2378db072617c380514a39672603)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Wed Jun 28 15:07:01 2006 +0200

    Replace i830InjectModes with i830DuplicateModes usage.
    
    The remaining functionality of DuplicateModes was OBE, and the name was bad.

diff --git a/src/i830_modes.c b/src/i830_modes.c
index 6b914bc..cb50523 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -587,56 +587,6 @@ i830DuplicateModes(ScrnInfoPtr pScrn, Di
     return first;
 }
 
-/**
- * Duplicates and appends a list of modes to a mode list.
- *
- * Take the doubly-linked list of modes we've probed for the device, and injects
- * it into the doubly-linked modeList.  We don't need to filter, because the
- * eventual call to xf86ValidateModes will do this for us.  I think.
- */
-static int
-i830InjectModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList,
-		DisplayModePtr addModes)
-{
-    DisplayModePtr  last = *modeList;
-    DisplayModePtr  first = *modeList;
-    DisplayModePtr  addMode;
-    int count = 0;
-
-    for (addMode = addModes; addMode != NULL; addMode = addMode->next) {
-	DisplayModePtr pNew;
-
-	pNew = I830DuplicateMode(addMode);
-#if 0
-	/* If the user didn't specify any modes, mark all modes as M_T_USERDEF
-	 * so that we can cycle through them, etc.  XXX: really need to?
-	 */
-	if (pScrn->display->modes[0] == NULL) {
-	    pNew->type |= M_T_USERDEF;
-	}
-#endif
-
-	/* Insert pNew into modeList */
-	if (last) {
-	    last->next = pNew;
-	    pNew->prev = last;
-	} else {
-	    first = pNew;
-	    pNew->prev = NULL;
-	}
-	pNew->next = NULL;
-	last = pNew;
-
-	count++;
-    }
-    *modeList = first;
-
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-	       "Injected %d modes detected from the monitor\n", count);
-
-    return count;
-}
-
 static MonPtr
 i830GetDDCMonitor(ScrnInfoPtr pScrn, I2CBusPtr pDDCBus)
 {
@@ -1037,9 +987,9 @@ I830ValidateXF86ModeList(ScrnInfoPtr pSc
      * care about enough to make some sort of unioned list.
      */
     if (pI830->pipeMon[1] != NULL) {
-	i830InjectModes(pScrn, &pScrn->modes, pI830->pipeMon[1]->Modes);
+	pScrn->modes = i830DuplicateModes(pScrn, pI830->pipeMon[1]->Modes);
     } else {
-	i830InjectModes(pScrn, &pScrn->modes, pI830->pipeMon[0]->Modes);
+	pScrn->modes = i830DuplicateModes(pScrn, pI830->pipeMon[0]->Modes);
     }
     if (pScrn->modes == NULL) {
 	FatalError("No modes found\n");
diff-tree ce5bd108c55d2378db072617c380514a39672603 (from 367f69f8e7710e53dcd286f1b62506a3276e80f9)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Wed Jun 28 14:21:49 2006 +0200

    Validate and insert user and VESA standard modes for DDC or configured fallback.
    
    This isn't really tested because I lack a good CRT to test against currently.

diff --git a/src/i830_modes.c b/src/i830_modes.c
index 7433344..6b914bc 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -237,10 +237,10 @@ I830GetVESAEstablishedMode(ScrnInfoPtr p
     {
 	if (pMode->HDisplay == est_timings[i].hsize &&
 	    pMode->VDisplay == est_timings[i].vsize &&
-	    fabs(I830ModeVRefresh(pMode) - est_timings[i].refresh) < 1.0)
+	    fabs(i830xf86ModeVRefresh(pMode) - est_timings[i].refresh) < 1.0)
 	{
 	    DisplayModePtr pNew = I830DuplicateMode(pMode);
-	    pNew->VRefresh = I830ModeVRefresh(pMode);
+	    pNew->VRefresh = i830xf86ModeVRefresh(pMode);
 	    return pNew;
 	}
     }
@@ -523,16 +523,80 @@ i830GetLVDSModes(ScrnInfoPtr pScrn, char
    return first;
 }
 
+static DisplayModePtr
+i830GetModeListTail(DisplayModePtr pModeList)
+{
+    DisplayModePtr last;
+
+    if (pModeList == NULL)
+	return NULL;
+
+    for (last = pModeList; last->next != NULL; last = last->next)
+	;
+
+    return last;
+}
+
+/**
+ * Appends a list of modes to another mode list, without duplication.
+ */
+static void
+i830AppendModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList,
+		DisplayModePtr addModes)
+{
+    DisplayModePtr first = *modeList;
+    DisplayModePtr last = i830GetModeListTail(first);
+
+    if (first == NULL) {
+	*modeList = addModes;
+    } else {
+	last->next = addModes;
+	addModes->prev = last;
+    }
+}
+
+/**
+ * Duplicates every mode in the given list and returns a pointer to the first
+ * mode.
+ *
+ * \param modeList doubly-linked mode list
+ */
+static DisplayModePtr
+i830DuplicateModes(ScrnInfoPtr pScrn, DisplayModePtr modeList)
+{
+    DisplayModePtr first = NULL, last = NULL;
+    DisplayModePtr mode;
+
+    for (mode = modeList; mode != NULL; mode = mode->next) {
+	DisplayModePtr new;
+
+	new = I830DuplicateMode(mode);
+
+	/* Insert pNew into modeList */
+	if (last) {
+	    last->next = new;
+	    new->prev = last;
+	} else {
+	    first = new;
+	    new->prev = NULL;
+	}
+	new->next = NULL;
+	last = new;
+    }
+
+    return first;
+}
+
 /**
- * Injects a list of probed modes into another mode list.
+ * Duplicates and appends a list of modes to a mode list.
  *
  * Take the doubly-linked list of modes we've probed for the device, and injects
  * it into the doubly-linked modeList.  We don't need to filter, because the
  * eventual call to xf86ValidateModes will do this for us.  I think.
  */
 static int
-I830InjectProbedModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList,
-		      DisplayModePtr addModes)
+i830InjectModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList,
+		DisplayModePtr addModes)
 {
     DisplayModePtr  last = *modeList;
     DisplayModePtr  first = *modeList;
@@ -573,25 +637,12 @@ I830InjectProbedModes(ScrnInfoPtr pScrn,
     return count;
 }
 
-static DisplayModePtr
-i830GetModeListTail(DisplayModePtr pModeList)
-{
-    DisplayModePtr last;
-
-    if (pModeList == NULL)
-	return NULL;
-
-    for (last = pModeList; last->next != NULL; last = last->next)
-	;
-
-    return last;
-}
-
 static MonPtr
 i830GetDDCMonitor(ScrnInfoPtr pScrn, I2CBusPtr pDDCBus)
 {
     xf86MonPtr ddc;
     MonPtr mon;
+    DisplayModePtr userModes;
     int i;
 
     ddc = xf86DoEDID_DDC2(pScrn->scrnIndex, pDDCBus);
@@ -601,7 +652,6 @@ i830GetDDCMonitor(ScrnInfoPtr pScrn, I2C
 
     mon = xnfcalloc(1, sizeof(*mon));
     mon->Modes = i830GetDDCModes(pScrn, ddc);
-    mon->Last = i830GetModeListTail(mon->Modes);
     mon->DDC = ddc;
 
     for (i = 0; i < DET_TIMINGS; i++) {
@@ -624,6 +674,22 @@ i830GetDDCMonitor(ScrnInfoPtr pScrn, I2C
 	}
     }
 
+    /* Add in VESA standard and user modelines, and do additional validation
+     * on them beyond what pipe config will do (x/y/pitch, clocks, flags)
+     */
+    userModes = i830DuplicateModes(pScrn, pScrn->monitor->Modes);
+
+    i830xf86ValidateModesSync(pScrn, userModes, mon);
+    if (ddc->features.hsize > 0 && ddc->features.vsize > 0) {
+	i830xf86ValidateModesSize(pScrn, userModes, ddc->features.hsize,
+				  ddc->features.vsize, -1);
+    }
+    i830xf86PruneInvalidModes(pScrn, &userModes, TRUE);
+
+    i830AppendModes(pScrn, &mon->Modes, userModes);
+
+    mon->Last = i830GetModeListTail(mon->Modes);
+
     return mon;
 }
 
@@ -643,6 +709,7 @@ static MonPtr
 i830GetConfiguredMonitor(ScrnInfoPtr pScrn)
 {
     MonPtr mon;
+    DisplayModePtr userModes;
 
     mon = xnfcalloc(1, sizeof(*mon));
     memcpy(mon, pScrn->monitor, sizeof(*mon));
@@ -654,6 +721,17 @@ i830GetConfiguredMonitor(ScrnInfoPtr pSc
     if (pScrn->monitor->model != NULL)
 	mon->model = xnfstrdup(pScrn->monitor->model);
 
+    /* Add in VESA standard and user modelines, and do additional validation
+     * on them beyond what pipe config will do (x/y/pitch, clocks, flags)
+     */
+    userModes = i830DuplicateModes(pScrn, pScrn->monitor->Modes);
+    i830xf86ValidateModesSync(pScrn, userModes, mon);
+    i830xf86PruneInvalidModes(pScrn, &userModes, FALSE);
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "prune 1\n");
+    i830AppendModes(pScrn, &mon->Modes, userModes);
+
+    mon->Last = i830GetModeListTail(mon->Modes);
+
     return mon;
 }
 
@@ -776,8 +854,7 @@ I830ReprobePipeModeList(ScrnInfoPtr pScr
 	    /* The code to choose the best mode per pipe later on will require
 	     * VRefresh to be set.
 	     */
-
-	    pMode->VRefresh = I830ModeVRefresh(pMode);
+	    pMode->VRefresh = i830xf86ModeVRefresh(pMode);
 	    I830xf86SetModeCrtc(pMode, INTERLACE_HALVE_V);
 #ifdef DEBUG_REPROBE
 	    PrintModeline(pScrn->scrnIndex, pMode);
@@ -960,9 +1037,9 @@ I830ValidateXF86ModeList(ScrnInfoPtr pSc
      * care about enough to make some sort of unioned list.
      */
     if (pI830->pipeMon[1] != NULL) {
-	I830InjectProbedModes(pScrn, &pScrn->modes, pI830->pipeMon[1]->Modes);
+	i830InjectModes(pScrn, &pScrn->modes, pI830->pipeMon[1]->Modes);
     } else {
-	I830InjectProbedModes(pScrn, &pScrn->modes, pI830->pipeMon[0]->Modes);
+	i830InjectModes(pScrn, &pScrn->modes, pI830->pipeMon[0]->Modes);
     }
     if (pScrn->modes == NULL) {
 	FatalError("No modes found\n");
diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c
index 6f620c8..09f6b34 100644
--- a/src/i830_xf86Modes.c
+++ b/src/i830_xf86Modes.c
@@ -44,13 +44,32 @@
  * there but we still want to use.  We need to come up with better API here.
  */
 
+
 /**
- * Calculates the vertical refresh of a mode.
+ * Calculates the horizontal sync rate of a mode.
  *
  * Exact copy of xf86Mode.c's.
  */
 double
-I830ModeVRefresh(DisplayModePtr mode)
+i830xf86ModeHSync(DisplayModePtr mode)
+{
+    double hsync = 0.0;
+    
+    if (mode->HSync > 0.0)
+	    hsync = mode->HSync;
+    else if (mode->HTotal > 0)
+	    hsync = (float)mode->Clock / (float)mode->HTotal;
+
+    return hsync;
+}
+
+/**
+ * Calculates the vertical refresh rate of a mode.
+ *
+ * Exact copy of xf86Mode.c's.
+ */
+double
+i830xf86ModeVRefresh(DisplayModePtr mode)
 {
     double refresh = 0.0;
 
@@ -291,6 +310,51 @@ i830xf86ValidateModesSize(ScrnInfoPtr pS
 }
 
 /**
+ * Marks as bad any modes that aren't supported by the given monitor's
+ * hsync and vrefresh ranges.
+ *
+ * \param modeList doubly-linked or circular list of modes.
+ *
+ * This is not in xf86Modes.c, but would be part of the proposed new API.
+ */
+void
+i830xf86ValidateModesSync(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+			  MonPtr mon)
+{
+    DisplayModePtr mode;
+
+    for (mode = modeList; mode != NULL; mode = mode->next) {
+	Bool bad;
+	int i;
+
+	bad = TRUE;
+	for (i = 0; i < mon->nHsync; i++) {
+	    if (i830xf86ModeHSync(mode) >= mon->hsync[i].lo &&
+		i830xf86ModeHSync(mode) <= mon->hsync[i].hi)
+	    {
+		bad = FALSE;
+	    }
+	}
+	if (bad)
+	    mode->status = MODE_HSYNC;
+
+	bad = TRUE;
+	for (i = 0; i < mon->nVrefresh; i++) {
+	    if (i830xf86ModeVRefresh(mode) >= mon->vrefresh[i].lo &&
+		i830xf86ModeVRefresh(mode) <= mon->vrefresh[i].hi)
+	    {
+		bad = FALSE;
+	    }
+	}
+	if (bad)
+	    mode->status = MODE_VSYNC;
+
+	if (mode->next == modeList)
+	    break;
+    }
+}
+
+/**
  * Marks as bad any modes extending beyond outside of the given clock ranges.
  *
  * \param modeList doubly-linked or circular list of modes.
diff --git a/src/i830_xf86Modes.h b/src/i830_xf86Modes.h
index 86e5b06..855aa46 100644
--- a/src/i830_xf86Modes.h
+++ b/src/i830_xf86Modes.h
@@ -26,7 +26,10 @@
  */
 
 double
-I830ModeVRefresh(DisplayModePtr mode);
+i830xf86ModeHSync(DisplayModePtr mode);
+
+double
+i830xf86ModeVRefresh(DisplayModePtr mode);
 
 void
 I830xf86SetModeCrtc(DisplayModePtr p, int adjustFlags);
@@ -47,6 +50,10 @@ i830xf86ValidateModesSize(ScrnInfoPtr pS
 			  int maxX, int maxY, int maxPitch);
 
 void
+i830xf86ValidateModesSync(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+			  MonPtr mon);
+
+void
 i830xf86PruneInvalidModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList,
 			  Bool verbose);
 
diff-tree 367f69f8e7710e53dcd286f1b62506a3276e80f9 (from 9fbd3d8f4befb75ed6f6bd9a9ffe0175626e8785)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Wed Jun 28 13:10:02 2006 +0200

    Replace xf86ValidateModes usage with a set of custom validators and pruning.
    
    This moves us to maintaining MonPtrs per pipe instead of using the EDID
    structure "xf86MonPtr", which is closer to what we want to be looking at when
    doing validation.  The new validation isn't enough yet -- particularly, we
    aren't importing and validating the custom modelines to the pipes when
    applicable, but this will be easier than (for example) trying to make flat
    panel modes pass xf86ValidateModes through various gross hacks.
    
    Hotplug turn-on/off also happens at SwitchMode time now, instead of at randr
    probe time.

diff --git a/src/i830.h b/src/i830.h
index 9bd0227..f1b9774 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -227,6 +227,10 @@ typedef struct _I830Rec {
    int fixedPipe;
 
    DisplayModePtr currentMode;
+   /* Mode saved during randr reprobe, which will need to be freed at the point
+    * of the next SwitchMode, when we lose this last reference to it.
+    */
+   DisplayModePtr savedCurrentMode;
 
    Bool Clone;
    int CloneRefresh;
@@ -401,8 +405,7 @@ typedef struct _I830Rec {
    int availablePipes;
    /* [0] is display plane A, [1] is display plane B. */
    int planeEnabled[MAX_DISPLAY_PIPES];
-   xf86MonPtr pipeMon[MAX_DISPLAY_PIPES];
-   DisplayModePtr pipeModes[MAX_DISPLAY_PIPES];
+   MonPtr pipeMon[MAX_DISPLAY_PIPES];
    DisplayModeRec pipeCurMode[MAX_DISPLAY_PIPES];
 
    /* Driver phase/state information */
diff --git a/src/i830_display.c b/src/i830_display.c
index 8080c55..24103cb 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -268,11 +268,12 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     /* If we've got a list of modes probed for the device, find the best match
      * in there to the requested mode.
      */
-    if (pI830->pipeModes[pipe] != NULL) {
+    if (pI830->pipeMon[pipe] != NULL) {
 	DisplayModePtr pBest = NULL, pScan;
 
 	assert(pScan->VRefresh != 0.0);
-	for (pScan = pI830->pipeModes[pipe]; pScan != NULL; pScan = pScan->next)
+	for (pScan = pI830->pipeMon[pipe]->Modes; pScan != NULL;
+	     pScan = pScan->next)
 	{
 	    /* Reject if it's larger than the desired mode. */
 	    if (pScan->HDisplay > pMode->HDisplay ||
@@ -284,9 +285,20 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 		pBest = pScan;
 	        continue;
 	    }
-	    /* Find if it's closer than the current best option */
-	    if ((pScan->HDisplay >= pBest->HDisplay && 
-		pScan->HDisplay >= pBest->HDisplay) ||
+	    /* Find if it's closer to the right size than the current best
+	     * option.
+	     */
+	    if (pScan->HDisplay >= pBest->HDisplay && 
+		pScan->VDisplay >= pBest->VDisplay)
+	    {
+		pBest = pScan;
+		continue;
+	    }
+	    /* Find if it's still closer to the right refresh than the current
+	     * best resolution.
+	     */
+	    if (pScan->HDisplay == pBest->HDisplay && 
+		pScan->VDisplay == pBest->VDisplay &&
 		(fabs(pScan->VRefresh - pMode->VRefresh) <
 		fabs(pBest->VRefresh - pMode->VRefresh)))
 	    {
@@ -801,6 +813,29 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
 	       (int)(pMode->HDisplay * pMode->VDisplay *
 		     pMode->VRefresh / 1000000));
 
+    if (pI830->savedCurrentMode) {
+	/* We're done with the currentMode that the last randr probe had left
+	 * behind, so free it.
+	 */
+	xfree(pI830->savedCurrentMode->name);
+	xfree(pI830->savedCurrentMode);
+	    
+	/* If we might have enabled/disabled some pipes, we need to reset
+	 * cloning mode support.
+	 */
+	if ((pI830->operatingDevices & 0x00ff) &&
+	    (pI830->operatingDevices & 0xff00))
+	{
+	    pI830->Clone = TRUE;
+	} else {
+	    pI830->Clone = FALSE;
+	}
+
+	/* If HW cursor currently showing, reset cursor state */
+	if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn)
+	    pI830->CursorInfoRec->ShowCursor(pScrn);
+    }
+
     i830DisableUnusedFunctions(pScrn);
 
     planeA = INREG(DSPACNTR);
diff --git a/src/i830_modes.c b/src/i830_modes.c
index 893ef10..7433344 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -47,6 +47,7 @@
 
 #include "xf86.h"
 #include "i830.h"
+#include "i830_display.h"
 #include "i830_xf86Modes.h"
 #include <randrstr.h>
 
@@ -247,7 +248,7 @@ I830GetVESAEstablishedMode(ScrnInfoPtr p
 }
 
 static DisplayModePtr
-I830GetDDCModes(ScrnInfoPtr pScrn, xf86MonPtr ddc)
+i830GetDDCModes(ScrnInfoPtr pScrn, xf86MonPtr ddc)
 {
     DisplayModePtr  last  = NULL;
     DisplayModePtr  new   = NULL;
@@ -487,9 +488,11 @@ i830GetLVDSModes(ScrnInfoPtr pScrn, char
 
    /* If the user hasn't specified modes, add the native mode */
    if (!count) {
-      first = last = i830FPNativeMode(pScrn);
-      if (first)
+      new = i830FPNativeMode(pScrn);
+      if (first) {
+	 I830xf86SortModes(new, &first, &last);
 	 count = 1;
+      }
    }
 
    /* add in all default vesa modes smaller than panel size, used for randr */
@@ -507,14 +510,7 @@ i830GetLVDSModes(ScrnInfoPtr pScrn, char
 	    else
 		new->type |= M_T_DEFAULT;
 
-	    new->next       = NULL;
-	    new->prev       = last;
-
-	    if (last)
-	       last->next = new;
-	    last = new;
-	    if (!first)
-	       first = new;
+	    I830xf86SortModes(new, &first, &last);
 
 	    count++;
 	 }
@@ -546,9 +542,6 @@ I830InjectProbedModes(ScrnInfoPtr pScrn,
     for (addMode = addModes; addMode != NULL; addMode = addMode->next) {
 	DisplayModePtr pNew;
 
-	/* XXX: Do we need to check if modeList already contains the same mode?
-	 */
-
 	pNew = I830DuplicateMode(addMode);
 #if 0
 	/* If the user didn't specify any modes, mark all modes as M_T_USERDEF
@@ -580,6 +573,102 @@ I830InjectProbedModes(ScrnInfoPtr pScrn,
     return count;
 }
 
+static DisplayModePtr
+i830GetModeListTail(DisplayModePtr pModeList)
+{
+    DisplayModePtr last;
+
+    if (pModeList == NULL)
+	return NULL;
+
+    for (last = pModeList; last->next != NULL; last = last->next)
+	;
+
+    return last;
+}
+
+static MonPtr
+i830GetDDCMonitor(ScrnInfoPtr pScrn, I2CBusPtr pDDCBus)
+{
+    xf86MonPtr ddc;
+    MonPtr mon;
+    int i;
+
+    ddc = xf86DoEDID_DDC2(pScrn->scrnIndex, pDDCBus);
+
+    if (ddc == NULL)
+	return NULL;
+
+    mon = xnfcalloc(1, sizeof(*mon));
+    mon->Modes = i830GetDDCModes(pScrn, ddc);
+    mon->Last = i830GetModeListTail(mon->Modes);
+    mon->DDC = ddc;
+
+    for (i = 0; i < DET_TIMINGS; i++) {
+	struct detailed_monitor_section *det_mon = &ddc->det_mon[i];
+
+	switch (ddc->det_mon[i].type) {
+	case DS_RANGES:
+	    mon->hsync[mon->nHsync].lo = det_mon->section.ranges.min_h;
+	    mon->hsync[mon->nHsync].hi = det_mon->section.ranges.max_h;
+	    mon->nHsync++;
+	    mon->vrefresh[mon->nVrefresh].lo = det_mon->section.ranges.min_v;
+	    mon->vrefresh[mon->nVrefresh].hi = det_mon->section.ranges.max_v;
+	    mon->nVrefresh++;
+	    break;
+	default:
+	    /* We probably don't care about trying to contruct ranges around
+	     * modes specified by DDC.
+	     */
+	    break;
+	}
+    }
+
+    return mon;
+}
+
+static MonPtr
+i830GetLVDSMonitor(ScrnInfoPtr pScrn)
+{
+    MonPtr mon;
+
+    mon = xnfcalloc(1, sizeof(*mon));
+    mon->Modes = i830GetLVDSModes(pScrn, pScrn->display->modes);
+    mon->Last = i830GetModeListTail(mon->Modes);
+
+    return mon;
+}
+
+static MonPtr
+i830GetConfiguredMonitor(ScrnInfoPtr pScrn)
+{
+    MonPtr mon;
+
+    mon = xnfcalloc(1, sizeof(*mon));
+    memcpy(mon, pScrn->monitor, sizeof(*mon));
+
+    if (pScrn->monitor->id != NULL)
+	mon->id = xnfstrdup(pScrn->monitor->id);
+    if (pScrn->monitor->vendor != NULL)
+	mon->vendor = xnfstrdup(pScrn->monitor->vendor);
+    if (pScrn->monitor->model != NULL)
+	mon->model = xnfstrdup(pScrn->monitor->model);
+
+    return mon;
+}
+
+static void
+i830FreeMonitor(ScrnInfoPtr pScrn, MonPtr mon)
+{
+    while (mon->Modes != NULL)
+	xf86DeleteMode(&mon->Modes, mon->Modes);
+    xfree(mon->id);
+    xfree(mon->vendor);
+    xfree(mon->model);
+    xfree(mon->DDC);
+    xfree(mon);
+}
+
 /**
  * Performs probing of modes available on the output connected to the given
  * pipe.
@@ -596,11 +685,7 @@ I830ReprobePipeModeList(ScrnInfoPtr pScr
     int i;
     int outputs;
     DisplayModePtr pMode;
-    Bool had_modes;
-
-    had_modes = (pI830->pipeModes[pipe] != NULL);
-    while (pI830->pipeModes[pipe] != NULL)
-	xf86DeleteMode(&pI830->pipeModes[pipe], pI830->pipeModes[pipe]);
+    MonPtr old_mon = pI830->pipeMon[pipe];
 
     if (pipe == 0)
 	outputs = pI830->operatingDevices & 0xff;
@@ -631,45 +716,87 @@ I830ReprobePipeModeList(ScrnInfoPtr pScr
 	return;
 
     if (outputs & PIPE_LFP) {
-	pI830->pipeMon[pipe] = NULL; /* XXX */
-	pI830->pipeModes[pipe] = i830GetLVDSModes(pScrn,
-						  pScrn->display->modes);
+	pI830->pipeMon[pipe] = i830GetLVDSMonitor(pScrn);
     } else if (pI830->output[output_index].pDDCBus != NULL) {
-	/* XXX: Free the mon */
-	pI830->pipeMon[pipe] = xf86DoEDID_DDC2(pScrn->scrnIndex,
-					       pI830->output[output_index].pDDCBus);
-	pI830->pipeModes[pipe] = I830GetDDCModes(pScrn,
-						 pI830->pipeMon[pipe]);
-
-	for (pMode = pI830->pipeModes[pipe]; pMode != NULL; pMode = pMode->next)
-	{
-	    I830xf86SetModeCrtc(pMode, INTERLACE_HALVE_V);
-	}
-	if (had_modes && pI830->pipeModes[pipe] == NULL) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		       "Failed to DDC pipe %d, disabling output\n", pipe);
-	    if (pipe == 0)
-		pI830->operatingDevices &= ~0x00ff;
-	    else
-		pI830->operatingDevices &= ~0xff00;
+	pI830->pipeMon[pipe] =
+	    i830GetDDCMonitor(pScrn, pI830->output[output_index].pDDCBus);
+    }
+    /* If DDC didn't work (or the flat panel equivalent), then see if we can
+     * detect if a monitor is at least plugged in.  If we can't tell that one
+     * is plugged in, then assume that it is.
+     */
+    if (pI830->pipeMon[pipe] == NULL) {
+	switch (pI830->output[output_index].type) {
+	case I830_OUTPUT_SDVO:
+	    if (I830DetectSDVODisplays(pScrn, output_index))
+		pI830->pipeMon[pipe] = i830GetConfiguredMonitor(pScrn);
+	    break;
+	case I830_OUTPUT_ANALOG:
+	    /* Do a disruptive detect if necessary, since we want to be sure we
+	     * know if a monitor is attached, and this detect process should be
+	     * infrequent.
+	     */
+	    if (i830DetectCRT(pScrn, TRUE))
+		pI830->pipeMon[pipe] = i830GetConfiguredMonitor(pScrn);
+	    break;
+	default:
+	    pI830->pipeMon[pipe] = i830GetConfiguredMonitor(pScrn);
+	    break;
 	}
-    } else {
-	ErrorF("don't know how to get modes for this device.\n");
     }
 
-    /* Set the vertical refresh, which is used by the choose-best-mode-per-pipe
-     * code later on.
-     */
 #ifdef DEBUG_REPROBE
     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Printing probed modes for pipe %d\n",
 	       pipe);
 #endif
-    for (pMode = pI830->pipeModes[pipe]; pMode != NULL; pMode = pMode->next) {
-	pMode->VRefresh = I830ModeVRefresh(pMode);
+    if (pI830->pipeMon[pipe] != NULL) {
+	int minclock, maxclock;
+
+	switch (pI830->output[output_index].type) {
+	case I830_OUTPUT_SDVO:
+	    minclock = 25000;
+	    maxclock = 165000;
+	case I830_OUTPUT_LVDS:
+	case I830_OUTPUT_ANALOG:
+	default:
+	    minclock = 25000;
+	    maxclock = 400000;
+	}
+
+	i830xf86ValidateModesFlags(pScrn, pI830->pipeMon[pipe]->Modes,
+				   V_INTERLACE);
+	i830xf86ValidateModesClocks(pScrn, pI830->pipeMon[pipe]->Modes,
+				    &minclock, &maxclock, 1);
+
+	i830xf86PruneInvalidModes(pScrn, &pI830->pipeMon[pipe]->Modes, TRUE);
+
+	for (pMode = pI830->pipeMon[pipe]->Modes; pMode != NULL;
+	     pMode = pMode->next)
+	{
+	    /* The code to choose the best mode per pipe later on will require
+	     * VRefresh to be set.
+	     */
+
+	    pMode->VRefresh = I830ModeVRefresh(pMode);
+	    I830xf86SetModeCrtc(pMode, INTERLACE_HALVE_V);
 #ifdef DEBUG_REPROBE
-	PrintModeline(pScrn->scrnIndex, pMode);
+	    PrintModeline(pScrn->scrnIndex, pMode);
 #endif
+	}
+    }
+
+    if (old_mon != NULL && pI830->pipeMon[pipe] == NULL) {
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		   "Failed to probe output on pipe %d, disabling output at next "
+		   "mode switch\n", pipe);
+	if (pipe == 0)
+	    pI830->operatingDevices &= ~0x00ff;
+	else
+	    pI830->operatingDevices &= ~0xff00;
     }
+
+    if (old_mon != NULL)
+	i830FreeMonitor(pScrn, old_mon);
 }
 
 /**
@@ -720,10 +847,8 @@ int
 I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    ClockRangePtr clockRanges;
-    int n, pipe;
-    DisplayModePtr saved_mode, availModes = NULL;
-    int saved_virtualX = 0, saved_virtualY = 0, saved_displayWidth = 0;
+    int pipe;
+    DisplayModePtr saved_mode, last;
     Bool pipes_reconfigured = FALSE;
     int originalVirtualX, originalVirtualY;
 
@@ -738,7 +863,7 @@ I830ValidateXF86ModeList(ScrnInfoPtr pSc
 	if ((pI830->operatingDevices & 0xff) == PIPE_NONE) {
 	    pI830->operatingDevices |= PIPE_CRT;
 	    I830ReprobePipeModeList(pScrn, 0);
-	    if (pI830->pipeModes[0] == NULL) {
+	    if (pI830->pipeMon[0] == NULL) {
 		/* No new output found. */
 		pI830->operatingDevices &= ~PIPE_CRT;
 	    } else {
@@ -751,7 +876,7 @@ I830ValidateXF86ModeList(ScrnInfoPtr pSc
 	} else if (((pI830->operatingDevices >> 8) & 0xff) == PIPE_NONE) {
 	    pI830->operatingDevices |= PIPE_CRT << 8;
 	    I830ReprobePipeModeList(pScrn, 1);
-	    if (pI830->pipeModes[1] == NULL) {
+	    if (pI830->pipeMon[1] == NULL) {
 		/* No new output found. */
 		pI830->operatingDevices &= ~(PIPE_CRT << 8);
 	    } else {
@@ -764,30 +889,59 @@ I830ValidateXF86ModeList(ScrnInfoPtr pSc
 	}
     }
 
-    /* Start by injecting the XFree86 default modes and user-configured
-     * modelines.  XXX: This actually isn't of use if we've got any DDC, as DDC
-     * currently has higher priority than the validated modelist.  We need to
-     * deal with that.
-     */
-    I830InjectProbedModes(pScrn, &availModes, pScrn->monitor->Modes);
-    if (pI830->pipeModes[0] != NULL) {
-	I830InjectProbedModes(pScrn, &availModes, pI830->pipeModes[0]);
+    if ((pI830->pipeMon[0] == NULL || pI830->pipeMon[0]->Modes == NULL) &&
+	(pI830->pipeMon[1] == NULL || pI830->pipeMon[1]->Modes == NULL))
+    {
+	FatalError("No modes found on either pipe\n");
     }
-    if (pI830->pipeModes[1] != NULL) {
-	I830InjectProbedModes(pScrn, &availModes, pI830->pipeModes[1]);
+
+    if (first_time) {
+	int maxX = -1, maxY = -1;
+
+	/* Set up a virtual size that will cover any clone mode we'd want to set
+	 * for either of the two pipes.
+	 */
+	for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++) {
+	    MonPtr mon = pI830->pipeMon[pipe];
+	    DisplayModePtr mode;
+
+	    if (mon == NULL)
+		continue;
+
+	    for (mode = mon->Modes; mode != NULL; mode = mode->next) {
+		if (mode->HDisplay > maxX)
+		    maxX = mode->HDisplay;
+		if (mode->VDisplay > maxY)
+		    maxY = mode->VDisplay;
+	    }
+	}
+	pScrn->virtualX = maxX;
+	pScrn->virtualY = maxY;
+	pScrn->displayWidth = (maxX + 63) & ~63;
     }
 
-   /*
-     * Set up the ClockRanges, which describe what clock ranges are available,
-     * and what sort of modes they can be used for.
+    I830GetOriginalVirtualSize(pScrn, &originalVirtualX, &originalVirtualY);
+
+    /* Disable modes that are larger than the virtual size we decided on
+     * initially.
      */
-    clockRanges = xnfcalloc(sizeof(ClockRange), 1);
-    clockRanges->next = NULL;
-    clockRanges->minClock = 25000;
-    clockRanges->maxClock = pI830->MaxClock;
-    clockRanges->clockIndex = -1;		/* programmable */
-    clockRanges->interlaceAllowed = TRUE;	/* XXX check this */
-    clockRanges->doubleScanAllowed = FALSE;	/* XXX check this */
+    if (!first_time) {
+	for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++) {
+	    MonPtr mon = pI830->pipeMon[pipe];
+	    DisplayModePtr mode;
+
+	    if (mon == NULL)
+		continue;
+
+	    for (mode = mon->Modes; mode != NULL; mode = mode->next)
+	    {
+		if (mode->HDisplay > originalVirtualX)
+		    mode->status = MODE_VIRTUAL_X;
+		if (mode->VDisplay > originalVirtualY)
+		    mode->status = MODE_VIRTUAL_Y;
+	    }
+	}
+    }
 
     /* Remove the current mode from the modelist if we're re-validating, so we
      * can find a new mode to map ourselves to afterwards.
@@ -797,53 +951,54 @@ I830ValidateXF86ModeList(ScrnInfoPtr pSc
 	I830xf86DeleteModeFromList(&pScrn->modes, saved_mode);
     }
 
-    if (!first_time) {
-	saved_virtualX = pScrn->virtualX;
-	saved_virtualY = pScrn->virtualY;
-	saved_displayWidth = pScrn->displayWidth;
-    }
-
-    I830GetOriginalVirtualSize(pScrn, &originalVirtualX, &originalVirtualY);
-
-    /* Take the pScrn->monitor->Modes we've accumulated and validate them into
-     * pScrn->modes.
-     * XXX: Should set up a scrp->monitor->DDC covering the union of the
-     *      capabilities of our pipes.
+    /* Clear any existing modes from pScrn->modes */
+    while (pScrn->modes != NULL)
+	xf86DeleteMode(&pScrn->modes, pScrn->modes);
+
+    /* Set pScrn->modes to the mode list for the an arbitrary head.
+     * pScrn->modes should only be used for XF86VidMode now, which we don't
+     * care about enough to make some sort of unioned list.
      */
-    n = xf86ValidateModes(pScrn,
-			  availModes, /* availModes */
-			  pScrn->display->modes, /* modeNames */
-			  clockRanges, /* clockRanges */
-			  !first_time ? &pScrn->displayWidth : NULL, /* linePitches */
-			  320, /* minPitch */
-			  MAX_DISPLAY_PITCH, /* maxPitch */
-			  64 * pScrn->bitsPerPixel, /* pitchInc */
-			  200, /* minHeight */
-			  MAX_DISPLAY_HEIGHT, /* maxHeight */
-			  originalVirtualX, /* virtualX maximum */
-			  originalVirtualY, /* virtualY maximum */
-			  pI830->FbMapSize, /* apertureSize */
-			  LOOKUP_BEST_REFRESH /* strategy */);
+    if (pI830->pipeMon[1] != NULL) {
+	I830InjectProbedModes(pScrn, &pScrn->modes, pI830->pipeMon[1]->Modes);
+    } else {
+	I830InjectProbedModes(pScrn, &pScrn->modes, pI830->pipeMon[0]->Modes);
+    }
+    if (pScrn->modes == NULL) {
+	FatalError("No modes found\n");
+    }
 
-    /* availModes is of no more use as xf86ValidateModes has duplicated and
-     * saved everything it needs.
+    /* Don't let pScrn->modes have modes larger than the max root window size.
+     * We don't really care about the monitors having it, particularly since we
+     * eventually want randr to be able to move to those sizes.
      */
-    while (availModes != NULL)
-	xf86DeleteMode(&availModes, availModes);
+    i830xf86ValidateModesSize(pScrn, pScrn->modes,
+			      originalVirtualX, originalVirtualY,
+			      pScrn->displayWidth);
 
-    if (!first_time) {
-	/* Restore things that may have been damaged by xf86ValidateModes. */
-	pScrn->virtualX = saved_virtualX;
-	pScrn->virtualY = saved_virtualY;
-	pScrn->displayWidth = saved_displayWidth;
-    }
+    /* Strip out anything bad that we threw out for virtualX. */
+    i830xf86PruneInvalidModes(pScrn, &pScrn->modes, TRUE);
 
-    /* Need to do xf86CrtcForModes so any user-configured modes are valid for
-     * non-LVDS.
+    /* For some reason, pScrn->modes is circular, unlike the other mode lists.
+     * How great is that?
      */
-    xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
+    last = i830GetModeListTail(pScrn->modes);
+    last->next = pScrn->modes;
+    pScrn->modes->prev = last;
 
-    xf86PruneDriverModes(pScrn);
+#if 0
+    /* XXX: do I need this any more?  Maybe XF86VidMode uses it?
+     * Set up the ClockRanges, which describe what clock ranges are available,
+     * and what sort of modes they can be used for.
+     */
+    clockRanges = xnfcalloc(sizeof(ClockRange), 1);
+    clockRanges->next = NULL;
+    clockRanges->minClock = 25000;
+    clockRanges->maxClock = pI830->MaxClock;
+    clockRanges->clockIndex = -1;		/* programmable */
+    clockRanges->interlaceAllowed = TRUE;	/* XXX check this */
+    clockRanges->doubleScanAllowed = FALSE;	/* XXX check this */
+#endif
 
 #if DEBUG_REPROBE
     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Modes post revalidate\n");
@@ -858,49 +1013,12 @@ I830ValidateXF86ModeList(ScrnInfoPtr pSc
     } while (0);
 #endif
 
-    /* Try to find the closest equivalent of the previous mode pointer to switch
-     * to.
-     */
-    if (saved_mode != NULL) {
-	DisplayModePtr pBestMode = NULL, pMode;
-
-	/* XXX: Is finding a matching x/y res enough?  probably not. */
-	for (pMode = pScrn->modes; ; pMode = pMode->next) {
-	    if (pMode->HDisplay == saved_mode->HDisplay &&
-		pMode->VDisplay == saved_mode->VDisplay)
-	    {
-		ErrorF("found matching mode %p\n", pMode);
-		pBestMode = pMode;
-	    }
-	    if (pMode->next == pScrn->modes)
-		break;
-	}
-
-	if (pBestMode != NULL)
-		xf86SwitchMode(pScrn->pScreen, pBestMode);
-	else
-		FatalError("No suitable modes after re-probe\n");
-
-	xfree(saved_mode->name);
-	xfree(saved_mode);
-    }
-
-    /* If we've enabled/disabled some pipes, we need to reset cloning mode
-     * support.
+    /* Save a pointer to the previous current mode.  We can't reset
+     * pScrn->currentmode, because we rely on xf86SwitchMode's shortcut not
+     * happening so we can hot-enable devices at SwitchMode.  We'll notice this
+     * case at SwitchMode and free the saved mode.
      */
-    if (pipes_reconfigured) {
-	if ((pI830->operatingDevices & 0x00ff) &&
-	    (pI830->operatingDevices & 0xff00))
-	{
-	    pI830->Clone = TRUE;
-	} else {
-	    pI830->Clone = FALSE;
-	}
-
-	/* If HW cursor currently showing, reset cursor state */
-	if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn)
-	    pI830->CursorInfoRec->ShowCursor(pScrn);
-    }
+    pI830->savedCurrentMode = saved_mode;
 
-    return n;
+    return 1; /* XXX */
 }
diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c
index 16a8cd8..6f620c8 100644
--- a/src/i830_xf86Modes.c
+++ b/src/i830_xf86Modes.c
@@ -238,6 +238,126 @@ PrintModeline(int scrnIndex,DisplayModeP
     xfree(flags);
 }
 
+/**
+ * Marks as bad any modes with unsupported flags.
+ *
+ * \param modeList doubly-linked or circular list of modes.
+ * \param flags flags supported by the driver.
+ *
+ * \bug only V_INTERLACE and V_DBLSCAN are supported.  Is that enough?
+ *
+ * This is not in xf86Modes.c, but would be part of the proposed new API.
+ */
+void
+i830xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+			    int flags)
+{
+    DisplayModePtr mode;
+
+    for (mode = modeList; mode != NULL; mode = mode->next) {
+	if (mode->Flags & V_INTERLACE && !(flags & V_INTERLACE))
+	    mode->status = MODE_NO_INTERLACE;
+	if (mode->Flags & V_DBLSCAN && !(flags & V_DBLSCAN))
+	    mode->status = MODE_NO_DBLESCAN;
+    }
+}
+
+/**
+ * Marks as bad any modes extending beyond the given max X, Y, or pitch.
+ *
+ * \param modeList doubly-linked or circular list of modes.
+ *
+ * This is not in xf86Modes.c, but would be part of the proposed new API.
+ */
+void
+i830xf86ValidateModesSize(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+			  int maxX, int maxY, int maxPitch)
+{
+    DisplayModePtr mode;
+
+    for (mode = modeList; mode != NULL; mode = mode->next) {
+	if (maxPitch > 0 && mode->HDisplay > maxPitch)
+	    mode->status = MODE_BAD_WIDTH;
+
+	if (maxX > 0 && mode->HDisplay > maxX)
+	    mode->status = MODE_VIRTUAL_X;
+
+	if (maxY > 0 && mode->VDisplay > maxY)
+	    mode->status = MODE_VIRTUAL_Y;
+
+	if (mode->next == modeList)
+	    break;
+    }
+}
+
+/**
+ * Marks as bad any modes extending beyond outside of the given clock ranges.
+ *
+ * \param modeList doubly-linked or circular list of modes.
+ * \param min pointer to minimums of clock ranges
+ * \param max pointer to maximums of clock ranges
+ * \param n_ranges number of ranges.
+ *
+ * This is not in xf86Modes.c, but would be part of the proposed new API.
+ */
+void
+i830xf86ValidateModesClocks(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+			    int *min, int *max, int n_ranges)
+{
+    DisplayModePtr mode;
+    int i;
+
+    for (mode = modeList; mode != NULL; mode = mode->next) {
+	Bool good = FALSE;
+	for (i = 0; i < n_ranges; i++) {
+	    if (mode->Clock >= min[i] && mode->Clock <= max[i]) {
+		good = TRUE;
+		break;
+	    }
+	}
+	if (!good)
+	    mode->status = MODE_CLOCK_RANGE;
+    }
+}
+
+/**
+ * Frees any modes from the list with a status other than MODE_OK.
+ *
+ * \param modeList pointer to a doubly-linked or circular list of modes.
+ * \param verbose determines whether the reason for mode invalidation is
+ *	  printed.
+ *
+ * This is not in xf86Modes.c, but would be part of the proposed new API.
+ */
+void
+i830xf86PruneInvalidModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList,
+			  Bool verbose)
+{
+    DisplayModePtr mode;
+
+    for (mode = *modeList; mode != NULL;) {
+	DisplayModePtr next = mode->next;
+
+	if (mode->status != MODE_OK) {
+	    if (verbose) {
+		char *type = "";
+		if (mode->type & M_T_BUILTIN)
+		    type = "built-in ";
+		else if (mode->type & M_T_DEFAULT)
+		    type = "default ";
+		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+			   "Not using %smode \"%s\" (%s)\n", type, mode->name,
+			   xf86ModeStatusToString(mode->status));
+	    }
+	    xf86DeleteMode(modeList, mode);
+	}
+
+	if (next == *modeList)
+	    break;
+	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
 
diff --git a/src/i830_xf86Modes.h b/src/i830_xf86Modes.h
index ba7d820..86e5b06 100644
--- a/src/i830_xf86Modes.h
+++ b/src/i830_xf86Modes.h
@@ -35,6 +35,26 @@ Bool
 I830ModesEqual(DisplayModePtr pMode1, DisplayModePtr pMode2);
 
 void
+i830xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+			    int flags);
+
+void
+i830xf86ValidateModesClocks(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+			    int *min, int *max, int n_ranges);
+
+void
+i830xf86ValidateModesSize(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+			  int maxX, int maxY, int maxPitch);
+
+void
+i830xf86PruneInvalidModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList,
+			  Bool verbose);
+
+void
+i830xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+			    int flags);
+
+void
 PrintModeline(int scrnIndex,DisplayModePtr mode);
 
 extern DisplayModeRec I830xf86DefaultModes[];
diff-tree 9fbd3d8f4befb75ed6f6bd9a9ffe0175626e8785 (from 56f7aedd0ad1f5645a90a5509b1263ec6b7b7ee1)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Tue Jun 27 23:31:40 2006 +0200

    If the panel power registers are all zeroes on Mobile parts, disable LVDS.
    
    This is the case on the Mac mini, which is an i945GM but has no LVDS attached.
    Powering on with the power timing registers zeroed would probably be a bad idea,
    even if there was a panel attached.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 6b7dfc7..ca87951 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1701,6 +1701,18 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
    if (!i830GetLVDSInfoFromBIOS(pScrn))
       has_lvds = FALSE;
 
+   /* If the panel sequencing, status, and control registers are all zero,
+    * assume there's no panel attached.  This is the case on the Mac mini,
+    * which is an i945GM but has no LVDS.  If we tried to power something on
+    * with zeroed panel sequencing registers, it probably wouldn't be a good
+    * thing anyway.
+    */
+   if (INREG(PP_STATUS) == 0 && INREG(PP_CONTROL) == 0 &&
+       INREG(LVDSPP_ON) == 0 && INREG(LVDSPP_OFF) == 0)
+   {
+      has_lvds = FALSE;
+   }
+
    if ((s = xf86GetOptValString(pI830->Options, OPTION_MONITOR_LAYOUT)) &&
       I830IsPrimary(pScrn)) {
       char *Mon1;
diff-tree 56f7aedd0ad1f5645a90a5509b1263ec6b7b7ee1 (from 7104b915da412a26661bab7b5a940e935e8cbc8a)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Tue Jun 27 00:37:56 2006 +0200

    Fix randr current mode reporting and mode loss/mis-configuration on re-randr.

diff --git a/src/i830.h b/src/i830.h
index 11015bf..9bd0227 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -606,6 +606,7 @@ Bool I830RandRInit(ScreenPtr pScreen, in
 Bool I830RandRSetConfig(ScreenPtr pScreen, Rotation rotation, int rate,
 			RRScreenSizePtr pSize);
 Rotation I830GetRotation(ScreenPtr pScreen);
+void I830GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y);
 
 /*
  * 12288 is set as the maximum, chosen because it is enough for
diff --git a/src/i830_display.c b/src/i830_display.c
index 1391c28..8080c55 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -285,32 +285,39 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	        continue;
 	    }
 	    /* Find if it's closer than the current best option */
-	    if (abs(pScan->VRefresh - pMode->VRefresh) >
-		abs(pBest->VRefresh - pMode->VRefresh))
+	    if ((pScan->HDisplay >= pBest->HDisplay && 
+		pScan->HDisplay >= pBest->HDisplay) ||
+		(fabs(pScan->VRefresh - pMode->VRefresh) <
+		fabs(pBest->VRefresh - pMode->VRefresh)))
 	    {
-		continue;
+		pBest = pScan;
 	    }
 	}
 	if (pBest != NULL) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		       "Choosing pipe's mode %p (%dx%dx%.1f) instead of xf86 "
-		       "mode %p (%dx%dx%.1f)\n", pBest,
+		       "Choosing pipe %d's mode %dx%d@%.1f instead of xf86 "
+		       "mode %dx%d@%.1f\n", pipe,
 		       pBest->HDisplay, pBest->VDisplay, pBest->VRefresh,
-		       pMode,
 		       pMode->HDisplay, pMode->VDisplay, pMode->VRefresh);
 	    pMode = pBest;
 	}
     }
-    if (I830ModesEqual(&pI830->pipeCurMode[pipe], pMode))
-	return TRUE;
-
-    ErrorF("Requested pix clock: %d\n", pMode->Clock);
-
     if (pipe == 0)
 	outputs = pI830->operatingDevices & 0xff;
     else
 	outputs = (pI830->operatingDevices >> 8) & 0xff;
 
+    if (outputs & PIPE_LCD_ACTIVE) {
+	if (I830ModesEqual(&pI830->pipeCurMode[pipe], pMasterMode))
+	    return TRUE;
+    } else {
+	if (I830ModesEqual(&pI830->pipeCurMode[pipe], pMode))
+	    return TRUE;
+    }
+
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested pix clock: %d\n",
+	       pMode->Clock);
+
     if ((outputs & PIPE_LCD_ACTIVE) && (outputs & ~PIPE_LCD_ACTIVE)) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		   "Can't enable LVDS and non-LVDS on the same pipe\n");
@@ -622,7 +629,11 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	OUTREG(SDVOC, sdvoc);
     }
 
-    pI830->pipeCurMode[pipe] = *pMode;
+    if (outputs & PIPE_LCD_ACTIVE) {
+	pI830->pipeCurMode[pipe] = *pMasterMode;
+    } else {
+	pI830->pipeCurMode[pipe] = *pMode;
+    }
 
     return TRUE;
 }
diff --git a/src/i830_modes.c b/src/i830_modes.c
index 6ee1a94..893ef10 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -43,12 +43,12 @@
 #include <stdio.h>
 #include <string.h>
 #include <assert.h>
+#include <math.h>
 
 #include "xf86.h"
 #include "i830.h"
 #include "i830_xf86Modes.h"
-
-#include <math.h>
+#include <randrstr.h>
 
 #define rint(x) floor(x)
 
@@ -415,11 +415,6 @@ i830FPNativeMode(ScrnInfoPtr pScrn)
 
    new->type       = M_T_USERDEF;
 
-   pScrn->virtualX = MAX(pScrn->virtualX, pI830->PanelXRes);
-   pScrn->virtualY = MAX(pScrn->virtualY, pI830->PanelYRes);
-   pScrn->display->virtualX = pScrn->virtualX;
-   pScrn->display->virtualY = pScrn->virtualY;
-
    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 	      "No valid mode specified, force to native mode\n");
 
@@ -450,9 +445,6 @@ i830GetLVDSModes(ScrnInfoPtr pScrn, char
    int             count      = 0;
    int             i, width, height;
 
-   pScrn->virtualX = pScrn->display->virtualX;
-   pScrn->virtualY = pScrn->display->virtualY;
-
    /* We have a flat panel connected to the primary display, and we
     * don't have any DDC info.
     */
@@ -733,6 +725,7 @@ I830ValidateXF86ModeList(ScrnInfoPtr pSc
     DisplayModePtr saved_mode, availModes = NULL;
     int saved_virtualX = 0, saved_virtualY = 0, saved_displayWidth = 0;
     Bool pipes_reconfigured = FALSE;
+    int originalVirtualX, originalVirtualY;
 
     for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++) {
 	I830ReprobePipeModeList(pScrn, pipe);
@@ -810,6 +803,8 @@ I830ValidateXF86ModeList(ScrnInfoPtr pSc
 	saved_displayWidth = pScrn->displayWidth;
     }
 
+    I830GetOriginalVirtualSize(pScrn, &originalVirtualX, &originalVirtualY);
+
     /* Take the pScrn->monitor->Modes we've accumulated and validate them into
      * pScrn->modes.
      * XXX: Should set up a scrp->monitor->DDC covering the union of the
@@ -825,8 +820,8 @@ I830ValidateXF86ModeList(ScrnInfoPtr pSc
 			  64 * pScrn->bitsPerPixel, /* pitchInc */
 			  200, /* minHeight */
 			  MAX_DISPLAY_HEIGHT, /* maxHeight */
-			  pScrn->virtualX, /* virtualX */
-			  pScrn->virtualY, /* virtualY */
+			  originalVirtualX, /* virtualX maximum */
+			  originalVirtualY, /* virtualY maximum */
 			  pI830->FbMapSize, /* apertureSize */
 			  LOOKUP_BEST_REFRESH /* strategy */);
 
diff --git a/src/i830_randr.c b/src/i830_randr.c
index 93c0519..4c7c087 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -35,6 +35,7 @@
 #include <randrstr.h>
 
 #include "i830.h"
+#include "i830_xf86Modes.h"
 
 typedef struct _i830RandRInfo {
     int				    virtualX;
@@ -100,9 +101,13 @@ I830RandRGetInfo (ScreenPtr pScreen, Rot
 	if (!pSize)
 	    return FALSE;
 	RRRegisterRate (pScreen, pSize, refresh);
-	if (mode == scrp->currentMode &&
-	    mode->HDisplay == scrp->virtualX && mode->VDisplay == scrp->virtualY)
+
+	if (I830ModesEqual(mode, scrp->currentMode) &&
+	    mode->HDisplay == scrp->virtualX &&
+	    mode->VDisplay == scrp->virtualY)
+	{
 	    RRSetCurrentConfig (pScreen, randrp->rotation, refresh, pSize);
+	}
 	if (mode->next == scrp->modes)
 	    break;
     }
@@ -116,7 +121,6 @@ I830RandRGetInfo (ScreenPtr pScreen, Rot
     if (scrp->currentMode->HDisplay != randrp->virtualX ||
 	scrp->currentMode->VDisplay != randrp->virtualY)
     {
-	mode = scrp->modes;
 	pSize = RRRegisterSize (pScreen,
 				randrp->virtualX, randrp->virtualY,
 				randrp->mmWidth,
@@ -164,6 +168,7 @@ I830RandRSetMode (ScreenPtr	    pScreen,
 	scrp->virtualX = mode->HDisplay;
 	scrp->virtualY = mode->VDisplay;
     }
+
     if(randrp->rotation & (RR_Rotate_90 | RR_Rotate_270))
     {
 	/* If the screen is rotated 90 or 270 degrees, swap the sizes. */
@@ -356,3 +361,21 @@ I830RandRInit (ScreenPtr    pScreen, int
 
     return TRUE;
 }
+
+void
+I830GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y)
+{
+    ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
+
+    if (i830RandRGeneration != serverGeneration ||
+	XF86RANDRINFO(pScreen)->virtualX == -1)
+    {
+	*x = pScrn->virtualX;
+	*y = pScrn->virtualY;
+    } else {
+	XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
+
+	*x = randrp->virtualX;
+	*y = randrp->virtualY;
+    }
+}
diff-tree b85f268051a785f90e4c55bd1cac80d673388f16 (from 6a3f89f4b6035534c7b93a4c05fd704305349785)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Jun 26 16:26:58 2006 +0200

    Fix remaining warning.

diff --git a/src/i830_memory.c b/src/i830_memory.c
index 50bbde5..c1c7cb7 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -874,7 +874,7 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
 	 return FALSE;
       } else {
 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Successful allocate "
-		       "offscreen memory at 0x%lx, size %d KB\n", 
+		       "offscreen memory at 0x%lx, size %ld KB\n", 
 			pI830->Offscreen.Start, pI830->Offscreen.Size/1024);
       }
 #endif
diff-tree 6a3f89f4b6035534c7b93a4c05fd704305349785 (from parents)
Merge: 3cdc53797bf6fdbfbcb53e07b269a5071f5ec97d e7723a4e5725147d3bd9ba22c5a3314b0556e440
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Jun 26 16:25:58 2006 +0200

    Merge branch 'master' into exa
    
    Conflicts:
    
    	src/i830.h

diff --cc src/i830.h
index ff82c73,79eb310..d0f8bc0
@@@ -491,8 -474,16 +494,19 @@@
  extern Bool I830Rotate(ScrnInfoPtr pScrn, DisplayModePtr mode);
  extern Bool I830FixOffset(ScrnInfoPtr pScrn, I830MemRange *mem);
  
 +extern void i830MarkSync(ScrnInfoPtr pScrn);
 +extern void i830WaitSync(ScrnInfoPtr pScrn);
++
+ /* i830_memory.c */
+ Bool I830BindAGPMemory(ScrnInfoPtr pScrn);
+ Bool I830UnbindAGPMemory(ScrnInfoPtr pScrn);
+ 
+ /* i830_randr.c */
+ Bool I830RandRInit(ScreenPtr pScreen, int rotation);
+ Bool I830RandRSetConfig(ScreenPtr pScreen, Rotation rotation, int rate,
+ 			RRScreenSizePtr pSize);
+ Rotation I830GetRotation(ScreenPtr pScreen);
+ 
  /*
   * 12288 is set as the maximum, chosen because it is enough for
   * 1920x1440 at 32bpp with a 2048 pixel line pitch with some to spare.
diff --cc src/i830_dri.c
index d73c84a,7c5f795..5653434
@@@ -1176,38 -1180,10 +1178,9 @@@
        DEALLOCATE_LOCAL(pptNew1);
        DEALLOCATE_LOCAL(pboxNew1);
     }
 -
 -   pI830->AccelInfoRec->NeedToSync = TRUE;
 +   i830MarkSync(pScrn);
  }
  
- extern I830EmitInvarientState(ScrnInfoPtr pScrn);
- extern I915EmitInvarientState(ScrnInfoPtr pScrn);
- 
- /* Initialize the first context */
- void
- IntelEmitInvarientState(ScrnInfoPtr pScrn)
- {
-    I830Ptr pI830 = I830PTR(pScrn);
-    CARD32 ctx_addr;
- 
-    ctx_addr = pI830->ContextMem.Start;
-    /* Align to a 2k boundry */
-    ctx_addr = ((ctx_addr + 2048 - 1) / 2048) * 2048;
- 
-    {
-       BEGIN_LP_RING(2);
-       OUT_RING(MI_SET_CONTEXT);
-       OUT_RING(ctx_addr |
- 	       CTXT_NO_RESTORE |
- 	       CTXT_PALETTE_SAVE_DISABLE | CTXT_PALETTE_RESTORE_DISABLE);
-       ADVANCE_LP_RING();
-    }
- 
-    if (IS_I9XX(pI830))
-       I915EmitInvarientState(pScrn);
-    else
-       I830EmitInvarientState(pScrn);
- }
- 
  /* Use callbacks from dri.c to support pageflipping mode for a single
   * 3d context without need for any specific full-screen extension.
   *
diff-tree 3cdc53797bf6fdbfbcb53e07b269a5071f5ec97d (from d7e5d996aa123e52857362fa8a1e69f709bfe218)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Jun 26 16:23:55 2006 +0200

    Fix build with new EXA headers.

diff --git a/src/i830_exa.c b/src/i830_exa.c
index 7212972..665c4d7 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -149,7 +149,7 @@ I830EXAPrepareSolid(PixmapPtr pPixmap, i
     I830Ptr pI830 = I830PTR(pScrn);
     unsigned long offset, pitch;
 
-    if (planemask != (Pixel)~0 && !EXA_PM_IS_SOLID(pPixmap, planemask))
+    if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planemask))
 	I830FALLBACK("planemask is not solid");
 
     offset = exaGetPixmapOffset(pPixmap);
@@ -234,7 +234,7 @@ I830EXAPrepareCopy(PixmapPtr pSrcPixmap,
     ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
 
-    if (planemask != (Pixel)~0 && !EXA_PM_IS_SOLID(pSrcPixmap, planemask))
+    if (!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planemask))
 	I830FALLBACK("planemask is not solid");
 
     pI830->copy_src_pitch = exaGetPixmapPitch(pSrcPixmap);
diff-tree 7104b915da412a26661bab7b5a940e935e8cbc8a (from 21dc3edfc41987bb8cf0f8d265fba9775cbe8cdb)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Jun 26 15:11:13 2006 +0200

    Clean up warnings.

diff --git a/src/i830_debug.c b/src/i830_debug.c
index 6d43cd6..e2a28b2 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -32,8 +32,8 @@
 #include "xf86.h"
 #include "xf86_ansic.h"
 #include "i830.h"
+#include "i830_debug.h"
 
-/* XXX: What was the syntax for sticking quotes around the "reg" argument? */
 #define DEFINEREG(reg) \
 	{ reg, #reg, 0 }
 
diff --git a/src/i830_display.c b/src/i830_display.c
index 05b7655..1391c28 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -919,7 +919,7 @@ i830LoadDetectCRT(ScrnInfoPtr pScrn)
  * This takes approximately 5ms in testing on an i915GM, with CRT connected or
  * not.
  */
-Bool
+static Bool
 i830DDCDetectCRT(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 7af5fb7..6b7dfc7 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1101,7 +1101,7 @@ I830SetupOutputBusses(ScrnInfoPtr pScrn)
    pI830->num_outputs = i;
 }
 
-void 
+static void 
 I830PreInitDDC(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
@@ -1128,7 +1128,8 @@ I830PreInitDDC(ScrnInfoPtr pScrn)
    }
 }
 
-void I830DetectMonitors(ScrnInfoPtr pScrn)
+static void
+I830DetectMonitors(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
    int i;
diff --git a/src/i830_modes.c b/src/i830_modes.c
index a43fa61..6ee1a94 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -181,7 +181,7 @@ I830DuplicateMode(DisplayModePtr pMode)
 /* This function will sort all modes according to their resolution.
  * Highest resolution first.
  */
-void
+static void
 I830xf86SortModes(DisplayModePtr new, DisplayModePtr *first,
 	      DisplayModePtr *last)
 {
@@ -246,7 +246,8 @@ I830GetVESAEstablishedMode(ScrnInfoPtr p
     return NULL;
 }
 
-DisplayModePtr I830GetDDCModes(ScrnInfoPtr pScrn, xf86MonPtr ddc)
+static DisplayModePtr
+I830GetDDCModes(ScrnInfoPtr pScrn, xf86MonPtr ddc)
 {
     DisplayModePtr  last  = NULL;
     DisplayModePtr  new   = NULL;
@@ -438,7 +439,7 @@ i830FPNativeMode(ScrnInfoPtr pScrn)
  *
  * \return doubly-linked list of modes.
  */
-DisplayModePtr
+static DisplayModePtr
 i830GetLVDSModes(ScrnInfoPtr pScrn, char **ppModeName)
 {
    I830Ptr pI830 = I830PTR(pScrn);
@@ -541,7 +542,7 @@ i830GetLVDSModes(ScrnInfoPtr pScrn, char
  * it into the doubly-linked modeList.  We don't need to filter, because the
  * eventual call to xf86ValidateModes will do this for us.  I think.
  */
-int
+static int
 I830InjectProbedModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList,
 		      DisplayModePtr addModes)
 {
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 06840ef..9a18f57 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -31,6 +31,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "xf86_OSproc.h"
 #include "compiler.h"
 #include "i830.h"
+#include "i830_display.h"
 #include "i830_sdvo_regs.h"
 
 CARD16 curr_table[6];
@@ -170,7 +171,7 @@ I830SDVOReadInputRegs(I830SDVOPtr s)
  * PROM.  It resets from the DDC bus back to internal registers at the next I2C
  * STOP.  PROM access is terminated by accessing an internal register.
  */
-Bool
+static Bool
 I830SDVOSetControlBusSwitch(I830SDVOPtr s, CARD8 target)
 {
     memset(s->sdvo_regs, 0, 9);
@@ -277,7 +278,7 @@ I830SDVOSetTargetOutput(I830SDVOPtr s, B
 }
 
 /* Fetches either input or output timings to *dtd, depending on cmd. */
-Bool
+static Bool
 I830SDVOGetTimings(I830SDVOPtr s, i830_sdvo_dtd *dtd, CARD8 cmd)
 {
     memset(s->sdvo_regs, 0, 9);
@@ -312,7 +313,7 @@ I830SDVOGetTimings(I830SDVOPtr s, i830_s
 }
 
 /* Sets either input or output timings to *dtd, depending on cmd. */
-Bool
+static Bool
 I830SDVOSetTimings(I830SDVOPtr s, i830_sdvo_dtd *dtd, CARD8 cmd)
 {
     memset(s->sdvo_regs, 0, 9);
diff-tree 21dc3edfc41987bb8cf0f8d265fba9775cbe8cdb (from parents)
Merge: f113e9002cf53510e30984f816d44b06f1e71216 5111b883480a5a9cc82200f2684cba67b515aa73
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Jun 26 15:06:42 2006 +0200

    Merge branch 'master' into modesetting
    
    Conflicts:
    
    	src/i830.h

diff --cc src/i830.h
index b3a0895,5315dff..11015bf
@@@ -587,21 -469,18 +587,26 @@@
 -extern int I830GetBestRefresh(ScrnInfoPtr pScrn, int refresh);
  extern Bool I830CheckModeSupport(ScrnInfoPtr pScrn, int x, int y, int mode);
  extern Bool I830Rotate(ScrnInfoPtr pScrn, DisplayModePtr mode);
  extern Bool I830FixOffset(ScrnInfoPtr pScrn, I830MemRange *mem);
- extern Bool I830BindAGPMemory(ScrnInfoPtr pScrn);
- extern Bool I830UnbindAGPMemory(ScrnInfoPtr pScrn);
- extern Bool I830RandRSetConfig(ScreenPtr pScreen, Rotation rotation,
- 			       int rate, RRScreenSizePtr pSize);
- extern Rotation I830GetRotation(ScreenPtr pScreen);
- extern Bool I830RandRInit(ScreenPtr pScreen, int rotation);
 +extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg,
 +			char *name);
- /* i830_modes.c */
- int I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time);
+ 
+ /* i830_memory.c */
+ Bool I830BindAGPMemory(ScrnInfoPtr pScrn);
+ Bool I830UnbindAGPMemory(ScrnInfoPtr pScrn);
  
 +/* i830_gtf.c */
 +DisplayModePtr i830GetGTF(int h_pixels, int v_lines, float freq,
 +			  int interlaced, int margins);
 +
++/* i830_modes.c */
++int I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time);
++
+ /* i830_randr.c */
+ Bool I830RandRInit(ScreenPtr pScreen, int rotation);
+ Bool I830RandRSetConfig(ScreenPtr pScreen, Rotation rotation, int rate,
+ 			RRScreenSizePtr pSize);
+ Rotation I830GetRotation(ScreenPtr pScreen);
+ 
  /*
   * 12288 is set as the maximum, chosen because it is enough for
   * 1920x1440 at 32bpp with a 2048 pixel line pitch with some to spare.
diff-tree f113e9002cf53510e30984f816d44b06f1e71216 (from 0e5cda3796ba0164496f0814eb57d1dfa7ab9257)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Jun 26 12:54:30 2006 +0200

    Fix the plane/pipe disabling and turn off missing outputs when no longer DDCed.

diff --git a/src/i830_display.c b/src/i830_display.c
index 4719cef..05b7655 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -633,8 +633,6 @@ i830DisableUnusedFunctions(ScrnInfoPtr p
     I830Ptr pI830 = I830PTR(pScrn);
     int outputsA, outputsB;
 
-    return;
-
     outputsA = pI830->operatingDevices & 0xff;
     outputsB = (pI830->operatingDevices >> 8) & 0xff;
 
@@ -644,7 +642,7 @@ i830DisableUnusedFunctions(ScrnInfoPtr p
     if ((outputsA & PIPE_CRT_ACTIVE) == 0 &&
 	(outputsB & PIPE_CRT_ACTIVE) == 0)
     {
-	CARD32 adpa = INREG(adpa);
+	CARD32 adpa = INREG(ADPA);
 
 	if (adpa & ADPA_DAC_ENABLE) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling CRT output\n");
@@ -704,6 +702,8 @@ i830DisableUnusedFunctions(ScrnInfoPtr p
 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling DPLL A\n");
 	    OUTREG(DPLL_A, dpll & ~DPLL_VCO_ENABLE);
 	}
+
+	memset(&pI830->pipeCurMode[0], 0, sizeof(pI830->pipeCurMode[0]));
     }
 
     if (!pI830->planeEnabled[1]) {
@@ -729,6 +729,8 @@ i830DisableUnusedFunctions(ScrnInfoPtr p
 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling DPLL B\n");
 	    OUTREG(DPLL_B, dpll & ~DPLL_VCO_ENABLE);
 	}
+
+	memset(&pI830->pipeCurMode[1], 0, sizeof(pI830->pipeCurMode[1]));
     }
 }
 
diff --git a/src/i830_modes.c b/src/i830_modes.c
index fe28c7a..a43fa61 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -603,7 +603,9 @@ I830ReprobePipeModeList(ScrnInfoPtr pScr
     int i;
     int outputs;
     DisplayModePtr pMode;
+    Bool had_modes;
 
+    had_modes = (pI830->pipeModes[pipe] != NULL);
     while (pI830->pipeModes[pipe] != NULL)
 	xf86DeleteMode(&pI830->pipeModes[pipe], pI830->pipeModes[pipe]);
 
@@ -650,6 +652,14 @@ I830ReprobePipeModeList(ScrnInfoPtr pScr
 	{
 	    I830xf86SetModeCrtc(pMode, INTERLACE_HALVE_V);
 	}
+	if (had_modes && pI830->pipeModes[pipe] == NULL) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		       "Failed to DDC pipe %d, disabling output\n", pipe);
+	    if (pipe == 0)
+		pI830->operatingDevices &= ~0x00ff;
+	    else
+		pI830->operatingDevices &= ~0xff00;
+	}
     } else {
 	ErrorF("don't know how to get modes for this device.\n");
     }
diff-tree 0e5cda3796ba0164496f0814eb57d1dfa7ab9257 (from 51d14f803aae6d0a738520c3cad110289ee444db)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Jun 26 10:30:46 2006 +0200

    Fix FP scaling by using the desired mode to get at the real [HV]Display.

diff --git a/src/i830_display.c b/src/i830_display.c
index a96e6ee..4719cef 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -262,6 +262,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     Bool ok, is_sdvo;
     int refclk, pixel_clock, sdvo_pixel_multiply;
     int outputs;
+    DisplayModePtr pMasterMode = pMode;
 
     assert(pMode->VRefresh != 0.0);
     /* If we've got a list of modes probed for the device, find the best match
@@ -341,8 +342,8 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     vtot = (pMode->CrtcVDisplay - 1) | ((pMode->CrtcVTotal - 1) << 16);
     vblank = (pMode->CrtcVBlankStart - 1) | ((pMode->CrtcVBlankEnd - 1) << 16);
     vsync = (pMode->CrtcVSyncStart - 1) | ((pMode->CrtcVSyncEnd - 1) << 16);
-    pipesrc = ((pMode->HDisplay - 1) << 16) | (pMode->VDisplay - 1);
-    dspsize = ((pMode->VDisplay - 1) << 16) | (pMode->HDisplay - 1);
+    pipesrc = ((pMasterMode->HDisplay - 1) << 16) | (pMasterMode->VDisplay - 1);
+    dspsize = ((pMasterMode->VDisplay - 1) << 16) | (pMasterMode->HDisplay - 1);
     pixel_clock = pMode->Clock;
     if (outputs & PIPE_LCD_ACTIVE && pI830->panel_fixed_hactive != 0)
     {
@@ -369,17 +370,6 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	vsync = (pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff - 1) |
 		((pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff +
 		  pI830->panel_fixed_vsyncwidth - 1) << 16);
-	/* Hack until we get better clone-mode modesetting.  If the mode to be
-	 * programmed is larger than the size of the panel, only display the
-	 * size of the panel.
-	 */
-	if (pMode->HDisplay > pI830->panel_fixed_hactive || 
-	    pMode->VDisplay > pI830->panel_fixed_vactive) {
-	    dspsize = ((pI830->panel_fixed_vactive - 1) << 16) |
-		      (pI830->panel_fixed_hactive - 1);
-	    pipesrc = ((pI830->panel_fixed_hactive - 1) << 16) |
-		      (pI830->panel_fixed_vactive - 1);
-	}
 	pixel_clock = pI830->panel_fixed_clock;
     }
 
diff-tree 51d14f803aae6d0a738520c3cad110289ee444db (from d2c18d8d79596513149273e4a0d322f04bf27e80)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Jun 26 10:21:23 2006 +0200

    Add a function to turn off unused outputs, DPLLs, planes, and pipes.

diff --git a/src/i830_display.c b/src/i830_display.c
index 1546c37..a96e6ee 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -637,6 +637,111 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     return TRUE;
 }
 
+static void
+i830DisableUnusedFunctions(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    int outputsA, outputsB;
+
+    return;
+
+    outputsA = pI830->operatingDevices & 0xff;
+    outputsB = (pI830->operatingDevices >> 8) & 0xff;
+
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling unused functions\n");
+
+    /* First, disable the unused outputs */
+    if ((outputsA & PIPE_CRT_ACTIVE) == 0 &&
+	(outputsB & PIPE_CRT_ACTIVE) == 0)
+    {
+	CARD32 adpa = INREG(adpa);
+
+	if (adpa & ADPA_DAC_ENABLE) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling CRT output\n");
+	    OUTREG(ADPA, adpa & ~ADPA_DAC_ENABLE);
+	}
+    }
+
+    if ((outputsB & PIPE_LCD_ACTIVE) == 0) {
+	CARD32 pp_status = INREG(PP_STATUS);
+
+	if (pp_status & PP_ON) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling LVDS output\n");
+	    i830SetLVDSPanelPower(pScrn, FALSE);
+	}
+    }
+
+    if (IS_I9XX(pI830) && ((outputsA & PIPE_DFP_ACTIVE) == 0 &&
+	(outputsB & PIPE_DFP_ACTIVE) == 0))
+    {
+	CARD32 sdvob = INREG(SDVOB);
+	CARD32 sdvoc = INREG(SDVOC);
+
+	if (sdvob & SDVO_ENABLE) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling SDVOB output\n");
+	    OUTREG(SDVOB, sdvob & ~SDVO_ENABLE);
+	}
+	if (sdvoc & SDVO_ENABLE) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling SDVOC output\n");
+	    OUTREG(SDVOC, sdvoc & ~SDVO_ENABLE);
+	}
+    }
+
+    /* 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.
+     */
+    if (!pI830->planeEnabled[0]) {
+	CARD32 dspcntr, pipeconf, dpll;
+
+	dspcntr = INREG(DSPACNTR);
+	if (dspcntr & DISPLAY_PLANE_ENABLE) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling plane A\n");
+	    OUTREG(DSPACNTR, dspcntr & ~DISPLAY_PLANE_ENABLE);
+
+	    /* Wait for vblank for the disable to take effect */
+	    i830WaitForVblank(pScrn);
+	}
+
+	pipeconf = INREG(PIPEACONF);
+	if (pipeconf & PIPEACONF_ENABLE) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling pipe A\n");
+	   OUTREG(PIPEACONF, pipeconf & ~PIPEACONF_ENABLE);
+	}
+
+	dpll = INREG(DPLL_A);
+	if (dpll & DPLL_VCO_ENABLE) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling DPLL A\n");
+	    OUTREG(DPLL_A, dpll & ~DPLL_VCO_ENABLE);
+	}
+    }
+
+    if (!pI830->planeEnabled[1]) {
+	CARD32 dspcntr, pipeconf, dpll;
+
+	dspcntr = INREG(DSPBCNTR);
+	if (dspcntr & DISPLAY_PLANE_ENABLE) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling plane B\n");
+	    OUTREG(DSPBCNTR, dspcntr & ~DISPLAY_PLANE_ENABLE);
+
+	    /* Wait for vblank for the disable to take effect */
+	    i830WaitForVblank(pScrn);
+	}
+
+	pipeconf = INREG(PIPEBCONF);
+	if (pipeconf & PIPEBCONF_ENABLE) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling pipe B\n");
+	   OUTREG(PIPEBCONF, pipeconf & ~PIPEBCONF_ENABLE);
+	}
+
+	dpll = INREG(DPLL_B);
+	if (dpll & DPLL_VCO_ENABLE) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling DPLL B\n");
+	    OUTREG(DPLL_B, dpll & ~DPLL_VCO_ENABLE);
+	}
+    }
+}
+
 /**
  * This function sets the given mode on the active pipes.
  */
@@ -693,6 +798,8 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
 	       (int)(pMode->HDisplay * pMode->VDisplay *
 		     pMode->VRefresh / 1000000));
 
+    i830DisableUnusedFunctions(pScrn);
+
     planeA = INREG(DSPACNTR);
     planeB = INREG(DSPBCNTR);
 
diff-tree d2c18d8d79596513149273e4a0d322f04bf27e80 (from 6d1d105d68d9c25890c3fd2ebad1367529c2a991)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Jun 26 10:15:11 2006 +0200

    Fix DDC probing after last (untested) commit.

diff --git a/src/i830_modes.c b/src/i830_modes.c
index e1e5fd5..fe28c7a 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -182,41 +182,43 @@ I830DuplicateMode(DisplayModePtr pMode)
  * Highest resolution first.
  */
 void
-I830xf86SortModes(DisplayModePtr *new, DisplayModePtr *first,
+I830xf86SortModes(DisplayModePtr new, DisplayModePtr *first,
 	      DisplayModePtr *last)
 {
     DisplayModePtr  p;
 
     p = *last;
     while (p) {
-	if ((((*new)->HDisplay < p->HDisplay) &&
-	     ((*new)->VDisplay < p->VDisplay)) ||
-	    (((*new)->HDisplay == p->HDisplay) &&
-	     ((*new)->VDisplay == p->VDisplay) &&
-	     ((*new)->Clock < p->Clock))) {
-
-	    if (p->next) p->next->prev = *new;
-	    (*new)->prev = p;
-	    (*new)->next = p->next;
-	    p->next = *new;
-	    if (!((*new)->next)) *last = *new;
+	if (((new->HDisplay < p->HDisplay) &&
+	     (new->VDisplay < p->VDisplay)) ||
+	    ((new->HDisplay == p->HDisplay) &&
+	     (new->VDisplay == p->VDisplay) &&
+	     (new->Clock < p->Clock))) {
+
+	    if (p->next) 
+		p->next->prev = new;
+	    new->prev = p;
+	    new->next = p->next;
+	    p->next = new;
+	    if (!(new->next))
+		*last = new;
 	    break;
 	}
 	if (!p->prev) {
-	    (*new)->prev = NULL;
-	    (*new)->next = p;
-	    p->prev = *new;
-	    *first = *new;
+	    new->prev = NULL;
+	    new->next = p;
+	    p->prev = new;
+	    *first = new;
 	    break;
 	}
 	p = p->prev;
     }
 
     if (!*first) {
-	*first = *new;
-	(*new)->prev = NULL;
-	(*new)->next = NULL;
-	*last = *new;
+	*first = new;
+	new->prev = NULL;
+	new->next = NULL;
+	*last = new;
     }
 }
 
@@ -230,7 +232,7 @@ I830GetVESAEstablishedMode(ScrnInfoPtr p
 {
     DisplayModePtr pMode;
 
-    for (pMode = I830xf86DefaultModes; pMode->name != NULL; pMode = pMode->next)
+    for (pMode = I830xf86DefaultModes; pMode->name != NULL; pMode++)
     {
 	if (pMode->HDisplay == est_timings[i].hsize &&
 	    pMode->VDisplay == est_timings[i].vsize &&
@@ -301,7 +303,7 @@ DisplayModePtr I830GetDDCModes(ScrnInfoP
 		       new->HTotal, new->HSyncStart, new->HSyncEnd,
 		       new->VTotal, new->VSyncStart, new->VSyncEnd);
 
-	    I830xf86SortModes(&new, &first, &last);
+	    I830xf86SortModes(new, &first, &last);
 	}
     }
 
@@ -315,7 +317,11 @@ DisplayModePtr I830GetDDCModes(ScrnInfoP
 	new->status = MODE_OK;
 	new->type |= M_T_DEFAULT;
 
-	I830xf86SortModes(&new, &first, &last);
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		   "Valid Mode from standard timing table: %s\n",
+		   new->name);
+
+	I830xf86SortModes(new, &first, &last);
 #else
 	for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) {
 
@@ -342,7 +348,7 @@ DisplayModePtr I830GetDDCModes(ScrnInfoP
 			       "Valid Mode from standard timing table: %s\n",
 			       new->name);
 
-		    I830xf86SortModes(&new, &first, &last);
+		    I830xf86SortModes(new, &first, &last);
 		    break;
 		}
 	    }
@@ -354,11 +360,11 @@ DisplayModePtr I830GetDDCModes(ScrnInfoP
     tmp = (ddc->timings1.t1 << 8) | ddc->timings1.t2;
     for (j = 0; j < 16; j++) {
 	if (tmp & (1 << j)) {
-	    DisplayModePtr pNew;
-
-	    pNew = I830GetVESAEstablishedMode(pScrn, j);
-	    assert(pNew != NULL); /* We'd better have all the est. modes. */
-
+	    new = I830GetVESAEstablishedMode(pScrn, j);
+	    if (new == NULL) {
+		ErrorF("Couldn't get established mode %d\n", j);
+		continue;
+	    }
 	    new->status = MODE_OK;
 	    new->type = M_T_DEFAULT;
 
@@ -367,7 +373,7 @@ DisplayModePtr I830GetDDCModes(ScrnInfoP
 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Valid Mode from established "
 		       "timing table: %s\n", new->name);
 
-	    I830xf86SortModes(&new, &first, &last);
+	    I830xf86SortModes(new, &first, &last);
 	}
     }
 
@@ -643,7 +649,6 @@ I830ReprobePipeModeList(ScrnInfoPtr pScr
 	for (pMode = pI830->pipeModes[pipe]; pMode != NULL; pMode = pMode->next)
 	{
 	    I830xf86SetModeCrtc(pMode, INTERLACE_HALVE_V);
-	    pMode->VRefresh = I830ModeVRefresh(pMode);
 	}
     } else {
 	ErrorF("don't know how to get modes for this device.\n");
@@ -714,7 +719,7 @@ I830ValidateXF86ModeList(ScrnInfoPtr pSc
     I830Ptr pI830 = I830PTR(pScrn);
     ClockRangePtr clockRanges;
     int n, pipe;
-    DisplayModePtr saved_mode, availModes;
+    DisplayModePtr saved_mode, availModes = NULL;
     int saved_virtualX = 0, saved_virtualY = 0, saved_displayWidth = 0;
     Bool pipes_reconfigured = FALSE;
 
diff-tree 6d1d105d68d9c25890c3fd2ebad1367529c2a991 (from 52e8231a19f28bd4744f983aee2197a18c20aa3a)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Jun 26 10:14:27 2006 +0200

    Unset pipe current mode on EnterVT, so we reprogram the mode for sure.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 32beb8a..7af5fb7 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3954,10 +3954,13 @@ I830BIOSEnterVT(int scrnIndex, int flags
    ResetState(pScrn, FALSE);
    SetHWOperatingState(pScrn);
 
+   /* Mark that we'll need to re-set the mode for sure */
+   memset(pI830->pipeCurMode, 0, sizeof(pI830->pipeCurMode));
+
    /* Detect monitor change and switch to suitable mode */
    if (!pI830->starting)
       I830DetectMonitorChange(pScrn);
-	    
+
    if (!i830SetMode(pScrn, pScrn->currentMode))
       return FALSE;
    
diff-tree 52e8231a19f28bd4744f983aee2197a18c20aa3a (from f5e5f8aeddb3e0d6d073471aeff6176fb54576e2)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Jun 26 07:46:28 2006 +0200

    Major cleanup of mode reprobing:
    - Don't mess with pScrn->monitor->Modes, and instead make our own availModes.
    - Don't re-program the pipe with the same values (no flicker at xrandr)
    - Move a bunch of stuff that should be exposed through the public API (probably)
      to i830_xf86Modes.c
    - Use a table with established modes plus GTF to come up with modes from EDID,
      instead of trying to walk and find one in pScrn->monitor->Modes.  I think
      this is correct.
    - Reset clone state if we've detected new pipes, which should turn on the
      cursor.

diff --git a/src/Makefile.am b/src/Makefile.am
index 8970db1..f8aaad1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -63,8 +63,9 @@ i810_drv_la_SOURCES = \
          i830_video.c \
          i830_rotate.c \
 	 i830_randr.c \
-	 i830_sdvo.c
-
+	 i830_sdvo.c \
+	 i830_xf86Modes.h \
+	 i830_xf86Modes.c
 if DRI
 i810_drv_la_SOURCES += \
          i810_dri.c \
diff --git a/src/i830.h b/src/i830.h
index c4a4771..b3a0895 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -403,6 +403,7 @@ typedef struct _I830Rec {
    int planeEnabled[MAX_DISPLAY_PIPES];
    xf86MonPtr pipeMon[MAX_DISPLAY_PIPES];
    DisplayModePtr pipeModes[MAX_DISPLAY_PIPES];
+   DisplayModeRec pipeCurMode[MAX_DISPLAY_PIPES];
 
    /* Driver phase/state information */
    Bool preinit;
diff --git a/src/i830_display.c b/src/i830_display.c
index 50f4940..1546c37 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -35,6 +35,7 @@
 #include "i830_bios.h"
 #include "i830_display.h"
 #include "i830_debug.h"
+#include "i830_xf86Modes.h"
 
 /** Returns the pixel clock for the given refclk and divisors. */
 static int i830_clock(int refclk, int m1, int m2, int n, int p1, int p2)
@@ -299,6 +300,8 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	    pMode = pBest;
 	}
     }
+    if (I830ModesEqual(&pI830->pipeCurMode[pipe], pMode))
+	return TRUE;
 
     ErrorF("Requested pix clock: %d\n", pMode->Clock);
 
@@ -629,6 +632,8 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	OUTREG(SDVOC, sdvoc);
     }
 
+    pI830->pipeCurMode[pipe] = *pMode;
+
     return TRUE;
 }
 
diff --git a/src/i830_modes.c b/src/i830_modes.c
index faa843e..e1e5fd5 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -42,9 +42,11 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <assert.h>
 
 #include "xf86.h"
 #include "i830.h"
+#include "i830_xf86Modes.h"
 
 #include <math.h>
 
@@ -92,6 +94,8 @@ static struct
     {720, 400, 70},
 };
 
+#define DEBUG_REPROBE 1
+
 extern const int i830refreshes[];
 
 void
@@ -157,6 +161,23 @@ I830PrintModes(ScrnInfoPtr scrp)
     } while (p != NULL && p != scrp->modes);
 }
 
+/**
+ * Allocates and returns a copy of pMode, including pointers within pMode.
+ */
+static DisplayModePtr
+I830DuplicateMode(DisplayModePtr pMode)
+{
+    DisplayModePtr pNew;
+
+    pNew = xnfalloc(sizeof(DisplayModeRec));
+    *pNew = *pMode;
+    pNew->next = NULL;
+    pNew->prev = NULL;
+    pNew->name = xnfstrdup(pMode->name);
+
+    return pNew;
+}
+
 /* This function will sort all modes according to their resolution.
  * Highest resolution first.
  */
@@ -200,32 +221,31 @@ I830xf86SortModes(DisplayModePtr *new, D
 }
 
 /**
- * Calculates the vertical refresh of a mode.
+ * Gets a new pointer to a VESA established mode.
  *
- * Taken directly from xf86Mode.c, and should be put back there --Eric Anholt
+ * \param i index into the VESA established modes table.
  */
-static double
-I830ModeVRefresh(DisplayModePtr mode)
+static DisplayModePtr
+I830GetVESAEstablishedMode(ScrnInfoPtr pScrn, int i)
 {
-    double refresh = 0.0;
+    DisplayModePtr pMode;
 
-    if (mode->VRefresh > 0.0)
-	refresh = mode->VRefresh;
-    else if (mode->HTotal > 0 && mode->VTotal > 0) {
-	refresh = mode->Clock * 1000.0 / mode->HTotal / mode->VTotal;
-	if (mode->Flags & V_INTERLACE)
-	    refresh *= 2.0;
-	if (mode->Flags & V_DBLSCAN)
-	    refresh /= 2.0;
-	if (mode->VScan > 1)
-	    refresh /= (float)(mode->VScan);
+    for (pMode = I830xf86DefaultModes; pMode->name != NULL; pMode = pMode->next)
+    {
+	if (pMode->HDisplay == est_timings[i].hsize &&
+	    pMode->VDisplay == est_timings[i].vsize &&
+	    fabs(I830ModeVRefresh(pMode) - est_timings[i].refresh) < 1.0)
+	{
+	    DisplayModePtr pNew = I830DuplicateMode(pMode);
+	    pNew->VRefresh = I830ModeVRefresh(pMode);
+	    return pNew;
+	}
     }
-    return refresh;
+    return NULL;
 }
 
 DisplayModePtr I830GetDDCModes(ScrnInfoPtr pScrn, xf86MonPtr ddc)
 {
-    DisplayModePtr  p;
     DisplayModePtr  last  = NULL;
     DisplayModePtr  new   = NULL;
     DisplayModePtr  first = NULL;
@@ -289,7 +309,16 @@ DisplayModePtr I830GetDDCModes(ScrnInfoP
     for (j = 0; j < 8; j++) {
         if (ddc->timings2[j].hsize == 0 || ddc->timings2[j].vsize == 0)
                continue;
+#if 1
+	new = i830GetGTF(ddc->timings2[j].hsize, ddc->timings2[j].vsize,
+			 ddc->timings2[j].refresh, FALSE, FALSE);
+	new->status = MODE_OK;
+	new->type |= M_T_DEFAULT;
+
+	I830xf86SortModes(&new, &first, &last);
+#else
 	for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) {
+
 	    /* Ignore all double scan modes */
 	    if ((ddc->timings2[j].hsize == p->HDisplay) &&
 		(ddc->timings2[j].vsize == p->VDisplay)) {
@@ -318,39 +347,27 @@ DisplayModePtr I830GetDDCModes(ScrnInfoP
 		}
 	    }
 	}
+#endif
     }
 
     /* Search thru established modes from EDID */
     tmp = (ddc->timings1.t1 << 8) | ddc->timings1.t2;
     for (j = 0; j < 16; j++) {
 	if (tmp & (1 << j)) {
-	    for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) {
-		if ((est_timings[j].hsize == p->HDisplay) &&
-		    (est_timings[j].vsize == p->VDisplay)) {
-		    float  refresh =
-			(float)p->Clock * 1000.0 / p->HTotal / p->VTotal;
-		    float err = (float)est_timings[j].refresh - refresh;
-
-		    if (err < 1.0) {
-			/* Is this good enough? */
-			new = xnfcalloc(1, sizeof (DisplayModeRec));
-			memcpy(new, p, sizeof(DisplayModeRec));
-			new->name = xnfalloc(strlen(p->name) + 1);
-			strcpy(new->name, p->name);
-			new->status = MODE_OK;
-			new->type   = M_T_DEFAULT;
-
-			count++;
-
-			xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-				   "Valid Mode from established timing "
-				   "table: %s\n", new->name);
-
-			I830xf86SortModes(&new, &first, &last);
-			break;
-		    }
-		}
-	    }
+	    DisplayModePtr pNew;
+
+	    pNew = I830GetVESAEstablishedMode(pScrn, j);
+	    assert(pNew != NULL); /* We'd better have all the est. modes. */
+
+	    new->status = MODE_OK;
+	    new->type = M_T_DEFAULT;
+
+	    count++;
+
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Valid Mode from established "
+		       "timing table: %s\n", new->name);
+
+	    I830xf86SortModes(&new, &first, &last);
 	}
     }
 
@@ -512,23 +529,6 @@ i830GetLVDSModes(ScrnInfoPtr pScrn, char
 }
 
 /**
- * Allocates and returns a copy of pMode, including pointers within pMode.
- */
-static DisplayModePtr
-I830DuplicateMode(DisplayModePtr pMode)
-{
-    DisplayModePtr pNew;
-
-    pNew = xnfalloc(sizeof(DisplayModeRec));
-    *pNew = *pMode;
-    pNew->next = NULL;
-    pNew->prev = NULL;
-    pNew->name = xnfstrdup(pMode->name);
-
-    return pNew;
-}
-
-/**
  * Injects a list of probed modes into another mode list.
  *
  * Take the doubly-linked list of modes we've probed for the device, and injects
@@ -536,11 +536,11 @@ I830DuplicateMode(DisplayModePtr pMode)
  * eventual call to xf86ValidateModes will do this for us.  I think.
  */
 int
-I830InjectProbedModes(ScrnInfoPtr pScrn, DisplayModePtr modeList,
-		      char **ppModeName, DisplayModePtr addModes)
+I830InjectProbedModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList,
+		      DisplayModePtr addModes)
 {
-    DisplayModePtr  last = modeList;
-    DisplayModePtr  first = modeList;
+    DisplayModePtr  last = *modeList;
+    DisplayModePtr  first = *modeList;
     DisplayModePtr  addMode;
     int count = 0;
 
@@ -551,12 +551,14 @@ I830InjectProbedModes(ScrnInfoPtr pScrn,
 	 */
 
 	pNew = I830DuplicateMode(addMode);
+#if 0
 	/* If the user didn't specify any modes, mark all modes as M_T_USERDEF
 	 * so that we can cycle through them, etc.  XXX: really need to?
 	 */
-	if (ppModeName[0] == NULL) {
+	if (pScrn->display->modes[0] == NULL) {
 	    pNew->type |= M_T_USERDEF;
 	}
+#endif
 
 	/* Insert pNew into modeList */
 	if (last) {
@@ -571,6 +573,7 @@ I830InjectProbedModes(ScrnInfoPtr pScrn,
 
 	count++;
     }
+    *modeList = first;
 
     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 	       "Injected %d modes detected from the monitor\n", count);
@@ -578,97 +581,6 @@ I830InjectProbedModes(ScrnInfoPtr pScrn,
     return count;
 }
 
-/*
- * I830xf86SetModeCrtc
- *
- * Initialises the Crtc parameters for a mode.  The initialisation includes
- * adjustments for interlaced and double scan modes.
- *
- * Taken directly from xf86Mode.c:xf86SetModeCrtc -- Eric Anholt
- *   (and it should be put back there!)
- */
-static void
-I830xf86SetModeCrtc(DisplayModePtr p, int adjustFlags)
-{
-    if ((p == NULL) || ((p->type & M_T_CRTC_C) == M_T_BUILTIN))
-	return;
-
-    p->CrtcHDisplay             = p->HDisplay;
-    p->CrtcHSyncStart           = p->HSyncStart;
-    p->CrtcHSyncEnd             = p->HSyncEnd;
-    p->CrtcHTotal               = p->HTotal;
-    p->CrtcHSkew                = p->HSkew;
-    p->CrtcVDisplay             = p->VDisplay;
-    p->CrtcVSyncStart           = p->VSyncStart;
-    p->CrtcVSyncEnd             = p->VSyncEnd;
-    p->CrtcVTotal               = p->VTotal;
-    if (p->Flags & V_INTERLACE) {
-	if (adjustFlags & INTERLACE_HALVE_V) {
-	    p->CrtcVDisplay         /= 2;
-	    p->CrtcVSyncStart       /= 2;
-	    p->CrtcVSyncEnd         /= 2;
-	    p->CrtcVTotal           /= 2;
-	}
-	/* Force interlaced modes to have an odd VTotal */
-	/* maybe we should only do this when INTERLACE_HALVE_V is set? */
-	p->CrtcVTotal |= 1;
-    }
-
-    if (p->Flags & V_DBLSCAN) {
-        p->CrtcVDisplay         *= 2;
-        p->CrtcVSyncStart       *= 2;
-        p->CrtcVSyncEnd         *= 2;
-        p->CrtcVTotal           *= 2;
-    }
-    if (p->VScan > 1) {
-        p->CrtcVDisplay         *= p->VScan;
-        p->CrtcVSyncStart       *= p->VScan;
-        p->CrtcVSyncEnd         *= p->VScan;
-        p->CrtcVTotal           *= p->VScan;
-    }
-    p->CrtcHAdjusted = FALSE;
-    p->CrtcVAdjusted = FALSE;
-
-    /*
-     * XXX
-     *
-     * The following is taken from VGA, but applies to other cores as well.
-     */
-    p->CrtcVBlankStart = min(p->CrtcVSyncStart, p->CrtcVDisplay);
-    p->CrtcVBlankEnd = max(p->CrtcVSyncEnd, p->CrtcVTotal);
-    if ((p->CrtcVBlankEnd - p->CrtcVBlankStart) >= 127) {
-        /* 
-         * V Blanking size must be < 127.
-         * Moving blank start forward is safer than moving blank end
-         * back, since monitors clamp just AFTER the sync pulse (or in
-         * the sync pulse), but never before.
-         */
-        p->CrtcVBlankStart = p->CrtcVBlankEnd - 127;
-	/*
-	 * If VBlankStart is now > VSyncStart move VBlankStart
-	 * to VSyncStart using the maximum width that fits into
-	 * VTotal.
-	 */
-	if (p->CrtcVBlankStart > p->CrtcVSyncStart) {
-	    p->CrtcVBlankStart = p->CrtcVSyncStart;
-	    p->CrtcVBlankEnd = min(p->CrtcHBlankStart + 127, p->CrtcVTotal);
-	}
-    }
-    p->CrtcHBlankStart = min(p->CrtcHSyncStart, p->CrtcHDisplay);
-    p->CrtcHBlankEnd = max(p->CrtcHSyncEnd, p->CrtcHTotal);
-
-    if ((p->CrtcHBlankEnd - p->CrtcHBlankStart) >= 63 * 8) {
-        /*
-         * H Blanking size must be < 63*8. Same remark as above.
-         */
-        p->CrtcHBlankStart = p->CrtcHBlankEnd - 63 * 8;
-	if (p->CrtcHBlankStart > p->CrtcHSyncStart) {
-	    p->CrtcHBlankStart = p->CrtcHSyncStart;
-	    p->CrtcHBlankEnd = min(p->CrtcHBlankStart + 63 * 8, p->CrtcHTotal);
-	}
-    }
-}
-
 /**
  * Performs probing of modes available on the output connected to the given
  * pipe.
@@ -740,14 +652,21 @@ I830ReprobePipeModeList(ScrnInfoPtr pScr
     /* Set the vertical refresh, which is used by the choose-best-mode-per-pipe
      * code later on.
      */
+#ifdef DEBUG_REPROBE
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Printing probed modes for pipe %d\n",
+	       pipe);
+#endif
     for (pMode = pI830->pipeModes[pipe]; pMode != NULL; pMode = pMode->next) {
 	pMode->VRefresh = I830ModeVRefresh(pMode);
+#ifdef DEBUG_REPROBE
+	PrintModeline(pScrn->scrnIndex, pMode);
+#endif
     }
 }
 
 /**
  * This function removes a mode from a list of modes.  It should probably be
- * moved to xf86Mode.c
+ * moved to xf86Mode.c.
  *
  * There are different types of mode lists:
  *
@@ -795,8 +714,9 @@ I830ValidateXF86ModeList(ScrnInfoPtr pSc
     I830Ptr pI830 = I830PTR(pScrn);
     ClockRangePtr clockRanges;
     int n, pipe;
-    DisplayModePtr saved_mode;
+    DisplayModePtr saved_mode, availModes;
     int saved_virtualX = 0, saved_virtualY = 0, saved_displayWidth = 0;
+    Bool pipes_reconfigured = FALSE;
 
     for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++) {
 	I830ReprobePipeModeList(pScrn, pipe);
@@ -815,6 +735,9 @@ I830ValidateXF86ModeList(ScrnInfoPtr pSc
 	    } else {
 		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 			   "Enabled new CRT on pipe A\n");
+		pipes_reconfigured = TRUE;
+		/* Clear the current mode, so we reprogram the pipe for sure. */
+		memset(&pI830->pipeCurMode[0], 0, sizeof(pI830->pipeCurMode[0]));
 	    }
 	} else if (((pI830->operatingDevices >> 8) & 0xff) == PIPE_NONE) {
 	    pI830->operatingDevices |= PIPE_CRT << 8;
@@ -825,19 +748,24 @@ I830ValidateXF86ModeList(ScrnInfoPtr pSc
 	    } else {
 		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 			   "Enabled new CRT on pipe B\n");
+		pipes_reconfigured = TRUE;
+		/* Clear the current mode, so we reprogram the pipe for sure. */
+		memset(&pI830->pipeCurMode[1], 0, sizeof(pI830->pipeCurMode[1]));
 	    }
 	}
     }
 
-    /* XXX: Clean out modes previously injected by our driver */
-
+    /* Start by injecting the XFree86 default modes and user-configured
+     * modelines.  XXX: This actually isn't of use if we've got any DDC, as DDC
+     * currently has higher priority than the validated modelist.  We need to
+     * deal with that.
+     */
+    I830InjectProbedModes(pScrn, &availModes, pScrn->monitor->Modes);
     if (pI830->pipeModes[0] != NULL) {
-	I830InjectProbedModes(pScrn, pScrn->monitor->Modes,
-			      pScrn->display->modes, pI830->pipeModes[0]);
+	I830InjectProbedModes(pScrn, &availModes, pI830->pipeModes[0]);
     }
     if (pI830->pipeModes[1] != NULL) {
-	I830InjectProbedModes(pScrn, pScrn->monitor->Modes,
-			      pScrn->display->modes, pI830->pipeModes[1]);
+	I830InjectProbedModes(pScrn, &availModes, pI830->pipeModes[1]);
     }
 
    /*
@@ -872,7 +800,7 @@ I830ValidateXF86ModeList(ScrnInfoPtr pSc
      *      capabilities of our pipes.
      */
     n = xf86ValidateModes(pScrn,
-			  pScrn->monitor->Modes, /* availModes */
+			  availModes, /* availModes */
 			  pScrn->display->modes, /* modeNames */
 			  clockRanges, /* clockRanges */
 			  !first_time ? &pScrn->displayWidth : NULL, /* linePitches */
@@ -886,6 +814,12 @@ I830ValidateXF86ModeList(ScrnInfoPtr pSc
 			  pI830->FbMapSize, /* apertureSize */
 			  LOOKUP_BEST_REFRESH /* strategy */);
 
+    /* availModes is of no more use as xf86ValidateModes has duplicated and
+     * saved everything it needs.
+     */
+    while (availModes != NULL)
+	xf86DeleteMode(&availModes, availModes);
+
     if (!first_time) {
 	/* Restore things that may have been damaged by xf86ValidateModes. */
 	pScrn->virtualX = saved_virtualX;
@@ -900,6 +834,19 @@ I830ValidateXF86ModeList(ScrnInfoPtr pSc
 
     xf86PruneDriverModes(pScrn);
 
+#if DEBUG_REPROBE
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Modes post revalidate\n");
+    do {
+	DisplayModePtr pMode;
+
+	for (pMode = pScrn->modes; ; pMode = pMode->next) {
+	    PrintModeline(pScrn->scrnIndex, pMode);
+	    if (pMode->next == pScrn->modes)
+		break;
+	}
+    } while (0);
+#endif
+
     /* Try to find the closest equivalent of the previous mode pointer to switch
      * to.
      */
@@ -926,5 +873,23 @@ I830ValidateXF86ModeList(ScrnInfoPtr pSc
 	xfree(saved_mode->name);
 	xfree(saved_mode);
     }
+
+    /* If we've enabled/disabled some pipes, we need to reset cloning mode
+     * support.
+     */
+    if (pipes_reconfigured) {
+	if ((pI830->operatingDevices & 0x00ff) &&
+	    (pI830->operatingDevices & 0xff00))
+	{
+	    pI830->Clone = TRUE;
+	} else {
+	    pI830->Clone = FALSE;
+	}
+
+	/* If HW cursor currently showing, reset cursor state */
+	if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn)
+	    pI830->CursorInfoRec->ShowCursor(pScrn);
+    }
+
     return n;
 }
diff --git a/src/i830_sdvo.h b/src/i830_sdvo.h
index d52eb60..52621e0 100644
--- a/src/i830_sdvo.h
+++ b/src/i830_sdvo.h
@@ -66,3 +66,6 @@ i830SDVOPostRestore(ScrnInfoPtr pScrn, i
 
 Bool
 I830DetectSDVODisplays(ScrnInfoPtr pScrn, int output_index);
+
+void
+I830DumpSDVO(ScrnInfoPtr pScrn);
diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c
new file mode 100644
index 0000000..16a8cd8
--- /dev/null
+++ b/src/i830_xf86Modes.c
@@ -0,0 +1,348 @@
+/* $XdotOrg: xserver/xorg/hw/xfree86/common/xf86Mode.c,v 1.10 2006/03/07 16:00:57 libv Exp $ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Mode.c,v 1.69 2003/10/08 14:58:28 dawes Exp $ */
+/*
+ * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the copyright holder(s)
+ * and author(s) shall not be used in advertising or otherwise to promote
+ * the sale, use or other dealings in this Software without prior written
+ * authorization from the copyright holder(s) and author(s).
+ */
+
+#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"
+
+/**
+ * @file this file contains symbols from xf86Mode.c and friends that are static
+ * there but we still want to use.  We need to come up with better API here.
+ */
+
+/**
+ * Calculates the vertical refresh of a mode.
+ *
+ * Exact copy of xf86Mode.c's.
+ */
+double
+I830ModeVRefresh(DisplayModePtr mode)
+{
+    double refresh = 0.0;
+
+    if (mode->VRefresh > 0.0)
+	refresh = mode->VRefresh;
+    else if (mode->HTotal > 0 && mode->VTotal > 0) {
+	refresh = mode->Clock * 1000.0 / mode->HTotal / mode->VTotal;
+	if (mode->Flags & V_INTERLACE)
+	    refresh *= 2.0;
+	if (mode->Flags & V_DBLSCAN)
+	    refresh /= 2.0;
+	if (mode->VScan > 1)
+	    refresh /= (float)(mode->VScan);
+    }
+    return refresh;
+}
+
+/*
+ * I830xf86SetModeCrtc
+ *
+ * Initialises the Crtc parameters for a mode.  The initialisation includes
+ * adjustments for interlaced and double scan modes.
+ *
+ * Exact copy of xf86Mode.c's.
+ */
+void
+I830xf86SetModeCrtc(DisplayModePtr p, int adjustFlags)
+{
+    if ((p == NULL) || ((p->type & M_T_CRTC_C) == M_T_BUILTIN))
+	return;
+
+    p->CrtcHDisplay             = p->HDisplay;
+    p->CrtcHSyncStart           = p->HSyncStart;
+    p->CrtcHSyncEnd             = p->HSyncEnd;
+    p->CrtcHTotal               = p->HTotal;
+    p->CrtcHSkew                = p->HSkew;
+    p->CrtcVDisplay             = p->VDisplay;
+    p->CrtcVSyncStart           = p->VSyncStart;
+    p->CrtcVSyncEnd             = p->VSyncEnd;
+    p->CrtcVTotal               = p->VTotal;
+    if (p->Flags & V_INTERLACE) {
+	if (adjustFlags & INTERLACE_HALVE_V) {
+	    p->CrtcVDisplay         /= 2;
+	    p->CrtcVSyncStart       /= 2;
+	    p->CrtcVSyncEnd         /= 2;
+	    p->CrtcVTotal           /= 2;
+	}
+	/* Force interlaced modes to have an odd VTotal */
+	/* maybe we should only do this when INTERLACE_HALVE_V is set? */
+	p->CrtcVTotal |= 1;
+    }
+
+    if (p->Flags & V_DBLSCAN) {
+        p->CrtcVDisplay         *= 2;
+        p->CrtcVSyncStart       *= 2;
+        p->CrtcVSyncEnd         *= 2;
+        p->CrtcVTotal           *= 2;
+    }
+    if (p->VScan > 1) {
+        p->CrtcVDisplay         *= p->VScan;
+        p->CrtcVSyncStart       *= p->VScan;
+        p->CrtcVSyncEnd         *= p->VScan;
+        p->CrtcVTotal           *= p->VScan;
+    }
+    p->CrtcHAdjusted = FALSE;
+    p->CrtcVAdjusted = FALSE;
+
+    /*
+     * XXX
+     *
+     * The following is taken from VGA, but applies to other cores as well.
+     */
+    p->CrtcVBlankStart = min(p->CrtcVSyncStart, p->CrtcVDisplay);
+    p->CrtcVBlankEnd = max(p->CrtcVSyncEnd, p->CrtcVTotal);
+    if ((p->CrtcVBlankEnd - p->CrtcVBlankStart) >= 127) {
+        /* 
+         * V Blanking size must be < 127.
+         * Moving blank start forward is safer than moving blank end
+         * back, since monitors clamp just AFTER the sync pulse (or in
+         * the sync pulse), but never before.
+         */
+        p->CrtcVBlankStart = p->CrtcVBlankEnd - 127;
+	/*
+	 * If VBlankStart is now > VSyncStart move VBlankStart
+	 * to VSyncStart using the maximum width that fits into
+	 * VTotal.
+	 */
+	if (p->CrtcVBlankStart > p->CrtcVSyncStart) {
+	    p->CrtcVBlankStart = p->CrtcVSyncStart;
+	    p->CrtcVBlankEnd = min(p->CrtcHBlankStart + 127, p->CrtcVTotal);
+	}
+    }
+    p->CrtcHBlankStart = min(p->CrtcHSyncStart, p->CrtcHDisplay);
+    p->CrtcHBlankEnd = max(p->CrtcHSyncEnd, p->CrtcHTotal);
+
+    if ((p->CrtcHBlankEnd - p->CrtcHBlankStart) >= 63 * 8) {
+        /*
+         * H Blanking size must be < 63*8. Same remark as above.
+         */
+        p->CrtcHBlankStart = p->CrtcHBlankEnd - 63 * 8;
+	if (p->CrtcHBlankStart > p->CrtcHSyncStart) {
+	    p->CrtcHBlankStart = p->CrtcHSyncStart;
+	    p->CrtcHBlankEnd = min(p->CrtcHBlankStart + 63 * 8, p->CrtcHTotal);
+	}
+    }
+}
+
+/**
+ * Returns true if the given modes should program to the same timings.
+ *
+ * This doesn't use Crtc values, as it might be used on ModeRecs without the
+ * Crtc values set.  So, it's assumed that the other numbers are enough.
+ *
+ * This isn't in xf86Modes.c, but it might deserve to be there.
+ */
+Bool
+I830ModesEqual(DisplayModePtr pMode1, DisplayModePtr pMode2)
+{
+     if (pMode1->Clock == pMode2->Clock &&
+	 pMode1->HDisplay == pMode2->HDisplay &&
+	 pMode1->HSyncStart == pMode2->HSyncStart &&
+	 pMode1->HSyncEnd == pMode2->HSyncEnd &&
+	 pMode1->HTotal == pMode2->HTotal &&
+	 pMode1->HSkew == pMode2->HSkew &&
+	 pMode1->VDisplay == pMode2->VDisplay &&
+	 pMode1->VSyncStart == pMode2->VSyncStart &&
+	 pMode1->VSyncEnd == pMode2->VSyncEnd &&
+	 pMode1->VTotal == pMode2->VTotal &&
+	 pMode1->VScan == pMode2->VScan &&
+	 pMode1->Flags == pMode2->Flags)
+     {
+	return TRUE;
+     } else {
+	return FALSE;
+     }
+}
+
+/* exact copy of xf86Mode.c */
+static void
+add(char **p, char *new)
+{
+    *p = xnfrealloc(*p, strlen(*p) + strlen(new) + 2);
+    strcat(*p, " ");
+    strcat(*p, new);
+}
+
+/**
+ * Print out a modeline.
+ *
+ * Convenient VRefresh printing was added, though, compared to xf86Mode.c
+ */
+void
+PrintModeline(int scrnIndex,DisplayModePtr mode)
+{
+    char tmp[256];
+    char *flags = xnfcalloc(1, 1);
+
+    if (mode->HSkew) { 
+	snprintf(tmp, 256, "hskew %i", mode->HSkew); 
+	add(&flags, tmp);
+    }
+    if (mode->VScan) { 
+	snprintf(tmp, 256, "vscan %i", mode->VScan); 
+	add(&flags, tmp);
+    }
+    if (mode->Flags & V_INTERLACE) add(&flags, "interlace");
+    if (mode->Flags & V_CSYNC) add(&flags, "composite");
+    if (mode->Flags & V_DBLSCAN) add(&flags, "doublescan");
+    if (mode->Flags & V_BCAST) add(&flags, "bcast");
+    if (mode->Flags & V_PHSYNC) add(&flags, "+hsync");
+    if (mode->Flags & V_NHSYNC) add(&flags, "-hsync");
+    if (mode->Flags & V_PVSYNC) add(&flags, "+vsync");
+    if (mode->Flags & V_NVSYNC) add(&flags, "-vsync");
+    if (mode->Flags & V_PCSYNC) add(&flags, "+csync");
+    if (mode->Flags & V_NCSYNC) add(&flags, "-csync");
+#if 0
+    if (mode->Flags & V_CLKDIV2) add(&flags, "vclk/2");
+#endif
+    xf86DrvMsg(scrnIndex, X_ERROR,
+		   "Modeline \"%s\"x%.01f  %6.2f  %i %i %i %i  %i %i %i %i%s\n",
+		   mode->name, mode->VRefresh, mode->Clock/1000., mode->HDisplay,
+		   mode->HSyncStart, mode->HSyncEnd, mode->HTotal,
+		   mode->VDisplay, mode->VSyncStart, mode->VSyncEnd,
+		   mode->VTotal, flags);
+    xfree(flags);
+}
+
+#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).
+ */
+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}
+};
diff --git a/src/i830_xf86Modes.h b/src/i830_xf86Modes.h
new file mode 100644
index 0000000..ba7d820
--- /dev/null
+++ b/src/i830_xf86Modes.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
+double
+I830ModeVRefresh(DisplayModePtr mode);
+
+void
+I830xf86SetModeCrtc(DisplayModePtr p, int adjustFlags);
+
+Bool
+I830ModesEqual(DisplayModePtr pMode1, DisplayModePtr pMode2);
+
+void
+PrintModeline(int scrnIndex,DisplayModePtr mode);
+
+extern DisplayModeRec I830xf86DefaultModes[];
diff-tree f5e5f8aeddb3e0d6d073471aeff6176fb54576e2 (from 89791914d2a78f19f4f60ca370d387e5b1ccfb46)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Fri Jun 23 23:29:55 2006 -0700

    WIP to allow re-probing and validation of modes for new heads at "xrandr" time.
    
    Now, DDC modes always end up being preferred to custom modelines, even if
    smaller.  This should probably be fixed by inserting custom modelines into
    the probed mode list if they're valid according to the probed parameters of the
    monitor.
    
    Too much code is lifted from static functions in xf86Mode.c, and those should be
    made unstatic if possible.  Using xf86ValidateModes is also rather hacky, and
    I want to break the function down, but this is a first step.

diff --git a/src/i830.h b/src/i830.h
index 59f563f..c4a4771 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -595,7 +595,7 @@ extern Bool I830RandRInit(ScreenPtr pScr
 extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg,
 			char *name);
 /* i830_modes.c */
-int I830ValidateXF86ModeList(ScrnInfoPtr pScrn);
+int I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time);
 
 /* i830_gtf.c */
 DisplayModePtr i830GetGTF(int h_pixels, int v_lines, float freq,
diff --git a/src/i830_display.c b/src/i830_display.c
index 8843f98..50f4940 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -262,6 +262,44 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     int refclk, pixel_clock, sdvo_pixel_multiply;
     int outputs;
 
+    assert(pMode->VRefresh != 0.0);
+    /* If we've got a list of modes probed for the device, find the best match
+     * in there to the requested mode.
+     */
+    if (pI830->pipeModes[pipe] != NULL) {
+	DisplayModePtr pBest = NULL, pScan;
+
+	assert(pScan->VRefresh != 0.0);
+	for (pScan = pI830->pipeModes[pipe]; pScan != NULL; pScan = pScan->next)
+	{
+	    /* Reject if it's larger than the desired mode. */
+	    if (pScan->HDisplay > pMode->HDisplay ||
+		pScan->VDisplay > pMode->VDisplay)
+	    {
+		continue;
+	    }
+	    if (pBest == NULL) {
+		pBest = pScan;
+	        continue;
+	    }
+	    /* Find if it's closer than the current best option */
+	    if (abs(pScan->VRefresh - pMode->VRefresh) >
+		abs(pBest->VRefresh - pMode->VRefresh))
+	    {
+		continue;
+	    }
+	}
+	if (pBest != NULL) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Choosing pipe's mode %p (%dx%dx%.1f) instead of xf86 "
+		       "mode %p (%dx%dx%.1f)\n", pBest,
+		       pBest->HDisplay, pBest->VDisplay, pBest->VRefresh,
+		       pMode,
+		       pMode->HDisplay, pMode->VDisplay, pMode->VRefresh);
+	    pMode = pBest;
+	}
+    }
+
     ErrorF("Requested pix clock: %d\n", pMode->Clock);
 
     if (pipe == 0)
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 75f9e4b..32beb8a 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2217,23 +2217,19 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
 
      pI830->MaxClock = 300000;
 
-   n = I830ValidateXF86ModeList(pScrn);
+   n = I830ValidateXF86ModeList(pScrn, TRUE);
    if (n <= 0) {
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
       PreInitCleanup(pScrn);
       return FALSE;
    }	
 
-   xf86PruneDriverModes(pScrn);
-
    if (pScrn->modes == NULL) {
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n");
       PreInitCleanup(pScrn);
       return FALSE;
    }
 
-   xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
-
    /*
     * Fix up modes to make hblank start at hsync start.
     * I don't know why the xf86 code mangles this...
diff --git a/src/i830_modes.c b/src/i830_modes.c
index 6f878a5..faa843e 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -1,6 +1,7 @@
 #define DEBUG_VERB 2
 /*
  * Copyright © 2002 David Dawes
+ * Copyright © 2006 Intel Corporation
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -26,6 +27,7 @@
  * the author(s).
  *
  * Authors: David Dawes <dawes at xfree86.org>
+ *	    Eric Anholt <eric.anholt at intel.com>
  *
  * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/vbe/vbeModes.c,v 1.6 2002/11/02 01:38:25 dawes Exp $
  */
@@ -197,6 +199,30 @@ I830xf86SortModes(DisplayModePtr *new, D
     }
 }
 
+/**
+ * Calculates the vertical refresh of a mode.
+ *
+ * Taken directly from xf86Mode.c, and should be put back there --Eric Anholt
+ */
+static double
+I830ModeVRefresh(DisplayModePtr mode)
+{
+    double refresh = 0.0;
+
+    if (mode->VRefresh > 0.0)
+	refresh = mode->VRefresh;
+    else if (mode->HTotal > 0 && mode->VTotal > 0) {
+	refresh = mode->Clock * 1000.0 / mode->HTotal / mode->VTotal;
+	if (mode->Flags & V_INTERLACE)
+	    refresh *= 2.0;
+	if (mode->Flags & V_DBLSCAN)
+	    refresh /= 2.0;
+	if (mode->VScan > 1)
+	    refresh /= (float)(mode->VScan);
+    }
+    return refresh;
+}
+
 DisplayModePtr I830GetDDCModes(ScrnInfoPtr pScrn, xf86MonPtr ddc)
 {
     DisplayModePtr  p;
@@ -552,6 +578,97 @@ I830InjectProbedModes(ScrnInfoPtr pScrn,
     return count;
 }
 
+/*
+ * I830xf86SetModeCrtc
+ *
+ * Initialises the Crtc parameters for a mode.  The initialisation includes
+ * adjustments for interlaced and double scan modes.
+ *
+ * Taken directly from xf86Mode.c:xf86SetModeCrtc -- Eric Anholt
+ *   (and it should be put back there!)
+ */
+static void
+I830xf86SetModeCrtc(DisplayModePtr p, int adjustFlags)
+{
+    if ((p == NULL) || ((p->type & M_T_CRTC_C) == M_T_BUILTIN))
+	return;
+
+    p->CrtcHDisplay             = p->HDisplay;
+    p->CrtcHSyncStart           = p->HSyncStart;
+    p->CrtcHSyncEnd             = p->HSyncEnd;
+    p->CrtcHTotal               = p->HTotal;
+    p->CrtcHSkew                = p->HSkew;
+    p->CrtcVDisplay             = p->VDisplay;
+    p->CrtcVSyncStart           = p->VSyncStart;
+    p->CrtcVSyncEnd             = p->VSyncEnd;
+    p->CrtcVTotal               = p->VTotal;
+    if (p->Flags & V_INTERLACE) {
+	if (adjustFlags & INTERLACE_HALVE_V) {
+	    p->CrtcVDisplay         /= 2;
+	    p->CrtcVSyncStart       /= 2;
+	    p->CrtcVSyncEnd         /= 2;
+	    p->CrtcVTotal           /= 2;
+	}
+	/* Force interlaced modes to have an odd VTotal */
+	/* maybe we should only do this when INTERLACE_HALVE_V is set? */
+	p->CrtcVTotal |= 1;
+    }
+
+    if (p->Flags & V_DBLSCAN) {
+        p->CrtcVDisplay         *= 2;
+        p->CrtcVSyncStart       *= 2;
+        p->CrtcVSyncEnd         *= 2;
+        p->CrtcVTotal           *= 2;
+    }
+    if (p->VScan > 1) {
+        p->CrtcVDisplay         *= p->VScan;
+        p->CrtcVSyncStart       *= p->VScan;
+        p->CrtcVSyncEnd         *= p->VScan;
+        p->CrtcVTotal           *= p->VScan;
+    }
+    p->CrtcHAdjusted = FALSE;
+    p->CrtcVAdjusted = FALSE;
+
+    /*
+     * XXX
+     *
+     * The following is taken from VGA, but applies to other cores as well.
+     */
+    p->CrtcVBlankStart = min(p->CrtcVSyncStart, p->CrtcVDisplay);
+    p->CrtcVBlankEnd = max(p->CrtcVSyncEnd, p->CrtcVTotal);
+    if ((p->CrtcVBlankEnd - p->CrtcVBlankStart) >= 127) {
+        /* 
+         * V Blanking size must be < 127.
+         * Moving blank start forward is safer than moving blank end
+         * back, since monitors clamp just AFTER the sync pulse (or in
+         * the sync pulse), but never before.
+         */
+        p->CrtcVBlankStart = p->CrtcVBlankEnd - 127;
+	/*
+	 * If VBlankStart is now > VSyncStart move VBlankStart
+	 * to VSyncStart using the maximum width that fits into
+	 * VTotal.
+	 */
+	if (p->CrtcVBlankStart > p->CrtcVSyncStart) {
+	    p->CrtcVBlankStart = p->CrtcVSyncStart;
+	    p->CrtcVBlankEnd = min(p->CrtcHBlankStart + 127, p->CrtcVTotal);
+	}
+    }
+    p->CrtcHBlankStart = min(p->CrtcHSyncStart, p->CrtcHDisplay);
+    p->CrtcHBlankEnd = max(p->CrtcHSyncEnd, p->CrtcHTotal);
+
+    if ((p->CrtcHBlankEnd - p->CrtcHBlankStart) >= 63 * 8) {
+        /*
+         * H Blanking size must be < 63*8. Same remark as above.
+         */
+        p->CrtcHBlankStart = p->CrtcHBlankEnd - 63 * 8;
+	if (p->CrtcHBlankStart > p->CrtcHSyncStart) {
+	    p->CrtcHBlankStart = p->CrtcHSyncStart;
+	    p->CrtcHBlankEnd = min(p->CrtcHBlankStart + 63 * 8, p->CrtcHTotal);
+	}
+    }
+}
+
 /**
  * Performs probing of modes available on the output connected to the given
  * pipe.
@@ -567,6 +684,7 @@ I830ReprobePipeModeList(ScrnInfoPtr pScr
     int output_index = -1;
     int i;
     int outputs;
+    DisplayModePtr pMode;
 
     while (pI830->pipeModes[pipe] != NULL)
 	xf86DeleteMode(&pI830->pipeModes[pipe], pI830->pipeModes[pipe]);
@@ -609,26 +727,108 @@ I830ReprobePipeModeList(ScrnInfoPtr pScr
 					       pI830->output[output_index].pDDCBus);
 	pI830->pipeModes[pipe] = I830GetDDCModes(pScrn,
 						 pI830->pipeMon[pipe]);
+
+	for (pMode = pI830->pipeModes[pipe]; pMode != NULL; pMode = pMode->next)
+	{
+	    I830xf86SetModeCrtc(pMode, INTERLACE_HALVE_V);
+	    pMode->VRefresh = I830ModeVRefresh(pMode);
+	}
     } else {
 	ErrorF("don't know how to get modes for this device.\n");
     }
+
+    /* Set the vertical refresh, which is used by the choose-best-mode-per-pipe
+     * code later on.
+     */
+    for (pMode = pI830->pipeModes[pipe]; pMode != NULL; pMode = pMode->next) {
+	pMode->VRefresh = I830ModeVRefresh(pMode);
+    }
 }
 
 /**
+ * This function removes a mode from a list of modes.  It should probably be
+ * moved to xf86Mode.c
+ *
+ * There are different types of mode lists:
+ *
+ *  - singly linked linear lists, ending in NULL
+ *  - doubly linked linear lists, starting and ending in NULL
+ *  - doubly linked circular lists
+ *
+ */
+
+static void
+I830xf86DeleteModeFromList(DisplayModePtr *modeList, DisplayModePtr mode)
+{
+    /* Catch the easy/insane cases */
+    if (modeList == NULL || *modeList == NULL || mode == NULL)
+	return;
+
+    /* If the mode is at the start of the list, move the start of the list */
+    if (*modeList == mode)
+	*modeList = mode->next;
+
+    /* If mode is the only one on the list, set the list to NULL */
+    if ((mode == mode->prev) && (mode == mode->next)) {
+	*modeList = NULL;
+    } else {
+	if ((mode->prev != NULL) && (mode->prev->next == mode))
+	    mode->prev->next = mode->next;
+	if ((mode->next != NULL) && (mode->next->prev == mode))
+	    mode->next->prev = mode->prev;
+    }
+}
+    
+/**
  * Probes for video modes on attached otuputs, and assembles a list to insert
  * into pScrn.
+ *
+ * \param first_time indicates that the memory layout has already been set up,
+ * 	  so displayWidth, virtualX, and virtualY shouldn't be touched.
+ *
+ * A SetMode must follow this call in order for operatingDevices to match the
+ * hardware's state, in case we detect a new output device.  
  */
 int
-I830ValidateXF86ModeList(ScrnInfoPtr pScrn)
+I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     ClockRangePtr clockRanges;
     int n, pipe;
+    DisplayModePtr saved_mode;
+    int saved_virtualX = 0, saved_virtualY = 0, saved_displayWidth = 0;
 
     for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++) {
 	I830ReprobePipeModeList(pScrn, pipe);
     }
 
+    /* If we've got a spare pipe, try to detect if a new CRT has been plugged
+     * in.
+     */
+    if ((pI830->operatingDevices & (PIPE_CRT | (PIPE_CRT << 8))) == 0) {
+	if ((pI830->operatingDevices & 0xff) == PIPE_NONE) {
+	    pI830->operatingDevices |= PIPE_CRT;
+	    I830ReprobePipeModeList(pScrn, 0);
+	    if (pI830->pipeModes[0] == NULL) {
+		/* No new output found. */
+		pI830->operatingDevices &= ~PIPE_CRT;
+	    } else {
+		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+			   "Enabled new CRT on pipe A\n");
+	    }
+	} else if (((pI830->operatingDevices >> 8) & 0xff) == PIPE_NONE) {
+	    pI830->operatingDevices |= PIPE_CRT << 8;
+	    I830ReprobePipeModeList(pScrn, 1);
+	    if (pI830->pipeModes[1] == NULL) {
+		/* No new output found. */
+		pI830->operatingDevices &= ~(PIPE_CRT << 8);
+	    } else {
+		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+			   "Enabled new CRT on pipe B\n");
+	    }
+	}
+    }
+
     /* XXX: Clean out modes previously injected by our driver */
 
     if (pI830->pipeModes[0] != NULL) {
@@ -652,23 +852,79 @@ I830ValidateXF86ModeList(ScrnInfoPtr pSc
     clockRanges->interlaceAllowed = TRUE;	/* XXX check this */
     clockRanges->doubleScanAllowed = FALSE;	/* XXX check this */
 
+    /* Remove the current mode from the modelist if we're re-validating, so we
+     * can find a new mode to map ourselves to afterwards.
+     */
+    saved_mode = pI830->currentMode;
+    if (saved_mode != NULL) {
+	I830xf86DeleteModeFromList(&pScrn->modes, saved_mode);
+    }
+
+    if (!first_time) {
+	saved_virtualX = pScrn->virtualX;
+	saved_virtualY = pScrn->virtualY;
+	saved_displayWidth = pScrn->displayWidth;
+    }
+
     /* Take the pScrn->monitor->Modes we've accumulated and validate them into
      * pScrn->modes.
+     * XXX: Should set up a scrp->monitor->DDC covering the union of the
+     *      capabilities of our pipes.
      */
     n = xf86ValidateModes(pScrn,
 			  pScrn->monitor->Modes, /* availModes */
 			  pScrn->display->modes, /* modeNames */
 			  clockRanges, /* clockRanges */
-			  NULL, /* linePitches */
+			  !first_time ? &pScrn->displayWidth : NULL, /* linePitches */
 			  320, /* minPitch */
 			  MAX_DISPLAY_PITCH, /* maxPitch */
 			  64 * pScrn->bitsPerPixel, /* pitchInc */
 			  200, /* minHeight */
 			  MAX_DISPLAY_HEIGHT, /* maxHeight */
-			  pScrn->display->virtualX, /* virtualX */
-			  pScrn->display->virtualY, /* virtualY */
+			  pScrn->virtualX, /* virtualX */
+			  pScrn->virtualY, /* virtualY */
 			  pI830->FbMapSize, /* apertureSize */
 			  LOOKUP_BEST_REFRESH /* strategy */);
 
+    if (!first_time) {
+	/* Restore things that may have been damaged by xf86ValidateModes. */
+	pScrn->virtualX = saved_virtualX;
+	pScrn->virtualY = saved_virtualY;
+	pScrn->displayWidth = saved_displayWidth;
+    }
+
+    /* Need to do xf86CrtcForModes so any user-configured modes are valid for
+     * non-LVDS.
+     */
+    xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
+
+    xf86PruneDriverModes(pScrn);
+
+    /* Try to find the closest equivalent of the previous mode pointer to switch
+     * to.
+     */
+    if (saved_mode != NULL) {
+	DisplayModePtr pBestMode = NULL, pMode;
+
+	/* XXX: Is finding a matching x/y res enough?  probably not. */
+	for (pMode = pScrn->modes; ; pMode = pMode->next) {
+	    if (pMode->HDisplay == saved_mode->HDisplay &&
+		pMode->VDisplay == saved_mode->VDisplay)
+	    {
+		ErrorF("found matching mode %p\n", pMode);
+		pBestMode = pMode;
+	    }
+	    if (pMode->next == pScrn->modes)
+		break;
+	}
+
+	if (pBestMode != NULL)
+		xf86SwitchMode(pScrn->pScreen, pBestMode);
+	else
+		FatalError("No suitable modes after re-probe\n");
+
+	xfree(saved_mode->name);
+	xfree(saved_mode);
+    }
     return n;
 }
diff --git a/src/i830_randr.c b/src/i830_randr.c
index 0311f2b..93c0519 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -79,6 +79,9 @@ I830RandRGetInfo (ScreenPtr pScreen, Rot
 	randrp->virtualY = scrp->virtualY;
     }
 
+    /* Re-probe the outputs for new monitors or modes */
+    I830ValidateXF86ModeList(scrp, FALSE);
+
     for (mode = scrp->modes; ; mode = mode->next)
     {
 	int refresh = I830RandRModeRefresh (mode);
diff-tree 89791914d2a78f19f4f60ca370d387e5b1ccfb46 (from bb4810521633b6c3db2fc7d01ddc71325583d265)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Fri Jun 23 18:21:17 2006 -0700

    Split probed modes out per pipe, and union them into the available modes.
    
    This is the first stage of getting runtime monitor attachment.  The old i830
    GTF code is returned to use to provide suitable modelines for xf86ValidateModes
    in the LVDS case, even though the LVDS doesn't care about the modeline and just
    always programs its fixed values.

diff --git a/src/Makefile.am b/src/Makefile.am
index da48149..8970db1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -55,6 +55,7 @@ i810_drv_la_SOURCES = \
 	 i830_display.h \
          i830_driver.c \
          i830.h \
+         i830_gtf.c \
          i830_i2c.c \
          i830_io.c \
          i830_memory.c \
diff --git a/src/i830.h b/src/i830.h
index 26a0063..59f563f 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -399,9 +399,10 @@ typedef struct _I830Rec {
 
    /* [0] is Pipe A, [1] is Pipe B. */
    int availablePipes;
-   int pipeDevices[MAX_DISPLAY_PIPES];
    /* [0] is display plane A, [1] is display plane B. */
    int planeEnabled[MAX_DISPLAY_PIPES];
+   xf86MonPtr pipeMon[MAX_DISPLAY_PIPES];
+   DisplayModePtr pipeModes[MAX_DISPLAY_PIPES];
 
    /* Driver phase/state information */
    Bool preinit;
@@ -593,8 +594,12 @@ extern Rotation I830GetRotation(ScreenPt
 extern Bool I830RandRInit(ScreenPtr pScreen, int rotation);
 extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg,
 			char *name);
-int I830xf86ValidateDDCModes(ScrnInfoPtr pScrn1, char **ppModeName);
-int i830ValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName);
+/* i830_modes.c */
+int I830ValidateXF86ModeList(ScrnInfoPtr pScrn);
+
+/* i830_gtf.c */
+DisplayModePtr i830GetGTF(int h_pixels, int v_lines, float freq,
+			  int interlaced, int margins);
 
 /*
  * 12288 is set as the maximum, chosen because it is enough for
diff --git a/src/i830_driver.c b/src/i830_driver.c
index f3cb186..75f9e4b 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1258,7 +1258,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
    int flags24;
    int i, n;
    char *s;
-   ClockRangePtr clockRanges;
    pointer pVBEModule = NULL;
    Bool enable, has_lvds;
    const char *chipname;
@@ -2218,50 +2217,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
 
      pI830->MaxClock = 300000;
 
-   /*
-     * Setup the ClockRanges, which describe what clock ranges are available,
-     * and what sort of modes they can be used for.
-     */
-    clockRanges = xnfcalloc(sizeof(ClockRange), 1);
-    clockRanges->next = NULL;
-    /* 25MHz appears to be the smallest that works. */
-    clockRanges->minClock = 25000;
-    clockRanges->maxClock = pI830->MaxClock;
-    clockRanges->clockIndex = -1;		/* programmable */
-    clockRanges->interlaceAllowed = TRUE;	/* XXX check this */
-    clockRanges->doubleScanAllowed = FALSE;	/* XXX check this */
-
-   if ( (pI830->pipe == 1 && pI830->operatingDevices & (PIPE_LFP << 8)) ||
-        (pI830->pipe == 0 && pI830->operatingDevices & PIPE_LFP) ) {
-      /* If we're outputting to an LFP, use the LFP mode validation that will
-       * rely on the scaler so that we can display any mode smaller than or the
-       * same size as the panel.
-       */
-      if (!has_lvds) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		    "Unable to locate panel information in BIOS VBT tables\n");
-         PreInitCleanup(pScrn);
-	 return FALSE;
-      }
-      n = i830ValidateFPModes(pScrn, pScrn->display->modes);
-   } else {
-      I830xf86ValidateDDCModes(pScrn, pScrn->display->modes);
-      /* XXX minPitch, minHeight are random numbers. */
-      n = xf86ValidateModes(pScrn,
-			    pScrn->monitor->Modes, /* availModes */
-			    pScrn->display->modes, /* modeNames */
-			    clockRanges, /* clockRanges */
-			    NULL, /* linePitches */
-			    320, /* minPitch */
-			    MAX_DISPLAY_PITCH, /* maxPitch */
-			    64 * pScrn->bitsPerPixel, /* pitchInc */
-			    200, /* minHeight */
-			    MAX_DISPLAY_HEIGHT, /* maxHeight */
-			    pScrn->display->virtualX, /* virtualX */
-			    pScrn->display->virtualY, /* virtualY */
-			    pI830->FbMapSize, /* apertureSize */
-			    LOOKUP_BEST_REFRESH /* strategy */);
-   }
+   n = I830ValidateXF86ModeList(pScrn);
    if (n <= 0) {
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
       PreInitCleanup(pScrn);
diff --git a/src/i830_gtf.c b/src/i830_gtf.c
new file mode 100644
index 0000000..2eff46a
--- /dev/null
+++ b/src/i830_gtf.c
@@ -0,0 +1,356 @@
+#define DEBUG_VERB 2
+/*
+ * Copyright © 2002 David Dawes
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the author(s) shall
+ * not be used in advertising or otherwise to promote the sale, use or other
+ * dealings in this Software without prior written authorization from
+ * the author(s).
+ *
+ * Authors: David Dawes <dawes at xfree86.org>
+ *
+ * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/vbe/vbeModes.c,v 1.6 2002/11/02 01:38:25 dawes Exp $
+ */
+/*
+ * Modified by Alan Hourihane <alanh at tungstengraphics.com>
+ * to support extended BIOS modes for the Intel chipsets
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include "xf86.h"
+#include "vbe.h"
+#include "vbeModes.h"
+#include "i830.h"
+
+#include <math.h>
+
+#define rint(x) floor(x)
+
+#define MARGIN_PERCENT    1.8   /* % of active vertical image                */
+#define CELL_GRAN         8.0   /* assumed character cell granularity        */
+#define MIN_PORCH         1     /* minimum front porch                       */
+#define V_SYNC_RQD        3     /* width of vsync in lines                   */
+#define H_SYNC_PERCENT    8.0   /* width of hsync as % of total line         */
+#define MIN_VSYNC_PLUS_BP 550.0 /* min time of vsync + back porch (microsec) */
+#define M                 600.0 /* blanking formula gradient                 */
+#define C                 40.0  /* blanking formula offset                   */
+#define K                 128.0 /* blanking formula scaling factor           */
+#define J                 20.0  /* blanking formula scaling factor           */
+
+/* C' and M' are part of the Blanking Duty Cycle computation */
+
+#define C_PRIME           (((C - J) * K/256.0) + J)
+#define M_PRIME           (K/256.0 * M)
+
+extern const int i830refreshes[];
+
+DisplayModePtr
+i830GetGTF(int h_pixels, int v_lines, float freq, int interlaced, int margins)
+{
+    float h_pixels_rnd;
+    float v_lines_rnd;
+    float v_field_rate_rqd;
+    float top_margin;
+    float bottom_margin;
+    float interlace;
+    float h_period_est;
+    float vsync_plus_bp;
+    float v_back_porch;
+    float total_v_lines;
+    float v_field_rate_est;
+    float h_period;
+    float v_field_rate;
+    float v_frame_rate;
+    float left_margin;
+    float right_margin;
+    float total_active_pixels;
+    float ideal_duty_cycle;
+    float h_blank;
+    float total_pixels;
+    float pixel_freq;
+    float h_freq;
+
+    float h_sync;
+    float h_front_porch;
+    float v_odd_front_porch_lines;
+    char modename[20];
+    DisplayModePtr m;
+
+    m = xnfcalloc(sizeof(DisplayModeRec), 1);
+    
+    
+    /*  1. In order to give correct results, the number of horizontal
+     *  pixels requested is first processed to ensure that it is divisible
+     *  by the character size, by rounding it to the nearest character
+     *  cell boundary:
+     *
+     *  [H PIXELS RND] = ((ROUND([H PIXELS]/[CELL GRAN RND],0))*[CELLGRAN RND])
+     */
+    
+    h_pixels_rnd = rint((float) h_pixels / CELL_GRAN) * CELL_GRAN;
+    
+    
+    /*  2. If interlace is requested, the number of vertical lines assumed
+     *  by the calculation must be halved, as the computation calculates
+     *  the number of vertical lines per field. In either case, the
+     *  number of lines is rounded to the nearest integer.
+     *   
+     *  [V LINES RND] = IF([INT RQD?]="y", ROUND([V LINES]/2,0),
+     *                                     ROUND([V LINES],0))
+     */
+
+    v_lines_rnd = interlaced ?
+            rint((float) v_lines) / 2.0 :
+            rint((float) v_lines);
+    
+    /*  3. Find the frame rate required:
+     *
+     *  [V FIELD RATE RQD] = IF([INT RQD?]="y", [I/P FREQ RQD]*2,
+     *                                          [I/P FREQ RQD])
+     */
+
+    v_field_rate_rqd = interlaced ? (freq * 2.0) : (freq);
+
+    /*  4. Find number of lines in Top margin:
+     *
+     *  [TOP MARGIN (LINES)] = IF([MARGINS RQD?]="Y",
+     *          ROUND(([MARGIN%]/100*[V LINES RND]),0),
+     *          0)
+     */
+
+    top_margin = margins ? rint(MARGIN_PERCENT / 100.0 * v_lines_rnd) : (0.0);
+
+    /*  5. Find number of lines in Bottom margin:
+     *
+     *  [BOT MARGIN (LINES)] = IF([MARGINS RQD?]="Y",
+     *          ROUND(([MARGIN%]/100*[V LINES RND]),0),
+     *          0)
+     */
+
+    bottom_margin = margins ? rint(MARGIN_PERCENT/100.0 * v_lines_rnd) : (0.0);
+
+    /*  6. If interlace is required, then set variable [INTERLACE]=0.5:
+     *   
+     *  [INTERLACE]=(IF([INT RQD?]="y",0.5,0))
+     */
+
+    interlace = interlaced ? 0.5 : 0.0;
+
+    /*  7. Estimate the Horizontal period
+     *
+     *  [H PERIOD EST] = ((1/[V FIELD RATE RQD]) - [MIN VSYNC+BP]/1000000) /
+     *                    ([V LINES RND] + (2*[TOP MARGIN (LINES)]) +
+     *                     [MIN PORCH RND]+[INTERLACE]) * 1000000
+     */
+
+    h_period_est = (((1.0/v_field_rate_rqd) - (MIN_VSYNC_PLUS_BP/1000000.0))
+                    / (v_lines_rnd + (2*top_margin) + MIN_PORCH + interlace)
+                    * 1000000.0);
+
+    /*  8. Find the number of lines in V sync + back porch:
+     *
+     *  [V SYNC+BP] = ROUND(([MIN VSYNC+BP]/[H PERIOD EST]),0)
+     */
+
+    vsync_plus_bp = rint(MIN_VSYNC_PLUS_BP/h_period_est);
+
+    /*  9. Find the number of lines in V back porch alone:
+     *
+     *  [V BACK PORCH] = [V SYNC+BP] - [V SYNC RND]
+     *
+     *  XXX is "[V SYNC RND]" a typo? should be [V SYNC RQD]?
+     */
+    
+    v_back_porch = vsync_plus_bp - V_SYNC_RQD;
+    
+    /*  10. Find the total number of lines in Vertical field period:
+     *
+     *  [TOTAL V LINES] = [V LINES RND] + [TOP MARGIN (LINES)] +
+     *                    [BOT MARGIN (LINES)] + [V SYNC+BP] + [INTERLACE] +
+     *                    [MIN PORCH RND]
+     */
+
+    total_v_lines = v_lines_rnd + top_margin + bottom_margin + vsync_plus_bp +
+        interlace + MIN_PORCH;
+    
+    /*  11. Estimate the Vertical field frequency:
+     *
+     *  [V FIELD RATE EST] = 1 / [H PERIOD EST] / [TOTAL V LINES] * 1000000
+     */
+
+    v_field_rate_est = 1.0 / h_period_est / total_v_lines * 1000000.0;
+    
+    /*  12. Find the actual horizontal period:
+     *
+     *  [H PERIOD] = [H PERIOD EST] / ([V FIELD RATE RQD] / [V FIELD RATE EST])
+     */
+
+    h_period = h_period_est / (v_field_rate_rqd / v_field_rate_est);
+    
+    /*  13. Find the actual Vertical field frequency:
+     *
+     *  [V FIELD RATE] = 1 / [H PERIOD] / [TOTAL V LINES] * 1000000
+     */
+
+    v_field_rate = 1.0 / h_period / total_v_lines * 1000000.0;
+
+    /*  14. Find the Vertical frame frequency:
+     *
+     *  [V FRAME RATE] = (IF([INT RQD?]="y", [V FIELD RATE]/2, [V FIELD RATE]))
+     */
+
+    v_frame_rate = interlaced ? v_field_rate / 2.0 : v_field_rate;
+
+    /*  15. Find number of pixels in left margin:
+     *
+     *  [LEFT MARGIN (PIXELS)] = (IF( [MARGINS RQD?]="Y",
+     *          (ROUND( ([H PIXELS RND] * [MARGIN%] / 100 /
+     *                   [CELL GRAN RND]),0)) * [CELL GRAN RND],
+     *          0))
+     */
+
+    left_margin = margins ?
+        rint(h_pixels_rnd * MARGIN_PERCENT / 100.0 / CELL_GRAN) * CELL_GRAN :
+        0.0;
+    
+    /*  16. Find number of pixels in right margin:
+     *
+     *  [RIGHT MARGIN (PIXELS)] = (IF( [MARGINS RQD?]="Y",
+     *          (ROUND( ([H PIXELS RND] * [MARGIN%] / 100 /
+     *                   [CELL GRAN RND]),0)) * [CELL GRAN RND],
+     *          0))
+     */
+    
+    right_margin = margins ?
+        rint(h_pixels_rnd * MARGIN_PERCENT / 100.0 / CELL_GRAN) * CELL_GRAN :
+        0.0;
+    
+    /*  17. Find total number of active pixels in image and left and right
+     *  margins:
+     *
+     *  [TOTAL ACTIVE PIXELS] = [H PIXELS RND] + [LEFT MARGIN (PIXELS)] +
+     *                          [RIGHT MARGIN (PIXELS)]
+     */
+
+    total_active_pixels = h_pixels_rnd + left_margin + right_margin;
+    
+    /*  18. Find the ideal blanking duty cycle from the blanking duty cycle
+     *  equation:
+     *
+     *  [IDEAL DUTY CYCLE] = [C'] - ([M']*[H PERIOD]/1000)
+     */
+
+    ideal_duty_cycle = C_PRIME - (M_PRIME * h_period / 1000.0);
+    
+    /*  19. Find the number of pixels in the blanking time to the nearest
+     *  double character cell:
+     *
+     *  [H BLANK (PIXELS)] = (ROUND(([TOTAL ACTIVE PIXELS] *
+     *                               [IDEAL DUTY CYCLE] /
+     *                               (100-[IDEAL DUTY CYCLE]) /
+     *                               (2*[CELL GRAN RND])), 0))
+     *                       * (2*[CELL GRAN RND])
+     */
+
+    h_blank = rint(total_active_pixels *
+                   ideal_duty_cycle /
+                   (100.0 - ideal_duty_cycle) /
+                   (2.0 * CELL_GRAN)) * (2.0 * CELL_GRAN);
+    
+    /*  20. Find total number of pixels:
+     *
+     *  [TOTAL PIXELS] = [TOTAL ACTIVE PIXELS] + [H BLANK (PIXELS)]
+     */
+
+    total_pixels = total_active_pixels + h_blank;
+    
+    /*  21. Find pixel clock frequency:
+     *
+     *  [PIXEL FREQ] = [TOTAL PIXELS] / [H PERIOD]
+     */
+    
+    pixel_freq = total_pixels / h_period;
+    
+    /*  22. Find horizontal frequency:
+     *
+     *  [H FREQ] = 1000 / [H PERIOD]
+     */
+
+    h_freq = 1000.0 / h_period;
+    
+
+    /* Stage 1 computations are now complete; I should really pass
+       the results to another function and do the Stage 2
+       computations, but I only need a few more values so I'll just
+       append the computations here for now */
+
+    
+
+    /*  17. Find the number of pixels in the horizontal sync period:
+     *
+     *  [H SYNC (PIXELS)] =(ROUND(([H SYNC%] / 100 * [TOTAL PIXELS] /
+     *                             [CELL GRAN RND]),0))*[CELL GRAN RND]
+     */
+
+    h_sync = rint(H_SYNC_PERCENT/100.0 * total_pixels / CELL_GRAN) * CELL_GRAN;
+
+    /*  18. Find the number of pixels in the horizontal front porch period:
+     *
+     *  [H FRONT PORCH (PIXELS)] = ([H BLANK (PIXELS)]/2)-[H SYNC (PIXELS)]
+     */
+
+    h_front_porch = (h_blank / 2.0) - h_sync;
+
+    /*  36. Find the number of lines in the odd front porch period:
+     *
+     *  [V ODD FRONT PORCH(LINES)]=([MIN PORCH RND]+[INTERLACE])
+     */
+    
+    v_odd_front_porch_lines = MIN_PORCH + interlace;
+    
+    /* finally, pack the results in the DisplayMode struct */
+    
+    m->HDisplay  = (int) (h_pixels_rnd);
+    m->HSyncStart = (int) (h_pixels_rnd + h_front_porch);
+    m->HSyncEnd = (int) (h_pixels_rnd + h_front_porch + h_sync);
+    m->HTotal = (int) (total_pixels);
+
+    m->VDisplay  = (int) (v_lines_rnd);
+    m->VSyncStart = (int) (v_lines_rnd + v_odd_front_porch_lines);
+    m->VSyncEnd = (int) (int) (v_lines_rnd + v_odd_front_porch_lines + V_SYNC_RQD);
+    m->VTotal = (int) (total_v_lines);
+
+    m->Clock   = (int)(pixel_freq * 1000);
+    m->SynthClock   = m->Clock;
+    m->HSync = h_freq;
+    m->VRefresh = v_frame_rate /* freq */;
+
+    snprintf(modename, sizeof(modename), "%dx%d", m->HDisplay,m->VDisplay);
+    m->name = xnfstrdup(modename);
+
+    return (m);
+}
diff --git a/src/i830_modes.c b/src/i830_modes.c
index c0c258c..6f878a5 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -197,7 +197,7 @@ I830xf86SortModes(DisplayModePtr *new, D
     }
 }
 
-DisplayModePtr I830xf86DDCModes(ScrnInfoPtr pScrn)
+DisplayModePtr I830GetDDCModes(ScrnInfoPtr pScrn, xf86MonPtr ddc)
 {
     DisplayModePtr  p;
     DisplayModePtr  last  = NULL;
@@ -206,7 +206,9 @@ DisplayModePtr I830xf86DDCModes(ScrnInfo
     int             count = 0;
     int             j, tmp;
     char            stmp[32];
-    xf86MonPtr      ddc   = pScrn->monitor->DDC;
+
+    if (ddc == NULL)
+	return NULL;
 
     /* Go thru detailed timing table first */
     for (j = 0; j < 4; j++) {
@@ -327,30 +329,17 @@ DisplayModePtr I830xf86DDCModes(ScrnInfo
     }
 
     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-	       "Total of %d mode(s) found.\n", count);
+	       "Total of %d DDC mode(s) found.\n", count);
 
     return first;
 }
 
-static void
-i830SetModeToPanelParameters(ScrnInfoPtr pScrn, DisplayModePtr pMode)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-
-   pMode->HTotal     = pI830->panel_fixed_hactive;
-   pMode->HSyncStart = pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff;
-   pMode->HSyncEnd   = pMode->HSyncStart + pI830->panel_fixed_hsyncwidth;
-   pMode->VTotal     = pI830->panel_fixed_vactive;
-   pMode->VSyncStart = pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff;
-   pMode->VSyncEnd   = pMode->VSyncStart + pI830->panel_fixed_vsyncwidth;
-   pMode->Clock      = pI830->panel_fixed_clock;
-}
-
 /**
  * This function returns a default mode for flat panels using the timing
  * information provided by the BIOS.
  */
-static DisplayModePtr i830FPNativeMode(ScrnInfoPtr pScrn)
+static DisplayModePtr
+i830FPNativeMode(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
    DisplayModePtr  new;
@@ -366,7 +355,14 @@ static DisplayModePtr i830FPNativeMode(S
    strcpy(new->name, stmp);
    new->HDisplay   = pI830->PanelXRes;
    new->VDisplay   = pI830->PanelYRes;
-   i830SetModeToPanelParameters(pScrn, new);
+   new->HSyncStart = pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff;
+   new->HSyncEnd   = new->HSyncStart + pI830->panel_fixed_hsyncwidth;
+   new->HTotal     = new->HSyncEnd + 1;
+   new->VSyncStart = pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff;
+   new->VSyncEnd   = new->VSyncStart + pI830->panel_fixed_vsyncwidth;
+   new->VTotal     = new->VSyncEnd + 1;
+   new->Clock      = pI830->panel_fixed_clock;
+
    new->type       = M_T_USERDEF;
 
    pScrn->virtualX = MAX(pScrn->virtualX, pI830->PanelXRes);
@@ -380,10 +376,21 @@ static DisplayModePtr i830FPNativeMode(S
    return new;
 }
 
-/* FP mode validation routine for using panel fitting.
+/**
+ * FP automatic modelist creation routine for using panel fitting.
+ *
+ * Constructs modes for any resolution less than the panel size specified by the
+ * user, with the user flag set, plus standard VESA mode sizes without the user
+ * flag set (for randr).
+ *
+ * Modes will be faked to use GTF parameters, even though at the time of being
+ * programmed into the LVDS they'll end up being forced to the panel's fixed
+ * mode.
+ *
+ * \return doubly-linked list of modes.
  */
-int
-i830ValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName)
+DisplayModePtr
+i830GetLVDSModes(ScrnInfoPtr pScrn, char **ppModeName)
 {
    I830Ptr pI830 = I830PTR(pScrn);
    DisplayModePtr  last       = NULL;
@@ -419,14 +426,8 @@ i830ValidateFPModes(ScrnInfoPtr pScrn, c
 	 continue;
       }
 
-      new             = xnfcalloc(1, sizeof(DisplayModeRec));
-      new->name       = xnfalloc(strlen(ppModeName[i]) + 1);
-      strcpy(new->name, ppModeName[i]);
-      new->HDisplay   = width;
-      new->VDisplay   = height;
-      new->type      |= M_T_USERDEF;
-
-      i830SetModeToPanelParameters(pScrn, new);
+      new = i830GetGTF(width, height, 60.0, FALSE, FALSE);
+      new->type |= M_T_USERDEF;
 
       new->next       = NULL;
       new->prev       = last;
@@ -437,21 +438,19 @@ i830ValidateFPModes(ScrnInfoPtr pScrn, c
       if (!first)
 	 first = new;
 
-      pScrn->display->virtualX = pScrn->virtualX = MAX(pScrn->virtualX, width);
-      pScrn->display->virtualY = pScrn->virtualY = MAX(pScrn->virtualY, height);
       count++;
       xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		 "Valid mode using panel fitting: %s\n", new->name);
    }
 
-   /* If all else fails, add the native mode */
+   /* If the user hasn't specified modes, add the native mode */
    if (!count) {
       first = last = i830FPNativeMode(pScrn);
       if (first)
 	 count = 1;
    }
 
-   /* add in all default vesa modes smaller than panel size, used for randr*/
+   /* add in all default vesa modes smaller than panel size, used for randr */
    for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) {
       if ((p->HDisplay <= pI830->PanelXRes) && (p->VDisplay <= pI830->PanelYRes)) {
 	 tmp = first;
@@ -460,13 +459,11 @@ i830ValidateFPModes(ScrnInfoPtr pScrn, c
 	       tmp = tmp->next;
 	 }
 	 if (!tmp) {
-	    new             = xnfcalloc(1, sizeof(DisplayModeRec));
-	    new->name       = xnfalloc(strlen(p->name) + 1);
-	    strcpy(new->name, p->name);
-	    new->HDisplay   = p->HDisplay;
-	    new->VDisplay   = p->VDisplay;
-	    i830SetModeToPanelParameters(pScrn, new);
-	    new->type      |= M_T_DEFAULT;
+	    new = i830GetGTF(p->HDisplay, p->VDisplay, 60.0, FALSE, FALSE);
+	    if (ppModeName[i] == NULL)
+		new->type |= M_T_USERDEF;
+	    else
+		new->type |= M_T_DEFAULT;
 
 	    new->next       = NULL;
 	    new->prev       = last;
@@ -476,166 +473,202 @@ i830ValidateFPModes(ScrnInfoPtr pScrn, c
 	    last = new;
 	    if (!first)
 	       first = new;
+
+	    count++;
 	 }
       }
    }
 
-   /* Close the doubly-linked mode list, if we found any usable modes */
-   if (last) {
-      last->next   = first;
-      first->prev  = last;
-      pScrn->modes = first;
-   }
-
    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 	      "Total number of valid FP mode(s) found: %d\n", count);
 
-   /* Adjust the display pitch to fit the modes we've come up with. */
-   pScrn->displayWidth = MAX(pScrn->displayWidth, pScrn->virtualX);
-   pScrn->displayWidth = (pScrn->displayWidth + 63) & ~63;
-
-   return count;
+   return first;
 }
 
-/* XFree86's xf86ValidateModes routine doesn't work well with DDC modes,
- * so here is our own validation routine.
+/**
+ * Allocates and returns a copy of pMode, including pointers within pMode.
  */
-int I830xf86ValidateDDCModes(ScrnInfoPtr pScrn1, char **ppModeName)
+static DisplayModePtr
+I830DuplicateMode(DisplayModePtr pMode)
 {
-    DisplayModePtr  p;
-    DisplayModePtr  last       = NULL;
-    DisplayModePtr  first      = NULL;
-    DisplayModePtr  ddcModes   = NULL;
-    int             count      = 0;
-    int             i, width, height;
-    ScrnInfoPtr pScrn = pScrn1;
-
-    pScrn->virtualX = pScrn1->display->virtualX;
-    pScrn->virtualY = pScrn1->display->virtualY;
-
-    if (pScrn->monitor->DDC) {
-	int  maxVirtX = pScrn->virtualX;
-	int  maxVirtY = pScrn->virtualY;
+    DisplayModePtr pNew;
 
-	/* Collect all of the DDC modes */
-	first = last = ddcModes = I830xf86DDCModes(pScrn);
+    pNew = xnfalloc(sizeof(DisplayModeRec));
+    *pNew = *pMode;
+    pNew->next = NULL;
+    pNew->prev = NULL;
+    pNew->name = xnfstrdup(pMode->name);
 
-	for (p = ddcModes; p; p = p->next) {
+    return pNew;
+}
 
-	    maxVirtX = MAX(maxVirtX, p->HDisplay);
-	    maxVirtY = MAX(maxVirtY, p->VDisplay);
-	    count++;
+/**
+ * Injects a list of probed modes into another mode list.
+ *
+ * Take the doubly-linked list of modes we've probed for the device, and injects
+ * it into the doubly-linked modeList.  We don't need to filter, because the
+ * eventual call to xf86ValidateModes will do this for us.  I think.
+ */
+int
+I830InjectProbedModes(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+		      char **ppModeName, DisplayModePtr addModes)
+{
+    DisplayModePtr  last = modeList;
+    DisplayModePtr  first = modeList;
+    DisplayModePtr  addMode;
+    int count = 0;
+
+    for (addMode = addModes; addMode != NULL; addMode = addMode->next) {
+	DisplayModePtr pNew;
+
+	/* XXX: Do we need to check if modeList already contains the same mode?
+	 */
+
+	pNew = I830DuplicateMode(addMode);
+	/* If the user didn't specify any modes, mark all modes as M_T_USERDEF
+	 * so that we can cycle through them, etc.  XXX: really need to?
+	 */
+	if (ppModeName[0] == NULL) {
+	    pNew->type |= M_T_USERDEF;
+	}
 
-	    last = p;
+	/* Insert pNew into modeList */
+	if (last) {
+	    last->next = pNew;
+	    pNew->prev = last;
+	} else {
+	    first = pNew;
+	    pNew->prev = NULL;
 	}
+	pNew->next = NULL;
+	last = pNew;
 
-	/* Match up modes that are specified in the XF86Config file */
-	if (ppModeName[0]) {
-	    DisplayModePtr  next;
-
-	    /* Reset the max virtual dimensions */
-	    maxVirtX = pScrn->virtualX;
-	    maxVirtY = pScrn->virtualY;
-
-	    /* Reset list */
-	    first = last = NULL;
-
-	    for (i = 0; ppModeName[i]; i++) {
-		/* FIXME: Use HDisplay and VDisplay instead of mode string */
-		if (sscanf(ppModeName[i], "%dx%d", &width, &height) == 2) {
-		    for (p = ddcModes; p; p = next) {
-			next = p->next;
-
-			if (p->HDisplay == width && p->VDisplay == height) {
-			    /* We found a DDC mode that matches the one
-                               requested in the XF86Config file */
-			    p->type |= M_T_USERDEF;
-
-			    /* Update  the max virtual setttings */
-			    maxVirtX = MAX(maxVirtX, width);
-			    maxVirtY = MAX(maxVirtY, height);
-
-			    /* Unhook from DDC modes */
-			    if (p->prev) p->prev->next = p->next;
-			    if (p->next) p->next->prev = p->prev;
-			    if (p == ddcModes) ddcModes = p->next;
-
-			    /* Add to used modes */
-			    if (last) {
-				last->next = p;
-				p->prev = last;
-			    } else {
-				first = p;
-				p->prev = NULL;
-			    }
-			    p->next = NULL;
-			    last = p;
+	count++;
+    }
 
-			    break;
-			}
-		    }
-		}
-	    }
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+	       "Injected %d modes detected from the monitor\n", count);
 
-	    /*
-	     * Add remaining DDC modes if they're smaller than the user
-	     * specified modes
-	     */
-	    for (p = ddcModes; p; p = next) {
-		next = p->next;
-		if (p->HDisplay <= maxVirtX && p->VDisplay <= maxVirtY) {
-		    /* Unhook from DDC modes */
-		    if (p->prev) p->prev->next = p->next;
-		    if (p->next) p->next->prev = p->prev;
-		    if (p == ddcModes) ddcModes = p->next;
-
-		    /* Add to used modes */
-		    if (last) {
-			last->next = p;
-			p->prev = last;
-		    } else {
-			first = p;
-			p->prev = NULL;
-		    }
-		    p->next = NULL;
-		    last = p;
-		}
-	    }
+    return count;
+}
 
-	    /* Delete unused modes */
-	    while (ddcModes)
-		xf86DeleteMode(&ddcModes, ddcModes);
-	} else {
-	    /*
-	     * No modes were configured, so we make the DDC modes
-	     * available for the user to cycle through.
-	     */
-	    for (p = ddcModes; p; p = p->next)
-		p->type |= M_T_USERDEF;
+/**
+ * Performs probing of modes available on the output connected to the given
+ * pipe.
+ *
+ * We do not support multiple outputs per pipe (since the cases for that are
+ * sufficiently rare we can't imagine the complexity being worth it), so
+ * the pipe is a sufficient specifier.
+ */
+static void
+I830ReprobePipeModeList(ScrnInfoPtr pScrn, int pipe)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    int output_index = -1;
+    int i;
+    int outputs;
+
+    while (pI830->pipeModes[pipe] != NULL)
+	xf86DeleteMode(&pI830->pipeModes[pipe], pI830->pipeModes[pipe]);
+
+    if (pipe == 0)
+	outputs = pI830->operatingDevices & 0xff;
+    else
+	outputs = (pI830->operatingDevices >> 8) & 0xff;
+
+    for (i = 0; i < MAX_OUTPUTS; i++) {
+	switch (pI830->output[i].type) {
+	case I830_OUTPUT_ANALOG:
+	    if (outputs & PIPE_CRT) {
+		output_index = i;
+	    }
+	    break;
+	case I830_OUTPUT_LVDS:
+	    if (outputs & PIPE_LFP) {
+		output_index = i;
+	    }
+	    break;
+	case I830_OUTPUT_SDVO:
+	    if (outputs & PIPE_DFP) {
+		output_index = i;
+	    }
+	    break;
 	}
+    }
+    /* XXX: If there's no output associated with the pipe, bail for now. */
+    if (output_index == -1)
+	return;
+
+    if (outputs & PIPE_LFP) {
+	pI830->pipeMon[pipe] = NULL; /* XXX */
+	pI830->pipeModes[pipe] = i830GetLVDSModes(pScrn,
+						  pScrn->display->modes);
+    } else if (pI830->output[output_index].pDDCBus != NULL) {
+	/* XXX: Free the mon */
+	pI830->pipeMon[pipe] = xf86DoEDID_DDC2(pScrn->scrnIndex,
+					       pI830->output[output_index].pDDCBus);
+	pI830->pipeModes[pipe] = I830GetDDCModes(pScrn,
+						 pI830->pipeMon[pipe]);
+    } else {
+	ErrorF("don't know how to get modes for this device.\n");
+    }
+}
 
-	pScrn->virtualX = pScrn->display->virtualX = maxVirtX;
-	pScrn->virtualY = pScrn->display->virtualY = maxVirtY;
+/**
+ * Probes for video modes on attached otuputs, and assembles a list to insert
+ * into pScrn.
+ */
+int
+I830ValidateXF86ModeList(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    ClockRangePtr clockRanges;
+    int n, pipe;
+
+    for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++) {
+	I830ReprobePipeModeList(pScrn, pipe);
     }
 
-    /* Close the doubly-linked mode list, if we found any usable modes */
-    if (last) {
-      DisplayModePtr  temp      = NULL;
-        /* we should add these to pScrn monitor modes */
-      last->next   = pScrn->monitor->Modes;
-      temp = pScrn->monitor->Modes->prev;
-      pScrn->monitor->Modes->prev = first;
-      pScrn->monitor->Modes->prev = last;
-
-      first->prev = temp;
-      if (temp)
-	temp->next = first;
+    /* XXX: Clean out modes previously injected by our driver */
 
-      pScrn->monitor->Modes = first;
+    if (pI830->pipeModes[0] != NULL) {
+	I830InjectProbedModes(pScrn, pScrn->monitor->Modes,
+			      pScrn->display->modes, pI830->pipeModes[0]);
+    }
+    if (pI830->pipeModes[1] != NULL) {
+	I830InjectProbedModes(pScrn, pScrn->monitor->Modes,
+			      pScrn->display->modes, pI830->pipeModes[1]);
     }
 
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-	       "Total number of valid DDC mode(s) found: %d\n", count);
+   /*
+     * Set up the ClockRanges, which describe what clock ranges are available,
+     * and what sort of modes they can be used for.
+     */
+    clockRanges = xnfcalloc(sizeof(ClockRange), 1);
+    clockRanges->next = NULL;
+    clockRanges->minClock = 25000;
+    clockRanges->maxClock = pI830->MaxClock;
+    clockRanges->clockIndex = -1;		/* programmable */
+    clockRanges->interlaceAllowed = TRUE;	/* XXX check this */
+    clockRanges->doubleScanAllowed = FALSE;	/* XXX check this */
+
+    /* Take the pScrn->monitor->Modes we've accumulated and validate them into
+     * pScrn->modes.
+     */
+    n = xf86ValidateModes(pScrn,
+			  pScrn->monitor->Modes, /* availModes */
+			  pScrn->display->modes, /* modeNames */
+			  clockRanges, /* clockRanges */
+			  NULL, /* linePitches */
+			  320, /* minPitch */
+			  MAX_DISPLAY_PITCH, /* maxPitch */
+			  64 * pScrn->bitsPerPixel, /* pitchInc */
+			  200, /* minHeight */
+			  MAX_DISPLAY_HEIGHT, /* maxHeight */
+			  pScrn->display->virtualX, /* virtualX */
+			  pScrn->display->virtualY, /* virtualY */
+			  pI830->FbMapSize, /* apertureSize */
+			  LOOKUP_BEST_REFRESH /* strategy */);
 
-    return count;
+    return n;
 }
diff-tree bb4810521633b6c3db2fc7d01ddc71325583d265 (from 66d9a1be302ad34573de98de21cbdf6419592092)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Thu Jun 22 09:38:27 2006 -0700

    Move FP mode validation next to other mode validation code.

diff --git a/src/i830.h b/src/i830.h
index d5bb9c6..26a0063 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -594,6 +594,7 @@ extern Bool I830RandRInit(ScreenPtr pScr
 extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg,
 			char *name);
 int I830xf86ValidateDDCModes(ScrnInfoPtr pScrn1, char **ppModeName);
+int i830ValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName);
 
 /*
  * 12288 is set as the maximum, chosen because it is enough for
diff --git a/src/i830_driver.c b/src/i830_driver.c
index c51587b..f3cb186 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1245,170 +1245,6 @@ I830IsPrimary(ScrnInfoPtr pScrn)
    return TRUE;
 }
 
-static void
-i830SetModeToPanelParameters(ScrnInfoPtr pScrn, DisplayModePtr pMode)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-
-   pMode->HTotal     = pI830->panel_fixed_hactive;
-   pMode->HSyncStart = pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff;
-   pMode->HSyncEnd   = pMode->HSyncStart + pI830->panel_fixed_hsyncwidth;
-   pMode->VTotal     = pI830->panel_fixed_vactive;
-   pMode->VSyncStart = pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff;
-   pMode->VSyncEnd   = pMode->VSyncStart + pI830->panel_fixed_vsyncwidth;
-   pMode->Clock      = pI830->panel_fixed_clock;
-}
-
-/**
- * This function returns a default mode for flat panels using the timing
- * information provided by the BIOS.
- */
-static DisplayModePtr i830FPNativeMode(ScrnInfoPtr pScrn)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   DisplayModePtr  new;
-   char            stmp[32];
-
-   if (pI830->PanelXRes == 0 || pI830->PanelYRes == 0)
-      return NULL;
-
-   /* Add native panel size */
-   new             = xnfcalloc(1, sizeof (DisplayModeRec));
-   sprintf(stmp, "%dx%d", pI830->PanelXRes, pI830->PanelYRes);
-   new->name       = xnfalloc(strlen(stmp) + 1);
-   strcpy(new->name, stmp);
-   new->HDisplay   = pI830->PanelXRes;
-   new->VDisplay   = pI830->PanelYRes;
-   i830SetModeToPanelParameters(pScrn, new);
-   new->type       = M_T_USERDEF;
-
-   pScrn->virtualX = MAX(pScrn->virtualX, pI830->PanelXRes);
-   pScrn->virtualY = MAX(pScrn->virtualY, pI830->PanelYRes);
-   pScrn->display->virtualX = pScrn->virtualX;
-   pScrn->display->virtualY = pScrn->virtualY;
-
-   xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-	      "No valid mode specified, force to native mode\n");
-
-   return new;
-}
-
-/* FP mode validation routine for using panel fitting.
- */
-static int i830ValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   DisplayModePtr  last       = NULL;
-   DisplayModePtr  new        = NULL;
-   DisplayModePtr  first      = NULL;
-   DisplayModePtr  p, tmp;
-   int             count      = 0;
-   int             i, width, height;
-
-   pScrn->virtualX = pScrn->display->virtualX;
-   pScrn->virtualY = pScrn->display->virtualY;
-
-   /* We have a flat panel connected to the primary display, and we
-    * don't have any DDC info.
-    */
-   for (i = 0; ppModeName[i] != NULL; i++) {
-
-      if (sscanf(ppModeName[i], "%dx%d", &width, &height) != 2)
-	 continue;
-
-      /* Note: We allow all non-standard modes as long as they do not
-       * exceed the native resolution of the panel.  Since these modes
-       * need the internal RMX unit in the video chips (and there is
-       * only one per card), this will only apply to the primary head.
-       */
-      if (width < 320 || width > pI830->PanelXRes ||
-	 height < 200 || height > pI830->PanelYRes) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Mode %s is out of range.\n",
-		    ppModeName[i]);
-	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		    "Valid modes must be between 320x200-%dx%d\n",
-		    pI830->PanelXRes, pI830->PanelYRes);
-	 continue;
-      }
-
-      new             = xnfcalloc(1, sizeof(DisplayModeRec));
-      new->name       = xnfalloc(strlen(ppModeName[i]) + 1);
-      strcpy(new->name, ppModeName[i]);
-      new->HDisplay   = width;
-      new->VDisplay   = height;
-      new->type      |= M_T_USERDEF;
-
-      i830SetModeToPanelParameters(pScrn, new);
-
-      new->next       = NULL;
-      new->prev       = last;
-
-      if (last)
-	 last->next = new;
-      last = new;
-      if (!first)
-	 first = new;
-
-      pScrn->display->virtualX = pScrn->virtualX = MAX(pScrn->virtualX, width);
-      pScrn->display->virtualY = pScrn->virtualY = MAX(pScrn->virtualY, height);
-      count++;
-      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		 "Valid mode using panel fitting: %s\n", new->name);
-   }
-
-   /* If all else fails, add the native mode */
-   if (!count) {
-      first = last = i830FPNativeMode(pScrn);
-      if (first)
-	 count = 1;
-   }
-
-   /* add in all default vesa modes smaller than panel size, used for randr*/
-   for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) {
-      if ((p->HDisplay <= pI830->PanelXRes) && (p->VDisplay <= pI830->PanelYRes)) {
-	 tmp = first;
-	 while (tmp) {
-	    if ((p->HDisplay == tmp->HDisplay) && (p->VDisplay == tmp->VDisplay)) break;
-	       tmp = tmp->next;
-	 }
-	 if (!tmp) {
-	    new             = xnfcalloc(1, sizeof(DisplayModeRec));
-	    new->name       = xnfalloc(strlen(p->name) + 1);
-	    strcpy(new->name, p->name);
-	    new->HDisplay   = p->HDisplay;
-	    new->VDisplay   = p->VDisplay;
-	    i830SetModeToPanelParameters(pScrn, new);
-	    new->type      |= M_T_DEFAULT;
-
-	    new->next       = NULL;
-	    new->prev       = last;
-
-	    if (last)
-	       last->next = new;
-	    last = new;
-	    if (!first)
-	       first = new;
-	 }
-      }
-   }
-
-   /* Close the doubly-linked mode list, if we found any usable modes */
-   if (last) {
-      last->next   = first;
-      first->prev  = last;
-      pScrn->modes = first;
-   }
-
-   xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-	      "Total number of valid FP mode(s) found: %d\n", count);
-
-   /* Adjust the display pitch to fit the modes we've come up with. */
-   pScrn->displayWidth = MAX(pScrn->displayWidth, pScrn->virtualX);
-   pScrn->displayWidth = (pScrn->displayWidth + 63) & ~63;
-
-   return count;
-}
-
 static Bool
 I830BIOSPreInit(ScrnInfoPtr pScrn, int flags)
 {
diff --git a/src/i830_modes.c b/src/i830_modes.c
index ce86d8c..c0c258c 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -332,6 +332,171 @@ DisplayModePtr I830xf86DDCModes(ScrnInfo
     return first;
 }
 
+static void
+i830SetModeToPanelParameters(ScrnInfoPtr pScrn, DisplayModePtr pMode)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+
+   pMode->HTotal     = pI830->panel_fixed_hactive;
+   pMode->HSyncStart = pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff;
+   pMode->HSyncEnd   = pMode->HSyncStart + pI830->panel_fixed_hsyncwidth;
+   pMode->VTotal     = pI830->panel_fixed_vactive;
+   pMode->VSyncStart = pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff;
+   pMode->VSyncEnd   = pMode->VSyncStart + pI830->panel_fixed_vsyncwidth;
+   pMode->Clock      = pI830->panel_fixed_clock;
+}
+
+/**
+ * This function returns a default mode for flat panels using the timing
+ * information provided by the BIOS.
+ */
+static DisplayModePtr i830FPNativeMode(ScrnInfoPtr pScrn)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+   DisplayModePtr  new;
+   char            stmp[32];
+
+   if (pI830->PanelXRes == 0 || pI830->PanelYRes == 0)
+      return NULL;
+
+   /* Add native panel size */
+   new             = xnfcalloc(1, sizeof (DisplayModeRec));
+   sprintf(stmp, "%dx%d", pI830->PanelXRes, pI830->PanelYRes);
+   new->name       = xnfalloc(strlen(stmp) + 1);
+   strcpy(new->name, stmp);
+   new->HDisplay   = pI830->PanelXRes;
+   new->VDisplay   = pI830->PanelYRes;
+   i830SetModeToPanelParameters(pScrn, new);
+   new->type       = M_T_USERDEF;
+
+   pScrn->virtualX = MAX(pScrn->virtualX, pI830->PanelXRes);
+   pScrn->virtualY = MAX(pScrn->virtualY, pI830->PanelYRes);
+   pScrn->display->virtualX = pScrn->virtualX;
+   pScrn->display->virtualY = pScrn->virtualY;
+
+   xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+	      "No valid mode specified, force to native mode\n");
+
+   return new;
+}
+
+/* FP mode validation routine for using panel fitting.
+ */
+int
+i830ValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+   DisplayModePtr  last       = NULL;
+   DisplayModePtr  new        = NULL;
+   DisplayModePtr  first      = NULL;
+   DisplayModePtr  p, tmp;
+   int             count      = 0;
+   int             i, width, height;
+
+   pScrn->virtualX = pScrn->display->virtualX;
+   pScrn->virtualY = pScrn->display->virtualY;
+
+   /* We have a flat panel connected to the primary display, and we
+    * don't have any DDC info.
+    */
+   for (i = 0; ppModeName[i] != NULL; i++) {
+
+      if (sscanf(ppModeName[i], "%dx%d", &width, &height) != 2)
+	 continue;
+
+      /* Note: We allow all non-standard modes as long as they do not
+       * exceed the native resolution of the panel.  Since these modes
+       * need the internal RMX unit in the video chips (and there is
+       * only one per card), this will only apply to the primary head.
+       */
+      if (width < 320 || width > pI830->PanelXRes ||
+	 height < 200 || height > pI830->PanelYRes) {
+	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Mode %s is out of range.\n",
+ 		    ppModeName[i]);
+	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		    "Valid modes must be between 320x200-%dx%d\n",
+		    pI830->PanelXRes, pI830->PanelYRes);
+	 continue;
+      }
+
+      new             = xnfcalloc(1, sizeof(DisplayModeRec));
+      new->name       = xnfalloc(strlen(ppModeName[i]) + 1);
+      strcpy(new->name, ppModeName[i]);
+      new->HDisplay   = width;
+      new->VDisplay   = height;
+      new->type      |= M_T_USERDEF;
+
+      i830SetModeToPanelParameters(pScrn, new);
+
+      new->next       = NULL;
+      new->prev       = last;
+
+      if (last)
+	 last->next = new;
+      last = new;
+      if (!first)
+	 first = new;
+
+      pScrn->display->virtualX = pScrn->virtualX = MAX(pScrn->virtualX, width);
+      pScrn->display->virtualY = pScrn->virtualY = MAX(pScrn->virtualY, height);
+      count++;
+      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		 "Valid mode using panel fitting: %s\n", new->name);
+   }
+
+   /* If all else fails, add the native mode */
+   if (!count) {
+      first = last = i830FPNativeMode(pScrn);
+      if (first)
+	 count = 1;
+   }
+
+   /* add in all default vesa modes smaller than panel size, used for randr*/
+   for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) {
+      if ((p->HDisplay <= pI830->PanelXRes) && (p->VDisplay <= pI830->PanelYRes)) {
+	 tmp = first;
+	 while (tmp) {
+	    if ((p->HDisplay == tmp->HDisplay) && (p->VDisplay == tmp->VDisplay)) break;
+	       tmp = tmp->next;
+	 }
+	 if (!tmp) {
+	    new             = xnfcalloc(1, sizeof(DisplayModeRec));
+	    new->name       = xnfalloc(strlen(p->name) + 1);
+	    strcpy(new->name, p->name);
+	    new->HDisplay   = p->HDisplay;
+	    new->VDisplay   = p->VDisplay;
+	    i830SetModeToPanelParameters(pScrn, new);
+	    new->type      |= M_T_DEFAULT;
+
+	    new->next       = NULL;
+	    new->prev       = last;
+
+	    if (last)
+	       last->next = new;
+	    last = new;
+	    if (!first)
+	       first = new;
+	 }
+      }
+   }
+
+   /* Close the doubly-linked mode list, if we found any usable modes */
+   if (last) {
+      last->next   = first;
+      first->prev  = last;
+      pScrn->modes = first;
+   }
+
+   xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+	      "Total number of valid FP mode(s) found: %d\n", count);
+
+   /* Adjust the display pitch to fit the modes we've come up with. */
+   pScrn->displayWidth = MAX(pScrn->displayWidth, pScrn->virtualX);
+   pScrn->displayWidth = (pScrn->displayWidth + 63) & ~63;
+
+   return count;
+}
+
 /* XFree86's xf86ValidateModes routine doesn't work well with DDC modes,
  * so here is our own validation routine.
  */
diff-tree 66d9a1be302ad34573de98de21cbdf6419592092 (from 72e25a7488c2eabcc92e9e0769a89dee687f52fd)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Wed Jun 21 17:11:54 2006 -0700

    Detect SDVO display presence at startup and default to displaying to it, too.

diff --git a/src/i830_display.c b/src/i830_display.c
index 0fadc0c..8843f98 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -514,11 +514,6 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 
 	/* And then turn the plane on */
 	OUTREG(DSPACNTR, dspcntr);
-
-	if (is_sdvo) {
-	  OUTREG(SDVOB, sdvob);
-	  OUTREG(SDVOC, sdvoc);
-	}
     } else {
 	/* Always make sure the LVDS is off before we play with DPLLs and pipe
 	 * configuration.
@@ -591,6 +586,11 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     if (outputs & PIPE_CRT_ACTIVE)
 	OUTREG(ADPA, adpa);
 
+    if (is_sdvo) {
+	OUTREG(SDVOB, sdvob);
+	OUTREG(SDVOC, sdvoc);
+    }
+
     return TRUE;
 }
 
diff --git a/src/i830_driver.c b/src/i830_driver.c
index c0938fa..c51587b 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1841,7 +1841,12 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
 
    I830DetectMonitors(pScrn);
 
-   for (i = 0; i < MAX_OUTPUTS; i++) {
+   /* Walk from the end so we'll happen to hit SDVO first, if we found some. An
+    * SDVO device is probably a DFP, and so probably pickier than (say) a CRT
+    * that we might find early in the list.  This hackery will go away when we
+    * start doing independent per-head mode selection.
+    */
+   for (i = MAX_OUTPUTS - 1; i >= 0; i--) {
      if (pI830->output[i].MonInfo) {
        pScrn->monitor->DDC = pI830->output[i].MonInfo;
        xf86SetDDCproperties(pScrn, pI830->output[i].MonInfo);
@@ -1956,6 +1961,23 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
 	 pI830->MonType1 |= PIPE_CRT;
       }
 
+      /* Check for attached SDVO outputs.  Assume that they're flat panels for
+       * now.  Though really, it's just a name at the moment, since we don't
+       * treat different SDVO outputs differently.
+       */
+      for (i = 0; i < MAX_OUTPUTS; i++) {
+	 if (pI830->output[i].type == I830_OUTPUT_SDVO &&
+	     pI830->output[i].sdvo_drv != NULL) {
+	    if (!I830DetectSDVODisplays(pScrn, i))
+	       continue;
+
+	    if (pI830->MonType1 == PIPE_NONE)
+	       pI830->MonType1 |= PIPE_DFP;
+	    else if (pI830->MonType2 == PIPE_NONE)
+	       pI830->MonType2 |= PIPE_DFP;
+	 }
+      }
+
       /* And, if we haven't found anything (including CRT through DDC), assume
        * that there's a CRT and that the user has set up some appropriate modes
        * or something.
@@ -4584,17 +4606,31 @@ I830CheckDevicesTimer(OsTimerPtr timer, 
    int cloned = 0;
 #if 0
    Bool found_crt;
-   int start, finish;
+   int start, finish, i;
 
    if (!pScrn->vtSema)
       return 1000;
 
    start = GetTimeInMillis();
-   found_crt = i830DetectCRT(pScrn, FALSE);
+   found_crt = i830DetectCRT(pScrn, FALSE);   
    finish = GetTimeInMillis();
-
    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Detected CRT as %s in %dms\n",
 	      found_crt ? "connected" : "disconnected", finish - start);
+
+   for (i = 0; i < MAX_OUTPUTS; i++) {
+      Bool found_sdvo = TRUE;
+
+      if (pI830->output[i].type != I830_OUTPUT_SDVO ||
+	  pI830->output[i].sdvo_drv == NULL)
+      {
+	 continue;
+      }
+      start = GetTimeInMillis();
+      found_sdvo = I830DetectSDVODisplays(pScrn, i);   
+      finish = GetTimeInMillis();
+      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Detected SDVO as %s in %dms\n",
+		 found_sdvo ? "connected" : "disconnected", finish - start);
+   }
 #endif
 
    if (pScrn->vtSema) {
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index c14277e..06840ef 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -947,3 +947,29 @@ I830DumpSDVO (ScrnInfoPtr pScrn)
 	    I830DumpOneSDVO (s);
     }
 }
+
+/**
+ * Asks the SDVO device if any displays are currently connected.
+ *
+ * This interface will need to be augmented, since we could potentially have
+ * multiple displays connected, and the caller will also probably want to know
+ * what type of display is connected.  But this is enough for the moment.
+ *
+ * Takes 14ms on average on my i945G.
+ */
+Bool
+I830DetectSDVODisplays(ScrnInfoPtr pScrn, int output_index)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830SDVOPtr s = pI830->output[output_index].sdvo_drv;
+
+    s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_ATTACHED_DISPLAYS;
+    I830SDVOWriteOutputs(s, 0);
+    I830SDVOReadInputRegs(s);
+
+    if (s->sdvo_regs[SDVO_I2C_CMD_STATUS] != SDVO_CMD_STATUS_SUCCESS)
+	return FALSE;
+
+    return (s->sdvo_regs[SDVO_I2C_RETURN_0] != 0 ||
+	    s->sdvo_regs[SDVO_I2C_RETURN_1] != 0);
+}
diff --git a/src/i830_sdvo.h b/src/i830_sdvo.h
index 6b77c97..d52eb60 100644
--- a/src/i830_sdvo.h
+++ b/src/i830_sdvo.h
@@ -63,3 +63,6 @@ i830SDVOPreRestore(ScrnInfoPtr pScrn, in
 
 void
 i830SDVOPostRestore(ScrnInfoPtr pScrn, int output_index);
+
+Bool
+I830DetectSDVODisplays(ScrnInfoPtr pScrn, int output_index);
diff-tree 72e25a7488c2eabcc92e9e0769a89dee687f52fd (from 726443309d72134341cff1f6db978aa1d6e3ce52)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Wed Jun 21 16:04:18 2006 -0700

    Fix SDVO output at low pixel clocks.
    
    I had interpreted the docs as saying that the multiplier setting would further
    divide the clock and stuff dummy bytes in.  Instead, we have to set the DPLL at
    the higher clock rate, and the pixel multiplier just controls the stuffing of
    dummy bytes.  Also, we have to set the multiplier both in the graphics chip and
    on the SDVO device on the other side.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index b95f795..e8462f9 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -726,7 +726,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 # define PLLB_REF_INPUT_SPREADSPECTRUMIN	(3 << 13)
 # define DISPLAY_RATE_SELECT_FPA1		(1 << 8)
 # define SDVO_MULTIPLIER_MASK			0x000000ff
-# define SDVO_DEFAULT_MULTIPLIER		0x00000003
+# define SDVO_MULTIPLIER_SHIFT_HIRES		4
+# define SDVO_MULTIPLIER_SHIFT_VGA		0
 
 #define BLC_PWM_CTL		0x61254
 #define BACKLIGHT_MODULATION_FREQ_SHIFT		(17)
@@ -769,6 +770,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define SDVO_INTERRUPT_ENABLE			(1 << 26)
 /* Programmed value is multiplier - 1, up to 5x.  alv, gdg only */
 #define SDVO_PORT_MULTIPLY_MASK			(7 << 23)
+#define SDVO_PORT_MULTIPLY_SHIFT		23
 #define SDVO_PHASE_SELECT_MASK			(15 << 19)
 #define SDVO_PHASE_SELECT_DEFAULT		(6 << 19)
 #define SDVO_CLOCK_OUTPUT_INVERT		(1 << 18)
diff --git a/src/i830_display.c b/src/i830_display.c
index f1642da..0fadc0c 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -259,7 +259,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     CARD32 pipesrc, dspsize, adpa;
     CARD32 sdvob = 0, sdvoc= 0;
     Bool ok, is_sdvo;
-    int refclk, pixel_clock;
+    int refclk, pixel_clock, sdvo_pixel_multiply;
     int outputs;
 
     ErrorF("Requested pix clock: %d\n", pMode->Clock);
@@ -342,6 +342,22 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	pixel_clock = pI830->panel_fixed_clock;
     }
 
+    if (pMode->Clock >= 100000)
+	sdvo_pixel_multiply = 1;
+    else if (pMode->Clock >= 50000)
+	sdvo_pixel_multiply = 2;
+    else
+	sdvo_pixel_multiply = 4;
+
+    /* In SDVO, we need to keep the clock on the bus between 1Ghz and 2Ghz.
+     * The clock on the bus is 10 times the pixel clock normally.  If that
+     * would be too low, we run the DPLL at a multiple of the pixel clock, and
+     * tell the SDVO device the multiplier so it can throw away the dummy bytes.
+     */
+    if (is_sdvo) {
+	pixel_clock *= sdvo_pixel_multiply;
+    }
+
     if (IS_I9XX(pI830)) {
 	refclk = 96000;
     } else {
@@ -386,7 +402,6 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	dpll |= PLL_REF_INPUT_TVCLKINBC;
     else
 	dpll |= PLL_REF_INPUT_DREFCLK;
-    dpll |= SDVO_DEFAULT_MULTIPLIER;
 
     if (is_sdvo) {
 	dpll |= DPLL_DVO_HIGH_SPEED;
@@ -399,6 +414,12 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	sdvoc |= 9 << 19;
 	if (pipe == 1)
 	    sdvob |= SDVO_PIPE_B_SELECT;
+
+	if (IS_I945G(pI830) || IS_I945GM(pI830))
+	    dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
+	else
+	    sdvob |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT;
+
 	OUTREG(SDVOC, INREG(SDVOC) & ~SDVO_ENABLE);
 	OUTREG(SDVOB, INREG(SDVOB) & ~SDVO_ENABLE);
     }
diff-tree 726443309d72134341cff1f6db978aa1d6e3ce52 (from 896ffe78fe96469cdd3ade77c8e68e1503967223)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Wed Jun 21 15:38:19 2006 -0700

    Add decoding of SDVO command names for debug output.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 7d23975..c14277e 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -58,6 +58,50 @@ static Bool sWriteByte(I830SDVOPtr s, in
     return TRUE;
 }
 
+
+#define SDVO_CMD_NAME_ENTRY(cmd) {cmd, #cmd}
+const struct _sdvo_cmd_name {
+    CARD8 cmd;
+    char *name;
+} sdvo_cmd_names[] = {
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_RESET),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DEVICE_CAPS),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FIRMWARE_REV),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TRAINED_INPUTS),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_OUTPUTS),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_OUTPUTS),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_IN_OUT_MAP),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_IN_OUT_MAP),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ATTACHED_DISPLAYS),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HOT_PLUG_SUPPORT),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_HOT_PLUG),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_HOT_PLUG),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INTR_EVENT_SOURCE),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_INPUT),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_OUTPUT),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART1),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART2),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART2),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART1),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART2),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART1),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART2),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_CLOCK_RATE_MULT),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CLOCK_RATE_MULT),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_TV_FORMATS),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_FORMAT),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_FORMAT),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_RESOLUTION_SUPPORT),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTROL_BUS_SWITCH),
+};
 /* following on from tracing the intel BIOS i2c routines */
 static void
 I830SDVOWriteOutputs(I830SDVOPtr s, int num_out)
@@ -67,6 +111,14 @@ I830SDVOWriteOutputs(I830SDVOPtr s, int 
     ErrorF("SDVO: W: %02X ", s->sdvo_regs[SDVO_I2C_OPCODE]);
     for (i = SDVO_I2C_ARG_0; i > SDVO_I2C_ARG_0 - num_out; i--)
 	ErrorF("%02X ", s->sdvo_regs[i]);
+    for (; i > SDVO_I2C_ARG_7; i--)
+	ErrorF("   ");
+    for (i = 0; i < sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]); i++) {
+	if (s->sdvo_regs[SDVO_I2C_OPCODE] == sdvo_cmd_names[i].cmd) {
+	    ErrorF("(%s)", sdvo_cmd_names[i].name);
+	    break;
+	}
+    }
     ErrorF("\n");
 
     /* blast the output regs */
diff-tree 896ffe78fe96469cdd3ade77c8e68e1503967223 (from parents)
Merge: 89c2c4bc40b8c032915ccb3ed4f3c143c3d8db12 52243d407cad93283956660de4771097ac0b4b2d
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Tue Jun 20 15:10:35 2006 -0700

    Merge branch 'modesetting-origin' into modesetting

diff --cc src/i810_reg.h
index c45368d,8fd6022..b95f795
@@@ -746,12 -753,9 +753,13 @@@
  #define PORT_HOTPLUG_STAT	0x61114
  # define CRT_HOTPLUG_INT_STATUS			(1 << 11)
  # define TV_HOTPLUG_INT_STATUS			(1 << 10)
 +# define CRT_HOTPLUG_MONITOR_MASK		(3 << 8)
 +# define CRT_HOTPLUG_MONITOR_COLOR		(3 << 8)
 +# define CRT_HOTPLUG_MONITOR_MONO		(2 << 8)
 +# define CRT_HOTPLUG_MONITOR_NONE		(0 << 8)
  # define SDVOC_HOTPLUG_INT_STATUS		(1 << 7)
  # define SDVOB_HOTPLUG_INT_STATUS		(1 << 6)
+ #define SDVOB_PRESERVE_MASK			((1 << 17) | (1 << 16) | (1 << 14))
  
  #define SDVOB			0x61140
  #define SDVOC			0x61160
diff-tree 89c2c4bc40b8c032915ccb3ed4f3c143c3d8db12 (from be08661e3126907c50c54485042fcde00b0da2b4)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Tue Jun 20 15:10:19 2006 -0700

    Add #if 0-ed code I've been using for CRT detection debugging.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index dd3122e..bc375e7 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -4545,6 +4545,20 @@ I830CheckDevicesTimer(OsTimerPtr timer, 
    ScrnInfoPtr pScrn = (ScrnInfoPtr) arg;
    I830Ptr pI830 = I830PTR(pScrn);
    int cloned = 0;
+#if 0
+   Bool found_crt;
+   int start, finish;
+
+   if (!pScrn->vtSema)
+      return 1000;
+
+   start = GetTimeInMillis();
+   found_crt = i830DetectCRT(pScrn, FALSE);
+   finish = GetTimeInMillis();
+
+   xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Detected CRT as %s in %dms\n",
+	      found_crt ? "connected" : "disconnected", finish - start);
+#endif
 
    if (pScrn->vtSema) {
       /* Check for monitor lid being closed/opened and act accordingly */
diff-tree be08661e3126907c50c54485042fcde00b0da2b4 (from b454c9601f005c69c11556a558150403378d34d9)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Tue Jun 20 14:48:03 2006 -0700

    Only default to enabling CRT or LVDS output if they're actually detected.
    
    Still, if we haven't detected any outputs automatically (including CRT through
    DDC), default to CRT anyway.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index a4fde94..dd3122e 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1952,26 +1952,17 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
 	 pI830->MonType2 |= PIPE_LFP;
       }
 
-      for (i=0; i<pI830->num_outputs; i++) {
-	 if (pI830->output[i].MonInfo == NULL)
-	    continue;
-
-	 switch (pI830->output[i].type) {
-	 case I830_OUTPUT_ANALOG:
-	 case I830_OUTPUT_DVO:
-	    pI830->MonType1 |= PIPE_CRT;
-	    break;
-	 case I830_OUTPUT_LVDS:
-	    pI830->MonType2 |= PIPE_LFP;
-	    break;
-	 case I830_OUTPUT_SDVO:
-	    /* XXX DVO */
-	    break;
-	 case I830_OUTPUT_UNUSED:
-	    break;
-	 }
+      if (i830DetectCRT(pScrn, TRUE)) {
+	 pI830->MonType1 |= PIPE_CRT;
       }
 
+      /* And, if we haven't found anything (including CRT through DDC), assume
+       * that there's a CRT and that the user has set up some appropriate modes
+       * or something.
+       */
+      if (pI830->MonType1 == PIPE_NONE && pI830->MonType2 == PIPE_NONE)
+	 pI830->MonType1 |= PIPE_CRT;
+
       if (pI830->MonType1 != PIPE_NONE)
 	 pI830->pipe = 0;
       else
diff-tree b454c9601f005c69c11556a558150403378d34d9 (from 0b76646666e9d330e77c6f81af8b91e34623be92)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Tue Jun 20 14:32:40 2006 -0700

    Add support for CRT detection using DDC.
    
    This method is slower (~5ms), but works on older chipsets.  Also, load-based
    detection is disabled, as it can be fooled by other outputs on the pipe being
    active, such as LVDS.

diff --git a/src/i830_display.c b/src/i830_display.c
index 6146933..3a4833e 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -737,15 +737,57 @@ i830LoadDetectCRT(ScrnInfoPtr pScrn)
 	return FALSE;
 }
 
+/**
+ * Detects CRT presence by probing for a response on the DDC address.
+ *
+ * This takes approximately 5ms in testing on an i915GM, with CRT connected or
+ * not.
+ */
 Bool
-i830DetectCRT(ScrnInfoPtr pScrn)
+i830DDCDetectCRT(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
+    struct _I830OutputRec *output;
+
+    output = &pI830->output[0];
+    /* CRT should always be at 0, but check anyway */
+    if (output->type != I830_OUTPUT_ANALOG)
+	return FALSE;
+
+    return xf86I2CProbeAddress(output->pDDCBus, 0x00A0);
+}
+
+/**
+ * Attempts to detect CRT presence through any method available.
+ *
+ * @param allow_disturb enables detection methods that may cause flickering
+ *        on active displays.
+ */
+Bool
+i830DetectCRT(ScrnInfoPtr pScrn, Bool allow_disturb)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    Bool found_ddc;
 
     if (IS_I945G(pI830) || IS_I945GM(pI830))
 	return i830HotplugDetectCRT(pScrn);
 
-    return i830LoadDetectCRT(pScrn);
+    found_ddc = i830DDCDetectCRT(pScrn);
+    if (found_ddc)
+	return TRUE;
+
+    /* Use the load-detect method if we're not currently outputting to the CRT,
+     * or we don't care.
+     *
+     * Actually, the method is unreliable currently.  We need to not share a
+     * pipe, as it seems having other outputs on that pipe will result in a
+     * false positive.
+     */
+    if (0 && (allow_disturb || !(INREG(ADPA) & !ADPA_DAC_ENABLE))) {
+	return i830LoadDetectCRT(pScrn);
+    }
+
+    return FALSE;
 }
 
 /**
diff --git a/src/i830_display.h b/src/i830_display.h
index aecf8dc..2e61afc 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -27,7 +27,7 @@
 
 /* i830_display.c */
 Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
-Bool i830DetectCRT(ScrnInfoPtr pScrn);
+Bool i830DetectCRT(ScrnInfoPtr pScrn, Bool allow_disturb);
 void i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on);
 void i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y);
 
diff-tree 0b76646666e9d330e77c6f81af8b91e34623be92 (from e4584a4f44a70d746396ed48b8e40033504d68b2)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Tue Jun 20 13:57:26 2006 -0700

    Add CRT detection function by testing for load, and clean up hotplug version.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index 53c65bb..c45368d 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -746,6 +746,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define PORT_HOTPLUG_STAT	0x61114
 # define CRT_HOTPLUG_INT_STATUS			(1 << 11)
 # define TV_HOTPLUG_INT_STATUS			(1 << 10)
+# define CRT_HOTPLUG_MONITOR_MASK		(3 << 8)
+# define CRT_HOTPLUG_MONITOR_COLOR		(3 << 8)
+# define CRT_HOTPLUG_MONITOR_MONO		(2 << 8)
+# define CRT_HOTPLUG_MONITOR_NONE		(0 << 8)
 # define SDVOC_HOTPLUG_INT_STATUS		(1 << 7)
 # define SDVOB_HOTPLUG_INT_STATUS		(1 << 6)
 
@@ -830,6 +834,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define PIPEACONF_PIPE_LOCKED	(1<<25)
 #define PIPEACONF_PALETTE	0
 #define PIPEACONF_GAMMA 	(1<<24)
+#define PIPECONF_FORCE_BORDER	(1<<25)
 
 #define PIPEBCONF 0x71008
 #define PIPEBCONF_ENABLE	(1<<31)
diff --git a/src/i830_display.c b/src/i830_display.c
index 73e976f..6146933 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -643,20 +643,109 @@ done:
     return ok;
 }
 
-Bool
-i830DetectCRT(ScrnInfoPtr pScrn)
+/**
+ * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence.
+ *
+ * Only for I945G/GM.
+ */
+static Bool
+i830HotplugDetectCRT(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     CARD32 temp;
+    const int timeout_ms = 1000;
+    int starttime, curtime;
 
     temp = INREG(PORT_HOTPLUG_EN);
-    OUTREG(PORT_HOTPLUG_EN, temp | CRT_HOTPLUG_FORCE_DETECT);
 
-    /* Wait for the bit to clear to signal detection finished. */
-    while (INREG(PORT_HOTPLUG_EN) & CRT_HOTPLUG_FORCE_DETECT)
-	;
+    OUTREG(PORT_HOTPLUG_EN, temp | CRT_HOTPLUG_FORCE_DETECT | (1 << 5));
+
+    for (curtime = starttime = GetTimeInMillis();
+	 (curtime - starttime) < timeout_ms; curtime = GetTimeInMillis())
+    {
+	if ((INREG(PORT_HOTPLUG_EN) & CRT_HOTPLUG_FORCE_DETECT) == 0)
+	    break;
+    }
+
+    if ((INREG(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_MONITOR_MASK) ==
+	CRT_HOTPLUG_MONITOR_COLOR)
+    {
+	return TRUE;
+    } else {
+	return FALSE;
+    }
+}
+
+/**
+ * Detects CRT presence by checking for load.
+ *
+ * Requires that the current pipe's DPLL is active.  This will cause flicker
+ * on the CRT, so it should not be used while the display is being used.  Only
+ * color (not monochrome) displays are detected.
+ */
+static Bool
+i830LoadDetectCRT(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD32 adpa, pipeconf;
+    CARD8 st00;
+    int pipeconf_reg, bclrpat_reg, dpll_reg;
+    int pipe;
+
+    pipe = pI830->pipe;
+    if (pipe == 0) {
+	bclrpat_reg = BCLRPAT_A;
+	pipeconf_reg = PIPEACONF;
+	dpll_reg = DPLL_A;
+    } else {
+	bclrpat_reg = BCLRPAT_B;
+	pipeconf_reg = PIPEBCONF;
+	dpll_reg = DPLL_B;
+    }
+
+    /* Don't try this if the DPLL isn't running. */
+    if (!(INREG(dpll_reg) & DPLL_VCO_ENABLE))
+	return FALSE;
+
+    adpa = INREG(ADPA);
+
+    /* Enable CRT output if disabled. */
+    if (!(adpa & ADPA_DAC_ENABLE)) {
+	OUTREG(ADPA, adpa | ADPA_DAC_ENABLE |
+	       ((pipe == 1) ? ADPA_PIPE_B_SELECT : 0));
+    }
+
+    /* Set the border color to red, green.  Maybe we should save/restore this
+     * reg.
+     */
+    OUTREG(bclrpat_reg, 0x00500050);
+
+    /* Force the border color through the active region */
+    pipeconf = INREG(pipeconf_reg);
+    OUTREG(pipeconf_reg, pipeconf | PIPECONF_FORCE_BORDER);
+
+    /* Read the ST00 VGA status register */
+    st00 = pI830->readStandard(pI830, 0x3c2);
+
+    /* Restore previous settings */
+    OUTREG(pipeconf_reg, pipeconf);
+    OUTREG(ADPA, adpa);
+
+    if (st00 & (1 << 4))
+	return TRUE;
+    else
+	return FALSE;
+}
+
+Bool
+i830DetectCRT(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    if (IS_I945G(pI830) || IS_I945GM(pI830))
+	return i830HotplugDetectCRT(pScrn);
 
-    return ((INREG(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_INT_STATUS));
+    return i830LoadDetectCRT(pScrn);
 }
 
 /**
diff-tree e4584a4f44a70d746396ed48b8e40033504d68b2 (from ab60e34dcfc52ab5f22a82145d5b4db51b4c62c5)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Tue Jun 20 10:39:28 2006 -0700

    Remove dead DisplayInfo option.

diff --git a/man/i810.man b/man/i810.man
index 099e1f8..f6b7368 100644
--- a/man/i810.man
+++ b/man/i810.man
@@ -179,12 +179,6 @@ NOTE: Using this option may cause text m
 and thus should be used with caution.
 Default: disabled.
 .TP
-.BI "Option \*qDisplayInfo\*q \*q" boolean \*q
-It has been found that a certain BIOS call can lockup the Xserver because
-of a problem in the Video BIOS. The log file will identify if you are
-suffering from this problem and tell you to turn this option off.
-Default: enabled
-.TP
 .BI "Option \*qDevicePresence\*q \*q" boolean \*q
 Tell the driver to perform an active detect of the currently connected
 monitors. This option is useful if the monitor was not connected when
diff --git a/src/i830.h b/src/i830.h
index c60bfbe..efd9f6d 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -416,7 +416,6 @@ typedef struct _I830Rec {
 
    unsigned int SaveGeneration;
    Bool vbeRestoreWorkaround;
-   Bool displayInfo;
    Bool devicePresence;
 
    OsTimerPtr devicesTimer;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 425ddd5..a4fde94 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -261,7 +261,6 @@ static OptionInfoRec I830BIOSOptions[] =
    {OPTION_COLOR_KEY,	"ColorKey",	OPTV_INTEGER,	{0},	FALSE},
    {OPTION_VIDEO_KEY,	"VideoKey",	OPTV_INTEGER,	{0},	FALSE},
    {OPTION_VBE_RESTORE,	"VBERestore",	OPTV_BOOLEAN,	{0},	FALSE},
-   {OPTION_DISPLAY_INFO,"DisplayInfo",	OPTV_BOOLEAN,	{0},	FALSE},
    {OPTION_DEVICE_PRESENCE,"DevicePresence",OPTV_BOOLEAN,{0},	FALSE},
    {OPTION_MONITOR_LAYOUT, "MonitorLayout", OPTV_ANYSTR,{0},	FALSE},
    {OPTION_CLONE,	"Clone",	OPTV_BOOLEAN,	{0},	FALSE},
@@ -2252,24 +2251,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
       }
    }
 
-   /* Buggy BIOS 3066 is known to cause this, so turn this off */
-   if (pI830->bios_version == 3066) {
-      pI830->displayInfo = FALSE;
-      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Detected Broken Video BIOS, turning off displayInfo.\n");
-   } else
-      pI830->displayInfo = TRUE;
-   from = X_DEFAULT;
-   if (!xf86ReturnOptValBool(pI830->Options, OPTION_DISPLAY_INFO, TRUE)) {
-      pI830->displayInfo = FALSE;
-      from = X_CONFIG;
-   }
-   if (xf86ReturnOptValBool(pI830->Options, OPTION_DISPLAY_INFO, FALSE)) {
-      pI830->displayInfo = TRUE;
-      from = X_CONFIG;
-   }
-   xf86DrvMsg(pScrn->scrnIndex, from, "Display Info: %s.\n",
-	      pI830->displayInfo ? "enabled" : "disabled");
-
    PrintDisplayDeviceInfo(pScrn);
 
    if (xf86IsEntityShared(pScrn->entityList[0])) {
diff-tree ab60e34dcfc52ab5f22a82145d5b4db51b4c62c5 (from c1c46f882f9a11c383c8d1d1ce393be8fda55ed0)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Tue Jun 20 10:07:47 2006 -0700

    Add debugging info for pipe/display plane size.

diff --git a/src/i830_display.c b/src/i830_display.c
index 95fa936..73e976f 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -411,6 +411,9 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	(int)(vtot & 0xffff) + 1, (int)(vtot >> 16) + 1,
 	(int)(vblank & 0xffff) + 1, (int)(vblank >> 16) + 1,
 	(int)(vsync & 0xffff) + 1, (int)(vsync >> 16) + 1);
+    ErrorF("pipesrc: %dx%d, dspsize: %dx%d\n",
+	(int)(pipesrc >> 16) + 1, (int)(pipesrc & 0xffff) + 1,
+	(int)(dspsize & 0xffff) + 1, (int)(dspsize >> 16) + 1);
 #endif
 
     i830PrintPll("chosen", refclk, m1, m2, n, p1, p2);
diff-tree 52243d407cad93283956660de4771097ac0b4b2d (from parents)
Merge: 2fb375b665f4802819b89f2277fd6154006c11ee 34f6a8204f1edec015283fc6b5f196e47897e3de
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Mon Jun 19 13:28:09 2006 -0700

    Merge branch 'modesetting-origin' into modesetting

diff-tree 2fb375b665f4802819b89f2277fd6154006c11ee (from b5acc6b3a3a3a109014d6b971f4722d0f0a4c29a)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Mon Jun 19 13:24:57 2006 -0700

    Set vblank interrupt configuration to match pipe configuration
    
    New i915 drm ioctl (in version 1.5) allows the X server to select
    which pipe drives vblank interrupts. Use this to drive from the 'preferred'
    pipe. Yes, per-window vblanks would be nice in a shared fb environment.
    Maybe someday.

diff --git a/src/i830.h b/src/i830.h
index 0c47f7d..aa9b275 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -546,6 +546,7 @@ extern void I830DRIUnmapScreenRegions(Sc
 extern Bool I830DRIMapScreenRegions(ScrnInfoPtr pScrn, drmI830Sarea *sarea);
 extern void I830DRIUnlock(ScrnInfoPtr pScrn);
 extern Bool I830DRILock(ScrnInfoPtr pScrn);
+extern Bool I830DRISetVBlankInterrupt (ScrnInfoPtr pScrn, Bool on);
 #endif
 
 extern Bool I830AccelInit(ScreenPtr pScreen);
diff --git a/src/i830_common.h b/src/i830_common.h
index 41b5cc3..a27bc01 100644
--- a/src/i830_common.h
+++ b/src/i830_common.h
@@ -52,6 +52,9 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define DRM_I830_INIT_HEAP                0x0a
 #define DRM_I830_CMDBUFFER                0x0b
 #define DRM_I830_DESTROY_HEAP             0x0c
+#define DRM_I830_SET_VBLANK_PIPE	  0x0d
+#define DRM_I830_GET_VBLANK_PIPE	  0x0e
+
 
 typedef struct {
    enum {
@@ -193,5 +196,11 @@ typedef struct {
 	int region;
 } drmI830MemDestroyHeap;
 
+#define	DRM_I830_VBLANK_PIPE_A	1
+#define	DRM_I830_VBLANK_PIPE_B	2
+
+typedef struct {
+	int pipe;
+} drmI830VBlankPipe;
 
 #endif /* _I830_DRM_H_ */
diff --git a/src/i830_display.c b/src/i830_display.c
index 7b9773a..a833675 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -631,6 +631,9 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
 		   pI830->planeEnabled[1] ? "enabled" : "disabled",
 		   planeB & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A");
 
+#ifdef XF86DRI
+   I830DRISetVBlankInterrupt (pScrn, TRUE);
+#endif
 done:
 #ifdef XF86DRI
     if (didLock)
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 762d3d9..0cd3ed0 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1449,6 +1449,31 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, 
 }
 
 Bool
+I830DRISetVBlankInterrupt (ScrnInfoPtr pScrn, Bool on)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    drmI830VBlankPipe pipe;
+
+    if (pI830->directRenderingEnabled && pI830->drmMinor >= 5) {
+	if (on) {
+	    if (pI830->planeEnabled[1])
+		pipe.pipe = DRM_I830_VBLANK_PIPE_B;
+	    else
+		pipe.pipe = DRM_I830_VBLANK_PIPE_A;
+	} else {
+	    pipe.pipe = 0;
+	}
+	if (drmCommandWrite(pI830->drmSubFD, DRM_I830_SET_VBLANK_PIPE,
+			    &pipe, sizeof (pipe))) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "I830 Vblank Pipe Setup Failed\n");
+	    return FALSE;
+	}
+    }
+
+    return TRUE;
+}
+
+Bool
 I830DRILock(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 3a7b54a..0a04aad 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2976,6 +2976,9 @@ RestoreHWState(ScrnInfoPtr pScrn)
 
    DPRINTF(PFX, "RestoreHWState\n");
 
+#ifdef XF86DRI
+   I830DRISetVBlankInterrupt (pScrn, FALSE);
+#endif
    vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL);
    vgaHWLock(hwp);
 
diff-tree b5acc6b3a3a3a109014d6b971f4722d0f0a4c29a (from c1c46f882f9a11c383c8d1d1ce393be8fda55ed0)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Mon Jun 19 13:22:17 2006 -0700

    Add backlight control to DPMS logic.
    
    Turn backlight on and off in response to DPMS state changes.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index 53c65bb..f7ba930 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -728,6 +728,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 # define SDVO_MULTIPLIER_MASK			0x000000ff
 # define SDVO_DEFAULT_MULTIPLIER		0x00000003
 
+#define BLC_PWM_CTL		0x61254
+#define BACKLIGHT_MODULATION_FREQ_SHIFT		(17)
+#define BACKLIGHT_MODULATION_FREQ_MASK		(0x7fff << 17)
+#define BLM_LEGACY_MODE				(1 << 16)
+#define BACKLIGHT_DUTY_CYCLE_SHIFT		(0)
+#define BACKLIGHT_DUTY_CYCLE_MASK		(0xffff)
+
 #define FPA0		0x06040
 #define FPA1		0x06044
 #define FPB0		0x06048
diff --git a/src/i830.h b/src/i830.h
index c60bfbe..0c47f7d 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -440,6 +440,8 @@ typedef struct _I830Rec {
    int panel_fixed_vsyncoff;
    int panel_fixed_vsyncwidth;
 
+   int backlight_duty_cycle;  /* restore backlight to this value */
+   
    Bool panel_wants_dither;
 
    unsigned char *VBIOS;
@@ -493,6 +495,7 @@ typedef struct _I830Rec {
    CARD32 savePaletteA[256];
    CARD32 savePaletteB[256];
    CARD32 saveSWF[17];
+   CARD32 saveBLC_PWM_CTL;
 } I830Rec;
 
 #define I830PTR(p) ((I830Ptr)((p)->driverPrivate))
diff --git a/src/i830_display.c b/src/i830_display.c
index 95fa936..7b9773a 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -664,7 +664,14 @@ i830SetLVDSPanelPower(ScrnInfoPtr pScrn,
 {
     I830Ptr pI830 = I830PTR(pScrn);
     CARD32 pp_status, pp_control;
+    CARD32 blc_pwm_ctl;
+    int backlight_duty_cycle;
 
+    blc_pwm_ctl = INREG (BLC_PWM_CTL);
+    backlight_duty_cycle = blc_pwm_ctl & BACKLIGHT_DUTY_CYCLE_MASK;
+    if (backlight_duty_cycle)
+        pI830->backlight_duty_cycle = backlight_duty_cycle;
+    
     if (on) {
 	OUTREG(PP_STATUS, INREG(PP_STATUS) | PP_ON);
 	OUTREG(PP_CONTROL, INREG(PP_CONTROL) | POWER_TARGET_ON);
@@ -672,7 +679,13 @@ i830SetLVDSPanelPower(ScrnInfoPtr pScrn,
 	    pp_status = INREG(PP_STATUS);
 	    pp_control = INREG(PP_CONTROL);
 	} while (!(pp_status & PP_ON) && !(pp_control & POWER_TARGET_ON));
+	OUTREG(BLC_PWM_CTL,
+	       (blc_pwm_ctl & ~BACKLIGHT_DUTY_CYCLE_MASK) |
+	       pI830->backlight_duty_cycle);
     } else {
+	OUTREG(BLC_PWM_CTL,
+	       (blc_pwm_ctl & ~BACKLIGHT_DUTY_CYCLE_MASK));
+	       
 	OUTREG(PP_STATUS, INREG(PP_STATUS) & ~PP_ON);
 	OUTREG(PP_CONTROL, INREG(PP_CONTROL) & ~POWER_TARGET_ON);
 	do {
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 425ddd5..3a7b54a 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2925,6 +2925,17 @@ SaveHWState(ScrnInfoPtr pScrn)
    pI830->saveLVDS = INREG(LVDS);
    pI830->savePP_CONTROL = INREG(PP_CONTROL);
    pI830->savePP_CYCLE = INREG(PP_CYCLE);
+   pI830->saveBLC_PWM_CTL = INREG(BLC_PWM_CTL);
+   pI830->backlight_duty_cycle = (pI830->saveBLC_PWM_CTL & 
+				  BACKLIGHT_DUTY_CYCLE_MASK);
+   /*
+    * If the light is off at server startup, just make it full brightness
+    */
+   if (!pI830->backlight_duty_cycle)
+      pI830->backlight_duty_cycle = ((pI830->saveBLC_PWM_CTL &
+				      BACKLIGHT_MODULATION_FREQ_MASK) >>
+				     BACKLIGHT_MODULATION_FREQ_SHIFT);
+    
 
    if (!IS_I9XX(pI830)) {
       pI830->saveDVOA = INREG(DVOA);
@@ -3031,6 +3042,7 @@ RestoreHWState(ScrnInfoPtr pScrn)
       }
    }
 
+   OUTREG(BLC_PWM_CTL, pI830->saveBLC_PWM_CTL);
    OUTREG(LVDSPP_ON, pI830->savePP_ON);
    OUTREG(LVDSPP_OFF, pI830->savePP_OFF);
    OUTREG(PP_CYCLE, pI830->savePP_CYCLE);
diff-tree d7e5d996aa123e52857362fa8a1e69f709bfe218 (from parents)
Merge: 89a5a0024a7e077a0726ffe1427e573df3bcbef5 a73ab7f0e6e3b0462e05c0031ffd602ed3e2bcd4
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Tue Jun 20 01:22:53 2006 +0800

    Merge branch 'master' into exa

diff --cc src/Makefile.am
index 83025fa,2745e8c..c9e8780
@@@ -55,8 -55,10 +55,12 @@@
           i830_video.c \
           i830_rotate.c \
  	 i830_randr.c \
+ 	 i830_3d.c \
+ 	 i830_reg.h \
+ 	 i915_3d.c \
 -	 i915_reg.h
++	 i915_reg.h \
 +	 i830_exa.c \
 +	 i830_xaa.c
  
  if DRI
  i810_drv_la_SOURCES += \
diff --cc src/i830_dri.c
index 76298a3,ed5e685..d73c84a
@@@ -1176,12 -1178,16 +1176,15 @@@
        DEALLOCATE_LOCAL(pptNew1);
        DEALLOCATE_LOCAL(pboxNew1);
     }
 -
 -   pI830->AccelInfoRec->NeedToSync = TRUE;
 +   i830MarkSync(pScrn);
  }
  
+ extern I830EmitInvarientState(ScrnInfoPtr pScrn);
+ extern I915EmitInvarientState(ScrnInfoPtr pScrn);
+ 
  /* Initialize the first context */
  void
- I830EmitInvarientState(ScrnInfoPtr pScrn)
+ IntelEmitInvarientState(ScrnInfoPtr pScrn)
  {
     I830Ptr pI830 = I830PTR(pScrn);
     CARD32 ctx_addr;
diff-tree 89a5a0024a7e077a0726ffe1427e573df3bcbef5 (from f2ab3aa3199e1c4b0edec72b5acea6d725cc514a)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Sun Jun 18 00:25:34 2006 -0700

    Fix crash with EXA during randr, when XAA structures were being accessed.  EXA
    shouldn't have any issues with there also being pixmaps in framebuffer while
    rotation is active.

diff --git a/src/i830_rotate.c b/src/i830_rotate.c
index e4a8064..ad4c484 100644
--- a/src/i830_rotate.c
+++ b/src/i830_rotate.c
@@ -959,21 +959,26 @@ I830Rotate(ScrnInfoPtr pScrn, DisplayMod
       }
    }
 
-   /* Don't allow pixmap cache or offscreen pixmaps when rotated */
-   /* XAA needs some serious fixing for this to happen */
-   if (pI830->rotation == RR_Rotate_0) {
-      pI830->AccelInfoRec->Flags = LINEAR_FRAMEBUFFER | OFFSCREEN_PIXMAPS | PIXMAP_CACHE;
-      pI830->AccelInfoRec->UsingPixmapCache = TRUE;
-      /* funny as it seems this will enable XAA's createpixmap */
-      pI830->AccelInfoRec->maxOffPixWidth = 0;
-      pI830->AccelInfoRec->maxOffPixHeight = 0;
-   } else {
-      pI830->AccelInfoRec->Flags = LINEAR_FRAMEBUFFER;
-      pI830->AccelInfoRec->UsingPixmapCache = FALSE;
-      /* funny as it seems this will disable XAA's createpixmap */
-      pI830->AccelInfoRec->maxOffPixWidth = 1;
-      pI830->AccelInfoRec->maxOffPixHeight = 1;
+#ifdef I830_USE_XAA
+   if (pI830->AccelInfoRec != NULL) {
+      /* Don't allow pixmap cache or offscreen pixmaps when rotated */
+      /* XAA needs some serious fixing for this to happen */
+      if (pI830->rotation == RR_Rotate_0) {
+	 pI830->AccelInfoRec->Flags = LINEAR_FRAMEBUFFER | OFFSCREEN_PIXMAPS |
+				      PIXMAP_CACHE;
+	 pI830->AccelInfoRec->UsingPixmapCache = TRUE;
+	 /* funny as it seems this will enable XAA's createpixmap */
+	 pI830->AccelInfoRec->maxOffPixWidth = 0;
+	 pI830->AccelInfoRec->maxOffPixHeight = 0;
+      } else {
+	 pI830->AccelInfoRec->Flags = LINEAR_FRAMEBUFFER;
+	 pI830->AccelInfoRec->UsingPixmapCache = FALSE;
+	 /* funny as it seems this will disable XAA's createpixmap */
+	 pI830->AccelInfoRec->maxOffPixWidth = 1;
+	 pI830->AccelInfoRec->maxOffPixHeight = 1;
+      }
    }
+#endif
 
    return TRUE;
 
diff-tree f2ab3aa3199e1c4b0edec72b5acea6d725cc514a (from bc42dbe07cbd61b357d8eed02608e026c4cf4485)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Sun Jun 18 00:32:01 2006 -0700

    Fix DRI in EXA mode: Don't attempt to use XAA symbols (use the driver's internal
    ones for EXA support when available).  Also, add an abstraction of XAA/EXA
    MarkSync and WaitSync functionality so we don't need to sprinkle the ifdefs all
    over, and correctly use them.

diff --git a/src/i830.h b/src/i830.h
index edc485b..9a8ecf8 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -491,6 +491,8 @@ extern Bool I830CheckModeSupport(ScrnInf
 extern Bool I830Rotate(ScrnInfoPtr pScrn, DisplayModePtr mode);
 extern Bool I830FixOffset(ScrnInfoPtr pScrn, I830MemRange *mem);
 
+extern void i830MarkSync(ScrnInfoPtr pScrn);
+extern void i830WaitSync(ScrnInfoPtr pScrn);
 /*
  * 12288 is set as the maximum, chosen because it is enough for
  * 1920x1440 at 32bpp with a 2048 pixel line pitch with some to spare.
diff --git a/src/i830_accel.c b/src/i830_accel.c
index a1a6488..f299398 100644
--- a/src/i830_accel.c
+++ b/src/i830_accel.c
@@ -208,10 +208,7 @@ I830RefreshRing(ScrnInfoPtr pScrn)
    pI830->LpRing->space = pI830->LpRing->head - (pI830->LpRing->tail + 8);
    if (pI830->LpRing->space < 0)
       pI830->LpRing->space += pI830->LpRing->mem.Size;
-#ifdef I830_USE_XAA
-   if (pI830->AccelInfoRec)
-      pI830->AccelInfoRec->NeedToSync = TRUE;
-#endif
+   i830MarkSync(pScrn);
 }
 
 /* The following function sets up the supported acceleration. Call it
diff --git a/src/i830_dri.c b/src/i830_dri.c
index c159686..76298a3 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -979,7 +979,6 @@ I830DRIInitBuffers(WindowPtr pWin, Regio
 {
    ScreenPtr pScreen = pWin->drawable.pScreen;
    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-   I830Ptr pI830 = I830PTR(pScrn);
    BoxPtr pbox = REGION_RECTS(prgn);
    int nbox = REGION_NUM_RECTS(prgn);
 
@@ -1017,9 +1016,7 @@ I830DRIInitBuffers(WindowPtr pWin, Regio
    }
 
    I830SelectBuffer(pScrn, I830_SELECT_FRONT);
-#ifdef I830_USE_XAA
-   pI830->AccelInfoRec->NeedToSync = TRUE;
-#endif
+   i830MarkSync(pScrn);
 }
 
 /* This routine is a modified form of XAADoBitBlt with the calls to
@@ -1033,7 +1030,6 @@ I830DRIMoveBuffers(WindowPtr pParent, DD
 {
    ScreenPtr pScreen = pParent->drawable.pScreen;
    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-   I830Ptr pI830 = I830PTR(pScrn);
    BoxPtr pboxTmp, pboxNext, pboxBase;
    DDXPointPtr pptTmp, pptNew2;
    int xdir, ydir;
@@ -1180,9 +1176,7 @@ I830DRIMoveBuffers(WindowPtr pParent, DD
       DEALLOCATE_LOCAL(pptNew1);
       DEALLOCATE_LOCAL(pboxNew1);
    }
-#ifdef I830_USE_XAA
-   pI830->AccelInfoRec->NeedToSync = TRUE;
-#endif
+   i830MarkSync(pScrn);
 }
 
 /* Initialize the first context */
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 5cfb6fc..fe61884 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -5258,18 +5258,8 @@ I830BIOSAdjustFrame(int scrnIndex, int x
 	   x, pI830->xoffset, y, pI830->yoffset);
 
    /* Sync the engine before adjust frame */
-#ifdef I830_USE_XAA
-   if (!pI830->noAccel && !pI830->useEXA && pI830->AccelInfoRec->NeedToSync) {
-      (*pI830->AccelInfoRec->Sync)(pScrn);
-      pI830->AccelInfoRec->NeedToSync = FALSE;
-   }
-#endif
-#ifdef I830_USE_EXA
-   if (!pI830->noAccel && pI830->useEXA) {
-	ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
-	exaWaitSync(pScreen);
-   }
-#endif
+   i830WaitSync(pScrn);
+
    if (I830IsPrimary(pScrn))
       Start = pI830->FrontBuffer.Start;
    else {
@@ -5398,16 +5388,11 @@ I830BIOSLeaveVT(int scrnIndex, int flags
    RestoreBIOSMemSize(pScrn);
    if (I830IsPrimary(pScrn))
       I830UnbindAGPMemory(pScrn);
+
 #ifdef I830_USE_XAA
    if (!pI830->useEXA && pI830->AccelInfoRec)
       pI830->AccelInfoRec->NeedToSync = FALSE;
 #endif
-#ifdef I830_USE_EXA
-   if (pI830->useEXA && pI830->EXADriverPtr) {
-      ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
-      exaMarkSync(pScreen);
-   }
-#endif
 
    /* DO IT AGAIN! AS IT SEEMS THAT SOME LFPs FLICKER OTHERWISE */
    if (I830IsPrimary(pScrn)) {
@@ -5741,18 +5726,7 @@ I830BIOSSwitchMode(int scrnIndex, Displa
 #endif
 
    /* Sync the engine before mode switch */
-#ifdef I830_USE_XAA
-   if (!pI830->noAccel && !pI830->useEXA) {
-      (*pI830->AccelInfoRec->Sync)(pScrn);
-      pI830->AccelInfoRec->NeedToSync = FALSE;
-   }
-#endif
-#ifdef I830_USE_EXA
-   if (!pI830->noAccel && pI830->useEXA) {
-      ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
-      exaWaitSync(pScreen);
-   }
-#endif
+   i830WaitSync(pScrn);
 
    /* Check if our currentmode is about to change. We do this so if we
     * are rotating, we don't need to call the mode setup again.
@@ -6122,14 +6096,8 @@ I830CheckDevicesTimer(OsTimerPtr timer, 
          xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
 		    "Hotkey switch to 0x%lx.\n", (unsigned long) temp);
 
-#ifdef I830_USE_XAA
-         if (!pI830->useEXA && pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
-            (*pI830->AccelInfoRec->Sync)(pScrn);
-            pI830->AccelInfoRec->NeedToSync = FALSE;
-            if (xf86IsEntityShared(pScrn->entityList[0]))
-               pI8302->AccelInfoRec->NeedToSync = FALSE;
-         }
-#endif
+	 i830WaitSync(pScrn);
+
          GetAttachableDisplayDeviceList(pScrn);
          
 	 pI8301->lastDevice0 = pI8301->lastDevice1;
@@ -6399,6 +6367,42 @@ I830CheckDevicesTimer(OsTimerPtr timer, 
 }
 
 void
+i830WaitSync(ScrnInfoPtr pScrn)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+
+#ifdef I830_USE_XAA
+   if (!pI830->noAccel && !pI830->useEXA && pI830->AccelInfoRec->NeedToSync) {
+      (*pI830->AccelInfoRec->Sync)(pScrn);
+      pI830->AccelInfoRec->NeedToSync = FALSE;
+   }
+#endif
+#ifdef I830_USE_EXA
+   if (!pI830->noAccel && pI830->useEXA && pI830->EXADriverPtr) {
+	ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
+	exaWaitSync(pScreen);
+   }
+#endif
+}
+
+void
+i830MarkSync(ScrnInfoPtr pScrn)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+
+#ifdef I830_USE_XAA
+   if (!pI830->useEXA && pI830->AccelInfoRec)
+      pI830->AccelInfoRec->NeedToSync = FALSE;
+#endif
+#ifdef I830_USE_EXA
+   if (pI830->useEXA && pI830->EXADriverPtr) {
+      ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
+      exaMarkSync(pScreen);
+   }
+#endif
+}
+
+void
 I830InitpScrn(ScrnInfoPtr pScrn)
 {
    pScrn->PreInit = I830BIOSPreInit;
diff --git a/src/i830_exa.c b/src/i830_exa.c
index b22430a..7212972 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -51,7 +51,7 @@ do {							\
 #define I830FALLBACK(s, arg...) { return FALSE; }
 #endif
 
-int I830CopyROP[16] =
+const int I830CopyROP[16] =
 {
    ROP_0,               /* GXclear */
    ROP_DSa,             /* GXand */
@@ -71,7 +71,7 @@ int I830CopyROP[16] =
    ROP_1                /* GXset */
 };
 
-static int I830PatternROP[16] =
+const int I830PatternROP[16] =
 {
     ROP_0,
     ROP_DPa,
diff --git a/src/i830_xaa.c b/src/i830_xaa.c
index 68ba4c7..9f3a391 100644
--- a/src/i830_xaa.c
+++ b/src/i830_xaa.c
@@ -92,6 +92,11 @@ static void I830SubsequentImageWriteScan
 #endif
 static void I830RestoreAccelState(ScrnInfoPtr pScrn);
 
+#ifdef I830_USE_EXA
+extern const int I830PatternROP[16];
+extern const int I830CopyROP[16];
+#endif
+
 Bool
 I830XAAInit(ScreenPtr pScreen)
 {
@@ -235,8 +240,17 @@ I830SetupForSolidFill(ScrnInfoPtr pScrn,
 	ErrorF("I830SetupForFillRectSolid color: %x rop: %x mask: %x\n",
 	       color, rop, planemask);
 
+#ifdef I830_USE_EXA
+    /* This function gets used by I830DRIInitBuffers(), and we might not have
+     * XAAGetPatternROP() available.  So just use the ROPs from our EXA code
+     * if available.
+     */
+    pI830->BR[13] = ((I830PatternROP[rop] << 16) |
+		     (pScrn->displayWidth * pI830->cpp));
+#else
     pI830->BR[13] = ((XAAGetPatternROP(rop) << 16) |
 		     (pScrn->displayWidth * pI830->cpp));
+#endif
 
     pI830->BR[16] = color;
 
@@ -291,7 +305,15 @@ I830SetupForScreenToScreenCopy(ScrnInfoP
 	       xdir, ydir, rop, planemask, transparency_color);
 
     pI830->BR[13] = (pScrn->displayWidth * pI830->cpp);
+#ifdef I830_USE_EXA
+    /* This function gets used by I830DRIInitBuffers(), and we might not have
+     * XAAGetCopyROP() available.  So just use the ROPs from our EXA code
+     * if available.
+     */
+    pI830->BR[13] |= I830CopyROP[rop] << 16;
+#else
     pI830->BR[13] |= XAAGetCopyROP(rop) << 16;
+#endif
 
     switch (pScrn->bitsPerPixel) {
     case 8:
diff-tree 34f6a8204f1edec015283fc6b5f196e47897e3de (from c1c46f882f9a11c383c8d1d1ce393be8fda55ed0)
Author: Keith Packard <keithp at mactel.(none)>
Date:   Sun Jun 4 00:15:06 2006 -0700

    Get sDVO output working on mac mini.
    Add lots of register debugging to track delta from BIOS settings.
    Fix various mode settings to mirror BIOS sDVO values.
    Disable analog/lvds output on pipe with sDVO.
    Borrow Dave Airlie's I830xf86ValidateDDCModes code.
    Fix various sDVO I2C messages to mirror Dave's code.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index 53c65bb..92e3342 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -748,6 +748,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 # define TV_HOTPLUG_INT_STATUS			(1 << 10)
 # define SDVOC_HOTPLUG_INT_STATUS		(1 << 7)
 # define SDVOB_HOTPLUG_INT_STATUS		(1 << 6)
+#define SDVOB_PRESERVE_MASK			((1 << 17) | (1 << 16) | (1 << 14))
 
 #define SDVOB			0x61140
 #define SDVOC			0x61160
@@ -765,7 +766,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define SDVOB_PCIE_CONCURRENCY			(1 << 3)
 #define SDVO_DETECTED				(1 << 2)
 /* Bits to be preserved when writing */
-#define SDVO_PRESERVE_MASK			(1 << 17)
+#define SDVOC_PRESERVE_MASK			(1 << 17)
 
 #define I830_HTOTAL_MASK 	0xfff0000
 #define I830_HACTIVE_MASK	0x7ff
diff --git a/src/i830.h b/src/i830.h
index c60bfbe..8cf7b71 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -420,6 +420,7 @@ typedef struct _I830Rec {
    Bool devicePresence;
 
    OsTimerPtr devicesTimer;
+   int MaxClock;
 
    int ddc2;
    int num_outputs;
@@ -589,6 +590,7 @@ extern Rotation I830GetRotation(ScreenPt
 extern Bool I830RandRInit(ScreenPtr pScreen, int rotation);
 extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg,
 			char *name);
+int I830xf86ValidateDDCModes(ScrnInfoPtr pScrn1, char **ppModeName);
 
 /*
  * 12288 is set as the maximum, chosen because it is enough for
diff --git a/src/i830_debug.c b/src/i830_debug.c
index b544257..6d43cd6 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -35,7 +35,7 @@
 
 /* XXX: What was the syntax for sticking quotes around the "reg" argument? */
 #define DEFINEREG(reg) \
-	{ reg, NULL, 0 }
+	{ reg, #reg, 0 }
 
 static struct i830SnapshotRec {
     int reg;
@@ -129,3 +129,14 @@ void i830CompareRegsToSnapshot(ScrnInfoP
 	}
     }
 }
+
+void i830DumpRegs (ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    int i;
+
+    for (i = 0; i < NUM_I830_SNAPSHOTREGS; i++) {
+	xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "%10.10s: 0x%08x\n",
+		    i830_snapshot[i].name, (unsigned int) INREG(i830_snapshot[i].reg));
+    }
+}
diff --git a/src/i830_debug.h b/src/i830_debug.h
index 269f03e..a8e3839 100644
--- a/src/i830_debug.h
+++ b/src/i830_debug.h
@@ -27,3 +27,4 @@
 
 void i830TakeRegSnapshot(ScrnInfoPtr pScrn);
 void i830CompareRegsToSnapshot(ScrnInfoPtr pScrn);
+void i830DumpRegs (ScrnInfoPtr pScrn);
diff --git a/src/i830_display.c b/src/i830_display.c
index 95fa936..d49da1f 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -34,6 +34,7 @@
 #include "i830.h"
 #include "i830_bios.h"
 #include "i830_display.h"
+#include "i830_debug.h"
 
 /** Returns the pixel clock for the given refclk and divisors. */
 static int i830_clock(int refclk, int m1, int m2, int n, int p1, int p2)
@@ -255,7 +256,8 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     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;
-    CARD32 pipesrc, dspsize, adpa, sdvoc = 0;
+    CARD32 pipesrc, dspsize, adpa;
+    CARD32 sdvob = 0, sdvoc= 0;
     Bool ok, is_sdvo;
     int refclk, pixel_clock;
     int outputs;
@@ -391,13 +393,14 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 
 	ErrorF("DVOB: %08x\nDVOC: %08x\n", (int)INREG(SDVOB), (int)INREG(SDVOC));
 
-	sdvoc = INREG(SDVOC) & SDVO_PRESERVE_MASK;
-	sdvoc |= SDVO_ENABLE;
+        sdvob = INREG(SDVOB) & SDVOB_PRESERVE_MASK;
+	sdvoc = INREG(SDVOC) & SDVOC_PRESERVE_MASK;
+	sdvob |= SDVO_ENABLE | (9 << 19) | SDVO_BORDER_ENABLE;
+	sdvoc |= 9 << 19;
 	if (pipe == 1)
-	    sdvoc |= SDVO_PIPE_B_SELECT;
-	//	sdvoc |= SDVO_PHASE_SELECT_DEFAULT;
-	sdvoc |= SDVO_BORDER_ENABLE;
+	    sdvob |= SDVO_PIPE_B_SELECT;
 	OUTREG(SDVOC, INREG(SDVOC) & ~SDVO_ENABLE);
+	OUTREG(SDVOB, INREG(SDVOB) & ~SDVO_ENABLE);
     }
 
     fp = ((n - 2) << 16) | ((m1 - 2) << 8) | (m2 - 2);
@@ -434,7 +437,10 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	FatalError("unknown display bpp\n");
     }
 
-    adpa = ADPA_DAC_ENABLE;
+    if (is_sdvo)
+	adpa = ADPA_DAC_DISABLE;
+    else
+	adpa = ADPA_DAC_ENABLE;
     if (pMode->Flags & V_PHSYNC)
 	adpa |= ADPA_HSYNC_ACTIVE_HIGH;
     if (pMode->Flags & V_PVSYNC)
@@ -466,9 +472,6 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	OUTREG(FPA0, fp);
 	OUTREG(DPLL_A, dpll);
 
-	if (is_sdvo)
-	  OUTREG(SDVOC, sdvoc);
-
 	OUTREG(HTOTAL_A, htot);
 	OUTREG(HBLANK_A, hblank);
 	OUTREG(HSYNC_A, hsync);
@@ -487,6 +490,11 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 
 	/* And then turn the plane on */
 	OUTREG(DSPACNTR, dspcntr);
+
+	if (is_sdvo) {
+	  OUTREG(SDVOB, sdvob);
+	  OUTREG(SDVOC, sdvoc);
+	}
     } else {
 	/* Always make sure the LVDS is off before we play with DPLLs and pipe
 	 * configuration.
@@ -637,6 +645,8 @@ done:
 	I830DRIUnlock(pScrn);
 #endif
 
+    i830DumpRegs (pScrn);
+    I830DumpSDVO (pScrn);
     return ok;
 }
 
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 425ddd5..c91bf43 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2386,14 +2386,17 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
 	      "Maximum space available for video modes: %d kByte\n", memsize);
 
+     pI830->MaxClock = 300000;
+
    /*
      * Setup the ClockRanges, which describe what clock ranges are available,
      * and what sort of modes they can be used for.
      */
     clockRanges = xnfcalloc(sizeof(ClockRange), 1);
     clockRanges->next = NULL;
-    clockRanges->minClock = 12000;	/* XXX: Random number */
-    clockRanges->maxClock = 400000;	/* XXX: May be lower */
+    /* 25MHz appears to be the smallest that works. */
+    clockRanges->minClock = 25000;
+    clockRanges->maxClock = pI830->MaxClock;
     clockRanges->clockIndex = -1;		/* programmable */
     clockRanges->interlaceAllowed = TRUE;	/* XXX check this */
     clockRanges->doubleScanAllowed = FALSE;	/* XXX check this */
@@ -2412,16 +2415,17 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
       }
       n = i830ValidateFPModes(pScrn, pScrn->display->modes);
    } else {
+      I830xf86ValidateDDCModes(pScrn, pScrn->display->modes);
       /* XXX minPitch, minHeight are random numbers. */
       n = xf86ValidateModes(pScrn,
 			    pScrn->monitor->Modes, /* availModes */
 			    pScrn->display->modes, /* modeNames */
 			    clockRanges, /* clockRanges */
 			    NULL, /* linePitches */
-			    256, /* minPitch */
+			    320, /* minPitch */
 			    MAX_DISPLAY_PITCH, /* maxPitch */
-			    64, /* pitchInc */
-			    pScrn->bitsPerPixel, /* minHeight */
+			    64 * pScrn->bitsPerPixel, /* pitchInc */
+			    200, /* minHeight */
 			    MAX_DISPLAY_HEIGHT, /* maxHeight */
 			    pScrn->display->virtualX, /* virtualX */
 			    pScrn->display->virtualY, /* virtualY */
@@ -2444,6 +2448,24 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
 
    xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
 
+   /*
+    * Fix up modes to make hblank start at hsync start.
+    * I don't know why the xf86 code mangles this...
+    */
+    {
+	DisplayModePtr	p;
+
+	for (p = pScrn->modes; p;) {
+	    xf86DrvMsg (pScrn->scrnIndex,
+			X_INFO, "move blank start from %d to %d\n",
+			p->CrtcHBlankStart, p->CrtcHDisplay);
+	    p->CrtcHBlankStart = p->CrtcHDisplay;
+	    p = p->next;
+	    if (p == pScrn->modes)
+		break;
+	}
+    }
+   
    pScrn->currentMode = pScrn->modes;
 
 #ifndef USE_PITCHES
diff --git a/src/i830_modes.c b/src/i830_modes.c
index 16576bb..ce86d8c 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -44,6 +44,52 @@
 #include "xf86.h"
 #include "i830.h"
 
+#include <math.h>
+
+#define rint(x) floor(x)
+
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+
+#define MARGIN_PERCENT    1.8   /* % of active vertical image                */
+#define CELL_GRAN         8.0   /* assumed character cell granularity        */
+#define MIN_PORCH         1     /* minimum front porch                       */
+#define V_SYNC_RQD        3     /* width of vsync in lines                   */
+#define H_SYNC_PERCENT    8.0   /* width of hsync as % of total line         */
+#define MIN_VSYNC_PLUS_BP 550.0 /* min time of vsync + back porch (microsec) */
+#define M                 600.0 /* blanking formula gradient                 */
+#define C                 40.0  /* blanking formula offset                   */
+#define K                 128.0 /* blanking formula scaling factor           */
+#define J                 20.0  /* blanking formula scaling factor           */
+
+/* C' and M' are part of the Blanking Duty Cycle computation */
+
+#define C_PRIME           (((C - J) * K/256.0) + J)
+#define M_PRIME           (K/256.0 * M)
+/* Established timings from EDID standard */
+static struct
+{
+    int hsize;
+    int vsize;
+    int refresh;
+} est_timings[] = {
+    {1280, 1024, 75},
+    {1024, 768, 75},
+    {1024, 768, 70},
+    {1024, 768, 60},
+    {1024, 768, 87},
+    {832, 624, 75},
+    {800, 600, 75},
+    {800, 600, 72},
+    {800, 600, 60},
+    {800, 600, 56},
+    {640, 480, 75},
+    {640, 480, 72},
+    {640, 480, 67},
+    {640, 480, 60},
+    {720, 400, 88},
+    {720, 400, 70},
+};
+
 extern const int i830refreshes[];
 
 void
@@ -108,3 +154,323 @@ I830PrintModes(ScrnInfoPtr scrp)
 	p = p->next;
     } while (p != NULL && p != scrp->modes);
 }
+
+/* This function will sort all modes according to their resolution.
+ * Highest resolution first.
+ */
+void
+I830xf86SortModes(DisplayModePtr *new, DisplayModePtr *first,
+	      DisplayModePtr *last)
+{
+    DisplayModePtr  p;
+
+    p = *last;
+    while (p) {
+	if ((((*new)->HDisplay < p->HDisplay) &&
+	     ((*new)->VDisplay < p->VDisplay)) ||
+	    (((*new)->HDisplay == p->HDisplay) &&
+	     ((*new)->VDisplay == p->VDisplay) &&
+	     ((*new)->Clock < p->Clock))) {
+
+	    if (p->next) p->next->prev = *new;
+	    (*new)->prev = p;
+	    (*new)->next = p->next;
+	    p->next = *new;
+	    if (!((*new)->next)) *last = *new;
+	    break;
+	}
+	if (!p->prev) {
+	    (*new)->prev = NULL;
+	    (*new)->next = p;
+	    p->prev = *new;
+	    *first = *new;
+	    break;
+	}
+	p = p->prev;
+    }
+
+    if (!*first) {
+	*first = *new;
+	(*new)->prev = NULL;
+	(*new)->next = NULL;
+	*last = *new;
+    }
+}
+
+DisplayModePtr I830xf86DDCModes(ScrnInfoPtr pScrn)
+{
+    DisplayModePtr  p;
+    DisplayModePtr  last  = NULL;
+    DisplayModePtr  new   = NULL;
+    DisplayModePtr  first = NULL;
+    int             count = 0;
+    int             j, tmp;
+    char            stmp[32];
+    xf86MonPtr      ddc   = pScrn->monitor->DDC;
+
+    /* Go thru detailed timing table first */
+    for (j = 0; j < 4; j++) {
+	if (ddc->det_mon[j].type == 0) {
+	    struct detailed_timings *d_timings =
+		&ddc->det_mon[j].section.d_timings;
+
+	    if (d_timings->h_active == 0 || d_timings->v_active == 0) break;
+
+	    new = xnfcalloc(1, sizeof (DisplayModeRec));
+	    memset(new, 0, sizeof (DisplayModeRec));
+
+	    new->HDisplay   = d_timings->h_active;
+	    new->VDisplay   = d_timings->v_active;
+
+	    sprintf(stmp, "%dx%d", new->HDisplay, new->VDisplay);
+	    new->name       = xnfalloc(strlen(stmp) + 1);
+	    strcpy(new->name, stmp);
+
+	    new->HTotal     = new->HDisplay + d_timings->h_blanking;
+	    new->HSyncStart = new->HDisplay + d_timings->h_sync_off;
+	    new->HSyncEnd   = new->HSyncStart + d_timings->h_sync_width;
+	    new->VTotal     = new->VDisplay + d_timings->v_blanking;
+	    new->VSyncStart = new->VDisplay + d_timings->v_sync_off;
+	    new->VSyncEnd   = new->VSyncStart + d_timings->v_sync_width;
+	    new->Clock      = d_timings->clock / 1000;
+	    new->Flags      = (d_timings->interlaced ? V_INTERLACE : 0);
+	    new->status     = MODE_OK;
+	    new->type       = M_T_DEFAULT;
+
+	    if (d_timings->sync == 3) {
+		switch (d_timings->misc) {
+		case 0: new->Flags |= V_NHSYNC | V_NVSYNC; break;
+		case 1: new->Flags |= V_PHSYNC | V_NVSYNC; break;
+		case 2: new->Flags |= V_NHSYNC | V_PVSYNC; break;
+		case 3: new->Flags |= V_PHSYNC | V_PVSYNC; break;
+		}
+	    }
+	    count++;
+
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		       "Valid Mode from Detailed timing table: %s (ht %d hss %d hse %d vt %d vss %d vse %d)\n",
+		       new->name,
+		       new->HTotal, new->HSyncStart, new->HSyncEnd,
+		       new->VTotal, new->VSyncStart, new->VSyncEnd);
+
+	    I830xf86SortModes(&new, &first, &last);
+	}
+    }
+
+    /* Search thru standard VESA modes from EDID */
+    for (j = 0; j < 8; j++) {
+        if (ddc->timings2[j].hsize == 0 || ddc->timings2[j].vsize == 0)
+               continue;
+	for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) {
+	    /* Ignore all double scan modes */
+	    if ((ddc->timings2[j].hsize == p->HDisplay) &&
+		(ddc->timings2[j].vsize == p->VDisplay)) {
+		float  refresh =
+		    (float)p->Clock * 1000.0 / p->HTotal / p->VTotal;
+		float err = (float)ddc->timings2[j].refresh - refresh;
+
+		if (err < 0) err = -err;
+		if (err < 1.0) {
+		    /* Is this good enough? */
+		    new = xnfcalloc(1, sizeof (DisplayModeRec));
+		    memcpy(new, p, sizeof(DisplayModeRec));
+		    new->name = xnfalloc(strlen(p->name) + 1);
+		    strcpy(new->name, p->name);
+		    new->status = MODE_OK;
+		    new->type   = M_T_DEFAULT;
+
+		    count++;
+
+		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+			       "Valid Mode from standard timing table: %s\n",
+			       new->name);
+
+		    I830xf86SortModes(&new, &first, &last);
+		    break;
+		}
+	    }
+	}
+    }
+
+    /* Search thru established modes from EDID */
+    tmp = (ddc->timings1.t1 << 8) | ddc->timings1.t2;
+    for (j = 0; j < 16; j++) {
+	if (tmp & (1 << j)) {
+	    for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) {
+		if ((est_timings[j].hsize == p->HDisplay) &&
+		    (est_timings[j].vsize == p->VDisplay)) {
+		    float  refresh =
+			(float)p->Clock * 1000.0 / p->HTotal / p->VTotal;
+		    float err = (float)est_timings[j].refresh - refresh;
+
+		    if (err < 1.0) {
+			/* Is this good enough? */
+			new = xnfcalloc(1, sizeof (DisplayModeRec));
+			memcpy(new, p, sizeof(DisplayModeRec));
+			new->name = xnfalloc(strlen(p->name) + 1);
+			strcpy(new->name, p->name);
+			new->status = MODE_OK;
+			new->type   = M_T_DEFAULT;
+
+			count++;
+
+			xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+				   "Valid Mode from established timing "
+				   "table: %s\n", new->name);
+
+			I830xf86SortModes(&new, &first, &last);
+			break;
+		    }
+		}
+	    }
+	}
+    }
+
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+	       "Total of %d mode(s) found.\n", count);
+
+    return first;
+}
+
+/* XFree86's xf86ValidateModes routine doesn't work well with DDC modes,
+ * so here is our own validation routine.
+ */
+int I830xf86ValidateDDCModes(ScrnInfoPtr pScrn1, char **ppModeName)
+{
+    DisplayModePtr  p;
+    DisplayModePtr  last       = NULL;
+    DisplayModePtr  first      = NULL;
+    DisplayModePtr  ddcModes   = NULL;
+    int             count      = 0;
+    int             i, width, height;
+    ScrnInfoPtr pScrn = pScrn1;
+
+    pScrn->virtualX = pScrn1->display->virtualX;
+    pScrn->virtualY = pScrn1->display->virtualY;
+
+    if (pScrn->monitor->DDC) {
+	int  maxVirtX = pScrn->virtualX;
+	int  maxVirtY = pScrn->virtualY;
+
+	/* Collect all of the DDC modes */
+	first = last = ddcModes = I830xf86DDCModes(pScrn);
+
+	for (p = ddcModes; p; p = p->next) {
+
+	    maxVirtX = MAX(maxVirtX, p->HDisplay);
+	    maxVirtY = MAX(maxVirtY, p->VDisplay);
+	    count++;
+
+	    last = p;
+	}
+
+	/* Match up modes that are specified in the XF86Config file */
+	if (ppModeName[0]) {
+	    DisplayModePtr  next;
+
+	    /* Reset the max virtual dimensions */
+	    maxVirtX = pScrn->virtualX;
+	    maxVirtY = pScrn->virtualY;
+
+	    /* Reset list */
+	    first = last = NULL;
+
+	    for (i = 0; ppModeName[i]; i++) {
+		/* FIXME: Use HDisplay and VDisplay instead of mode string */
+		if (sscanf(ppModeName[i], "%dx%d", &width, &height) == 2) {
+		    for (p = ddcModes; p; p = next) {
+			next = p->next;
+
+			if (p->HDisplay == width && p->VDisplay == height) {
+			    /* We found a DDC mode that matches the one
+                               requested in the XF86Config file */
+			    p->type |= M_T_USERDEF;
+
+			    /* Update  the max virtual setttings */
+			    maxVirtX = MAX(maxVirtX, width);
+			    maxVirtY = MAX(maxVirtY, height);
+
+			    /* Unhook from DDC modes */
+			    if (p->prev) p->prev->next = p->next;
+			    if (p->next) p->next->prev = p->prev;
+			    if (p == ddcModes) ddcModes = p->next;
+
+			    /* Add to used modes */
+			    if (last) {
+				last->next = p;
+				p->prev = last;
+			    } else {
+				first = p;
+				p->prev = NULL;
+			    }
+			    p->next = NULL;
+			    last = p;
+
+			    break;
+			}
+		    }
+		}
+	    }
+
+	    /*
+	     * Add remaining DDC modes if they're smaller than the user
+	     * specified modes
+	     */
+	    for (p = ddcModes; p; p = next) {
+		next = p->next;
+		if (p->HDisplay <= maxVirtX && p->VDisplay <= maxVirtY) {
+		    /* Unhook from DDC modes */
+		    if (p->prev) p->prev->next = p->next;
+		    if (p->next) p->next->prev = p->prev;
+		    if (p == ddcModes) ddcModes = p->next;
+
+		    /* Add to used modes */
+		    if (last) {
+			last->next = p;
+			p->prev = last;
+		    } else {
+			first = p;
+			p->prev = NULL;
+		    }
+		    p->next = NULL;
+		    last = p;
+		}
+	    }
+
+	    /* Delete unused modes */
+	    while (ddcModes)
+		xf86DeleteMode(&ddcModes, ddcModes);
+	} else {
+	    /*
+	     * No modes were configured, so we make the DDC modes
+	     * available for the user to cycle through.
+	     */
+	    for (p = ddcModes; p; p = p->next)
+		p->type |= M_T_USERDEF;
+	}
+
+	pScrn->virtualX = pScrn->display->virtualX = maxVirtX;
+	pScrn->virtualY = pScrn->display->virtualY = maxVirtY;
+    }
+
+    /* Close the doubly-linked mode list, if we found any usable modes */
+    if (last) {
+      DisplayModePtr  temp      = NULL;
+        /* we should add these to pScrn monitor modes */
+      last->next   = pScrn->monitor->Modes;
+      temp = pScrn->monitor->Modes->prev;
+      pScrn->monitor->Modes->prev = first;
+      pScrn->monitor->Modes->prev = last;
+
+      first->prev = temp;
+      if (temp)
+	temp->next = first;
+
+      pScrn->monitor->Modes = first;
+    }
+
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+	       "Total number of valid DDC mode(s) found: %d\n", count);
+
+    return count;
+}
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 579f77a..7d23975 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -139,7 +139,7 @@ I830SDVOSetTargetInput(I830SDVOPtr s, Bo
     s->sdvo_regs[SDVO_I2C_ARG_0] = target_1;
     s->sdvo_regs[SDVO_I2C_ARG_1] = target_2;
 
-    I830SDVOWriteOutputs(s, 1);
+    I830SDVOWriteOutputs(s, 2);
 
     I830SDVOReadInputRegs(s);
 
@@ -218,7 +218,7 @@ I830SDVOSetTargetOutput(I830SDVOPtr s, B
     s->sdvo_regs[SDVO_I2C_ARG_0] = target_1;
     s->sdvo_regs[SDVO_I2C_ARG_1] = target_2;
 
-    I830SDVOWriteOutputs(s, 1);
+    I830SDVOWriteOutputs(s, 2);
     I830SDVOReadInputRegs(s);
 
     return TRUE;
@@ -259,7 +259,7 @@ I830SDVOGetTimings(I830SDVOPtr s, i830_s
     return TRUE;
 }
 
-/* Fetches either input or output timings to *dtd, depending on cmd. */
+/* Sets either input or output timings to *dtd, depending on cmd. */
 Bool
 I830SDVOSetTimings(I830SDVOPtr s, i830_sdvo_dtd *dtd, CARD8 cmd)
 {
@@ -286,7 +286,7 @@ I830SDVOSetTimings(I830SDVOPtr s, i830_s
     s->sdvo_regs[SDVO_I2C_ARG_5] = dtd->sdvo_flags;
     s->sdvo_regs[SDVO_I2C_ARG_6] = dtd->v_sync_off_high;
     s->sdvo_regs[SDVO_I2C_ARG_7] = dtd->reserved;
-    I830SDVOWriteOutputs(s, 8);
+    I830SDVOWriteOutputs(s, 7);
     I830SDVOReadInputRegs(s);
 
     return TRUE;
@@ -477,6 +477,7 @@ I830SDVOPreSetMode(I830SDVOPtr s, Displa
     CARD8 c17a[8];
     CARD16 out_timings[6];
     CARD16 clock_min, clock_max;
+    Bool out1, out2;
 
     /* do some mode translations */
     h_blank_len = mode->CrtcHBlankEnd - mode->CrtcHBlankStart;
@@ -516,30 +517,41 @@ I830SDVOPreSetMode(I830SDVOPtr s, Displa
     out_timings[4] = c17a[5] | ((short)c17a[4] << 8);
     out_timings[5] = c17a[3] | ((short)c17a[2] << 8);
 
-    I830SDVOSetTargetInput(s, TRUE, TRUE);
+    I830SDVOSetTargetInput(s, FALSE, FALSE);
     I830SDVOGetInputPixelClockRange(s, &clock_min, &clock_max);
     ErrorF("clock min/max: %d %d\n", clock_min, clock_max);
 
+    I830SDVOGetActiveOutputs(s, &out1, &out2);
+    
     I830SDVOSetActiveOutputs(s, FALSE, FALSE);
 
-    I830SDVOSetTargetOutput(s, TRUE, TRUE);
+    I830SDVOSetTargetOutput(s, TRUE, FALSE);
     I830SDVOSetOutputTimingsPart1(s, clock, out_timings[0], out_timings[1],
 				  out_timings[2]);
     I830SDVOSetOutputTimingsPart2(s, out_timings[3], out_timings[4],
 				  out_timings[5]);
 
+    I830SDVOSetTargetInput (s, FALSE, FALSE);
+    
     I830SDVOCreatePreferredInputTiming(s, clock, width, height);
     I830SDVOGetPreferredInputTimingPart1(s);
     I830SDVOGetPreferredInputTimingPart2(s);
+    
+    I830SDVOSetTargetInput (s, FALSE, FALSE);
+    
     I830SDVOSetInputTimingsPart1(s, clock, curr_table[0], curr_table[1],
 				 curr_table[2]);
     I830SDVOSetInputTimingsPart2(s, curr_table[3], curr_table[4],
 				 out_timings[5]);
 
-    /*if (mode->PrivFlags & I830_MFLAG_DOUBLE)
-	I830SDVOSetClockRateMult(s, 0x02);
-    else */
-	I830SDVOSetClockRateMult(s, 0x01);
+    I830SDVOSetTargetInput (s, FALSE, FALSE);
+    
+    if (clock >= 10000)
+	I830SDVOSetClockRateMult(s, SDVO_CLOCK_RATE_MULT_1X);
+    else if (clock >= 5000)
+	I830SDVOSetClockRateMult(s, SDVO_CLOCK_RATE_MULT_2X);
+    else
+	I830SDVOSetClockRateMult(s, SDVO_CLOCK_RATE_MULT_4X);
 
     return TRUE;
 }
@@ -548,6 +560,7 @@ Bool
 I830SDVOPostSetMode(I830SDVOPtr s, DisplayModePtr mode)
 {
     Bool ret = TRUE;
+    Bool out1, out2;
 
     /* the BIOS writes out 6 commands post mode set */
     /* two 03s, 04 05, 10, 1d */
@@ -564,7 +577,9 @@ I830SDVOPostSetMode(I830SDVOPtr s, Displ
 	ret = FALSE;
     }
 
-    I830SDVOSetActiveOutputs(s, TRUE, TRUE);
+    I830SDVOGetActiveOutputs (s, &out1, &out2);
+    I830SDVOSetActiveOutputs(s, TRUE, FALSE);
+    I830SDVOSetTargetInput (s, FALSE, FALSE);
 
     return ret;
 }
@@ -580,7 +595,7 @@ i830SDVOSave(ScrnInfoPtr pScrn, int outp
 			     &sdvo->save_sdvo_active_2);
 
     if (sdvo->caps.caps & 0x1) {
-       I830SDVOSetTargetInput(sdvo, TRUE, FALSE);
+       I830SDVOSetTargetInput(sdvo, FALSE, FALSE);
        I830SDVOGetTimings(sdvo, &sdvo->save_input_dtd_1,
 			  SDVO_CMD_GET_INPUT_TIMINGS_PART1);
     }
@@ -622,7 +637,7 @@ i830SDVOPostRestore(ScrnInfoPtr pScrn, i
     I830SDVOPtr sdvo = pI830->output[output_index].sdvo_drv;
 
     if (sdvo->caps.caps & 0x1) {
-       I830SDVOSetTargetInput(sdvo, TRUE, FALSE);
+       I830SDVOSetTargetInput(sdvo, FALSE, FALSE);
        I830SDVOSetTimings(sdvo, &sdvo->save_input_dtd_1,
 			  SDVO_CMD_SET_INPUT_TIMINGS_PART1);
     }
@@ -830,3 +845,53 @@ I830SDVOInit(ScrnInfoPtr pScrn, int outp
 
     return sdvo;
 }
+
+static void
+I830DumpSDVOCmd (I830SDVOPtr s, int opcode)
+{
+    memset (s->sdvo_regs, 0, sizeof (s->sdvo_regs));
+    s->sdvo_regs[SDVO_I2C_OPCODE] = opcode;
+    I830SDVOWriteOutputs (s, 0);
+    I830SDVOReadInputRegs (s);
+}
+
+static void
+I830DumpOneSDVO (I830SDVOPtr s)
+{
+    ErrorF ("Dump %s\n", s->d.DevName);
+    I830DumpSDVOCmd (s, SDVO_CMD_GET_DEVICE_CAPS);
+    I830DumpSDVOCmd (s, SDVO_CMD_GET_FIRMWARE_REV);
+    I830DumpSDVOCmd (s, SDVO_CMD_GET_TRAINED_INPUTS);
+    I830DumpSDVOCmd (s, SDVO_CMD_GET_ACTIVE_OUTPUTS);
+    I830DumpSDVOCmd (s, SDVO_CMD_GET_IN_OUT_MAP);
+    I830DumpSDVOCmd (s, SDVO_CMD_GET_ATTACHED_DISPLAYS);
+    I830DumpSDVOCmd (s, SDVO_CMD_GET_HOT_PLUG_SUPPORT);
+    I830DumpSDVOCmd (s, SDVO_CMD_GET_ACTIVE_HOT_PLUG);
+    I830DumpSDVOCmd (s, SDVO_CMD_GET_INTR_EVENT_SOURCE);
+    I830DumpSDVOCmd (s, SDVO_CMD_GET_INPUT_TIMINGS_PART1);
+    I830DumpSDVOCmd (s, SDVO_CMD_GET_INPUT_TIMINGS_PART2);
+    I830DumpSDVOCmd (s, SDVO_CMD_GET_OUTPUT_TIMINGS_PART1);
+    I830DumpSDVOCmd (s, SDVO_CMD_GET_OUTPUT_TIMINGS_PART2);
+    I830DumpSDVOCmd (s, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1);
+    I830DumpSDVOCmd (s, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2);
+    I830DumpSDVOCmd (s, SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE);
+    I830DumpSDVOCmd (s, SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE);
+    I830DumpSDVOCmd (s, SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS);
+    I830DumpSDVOCmd (s, SDVO_CMD_GET_CLOCK_RATE_MULT);
+    I830DumpSDVOCmd (s, SDVO_CMD_GET_SUPPORTED_TV_FORMATS);
+    I830DumpSDVOCmd (s, SDVO_CMD_GET_TV_FORMAT);
+}
+		 
+void
+I830DumpSDVO (ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830SDVOPtr	s;
+    int	i;
+
+    for (i = 0; i < 4; i++) {
+	s = pI830->output[i].sdvo_drv;
+	if (s)
+	    I830DumpOneSDVO (s);
+    }
+}
diff --git a/src/i830_sdvo_regs.h b/src/i830_sdvo_regs.h
index 37cfcf2..a35d5a4 100644
--- a/src/i830_sdvo_regs.h
+++ b/src/i830_sdvo_regs.h
@@ -157,7 +157,9 @@
 #define SDVO_CMD_SET_CLOCK_RATE_MULT			0x21
 # define SDVO_CLOCK_RATE_MULT_1X				(1 << 0)
 # define SDVO_CLOCK_RATE_MULT_2X				(1 << 1)
+# define SDVO_CLOCK_RATE_MULT_3X				(1 << 2)
 # define SDVO_CLOCK_RATE_MULT_4X				(1 << 3)
+# define SDVO_CLOCK_RATE_MULT_5X				(1 << 4)
 
 #define SDVO_CMD_GET_SUPPORTED_TV_FORMATS		0x27
 
diff-tree c1c46f882f9a11c383c8d1d1ce393be8fda55ed0 (from parents)
Merge: 1e2da2450d7213c0aa4d4bd1fba5723dcda13ddf f2967a2f5f47b636b2445fa69dbc3ec79e065c90
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon May 22 10:42:24 2006 -0700

    Merge branch 'master' into modesetting
    
    Conflicts:
    
    	man/.gitignore

diff --cc src/common.h
index 6e68767,a6e4ca3..21977af
@@@ -83,9 -84,7 +84,8 @@@
  #ifdef XF86DRI
  extern const char *I810driSymbols[];
  extern const char *I810drmSymbols[];
- extern const char *I810shadowSymbols[];
  #endif
 +extern const char *I810i2cSymbols[];
  
  extern void I830DPRINTF_stub(const char *filename, int line,
  			     const char *function, const char *fmt, ...);
diff-tree 1e2da2450d7213c0aa4d4bd1fba5723dcda13ddf (from 1bc2a8f7a20b2ea9251e93157c0f2342fdbb951c)
Author: Lukáš Hejtmanek <xhejtman at mail.muni.cz>
Date:   Mon May 22 09:48:09 2006 -0700

    Replace VBE call to do DPMS with native code, and fix screensaver in clone mode.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 3eb3205..425ddd5 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -4258,27 +4258,30 @@ I830BIOSSaveScreen(ScreenPtr pScreen, in
    I830Ptr pI830 = I830PTR(pScrn);
    Bool on = xf86IsUnblank(mode);
    CARD32 temp, ctrl, base;
+   int i;
 
    DPRINTF(PFX, "I830BIOSSaveScreen: %d, on is %s\n", mode, BOOLTOSTRING(on));
 
    if (pScrn->vtSema) {
-      if (pI830->pipe == 0) {
-	 ctrl = DSPACNTR;
-	 base = DSPABASE;
-      } else {
-	 ctrl = DSPBCNTR;
-	 base = DSPBADDR;
-      }
-      if (pI830->planeEnabled[pI830->pipe]) {
-	 temp = INREG(ctrl);
-	 if (on)
-	    temp |= DISPLAY_PLANE_ENABLE;
-	 else
-	    temp &= ~DISPLAY_PLANE_ENABLE;
-	 OUTREG(ctrl, temp);
-	 /* Flush changes */
-	 temp = INREG(base);
-	 OUTREG(base, temp);
+      for (i = 0; i < pI830->availablePipes; i++) {
+        if (i == 0) {
+	    ctrl = DSPACNTR;
+	    base = DSPABASE;
+        } else {
+	    ctrl = DSPBCNTR;
+	    base = DSPBADDR;
+        }
+        if (pI830->planeEnabled[i]) {
+	   temp = INREG(ctrl);
+	   if (on)
+	      temp |= DISPLAY_PLANE_ENABLE;
+	   else
+	      temp &= ~DISPLAY_PLANE_ENABLE;
+	   OUTREG(ctrl, temp);
+	   /* Flush changes */
+	   temp = INREG(base);
+	   OUTREG(base, temp);
+        }
       }
 
       if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn) {
@@ -4292,63 +4295,91 @@ I830BIOSSaveScreen(ScreenPtr pScreen, in
    return TRUE;
 }
 
+static void
+I830DPMSCRT(ScrnInfoPtr pScrn, int mode)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+   CARD32 temp;
+   
+   temp = INREG(ADPA);
+   temp &= ~(ADPA_HSYNC_CNTL_DISABLE|ADPA_VSYNC_CNTL_DISABLE);
+   switch(mode) {
+   case DPMSModeOn:
+      break;
+   case DPMSModeStandby:
+      temp |= ADPA_HSYNC_CNTL_DISABLE;
+      break;
+   case DPMSModeSuspend:
+      temp |= ADPA_VSYNC_CNTL_DISABLE;
+      break;
+   case DPMSModeOff:
+      temp |= ADPA_HSYNC_CNTL_DISABLE|ADPA_VSYNC_CNTL_DISABLE;
+      break;
+   }
+   OUTREG(ADPA, temp);
+}
+
+static void
+I830DPMSLVDS(ScrnInfoPtr pScrn, int mode)
+{
+   if (mode == DPMSModeOn)
+      i830SetLVDSPanelPower(pScrn, TRUE);
+   else
+      i830SetLVDSPanelPower(pScrn, FALSE);
+}
+
 /* Use the VBE version when available. */
 static void
 I830DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
 			      int flags)
 {
    I830Ptr pI830 = I830PTR(pScrn);
-   vbeInfoPtr pVbe = pI830->pVbe;
+   int i;
+   CARD32 temp, ctrl, base;
 
-   if (pI830->Clone) {
-      SetBIOSPipe(pScrn, !pI830->pipe);
-      if (xf86LoaderCheckSymbol("VBEDPMSSet")) {
-         VBEDPMSSet(pVbe, PowerManagementMode);
+   for (i = 0; i < pI830->availablePipes; i++) {
+      if (i == 0) {
+         ctrl = DSPACNTR;
+         base = DSPABASE;
       } else {
-         pVbe->pInt10->num = 0x10;
-         pVbe->pInt10->ax = 0x4f10;
-         pVbe->pInt10->bx = 0x01;
-
-         switch (PowerManagementMode) {
-         case DPMSModeOn:
-	    break;
-         case DPMSModeStandby:
-	    pVbe->pInt10->bx |= 0x0100;
-	    break;
-         case DPMSModeSuspend:
-	    pVbe->pInt10->bx |= 0x0200;
-	    break;
-         case DPMSModeOff:
-	    pVbe->pInt10->bx |= 0x0400;
-	    break;
-         }
-         xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
+         ctrl = DSPBCNTR;
+         base = DSPBADDR;
+      }
+      if (pI830->planeEnabled[i]) {
+	   temp = INREG(ctrl);
+	   if (PowerManagementMode == DPMSModeOn)
+	      temp |= DISPLAY_PLANE_ENABLE;
+	   else
+	      temp &= ~DISPLAY_PLANE_ENABLE;
+	   OUTREG(ctrl, temp);
+	   /* Flush changes */
+	   temp = INREG(base);
+	   OUTREG(base, temp);
       }
    }
 
-   SetPipeAccess(pScrn);
+   if (pI830->operatingDevices & (PIPE_CRT_ACTIVE | (PIPE_CRT_ACTIVE<<8))) {
+      I830DPMSCRT(pScrn, PowerManagementMode);
+   }
 
-   if (xf86LoaderCheckSymbol("VBEDPMSSet")) {
-      VBEDPMSSet(pVbe, PowerManagementMode);
-   } else {
-      pVbe->pInt10->num = 0x10;
-      pVbe->pInt10->ax = 0x4f10;
-      pVbe->pInt10->bx = 0x01;
-
-      switch (PowerManagementMode) {
-      case DPMSModeOn:
-	 break;
-      case DPMSModeStandby:
-	 pVbe->pInt10->bx |= 0x0100;
-	 break;
-      case DPMSModeSuspend:
-	 pVbe->pInt10->bx |= 0x0200;
-	 break;
-      case DPMSModeOff:
-	 pVbe->pInt10->bx |= 0x0400;
-	 break;
-      }
-      xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
+   if (pI830->operatingDevices & (PIPE_LCD_ACTIVE | (PIPE_LCD_ACTIVE<<8))) {
+      I830DPMSLVDS(pScrn, PowerManagementMode);
+   }
+
+   if (pI830->operatingDevices & (PIPE_DFP_ACTIVE | (PIPE_DFP_ACTIVE<<8))) {
+      /* TBD */
+   }
+
+   if (pI830->operatingDevices & (PIPE_DFP2_ACTIVE | (PIPE_DFP2_ACTIVE<<8))) {
+      /* TBD */
+   }
+
+   if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn) {
+      if (PowerManagementMode == DPMSModeOn)
+         pI830->CursorInfoRec->ShowCursor(pScrn);
+      else
+         pI830->CursorInfoRec->HideCursor(pScrn);
+      pI830->cursorOn = TRUE;
    }
 }
 
diff-tree bc42dbe07cbd61b357d8eed02608e026c4cf4485 (from e70d99d51edc39ea53536c2f4d62ac622ba3e0d9)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Mon May 22 11:22:03 2006 +0800

    fix a typo

diff --git a/src/i830_exa.c b/src/i830_exa.c
index a67e549..b22430a 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -234,7 +234,7 @@ I830EXAPrepareCopy(PixmapPtr pSrcPixmap,
     ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
 
-    if (planemask != (Pixel)~0 && !EXA_PM_IS_SOLID(pScrPixmap, planemask))
+    if (planemask != (Pixel)~0 && !EXA_PM_IS_SOLID(pSrcPixmap, planemask))
 	I830FALLBACK("planemask is not solid");
 
     pI830->copy_src_pitch = exaGetPixmapPitch(pSrcPixmap);
diff-tree e70d99d51edc39ea53536c2f4d62ac622ba3e0d9 (from b3d79ad9ecc70e9f841092fc75b7e23576b685dd)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Fri May 19 15:47:19 2006 +0800

    revert wrong setting for memorySize, which should
    be at the range of pI830->Offscreen.

diff --git a/src/i830_exa.c b/src/i830_exa.c
index a37be39..a67e549 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -394,7 +394,7 @@ I830EXAInit(ScreenPtr pScreen)
     pI830->EXADriverPtr->exa_minor = 0;
     pI830->EXADriverPtr->memoryBase = pI830->FbBase;
     pI830->EXADriverPtr->offScreenBase = pI830->Offscreen.Start;
-    pI830->EXADriverPtr->memorySize = pScrn->videoRam*1024;
+    pI830->EXADriverPtr->memorySize = pI830->Offscreen.End;
 	   
     if(pI830->EXADriverPtr->memorySize >
        pI830->EXADriverPtr->offScreenBase)
diff-tree b3d79ad9ecc70e9f841092fc75b7e23576b685dd (from 33ad959323f70f76c494c66ec35a04d7d839f612)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Thu May 18 16:31:40 2006 +0800

    oop I830FALLBACK define error

diff --git a/src/i830_exa.c b/src/i830_exa.c
index 5d95ea7..a37be39 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -48,7 +48,7 @@ do {							\
 	return FALSE;					\
 } while(0)
 #else
-#define I830FALLBACK(x) { return FALSE; }
+#define I830FALLBACK(s, arg...) { return FALSE; }
 #endif
 
 int I830CopyROP[16] =
diff-tree 1bc2a8f7a20b2ea9251e93157c0f2342fdbb951c (from fbba4312e7cb326fdcf6a71194c4fc4a7a9b5488)
Author: Dave Airlie <airlied at linux.ie>
Date:   Thu May 18 16:58:22 2006 +1000

    fixup I830SDVOGetActiveInputs to use return values not args

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index fe37d21..579f77a 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -169,8 +169,8 @@ I830SDVOGetActiveOutputs(I830SDVOPtr s, 
     I830SDVOWriteOutputs(s, 0);
     I830SDVOReadInputRegs(s);
 
-    *on_1 = s->sdvo_regs[SDVO_I2C_ARG_0];
-    *on_2 = s->sdvo_regs[SDVO_I2C_ARG_1];
+    *on_1 = s->sdvo_regs[SDVO_I2C_RETURN_0];
+    *on_2 = s->sdvo_regs[SDVO_I2C_RETURN_1];
 
     return TRUE;
 }
diff-tree 33ad959323f70f76c494c66ec35a04d7d839f612 (from 52af679c94a25c0c6e5df5f3647f62fdd256c826)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Thu May 18 11:32:59 2006 +0800

    Add DEBUG_I830FALLBACK for easier tracking

diff --git a/src/i830_exa.c b/src/i830_exa.c
index b250fb2..5d95ea7 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -37,6 +37,20 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "i830.h"
 #include "i810_reg.h"
 
+#ifdef I830DEBUG
+#define DEBUG_I830FALLBACK 0
+#endif
+
+#ifdef DEBUG_I830FALLBACK
+#define I830FALLBACK(s, arg...)				\
+do {							\
+	DPRINTF(PFX, "EXA fallback: " s "\n", ##arg); 	\
+	return FALSE;					\
+} while(0)
+#else
+#define I830FALLBACK(x) { return FALSE; }
+#endif
+
 int I830CopyROP[16] =
 {
    ROP_0,               /* GXclear */
@@ -136,15 +150,15 @@ I830EXAPrepareSolid(PixmapPtr pPixmap, i
     unsigned long offset, pitch;
 
     if (planemask != (Pixel)~0 && !EXA_PM_IS_SOLID(pPixmap, planemask))
-	return FALSE;
+	I830FALLBACK("planemask is not solid");
 
     offset = exaGetPixmapOffset(pPixmap);
     pitch = exaGetPixmapPitch(pPixmap);
 
     if ( offset % pI830->EXADriverPtr->pixmapOffsetAlign != 0)
-	return FALSE;
+	I830FALLBACK("pixmap offset not aligned");
     if ( pitch % pI830->EXADriverPtr->pixmapPitchAlign != 0)
-	return FALSE;
+	I830FALLBACK("pixmap pitch not aligned");
 
     pI830->BR[13] = pitch;
     pI830->BR[13] |= I830PatternROP[alu] << 16;
@@ -221,7 +235,7 @@ I830EXAPrepareCopy(PixmapPtr pSrcPixmap,
     I830Ptr pI830 = I830PTR(pScrn);
 
     if (planemask != (Pixel)~0 && !EXA_PM_IS_SOLID(pScrPixmap, planemask))
-	return FALSE;
+	I830FALLBACK("planemask is not solid");
 
     pI830->copy_src_pitch = exaGetPixmapPitch(pSrcPixmap);
     pI830->copy_src_off = exaGetPixmapOffset(pSrcPixmap);
diff-tree 52af679c94a25c0c6e5df5f3647f62fdd256c826 (from fdb52a8c6da0f3d3f4cfbf1583b2dc4d91f7e933)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Thu May 18 11:31:14 2006 +0800

    Check alignment require in PrepareSolid, noticed by Eric,
    as pixmap offset align set is violated in Solid.

diff --git a/src/i830_exa.c b/src/i830_exa.c
index 6726a0e..b250fb2 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -133,11 +133,20 @@ I830EXAPrepareSolid(PixmapPtr pPixmap, i
 {
     ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
+    unsigned long offset, pitch;
 
     if (planemask != (Pixel)~0 && !EXA_PM_IS_SOLID(pPixmap, planemask))
 	return FALSE;
 
-    pI830->BR[13] = exaGetPixmapPitch(pPixmap);
+    offset = exaGetPixmapOffset(pPixmap);
+    pitch = exaGetPixmapPitch(pPixmap);
+
+    if ( offset % pI830->EXADriverPtr->pixmapOffsetAlign != 0)
+	return FALSE;
+    if ( pitch % pI830->EXADriverPtr->pixmapPitchAlign != 0)
+	return FALSE;
+
+    pI830->BR[13] = pitch;
     pI830->BR[13] |= I830PatternROP[alu] << 16;
 
     pI830->BR[16] = fg;
@@ -165,8 +174,10 @@ I830EXASolid(PixmapPtr pPixmap, int x1, 
     ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
     int h, w;
-    unsigned int offset;
+    unsigned long offset;
 
+    /* pixmap's offset and pitch is aligned, 
+       otherwise it falls back in PrepareSolid */
     offset = exaGetPixmapOffset(pPixmap) + y1 * exaGetPixmapPitch(pPixmap) +
 	x1 * (pPixmap->drawable.bitsPerPixel / 8);
     
diff-tree fdb52a8c6da0f3d3f4cfbf1583b2dc4d91f7e933 (from 011a1c99d49c1c69b5fa81ade6a2ed73e84276ae)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Thu May 18 11:24:46 2006 +0800

    Solid planemask in PrepareSolid/Copy might be 0xffffffff
    or bits up to the depth. This should save some fallback
    case, noticed by Eric.

diff --git a/src/i830_exa.c b/src/i830_exa.c
index 6acc00c..6726a0e 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -134,7 +134,7 @@ I830EXAPrepareSolid(PixmapPtr pPixmap, i
     ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
 
-    if (planemask != (Pixel)~0)
+    if (planemask != (Pixel)~0 && !EXA_PM_IS_SOLID(pPixmap, planemask))
 	return FALSE;
 
     pI830->BR[13] = exaGetPixmapPitch(pPixmap);
@@ -209,7 +209,7 @@ I830EXAPrepareCopy(PixmapPtr pSrcPixmap,
     ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
 
-    if (planemask != (Pixel)~0)
+    if (planemask != (Pixel)~0 && !EXA_PM_IS_SOLID(pScrPixmap, planemask))
 	return FALSE;
 
     pI830->copy_src_pitch = exaGetPixmapPitch(pSrcPixmap);
diff-tree 011a1c99d49c1c69b5fa81ade6a2ed73e84276ae (from fcec956807038a2e90287850df8b4410b1f8b3c2)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed May 17 11:16:00 2006 +0800

    Fix memorySize to enable offscreen mem manage.

diff --git a/src/i830_exa.c b/src/i830_exa.c
index 59c2d51..6acc00c 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -369,7 +369,7 @@ I830EXAInit(ScreenPtr pScreen)
     pI830->EXADriverPtr->exa_minor = 0;
     pI830->EXADriverPtr->memoryBase = pI830->FbBase;
     pI830->EXADriverPtr->offScreenBase = pI830->Offscreen.Start;
-    pI830->EXADriverPtr->memorySize = pI830->Offscreen.Size;
+    pI830->EXADriverPtr->memorySize = pScrn->videoRam*1024;
 	   
     if(pI830->EXADriverPtr->memorySize >
        pI830->EXADriverPtr->offScreenBase)
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 5fbc8cf..50bbde5 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -872,6 +872,10 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
 		       "offscreen memory.  Not enough VRAM?\n");
 	 }
 	 return FALSE;
+      } else {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Successful allocate "
+		       "offscreen memory at 0x%lx, size %d KB\n", 
+			pI830->Offscreen.Start, pI830->Offscreen.Size/1024);
       }
 #endif
    } else {
diff-tree fbba4312e7cb326fdcf6a71194c4fc4a7a9b5488 (from 190f9ad0606e96e684e0b028d576d822dc9aa3cf)
Author: Dave Airlie <airlied at linux.ie>
Date:   Fri May 12 18:44:27 2006 +1000

    add sdvo capability reading support
    
    This reads the SDVO cap bits and uses them to figure out the input/output
    to save/restore

diff --git a/src/i830.h b/src/i830.h
index 7c4d50c..c60bfbe 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -194,6 +194,7 @@ typedef struct _I830SDVODriver {
    unsigned char sdvo_regs[20];
    CARD32 output_device;		/* SDVOB or SDVOC */
 
+   i830_sdvo_caps caps;
    int save_sdvo_mult;
    Bool save_sdvo_active_1, save_sdvo_active_2;
    i830_sdvo_dtd save_input_dtd_1, save_input_dtd_2;
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 99cdc6a..fe37d21 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -579,19 +579,29 @@ i830SDVOSave(ScrnInfoPtr pScrn, int outp
     I830SDVOGetActiveOutputs(sdvo, &sdvo->save_sdvo_active_1,
 			     &sdvo->save_sdvo_active_2);
 
-    I830SDVOSetTargetInput(sdvo, TRUE, FALSE);
-    I830SDVOGetTimings(sdvo, &sdvo->save_input_dtd_1,
-		       SDVO_CMD_GET_INPUT_TIMINGS_PART1);
-    I830SDVOSetTargetInput(sdvo, FALSE, TRUE);
-    I830SDVOGetTimings(sdvo, &sdvo->save_input_dtd_2,
-		       SDVO_CMD_GET_INPUT_TIMINGS_PART1);
-
-    I830SDVOSetTargetOutput(sdvo, TRUE, FALSE);
-    I830SDVOGetTimings(sdvo, &sdvo->save_output_dtd_1,
-		       SDVO_CMD_GET_OUTPUT_TIMINGS_PART1);
-    I830SDVOSetTargetOutput(sdvo, FALSE, TRUE);
-    I830SDVOGetTimings(sdvo, &sdvo->save_output_dtd_2,
-		       SDVO_CMD_GET_OUTPUT_TIMINGS_PART1);
+    if (sdvo->caps.caps & 0x1) {
+       I830SDVOSetTargetInput(sdvo, TRUE, FALSE);
+       I830SDVOGetTimings(sdvo, &sdvo->save_input_dtd_1,
+			  SDVO_CMD_GET_INPUT_TIMINGS_PART1);
+    }
+
+    if (sdvo->caps.caps & 0x2) {
+       I830SDVOSetTargetInput(sdvo, FALSE, TRUE);
+       I830SDVOGetTimings(sdvo, &sdvo->save_input_dtd_2,
+			  SDVO_CMD_GET_INPUT_TIMINGS_PART1);
+    }
+    
+    if (sdvo->caps.output_0_supported) {
+       I830SDVOSetTargetOutput(sdvo, TRUE, FALSE);
+       I830SDVOGetTimings(sdvo, &sdvo->save_output_dtd_1,
+			  SDVO_CMD_GET_OUTPUT_TIMINGS_PART1);
+    }
+
+    if (sdvo->caps.output_1_supported) {
+       I830SDVOSetTargetOutput(sdvo, FALSE, TRUE);
+       I830SDVOGetTimings(sdvo, &sdvo->save_output_dtd_2,
+			  SDVO_CMD_GET_OUTPUT_TIMINGS_PART1);
+    }
 
     sdvo->save_SDVOX = INREG(sdvo->output_device);
 }
@@ -611,19 +621,29 @@ i830SDVOPostRestore(ScrnInfoPtr pScrn, i
     I830Ptr pI830 = I830PTR(pScrn);
     I830SDVOPtr sdvo = pI830->output[output_index].sdvo_drv;
 
-    I830SDVOSetTargetInput(sdvo, TRUE, FALSE);
-    I830SDVOSetTimings(sdvo, &sdvo->save_input_dtd_1,
-		       SDVO_CMD_SET_INPUT_TIMINGS_PART1);
-    I830SDVOSetTargetInput(sdvo, FALSE, TRUE);
-    I830SDVOSetTimings(sdvo, &sdvo->save_input_dtd_2,
-		       SDVO_CMD_SET_INPUT_TIMINGS_PART1);
-
-    I830SDVOSetTargetOutput(sdvo, TRUE, FALSE);
-    I830SDVOSetTimings(sdvo, &sdvo->save_output_dtd_1,
-		       SDVO_CMD_SET_OUTPUT_TIMINGS_PART1);
-    I830SDVOSetTargetOutput(sdvo, FALSE, TRUE);
-    I830SDVOSetTimings(sdvo, &sdvo->save_output_dtd_2,
-		       SDVO_CMD_SET_OUTPUT_TIMINGS_PART1);
+    if (sdvo->caps.caps & 0x1) {
+       I830SDVOSetTargetInput(sdvo, TRUE, FALSE);
+       I830SDVOSetTimings(sdvo, &sdvo->save_input_dtd_1,
+			  SDVO_CMD_SET_INPUT_TIMINGS_PART1);
+    }
+
+    if (sdvo->caps.caps & 0x2) {
+       I830SDVOSetTargetInput(sdvo, FALSE, TRUE);
+       I830SDVOSetTimings(sdvo, &sdvo->save_input_dtd_2,
+			  SDVO_CMD_SET_INPUT_TIMINGS_PART1);
+    }
+
+    if (sdvo->caps.output_0_supported) {
+       I830SDVOSetTargetOutput(sdvo, TRUE, FALSE);
+       I830SDVOSetTimings(sdvo, &sdvo->save_output_dtd_1,
+			  SDVO_CMD_SET_OUTPUT_TIMINGS_PART1);
+    }
+
+    if (sdvo->caps.output_1_supported) {
+       I830SDVOSetTargetOutput(sdvo, FALSE, TRUE);
+       I830SDVOSetTimings(sdvo, &sdvo->save_output_dtd_2,
+			  SDVO_CMD_SET_OUTPUT_TIMINGS_PART1);
+    }
 
     I830SDVOSetClockRateMult(sdvo, sdvo->save_sdvo_mult);
 
@@ -633,6 +653,24 @@ i830SDVOPostRestore(ScrnInfoPtr pScrn, i
 			     sdvo->save_sdvo_active_2);
 }
 
+static void
+I830SDVOGetCapabilities(I830SDVOPtr s, i830_sdvo_caps *caps)
+{
+  memset(s->sdvo_regs, 0, 9);
+  s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_DEVICE_CAPS;
+  I830SDVOWriteOutputs(s, 0);
+  I830SDVOReadInputRegs(s);
+
+  caps->vendor_id = s->sdvo_regs[SDVO_I2C_RETURN_0];
+  caps->device_id = s->sdvo_regs[SDVO_I2C_RETURN_1];
+  caps->device_rev_id = s->sdvo_regs[SDVO_I2C_RETURN_2];
+  caps->sdvo_version_major = s->sdvo_regs[SDVO_I2C_RETURN_3];
+  caps->sdvo_version_minor = s->sdvo_regs[SDVO_I2C_RETURN_4];
+  caps->caps = s->sdvo_regs[SDVO_I2C_RETURN_5];
+  caps->output_0_supported = s->sdvo_regs[SDVO_I2C_RETURN_6];
+  caps->output_1_supported = s->sdvo_regs[SDVO_I2C_RETURN_7];
+}
+
 static Bool
 I830SDVODDCI2CGetByte(I2CDevPtr d, I2CByte *data, Bool last)
 {
@@ -669,7 +707,7 @@ I830SDVODDCI2CStart(I2CBusPtr b, int tim
     I830SDVOPtr sdvo = b->DriverPrivate.ptr;
     I2CBusPtr i2cbus = sdvo->d.pI2CBus;
 
-    I830SDVOSetControlBusSwitch(sdvo, SDVO_CONTROL_BUS_DDC1);
+    I830SDVOSetControlBusSwitch(sdvo, SDVO_CONTROL_BUS_DDC2);
     return i2cbus->I2CStart(i2cbus, timeout);
 }
 
@@ -781,5 +819,14 @@ I830SDVOInit(ScrnInfoPtr pScrn, int outp
 
     pI830->output[output_index].sdvo_drv = sdvo;
 
+    I830SDVOGetCapabilities(sdvo, &sdvo->caps);
+    
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+	       "SDVO device VID/DID: %02X:%02X.%02X, %02X, output 1: %c, output 2: %c\n",
+	       sdvo->caps.vendor_id, sdvo->caps.device_id,
+	       sdvo->caps.device_rev_id, sdvo->caps.caps,
+	       sdvo->caps.output_0_supported ? 'Y' : 'N',
+	       sdvo->caps.output_1_supported ? 'Y' : 'N');
+
     return sdvo;
 }
diff --git a/src/i830_sdvo.h b/src/i830_sdvo.h
index ec4b538..6b77c97 100644
--- a/src/i830_sdvo.h
+++ b/src/i830_sdvo.h
@@ -25,6 +25,17 @@
  *
  */
 
+typedef struct _i830_sdvo_caps {
+  CARD8 vendor_id;
+  CARD8 device_id;
+  CARD8 device_rev_id;
+  CARD8 sdvo_version_major;
+  CARD8 sdvo_version_minor;
+  CARD8 caps;
+  CARD8 output_0_supported;
+  CARD8 output_1_supported;
+} __attribute__((packed)) i830_sdvo_caps;
+
 typedef struct _i830_sdvo_dtd {
     CARD16 clock;
     CARD8 h_active;
diff-tree 190f9ad0606e96e684e0b028d576d822dc9aa3cf (from fb10966e9f43f44488097b0daf2fbe10c6a804dc)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Tue May 9 13:51:25 2006 -0700

    Video overlay gamma bounds checking must be done bytewise.
    Also, pend bound computations to register writes to allow
    updates to individual values that are 'out of spec' so
    the client can update multiple values.

diff --git a/src/i830_video.c b/src/i830_video.c
index 0ae6860..a608a7e 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -592,18 +592,53 @@ I830SetOneLineModeRatio(ScrnInfoPtr pScr
       pPriv->oneLineMode = FALSE;
 }
 
+static CARD32 I830BoundGammaElt (CARD32 elt, CARD32 eltPrev)
+{
+   elt &= 0xff;
+   eltPrev &= 0xff;
+   if (elt < eltPrev)
+      elt = eltPrev;
+   else if ((elt - eltPrev) > 0x7e)
+      elt = eltPrev + 0x7e;
+   return elt;
+}
+
+static CARD32 I830BoundGamma (CARD32 gamma, CARD32 gammaPrev)
+{
+   return (I830BoundGammaElt (gamma >> 24, gammaPrev >> 24) << 24 |
+	   I830BoundGammaElt (gamma >> 16, gammaPrev >> 16) << 16 |
+	   I830BoundGammaElt (gamma >>  8, gammaPrev >>  8) <<  8 |
+	   I830BoundGammaElt (gamma      , gammaPrev      ));
+}
+
 static void
 I830UpdateGamma(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
    I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr;
-
-   OUTREG(OGAMC5, pPriv->gamma5);
-   OUTREG(OGAMC4, pPriv->gamma4);
-   OUTREG(OGAMC3, pPriv->gamma3);
-   OUTREG(OGAMC2, pPriv->gamma2);
-   OUTREG(OGAMC1, pPriv->gamma1);
-   OUTREG(OGAMC0, pPriv->gamma0);
+   CARD32   gamma0 = pPriv->gamma0;
+   CARD32   gamma1 = pPriv->gamma1;
+   CARD32   gamma2 = pPriv->gamma2;
+   CARD32   gamma3 = pPriv->gamma3;
+   CARD32   gamma4 = pPriv->gamma4;
+   CARD32   gamma5 = pPriv->gamma5;
+
+   ErrorF ("Original gamma: 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n",
+	   gamma0, gamma1, gamma2, gamma3, gamma4, gamma5);
+   gamma1 = I830BoundGamma (gamma1, gamma0);
+   gamma2 = I830BoundGamma (gamma2, gamma1);
+   gamma3 = I830BoundGamma (gamma3, gamma2);
+   gamma4 = I830BoundGamma (gamma4, gamma3);
+   gamma5 = I830BoundGamma (gamma5, gamma4);
+   ErrorF ("Bounded  gamma: 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n",
+	   gamma0, gamma1, gamma2, gamma3, gamma4, gamma5);
+
+   OUTREG(OGAMC5, gamma5);
+   OUTREG(OGAMC4, gamma4);
+   OUTREG(OGAMC3, gamma3);
+   OUTREG(OGAMC2, gamma2);
+   OUTREG(OGAMC1, gamma1);
+   OUTREG(OGAMC0, gamma0);
 }
 
 static XF86VideoAdaptorPtr
@@ -849,28 +884,16 @@ I830SetPortAttribute(ScrnInfoPtr pScrn,
 #endif
    } else if (attribute == xvGamma0 && (IS_I9XX(pI830))) {
       pPriv->gamma0 = value; 
-      if (pPriv->gamma1 - pPriv->gamma0 > 0x7d)
-         pPriv->gamma1 = pPriv->gamma0 + 0x7d;
    } else if (attribute == xvGamma1 && (IS_I9XX(pI830))) {
       pPriv->gamma1 = value;
-      if (pPriv->gamma1 - pPriv->gamma0 > 0x7d)
-        pPriv->gamma0 = pPriv->gamma1 - 0x7d;
    } else if (attribute == xvGamma2 && (IS_I9XX(pI830))) {
       pPriv->gamma2 = value;
-      if (pPriv->gamma3 - pPriv->gamma2 > 0x7d)
-         pPriv->gamma3 = pPriv->gamma2 + 0x7d;
    } else if (attribute == xvGamma3 && (IS_I9XX(pI830))) {
       pPriv->gamma3 = value;
-      if (pPriv->gamma3 - pPriv->gamma2 > 0x7d)
-         pPriv->gamma2 = pPriv->gamma3 - 0x7d;
    } else if (attribute == xvGamma4 && (IS_I9XX(pI830))) {
       pPriv->gamma4 = value;
-      if (pPriv->gamma5 - pPriv->gamma4 > 0x7d)
-         pPriv->gamma5 = pPriv->gamma4 + 0x7d;
    } else if (attribute == xvGamma5 && (IS_I9XX(pI830))) {
       pPriv->gamma5 = value;
-      if (pPriv->gamma5 - pPriv->gamma4 > 0x7d)
-         pPriv->gamma4 = pPriv->gamma5 - 0x7d;
    } else if (attribute == xvColorKey) {
       pPriv->colorKey = value;
       switch (pScrn->depth) {
diff-tree fb10966e9f43f44488097b0daf2fbe10c6a804dc (from a66f2c01f7d557d860883346671fb864807dbdca)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Thu May 4 18:52:08 2006 -0700

    Use xf86int10Addr() when calculating an address to read the video BIOS from, out
    
    of int10's copy.  Fixes a crash on FreeBSD.

diff --git a/src/i830_bios.c b/src/i830_bios.c
index 19b1b5a..4b87351 100644
--- a/src/i830_bios.c
+++ b/src/i830_bios.c
@@ -91,7 +91,8 @@ i830GetBIOS(ScrnInfoPtr pScrn)
 	return FALSE;
 
     if (pI830->pVbe != NULL) {
-	memcpy(pI830->VBIOS, (void *)(pI830->pVbe->pInt10->BIOSseg << 4),
+	memcpy(pI830->VBIOS, xf86int10Addr(pI830->pVbe->pInt10,
+					   pI830->pVbe->pInt10->BIOSseg << 4),
 	       INTEL_VBIOS_SIZE);
     } else {
 	xf86ReadPciBIOS(0, pI830->PciTag, 0, pI830->VBIOS, INTEL_VBIOS_SIZE);
diff-tree a66f2c01f7d557d860883346671fb864807dbdca (from a555e28e5afc81969ef7b28482e654cc26b3a446)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon May 1 12:35:21 2006 -0700

    Stop doing the BIOS memory size tweaking now that we don't ask the BIOS about
    what modes are available.

diff --git a/src/i830.h b/src/i830.h
index d72b72b..7c4d50c 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -245,8 +245,6 @@ typedef struct _I830Rec {
    long FbMapSize;
    long TotalVideoRam;
    I830MemRange StolenMemory;		/* pre-allocated memory */
-   long BIOSMemorySize;			/* min stolen pool size */
-   int BIOSMemSizeLoc;
 
    /* These change according to what has been allocated. */
    long FreeMemory;
@@ -384,12 +382,6 @@ typedef struct _I830Rec {
    VbeInfoBlock *vbeInfo;
    VESAPtr vesa;
 
-   Bool overrideBIOSMemSize;
-   int saveBIOSMemSize;
-   int newBIOSMemSize;
-   Bool useSWF1;
-   int saveSWF1;
-
    Bool swfSaved;
    CARD32 saveSWF0;
    CARD32 saveSWF4;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index dcb1acf..3eb3205 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -871,291 +871,6 @@ I830UnmapMem(ScrnInfoPtr pScrn)
    return TRUE;
 }
 
-#ifndef HAVE_GET_PUT_BIOSMEMSIZE
-#define HAVE_GET_PUT_BIOSMEMSIZE 1
-#endif
-
-#if HAVE_GET_PUT_BIOSMEMSIZE
-/*
- * Tell the BIOS how much video memory is available.  The BIOS call used
- * here won't always be available.
- */
-static Bool
-PutBIOSMemSize(ScrnInfoPtr pScrn, int memSize)
-{
-   vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
-
-   DPRINTF(PFX, "PutBIOSMemSize: %d kB\n", memSize / 1024);
-
-   pVbe->pInt10->num = 0x10;
-   pVbe->pInt10->ax = 0x5f11;
-   pVbe->pInt10->bx = 0;
-   pVbe->pInt10->cx = memSize / GTT_PAGE_SIZE;
-
-   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
-   return Check5fStatus(pScrn, 0x5f11, pVbe->pInt10->ax);
-}
-
-/*
- * This reports what the previous VBEGetVBEInfo() found.  Be sure to call
- * VBEGetVBEInfo() after changing the BIOS memory size view.  If
- * a separate BIOS call is added for this, it can be put here.  Only
- * return a valid value if the funtionality for PutBIOSMemSize()
- * is available.
- */
-static int
-GetBIOSMemSize(ScrnInfoPtr pScrn)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   int memSize = KB(pI830->vbeInfo->TotalMemory * 64);
-
-   DPRINTF(PFX, "GetBIOSMemSize\n");
-
-   if (PutBIOSMemSize(pScrn, memSize))
-      return memSize;
-   else
-      return -1;
-}
-#endif
-
-/*
- * These three functions allow the video BIOS's view of the available video
- * memory to be changed.  This is currently implemented only for the 830
- * and 845G, which can do this via a BIOS scratch register that holds the
- * BIOS's view of the (pre-reserved) memory size.  If another mechanism
- * is available in the future, it can be plugged in here.  
- *
- * The mapping used for the 830/845G scratch register's low 4 bits is:
- *
- *             320k => 0
- *             832k => 1
- *            8000k => 8
- *
- * The "unusual" values are the 512k, 1M, 8M pre-reserved memory, less
- * overhead, rounded down to the BIOS-reported 64k granularity.
- */
-
-static Bool
-SaveBIOSMemSize(ScrnInfoPtr pScrn)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-
-   DPRINTF(PFX, "SaveBIOSMemSize\n");
-
-   if (!I830IsPrimary(pScrn))
-      return FALSE;
-
-   pI830->useSWF1 = FALSE;
-
-#if HAVE_GET_PUT_BIOSMEMSIZE
-   if ((pI830->saveBIOSMemSize = GetBIOSMemSize(pScrn)) != -1)
-      return TRUE;
-#endif
-
-   if (IS_I830(pI830) || IS_845G(pI830)) {
-      pI830->useSWF1 = TRUE;
-      pI830->saveSWF1 = INREG(SWF1) & 0x0f;
-
-      /*
-       * This is for sample purposes only.  pI830->saveBIOSMemSize isn't used
-       * when pI830->useSWF1 is TRUE.
-       */
-      switch (pI830->saveSWF1) {
-      case 0:
-	 pI830->saveBIOSMemSize = KB(320);
-	 break;
-      case 1:
-	 pI830->saveBIOSMemSize = KB(832);
-	 break;
-      case 8:
-	 pI830->saveBIOSMemSize = KB(8000);
-	 break;
-      default:
-	 pI830->saveBIOSMemSize = 0;
-	 break;
-      }
-      return TRUE;
-   }
-   return FALSE;
-}
-
-/*
- * TweakMemorySize() tweaks the BIOS image to set the correct size.
- * Original implementation by Christian Zietz in a stand-alone tool.
- */
-static CARD32
-TweakMemorySize(ScrnInfoPtr pScrn, CARD32 newsize, Bool preinit)
-{
-#define SIZE 0x10000
-#define _855_IDOFFSET (-23)
-#define _845_IDOFFSET (-19)
-    
-    const char *MAGICstring = "Total time for VGA POST:";
-    const int len = strlen(MAGICstring);
-    I830Ptr pI830 = I830PTR(pScrn);
-    volatile char *position;
-    char *biosAddr;
-    CARD32 oldsize;
-    CARD32 oldpermission;
-    CARD32 ret = 0;
-    int i,j = 0;
-    int reg = (IS_845G(pI830) || IS_I865G(pI830)) ? _845_DRAM_RW_CONTROL
-	: _855_DRAM_RW_CONTROL;
-    
-    PCITAG tag =pciTag(0,0,0);
-
-    if (!I830IsPrimary(pScrn))
-       return 0;
-
-    if(!pI830->PciInfo 
-       || !(IS_845G(pI830) || IS_I85X(pI830) || IS_I865G(pI830)))
-	return 0;
-
-    if (!pI830->pVbe)
-	return 0;
-
-    biosAddr = xf86int10Addr(pI830->pVbe->pInt10, 
-				    pI830->pVbe->pInt10->BIOSseg << 4);
-
-    if (!pI830->BIOSMemSizeLoc) {
-	if (!preinit)
-	    return 0;
-
-	/* Search for MAGIC string */
-	for (i = 0; i < SIZE; i++) {
-	    if (biosAddr[i] == MAGICstring[j]) {
-		if (++j == len)
-		    break;
-	    } else {
-		i -= j;
-		j = 0;
-	    }
-	}
-	if (j < len) return 0;
-
-	pI830->BIOSMemSizeLoc =  (i - j + 1 + (IS_845G(pI830)
-					    ? _845_IDOFFSET : _855_IDOFFSET));
-    }
-    
-    position = biosAddr + pI830->BIOSMemSizeLoc;
-    oldsize = *(CARD32 *)position;
-
-    ret = oldsize - 0x21000;
-    
-    /* verify that register really contains current size */
-    if (preinit && ((ret >> 16) !=  pI830->vbeInfo->TotalMemory))
-	return 0;
-
-    oldpermission = pciReadLong(tag, reg);
-    pciWriteLong(tag, reg, DRAM_WRITE | (oldpermission & 0xffff)); 
-    
-    *(CARD32 *)position = newsize + 0x21000;
-
-    if (preinit) {
-	/* reinitialize VBE for new size */
-	if (I830IsPrimary(pScrn)) {
-	   VBEFreeVBEInfo(pI830->vbeInfo);
-	   vbeFree(pI830->pVbe);
-	   pI830->pVbe = VBEInit(NULL, pI830->pEnt->index);
-	   pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe);
-	} else {
-           I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
-           pI830->pVbe = pI8301->pVbe;
-           pI830->vbeInfo = pI8301->vbeInfo;
-	}
-	
-	/* verify that change was successful */
-	if (pI830->vbeInfo->TotalMemory != (newsize >> 16)){
-	    ret = 0;
-	    *(CARD32 *)position = oldsize;
-	} else {
-	    pI830->BIOSMemorySize = KB(pI830->vbeInfo->TotalMemory * 64);
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
-		       "Tweak BIOS image to %d kB VideoRAM\n",
-		       (int)(pI830->BIOSMemorySize / 1024));
-	}
-    }
-
-    pciWriteLong(tag, reg, oldpermission);
-
-     return ret;
-}
-
-static void
-RestoreBIOSMemSize(ScrnInfoPtr pScrn)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   CARD32 swf1;
-
-   DPRINTF(PFX, "RestoreBIOSMemSize\n");
-
-   if (!I830IsPrimary(pScrn))
-      return;
-
-   if (TweakMemorySize(pScrn, pI830->saveBIOSMemSize,FALSE))
-      return;
-
-   if (!pI830->overrideBIOSMemSize)
-      return;
-
-#if HAVE_GET_PUT_BIOSMEMSIZE
-   if (!pI830->useSWF1) {
-      PutBIOSMemSize(pScrn, pI830->saveBIOSMemSize);
-      return;
-   }
-#endif
-
-   if ((IS_I830(pI830) || IS_845G(pI830)) && pI830->useSWF1) {
-      swf1 = INREG(SWF1);
-      swf1 &= ~0x0f;
-      swf1 |= (pI830->saveSWF1 & 0x0f);
-      OUTREG(SWF1, swf1);
-   }
-}
-
-static void
-SetBIOSMemSize(ScrnInfoPtr pScrn, int newSize)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   unsigned long swf1;
-   Bool mapped;
-
-   DPRINTF(PFX, "SetBIOSMemSize: %d kB\n", newSize / 1024);
-
-   if (!pI830->overrideBIOSMemSize)
-      return;
-
-#if HAVE_GET_PUT_BIOSMEMSIZE
-   if (!pI830->useSWF1) {
-      PutBIOSMemSize(pScrn, newSize);
-      return;
-   }
-#endif
-
-   if ((IS_I830(pI830) || IS_845G(pI830)) && pI830->useSWF1) {
-      unsigned long newSWF1;
-
-      /* Need MMIO access here. */
-      mapped = (pI830->MMIOBase != NULL);
-      if (!mapped)
-	 I830MapMMIO(pScrn);
-
-      if (newSize <= KB(832))
-	 newSWF1 = 1;
-      else
-	 newSWF1 = 8;
-
-      swf1 = INREG(SWF1);
-      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Before: SWF1 is 0x%08lx\n", swf1);
-      swf1 &= ~0x0f;
-      swf1 |= (newSWF1 & 0x0f);
-      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "After: SWF1 is 0x%08lx\n", swf1);
-      OUTREG(SWF1, swf1);
-      if (!mapped)
-	 I830UnmapMMIO(pScrn);
-   }
-}
-
 static CARD32 val8[256];
 
 static void
@@ -1509,7 +1224,6 @@ PreInitCleanup(ScrnInfoPtr pScrn)
       if (pI830->entityPrivate)
          pI830->entityPrivate->pScrn_2 = NULL;
    }
-   RestoreBIOSMemSize(pScrn);
    if (pI830->swfSaved) {
       OUTREG(SWF0, pI830->saveSWF0);
       OUTREG(SWF4, pI830->saveSWF4);
@@ -2423,67 +2137,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
 		    pScrn->videoRam);
    }
 
-   if (mem > 0) {
-      /*
-       * If the reserved (BIOS accessible) memory is less than the desired
-       * amount, try to increase it.  So far this is only implemented for
-       * the 845G and 830, but those details are handled in SetBIOSMemSize().
-       * 
-       * The BIOS-accessible amount is only important for setting video
-       * modes.  The maximum amount we try to set is limited to what would
-       * be enough for 1920x1440 with a 2048 pitch.
-       *
-       * If ALLOCATE_ALL_BIOSMEM is enabled in i830_memory.c, all of the
-       * BIOS-aware memory will get allocated.  If it isn't then it may
-       * not be, and in that case there is an assumption that the video
-       * BIOS won't attempt to access memory beyond what is needed for
-       * modes that are actually used.  ALLOCATE_ALL_BIOSMEM is enabled by
-       * default.
-       */
-
-      /* Try to keep HW cursor and Overlay amounts separate from this. */
-      int reserve = (HWCURSOR_SIZE + HWCURSOR_SIZE_ARGB + OVERLAY_SIZE) / 1024;
-
-      if (pScrn->videoRam - reserve >= I830_MAXIMUM_VBIOS_MEM)
-	 pI830->newBIOSMemSize = KB(I830_MAXIMUM_VBIOS_MEM);
-      else 
-	 pI830->newBIOSMemSize =
-			KB(ROUND_DOWN_TO(pScrn->videoRam - reserve, 64));
-      if (pI830->vbeInfo->TotalMemory * 64 < pI830->newBIOSMemSize / 1024) {
-
-	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		    "Will attempt to tell the BIOS that there is "
-		    "%d kB VideoRAM\n", pI830->newBIOSMemSize / 1024);
-	 if (SaveBIOSMemSize(pScrn)) {
-	    pI830->overrideBIOSMemSize = TRUE;
-	    SetBIOSMemSize(pScrn, pI830->newBIOSMemSize);
-
-	    if (I830IsPrimary(pScrn)) {
-	       VBEFreeVBEInfo(pI830->vbeInfo);
-	       vbeFree(pI830->pVbe);
-	       pI830->pVbe = VBEInit(NULL, pI830->pEnt->index);
-	       pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe);
-	    } else {
-               I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
-	       pI830->pVbe = pI8301->pVbe;
-	       pI830->vbeInfo = pI8301->vbeInfo;
-	    }
-
-	    pI830->BIOSMemorySize = KB(pI830->vbeInfo->TotalMemory * 64);
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		       "BIOS now sees %ld kB VideoRAM\n",
-		       pI830->BIOSMemorySize / 1024);
- 	 } else if ((pI830->saveBIOSMemSize
-		 = TweakMemorySize(pScrn, pI830->newBIOSMemSize,TRUE)) != 0) 
-	     pI830->overrideBIOSMemSize = TRUE;
-	 else {
-	     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-			"BIOS view of memory size can't be changed "
-			"(this is not an error).\n");
-	 }
-      }
-   }
-
    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
 	      "Pre-allocated VideoRAM: %ld kByte\n",
 	      pI830->StolenMemory.Size / 1024);
@@ -2923,9 +2576,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
 
    I830PrintModes(pScrn);
 
-   /* PreInit shouldn't leave any state changes, so restore this. */
-   RestoreBIOSMemSize(pScrn);
-
    /* Don't need MMIO access anymore. */
    if (pI830->swfSaved) {
       OUTREG(SWF0, pI830->saveSWF0);
@@ -3870,11 +3520,6 @@ I830BIOSScreenInit(int scrnIndex, Screen
       pI830->pVbe = pI8301->pVbe;
    }
 
-   if (I830IsPrimary(pScrn)) {
-      if (!TweakMemorySize(pScrn, pI830->newBIOSMemSize,FALSE))
-         SetBIOSMemSize(pScrn, pI830->newBIOSMemSize);
-   }
-
    if (!pI830->pVbe)
       return FALSE;
 
@@ -4298,7 +3943,6 @@ I830BIOSLeaveVT(int scrnIndex, int flags
    ResetState(pScrn, TRUE);
 
    RestoreHWState(pScrn);
-   RestoreBIOSMemSize(pScrn);
    if (I830IsPrimary(pScrn))
       I830UnbindAGPMemory(pScrn);
    if (pI830->AccelInfoRec)
@@ -4487,10 +4131,6 @@ I830BIOSEnterVT(int scrnIndex, int flags
          return FALSE;
 
    CheckInheritedState(pScrn);
-   if (I830IsPrimary(pScrn)) {
-      if (!TweakMemorySize(pScrn, pI830->newBIOSMemSize,FALSE))
-         SetBIOSMemSize(pScrn, pI830->newBIOSMemSize);
-   }
 
    ResetState(pScrn, FALSE);
    SetHWOperatingState(pScrn);
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 433aa47..2d8610a 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -65,10 +65,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 static int nextTile = 0;
 static unsigned int tileGeneration = -1;
 
-#ifndef ALLOCATE_ALL_BIOSMEM
-#define ALLOCATE_ALL_BIOSMEM 1
-#endif
-
 static unsigned long
 GetBestTileAlignment(unsigned long size)
 {
@@ -252,11 +248,7 @@ I830FreeVidMem(ScrnInfoPtr pScrn, I830Me
        * USE CAUTION when changing anything here...
        */
       I830MemPool *Pool = range->Pool;
-      if (pI830->overrideBIOSMemSize &&
-          pI830->BIOSMemorySize > pI830->StolenMemory.Size) 
-         Pool->Total.End = pI830->BIOSMemorySize;
-      else 
-         Pool->Total.End = pI830->StolenMemory.End;
+      Pool->Total.End = pI830->StolenMemory.End;
 
       if (pI830->StolenOnly)
          Pool->Free.End += range->Size;
@@ -1078,13 +1070,6 @@ I830ResetAllocations(ScrnInfoPtr pScrn, 
    pI830->MemoryAperture.Size = pI830->FbMapSize - pI830->StolenMemory.Size;
    pI830->StolenPool.Fixed = pI830->StolenMemory;
    pI830->StolenPool.Total = pI830->StolenMemory;
-#if ALLOCATE_ALL_BIOSMEM
-   if (pI830->overrideBIOSMemSize &&
-       pI830->BIOSMemorySize > pI830->StolenMemory.Size) {
-      pI830->StolenPool.Total.End = pI830->BIOSMemorySize;
-      pI830->StolenPool.Total.Size = pI830->BIOSMemorySize;
-   }
-#endif
    pI830->StolenPool.Free = pI830->StolenPool.Total;
    pI830->FreeMemory = pI830->TotalVideoRam - pI830->StolenPool.Total.Size;
    pI830->allocatedMemory = 0;
diff-tree fcec956807038a2e90287850df8b4410b1f8b3c2 (from 0be9bc604420e4433697cc31e8ac58c9f36185e1)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Sat Apr 29 10:55:25 2006 +0800

    Save initialize EXADriverPtr, and free it in failure.

diff --git a/src/i830_exa.c b/src/i830_exa.c
index 6db94d9..59c2d51 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -362,7 +362,8 @@ I830EXAInit(ScreenPtr pScreen)
 	pI830->noAccel = TRUE;
 	return FALSE;
     }
-
+    memset(pI830->EXADriverPtr, 0, sizeof(*pI830->EXADriverPtr));
+    
     pI830->bufferOffset = 0;
     pI830->EXADriverPtr->exa_major = 2;
     pI830->EXADriverPtr->exa_minor = 0;
@@ -409,6 +410,7 @@ I830EXAInit(ScreenPtr pScreen)
 #endif
 
     if(!exaDriverInit(pScreen, pI830->EXADriverPtr)) {
+	xfree(pI830->EXADriverPtr);
 	pI830->noAccel = TRUE;
 	return FALSE;
     }
diff-tree 0be9bc604420e4433697cc31e8ac58c9f36185e1 (from a00a3d198aee7c173c2c36858f4447e13c86eb7f)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Sat Apr 29 10:54:02 2006 +0800

    I830CheckDevicesTimer() sync should be in I830_USE_XAA case.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 50f2059..5cfb6fc 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -6122,13 +6122,14 @@ I830CheckDevicesTimer(OsTimerPtr timer, 
          xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
 		    "Hotkey switch to 0x%lx.\n", (unsigned long) temp);
 
-         if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
+#ifdef I830_USE_XAA
+         if (!pI830->useEXA && pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
             (*pI830->AccelInfoRec->Sync)(pScrn);
             pI830->AccelInfoRec->NeedToSync = FALSE;
             if (xf86IsEntityShared(pScrn->entityList[0]))
                pI8302->AccelInfoRec->NeedToSync = FALSE;
          }
-
+#endif
          GetAttachableDisplayDeviceList(pScrn);
          
 	 pI8301->lastDevice0 = pI8301->lastDevice1;
diff-tree a00a3d198aee7c173c2c36858f4447e13c86eb7f (from c94cc67bcc507e8256ae4b51b84dfe3f4aa12ab5)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Sat Apr 29 10:52:45 2006 +0800

    fix I830BIOSAdjustFrame() sync in I830_USE_EXA case, use exaWaitSync() helper.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 6b03c0f..50f2059 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -196,6 +196,7 @@ const char *I830exaSymbols[] = {
     "exaDriverFini",
     "exaOffscreenAlloc",
     "exaOffscreenFree",
+    "exaWaitSync",
     NULL
 };
 #endif
@@ -5257,11 +5258,18 @@ I830BIOSAdjustFrame(int scrnIndex, int x
 	   x, pI830->xoffset, y, pI830->yoffset);
 
    /* Sync the engine before adjust frame */
-   if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
+#ifdef I830_USE_XAA
+   if (!pI830->noAccel && !pI830->useEXA && pI830->AccelInfoRec->NeedToSync) {
       (*pI830->AccelInfoRec->Sync)(pScrn);
       pI830->AccelInfoRec->NeedToSync = FALSE;
    }
-
+#endif
+#ifdef I830_USE_EXA
+   if (!pI830->noAccel && pI830->useEXA) {
+	ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
+	exaWaitSync(pScreen);
+   }
+#endif
    if (I830IsPrimary(pScrn))
       Start = pI830->FrontBuffer.Start;
    else {
diff-tree c94cc67bcc507e8256ae4b51b84dfe3f4aa12ab5 (from a4a4ced50cc235e79013ce8dd78e35c6eb4c98ca)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Fri Apr 28 15:33:57 2006 -0700

    Update to EXA 2.0 API.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index d6f686d..6b03c0f 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3533,7 +3533,15 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
 
 #ifdef I830_USE_EXA
    if (!pI830->noAccel && pI830->useEXA) {
-      if (!xf86LoadSubModule(pScrn, "exa")) {
+      XF86ModReqInfo req;
+      int errmaj, errmin;
+
+      memset(&req, 0, sizeof(req));
+      req.majorversion = 2;
+      req.minorversion = 0;
+      if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL, &req,
+		&errmaj, &errmin)) {
+	 LoaderErrorMsg(NULL, "exa", errmaj, errmin);
 	 PreInitCleanup(pScrn);
 	 return FALSE;
       }
@@ -5387,8 +5395,10 @@ I830BIOSLeaveVT(int scrnIndex, int flags
       pI830->AccelInfoRec->NeedToSync = FALSE;
 #endif
 #ifdef I830_USE_EXA
-   if (pI830->useEXA && pI830->EXADriverPtr)
-       pI830->EXADriverPtr->card.needsSync = TRUE;
+   if (pI830->useEXA && pI830->EXADriverPtr) {
+      ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
+      exaMarkSync(pScreen);
+   }
 #endif
 
    /* DO IT AGAIN! AS IT SEEMS THAT SOME LFPs FLICKER OTHERWISE */
@@ -5732,7 +5742,7 @@ I830BIOSSwitchMode(int scrnIndex, Displa
 #ifdef I830_USE_EXA
    if (!pI830->noAccel && pI830->useEXA) {
       ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
-      (*pI830->EXADriverPtr->accel.WaitMarker)(pScreen, 0);
+      exaWaitSync(pScreen);
    }
 #endif
 
diff --git a/src/i830_exa.c b/src/i830_exa.c
index a6aa6a7..6db94d9 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -357,54 +357,55 @@ I830EXAInit(ScreenPtr pScreen)
     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
 
-    if(pI830->useEXA) {
-	if(!(pI830->EXADriverPtr = xnfcalloc(sizeof(ExaDriverRec), 1))) {
-	    pI830->noAccel = TRUE;
-	    return FALSE;
-	}
+    pI830->EXADriverPtr = exaDriverAlloc();
+    if (pI830->EXADriverPtr == NULL) {
+	pI830->noAccel = TRUE;
+	return FALSE;
     }
 
     pI830->bufferOffset = 0;
-    pI830->EXADriverPtr->card.memoryBase = pI830->FbBase;
-    pI830->EXADriverPtr->card.offScreenBase = pI830->Offscreen.Start;
-    pI830->EXADriverPtr->card.memorySize = pI830->Offscreen.Size;
+    pI830->EXADriverPtr->exa_major = 2;
+    pI830->EXADriverPtr->exa_minor = 0;
+    pI830->EXADriverPtr->memoryBase = pI830->FbBase;
+    pI830->EXADriverPtr->offScreenBase = pI830->Offscreen.Start;
+    pI830->EXADriverPtr->memorySize = pI830->Offscreen.Size;
 	   
-    if(pI830->EXADriverPtr->card.memorySize >
-       pI830->EXADriverPtr->card.offScreenBase)
-	pI830->EXADriverPtr->card.flags = EXA_OFFSCREEN_PIXMAPS;
+    if(pI830->EXADriverPtr->memorySize >
+       pI830->EXADriverPtr->offScreenBase)
+	pI830->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS;
     else {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Not enough video RAM for "
 		   "offscreen memory manager. Xv disabled\n");
 	/* disable Xv here... */
     }
 
-    pI830->EXADriverPtr->card.pixmapOffsetAlign = 256;
-    pI830->EXADriverPtr->card.pixmapPitchAlign = 64;
-    pI830->EXADriverPtr->card.maxX = 4095;
-    pI830->EXADriverPtr->card.maxY = 4095;
+    pI830->EXADriverPtr->pixmapOffsetAlign = 256;
+    pI830->EXADriverPtr->pixmapPitchAlign = 64;
+    pI830->EXADriverPtr->maxX = 4095;
+    pI830->EXADriverPtr->maxY = 4095;
 
     /* Sync */
-    pI830->EXADriverPtr->accel.WaitMarker = I830EXASync;
+    pI830->EXADriverPtr->WaitMarker = I830EXASync;
 
     /* Solid fill */
-    pI830->EXADriverPtr->accel.PrepareSolid = I830EXAPrepareSolid;
-    pI830->EXADriverPtr->accel.Solid = I830EXASolid;
-    pI830->EXADriverPtr->accel.DoneSolid = I830EXADoneSolid;
+    pI830->EXADriverPtr->PrepareSolid = I830EXAPrepareSolid;
+    pI830->EXADriverPtr->Solid = I830EXASolid;
+    pI830->EXADriverPtr->DoneSolid = I830EXADoneSolid;
 
     /* Copy */
-    pI830->EXADriverPtr->accel.PrepareCopy = I830EXAPrepareCopy;
-    pI830->EXADriverPtr->accel.Copy = I830EXACopy;
-    pI830->EXADriverPtr->accel.DoneCopy = I830EXADoneCopy;
+    pI830->EXADriverPtr->PrepareCopy = I830EXAPrepareCopy;
+    pI830->EXADriverPtr->Copy = I830EXACopy;
+    pI830->EXADriverPtr->DoneCopy = I830EXADoneCopy;
 #if 0
     /* Upload, download to/from Screen */
-    pI830->EXADriverPtr->accel.UploadToScreen = I830EXAUploadToScreen;
-    pI830->EXADriverPtr->accel.DownloadFromScreen = I830EXADownloadFromScreen;
+    pI830->EXADriverPtr->UploadToScreen = I830EXAUploadToScreen;
+    pI830->EXADriverPtr->DownloadFromScreen = I830EXADownloadFromScreen;
 
     /* Composite */
-    pI830->EXADriverPtr->accel.CheckComposite = I830EXACheckComposite;
-    pI830->EXADriverPtr->accel.PrepareComposite = I830EXAPrepareComposite;
-    pI830->EXADriverPtr->accel.Composite = I830EXAComposite;
-    pI830->EXADriverPtr->accel.DoneComposite = I830EXADoneComposite;
+    pI830->EXADriverPtr->CheckComposite = I830EXACheckComposite;
+    pI830->EXADriverPtr->PrepareComposite = I830EXAPrepareComposite;
+    pI830->EXADriverPtr->Composite = I830EXAComposite;
+    pI830->EXADriverPtr->DoneComposite = I830EXADoneComposite;
 #endif
 
     if(!exaDriverInit(pScreen, pI830->EXADriverPtr)) {
diff-tree a4a4ced50cc235e79013ce8dd78e35c6eb4c98ca (from 941a49f91eac02e256706d8821a2cb069ff7ffef)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Fri Apr 28 14:59:52 2006 -0700

    Get it to compile.

diff --git a/src/Makefile.am b/src/Makefile.am
index c64c203..83025fa 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -24,7 +24,7 @@ SUBDIRS = xvmc
 # -avoid-version prevents gratuitous .0.0.0 version numbers on the end
 # _ladir passes a dummy rpath to libtool so the thing will actually link
 # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
-AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ -DI830_XV
+AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ -DI830_XV -DI830_USE_XAA -DI830_USE_EXA
 
 i810_drv_la_LTLIBRARIES = i810_drv.la
 i810_drv_la_LDFLAGS = -module -avoid-version
@@ -54,7 +54,9 @@ i810_drv_la_SOURCES = \
          i830_modes.c \
          i830_video.c \
          i830_rotate.c \
-	 i830_randr.c
+	 i830_randr.c \
+	 i830_exa.c \
+	 i830_xaa.c
 
 if DRI
 i810_drv_la_SOURCES += \
diff --git a/src/i830_driver.c b/src/i830_driver.c
index de510e6..d6f686d 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -5724,7 +5724,7 @@ I830BIOSSwitchMode(int scrnIndex, Displa
 
    /* Sync the engine before mode switch */
 #ifdef I830_USE_XAA
-   if (!pI830->noAccel && !pI830->useEXA)
+   if (!pI830->noAccel && !pI830->useEXA) {
       (*pI830->AccelInfoRec->Sync)(pScrn);
       pI830->AccelInfoRec->NeedToSync = FALSE;
    }
diff-tree 941a49f91eac02e256706d8821a2cb069ff7ffef (from 1dbb19059f5dd5cd2ad386c4f73498095987b943)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Fri Apr 28 14:57:03 2006 -0700

    Commit what applied from Jesse Barnes's i830-exa-latest.patch.

diff --git a/man/i810.man b/man/i810.man
index 099e1f8..62d6b73 100644
--- a/man/i810.man
+++ b/man/i810.man
@@ -204,6 +204,12 @@ Allows more memory for the offscreen all
 situations where HDTV movies are required to play but not enough offscreen
 memory is usually available. Set this to 6144 for upto 1920x1080 HDTV support.
 Default 0KB (off).
+.TP
+.BI "Option \*qAccelMethod\*q \*q" string \*q
+Choose acceleration architecture, either "XAA" or "EXA".  XAA is the old
+(but stable) XFree86 based acceleration architecture.  EXA is a newer and
+simpler acceleration architecture designed to better accelerate the X Render
+extension.  Default: "XAA".
 
 .SH "SEE ALSO"
 __xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), xorgconfig(__appmansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__)
@@ -213,4 +219,5 @@ Jeff Hartmann, Mark Vojkovich, Alan Hour
 support reworked for XFree86 4.3 by David Dawes and Keith Whitwell.
 852GM, 855GM, and 865G support added by David Dawes and Keith Whitwell.
 915G and 915GM support added by Alan Hourihane and Keith Whitwell.
-Dual Head, Clone and lid status support added by Alan Hourihane.
+Dual Head, Clone and lid status support added by Alan Hourihane.  EXA support
+added by Jesse Barnes.
diff --git a/src/i830.h b/src/i830.h
index d227662..edc485b 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -68,6 +68,15 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "i830_dri.h"
 #endif
 
+#ifdef I830_USE_EXA
+#include "exa.h"
+Bool I830EXAInit(ScreenPtr pScreen);
+#endif
+
+#ifdef I830_USE_XAA
+Bool I830XAAInit(ScreenPtr pScreen);
+#endif
+
 #include "common.h"
 
 /* I830 Video BIOS support */
@@ -203,7 +212,9 @@ typedef struct _I830Rec {
    I830MemRange FrontBuffer2;
    I830MemRange Scratch;
    I830MemRange Scratch2;
-
+#ifdef I830_USE_EXA
+   I830MemRange Offscreen;
+#endif
    /* Regions allocated either from the above pools, or from agpgart. */
    I830MemRange	*CursorMem;
    I830MemRange	*CursorMemARGB;
@@ -279,13 +290,22 @@ typedef struct _I830Rec {
    I830RegRec SavedReg;
    I830RegRec ModeReg;
 
+   Bool useEXA;
    Bool noAccel;
    Bool SWCursor;
    Bool cursorOn;
+#ifdef I830_USE_XAA
    XAAInfoRecPtr AccelInfoRec;
+#endif
    xf86CursorInfoPtr CursorInfoRec;
    CloseScreenProcPtr CloseScreen;
 
+#ifdef I830_USE_EXA
+   unsigned int copy_src_pitch;
+   unsigned int copy_src_off;
+   ExaDriverPtr	EXADriverPtr;
+#endif
+
    I830WriteIndexedByteFunc writeControl;
    I830ReadIndexedByteFunc readControl;
    I830WriteByteFunc writeStandard;
diff --git a/src/i830_accel.c b/src/i830_accel.c
index a11f64b..a1a6488 100644
--- a/src/i830_accel.c
+++ b/src/i830_accel.c
@@ -7,10 +7,6 @@
 #include "config.h"
 #endif
 
-#ifndef DO_SCANLINE_IMAGE_WRITE
-#define DO_SCANLINE_IMAGE_WRITE 0
-#endif
-
 /**************************************************************************
 
 Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
@@ -111,7 +107,9 @@ I830WaitLpRing(ScrnInfoPtr pScrn, int n,
 	    DRICloseScreen(screenInfo.screens[pScrn->scrnIndex]);
 	 }
 #endif
+#ifdef I830_USE_XAA
 	 pI830->AccelInfoRec = NULL;	/* Stops recursive behavior */
+#endif
 	 FatalError("lockup\n");
       }
 
@@ -210,46 +208,11 @@ I830RefreshRing(ScrnInfoPtr pScrn)
    pI830->LpRing->space = pI830->LpRing->head - (pI830->LpRing->tail + 8);
    if (pI830->LpRing->space < 0)
       pI830->LpRing->space += pI830->LpRing->mem.Size;
-
+#ifdef I830_USE_XAA
    if (pI830->AccelInfoRec)
       pI830->AccelInfoRec->NeedToSync = TRUE;
-}
-
-/* I830 Accel Functions */
-
-static void I830SetupForMono8x8PatternFill(ScrnInfoPtr pScrn,
-					   int pattx, int patty,
-					   int fg, int bg, int rop,
-					   unsigned int planemask);
-static void I830SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn,
-						 int pattx, int patty,
-						 int x, int y, int w, int h);
-
-static void I830SetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
-							   int fg, int bg,
-							   int rop,
-							   unsigned int mask);
-
-static void I830SubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr
-							     pScrn, int x,
-							     int y, int w,
-							     int h,
-							     int skipleft);
-
-static void I830SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno);
-
-#if DO_SCANLINE_IMAGE_WRITE
-static void I830SetupForScanlineImageWrite(ScrnInfoPtr pScrn, int rop,
-					   unsigned int planemask,
-					   int trans_color, int bpp,
-					   int depth);
-static void I830SubsequentScanlineImageWriteRect(ScrnInfoPtr pScrn,
-						 int x, int y, int w, int h,
-						 int skipleft);
-static void I830SubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno);
 #endif
-static void I830RestoreAccelState(ScrnInfoPtr pScrn);
-
+}
 
 /* The following function sets up the supported acceleration. Call it
  * from the FbInit() function in the SVGA driver, or before ScreenInit
@@ -258,539 +221,16 @@ static void I830RestoreAccelState(ScrnIn
 Bool
 I830AccelInit(ScreenPtr pScreen)
 {
-   XAAInfoRecPtr infoPtr;
-   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-   I830Ptr pI830 = I830PTR(pScrn);
-   int i;
-   int width = 0;
-   int nr_buffers = 0;
-   unsigned char *ptr = NULL;
-
-   if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
-      ErrorF("I830AccelInit\n");
-
-   pI830->AccelInfoRec = infoPtr = XAACreateInfoRec();
-   if (!infoPtr)
-      return FALSE;
-
-   pI830->bufferOffset = 0;
-   infoPtr->Flags = LINEAR_FRAMEBUFFER | OFFSCREEN_PIXMAPS | PIXMAP_CACHE;
-
-   /* Use the same sync function as the I830.
-    */
-   infoPtr->Sync = I830Sync;
-
-   /* Everything else is different enough to justify different functions */
-   {
-      infoPtr->SolidFillFlags = NO_PLANEMASK;
-      infoPtr->SetupForSolidFill = I830SetupForSolidFill;
-      infoPtr->SubsequentSolidFillRect = I830SubsequentSolidFillRect;
-   }
-
-   {
-      infoPtr->ScreenToScreenCopyFlags = (NO_PLANEMASK | NO_TRANSPARENCY);
-
-      infoPtr->SetupForScreenToScreenCopy = I830SetupForScreenToScreenCopy;
-      infoPtr->SubsequentScreenToScreenCopy =
-	    I830SubsequentScreenToScreenCopy;
-   }
-
-   {
-      infoPtr->SetupForMono8x8PatternFill = I830SetupForMono8x8PatternFill;
-      infoPtr->SubsequentMono8x8PatternFillRect =
-	    I830SubsequentMono8x8PatternFillRect;
-
-      infoPtr->Mono8x8PatternFillFlags = (HARDWARE_PATTERN_PROGRAMMED_BITS |
-					  HARDWARE_PATTERN_SCREEN_ORIGIN |
-					  HARDWARE_PATTERN_PROGRAMMED_ORIGIN |
-					  BIT_ORDER_IN_BYTE_MSBFIRST |
-					  NO_PLANEMASK);
-
-   }
+#ifdef I830_USE_EXA
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
 
-   /* On the primary screen */
-   if (pI830->init == 0) {
-      if (pI830->Scratch.Size != 0) {
-         width = ((pScrn->displayWidth + 31) & ~31) / 8;
-         nr_buffers = pI830->Scratch.Size / width;
-         ptr = pI830->FbBase + pI830->Scratch.Start;
-      }
-   } else {
-   /* On the secondary screen */
-      I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
-      if (pI8301->Scratch2.Size != 0) {
-         width = ((pScrn->displayWidth + 31) & ~31) / 8;
-         nr_buffers = pI8301->Scratch2.Size / width;
-         /* We have to use the primary screen's FbBase, as that's where
-          * we allocated Scratch2, so we get the correct pointer */
-         ptr = pI8301->FbBase + pI8301->Scratch2.Start;
-      }
-   }
-
-   if (nr_buffers) {
-      pI830->NumScanlineColorExpandBuffers = nr_buffers;
-      pI830->ScanlineColorExpandBuffers = (unsigned char **)
-	    xnfcalloc(nr_buffers, sizeof(unsigned char *));
-
-      for (i = 0; i < nr_buffers; i++, ptr += width)
-	 pI830->ScanlineColorExpandBuffers[i] = ptr;
-
-      infoPtr->ScanlineCPUToScreenColorExpandFillFlags =
-	    (NO_PLANEMASK | ROP_NEEDS_SOURCE | BIT_ORDER_IN_BYTE_MSBFIRST);
-
-      infoPtr->ScanlineColorExpandBuffers = (unsigned char **)
-	    xnfcalloc(1, sizeof(unsigned char *));
-      infoPtr->NumScanlineColorExpandBuffers = 1;
-
-      infoPtr->ScanlineColorExpandBuffers[0] =
-	    pI830->ScanlineColorExpandBuffers[0];
-      pI830->nextColorExpandBuf = 0;
-
-      infoPtr->SetupForScanlineCPUToScreenColorExpandFill =
-	    I830SetupForScanlineCPUToScreenColorExpandFill;
-
-      infoPtr->SubsequentScanlineCPUToScreenColorExpandFill =
-	    I830SubsequentScanlineCPUToScreenColorExpandFill;
-
-      infoPtr->SubsequentColorExpandScanline =
-	    I830SubsequentColorExpandScanline;
-
-#if DO_SCANLINE_IMAGE_WRITE
-      infoPtr->NumScanlineImageWriteBuffers = 1;
-      infoPtr->ScanlineImageWriteBuffers = infoPtr->ScanlineColorExpandBuffers;
-      infoPtr->SetupForScanlineImageWrite = I830SetupForScanlineImageWrite;
-      infoPtr->SubsequentScanlineImageWriteRect =
-	    I830SubsequentScanlineImageWriteRect;
-      infoPtr->SubsequentImageWriteScanline = I830SubsequentImageWriteScanline;
-      infoPtr->ScanlineImageWriteFlags = NO_GXCOPY |
-					 NO_PLANEMASK |
-					 ROP_NEEDS_SOURCE |
-					 SCANLINE_PAD_DWORD;
+    if (pI830->useEXA)
+	return I830EXAInit(pScreen);
 #endif
-   }
-
-   {
-      Bool shared_accel = FALSE;
-      int i;
-
-      for(i = 0; i < pScrn->numEntities; i++) {
-         if(xf86IsEntityShared(pScrn->entityList[i]))
-            shared_accel = TRUE;
-      }
-      if(shared_accel == TRUE)
-         infoPtr->RestoreAccelState = I830RestoreAccelState;
-   }
-
-   I830SelectBuffer(pScrn, I830_SELECT_FRONT);
-
-   return XAAInit(pScreen, infoPtr);
-}
-
-void
-I830SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
-		      unsigned int planemask)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-
-   if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
-      ErrorF("I830SetupForFillRectSolid color: %x rop: %x mask: %x\n",
-	     color, rop, planemask);
-
-   pI830->BR[13] = ((XAAGetPatternROP(rop) << 16) |
-		    (pScrn->displayWidth * pI830->cpp));
-
-   pI830->BR[16] = color;
-
-   switch (pScrn->bitsPerPixel) {
-   case 8:
-      break;
-   case 16:
-      pI830->BR[13] |= (1 << 24);
-      break;
-   case 32:
-      pI830->BR[13] |= ((1 << 25) | (1 << 24));
-      break;
-   }
-}
-
-void
-I830SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-
-   if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
-      ErrorF("I830SubsequentFillRectSolid %d,%d %dx%d\n", x, y, w, h);
-
-   {
-      BEGIN_LP_RING(6);
-
-      if (pScrn->bitsPerPixel == 32) {
-	 OUT_RING(COLOR_BLT_CMD | COLOR_BLT_WRITE_ALPHA |
-		  COLOR_BLT_WRITE_RGB);
-      } else {
-	 OUT_RING(COLOR_BLT_CMD);
-      }
-      OUT_RING(pI830->BR[13]);
-      OUT_RING((h << 16) | (w * pI830->cpp));
-      OUT_RING(pI830->bufferOffset + (y * pScrn->displayWidth + x) *
-	       pI830->cpp);
-      OUT_RING(pI830->BR[16]);
-      OUT_RING(0);
-
-      ADVANCE_LP_RING();
-   }
-}
-
-void
-I830SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop,
-			       unsigned int planemask, int transparency_color)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-
-   if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
-      ErrorF("I830SetupForScreenToScreenCopy %d %d %x %x %d\n",
-	     xdir, ydir, rop, planemask, transparency_color);
-
-   pI830->BR[13] = (pScrn->displayWidth * pI830->cpp);
-   pI830->BR[13] |= XAAGetCopyROP(rop) << 16;
-
-   switch (pScrn->bitsPerPixel) {
-   case 8:
-      break;
-   case 16:
-      pI830->BR[13] |= (1 << 24);
-      break;
-   case 32:
-      pI830->BR[13] |= ((1 << 25) | (1 << 24));
-      break;
-   }
-
-}
-
-void
-I830SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int src_x1, int src_y1,
-				 int dst_x1, int dst_y1, int w, int h)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   int dst_x2, dst_y2;
-
-   if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
-      ErrorF("I830SubsequentScreenToScreenCopy %d,%d - %d,%d %dx%d\n",
-	     src_x1, src_y1, dst_x1, dst_y1, w, h);
-
-   dst_x2 = dst_x1 + w;
-   dst_y2 = dst_y1 + h;
-
-   {
-      BEGIN_LP_RING(8);
-
-      if (pScrn->bitsPerPixel == 32) {
-	 OUT_RING(XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
-		  XY_SRC_COPY_BLT_WRITE_RGB);
-      } else {
-	 OUT_RING(XY_SRC_COPY_BLT_CMD);
-      }
-      OUT_RING(pI830->BR[13]);
-      OUT_RING((dst_y1 << 16) | (dst_x1 & 0xffff));
-      OUT_RING((dst_y2 << 16) | (dst_x2 & 0xffff));
-      OUT_RING(pI830->bufferOffset);
-      OUT_RING((src_y1 << 16) | (src_x1 & 0xffff));
-      OUT_RING(pI830->BR[13] & 0xFFFF);
-      OUT_RING(pI830->bufferOffset);
-
-      ADVANCE_LP_RING();
-   }
-}
-
-static void
-I830SetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int pattx, int patty,
-			       int fg, int bg, int rop,
-			       unsigned int planemask)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-
-   if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
-      ErrorF("I830SetupForMono8x8PatternFill\n");
-
-   pI830->BR[16] = pattx;
-   pI830->BR[17] = patty;
-   pI830->BR[18] = bg;
-   pI830->BR[19] = fg;
-
-   pI830->BR[13] = (pScrn->displayWidth * pI830->cpp);	/* In bytes */
-   pI830->BR[13] |= XAAGetPatternROP(rop) << 16;
-   if (bg == -1)
-      pI830->BR[13] |= (1 << 28);
-
-   switch (pScrn->bitsPerPixel) {
-   case 8:
-      break;
-   case 16:
-      pI830->BR[13] |= (1 << 24);
-      break;
-   case 32:
-      pI830->BR[13] |= ((1 << 25) | (1 << 24));
-      break;
-   }
-
-}
-
-static void
-I830SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int pattx, int patty,
-				     int x, int y, int w, int h)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   int x1, x2, y1, y2;
-
-   x1 = x;
-   x2 = x + w;
-   y1 = y;
-   y2 = y + h;
-
-   if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
-      ErrorF("I830SubsequentMono8x8PatternFillRect\n");
-
-   {
-      BEGIN_LP_RING(10);
-
-      if (pScrn->bitsPerPixel == 32) {
-	 OUT_RING(XY_MONO_PAT_BLT_CMD | XY_MONO_PAT_BLT_WRITE_ALPHA |
-		  XY_MONO_PAT_BLT_WRITE_RGB |
-		  ((patty << 8) & XY_MONO_PAT_VERT_SEED) |
-		  ((pattx << 12) & XY_MONO_PAT_HORT_SEED));
-      } else {
-	 OUT_RING(XY_MONO_PAT_BLT_CMD |
-		  ((patty << 8) & XY_MONO_PAT_VERT_SEED) |
-		  ((pattx << 12) & XY_MONO_PAT_HORT_SEED));
-      }
-      OUT_RING(pI830->BR[13]);
-      OUT_RING((y1 << 16) | x1);
-      OUT_RING((y2 << 16) | x2);
-      OUT_RING(pI830->bufferOffset);
-      OUT_RING(pI830->BR[18]);		/* bg */
-      OUT_RING(pI830->BR[19]);		/* fg */
-      OUT_RING(pI830->BR[16]);		/* pattern data */
-      OUT_RING(pI830->BR[17]);
-      OUT_RING(0);
-      ADVANCE_LP_RING();
-   }
-}
-
-static void
-I830GetNextScanlineColorExpandBuffer(ScrnInfoPtr pScrn)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   XAAInfoRecPtr infoPtr = pI830->AccelInfoRec;
-
-   if (pI830->nextColorExpandBuf == pI830->NumScanlineColorExpandBuffers)
-      I830Sync(pScrn);
-
-   infoPtr->ScanlineColorExpandBuffers[0] =
-	 pI830->ScanlineColorExpandBuffers[pI830->nextColorExpandBuf];
-
-   if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
-      ErrorF("using color expand buffer %d\n", pI830->nextColorExpandBuf);
-
-   pI830->nextColorExpandBuf++;
-}
-
-static void
-I830SetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
-					       int fg, int bg, int rop,
-					       unsigned int planemask)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-
-   if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
-      ErrorF("I830SetupForScanlineScreenToScreenColorExpand %d %d %x %x\n",
-	     fg, bg, rop, planemask);
-
-   /* Fill out register values */
-   pI830->BR[13] = (pScrn->displayWidth * pI830->cpp);
-   pI830->BR[13] |= XAAGetCopyROP(rop) << 16;
-   if (bg == -1)
-      pI830->BR[13] |= (1 << 29);
-
-   switch (pScrn->bitsPerPixel) {
-   case 8:
-      break;
-   case 16:
-      pI830->BR[13] |= (1 << 24);
-      break;
-   case 32:
-      pI830->BR[13] |= ((1 << 25) | (1 << 24));
-      break;
-   }
-
-   pI830->BR[18] = bg;
-   pI830->BR[19] = fg;
-
-   I830GetNextScanlineColorExpandBuffer(pScrn);
-}
-
-static void
-I830SubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
-						 int x, int y,
-						 int w, int h, int skipleft)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-
-   if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
-      ErrorF("I830SubsequentScanlineCPUToScreenColorExpandFill "
-	     "%d,%d %dx%x %d\n", x, y, w, h, skipleft);
-
-   /* Fill out register values */
-   pI830->BR[9] = (pI830->bufferOffset +
-		   (y * pScrn->displayWidth + x) * pI830->cpp);
-   pI830->BR[11] = ((1 << 16) | w);
-}
-
-static void
-I830SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-
-   if (pI830->init == 0) {
-      pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] -
-		       pI830->FbBase);
-   } else {
-      I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
-
-      /* We have to use the primary screen's FbBase, as that's where
-       * we allocated Scratch2, so we get the correct pointer */
-      pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] -
-		       pI8301->FbBase);
-   }
-
-   if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
-      ErrorF("I830SubsequentColorExpandScanline %d (addr %x)\n",
-	     bufno, pI830->BR[12]);
-
-   {
-      BEGIN_LP_RING(8);
-
-      if (pScrn->bitsPerPixel == 32) {
-	 OUT_RING(XY_MONO_SRC_BLT_CMD | XY_MONO_SRC_BLT_WRITE_ALPHA |
-		  XY_MONO_SRC_BLT_WRITE_RGB);
-      } else {
-	 OUT_RING(XY_MONO_SRC_BLT_CMD);
-      }
-      OUT_RING(pI830->BR[13]);
-      OUT_RING(0);			/* x1 = 0, y1 = 0 */
-      OUT_RING(pI830->BR[11]);		/* x2 = w, y2 = 1 */
-      OUT_RING(pI830->BR[9]);		/* dst addr */
-      OUT_RING(pI830->BR[12]);		/* src addr */
-      OUT_RING(pI830->BR[18]);		/* bg */
-      OUT_RING(pI830->BR[19]);		/* fg */
-
-      ADVANCE_LP_RING();
-   }
-
-   /* Advance to next scanline.
-    */
-   pI830->BR[9] += pScrn->displayWidth * pI830->cpp;
-   I830GetNextScanlineColorExpandBuffer(pScrn);
-}
-
-#if DO_SCANLINE_IMAGE_WRITE
-static void
-I830SetupForScanlineImageWrite(ScrnInfoPtr pScrn, int rop,
-			       unsigned int planemask, int trans_color,
-			       int bpp, int depth)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-
-   if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
-      ErrorF("I830SetupForScanlineImageWrite %x %x\n", rop, planemask);
-
-   /* Fill out register values */
-   pI830->BR[13] = (pScrn->displayWidth * pI830->cpp);
-   pI830->BR[13] |= XAAGetCopyROP(rop) << 16;
-
-   switch (pScrn->bitsPerPixel) {
-   case 8:
-      break;
-   case 16:
-      pI830->BR[13] |= (1 << 24);
-      break;
-   case 32:
-      pI830->BR[13] |= ((1 << 25) | (1 << 24));
-      break;
-   }
-
-   I830GetNextScanlineColorExpandBuffer(pScrn);
-}
-
-static void
-I830SubsequentScanlineImageWriteRect(ScrnInfoPtr pScrn, int x, int y,
-				     int w, int h, int skipleft)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-
-   if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
-      ErrorF("I830SubsequentScanlineImageWriteRect "
-	     "%d,%d %dx%x %d\n", x, y, w, h, skipleft);
-
-   /* Fill out register values */
-   pI830->BR[9] = (pI830->bufferOffset +
-		   (y * pScrn->displayWidth + x) * pI830->cpp);
-   pI830->BR[11] = ((1 << 16) | w);
-}
-
-static void
-I830SubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-
-   if (pI830->init == 0) {
-      pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] -
-		       pI830->FbBase);
-   } else {
-      I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
-
-      /* We have to use the primary screen's FbBase, as that's where
-       * we allocated Scratch2, so we get the correct pointer */
-      pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] -
-		       pI8301->FbBase);
-   }
-
-   if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
-      ErrorF("I830SubsequentImageWriteScanline %d (addr %x)\n",
-	     bufno, pI830->BR[12]);
-
-   {
-      BEGIN_LP_RING(8);
-
-      if (pScrn->bitsPerPixel == 32) {
-	 OUT_RING(XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
-		  XY_SRC_COPY_BLT_WRITE_RGB);
-      } else {
-	 OUT_RING(XY_SRC_COPY_BLT_CMD);
-      }
-      OUT_RING(pI830->BR[13]);
-      OUT_RING(0);			/* x1 = 0, y1 = 0 */
-      OUT_RING(pI830->BR[11]);		/* x2 = w, y2 = 1 */
-      OUT_RING(pI830->BR[9]);		/* dst addr */
-      OUT_RING(0);			/* source origin (0,0) */
-      OUT_RING(pI830->BR[11] & 0xffff);	/* source pitch */
-      OUT_RING(pI830->BR[12]);		/* src addr */
-
-      ADVANCE_LP_RING();
-   }
-
-   /* Advance to next scanline.
-    */
-   pI830->BR[9] += pScrn->displayWidth * pI830->cpp;
-   I830GetNextScanlineColorExpandBuffer(pScrn);
-}
-#endif
-
-/* Support for multiscreen */
-static void
-I830RestoreAccelState(ScrnInfoPtr pScrn)
-{
-#if 0
-   /* might be needed, but everything is on a ring, so I don't think so */
-   I830Sync(pScrn);
+#ifdef I830_USE_XAA
+    return I830XAAInit(pScreen);
 #endif
+    return FALSE;
 }
+
diff --git a/src/i830_dga.c b/src/i830_dga.c
index 1129fa3..08207d3 100644
--- a/src/i830_dga.c
+++ b/src/i830_dga.c
@@ -238,6 +238,7 @@ static void
 I830_FillRect(ScrnInfoPtr pScrn,
 	      int x, int y, int w, int h, unsigned long color)
 {
+#ifdef I830_USE_XAA
    I830Ptr pI830 = I830PTR(pScrn);
 
    MARKER();
@@ -247,11 +248,13 @@ I830_FillRect(ScrnInfoPtr pScrn,
       (*pI830->AccelInfoRec->SubsequentSolidFillRect) (pScrn, x, y, w, h);
       SET_SYNC_FLAG(pI830->AccelInfoRec);
    }
+#endif
 }
 
 static void
 I830_Sync(ScrnInfoPtr pScrn)
 {
+#ifdef I830_USE_XAA
    I830Ptr pI830 = I830PTR(pScrn);
 
    MARKER();
@@ -259,12 +262,14 @@ I830_Sync(ScrnInfoPtr pScrn)
    if (pI830->AccelInfoRec) {
       (*pI830->AccelInfoRec->Sync) (pScrn);
    }
+#endif
 }
 
 static void
 I830_BlitRect(ScrnInfoPtr pScrn,
 	      int srcx, int srcy, int w, int h, int dstx, int dsty)
 {
+#ifdef I830_USE_XAA
    I830Ptr pI830 = I830PTR(pScrn);
 
    MARKER();
@@ -279,6 +284,7 @@ I830_BlitRect(ScrnInfoPtr pScrn,
 							    dstx, dsty, w, h);
       SET_SYNC_FLAG(pI830->AccelInfoRec);
    }
+#endif
 }
 
 #if 0
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 13d2cfd..c159686 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1017,7 +1017,9 @@ I830DRIInitBuffers(WindowPtr pWin, Regio
    }
 
    I830SelectBuffer(pScrn, I830_SELECT_FRONT);
+#ifdef I830_USE_XAA
    pI830->AccelInfoRec->NeedToSync = TRUE;
+#endif
 }
 
 /* This routine is a modified form of XAADoBitBlt with the calls to
@@ -1178,8 +1180,9 @@ I830DRIMoveBuffers(WindowPtr pParent, DD
       DEALLOCATE_LOCAL(pptNew1);
       DEALLOCATE_LOCAL(pboxNew1);
    }
-
+#ifdef I830_USE_XAA
    pI830->AccelInfoRec->NeedToSync = TRUE;
+#endif
 }
 
 /* Initialize the first context */
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 053ccd1..de510e6 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -189,6 +189,17 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "dri.h"
 #endif
 
+#ifdef I830_USE_EXA
+const char *I830exaSymbols[] = {
+    "exaGetVersion",
+    "exaDriverInit",
+    "exaDriverFini",
+    "exaOffscreenAlloc",
+    "exaOffscreenFree",
+    NULL
+};
+#endif
+
 #define BIT(x) (1 << (x))
 #define MAX(a,b) ((a) > (b) ? (a) : (b))
 #define NB_OF(x) (sizeof (x) / sizeof (*x))
@@ -227,6 +238,9 @@ static PciChipsets I830BIOSPciChipsets[]
  */
 
 typedef enum {
+#if defined(I830_USE_XAA) && defined(I830_USE_EXA)
+   OPTION_ACCELMETHOD,
+#endif
    OPTION_NOACCEL,
    OPTION_SW_CURSOR,
    OPTION_CACHE_LINES,
@@ -248,6 +262,9 @@ typedef enum {
 } I830Opts;
 
 static OptionInfoRec I830BIOSOptions[] = {
+#if defined(I830_USE_XAA) && defined(I830_USE_EXA)
+   {OPTION_ACCELMETHOD,	"AccelMethod",	OPTV_ANYSTR,	{0},	FALSE},
+#endif
    {OPTION_NOACCEL,	"NoAccel",	OPTV_BOOLEAN,	{0},	FALSE},
    {OPTION_SW_CURSOR,	"SWcursor",	OPTV_BOOLEAN,	{0},	FALSE},
    {OPTION_CACHE_LINES,	"CacheLines",	OPTV_INTEGER,	{0},	FALSE},
@@ -2448,6 +2465,42 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
    if (xf86ReturnOptValBool(pI830->Options, OPTION_NOACCEL, FALSE)) {
       pI830->noAccel = TRUE;
    }
+
+   /*
+    * The ugliness below:
+    * If either XAA or EXA (exclusive) is compiled in, default to it.
+    * 
+    * If both are compiled in, and the user didn't specify noAccel, use the
+    * config option AccelMethod to determine which to use, defaulting to XAA
+    * if none is specified, or if the string was unrecognized.
+    *
+    * All this *could* go away if we removed XAA support from this driver,
+    * for example. :)
+    */
+   if (!pI830->noAccel) {
+#if (defined(I830_USE_EXA) && defined(I830_USE_XAA)) || !defined(I830_USE_EXA)
+       pI830->useEXA = FALSE;
+#else
+       pI830->useEXA = TRUE;
+#endif
+#if defined(I830_USE_XAA) && defined(I830_USE_EXA)
+       int from = X_DEFAULT;
+       if ((s = (char *)xf86GetOptValString(pI830->Options,
+					    OPTION_ACCELMETHOD))) {
+	   if (!xf86NameCmp(s, "EXA")) {
+	       from = X_CONFIG;
+	       pI830->useEXA = TRUE;
+	   }
+	   else if (!xf86NameCmp(s, "XAA")) {
+	       from = X_CONFIG;
+	       pI830->useEXA = FALSE;
+	   }
+       }
+#endif
+       xf86DrvMsg(pScrn->scrnIndex, from, "Using %s for acceleration\n",
+		  pI830->useEXA ? "EXA" : "XAA");
+   }
+
    if (xf86ReturnOptValBool(pI830->Options, OPTION_SW_CURSOR, FALSE)) {
       pI830->SWCursor = TRUE;
    }
@@ -3468,14 +3521,25 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
 
    xf86LoaderReqSymLists(I810fbSymbols, NULL);
 
-   if (!pI830->noAccel) {
+#ifdef I830_USE_XAA
+   if (!pI830->noAccel && !pI830->useEXA) {
       if (!xf86LoadSubModule(pScrn, "xaa")) {
 	 PreInitCleanup(pScrn);
 	 return FALSE;
       }
       xf86LoaderReqSymLists(I810xaaSymbols, NULL);
    }
+#endif
 
+#ifdef I830_USE_EXA
+   if (!pI830->noAccel && pI830->useEXA) {
+      if (!xf86LoadSubModule(pScrn, "exa")) {
+	 PreInitCleanup(pScrn);
+	 return FALSE;
+      }
+      xf86LoaderReqSymLists(I830exaSymbols, NULL);
+   }
+#endif
    if (!pI830->SWCursor) {
       if (!xf86LoadSubModule(pScrn, "ramdac")) {
 	 PreInitCleanup(pScrn);
@@ -3622,16 +3686,25 @@ ResetState(ScrnInfoPtr pScrn, Bool flush
    /* Reset the fence registers to 0 */
    for (i = 0; i < 8; i++)
       OUTREG(FENCE + i * 4, 0);
-
    /* Flush the ring buffer (if enabled), then disable it. */
-   if (pI830->AccelInfoRec != NULL && flush) {
-      temp = INREG(LP_RING + RING_LEN);
-      if (temp & 1) {
-	 I830RefreshRing(pScrn);
-	 I830Sync(pScrn);
-	 DO_RING_IDLE();
-      }
-   }
+   /* God this is ugly */
+#define flush_ring() do { \
+      temp = INREG(LP_RING + RING_LEN); \
+      if (temp & 1) { \
+	 I830RefreshRing(pScrn); \
+	 I830Sync(pScrn); \
+	 DO_RING_IDLE(); \
+      } \
+   } while(0)
+#ifdef I830_USE_XAA
+   if (!pI830->useEXA && flush && pI830->AccelInfoRec)
+       flush_ring();
+#endif
+#ifdef I830_USE_XAA
+   if (pI830->useEXA && flush && pI830->EXADriverPtr)
+       flush_ring();
+#endif
+
    OUTREG(LP_RING + RING_LEN, 0);
    OUTREG(LP_RING + RING_HEAD, 0);
    OUTREG(LP_RING + RING_TAIL, 0);
@@ -5309,8 +5382,14 @@ I830BIOSLeaveVT(int scrnIndex, int flags
    RestoreBIOSMemSize(pScrn);
    if (I830IsPrimary(pScrn))
       I830UnbindAGPMemory(pScrn);
-   if (pI830->AccelInfoRec)
+#ifdef I830_USE_XAA
+   if (!pI830->useEXA && pI830->AccelInfoRec)
       pI830->AccelInfoRec->NeedToSync = FALSE;
+#endif
+#ifdef I830_USE_EXA
+   if (pI830->useEXA && pI830->EXADriverPtr)
+       pI830->EXADriverPtr->card.needsSync = TRUE;
+#endif
 
    /* DO IT AGAIN! AS IT SEEMS THAT SOME LFPs FLICKER OTHERWISE */
    if (I830IsPrimary(pScrn)) {
@@ -5644,10 +5723,18 @@ I830BIOSSwitchMode(int scrnIndex, Displa
 #endif
 
    /* Sync the engine before mode switch */
-   if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
+#ifdef I830_USE_XAA
+   if (!pI830->noAccel && !pI830->useEXA)
       (*pI830->AccelInfoRec->Sync)(pScrn);
       pI830->AccelInfoRec->NeedToSync = FALSE;
    }
+#endif
+#ifdef I830_USE_EXA
+   if (!pI830->noAccel && pI830->useEXA) {
+      ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
+      (*pI830->EXADriverPtr->accel.WaitMarker)(pScreen, 0);
+   }
+#endif
 
    /* Check if our currentmode is about to change. We do this so if we
     * are rotating, we don't need to call the mode setup again.
@@ -5801,7 +5888,9 @@ I830BIOSCloseScreen(int scrnIndex, Scree
 {
    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
    I830Ptr pI830 = I830PTR(pScrn);
+#ifdef I830_USE_XAA
    XAAInfoRecPtr infoPtr = pI830->AccelInfoRec;
+#endif
 
    pI830->closing = TRUE;
 #ifdef XF86DRI
@@ -5827,14 +5916,21 @@ I830BIOSCloseScreen(int scrnIndex, Scree
       xfree(pI830->ScanlineColorExpandBuffers);
       pI830->ScanlineColorExpandBuffers = 0;
    }
-
+#ifdef I830_USE_XAA
    if (infoPtr) {
       if (infoPtr->ScanlineColorExpandBuffers)
 	 xfree(infoPtr->ScanlineColorExpandBuffers);
       XAADestroyInfoRec(infoPtr);
       pI830->AccelInfoRec = NULL;
    }
-
+#endif
+#ifdef I830_USE_EXA
+   if (pI830->useEXA && pI830->EXADriverPtr) {
+       exaDriverFini(pScreen);
+       xfree(pI830->EXADriverPtr);
+       pI830->EXADriverPtr = NULL;
+   }
+#endif
    if (pI830->CursorInfoRec) {
       xf86DestroyCursorInfoRec(pI830->CursorInfoRec);
       pI830->CursorInfoRec = 0;
diff --git a/src/i830_exa.c b/src/i830_exa.c
new file mode 100644
index 0000000..a6aa6a7
--- /dev/null
+++ b/src/i830_exa.c
@@ -0,0 +1,418 @@
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+All Rights Reserved.
+Copyright (c) 2005 Jesse Barnes <jbarnes at virtuousgeek.org>
+  Based on code from i830_xaa.c.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86_ansic.h"
+#include "xf86.h"
+#include "xaarop.h"
+#include "i830.h"
+#include "i810_reg.h"
+
+int I830CopyROP[16] =
+{
+   ROP_0,               /* GXclear */
+   ROP_DSa,             /* GXand */
+   ROP_SDna,            /* GXandReverse */
+   ROP_S,               /* GXcopy */
+   ROP_DSna,            /* GXandInverted */
+   ROP_D,               /* GXnoop */
+   ROP_DSx,             /* GXxor */
+   ROP_DSo,             /* GXor */
+   ROP_DSon,            /* GXnor */
+   ROP_DSxn,            /* GXequiv */
+   ROP_Dn,              /* GXinvert*/
+   ROP_SDno,            /* GXorReverse */
+   ROP_Sn,              /* GXcopyInverted */
+   ROP_DSno,            /* GXorInverted */
+   ROP_DSan,            /* GXnand */
+   ROP_1                /* GXset */
+};
+
+static int I830PatternROP[16] =
+{
+    ROP_0,
+    ROP_DPa,
+    ROP_PDna,
+    ROP_P,
+    ROP_DPna,
+    ROP_D,
+    ROP_DPx,
+    ROP_DPo,
+    ROP_DPon,
+    ROP_PDxn,
+    ROP_Dn,
+    ROP_PDno,
+    ROP_Pn,
+    ROP_DPno,
+    ROP_DPan,
+    ROP_1
+};
+
+void i830ScratchSave(ScreenPtr pScreen, ExaOffscreenArea *area);
+Bool i830UploadToScreen(PixmapPtr pDst, char *src, int src_pitch);
+Bool i830UploadToScratch(PixmapPtr pSrc, PixmapPtr pDst);
+Bool i830DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h,
+			    char *dst, int dst_pitch);
+
+/**
+ * I830EXASync - wait for a command to finish
+ * @pScreen: current screen
+ * @marker: marker command to wait for
+ *
+ * Wait for the command specified by @marker to finish, then return.
+ */
+static void
+I830EXASync(ScreenPtr pScreen, int marker)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+
+#ifdef XF86DRI
+    /* VT switching tries to do this. */
+    if (!pI830->LockHeld && pI830->directRenderingEnabled)
+	return;
+#endif
+
+    if (pI830->entityPrivate && !pI830->entityPrivate->RingRunning)
+	return;
+
+    /* Send a flush instruction and then wait till the ring is empty.
+     * This is stronger than waiting for the blitter to finish as it also
+     * flushes the internal graphics caches.
+     */
+    {
+	BEGIN_LP_RING(2);
+	OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
+	OUT_RING(MI_NOOP);		/* pad to quadword */
+	ADVANCE_LP_RING();
+    }
+
+    I830WaitLpRing(pScrn, pI830->LpRing->mem.Size - 8, 0);
+
+    pI830->LpRing->space = pI830->LpRing->mem.Size - 8;
+    pI830->nextColorExpandBuf = 0;
+}
+
+/**
+ * I830EXAPrepareSolid - prepare for a Solid operation, if possible
+ *
+ * TODO:
+ *   - support planemask using FILL_MONO_SRC_BLT_CMD?
+ */
+static Bool
+I830EXAPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    if (planemask != (Pixel)~0)
+	return FALSE;
+
+    pI830->BR[13] = exaGetPixmapPitch(pPixmap);
+    pI830->BR[13] |= I830PatternROP[alu] << 16;
+
+    pI830->BR[16] = fg;
+
+    /*
+     * Depth: 00 - 8 bit, 01 - 16 bit, 10 - 24 bit, 11 - 32 bit
+     */
+    switch (pScrn->bitsPerPixel) {
+    case 8:
+	pI830->BR[13] |= ((0 << 25) | (0 << 24));
+	break;
+    case 16:
+	pI830->BR[13] |= ((0 << 25) | (1 << 24));
+	break;
+    case 32:
+	pI830->BR[13] |= ((1 << 25) | (1 << 24));
+	break;
+    }
+    return TRUE;
+}
+
+static void
+I830EXASolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+    int h, w;
+    unsigned int offset;
+
+    offset = exaGetPixmapOffset(pPixmap) + y1 * exaGetPixmapPitch(pPixmap) +
+	x1 * (pPixmap->drawable.bitsPerPixel / 8);
+    
+    h = y2 - y1;
+    w = x2 - x1;
+
+    {
+	BEGIN_LP_RING(6);
+
+	if (pScrn->bitsPerPixel == 32)
+	    OUT_RING(COLOR_BLT_CMD | COLOR_BLT_WRITE_ALPHA |
+		     COLOR_BLT_WRITE_RGB);
+	else
+	    OUT_RING(COLOR_BLT_CMD);
+
+	OUT_RING(pI830->BR[13]);
+	OUT_RING((h << 16) | (w * (pPixmap->drawable.bitsPerPixel/8)));
+	OUT_RING(offset);
+	OUT_RING(pI830->BR[16]);
+	OUT_RING(0);
+
+	ADVANCE_LP_RING();
+    }
+}
+
+static void
+I830EXADoneSolid(PixmapPtr pPixmap)
+{
+    return;
+}
+
+/**
+ * TODO:
+ *   - support planemask using FULL_BLT_CMD?
+ */
+static Bool
+I830EXAPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
+		   int ydir, int alu, Pixel planemask)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    if (planemask != (Pixel)~0)
+	return FALSE;
+
+    pI830->copy_src_pitch = exaGetPixmapPitch(pSrcPixmap);
+    pI830->copy_src_off = exaGetPixmapOffset(pSrcPixmap);
+
+    pI830->BR[13] = exaGetPixmapPitch(pDstPixmap);
+    pI830->BR[13] |= I830CopyROP[alu] << 16;
+
+    switch (pScrn->bitsPerPixel) {
+    case 8:
+	break;
+    case 16:
+	pI830->BR[13] |= (1 << 24);
+	break;
+    case 32:
+	pI830->BR[13] |= ((1 << 25) | (1 << 24));
+	break;
+    }
+    return TRUE;
+}
+
+static void
+I830EXACopy(PixmapPtr pDstPixmap, int src_x1, int src_y1, int dst_x1,
+	    int dst_y1, int w, int h)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+    int dst_x2, dst_y2;
+    unsigned int src_off, dst_off;
+
+    dst_x2 = dst_x1 + w;
+    dst_y2 = dst_y1 + h;
+
+    src_off = pI830->copy_src_off;
+    dst_off = exaGetPixmapOffset(pDstPixmap);
+
+    {
+	BEGIN_LP_RING(8);
+
+	if (pScrn->bitsPerPixel == 32)
+	    OUT_RING(XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
+		     XY_SRC_COPY_BLT_WRITE_RGB);
+	else
+	    OUT_RING(XY_SRC_COPY_BLT_CMD);
+
+	OUT_RING(pI830->BR[13]);
+	OUT_RING((dst_y1 << 16) | (dst_x1 & 0xffff));
+	OUT_RING((dst_y2 << 16) | (dst_x2 & 0xffff));
+	OUT_RING(dst_off);
+	OUT_RING((src_y1 << 16) | (src_x1 & 0xffff));
+	OUT_RING(pI830->copy_src_pitch);
+	OUT_RING(src_off);
+
+	ADVANCE_LP_RING();
+    }
+}
+
+static void
+I830EXADoneCopy(PixmapPtr pDstPixmap)
+{
+    return;
+}
+
+#if 0 /* Not done (or even started for that matter) */
+static Bool
+I830EXAUploadToScreen(PixmapPtr pDst, char *src, int src_pitch)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+    unsigned char *dst = pDst->devPrivate.ptr;
+    int dst_pitch = exaGetPixmapPitch(pDst);
+    int size = src_pitch < dst_pitch ? src_pitch : dst_pitch;
+    int h = pDst->drawable.height;
+
+    I830Sync(pScrn);
+
+    while(h--) {
+	i830MemCopyToVideoRam(pI830, dst, (unsigned char *)src, size);
+	src += src_pitch;
+	dst += dst_pitch;
+    }
+
+    return TRUE;
+}
+
+static Bool
+I830EXADownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h,
+			  char *dst, int dst_pitch)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+    unsigned char *src = pSrc->devPrivate.ptr;
+    int src_pitch = exaGetPixmapPitch(pSrc);
+    int size = src_pitch < dst_pitch ? src_pitch : dst_pitch;
+
+    I830Sync(pScrn);
+
+    while(h--) {
+	i830MemCopyFromVideoRam(pI830, (unsigned char *)dst, src, size);
+	src += src_pitch;
+	dst += dst_pitch;
+    }
+
+    return TRUE;
+}
+
+static Bool
+I830EXACheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+		      PicturePtr pDstPicture)
+{
+    return FALSE; /* no Composite yet */
+}
+
+static Bool
+I830EXAPrepareComposite(int op, PicturePtr pSrcPicture,
+			PicturePtr pMaskPicture, PicturePtr pDstPicture,
+			PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
+{
+    return FALSE; /* no Composite yet */
+}
+
+static void
+I830EXAComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
+		 int dstX, int dstY, int width, int height)
+{
+    return; /* no Composite yet */
+}
+
+static void
+I830EXADoneComposite(PixmapPtr pDst)
+{
+    return; /* no Composite yet */
+}
+#endif
+
+/*
+ * TODO:
+ *   - Dual head?
+ *   - Upload/Download
+ *   - Composite
+ */
+Bool
+I830EXAInit(ScreenPtr pScreen)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    if(pI830->useEXA) {
+	if(!(pI830->EXADriverPtr = xnfcalloc(sizeof(ExaDriverRec), 1))) {
+	    pI830->noAccel = TRUE;
+	    return FALSE;
+	}
+    }
+
+    pI830->bufferOffset = 0;
+    pI830->EXADriverPtr->card.memoryBase = pI830->FbBase;
+    pI830->EXADriverPtr->card.offScreenBase = pI830->Offscreen.Start;
+    pI830->EXADriverPtr->card.memorySize = pI830->Offscreen.Size;
+	   
+    if(pI830->EXADriverPtr->card.memorySize >
+       pI830->EXADriverPtr->card.offScreenBase)
+	pI830->EXADriverPtr->card.flags = EXA_OFFSCREEN_PIXMAPS;
+    else {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Not enough video RAM for "
+		   "offscreen memory manager. Xv disabled\n");
+	/* disable Xv here... */
+    }
+
+    pI830->EXADriverPtr->card.pixmapOffsetAlign = 256;
+    pI830->EXADriverPtr->card.pixmapPitchAlign = 64;
+    pI830->EXADriverPtr->card.maxX = 4095;
+    pI830->EXADriverPtr->card.maxY = 4095;
+
+    /* Sync */
+    pI830->EXADriverPtr->accel.WaitMarker = I830EXASync;
+
+    /* Solid fill */
+    pI830->EXADriverPtr->accel.PrepareSolid = I830EXAPrepareSolid;
+    pI830->EXADriverPtr->accel.Solid = I830EXASolid;
+    pI830->EXADriverPtr->accel.DoneSolid = I830EXADoneSolid;
+
+    /* Copy */
+    pI830->EXADriverPtr->accel.PrepareCopy = I830EXAPrepareCopy;
+    pI830->EXADriverPtr->accel.Copy = I830EXACopy;
+    pI830->EXADriverPtr->accel.DoneCopy = I830EXADoneCopy;
+#if 0
+    /* Upload, download to/from Screen */
+    pI830->EXADriverPtr->accel.UploadToScreen = I830EXAUploadToScreen;
+    pI830->EXADriverPtr->accel.DownloadFromScreen = I830EXADownloadFromScreen;
+
+    /* Composite */
+    pI830->EXADriverPtr->accel.CheckComposite = I830EXACheckComposite;
+    pI830->EXADriverPtr->accel.PrepareComposite = I830EXAPrepareComposite;
+    pI830->EXADriverPtr->accel.Composite = I830EXAComposite;
+    pI830->EXADriverPtr->accel.DoneComposite = I830EXADoneComposite;
+#endif
+
+    if(!exaDriverInit(pScreen, pI830->EXADriverPtr)) {
+	pI830->noAccel = TRUE;
+	return FALSE;
+    }
+
+    I830SelectBuffer(pScrn, I830_SELECT_FRONT);
+
+    return TRUE;
+}
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 433aa47..5fbc8cf 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -850,6 +850,30 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
 	 }
 	 return FALSE;
       }
+#ifdef I830_USE_EXA
+      size = lineSize * pScrn->virtualY;
+      size = ROUND_TO_PAGE(size);
+
+      if (tileable) {
+	 align = KB(512);
+	 alignflags = ALIGN_BOTH_ENDS;
+      } else {
+	 align = KB(64);
+	 alignflags = 0;
+      }
+
+      alloced = I830AllocVidMem(pScrn, &(pI830->Offscreen),
+				&(pI830->StolenPool), size, align,
+				flags | alignflags |
+				FROM_ANYWHERE | ALLOCATE_AT_BOTTOM);
+      if (alloced < size) {
+	 if (!dryrun) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate "
+		       "offscreen memory.  Not enough VRAM?\n");
+	 }
+	 return FALSE;
+      }
+#endif
    } else {
       long lineSize;
       long extra = 0;
diff --git a/src/i830_video.c b/src/i830_video.c
index 0ae6860..e6f6341 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -1830,8 +1830,6 @@ I830AllocateMemory(ScrnInfoPtr pScrn, FB
    ScreenPtr pScreen;
    FBLinearPtr new_linear = NULL;
 
-   DPRINTF(PFX, "I830AllocateMemory\n");
-
    if (linear) {
       if (linear->size >= size)
 	 return linear;
diff --git a/src/i830_xaa.c b/src/i830_xaa.c
new file mode 100644
index 0000000..68ba4c7
--- /dev/null
+++ b/src/i830_xaa.c
@@ -0,0 +1,636 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86_ansic.h"
+#include "xf86.h"
+#include "xaarop.h"
+#include "i830.h"
+#include "i810_reg.h"
+
+#ifndef DO_SCANLINE_IMAGE_WRITE
+#define DO_SCANLINE_IMAGE_WRITE 0
+#endif
+
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Reformatted with GNU indent (2.2.8), using the following options:
+ *
+ *    -bad -bap -c41 -cd0 -ncdb -ci6 -cli0 -cp0 -ncs -d0 -di3 -i3 -ip3 -l78
+ *    -lp -npcs -psl -sob -ss -br -ce -sc -hnl
+ *
+ * This provides a good match with the original i810 code and preferred
+ * XFree86 formatting conventions.
+ *
+ * When editing this driver, please follow the existing formatting, and edit
+ * with <TAB> characters expanded at 8-column intervals.
+ */
+
+/*
+ * Authors:
+ *   Keith Whitwell <keith at tungstengraphics.com>
+ *
+ */
+
+/* I830 Accel Functions */
+static void I830SetupForMono8x8PatternFill(ScrnInfoPtr pScrn,
+					   int pattx, int patty,
+					   int fg, int bg, int rop,
+					   unsigned int planemask);
+static void I830SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn,
+						 int pattx, int patty,
+						 int x, int y, int w, int h);
+
+static void I830SetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
+							   int fg, int bg,
+							   int rop,
+							   unsigned int mask);
+
+static void I830SubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr
+							     pScrn, int x,
+							     int y, int w,
+							     int h,
+							     int skipleft);
+
+static void I830SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno);
+
+#if DO_SCANLINE_IMAGE_WRITE
+static void I830SetupForScanlineImageWrite(ScrnInfoPtr pScrn, int rop,
+					   unsigned int planemask,
+					   int trans_color, int bpp,
+					   int depth);
+static void I830SubsequentScanlineImageWriteRect(ScrnInfoPtr pScrn,
+						 int x, int y, int w, int h,
+						 int skipleft);
+static void I830SubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno);
+#endif
+static void I830RestoreAccelState(ScrnInfoPtr pScrn);
+
+Bool
+I830XAAInit(ScreenPtr pScreen)
+{
+    XAAInfoRecPtr infoPtr;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+    int i;
+    int width = 0;
+    int nr_buffers = 0;
+    unsigned char *ptr = NULL;
+
+    if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+	ErrorF("I830XAAInit\n");
+
+    pI830->AccelInfoRec = infoPtr = XAACreateInfoRec();
+    if (!infoPtr)
+	return FALSE;
+
+    pI830->bufferOffset = 0;
+    infoPtr->Flags = LINEAR_FRAMEBUFFER | OFFSCREEN_PIXMAPS | PIXMAP_CACHE;
+
+    /* Use the same sync function as the I830.
+     */
+    infoPtr->Sync = I830Sync;
+
+    /* Everything else is different enough to justify different functions */
+    {
+	infoPtr->SolidFillFlags = NO_PLANEMASK;
+	infoPtr->SetupForSolidFill = I830SetupForSolidFill;
+	infoPtr->SubsequentSolidFillRect = I830SubsequentSolidFillRect;
+    }
+
+    {
+	infoPtr->ScreenToScreenCopyFlags = (NO_PLANEMASK | NO_TRANSPARENCY);
+
+	infoPtr->SetupForScreenToScreenCopy = I830SetupForScreenToScreenCopy;
+	infoPtr->SubsequentScreenToScreenCopy =
+	    I830SubsequentScreenToScreenCopy;
+    }
+
+    {
+	infoPtr->SetupForMono8x8PatternFill = I830SetupForMono8x8PatternFill;
+	infoPtr->SubsequentMono8x8PatternFillRect =
+	    I830SubsequentMono8x8PatternFillRect;
+
+	infoPtr->Mono8x8PatternFillFlags = (HARDWARE_PATTERN_PROGRAMMED_BITS |
+					    HARDWARE_PATTERN_SCREEN_ORIGIN |
+					    HARDWARE_PATTERN_PROGRAMMED_ORIGIN|
+					    BIT_ORDER_IN_BYTE_MSBFIRST |
+					    NO_PLANEMASK);
+
+    }
+
+    /* On the primary screen */
+    if (pI830->init == 0) {
+	if (pI830->Scratch.Size != 0) {
+	    width = ((pScrn->displayWidth + 31) & ~31) / 8;
+	    nr_buffers = pI830->Scratch.Size / width;
+	    ptr = pI830->FbBase + pI830->Scratch.Start;
+	}
+    } else {
+	/* On the secondary screen */
+	I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
+	if (pI8301->Scratch2.Size != 0) {
+	    width = ((pScrn->displayWidth + 31) & ~31) / 8;
+	    nr_buffers = pI8301->Scratch2.Size / width;
+	    /* We have to use the primary screen's FbBase, as that's where
+	     * we allocated Scratch2, so we get the correct pointer */
+	    ptr = pI8301->FbBase + pI8301->Scratch2.Start;
+	}
+    }
+
+    if (nr_buffers) {
+	pI830->NumScanlineColorExpandBuffers = nr_buffers;
+	pI830->ScanlineColorExpandBuffers = (unsigned char **)
+	    xnfcalloc(nr_buffers, sizeof(unsigned char *));
+
+	for (i = 0; i < nr_buffers; i++, ptr += width)
+	    pI830->ScanlineColorExpandBuffers[i] = ptr;
+
+	infoPtr->ScanlineCPUToScreenColorExpandFillFlags =
+	    (NO_PLANEMASK | ROP_NEEDS_SOURCE | BIT_ORDER_IN_BYTE_MSBFIRST);
+
+	infoPtr->ScanlineColorExpandBuffers = (unsigned char **)
+	    xnfcalloc(1, sizeof(unsigned char *));
+	infoPtr->NumScanlineColorExpandBuffers = 1;
+
+	infoPtr->ScanlineColorExpandBuffers[0] =
+	    pI830->ScanlineColorExpandBuffers[0];
+	pI830->nextColorExpandBuf = 0;
+
+	infoPtr->SetupForScanlineCPUToScreenColorExpandFill =
+	    I830SetupForScanlineCPUToScreenColorExpandFill;
+
+	infoPtr->SubsequentScanlineCPUToScreenColorExpandFill =
+	    I830SubsequentScanlineCPUToScreenColorExpandFill;
+
+	infoPtr->SubsequentColorExpandScanline =
+	    I830SubsequentColorExpandScanline;
+
+#if DO_SCANLINE_IMAGE_WRITE
+	infoPtr->NumScanlineImageWriteBuffers = 1;
+	infoPtr->ScanlineImageWriteBuffers =
+	    infoPtr->ScanlineColorExpandBuffers;
+	infoPtr->SetupForScanlineImageWrite = I830SetupForScanlineImageWrite;
+	infoPtr->SubsequentScanlineImageWriteRect =
+	    I830SubsequentScanlineImageWriteRect;
+	infoPtr->SubsequentImageWriteScanline =
+	    I830SubsequentImageWriteScanline;
+	infoPtr->ScanlineImageWriteFlags = NO_GXCOPY |
+	    NO_PLANEMASK |
+	    ROP_NEEDS_SOURCE |
+	    SCANLINE_PAD_DWORD;
+#endif
+    }
+
+    {
+	Bool shared_accel = FALSE;
+	int i;
+
+	for(i = 0; i < pScrn->numEntities; i++) {
+	    if(xf86IsEntityShared(pScrn->entityList[i]))
+		shared_accel = TRUE;
+	}
+	if(shared_accel == TRUE)
+	    infoPtr->RestoreAccelState = I830RestoreAccelState;
+    }
+
+    I830SelectBuffer(pScrn, I830_SELECT_FRONT);
+
+    return XAAInit(pScreen, infoPtr);
+}
+
+void
+I830SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
+		      unsigned int planemask)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+	ErrorF("I830SetupForFillRectSolid color: %x rop: %x mask: %x\n",
+	       color, rop, planemask);
+
+    pI830->BR[13] = ((XAAGetPatternROP(rop) << 16) |
+		     (pScrn->displayWidth * pI830->cpp));
+
+    pI830->BR[16] = color;
+
+    switch (pScrn->bitsPerPixel) {
+    case 8:
+	break;
+    case 16:
+	pI830->BR[13] |= (1 << 24);
+	break;
+    case 32:
+	pI830->BR[13] |= ((1 << 25) | (1 << 24));
+	break;
+    }
+}
+
+void
+I830SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+	ErrorF("I830SubsequentFillRectSolid %d,%d %dx%d\n", x, y, w, h);
+
+    {
+	BEGIN_LP_RING(6);
+
+	if (pScrn->bitsPerPixel == 32) {
+	    OUT_RING(COLOR_BLT_CMD | COLOR_BLT_WRITE_ALPHA |
+		     COLOR_BLT_WRITE_RGB);
+	} else {
+	    OUT_RING(COLOR_BLT_CMD);
+	}
+	OUT_RING(pI830->BR[13]);
+	OUT_RING((h << 16) | (w * pI830->cpp));
+	OUT_RING(pI830->bufferOffset + (y * pScrn->displayWidth + x) *
+		 pI830->cpp);
+	OUT_RING(pI830->BR[16]);
+	OUT_RING(0);
+
+	ADVANCE_LP_RING();
+    }
+}
+
+void
+I830SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop,
+			       unsigned int planemask, int transparency_color)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+	ErrorF("I830SetupForScreenToScreenCopy %d %d %x %x %d\n",
+	       xdir, ydir, rop, planemask, transparency_color);
+
+    pI830->BR[13] = (pScrn->displayWidth * pI830->cpp);
+    pI830->BR[13] |= XAAGetCopyROP(rop) << 16;
+
+    switch (pScrn->bitsPerPixel) {
+    case 8:
+	break;
+    case 16:
+	pI830->BR[13] |= (1 << 24);
+	break;
+    case 32:
+	pI830->BR[13] |= ((1 << 25) | (1 << 24));
+	break;
+    }
+
+}
+
+void
+I830SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int src_x1, int src_y1,
+				 int dst_x1, int dst_y1, int w, int h)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    int dst_x2, dst_y2;
+
+    if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+	ErrorF("I830SubsequentScreenToScreenCopy %d,%d - %d,%d %dx%d\n",
+	       src_x1, src_y1, dst_x1, dst_y1, w, h);
+
+    dst_x2 = dst_x1 + w;
+    dst_y2 = dst_y1 + h;
+
+    {
+	BEGIN_LP_RING(8);
+
+	if (pScrn->bitsPerPixel == 32) {
+	    OUT_RING(XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
+		     XY_SRC_COPY_BLT_WRITE_RGB);
+	} else {
+	    OUT_RING(XY_SRC_COPY_BLT_CMD);
+	}
+	OUT_RING(pI830->BR[13]);
+	OUT_RING((dst_y1 << 16) | (dst_x1 & 0xffff));
+	OUT_RING((dst_y2 << 16) | (dst_x2 & 0xffff));
+	OUT_RING(pI830->bufferOffset);
+	OUT_RING((src_y1 << 16) | (src_x1 & 0xffff));
+	OUT_RING(pI830->BR[13] & 0xFFFF);
+	OUT_RING(pI830->bufferOffset);
+
+	ADVANCE_LP_RING();
+    }
+}
+
+static void
+I830SetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int pattx, int patty,
+			       int fg, int bg, int rop,
+			       unsigned int planemask)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+	ErrorF("I830SetupForMono8x8PatternFill\n");
+
+    pI830->BR[16] = pattx;
+    pI830->BR[17] = patty;
+    pI830->BR[18] = bg;
+    pI830->BR[19] = fg;
+
+    pI830->BR[13] = (pScrn->displayWidth * pI830->cpp);	/* In bytes */
+    pI830->BR[13] |= XAAGetPatternROP(rop) << 16;
+    if (bg == -1)
+	pI830->BR[13] |= (1 << 28);
+
+    switch (pScrn->bitsPerPixel) {
+    case 8:
+	break;
+    case 16:
+	pI830->BR[13] |= (1 << 24);
+	break;
+    case 32:
+	pI830->BR[13] |= ((1 << 25) | (1 << 24));
+	break;
+    }
+
+}
+
+static void
+I830SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int pattx, int patty,
+				     int x, int y, int w, int h)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    int x1, x2, y1, y2;
+
+    x1 = x;
+    x2 = x + w;
+    y1 = y;
+    y2 = y + h;
+
+    if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+	ErrorF("I830SubsequentMono8x8PatternFillRect\n");
+
+    {
+	BEGIN_LP_RING(10);
+
+	if (pScrn->bitsPerPixel == 32) {
+	    OUT_RING(XY_MONO_PAT_BLT_CMD | XY_MONO_PAT_BLT_WRITE_ALPHA |
+		     XY_MONO_PAT_BLT_WRITE_RGB |
+		     ((patty << 8) & XY_MONO_PAT_VERT_SEED) |
+		     ((pattx << 12) & XY_MONO_PAT_HORT_SEED));
+	} else {
+	    OUT_RING(XY_MONO_PAT_BLT_CMD |
+		     ((patty << 8) & XY_MONO_PAT_VERT_SEED) |
+		     ((pattx << 12) & XY_MONO_PAT_HORT_SEED));
+	}
+	OUT_RING(pI830->BR[13]);
+	OUT_RING((y1 << 16) | x1);
+	OUT_RING((y2 << 16) | x2);
+	OUT_RING(pI830->bufferOffset);
+	OUT_RING(pI830->BR[18]);		/* bg */
+	OUT_RING(pI830->BR[19]);		/* fg */
+	OUT_RING(pI830->BR[16]);		/* pattern data */
+	OUT_RING(pI830->BR[17]);
+	OUT_RING(0);
+	ADVANCE_LP_RING();
+    }
+}
+
+static void
+I830GetNextScanlineColorExpandBuffer(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    XAAInfoRecPtr infoPtr = pI830->AccelInfoRec;
+
+    if (pI830->nextColorExpandBuf == pI830->NumScanlineColorExpandBuffers)
+	I830Sync(pScrn);
+
+    infoPtr->ScanlineColorExpandBuffers[0] =
+	pI830->ScanlineColorExpandBuffers[pI830->nextColorExpandBuf];
+
+    if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+	ErrorF("using color expand buffer %d\n", pI830->nextColorExpandBuf);
+
+    pI830->nextColorExpandBuf++;
+}
+
+static void
+I830SetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
+					       int fg, int bg, int rop,
+					       unsigned int planemask)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+	ErrorF("I830SetupForScanlineScreenToScreenColorExpand %d %d %x %x\n",
+	       fg, bg, rop, planemask);
+
+    /* Fill out register values */
+    pI830->BR[13] = (pScrn->displayWidth * pI830->cpp);
+    pI830->BR[13] |= XAAGetCopyROP(rop) << 16;
+    if (bg == -1)
+	pI830->BR[13] |= (1 << 29);
+
+    switch (pScrn->bitsPerPixel) {
+    case 8:
+	break;
+    case 16:
+	pI830->BR[13] |= (1 << 24);
+	break;
+    case 32:
+	pI830->BR[13] |= ((1 << 25) | (1 << 24));
+	break;
+    }
+
+    pI830->BR[18] = bg;
+    pI830->BR[19] = fg;
+
+    I830GetNextScanlineColorExpandBuffer(pScrn);
+}
+
+static void
+I830SubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
+						 int x, int y,
+						 int w, int h, int skipleft)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+	ErrorF("I830SubsequentScanlineCPUToScreenColorExpandFill "
+	       "%d,%d %dx%x %d\n", x, y, w, h, skipleft);
+
+    /* Fill out register values */
+    pI830->BR[9] = (pI830->bufferOffset +
+		    (y * pScrn->displayWidth + x) * pI830->cpp);
+    pI830->BR[11] = ((1 << 16) | w);
+}
+
+static void
+I830SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    if (pI830->init == 0) {
+	pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] -
+			 pI830->FbBase);
+    } else {
+	I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
+
+	/* We have to use the primary screen's FbBase, as that's where
+	 * we allocated Scratch2, so we get the correct pointer */
+	pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] -
+			 pI8301->FbBase);
+    }
+
+    if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+	ErrorF("I830SubsequentColorExpandScanline %d (addr %x)\n",
+	       bufno, pI830->BR[12]);
+
+    {
+	BEGIN_LP_RING(8);
+
+	if (pScrn->bitsPerPixel == 32) {
+	    OUT_RING(XY_MONO_SRC_BLT_CMD | XY_MONO_SRC_BLT_WRITE_ALPHA |
+		     XY_MONO_SRC_BLT_WRITE_RGB);
+	} else {
+	    OUT_RING(XY_MONO_SRC_BLT_CMD);
+	}
+	OUT_RING(pI830->BR[13]);
+	OUT_RING(0);			/* x1 = 0, y1 = 0 */
+	OUT_RING(pI830->BR[11]);		/* x2 = w, y2 = 1 */
+	OUT_RING(pI830->BR[9]);		/* dst addr */
+	OUT_RING(pI830->BR[12]);		/* src addr */
+	OUT_RING(pI830->BR[18]);		/* bg */
+	OUT_RING(pI830->BR[19]);		/* fg */
+
+	ADVANCE_LP_RING();
+    }
+
+    /* Advance to next scanline.
+     */
+    pI830->BR[9] += pScrn->displayWidth * pI830->cpp;
+    I830GetNextScanlineColorExpandBuffer(pScrn);
+}
+
+#if DO_SCANLINE_IMAGE_WRITE
+static void
+I830SetupForScanlineImageWrite(ScrnInfoPtr pScrn, int rop,
+			       unsigned int planemask, int trans_color,
+			       int bpp, int depth)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+	ErrorF("I830SetupForScanlineImageWrite %x %x\n", rop, planemask);
+
+    /* Fill out register values */
+    pI830->BR[13] = (pScrn->displayWidth * pI830->cpp);
+    pI830->BR[13] |= XAAGetCopyROP(rop) << 16;
+
+    switch (pScrn->bitsPerPixel) {
+    case 8:
+	break;
+    case 16:
+	pI830->BR[13] |= (1 << 24);
+	break;
+    case 32:
+	pI830->BR[13] |= ((1 << 25) | (1 << 24));
+	break;
+    }
+
+    I830GetNextScanlineColorExpandBuffer(pScrn);
+}
+
+static void
+I830SubsequentScanlineImageWriteRect(ScrnInfoPtr pScrn, int x, int y,
+				     int w, int h, int skipleft)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+	ErrorF("I830SubsequentScanlineImageWriteRect "
+	       "%d,%d %dx%x %d\n", x, y, w, h, skipleft);
+
+    /* Fill out register values */
+    pI830->BR[9] = (pI830->bufferOffset +
+		    (y * pScrn->displayWidth + x) * pI830->cpp);
+    pI830->BR[11] = ((1 << 16) | w);
+}
+
+static void
+I830SubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    if (pI830->init == 0) {
+	pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] -
+			 pI830->FbBase);
+    } else {
+	I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
+
+	/* We have to use the primary screen's FbBase, as that's where
+	 * we allocated Scratch2, so we get the correct pointer */
+	pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] -
+			 pI8301->FbBase);
+    }
+
+    if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+	ErrorF("I830SubsequentImageWriteScanline %d (addr %x)\n",
+	       bufno, pI830->BR[12]);
+
+    {
+	BEGIN_LP_RING(8);
+
+	if (pScrn->bitsPerPixel == 32) {
+	    OUT_RING(XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
+		     XY_SRC_COPY_BLT_WRITE_RGB);
+	} else {
+	    OUT_RING(XY_SRC_COPY_BLT_CMD);
+	}
+	OUT_RING(pI830->BR[13]);
+	OUT_RING(0);			/* x1 = 0, y1 = 0 */
+	OUT_RING(pI830->BR[11]);		/* x2 = w, y2 = 1 */
+	OUT_RING(pI830->BR[9]);		/* dst addr */
+	OUT_RING(0);			/* source origin (0,0) */
+	OUT_RING(pI830->BR[11] & 0xffff);	/* source pitch */
+	OUT_RING(pI830->BR[12]);		/* src addr */
+
+	ADVANCE_LP_RING();
+    }
+
+    /* Advance to next scanline.
+     */
+    pI830->BR[9] += pScrn->displayWidth * pI830->cpp;
+    I830GetNextScanlineColorExpandBuffer(pScrn);
+}
+#endif /* DO_SCANLINE_IMAGE_WRITE */
+/* Support for multiscreen */
+
+static void
+I830RestoreAccelState(ScrnInfoPtr pScrn)
+{
+#if 0
+   /* might be needed, but everything is on a ring, so I don't think so */
+   I830Sync(pScrn);
+#endif
+}
+
diff-tree a555e28e5afc81969ef7b28482e654cc26b3a446 (from cc70e6b789a1901bbe4e3501b6b654542d3cdc20)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Apr 24 16:55:44 2006 -0700

    Correct some SDVO-related register definitions.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index dee39ce..53c65bb 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -757,11 +757,12 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define SDVO_INTERRUPT_ENABLE			(1 << 26)
 /* Programmed value is multiplier - 1, up to 5x.  alv, gdg only */
 #define SDVO_PORT_MULTIPLY_MASK			(7 << 23)
-#define SDVO_PHASE_SELECT_MASK			(15 << 23)
-#define SDVO_PHASE_SELECT_DEFAULT		(6 << 23)
+#define SDVO_PHASE_SELECT_MASK			(15 << 19)
+#define SDVO_PHASE_SELECT_DEFAULT		(6 << 19)
 #define SDVO_CLOCK_OUTPUT_INVERT		(1 << 18)
 #define SDVOC_GANG_MODE				(1 << 16)
 #define SDVO_BORDER_ENABLE			(1 << 7)
+#define SDVOB_PCIE_CONCURRENCY			(1 << 3)
 #define SDVO_DETECTED				(1 << 2)
 /* Bits to be preserved when writing */
 #define SDVO_PRESERVE_MASK			(1 << 17)
diff --git a/src/i830_sdvo_regs.h b/src/i830_sdvo_regs.h
index 9165c39..37cfcf2 100644
--- a/src/i830_sdvo_regs.h
+++ b/src/i830_sdvo_regs.h
@@ -122,7 +122,7 @@
 # define SDVO_DTD_HSYNC_OFF				SDVO_I2C_ARG_0
 # define SDVO_DTD_HSYNC_WIDTH				SDVO_I2C_ARG_1
 # define SDVO_DTD_VSYNC_OFF_WIDTH			SDVO_I2C_ARG_2
-# define SDVO_DTD_SYSNC_OFF_WIDTH_HIGH			SDVO_I2C_ARG_3
+# define SDVO_DTD_SYNC_OFF_WIDTH_HIGH			SDVO_I2C_ARG_3
 # define SDVO_DTD_DTD_FLAGS				SDVO_I2C_ARG_4
 # define SDVO_DTD_DTD_FLAG_INTERLACED				(1 << 7)
 # define SDVO_DTD_DTD_FLAG_STEREO_MASK				(3 << 5)
@@ -155,9 +155,9 @@
 
 #define SDVO_CMD_GET_CLOCK_RATE_MULT			0x20
 #define SDVO_CMD_SET_CLOCK_RATE_MULT			0x21
-# define SDVO_CLOCK_RATE_MULT_1X				0
-# define SDVO_CLOCK_RATE_MULT_2X				1
-# define SDVO_CLOCK_RATE_MULT_4X				3
+# define SDVO_CLOCK_RATE_MULT_1X				(1 << 0)
+# define SDVO_CLOCK_RATE_MULT_2X				(1 << 1)
+# define SDVO_CLOCK_RATE_MULT_4X				(1 << 3)
 
 #define SDVO_CMD_GET_SUPPORTED_TV_FORMATS		0x27
 
diff-tree cc70e6b789a1901bbe4e3501b6b654542d3cdc20 (from b498d2b1d1170123595ada65353428578b59a361)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Apr 24 16:49:48 2006 -0700

    Save/restore the output's SDVO reg.  Note that we might be programming the other
    SDVO reg instead of the one assigned to the output.  When trying to fix that, I
    ended up getting no output at all.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index e58b659..99cdc6a 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -438,7 +438,7 @@ I830SDVOGetClockRateMult(I830SDVOPtr s)
     I830SDVOWriteOutputs(s, 0);
     I830SDVOReadInputRegs(s);
 
-    if (s->sdvo_regs[SDVO_CMD_GET_CLOCK_RATE_MULT] != SDVO_CMD_STATUS_SUCCESS) {
+    if (s->sdvo_regs[SDVO_I2C_CMD_STATUS] != SDVO_CMD_STATUS_SUCCESS) {
 	xf86DrvMsg(s->d.pI2CBus->scrnIndex, X_ERROR,
 		   "Couldn't get SDVO clock rate multiplier\n");
 	return SDVO_CLOCK_RATE_MULT_1X;
@@ -592,6 +592,8 @@ i830SDVOSave(ScrnInfoPtr pScrn, int outp
     I830SDVOSetTargetOutput(sdvo, FALSE, TRUE);
     I830SDVOGetTimings(sdvo, &sdvo->save_output_dtd_2,
 		       SDVO_CMD_GET_OUTPUT_TIMINGS_PART1);
+
+    sdvo->save_SDVOX = INREG(sdvo->output_device);
 }
 
 void
@@ -624,6 +626,9 @@ i830SDVOPostRestore(ScrnInfoPtr pScrn, i
 		       SDVO_CMD_SET_OUTPUT_TIMINGS_PART1);
 
     I830SDVOSetClockRateMult(sdvo, sdvo->save_sdvo_mult);
+
+    OUTREG(sdvo->output_device, sdvo->save_SDVOX);
+
     I830SDVOSetActiveOutputs(sdvo, sdvo->save_sdvo_active_1,
 			     sdvo->save_sdvo_active_2);
 }
diff-tree b498d2b1d1170123595ada65353428578b59a361 (from 56c1f8b0de9b6acc50f51561caf14d3e6bac09ec)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Apr 24 15:42:46 2006 -0700

    Start trying to save/restore SDVO state on VT switches.

diff --git a/src/i830.h b/src/i830.h
index 3b81c92..d72b72b 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -69,6 +69,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #endif
 
 #include "common.h"
+#include "i830_sdvo.h"
 
 /* I830 Video BIOS support */
 
@@ -192,6 +193,12 @@ typedef struct _I830SDVODriver {
    I2CDevRec d;
    unsigned char sdvo_regs[20];
    CARD32 output_device;		/* SDVOB or SDVOC */
+
+   int save_sdvo_mult;
+   Bool save_sdvo_active_1, save_sdvo_active_2;
+   i830_sdvo_dtd save_input_dtd_1, save_input_dtd_2;
+   i830_sdvo_dtd save_output_dtd_1, save_output_dtd_2;
+   CARD32 save_SDVOX;
 } I830SDVORec, *I830SDVOPtr;
 
 struct _I830OutputRec {
@@ -493,7 +500,6 @@ typedef struct _I830Rec {
    CARD32 savePaletteA[256];
    CARD32 savePaletteB[256];
    CARD32 saveSWF[17];
-
 } I830Rec;
 
 #define I830PTR(p) ((I830Ptr)((p)->driverPrivate))
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 7c6de99..dcb1acf 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3276,9 +3276,11 @@ SaveHWState(ScrnInfoPtr pScrn)
    pI830->savePP_CONTROL = INREG(PP_CONTROL);
    pI830->savePP_CYCLE = INREG(PP_CYCLE);
 
-   pI830->saveDVOA = INREG(DVOA);
-   pI830->saveDVOB = INREG(DVOB);
-   pI830->saveDVOC = INREG(DVOC);
+   if (!IS_I9XX(pI830)) {
+      pI830->saveDVOA = INREG(DVOA);
+      pI830->saveDVOB = INREG(DVOB);
+      pI830->saveDVOC = INREG(DVOC);
+   }
 
    for(i = 0; i < 7; i++) {
       pI830->saveSWF[i] = INREG(SWF0 + (i << 2));
@@ -3287,7 +3289,15 @@ SaveHWState(ScrnInfoPtr pScrn)
    pI830->saveSWF[14] = INREG(SWF30);
    pI830->saveSWF[15] = INREG(SWF31);
    pI830->saveSWF[16] = INREG(SWF32);
-   
+
+   for (i = 0; i < pI830->num_outputs; i++) {
+      if (pI830->output[i].type == I830_OUTPUT_SDVO &&
+	  pI830->output[i].sdvo_drv != NULL)
+      {
+	 i830SDVOSave(pScrn, i);
+      }
+   }
+
    vgaHWUnlock(hwp);
    vgaHWSave(pScrn, vgaReg, VGA_SR_ALL);
 
@@ -3325,6 +3335,14 @@ RestoreHWState(ScrnInfoPtr pScrn)
 
    i830SetLVDSPanelPower(pScrn, FALSE);
 
+   for (i = 0; i < pI830->num_outputs; i++) {
+      if (pI830->output[i].type == I830_OUTPUT_SDVO &&
+	  pI830->output[i].sdvo_drv != NULL)
+      {
+	 i830SDVOPreRestore(pScrn, i);
+      }
+   }
+
    OUTREG(FPA0, pI830->saveFPA0);
    OUTREG(FPA1, pI830->saveFPA1);
    OUTREG(DPLL_A, pI830->saveDPLL_A);
@@ -3381,9 +3399,20 @@ RestoreHWState(ScrnInfoPtr pScrn)
 
    OUTREG(ADPA, pI830->saveADPA);
    OUTREG(LVDS, pI830->saveLVDS);
-   OUTREG(DVOA, pI830->saveDVOA);
-   OUTREG(DVOB, pI830->saveDVOB);
-   OUTREG(DVOC, pI830->saveDVOC);
+   if (!IS_I9XX(pI830)) {
+      OUTREG(DVOA, pI830->saveDVOA);
+      OUTREG(DVOB, pI830->saveDVOB);
+      OUTREG(DVOC, pI830->saveDVOC);
+   }
+
+   for (i = 0; i < pI830->num_outputs; i++) {
+      if (pI830->output[i].type == I830_OUTPUT_SDVO &&
+	  pI830->output[i].sdvo_drv != NULL)
+      {
+	 i830SDVOPostRestore(pScrn, i);
+      }
+   }
+
    OUTREG(PP_CONTROL, pI830->savePP_CONTROL);
 
    for(i = 0; i < 7; i++) {
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index e8898fc..e58b659 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -160,7 +160,7 @@ I830SDVOGetTrainedInputs(I830SDVOPtr s)
 }
 
 static Bool
-I830SDVOGetActiveOutputs(I830SDVOPtr s)
+I830SDVOGetActiveOutputs(I830SDVOPtr s, Bool *on_1, Bool *on_2)
 {
     memset(s->sdvo_regs, 0, 9);
 
@@ -169,6 +169,9 @@ I830SDVOGetActiveOutputs(I830SDVOPtr s)
     I830SDVOWriteOutputs(s, 0);
     I830SDVOReadInputRegs(s);
 
+    *on_1 = s->sdvo_regs[SDVO_I2C_ARG_0];
+    *on_2 = s->sdvo_regs[SDVO_I2C_ARG_1];
+
     return TRUE;
 }
 
@@ -221,39 +224,73 @@ I830SDVOSetTargetOutput(I830SDVOPtr s, B
     return TRUE;
 }
 
-#if 0
-static Bool
-I830SDVOGetOutputTimingsPart1(I830SDVOPtr s)
+/* Fetches either input or output timings to *dtd, depending on cmd. */
+Bool
+I830SDVOGetTimings(I830SDVOPtr s, i830_sdvo_dtd *dtd, CARD8 cmd)
 {
     memset(s->sdvo_regs, 0, 9);
+    s->sdvo_regs[SDVO_I2C_OPCODE] = cmd;
+    I830SDVOWriteOutputs(s, 0);
+    I830SDVOReadInputRegs(s);
 
-    s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_OUTPUT_TIMINGS_PART1;
-
-    /* XXX: No args */
-    s->sdvo_regs[0x07] = 0x0;
+    dtd->clock = s->sdvo_regs[SDVO_I2C_RETURN_0] |
+		 (s->sdvo_regs[SDVO_I2C_RETURN_1] << 8);
+    dtd->h_active = s->sdvo_regs[SDVO_I2C_RETURN_2];
+    dtd->h_blank = s->sdvo_regs[SDVO_I2C_RETURN_3];
+    dtd->h_high = s->sdvo_regs[SDVO_I2C_RETURN_4];
+    dtd->v_active = s->sdvo_regs[SDVO_I2C_RETURN_5];
+    dtd->v_blank = s->sdvo_regs[SDVO_I2C_RETURN_6];
+    dtd->v_high = s->sdvo_regs[SDVO_I2C_RETURN_7];
 
+    memset(s->sdvo_regs, 0, 9);
+    s->sdvo_regs[SDVO_I2C_OPCODE] = cmd + 1;
     I830SDVOWriteOutputs(s, 0);
     I830SDVOReadInputRegs(s);
-  
+
+    dtd->h_sync_off = s->sdvo_regs[SDVO_I2C_RETURN_0];
+    dtd->h_sync_width = s->sdvo_regs[SDVO_I2C_RETURN_1];
+    dtd->v_sync_off_width = s->sdvo_regs[SDVO_I2C_RETURN_2];
+    dtd->sync_off_width_high = s->sdvo_regs[SDVO_I2C_RETURN_3];
+    dtd->dtd_flags = s->sdvo_regs[SDVO_I2C_RETURN_4];
+    dtd->sdvo_flags = s->sdvo_regs[SDVO_I2C_RETURN_5];
+    dtd->v_sync_off_high = s->sdvo_regs[SDVO_I2C_RETURN_6];
+    dtd->reserved = s->sdvo_regs[SDVO_I2C_RETURN_7];
+
     return TRUE;
 }
 
-static Bool
-I830SDVOGetOutputTimingsPart2(I830SDVOPtr s)
+/* Fetches either input or output timings to *dtd, depending on cmd. */
+Bool
+I830SDVOSetTimings(I830SDVOPtr s, i830_sdvo_dtd *dtd, CARD8 cmd)
 {
     memset(s->sdvo_regs, 0, 9);
+    s->sdvo_regs[SDVO_I2C_OPCODE] = cmd;
+    s->sdvo_regs[SDVO_I2C_ARG_0] = dtd->clock & 0xff;
+    s->sdvo_regs[SDVO_I2C_ARG_1] = dtd->clock >> 8;
+    s->sdvo_regs[SDVO_I2C_ARG_2] = dtd->h_active;
+    s->sdvo_regs[SDVO_I2C_ARG_3] = dtd->h_blank;
+    s->sdvo_regs[SDVO_I2C_ARG_4] = dtd->h_high;
+    s->sdvo_regs[SDVO_I2C_ARG_5] = dtd->v_active;
+    s->sdvo_regs[SDVO_I2C_ARG_6] = dtd->v_blank;
+    s->sdvo_regs[SDVO_I2C_ARG_7] = dtd->v_high;
+    I830SDVOWriteOutputs(s, 8);
+    I830SDVOReadInputRegs(s);
 
-    s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_OUTPUT_TIMINGS_PART2;
-
-    /* XXX: No args */
-    s->sdvo_regs[0x07] = 0x0;
-
-    I830SDVOWriteOutputs(s, 0);
+    memset(s->sdvo_regs, 0, 9);
+    s->sdvo_regs[SDVO_I2C_OPCODE] = cmd + 1;
+    s->sdvo_regs[SDVO_I2C_ARG_0] = dtd->h_sync_off;
+    s->sdvo_regs[SDVO_I2C_ARG_1] = dtd->h_sync_width;
+    s->sdvo_regs[SDVO_I2C_ARG_2] = dtd->v_sync_off_width;
+    s->sdvo_regs[SDVO_I2C_ARG_3] = dtd->sync_off_width_high;
+    s->sdvo_regs[SDVO_I2C_ARG_4] = dtd->dtd_flags;
+    s->sdvo_regs[SDVO_I2C_ARG_5] = dtd->sdvo_flags;
+    s->sdvo_regs[SDVO_I2C_ARG_6] = dtd->v_sync_off_high;
+    s->sdvo_regs[SDVO_I2C_ARG_7] = dtd->reserved;
+    I830SDVOWriteOutputs(s, 8);
     I830SDVOReadInputRegs(s);
 
     return TRUE;
 }
-#endif
 
 static Bool
 I830SDVOSetTimingsPart1(I830SDVOPtr s, char cmd, CARD16 clock, CARD16 magic1,
@@ -391,6 +428,29 @@ I830SDVOGetPreferredInputTimingPart2(I83
     return TRUE;
 }
 
+static int
+I830SDVOGetClockRateMult(I830SDVOPtr s)
+{
+    memset(s->sdvo_regs, 0, 9);
+
+    s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_CLOCK_RATE_MULT;
+
+    I830SDVOWriteOutputs(s, 0);
+    I830SDVOReadInputRegs(s);
+
+    if (s->sdvo_regs[SDVO_CMD_GET_CLOCK_RATE_MULT] != SDVO_CMD_STATUS_SUCCESS) {
+	xf86DrvMsg(s->d.pI2CBus->scrnIndex, X_ERROR,
+		   "Couldn't get SDVO clock rate multiplier\n");
+	return SDVO_CLOCK_RATE_MULT_1X;
+    } else {
+	xf86DrvMsg(s->d.pI2CBus->scrnIndex, X_INFO,
+		   "Current clock rate multiplier: %d\n",
+		   s->sdvo_regs[SDVO_I2C_RETURN_0]);
+    }
+
+    return s->sdvo_regs[SDVO_I2C_RETURN_0];
+}
+
 static Bool
 I830SDVOSetClockRateMult(I830SDVOPtr s, CARD8 val)
 {
@@ -460,7 +520,6 @@ I830SDVOPreSetMode(I830SDVOPtr s, Displa
     I830SDVOGetInputPixelClockRange(s, &clock_min, &clock_max);
     ErrorF("clock min/max: %d %d\n", clock_min, clock_max);
 
-    I830SDVOGetActiveOutputs(s);
     I830SDVOSetActiveOutputs(s, FALSE, FALSE);
 
     I830SDVOSetTargetOutput(s, TRUE, TRUE);
@@ -505,12 +564,70 @@ I830SDVOPostSetMode(I830SDVOPtr s, Displ
 	ret = FALSE;
     }
 
-    I830SDVOGetActiveOutputs(s);
     I830SDVOSetActiveOutputs(s, TRUE, TRUE);
 
     return ret;
 }
 
+void
+i830SDVOSave(ScrnInfoPtr pScrn, int output_index)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830SDVOPtr sdvo = pI830->output[output_index].sdvo_drv;
+
+    sdvo->save_sdvo_mult = I830SDVOGetClockRateMult(sdvo);
+    I830SDVOGetActiveOutputs(sdvo, &sdvo->save_sdvo_active_1,
+			     &sdvo->save_sdvo_active_2);
+
+    I830SDVOSetTargetInput(sdvo, TRUE, FALSE);
+    I830SDVOGetTimings(sdvo, &sdvo->save_input_dtd_1,
+		       SDVO_CMD_GET_INPUT_TIMINGS_PART1);
+    I830SDVOSetTargetInput(sdvo, FALSE, TRUE);
+    I830SDVOGetTimings(sdvo, &sdvo->save_input_dtd_2,
+		       SDVO_CMD_GET_INPUT_TIMINGS_PART1);
+
+    I830SDVOSetTargetOutput(sdvo, TRUE, FALSE);
+    I830SDVOGetTimings(sdvo, &sdvo->save_output_dtd_1,
+		       SDVO_CMD_GET_OUTPUT_TIMINGS_PART1);
+    I830SDVOSetTargetOutput(sdvo, FALSE, TRUE);
+    I830SDVOGetTimings(sdvo, &sdvo->save_output_dtd_2,
+		       SDVO_CMD_GET_OUTPUT_TIMINGS_PART1);
+}
+
+void
+i830SDVOPreRestore(ScrnInfoPtr pScrn, int output_index)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830SDVOPtr sdvo = pI830->output[output_index].sdvo_drv;
+
+    I830SDVOSetActiveOutputs(sdvo, FALSE, FALSE);
+}
+
+void
+i830SDVOPostRestore(ScrnInfoPtr pScrn, int output_index)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830SDVOPtr sdvo = pI830->output[output_index].sdvo_drv;
+
+    I830SDVOSetTargetInput(sdvo, TRUE, FALSE);
+    I830SDVOSetTimings(sdvo, &sdvo->save_input_dtd_1,
+		       SDVO_CMD_SET_INPUT_TIMINGS_PART1);
+    I830SDVOSetTargetInput(sdvo, FALSE, TRUE);
+    I830SDVOSetTimings(sdvo, &sdvo->save_input_dtd_2,
+		       SDVO_CMD_SET_INPUT_TIMINGS_PART1);
+
+    I830SDVOSetTargetOutput(sdvo, TRUE, FALSE);
+    I830SDVOSetTimings(sdvo, &sdvo->save_output_dtd_1,
+		       SDVO_CMD_SET_OUTPUT_TIMINGS_PART1);
+    I830SDVOSetTargetOutput(sdvo, FALSE, TRUE);
+    I830SDVOSetTimings(sdvo, &sdvo->save_output_dtd_2,
+		       SDVO_CMD_SET_OUTPUT_TIMINGS_PART1);
+
+    I830SDVOSetClockRateMult(sdvo, sdvo->save_sdvo_mult);
+    I830SDVOSetActiveOutputs(sdvo, sdvo->save_sdvo_active_1,
+			     sdvo->save_sdvo_active_2);
+}
+
 static Bool
 I830SDVODDCI2CGetByte(I2CDevPtr d, I2CByte *data, Bool last)
 {
diff --git a/src/i830_sdvo.h b/src/i830_sdvo.h
new file mode 100644
index 0000000..ec4b538
--- /dev/null
+++ b/src/i830_sdvo.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
+typedef struct _i830_sdvo_dtd {
+    CARD16 clock;
+    CARD8 h_active;
+    CARD8 h_blank;
+    CARD8 h_high;
+    CARD8 v_active;
+    CARD8 v_blank;
+    CARD8 v_high;
+
+    CARD8 h_sync_off;
+    CARD8 h_sync_width;
+    CARD8 v_sync_off_width;
+    CARD8 sync_off_width_high;
+    CARD8 dtd_flags;
+    CARD8 sdvo_flags;
+    CARD8 v_sync_off_high;
+    CARD8 reserved;
+} __attribute__((packed)) i830_sdvo_dtd;
+
+void
+i830SDVOSave(ScrnInfoPtr pScrn, int output_index);
+
+void
+i830SDVOPreRestore(ScrnInfoPtr pScrn, int output_index);
+
+void
+i830SDVOPostRestore(ScrnInfoPtr pScrn, int output_index);
diff --git a/src/i830_sdvo_regs.h b/src/i830_sdvo_regs.h
index 5ad4ac9..9165c39 100644
--- a/src/i830_sdvo_regs.h
+++ b/src/i830_sdvo_regs.h
@@ -154,8 +154,10 @@
 #define SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS		0x1f
 
 #define SDVO_CMD_GET_CLOCK_RATE_MULT			0x20
-
 #define SDVO_CMD_SET_CLOCK_RATE_MULT			0x21
+# define SDVO_CLOCK_RATE_MULT_1X				0
+# define SDVO_CLOCK_RATE_MULT_2X				1
+# define SDVO_CLOCK_RATE_MULT_4X				3
 
 #define SDVO_CMD_GET_SUPPORTED_TV_FORMATS		0x27
 
diff-tree 56c1f8b0de9b6acc50f51561caf14d3e6bac09ec (from 9ba5319b36e7286e33cf0dcdd804dfc0458a81f5)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Apr 24 14:10:20 2006 -0700

    Clean up some argument passing, and remove extra SetTarget{In,Out}Puts that had
    no effect.  Note that we are currently trying to program both outputs of any
    SDVO device the same way.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 172a9be..e8898fc 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -131,12 +131,13 @@ I830SDVOSetControlBusSwitch(I830SDVOPtr 
 }
 
 static Bool
-I830SDVOSetTargetInput(I830SDVOPtr s)
+I830SDVOSetTargetInput(I830SDVOPtr s, Bool target_1, Bool target_2)
 {
-    /* write out 0x10 */
     memset(s->sdvo_regs, 0, 9);
 
     s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_TARGET_INPUT;
+    s->sdvo_regs[SDVO_I2C_ARG_0] = target_1;
+    s->sdvo_regs[SDVO_I2C_ARG_1] = target_2;
 
     I830SDVOWriteOutputs(s, 1);
 
@@ -146,16 +147,12 @@ I830SDVOSetTargetInput(I830SDVOPtr s)
 }
 
 static Bool
-I830SDVOGetTrainedInputs(I830SDVOPtr s, int on)
+I830SDVOGetTrainedInputs(I830SDVOPtr s)
 {
     memset(s->sdvo_regs, 0, 9);
 
     s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_TRAINED_INPUTS;
 
-    /* XXX: I don't believe we need to set anything here --anholt */
-    s->sdvo_regs[0x07] = on ? 0x80 : 0x00;
-    s->sdvo_regs[0x04] = on ? 0x80 : 0x00;
-
     I830SDVOWriteOutputs(s, 0);
     I830SDVOReadInputRegs(s);
 
@@ -163,15 +160,12 @@ I830SDVOGetTrainedInputs(I830SDVOPtr s, 
 }
 
 static Bool
-I830SDVOGetActiveOutputs(I830SDVOPtr s, int on)
+I830SDVOGetActiveOutputs(I830SDVOPtr s)
 {
     memset(s->sdvo_regs, 0, 9);
 
     s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_ACTIVE_OUTPUTS;
 
-    s->sdvo_regs[0x07] = on ? 0x01 : 0x00;
-    s->sdvo_regs[0x03] = 0x1;
-
     I830SDVOWriteOutputs(s, 0);
     I830SDVOReadInputRegs(s);
 
@@ -179,15 +173,13 @@ I830SDVOGetActiveOutputs(I830SDVOPtr s, 
 }
 
 static Bool
-I830SDVOSetActiveOutputs(I830SDVOPtr s, int on)
+I830SDVOSetActiveOutputs(I830SDVOPtr s, Bool on_1, Bool on_2)
 {
     memset(s->sdvo_regs, 0, 9);
 
     s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_ACTIVE_OUTPUTS;
-
-    /* XXX: This should be touching args 0,1, I believe.  --anholt */
-    s->sdvo_regs[0x07] = on ? 0x01 : 0x00;
-    s->sdvo_regs[0x03] = on ? 0x01 : 0x00;
+    s->sdvo_regs[SDVO_I2C_ARG_0] = on_1;
+    s->sdvo_regs[SDVO_I2C_ARG_1] = on_2;
 
     I830SDVOWriteOutputs(s, 2);
     I830SDVOReadInputRegs(s);
@@ -196,39 +188,34 @@ I830SDVOSetActiveOutputs(I830SDVOPtr s, 
 }
 
 static Bool
-I830SDVOGetInputPixelClockRange(I830SDVOPtr s, CARD16 clock, CARD16 height)
+I830SDVOGetInputPixelClockRange(I830SDVOPtr s, CARD16 *clock_min,
+				CARD16 *clock_max)
 {
     memset(s->sdvo_regs, 0, 9);
 
     s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE;
 
-    /* XXX: SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE shouldn't be taking args. */
-
-    /* set clock regs */
-    s->sdvo_regs[0x06] = (clock >> 8) & 0xff;
-    s->sdvo_regs[0x07] = clock & 0xff;
-
-    /* set height regs */
-    s->sdvo_regs[0x02] = (height >> 8) & 0xff;
-    s->sdvo_regs[0x03] = height & 0xff;
-
     I830SDVOWriteOutputs(s, 0);
     I830SDVOReadInputRegs(s);
 
+    *clock_min = s->sdvo_regs[SDVO_I2C_RETURN_0] |
+		 (s->sdvo_regs[SDVO_I2C_RETURN_1] << 8);
+    *clock_max = s->sdvo_regs[SDVO_I2C_RETURN_2] |
+		 (s->sdvo_regs[SDVO_I2C_RETURN_3] << 8);
+
     return TRUE;
 }
 
 static Bool
-I830SDVOSetTargetOutput(I830SDVOPtr s)
+I830SDVOSetTargetOutput(I830SDVOPtr s, Bool target_1, Bool target_2)
 {
     memset(s->sdvo_regs, 0, 9);
 
     s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_TARGET_OUTPUT;
+    s->sdvo_regs[SDVO_I2C_ARG_0] = target_1;
+    s->sdvo_regs[SDVO_I2C_ARG_1] = target_2;
 
-    s->sdvo_regs[SDVO_I2C_ARG_0] = 0x1;	/* Enable */
-    s->sdvo_regs[SDVO_I2C_ARG_1] = 0x0; /* Disable */
-
-    I830SDVOWriteOutputs(s, 1);		/* XXX: Only write these two */
+    I830SDVOWriteOutputs(s, 1);
     I830SDVOReadInputRegs(s);
 
     return TRUE;
@@ -309,26 +296,6 @@ I830SDVOSetOutputTimingsPart1(I830SDVOPt
 }
 
 static Bool
-I830SDVOGetPreferredInputTimingPart2(I830SDVOPtr s, CARD16 clock,
-				     CARD16 magic1, CARD16 magic2,
-				     CARD16 magic3)
-{
-    Bool ok;
-
-    /* XXX: This is a rather different command */
-    ok = I830SDVOSetTimingsPart1(s, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2,
-				 clock, magic1, magic2, magic3);
-
-    curr_table[3] = s->sdvo_regs[SDVO_I2C_RETURN_0] |
-		    (s->sdvo_regs[SDVO_I2C_RETURN_1] << 8);
-    curr_table[4] = s->sdvo_regs[SDVO_I2C_RETURN_2] |
-		    (s->sdvo_regs[SDVO_I2C_RETURN_3] << 8);
-    curr_table[5] = 0x1e;
-
-    return ok;
-}
-
-static Bool
 I830SDVOSetTimingsPart2(I830SDVOPtr s, CARD8 cmd, CARD16 magic4, CARD16 magic5,
 			CARD16 magic6)
 {
@@ -408,6 +375,23 @@ I830SDVOGetPreferredInputTimingPart1(I83
 }
 
 static Bool
+I830SDVOGetPreferredInputTimingPart2(I830SDVOPtr s)
+{
+    s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2;
+
+    I830SDVOWriteOutputs(s, 0);
+    I830SDVOReadInputRegs(s);
+
+    curr_table[3] = s->sdvo_regs[SDVO_I2C_RETURN_0] |
+		    (s->sdvo_regs[SDVO_I2C_RETURN_1] << 8);
+    curr_table[4] = s->sdvo_regs[SDVO_I2C_RETURN_2] |
+		    (s->sdvo_regs[SDVO_I2C_RETURN_3] << 8);
+    curr_table[5] = 0x1e;
+
+    return TRUE;
+}
+
+static Bool
 I830SDVOSetClockRateMult(I830SDVOPtr s, CARD8 val)
 {
     memset(s->sdvo_regs, 0, 9);
@@ -432,6 +416,7 @@ I830SDVOPreSetMode(I830SDVOPtr s, Displa
     CARD8 c16a[8];
     CARD8 c17a[8];
     CARD16 out_timings[6];
+    CARD16 clock_min, clock_max;
 
     /* do some mode translations */
     h_blank_len = mode->CrtcHBlankEnd - mode->CrtcHBlankStart;
@@ -471,40 +456,27 @@ I830SDVOPreSetMode(I830SDVOPtr s, Displa
     out_timings[4] = c17a[5] | ((short)c17a[4] << 8);
     out_timings[5] = c17a[3] | ((short)c17a[2] << 8);
 
-    I830SDVOSetTargetInput(s);
-    I830SDVOGetInputPixelClockRange(s, clock, height);
+    I830SDVOSetTargetInput(s, TRUE, TRUE);
+    I830SDVOGetInputPixelClockRange(s, &clock_min, &clock_max);
+    ErrorF("clock min/max: %d %d\n", clock_min, clock_max);
 
-    I830SDVOGetActiveOutputs(s, 0);
-    I830SDVOSetActiveOutputs(s, 0);
+    I830SDVOGetActiveOutputs(s);
+    I830SDVOSetActiveOutputs(s, FALSE, FALSE);
 
-    I830SDVOSetTargetOutput(s);
+    I830SDVOSetTargetOutput(s, TRUE, TRUE);
     I830SDVOSetOutputTimingsPart1(s, clock, out_timings[0], out_timings[1],
 				  out_timings[2]);
-
-    I830SDVOSetTargetOutput(s);
     I830SDVOSetOutputTimingsPart2(s, out_timings[3], out_timings[4],
 				  out_timings[5]);
 
-    I830SDVOSetTargetInput(s);
-
     I830SDVOCreatePreferredInputTiming(s, clock, width, height);
-    I830SDVOSetTargetInput(s);
-
     I830SDVOGetPreferredInputTimingPart1(s);
-    I830SDVOSetTargetInput(s);
-
-    I830SDVOGetPreferredInputTimingPart2(s, clock, out_timings[0], out_timings[1],
-					 out_timings[2]);
-    I830SDVOSetTargetInput(s);
-
+    I830SDVOGetPreferredInputTimingPart2(s);
     I830SDVOSetInputTimingsPart1(s, clock, curr_table[0], curr_table[1],
 				 curr_table[2]);
-
-    I830SDVOSetTargetInput(s);
     I830SDVOSetInputTimingsPart2(s, curr_table[3], curr_table[4],
 				 out_timings[5]);
 
-    I830SDVOSetTargetInput(s);
     /*if (mode->PrivFlags & I830_MFLAG_DOUBLE)
 	I830SDVOSetClockRateMult(s, 0x02);
     else */
@@ -516,15 +488,13 @@ I830SDVOPreSetMode(I830SDVOPtr s, Displa
 Bool
 I830SDVOPostSetMode(I830SDVOPtr s, DisplayModePtr mode)
 {
-    int clock = mode->Clock/10, height=mode->CrtcVDisplay;
     Bool ret = TRUE;
 
     /* the BIOS writes out 6 commands post mode set */
     /* two 03s, 04 05, 10, 1d */
     /* these contain the height and mode clock / 10 by the looks of it */
 
-    I830SDVOGetTrainedInputs(s, 1);
-    I830SDVOGetTrainedInputs(s, 0);
+    I830SDVOGetTrainedInputs(s);
 
     /* THIS IS A DIRTY HACK - sometimes for some reason on startup
      * the BIOS doesn't find my DVI monitor -
@@ -535,11 +505,8 @@ I830SDVOPostSetMode(I830SDVOPtr s, Displ
 	ret = FALSE;
     }
 
-    I830SDVOGetActiveOutputs(s, 1);
-    I830SDVOSetActiveOutputs(s, 1);
-
-    I830SDVOSetTargetInput(s);
-    I830SDVOGetInputPixelClockRange(s, clock, height);
+    I830SDVOGetActiveOutputs(s);
+    I830SDVOSetActiveOutputs(s, TRUE, TRUE);
 
     return ret;
 }
diff-tree 9ba5319b36e7286e33cf0dcdd804dfc0458a81f5 (from d32514aee4b00b035652830e8b5e6c0b43cf159c)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Apr 24 13:55:05 2006 -0700

    Only write out as many arguments as the commands need, and fix up the numbers in
    some cases.  Pretty-print the return status.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 412d798..172a9be 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -64,19 +64,29 @@ I830SDVOWriteOutputs(I830SDVOPtr s, int 
 {
     int i;
 
-    ErrorF("SDVO: W: ");
-    for (i = num_out; i <= SDVO_I2C_ARG_0; i++)
+    ErrorF("SDVO: W: %02X ", s->sdvo_regs[SDVO_I2C_OPCODE]);
+    for (i = SDVO_I2C_ARG_0; i > SDVO_I2C_ARG_0 - num_out; i--)
 	ErrorF("%02X ", s->sdvo_regs[i]);
     ErrorF("\n");
 
     /* blast the output regs */
-    for (i = SDVO_I2C_ARG_0; i >= num_out; i--) {
+    for (i = SDVO_I2C_ARG_0; i > SDVO_I2C_ARG_0 - num_out; i--) {
 	sWriteByte(s, i, s->sdvo_regs[i]);
     }
     /* blast the command reg */
     sWriteByte(s, SDVO_I2C_OPCODE, s->sdvo_regs[SDVO_I2C_OPCODE]);
 }
 
+static const char *cmd_status_names[] = {
+	"Power on",
+	"Success",
+	"Not supported",
+	"Invalid arg",
+	"Pending",
+	"Target not supported",
+	"Scaling not supported"
+};
+
 static void
 I830SDVOReadInputRegs(I830SDVOPtr s)
 {
@@ -95,8 +105,12 @@ I830SDVOReadInputRegs(I830SDVOPtr s)
     sReadByte(s, SDVO_I2C_RETURN_4, &s->sdvo_regs[SDVO_I2C_RETURN_4]);
 
     ErrorF("SDVO: R: ");
-    for (i = SDVO_I2C_CMD_STATUS; i <= SDVO_I2C_RETURN_7; i++)
+    for (i = SDVO_I2C_RETURN_0; i <= SDVO_I2C_RETURN_7; i++)
 	ErrorF("%02X ", s->sdvo_regs[i]);
+    if (s->sdvo_regs[SDVO_I2C_CMD_STATUS] <= SDVO_CMD_STATUS_SCALING_NOT_SUPP)
+	ErrorF("(%s)", cmd_status_names[s->sdvo_regs[SDVO_I2C_CMD_STATUS]]);
+    else
+	ErrorF("(??? %d)", s->sdvo_regs[SDVO_I2C_CMD_STATUS]);
     ErrorF("\n");
 }
 
@@ -112,7 +126,7 @@ I830SDVOSetControlBusSwitch(I830SDVOPtr 
     s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_CONTROL_BUS_SWITCH;
     s->sdvo_regs[SDVO_I2C_ARG_0] = target;
 
-    I830SDVOWriteOutputs(s, 7);
+    I830SDVOWriteOutputs(s, 1);
     return TRUE;
 }
 
@@ -124,7 +138,7 @@ I830SDVOSetTargetInput(I830SDVOPtr s)
 
     s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_TARGET_INPUT;
 
-    I830SDVOWriteOutputs(s, 0);
+    I830SDVOWriteOutputs(s, 1);
 
     I830SDVOReadInputRegs(s);
 
@@ -175,7 +189,7 @@ I830SDVOSetActiveOutputs(I830SDVOPtr s, 
     s->sdvo_regs[0x07] = on ? 0x01 : 0x00;
     s->sdvo_regs[0x03] = on ? 0x01 : 0x00;
 
-    I830SDVOWriteOutputs(s, 0);
+    I830SDVOWriteOutputs(s, 2);
     I830SDVOReadInputRegs(s);
 
     return TRUE;
@@ -214,7 +228,7 @@ I830SDVOSetTargetOutput(I830SDVOPtr s)
     s->sdvo_regs[SDVO_I2C_ARG_0] = 0x1;	/* Enable */
     s->sdvo_regs[SDVO_I2C_ARG_1] = 0x0; /* Disable */
 
-    I830SDVOWriteOutputs(s, 0);		/* XXX: Only write these two */
+    I830SDVOWriteOutputs(s, 1);		/* XXX: Only write these two */
     I830SDVOReadInputRegs(s);
 
     return TRUE;
@@ -272,7 +286,7 @@ I830SDVOSetTimingsPart1(I830SDVOPtr s, c
     s->sdvo_regs[SDVO_I2C_ARG_6] = magic1 & 0xff;
     s->sdvo_regs[SDVO_I2C_ARG_7] = (magic1 >> 8) & 0xff;
 
-    I830SDVOWriteOutputs(s, 0);
+    I830SDVOWriteOutputs(s, 8);
     I830SDVOReadInputRegs(s);
   
     return TRUE;
@@ -330,7 +344,7 @@ I830SDVOSetTimingsPart2(I830SDVOPtr s, C
     s->sdvo_regs[SDVO_I2C_ARG_4] = magic6 & 0xff;
     s->sdvo_regs[SDVO_I2C_ARG_5] = (magic6 >> 8) & 0xff;
 
-    I830SDVOWriteOutputs(s, 0);
+    I830SDVOWriteOutputs(s, 8);
     I830SDVOReadInputRegs(s);
   
     return TRUE;
@@ -367,7 +381,7 @@ I830SDVOCreatePreferredInputTiming(I830S
     s->sdvo_regs[SDVO_I2C_ARG_4] = height & 0xff;  
     s->sdvo_regs[SDVO_I2C_ARG_5] = (height >> 8) & 0xff;
 
-    I830SDVOWriteOutputs(s, 0);
+    I830SDVOWriteOutputs(s, 7);
     I830SDVOReadInputRegs(s);
 
     return TRUE;
@@ -401,7 +415,7 @@ I830SDVOSetClockRateMult(I830SDVOPtr s, 
     s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_CLOCK_RATE_MULT;
 
     s->sdvo_regs[SDVO_I2C_ARG_0] = val;
-    I830SDVOWriteOutputs(s, 0);
+    I830SDVOWriteOutputs(s, 1);
     I830SDVOReadInputRegs(s);
 
     return TRUE;
diff-tree d32514aee4b00b035652830e8b5e6c0b43cf159c (from effab21c3d108fac7a4e28ae4dabb0b5f74a5380)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Apr 24 12:21:45 2006 -0700

    Start trying to implement DDC over SDVO.  It's slightly tricky because the
    control bus will reset from DDC mode to internal-registers mode after every
    Stop afer a Start on the DDC bus.  The xf86 DDC code causes multiple Start/Stops
    in one probe.  So, we create a wrapper bus that does the control bus switch at
    every Start.  It's not working yet on my hardware, but I'm pretty sure this is
    the right way to go.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 3f67106..7c6de99 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1462,16 +1462,12 @@ void I830DetectMonitors(ScrnInfoPtr pScr
       break;
       case I830_OUTPUT_SDVO:
 	 if (pI830->output[i].sdvo_drv != NULL) {
-#if 0
-	    I830SDVOSetupDDC(pI830->output[i].sdvo_drv);
-
 	    pI830->output[i].MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex,
-						       pI830->output[i].pI2CBus);
+						       pI830->output[i].pDDCBus);
 
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC SDVO %d, %08X\n", i,
-		       pI830->output[i].pI2CBus->DriverPrivate.uval);
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC SDVO %d, %08lX\n", i,
+		       pI830->output[i].pDDCBus->DriverPrivate.uval);
 	    xf86PrintEDID(pI830->output[i].MonInfo);
-#endif
 	 }
 	 break;
       case I830_OUTPUT_UNUSED:
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 0578461..412d798 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -100,21 +100,19 @@ I830SDVOReadInputRegs(I830SDVOPtr s)
     ErrorF("\n");
 }
 
+/* Sets the control bus switch to either point at one of the DDC buses or the
+ * PROM.  It resets from the DDC bus back to internal registers at the next I2C
+ * STOP.  PROM access is terminated by accessing an internal register.
+ */
 Bool
-I830SDVOSetupDDC(I830SDVOPtr s, int enable)
+I830SDVOSetControlBusSwitch(I830SDVOPtr s, CARD8 target)
 {
     memset(s->sdvo_regs, 0, 9);
 
     s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_CONTROL_BUS_SWITCH;
-    s->sdvo_regs[SDVO_I2C_ARG_0] = SDVO_CONTROL_BUS_DDC2;
+    s->sdvo_regs[SDVO_I2C_ARG_0] = target;
 
     I830SDVOWriteOutputs(s, 7);
-
-    sReadByte(s, SDVO_I2C_CMD_STATUS, &s->sdvo_regs[SDVO_I2C_CMD_STATUS]);
-
-    ErrorF("SDVO: R: ");
-    ErrorF("%02X ", s->sdvo_regs[SDVO_I2C_CMD_STATUS]);
-    ErrorF("\n");
     return TRUE;
 }
 
@@ -532,6 +530,80 @@ I830SDVOPostSetMode(I830SDVOPtr s, Displ
     return ret;
 }
 
+static Bool
+I830SDVODDCI2CGetByte(I2CDevPtr d, I2CByte *data, Bool last)
+{
+    I830SDVOPtr sdvo = d->pI2CBus->DriverPrivate.ptr;
+    I2CBusPtr i2cbus = sdvo->d.pI2CBus, savebus;
+    Bool ret;
+
+    savebus = d->pI2CBus;
+    d->pI2CBus = i2cbus;
+    ret = i2cbus->I2CGetByte(d, data, last);
+    d->pI2CBus = savebus;
+
+    return ret;
+}
+
+static Bool
+I830SDVODDCI2CPutByte(I2CDevPtr d, I2CByte c)
+{
+    I830SDVOPtr sdvo = d->pI2CBus->DriverPrivate.ptr;
+    I2CBusPtr i2cbus = sdvo->d.pI2CBus, savebus;
+    Bool ret;
+
+    savebus = d->pI2CBus;
+    d->pI2CBus = i2cbus;
+    ret = i2cbus->I2CPutByte(d, c);
+    d->pI2CBus = savebus;
+
+    return ret;
+}
+
+static Bool
+I830SDVODDCI2CStart(I2CBusPtr b, int timeout)
+{
+    I830SDVOPtr sdvo = b->DriverPrivate.ptr;
+    I2CBusPtr i2cbus = sdvo->d.pI2CBus;
+
+    I830SDVOSetControlBusSwitch(sdvo, SDVO_CONTROL_BUS_DDC1);
+    return i2cbus->I2CStart(i2cbus, timeout);
+}
+
+static void
+I830SDVODDCI2CStop(I2CDevPtr d)
+{
+    I830SDVOPtr sdvo = d->pI2CBus->DriverPrivate.ptr;
+    I2CBusPtr i2cbus = sdvo->d.pI2CBus, savebus;
+
+    savebus = d->pI2CBus;
+    d->pI2CBus = i2cbus;
+    i2cbus->I2CStop(d);
+    d->pI2CBus = savebus;
+}
+
+/* It's a shame that xf86i2c.c's I2CAddress() doesn't use the bus's pointers,
+ * so it's useless to us here.
+ */
+static Bool
+I830SDVODDCI2CAddress(I2CDevPtr d, I2CSlaveAddr addr)
+{
+    if (d->pI2CBus->I2CStart(d->pI2CBus, d->StartTimeout)) {
+	if (d->pI2CBus->I2CPutByte(d, addr & 0xFF)) {
+	    if ((addr & 0xF8) != 0xF0 &&
+		(addr & 0xFE) != 0x00)
+		return TRUE;
+
+	    if (d->pI2CBus->I2CPutByte(d, (addr >> 8) & 0xFF))
+		return TRUE;
+	}
+
+	d->pI2CBus->I2CStop(d);
+    }
+
+    return FALSE;
+}
+
 I830SDVOPtr
 I830SDVOInit(ScrnInfoPtr pScrn, int output_index, CARD32 output_device)
 {
@@ -539,6 +611,9 @@ I830SDVOInit(ScrnInfoPtr pScrn, int outp
     I830SDVOPtr sdvo;
     int i;
     unsigned char ch[0x40];
+    I2CBusPtr i2cbus, ddcbus;
+
+    i2cbus = pI830->output[output_index].pI2CBus;
 
     sdvo = xcalloc(1, sizeof(I830SDVORec));
     if (sdvo == NULL)
@@ -551,7 +626,7 @@ I830SDVOInit(ScrnInfoPtr pScrn, int outp
 	sdvo->d.DevName = "SDVO Controller C";
 	sdvo->d.SlaveAddr = 0x72;
     }
-    sdvo->d.pI2CBus = pI830->output[output_index].pI2CBus;
+    sdvo->d.pI2CBus = i2cbus;
     sdvo->d.DriverPrivate.ptr = sdvo;
     sdvo->output_device = output_device;
 
@@ -563,9 +638,38 @@ I830SDVOInit(ScrnInfoPtr pScrn, int outp
 	return NULL;
     }
 
+    /* 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
+     * Start, extra attempts should be harmless.
+     */
+    ddcbus = xf86CreateI2CBusRec();
+    if (ddcbus == NULL) {
+	xf86DestroyI2CDevRec(&sdvo->d, 0);
+	xfree(sdvo);
+	return NULL;
+    }
+    ddcbus->BusName = "SDVO DDC Bus";
+    ddcbus->scrnIndex = i2cbus->scrnIndex;
+    ddcbus->I2CGetByte = I830SDVODDCI2CGetByte;
+    ddcbus->I2CPutByte = I830SDVODDCI2CPutByte;
+    ddcbus->I2CStart = I830SDVODDCI2CStart;
+    ddcbus->I2CStop = I830SDVODDCI2CStop;
+    ddcbus->I2CAddress = I830SDVODDCI2CAddress;
+    ddcbus->DriverPrivate.ptr = sdvo;
+    if (!xf86I2CBusInit(ddcbus)) {
+	xf86DestroyI2CDevRec(&sdvo->d, 0);
+	xfree(sdvo);
+	return NULL;
+    }
+
+    pI830->output[output_index].pDDCBus = ddcbus;
+
     /* Read the regs to test if we can talk to the device */
     for (i = 0; i < 0x40; i++) {
 	if (!sReadByte(sdvo, i, &ch[i])) {
+	    xf86DestroyI2CBusRec(pI830->output[output_index].pDDCBus, FALSE,
+		FALSE);
 	    xf86DestroyI2CDevRec(&sdvo->d, 0);
 	    xfree(sdvo);
 	    return NULL;
diff-tree effab21c3d108fac7a4e28ae4dabb0b5f74a5380 (from bcb441225d1365435bc3373901180de944298e86)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Apr 24 11:42:24 2006 -0700

    Set displayWidth to a sufficient value for the modes we come up with for LVDS.
    
    Reported by:	Lukáš Hejtmánek

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 8fba83c..3f67106 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1693,6 +1693,10 @@ static int i830ValidateFPModes(ScrnInfoP
    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 	      "Total number of valid FP mode(s) found: %d\n", count);
 
+   /* Adjust the display pitch to fit the modes we've come up with. */
+   pScrn->displayWidth = MAX(pScrn->displayWidth, pScrn->virtualX);
+   pScrn->displayWidth = (pScrn->displayWidth + 63) & ~63;
+
    return count;
 }
 
diff-tree bcb441225d1365435bc3373901180de944298e86 (from 47bd9059431eadfd8824e496eb91bb50efa0e282)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Apr 24 10:54:45 2006 -0700

    Simplify the i2c code by using the GetBits/PutBits interface rather than
    reimplementing it.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index c790e8b..dee39ce 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -267,12 +267,12 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define GPIOG			0x5028
 #define GPIOH			0x502c
 # define GPIO_CLOCK_DIR_MASK		(1 << 0)
-# define GPIO_CLOCK_DIR			(1 << 1)
+# define GPIO_CLOCK_DIR_OUT		(1 << 1)
 # define GPIO_CLOCK_VAL_MASK		(1 << 2)
 # define GPIO_CLOCK_VAL_OUT		(1 << 3)
 # define GPIO_CLOCK_VAL_IN		(1 << 4)
 # define GPIO_DATA_DIR_MASK		(1 << 8)
-# define GPIO_DATA_DIR			(1 << 9)
+# define GPIO_DATA_DIR_OUT		(1 << 9)
 # define GPIO_DATA_VAL_MASK		(1 << 10)
 # define GPIO_DATA_VAL_OUT		(1 << 11)
 # define GPIO_DATA_VAL_IN		(1 << 12)
diff --git a/src/i830_i2c.c b/src/i830_i2c.c
index 8c80a0a..fa0ca30 100644
--- a/src/i830_i2c.c
+++ b/src/i830_i2c.c
@@ -49,215 +49,35 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "shadow.h"
 #include "i830.h"
 
-#define I2C_TIMEOUT(x)	/*(x)*/  /* Report timeouts */
-#define I2C_TRACE(x)    /*(x)*/  /* Report progress */
-
-static void i830_setscl(I2CBusPtr b, int state)
+static void
+i830I2CGetBits(I2CBusPtr b, int *clock, int *data)
 {
-    ScrnInfoPtr    pScrn      = xf86Screens[b->scrnIndex];
+    ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
     I830Ptr pI830 = I830PTR(pScrn);
     CARD32 val;
 
-    OUTREG(b->DriverPrivate.uval,
-	(state ? GPIO_CLOCK_VAL_OUT : 0) |
-	GPIO_CLOCK_DIR |
-	GPIO_CLOCK_DIR_MASK |
-	GPIO_CLOCK_VAL_MASK);
     val = INREG(b->DriverPrivate.uval);
+    *data = (val & GPIO_DATA_VAL_IN) != 0;
+    *clock = (val & GPIO_CLOCK_VAL_IN) != 0;
 }
 
-static void i830_setsda(I2CBusPtr b, int state)
+static void
+i830I2CPutBits(I2CBusPtr b, int clock, int data)
 {
-    ScrnInfoPtr    pScrn      = xf86Screens[b->scrnIndex];
+    ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
     I830Ptr pI830 = I830PTR(pScrn);
-    CARD32 val;
 
-    OUTREG(b->DriverPrivate.uval, (state ? GPIO_DATA_VAL_OUT : 0) |
-	GPIO_DATA_DIR |
+    OUTREG(b->DriverPrivate.uval,
+	(data ? GPIO_DATA_VAL_OUT : 0) |
+	(clock ? GPIO_CLOCK_VAL_OUT : 0) |
+	GPIO_CLOCK_DIR_OUT |
+	GPIO_DATA_DIR_OUT |
+	GPIO_CLOCK_DIR_MASK |
+	GPIO_CLOCK_VAL_MASK |
 	GPIO_DATA_DIR_MASK |
 	GPIO_DATA_VAL_MASK);
-    val = INREG(b->DriverPrivate.uval);
-}
-
-static void i830_getscl(I2CBusPtr b, int *state)
-{
-    ScrnInfoPtr    pScrn      = xf86Screens[b->scrnIndex];
-    I830Ptr pI830 = I830PTR(pScrn);
-    CARD32 val;
-
-    OUTREG(b->DriverPrivate.uval, GPIO_CLOCK_DIR_MASK);
-    OUTREG(b->DriverPrivate.uval, 0);
-    val = INREG(b->DriverPrivate.uval);
-    *state = ((val & GPIO_CLOCK_VAL_IN) != 0);
-}
-
-static int i830_getsda(I2CBusPtr b)
-{
-    ScrnInfoPtr    pScrn      = xf86Screens[b->scrnIndex];
-    I830Ptr pI830 = I830PTR(pScrn);
-    CARD32 val;
-
-    OUTREG(b->DriverPrivate.uval, GPIO_DATA_DIR_MASK);
-    OUTREG(b->DriverPrivate.uval, 0);
-    val = INREG(b->DriverPrivate.uval);
-    return ((val & GPIO_DATA_VAL_IN) != 0);
-}
-
-static inline void sdalo(I2CBusPtr b)
-{
-    i830_setsda(b, 0);
-    b->I2CUDelay(b, b->RiseFallTime);
-}
-
-static inline void sdahi(I2CBusPtr b)
-{
-    i830_setsda(b, 1);
-    b->I2CUDelay(b, b->RiseFallTime);
-}
-
-static inline void scllo(I2CBusPtr b)
-{
-    i830_setscl(b, 0);
-    b->I2CUDelay(b, b->RiseFallTime);
-}
-
-static inline int sclhi(I2CBusPtr b, int timeout)
-{
-    int scl = 0;
-    int i;
-
-    i830_setscl(b, 1);
-    b->I2CUDelay(b, b->RiseFallTime);
-  
-    for (i = timeout; i > 0; i -= b->RiseFallTime) {
-	i830_getscl(b, &scl);
-	if (scl) break;
-	b->I2CUDelay(b, b->RiseFallTime);
-    }
-
-    if (i <= 0) {
-	I2C_TIMEOUT(ErrorF("[I2CRaiseSCL(<%s>, %d) timeout]", b->BusName, timeout));    
-	return FALSE;
-    }
-    return TRUE;
-}
-
-static Bool
-I830I2CGetByte(I2CDevPtr d, I2CByte *data, Bool last)
-{
-    I2CBusPtr b = d->pI2CBus;
-    int i;
-    unsigned char indata = 0;
-
-    sdahi(b);
-
-    for (i = 0; i < 8; i++) {
-      if (sclhi(b, d->BitTimeout)==FALSE) {
-	I2C_TRACE(ErrorF("timeout at bit #%d\n", 7-i));
-	return FALSE;
-      }
-      indata*=2;
-      if ( i830_getsda (b) ) {
-	indata |= 0x01;
-      }
-      scllo(b);
-    }
-
-    if (last)
-      sdahi(b);
-    else
-      sdalo(b);
-
-    if (sclhi(b, d->BitTimeout) == FALSE) {
-      sdahi(b);
-      return FALSE;
-    }
-
-    scllo(b);
-    sdahi(b);
-
-    *data = indata & 0xff;
-    I2C_TRACE(ErrorF("R%02x ", (int) *data));
-    
-    return TRUE;
-}
-
-static Bool
-I830I2CPutByte(I2CDevPtr d, I2CByte c)
-{
-    int i;
-    int sb, ack;
-    I2CBusPtr b = d->pI2CBus;
-
-    for (i = 7; i>=0; i--) {
-      sb = c & (1 << i);
-      i830_setsda(b, sb);
-      b->I2CUDelay(b, b->RiseFallTime);
-
-      if (sclhi(b, d->ByteTimeout) == FALSE) {
-	sdahi(b);
-	return FALSE;
-      }
-
-      i830_setscl(b, 0);
-      b->I2CUDelay(b, b->RiseFallTime);
-    }
-    sdahi(b);
-    if (sclhi(b, d->ByteTimeout) == FALSE) {
-      I2C_TIMEOUT(ErrorF("[I2CPutByte(<%s>, 0x%02x, %d, %d, %d) timeout]", 
-			 b->BusName, c, d->BitTimeout, 
-			 d->ByteTimeout, d->AcknTimeout));
-      return FALSE;
-    }
-    ack = i830_getsda(b);
-    I2C_TRACE(ErrorF("Put byte 0x%02x , getsda() = %d\n", c & 0xff, ack));
-
-    scllo(b);
-    return 0 == ack;
 }
 
-static Bool
-I830I2CStart(I2CBusPtr b, int timeout)
-{
-    if (sclhi(b, timeout) == FALSE)
-	return FALSE;
-
-    sdalo(b);
-    scllo(b);
-    
-    return TRUE;
-}
-
-static void
-I830I2CStop(I2CDevPtr d)
-{
-    I2CBusPtr b = d->pI2CBus;
-
-    sdalo(b);
-    sclhi(b, d->ByteTimeout);
-    sdahi(b);
-}
-
-static Bool
-I830I2CAddress(I2CDevPtr d, I2CSlaveAddr addr)
-{
-    if (I830I2CStart(d->pI2CBus, d->StartTimeout)) {
-	if (I830I2CPutByte(d, addr & 0xFF)) {
-	    if ((addr & 0xF8) != 0xF0 &&
-		(addr & 0xFE) != 0x00)
-		return TRUE;
-
-	    if (I830I2CPutByte(d, (addr >> 8) & 0xFF))
-		return TRUE;
-	}
-
-	I830I2CStop(d);
-    }
-
-    return FALSE;
-}
-
-
 /* the i830 has a number of I2C Buses */
 Bool
 I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg, char *name)
@@ -271,11 +91,8 @@ I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr
 
     pI2CBus->BusName = name;
     pI2CBus->scrnIndex = pScrn->scrnIndex;
-    pI2CBus->I2CGetByte = I830I2CGetByte;
-    pI2CBus->I2CPutByte = I830I2CPutByte;
-    pI2CBus->I2CStart = I830I2CStart;
-    pI2CBus->I2CStop = I830I2CStop;
-    pI2CBus->I2CAddress = I830I2CAddress;
+    pI2CBus->I2CGetBits = i830I2CGetBits;
+    pI2CBus->I2CPutBits = i830I2CPutBits;
     pI2CBus->DriverPrivate.uval = i2c_reg;
 
     if (!xf86I2CBusInit(pI2CBus))
diff-tree 47bd9059431eadfd8824e496eb91bb50efa0e282 (from parents)
Merge: 729c373121ce2bbb0d813cc923f1254e8b37a025 32a0ad570d9c010e7d26d980830f719782d9f2f3
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Apr 24 10:36:24 2006 -0700

    Merge branch 'lukas-resume'

diff-tree 729c373121ce2bbb0d813cc923f1254e8b37a025 (from 0ba7b13fb4410c6a48b2fb098d2033e040eca6d2)
Author: Dave Airlie <airlied at linux.ie>
Date:   Thu Apr 20 13:34:55 2006 +1000

    move sdvo output setting
    
    we have to set the sdvo register a lot earlier in order for them to sync
    properly otherwise my monitor doesn't sync unfortunately, also
    disable the sdvo while tweaking the PLLs.
    
    This also comments out a setting that seems to break my system here for
    Eric to look at later.

diff --git a/src/i830_display.c b/src/i830_display.c
index 471b87e..95fa936 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -395,8 +395,9 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	sdvoc |= SDVO_ENABLE;
 	if (pipe == 1)
 	    sdvoc |= SDVO_PIPE_B_SELECT;
-	sdvoc |= SDVO_PHASE_SELECT_DEFAULT;
+	//	sdvoc |= SDVO_PHASE_SELECT_DEFAULT;
 	sdvoc |= SDVO_BORDER_ENABLE;
+	OUTREG(SDVOC, INREG(SDVOC) & ~SDVO_ENABLE);
     }
 
     fp = ((n - 2) << 16) | ((m1 - 2) << 8) | (m2 - 2);
@@ -464,6 +465,10 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 
 	OUTREG(FPA0, fp);
 	OUTREG(DPLL_A, dpll);
+
+	if (is_sdvo)
+	  OUTREG(SDVOC, sdvoc);
+
 	OUTREG(HTOTAL_A, htot);
 	OUTREG(HBLANK_A, hblank);
 	OUTREG(HSYNC_A, hsync);
@@ -553,8 +558,6 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 
     if (outputs & PIPE_CRT_ACTIVE)
 	OUTREG(ADPA, adpa);
-    if (is_sdvo)
-	OUTREG(SDVOC, sdvoc);
 
     return TRUE;
 }
diff-tree 0ba7b13fb4410c6a48b2fb098d2033e040eca6d2 (from 2991d81a3b643161babab6b8f44c057aaaf351c3)
Author: Dave Airlie <airlied at linux.ie>
Date:   Thu Apr 20 12:29:06 2006 +1000

    fix type 0 instead of O

diff --git a/src/i810_reg.h b/src/i810_reg.h
index 82571e0..2a03f32 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -722,7 +722,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 # define PLLB_REF_INPUT_SPREADSPECTRUMIN	(3 << 13)
 # define DISPLAY_RATE_SELECT_FPA1		(1 << 8)
 # define SDVO_MULTIPLIER_MASK			0x000000ff
-# define SDV0_DEFAULT_MULTIPLIER		0x00000003
+# define SDVO_DEFAULT_MULTIPLIER		0x00000003
 
 #define FPA0		0x06040
 #define FPA1		0x06044
diff --git a/src/i830_display.c b/src/i830_display.c
index f8bd0d8..471b87e 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -384,7 +384,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	dpll |= PLL_REF_INPUT_TVCLKINBC;
     else
 	dpll |= PLL_REF_INPUT_DREFCLK;
-    dpll |= SDV0_DEFAULT_MULTIPLIER;
+    dpll |= SDVO_DEFAULT_MULTIPLIER;
 
     if (is_sdvo) {
 	dpll |= DPLL_DVO_HIGH_SPEED;
diff-tree 2991d81a3b643161babab6b8f44c057aaaf351c3 (from b5f099e03a9f58b6b99933fb06526bce4db72bd3)
Author: Dave Airlie <airlied at linux.ie>
Date:   Thu Apr 20 12:27:47 2006 +1000

    correct height parameter in sdvo packet

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 4d76044..0578461 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -366,8 +366,8 @@ I830SDVOCreatePreferredInputTiming(I830S
     s->sdvo_regs[SDVO_I2C_ARG_1] = (clock >> 8) & 0xff;
     s->sdvo_regs[SDVO_I2C_ARG_2] = width & 0xff;
     s->sdvo_regs[SDVO_I2C_ARG_3] = (width >> 8) & 0xff;
-    s->sdvo_regs[SDVO_I2C_ARG_4] = (height >> 8) & 0xff;
-    s->sdvo_regs[SDVO_I2C_ARG_5] = height & 0xff;  
+    s->sdvo_regs[SDVO_I2C_ARG_4] = height & 0xff;  
+    s->sdvo_regs[SDVO_I2C_ARG_5] = (height >> 8) & 0xff;
 
     I830SDVOWriteOutputs(s, 0);
     I830SDVOReadInputRegs(s);
diff-tree b5f099e03a9f58b6b99933fb06526bce4db72bd3 (from 2909802de63756972b38651a496b4ff1b36ac8a2)
Author: Dave Airlie <airlied at linux.ie>
Date:   Thu Apr 20 09:50:36 2006 +1000

    cleanup sDVO for device on C only
    
    This destroys the i2c device properly if the device isn't detected,
    and allows sDVO to work on GM chipsets, and doesn't initialise
    the i2c bus twice for sDVO.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 61cc231..e0bb55a 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1369,7 +1369,6 @@ I830SetupOutputBusses(ScrnInfoPtr pScrn)
       pI830->output[i].type = I830_OUTPUT_LVDS;
       I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOC, "LVDSDDC_C");
       i++;
-      break;
    case PCI_CHIP_I915_G:
    case PCI_CHIP_I945_G:
       /* Set up SDVOB */
@@ -1380,7 +1379,7 @@ I830SetupOutputBusses(ScrnInfoPtr pScrn)
 
       /* Set up SDVOC */
       pI830->output[i].type = I830_OUTPUT_SDVO;
-      I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "SDVOCTRL_E");
+      pI830->output[i].pI2CBus = pI830->output[i-1].pI2CBus;
       I830SDVOInit(pScrn, i, SDVOC);
       i++;
       break;
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index bbf2b93..4d76044 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -544,11 +544,13 @@ I830SDVOInit(ScrnInfoPtr pScrn, int outp
     if (sdvo == NULL)
 	return NULL;
 
-    sdvo->d.DevName = "SDVO Controller";
-    if (output_device == SDVOB)
+    if (output_device == SDVOB) {
+	sdvo->d.DevName = "SDVO Controller B";
 	sdvo->d.SlaveAddr = 0x70;
-    else
+    } else {
+	sdvo->d.DevName = "SDVO Controller C";
 	sdvo->d.SlaveAddr = 0x72;
+    }
     sdvo->d.pI2CBus = pI830->output[output_index].pI2CBus;
     sdvo->d.DriverPrivate.ptr = sdvo;
     sdvo->output_device = output_device;
@@ -564,6 +566,7 @@ I830SDVOInit(ScrnInfoPtr pScrn, int outp
     /* Read the regs to test if we can talk to the device */
     for (i = 0; i < 0x40; i++) {
 	if (!sReadByte(sdvo, i, &ch[i])) {
+	    xf86DestroyI2CDevRec(&sdvo->d, 0);
 	    xfree(sdvo);
 	    return NULL;
 	}
diff-tree 2909802de63756972b38651a496b4ff1b36ac8a2 (from 132dc0599cf44389c4cc03919f1da8d3a0762b44)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Wed Apr 19 16:29:06 2006 -0700

    Clean up SDVO initialization, include config.h, and make it check the right
    slave address on the first device as well.  This gets me to the point of
    bringing up some modes on my device.

diff --git a/src/i830.h b/src/i830.h
index fa1f017..08eae70 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -189,9 +189,9 @@ struct _I830DVODriver {
 };
 
 typedef struct _I830SDVODriver {
-   int found;
    I2CDevRec d;
    unsigned char sdvo_regs[20];
+   CARD32 output_device;		/* SDVOB or SDVOC */
 } I830SDVORec, *I830SDVOPtr;
 
 struct _I830OutputRec {
diff --git a/src/i830_display.c b/src/i830_display.c
index 6fef425..f8bd0d8 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -592,7 +592,7 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
     }
 
     for (i = 0; i < pI830->num_outputs; i++) {
-	if (pI830->output[i].sdvo_drv && pI830->output[i].sdvo_drv->found)
+	if (pI830->output[i].sdvo_drv)
 	    I830SDVOPreSetMode(pI830->output[i].sdvo_drv, pMode);
     }
 
@@ -607,7 +607,7 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
 	    goto done;
     }
     for (i = 0; i < pI830->num_outputs; i++) {
-	if (pI830->output[i].sdvo_drv && pI830->output[i].sdvo_drv->found)
+	if (pI830->output[i].sdvo_drv)
 	    I830SDVOPostSetMode(pI830->output[i].sdvo_drv, pMode);
     }
 
diff --git a/src/i830_display.h b/src/i830_display.h
index 9f07ba1..aecf8dc 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -32,7 +32,7 @@ void i830SetLVDSPanelPower(ScrnInfoPtr p
 void i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y);
 
 /* i830_sdvo.c */
-I830SDVOPtr I830SDVOInit(I2CBusPtr b);
-Bool I830I2CDetectSDVOController(ScrnInfoPtr pScrn, int output_index);
+I830SDVOPtr I830SDVOInit(ScrnInfoPtr pScrn, int output_index,
+			 CARD32 output_device);
 Bool I830SDVOPreSetMode(I830SDVOPtr s, DisplayModePtr mode);
 Bool I830SDVOPostSetMode(I830SDVOPtr s, DisplayModePtr mode);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 591605a..61cc231 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1339,7 +1339,6 @@ I830SetupOutputBusses(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
    int i = 0;
-   Bool ret;
 
    /* everyone has at least a single analog output */
    pI830->output[i].type = I830_OUTPUT_ANALOG;
@@ -1376,21 +1375,13 @@ I830SetupOutputBusses(ScrnInfoPtr pScrn)
       /* Set up SDVOB */
       pI830->output[i].type = I830_OUTPUT_SDVO;
       I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "SDVOCTRL_E");
-
-      pI830->output[i].sdvo_drv = I830SDVOInit(pI830->output[i].pI2CBus);
-      ret = I830I2CDetectSDVOController(pScrn, i);
-      if (ret == TRUE)
-	 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found sDVOB\n");
+      I830SDVOInit(pScrn, i, SDVOB);
       i++;
 
       /* Set up SDVOC */
       pI830->output[i].type = I830_OUTPUT_SDVO;
       I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "SDVOCTRL_E");
-
-      pI830->output[i].sdvo_drv = I830SDVOInit(pI830->output[i].pI2CBus);
-      ret = I830I2CDetectSDVOController(pScrn, i);
-      if (ret == TRUE)
-	 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found sDVOC\n");
+      I830SDVOInit(pScrn, i, SDVOC);
       i++;
       break;
    }
@@ -1471,7 +1462,7 @@ void I830DetectMonitors(ScrnInfoPtr pScr
 #endif
       break;
       case I830_OUTPUT_SDVO:
-	 if (pI830->output[i].sdvo_drv->found) {
+	 if (pI830->output[i].sdvo_drv != NULL) {
 #if 0
 	    I830SDVOSetupDDC(pI830->output[i].sdvo_drv);
 
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index b656bc6..bbf2b93 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -23,6 +23,9 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 **************************************************************************/
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
 #include "xf86.h"
 #include "xf86_ansic.h"
 #include "xf86_OSproc.h"
@@ -530,49 +533,43 @@ I830SDVOPostSetMode(I830SDVOPtr s, Displ
 }
 
 I830SDVOPtr
-I830SDVOInit(I2CBusPtr b)
+I830SDVOInit(ScrnInfoPtr pScrn, int output_index, CARD32 output_device)
 {
+    I830Ptr pI830 = I830PTR(pScrn);
     I830SDVOPtr sdvo;
+    int i;
+    unsigned char ch[0x40];
 
     sdvo = xcalloc(1, sizeof(I830SDVORec));
     if (sdvo == NULL)
 	return NULL;
 
     sdvo->d.DevName = "SDVO Controller";
-    sdvo->d.SlaveAddr = 0x39 << 1;
-    sdvo->d.pI2CBus = b;
-    sdvo->d.StartTimeout = b->StartTimeout;
-    sdvo->d.BitTimeout = b->BitTimeout;
-    sdvo->d.AcknTimeout = b->AcknTimeout;
-    sdvo->d.ByteTimeout = b->ByteTimeout;
+    if (output_device == SDVOB)
+	sdvo->d.SlaveAddr = 0x70;
+    else
+	sdvo->d.SlaveAddr = 0x72;
+    sdvo->d.pI2CBus = pI830->output[output_index].pI2CBus;
     sdvo->d.DriverPrivate.ptr = sdvo;
+    sdvo->output_device = output_device;
 
     if (!xf86I2CDevInit(&sdvo->d)) {
-	xf86DrvMsg(b->scrnIndex, X_ERROR,
-		   "Failed to initialize SDVO I2C device\n");
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "Failed to initialize SDVO I2C device %s\n",
+		   output_device == SDVOB ? "SDVOB" : "SDVOC");
 	xfree(sdvo);
 	return NULL;
     }
-    return sdvo;
-}
-
-Bool
-I830I2CDetectSDVOController(ScrnInfoPtr pScrn, int output_index)
-{
-    I830Ptr pI830 = I830PTR(pScrn);
-    unsigned char ch[64];
-    int i;
-    I830SDVOPtr sdvo = pI830->output[output_index].sdvo_drv;
-
-    if (sdvo == NULL)
-	return FALSE;
 
+    /* Read the regs to test if we can talk to the device */
     for (i = 0; i < 0x40; i++) {
-	if (!sReadByte(sdvo, i, &ch[i]))
-	    return FALSE;
+	if (!sReadByte(sdvo, i, &ch[i])) {
+	    xfree(sdvo);
+	    return NULL;
+	}
     }
 
-    pI830->output[output_index].sdvo_drv->found = 1;
+    pI830->output[output_index].sdvo_drv = sdvo;
 
-    return TRUE;
+    return sdvo;
 }
diff-tree 32a0ad570d9c010e7d26d980830f719782d9f2f3 (from a371a04a57620b7128e3c4395bc7c2ac55effe19)
Author: Lukáš Hejtmanek <xhejtman at mail.muni.cz>
Date:   Wed Apr 19 19:43:45 2006 -0300

    Add  more registers to save/restore. Save/restore palette as well

diff --git a/.gitignore b/.gitignore
index c7bcbee..094379b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@ Makefile
 Makefile.in
 *.la
 *.lo
+*.o
 aclocal.m4
 autom4te.cache
 compile
diff --git a/src/i810_reg.h b/src/i810_reg.h
index 92d9cf9..14327eb 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -681,6 +681,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define PP_CONTROL	0x61204
 # define POWER_TARGET_ON			(1 << 0)
 
+#define LVDSPP_ON       0x61208
+#define LVDSPP_OFF      0x6120c
+#define PP_CYCLE        0x61210
+
 #define PFIT_CONTROL	0x61230
 # define PFIT_ENABLE				(1 << 31)
 # define VERT_INTERP_DISABLE			(0 << 10)
diff --git a/src/i830.h b/src/i830.h
index babbe08..9fe7099 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -481,7 +481,18 @@ typedef struct _I830Rec {
    CARD32 saveVCLK_POST_DIV;
    CARD32 saveVGACNTRL;
    CARD32 saveADPA;
+   CARD32 saveLVDS;
+   CARD32 saveDVOA;
+   CARD32 saveDVOB;
+   CARD32 saveDVOC;
+   CARD32 savePP_ON;
+   CARD32 savePP_OFF;
+   CARD32 savePP_CONTROL;
+   CARD32 savePP_CYCLE;
    CARD32 savePFIT_CONTROL;
+   CARD32 savePaletteA[256];
+   CARD32 savePaletteB[256];
+   CARD32 saveSWF[17];
 
 } I830Rec;
 
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 8930db0..37829e9 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3201,6 +3201,7 @@ SaveHWState(ScrnInfoPtr pScrn)
    vgaHWPtr hwp = VGAHWPTR(pScrn);
    vgaRegPtr vgaReg = &hwp->SavedReg;
    CARD32 temp;
+   int i;
 
    /*
     * Print out the PIPEACONF and PIPEBCONF registers.
@@ -3218,11 +3219,8 @@ SaveHWState(ScrnInfoPtr pScrn)
 
    /* Save video mode information for native mode-setting. */
    pI830->saveDSPACNTR = INREG(DSPACNTR);
-   pI830->saveDSPBCNTR = INREG(DSPBCNTR);
    pI830->savePIPEACONF = INREG(PIPEACONF);
-   pI830->savePIPEBCONF = INREG(PIPEBCONF);
    pI830->savePIPEASRC = INREG(PIPEASRC);
-   pI830->savePIPEBSRC = INREG(PIPEBSRC);
    pI830->saveFPA0 = INREG(FPA0);
    pI830->saveFPA1 = INREG(FPA1);
    pI830->saveDPLL_A = INREG(DPLL_A);
@@ -3237,19 +3235,31 @@ SaveHWState(ScrnInfoPtr pScrn)
    pI830->saveDSPAPOS = INREG(DSPAPOS);
    pI830->saveDSPABASE = INREG(DSPABASE);
 
-   pI830->saveFPB0 = INREG(FPB0);
-   pI830->saveFPB1 = INREG(FPB1);
-   pI830->saveDPLL_B = INREG(DPLL_B);
-   pI830->saveHTOTAL_B = INREG(HTOTAL_B);
-   pI830->saveHBLANK_B = INREG(HBLANK_B);
-   pI830->saveHSYNC_B = INREG(HSYNC_B);
-   pI830->saveVTOTAL_B = INREG(VTOTAL_B);
-   pI830->saveVBLANK_B = INREG(VBLANK_B);
-   pI830->saveVSYNC_B = INREG(VSYNC_B);
-   pI830->saveDSPBSTRIDE = INREG(DSPBSTRIDE);
-   pI830->saveDSPBSIZE = INREG(DSPBSIZE);
-   pI830->saveDSPBPOS = INREG(DSPBPOS);
-   pI830->saveDSPBBASE = INREG(DSPBBASE);
+   for(i= 0; i < 256; i++) {
+      pI830->savePaletteA[i] = INREG(PALETTE_A + (i << 2));
+   }
+
+   if(pI830->availablePipes == 2) {
+      pI830->savePIPEBCONF = INREG(PIPEBCONF);
+      pI830->savePIPEBSRC = INREG(PIPEBSRC);
+      pI830->saveDSPBCNTR = INREG(DSPBCNTR);
+      pI830->saveFPB0 = INREG(FPB0);
+      pI830->saveFPB1 = INREG(FPB1);
+      pI830->saveDPLL_B = INREG(DPLL_B);
+      pI830->saveHTOTAL_B = INREG(HTOTAL_B);
+      pI830->saveHBLANK_B = INREG(HBLANK_B);
+      pI830->saveHSYNC_B = INREG(HSYNC_B);
+      pI830->saveVTOTAL_B = INREG(VTOTAL_B);
+      pI830->saveVBLANK_B = INREG(VBLANK_B);
+      pI830->saveVSYNC_B = INREG(VSYNC_B);
+      pI830->saveDSPBSTRIDE = INREG(DSPBSTRIDE);
+      pI830->saveDSPBSIZE = INREG(DSPBSIZE);
+      pI830->saveDSPBPOS = INREG(DSPBPOS);
+      pI830->saveDSPBBASE = INREG(DSPBBASE);
+      for(i= 0; i < 256; i++) {
+         pI830->savePaletteB[i] = INREG(PALETTE_B + (i << 2));
+      }
+   }
 
    pI830->saveVCLK_DIVISOR_VGA0 = INREG(VCLK_DIVISOR_VGA0);
    pI830->saveVCLK_DIVISOR_VGA1 = INREG(VCLK_DIVISOR_VGA1);
@@ -3259,6 +3269,23 @@ SaveHWState(ScrnInfoPtr pScrn)
    pI830->saveADPA = INREG(ADPA);
 
    pI830->savePFIT_CONTROL = INREG(PFIT_CONTROL);
+   pI830->savePP_ON = INREG(LVDSPP_ON);
+   pI830->savePP_OFF = INREG(LVDSPP_OFF);
+   pI830->saveLVDS = INREG(LVDS);
+   pI830->savePP_CONTROL = INREG(PP_CONTROL);
+   pI830->savePP_CYCLE = INREG(PP_CYCLE);
+
+   pI830->saveDVOA = INREG(DVOA);
+   pI830->saveDVOB = INREG(DVOB);
+   pI830->saveDVOC = INREG(DVOC);
+
+   for(i = 0; i < 7; i++) {
+      pI830->saveSWF[i] = INREG(SWF0 + (i << 2));
+      pI830->saveSWF[i+7] = INREG(SWF00 + (i << 2));
+   }
+   pI830->saveSWF[14] = INREG(SWF30);
+   pI830->saveSWF[15] = INREG(SWF31);
+   pI830->saveSWF[16] = INREG(SWF32);
    
    vgaHWUnlock(hwp);
    vgaHWSave(pScrn, vgaReg, VGA_SR_ALL);
@@ -3273,6 +3300,7 @@ RestoreHWState(ScrnInfoPtr pScrn)
    vgaHWPtr hwp = VGAHWPTR(pScrn);
    vgaRegPtr vgaReg = &hwp->SavedReg;
    CARD32 temp;
+   int i;
 
    DPRINTF(PFX, "RestoreHWState\n");
 
@@ -3294,6 +3322,8 @@ RestoreHWState(ScrnInfoPtr pScrn)
    /* XXX: Wait for a vblank */
    sleep(1);
 
+   i830SetLVDSPanelPower(pScrn, FALSE);
+
    OUTREG(FPA0, pI830->saveFPA0);
    OUTREG(FPA1, pI830->saveFPA1);
    OUTREG(DPLL_A, pI830->saveDPLL_A);
@@ -3308,22 +3338,33 @@ RestoreHWState(ScrnInfoPtr pScrn)
    OUTREG(DSPAPOS, pI830->saveDSPAPOS);
    OUTREG(DSPABASE, pI830->saveDSPABASE);
    OUTREG(PIPEASRC, pI830->savePIPEASRC);
+   for(i = 0; i < 256; i++) {
+         OUTREG(PALETTE_A + (i << 2), pI830->savePaletteA[i]);
+   }
 
-   OUTREG(FPB0, pI830->saveFPB0);
-   OUTREG(FPB1, pI830->saveFPB1);
-   OUTREG(DPLL_B, pI830->saveDPLL_B);
-   OUTREG(HTOTAL_B, pI830->saveHTOTAL_B);
-   OUTREG(HBLANK_B, pI830->saveHBLANK_B);
-   OUTREG(HSYNC_B, pI830->saveHSYNC_B);
-   OUTREG(VTOTAL_B, pI830->saveVTOTAL_B);
-   OUTREG(VBLANK_B, pI830->saveVBLANK_B);
-   OUTREG(VSYNC_B, pI830->saveVSYNC_B);
-   OUTREG(DSPBSTRIDE, pI830->saveDSPBSTRIDE);
-   OUTREG(DSPBSIZE, pI830->saveDSPBSIZE);
-   OUTREG(DSPBPOS, pI830->saveDSPBPOS);
-   OUTREG(DSPBBASE, pI830->saveDSPBBASE);
-   OUTREG(PIPEBSRC, pI830->savePIPEBSRC);
+   if(pI830->availablePipes == 2) {
+      OUTREG(FPB0, pI830->saveFPB0);
+      OUTREG(FPB1, pI830->saveFPB1);
+      OUTREG(DPLL_B, pI830->saveDPLL_B);
+      OUTREG(HTOTAL_B, pI830->saveHTOTAL_B);
+      OUTREG(HBLANK_B, pI830->saveHBLANK_B);
+      OUTREG(HSYNC_B, pI830->saveHSYNC_B);
+      OUTREG(VTOTAL_B, pI830->saveVTOTAL_B);
+      OUTREG(VBLANK_B, pI830->saveVBLANK_B);
+      OUTREG(VSYNC_B, pI830->saveVSYNC_B);
+      OUTREG(DSPBSTRIDE, pI830->saveDSPBSTRIDE);
+      OUTREG(DSPBSIZE, pI830->saveDSPBSIZE);
+      OUTREG(DSPBPOS, pI830->saveDSPBPOS);
+      OUTREG(DSPBBASE, pI830->saveDSPBBASE);
+      OUTREG(PIPEBSRC, pI830->savePIPEBSRC);
+      for(i= 0; i < 256; i++) {
+         OUTREG(PALETTE_B + (i << 2), pI830->savePaletteB[i]);
+      }
+   }
 
+   OUTREG(LVDSPP_ON, pI830->savePP_ON);
+   OUTREG(LVDSPP_OFF, pI830->savePP_OFF);
+   OUTREG(PP_CYCLE, pI830->savePP_CYCLE);
    OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL);
    
    OUTREG(VCLK_DIVISOR_VGA0, pI830->saveVCLK_DIVISOR_VGA0);
@@ -3338,6 +3379,20 @@ RestoreHWState(ScrnInfoPtr pScrn)
    OUTREG(DSPBCNTR, pI830->saveDSPBCNTR);
 
    OUTREG(ADPA, pI830->saveADPA);
+   OUTREG(LVDS, pI830->saveLVDS);
+   OUTREG(DVOA, pI830->saveDVOA);
+   OUTREG(DVOB, pI830->saveDVOB);
+   OUTREG(DVOC, pI830->saveDVOC);
+   OUTREG(PP_CONTROL, pI830->savePP_CONTROL);
+
+   for(i = 0; i < 7; i++) {
+	   OUTREG(SWF0 + (i << 2), pI830->saveSWF[i]);
+	   OUTREG(SWF00 + (i << 2), pI830->saveSWF[i+7]);
+   }
+
+   OUTREG(SWF30, pI830->saveSWF[14]);
+   OUTREG(SWF31, pI830->saveSWF[15]);
+   OUTREG(SWF32, pI830->saveSWF[16]);
 
    i830CompareRegsToSnapshot(pScrn);
 
diff-tree 132dc0599cf44389c4cc03919f1da8d3a0762b44 (from 88bb4b578857588f34ac84b7a20577139eccab6d)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Wed Apr 19 15:04:17 2006 -0700

    Whine if SDVO I2C device init fails, rather than be silent.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 3b3efa1..b656bc6 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -547,13 +547,13 @@ I830SDVOInit(I2CBusPtr b)
     sdvo->d.ByteTimeout = b->ByteTimeout;
     sdvo->d.DriverPrivate.ptr = sdvo;
 
-    if (!xf86I2CDevInit(&sdvo->d))
-	goto out;
+    if (!xf86I2CDevInit(&sdvo->d)) {
+	xf86DrvMsg(b->scrnIndex, X_ERROR,
+		   "Failed to initialize SDVO I2C device\n");
+	xfree(sdvo);
+	return NULL;
+    }
     return sdvo;
-
-out:
-    xfree(sdvo);
-    return NULL;
 }
 
 Bool
diff-tree 88bb4b578857588f34ac84b7a20577139eccab6d (from d8f7dfac769d7b03f069306b1296bb2e1e08b009)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Wed Apr 19 14:23:45 2006 -0700

    Add more SDVO code.  It's taken from airlied's driver, but with magic numbers
    replaced by symbolic names in many places.  I tried to restrain myself from
    functional changes in airlied's code in this pass.

diff --git a/src/i830.h b/src/i830.h
index a631258..fa1f017 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -580,10 +580,6 @@ extern Bool I830RandRInit(ScreenPtr pScr
 extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg,
 			char *name);
 
-/* i830_sdvo.c */
-extern I830SDVOPtr I830SDVOInit(I2CBusPtr b);
-extern Bool I830I2CDetectSDVOController(ScrnInfoPtr pScrn, int output_index);
-
 /*
  * 12288 is set as the maximum, chosen because it is enough for
  * 1920x1440 at 32bpp with a 2048 pixel line pitch with some to spare.
diff --git a/src/i830_display.c b/src/i830_display.c
index fd3c352..6fef425 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -571,6 +571,7 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
 #ifdef XF86DRI
     Bool didLock = FALSE;
 #endif
+    int i;
 
     DPRINTF(PFX, "i830SetMode\n");
 
@@ -590,6 +591,11 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
 	pI830->planeEnabled[1] = 0;
     }
 
+    for (i = 0; i < pI830->num_outputs; i++) {
+	if (pI830->output[i].sdvo_drv && pI830->output[i].sdvo_drv->found)
+	    I830SDVOPreSetMode(pI830->output[i].sdvo_drv, pMode);
+    }
+
     if (pI830->planeEnabled[0]) {
 	ok = i830PipeSetMode(pScrn, pMode, 0);
 	if (!ok)
@@ -600,6 +606,10 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
 	if (!ok)
 	    goto done;
     }
+    for (i = 0; i < pI830->num_outputs; i++) {
+	if (pI830->output[i].sdvo_drv && pI830->output[i].sdvo_drv->found)
+	    I830SDVOPostSetMode(pI830->output[i].sdvo_drv, pMode);
+    }
 
     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Mode bandwidth is %d Mpixel/s\n",
 	       (int)(pMode->HDisplay * pMode->VDisplay *
diff --git a/src/i830_display.h b/src/i830_display.h
index d8e4e5e..9f07ba1 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -25,7 +25,14 @@
  *
  */
 
+/* i830_display.c */
 Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
 Bool i830DetectCRT(ScrnInfoPtr pScrn);
 void i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on);
 void i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y);
+
+/* i830_sdvo.c */
+I830SDVOPtr I830SDVOInit(I2CBusPtr b);
+Bool I830I2CDetectSDVOController(ScrnInfoPtr pScrn, int output_index);
+Bool I830SDVOPreSetMode(I830SDVOPtr s, DisplayModePtr mode);
+Bool I830SDVOPostSetMode(I830SDVOPtr s, DisplayModePtr mode);
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 7f5549c..3b3efa1 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -28,6 +28,9 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "xf86_OSproc.h"
 #include "compiler.h"
 #include "i830.h"
+#include "i830_sdvo_regs.h"
+
+CARD16 curr_table[6];
 
 /* SDVO support for i9xx chipsets */
 static Bool sReadByte(I830SDVOPtr s, int addr, unsigned char *ch)
@@ -41,7 +44,6 @@ static Bool sReadByte(I830SDVOPtr s, int
     return TRUE;
 }
 
-#if 0
 static Bool sWriteByte(I830SDVOPtr s, int addr, unsigned char ch)
 {
     if (!xf86I2CWriteByte(&s->d, addr, ch)) {
@@ -52,8 +54,481 @@ static Bool sWriteByte(I830SDVOPtr s, in
     }
     return TRUE;
 }
+
+/* following on from tracing the intel BIOS i2c routines */
+static void
+I830SDVOWriteOutputs(I830SDVOPtr s, int num_out)
+{
+    int i;
+
+    ErrorF("SDVO: W: ");
+    for (i = num_out; i <= SDVO_I2C_ARG_0; i++)
+	ErrorF("%02X ", s->sdvo_regs[i]);
+    ErrorF("\n");
+
+    /* blast the output regs */
+    for (i = SDVO_I2C_ARG_0; i >= num_out; i--) {
+	sWriteByte(s, i, s->sdvo_regs[i]);
+    }
+    /* blast the command reg */
+    sWriteByte(s, SDVO_I2C_OPCODE, s->sdvo_regs[SDVO_I2C_OPCODE]);
+}
+
+static void
+I830SDVOReadInputRegs(I830SDVOPtr s)
+{
+    int i;
+
+    /* follow BIOS ordering */
+    sReadByte(s, SDVO_I2C_CMD_STATUS, &s->sdvo_regs[SDVO_I2C_CMD_STATUS]);
+  
+    sReadByte(s, SDVO_I2C_RETURN_3, &s->sdvo_regs[SDVO_I2C_RETURN_3]);
+    sReadByte(s, SDVO_I2C_RETURN_2, &s->sdvo_regs[SDVO_I2C_RETURN_2]);
+    sReadByte(s, SDVO_I2C_RETURN_1, &s->sdvo_regs[SDVO_I2C_RETURN_1]);
+    sReadByte(s, SDVO_I2C_RETURN_0, &s->sdvo_regs[SDVO_I2C_RETURN_0]);
+    sReadByte(s, SDVO_I2C_RETURN_7, &s->sdvo_regs[SDVO_I2C_RETURN_7]);
+    sReadByte(s, SDVO_I2C_RETURN_6, &s->sdvo_regs[SDVO_I2C_RETURN_6]);
+    sReadByte(s, SDVO_I2C_RETURN_5, &s->sdvo_regs[SDVO_I2C_RETURN_5]);
+    sReadByte(s, SDVO_I2C_RETURN_4, &s->sdvo_regs[SDVO_I2C_RETURN_4]);
+
+    ErrorF("SDVO: R: ");
+    for (i = SDVO_I2C_CMD_STATUS; i <= SDVO_I2C_RETURN_7; i++)
+	ErrorF("%02X ", s->sdvo_regs[i]);
+    ErrorF("\n");
+}
+
+Bool
+I830SDVOSetupDDC(I830SDVOPtr s, int enable)
+{
+    memset(s->sdvo_regs, 0, 9);
+
+    s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_CONTROL_BUS_SWITCH;
+    s->sdvo_regs[SDVO_I2C_ARG_0] = SDVO_CONTROL_BUS_DDC2;
+
+    I830SDVOWriteOutputs(s, 7);
+
+    sReadByte(s, SDVO_I2C_CMD_STATUS, &s->sdvo_regs[SDVO_I2C_CMD_STATUS]);
+
+    ErrorF("SDVO: R: ");
+    ErrorF("%02X ", s->sdvo_regs[SDVO_I2C_CMD_STATUS]);
+    ErrorF("\n");
+    return TRUE;
+}
+
+static Bool
+I830SDVOSetTargetInput(I830SDVOPtr s)
+{
+    /* write out 0x10 */
+    memset(s->sdvo_regs, 0, 9);
+
+    s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_TARGET_INPUT;
+
+    I830SDVOWriteOutputs(s, 0);
+
+    I830SDVOReadInputRegs(s);
+
+    return TRUE;
+}
+
+static Bool
+I830SDVOGetTrainedInputs(I830SDVOPtr s, int on)
+{
+    memset(s->sdvo_regs, 0, 9);
+
+    s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_TRAINED_INPUTS;
+
+    /* XXX: I don't believe we need to set anything here --anholt */
+    s->sdvo_regs[0x07] = on ? 0x80 : 0x00;
+    s->sdvo_regs[0x04] = on ? 0x80 : 0x00;
+
+    I830SDVOWriteOutputs(s, 0);
+    I830SDVOReadInputRegs(s);
+
+    return TRUE;
+}
+
+static Bool
+I830SDVOGetActiveOutputs(I830SDVOPtr s, int on)
+{
+    memset(s->sdvo_regs, 0, 9);
+
+    s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_ACTIVE_OUTPUTS;
+
+    s->sdvo_regs[0x07] = on ? 0x01 : 0x00;
+    s->sdvo_regs[0x03] = 0x1;
+
+    I830SDVOWriteOutputs(s, 0);
+    I830SDVOReadInputRegs(s);
+
+    return TRUE;
+}
+
+static Bool
+I830SDVOSetActiveOutputs(I830SDVOPtr s, int on)
+{
+    memset(s->sdvo_regs, 0, 9);
+
+    s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_ACTIVE_OUTPUTS;
+
+    /* XXX: This should be touching args 0,1, I believe.  --anholt */
+    s->sdvo_regs[0x07] = on ? 0x01 : 0x00;
+    s->sdvo_regs[0x03] = on ? 0x01 : 0x00;
+
+    I830SDVOWriteOutputs(s, 0);
+    I830SDVOReadInputRegs(s);
+
+    return TRUE;
+}
+
+static Bool
+I830SDVOGetInputPixelClockRange(I830SDVOPtr s, CARD16 clock, CARD16 height)
+{
+    memset(s->sdvo_regs, 0, 9);
+
+    s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE;
+
+    /* XXX: SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE shouldn't be taking args. */
+
+    /* set clock regs */
+    s->sdvo_regs[0x06] = (clock >> 8) & 0xff;
+    s->sdvo_regs[0x07] = clock & 0xff;
+
+    /* set height regs */
+    s->sdvo_regs[0x02] = (height >> 8) & 0xff;
+    s->sdvo_regs[0x03] = height & 0xff;
+
+    I830SDVOWriteOutputs(s, 0);
+    I830SDVOReadInputRegs(s);
+
+    return TRUE;
+}
+
+static Bool
+I830SDVOSetTargetOutput(I830SDVOPtr s)
+{
+    memset(s->sdvo_regs, 0, 9);
+
+    s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_TARGET_OUTPUT;
+
+    s->sdvo_regs[SDVO_I2C_ARG_0] = 0x1;	/* Enable */
+    s->sdvo_regs[SDVO_I2C_ARG_1] = 0x0; /* Disable */
+
+    I830SDVOWriteOutputs(s, 0);		/* XXX: Only write these two */
+    I830SDVOReadInputRegs(s);
+
+    return TRUE;
+}
+
+#if 0
+static Bool
+I830SDVOGetOutputTimingsPart1(I830SDVOPtr s)
+{
+    memset(s->sdvo_regs, 0, 9);
+
+    s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_OUTPUT_TIMINGS_PART1;
+
+    /* XXX: No args */
+    s->sdvo_regs[0x07] = 0x0;
+
+    I830SDVOWriteOutputs(s, 0);
+    I830SDVOReadInputRegs(s);
+  
+    return TRUE;
+}
+
+static Bool
+I830SDVOGetOutputTimingsPart2(I830SDVOPtr s)
+{
+    memset(s->sdvo_regs, 0, 9);
+
+    s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_OUTPUT_TIMINGS_PART2;
+
+    /* XXX: No args */
+    s->sdvo_regs[0x07] = 0x0;
+
+    I830SDVOWriteOutputs(s, 0);
+    I830SDVOReadInputRegs(s);
+
+    return TRUE;
+}
 #endif
 
+static Bool
+I830SDVOSetTimingsPart1(I830SDVOPtr s, char cmd, CARD16 clock, CARD16 magic1,
+			CARD16 magic2, CARD16 magic3)
+{
+    memset(s->sdvo_regs, 0, 9);
+
+    s->sdvo_regs[SDVO_I2C_OPCODE] = cmd;
+
+    /* set clock regs */
+    s->sdvo_regs[SDVO_I2C_ARG_0] = clock & 0xff;
+    s->sdvo_regs[SDVO_I2C_ARG_1] = (clock >> 8) & 0xff;
+    s->sdvo_regs[SDVO_I2C_ARG_2] = magic3 & 0xff;  
+    s->sdvo_regs[SDVO_I2C_ARG_3] = (magic3 >> 8) & 0xff;
+    s->sdvo_regs[SDVO_I2C_ARG_4] = magic2 & 0xff;  
+    s->sdvo_regs[SDVO_I2C_ARG_5] = (magic2 >> 8) & 0xff;
+    s->sdvo_regs[SDVO_I2C_ARG_6] = magic1 & 0xff;
+    s->sdvo_regs[SDVO_I2C_ARG_7] = (magic1 >> 8) & 0xff;
+
+    I830SDVOWriteOutputs(s, 0);
+    I830SDVOReadInputRegs(s);
+  
+    return TRUE;
+}
+
+static Bool
+I830SDVOSetInputTimingsPart1(I830SDVOPtr s, CARD16 clock,
+			     CARD16 magic1, CARD16 magic2, CARD16 magic3)
+{
+    return I830SDVOSetTimingsPart1(s, SDVO_CMD_SET_INPUT_TIMINGS_PART1,
+				   clock, magic1, magic2, magic3);
+}
+
+static Bool
+I830SDVOSetOutputTimingsPart1(I830SDVOPtr s, CARD16 clock, CARD16 magic1,
+			      CARD16 magic2, CARD16 magic3)
+{
+    return I830SDVOSetTimingsPart1(s, SDVO_CMD_SET_OUTPUT_TIMINGS_PART1,
+				   clock, magic1, magic2, magic3);
+}
+
+static Bool
+I830SDVOGetPreferredInputTimingPart2(I830SDVOPtr s, CARD16 clock,
+				     CARD16 magic1, CARD16 magic2,
+				     CARD16 magic3)
+{
+    Bool ok;
+
+    /* XXX: This is a rather different command */
+    ok = I830SDVOSetTimingsPart1(s, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2,
+				 clock, magic1, magic2, magic3);
+
+    curr_table[3] = s->sdvo_regs[SDVO_I2C_RETURN_0] |
+		    (s->sdvo_regs[SDVO_I2C_RETURN_1] << 8);
+    curr_table[4] = s->sdvo_regs[SDVO_I2C_RETURN_2] |
+		    (s->sdvo_regs[SDVO_I2C_RETURN_3] << 8);
+    curr_table[5] = 0x1e;
+
+    return ok;
+}
+
+static Bool
+I830SDVOSetTimingsPart2(I830SDVOPtr s, CARD8 cmd, CARD16 magic4, CARD16 magic5,
+			CARD16 magic6)
+{
+    memset(s->sdvo_regs, 0, 9);
+  
+    s->sdvo_regs[SDVO_I2C_OPCODE] = cmd;
+ 
+    /* set clock regs */
+    s->sdvo_regs[SDVO_I2C_ARG_0] = magic4 & 0xff;
+    s->sdvo_regs[SDVO_I2C_ARG_1] = (magic4 >> 8) & 0xff;
+    s->sdvo_regs[SDVO_I2C_ARG_2] = magic5 & 0xff;
+    s->sdvo_regs[SDVO_I2C_ARG_3] = (magic5 >> 8) & 0xff;
+    s->sdvo_regs[SDVO_I2C_ARG_4] = magic6 & 0xff;
+    s->sdvo_regs[SDVO_I2C_ARG_5] = (magic6 >> 8) & 0xff;
+
+    I830SDVOWriteOutputs(s, 0);
+    I830SDVOReadInputRegs(s);
+  
+    return TRUE;
+}
+
+static Bool
+I830SDVOSetInputTimingsPart2(I830SDVOPtr s, CARD16 magic4, CARD16 magic5,
+			     CARD16 magic6)
+{
+    return I830SDVOSetTimingsPart2(s, SDVO_CMD_SET_INPUT_TIMINGS_PART2, magic4,
+				   magic5, magic6);
+}
+
+static Bool
+I830SDVOSetOutputTimingsPart2(I830SDVOPtr s, CARD16 magic4, CARD16 magic5,
+			      CARD16 magic6)
+{
+    return I830SDVOSetTimingsPart2(s, SDVO_CMD_SET_OUTPUT_TIMINGS_PART2, magic4,
+				   magic5, magic6);
+}
+
+static Bool
+I830SDVOCreatePreferredInputTiming(I830SDVOPtr s, CARD16 clock, CARD16 width,
+				   CARD16 height)
+{
+    memset(s->sdvo_regs, 0, 9);
+
+    s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING;
+
+    s->sdvo_regs[SDVO_I2C_ARG_0] = clock & 0xff;
+    s->sdvo_regs[SDVO_I2C_ARG_1] = (clock >> 8) & 0xff;
+    s->sdvo_regs[SDVO_I2C_ARG_2] = width & 0xff;
+    s->sdvo_regs[SDVO_I2C_ARG_3] = (width >> 8) & 0xff;
+    s->sdvo_regs[SDVO_I2C_ARG_4] = (height >> 8) & 0xff;
+    s->sdvo_regs[SDVO_I2C_ARG_5] = height & 0xff;  
+
+    I830SDVOWriteOutputs(s, 0);
+    I830SDVOReadInputRegs(s);
+
+    return TRUE;
+}
+
+static Bool
+I830SDVOGetPreferredInputTimingPart1(I830SDVOPtr s)
+{
+    memset(s->sdvo_regs, 0, 9);
+
+    s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1;
+
+    I830SDVOWriteOutputs(s, 0);
+    I830SDVOReadInputRegs(s);
+
+    curr_table[0] = s->sdvo_regs[SDVO_I2C_RETURN_6] |
+		    (s->sdvo_regs[SDVO_I2C_RETURN_7] << 8);
+    curr_table[1] = s->sdvo_regs[SDVO_I2C_RETURN_4] |
+		    (s->sdvo_regs[SDVO_I2C_RETURN_5] << 8);
+    curr_table[2] = s->sdvo_regs[SDVO_I2C_RETURN_2] |
+		    (s->sdvo_regs[SDVO_I2C_RETURN_3] << 8);
+
+    return TRUE;
+}
+
+static Bool
+I830SDVOSetClockRateMult(I830SDVOPtr s, CARD8 val)
+{
+    memset(s->sdvo_regs, 0, 9);
+
+    s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_CLOCK_RATE_MULT;
+
+    s->sdvo_regs[SDVO_I2C_ARG_0] = val;
+    I830SDVOWriteOutputs(s, 0);
+    I830SDVOReadInputRegs(s);
+
+    return TRUE;
+}
+
+Bool
+I830SDVOPreSetMode(I830SDVOPtr s, DisplayModePtr mode)
+{
+    CARD16 clock = mode->Clock/10, width = mode->CrtcHDisplay;
+    CARD16 height = mode->CrtcVDisplay;
+    CARD16 h_blank_len, h_sync_len, v_blank_len, v_sync_len;
+    CARD16 h_sync_offset, v_sync_offset;
+    CARD16 sync_flags;
+    CARD8 c16a[8];
+    CARD8 c17a[8];
+    CARD16 out_timings[6];
+
+    /* do some mode translations */
+    h_blank_len = mode->CrtcHBlankEnd - mode->CrtcHBlankStart;
+    h_sync_len = mode->CrtcHSyncEnd - mode->CrtcHSyncStart;
+
+    v_blank_len = mode->CrtcVBlankEnd - mode->CrtcVBlankStart;
+    v_sync_len = mode->CrtcVSyncEnd - mode->CrtcVSyncStart;
+
+    h_sync_offset = mode->CrtcHSyncStart - mode->CrtcHBlankStart;
+    v_sync_offset = mode->CrtcVSyncStart - mode->CrtcVBlankStart;
+
+    sync_flags = 0x18;
+    if (mode->Flags & V_PHSYNC)
+	sync_flags |= 0x2;
+    if (mode->Flags & V_PVSYNC)
+	sync_flags |= 0x4;
+    /* high bits of 0 */
+    c16a[7] = clock & 0xff;
+    c16a[6] = (clock >> 8) & 0xff;
+    c16a[5] = (width & 0xff);
+    c16a[4] = (h_blank_len & 0xff);
+    c16a[3] = (((width >> 8) & 0xf) << 4) | ((h_blank_len >> 8) & 0xf);
+    c16a[2] = (height & 0xff);
+    c16a[1] = (v_blank_len & 0xff);
+    c16a[0] = (((height >> 8) & 0xf) << 4) | ((v_blank_len >> 8) & 0xf);
+
+    c17a[7] = h_sync_offset;
+    c17a[6] = h_sync_len & 0xff;
+    c17a[5] = (v_sync_offset & 0xf) << 4 | (v_sync_len & 0xf);
+    c17a[4] = 0;
+    c17a[3] = sync_flags;
+    c17a[2] = 0;
+    out_timings[0] = c16a[1] | ((short)c16a[0] << 8);
+    out_timings[1] = c16a[3] | ((short)c16a[2] << 8);
+    out_timings[2] = c16a[5] | ((short)c16a[4] << 8);
+    out_timings[3] = c17a[7] | ((short)c17a[6] << 8);
+    out_timings[4] = c17a[5] | ((short)c17a[4] << 8);
+    out_timings[5] = c17a[3] | ((short)c17a[2] << 8);
+
+    I830SDVOSetTargetInput(s);
+    I830SDVOGetInputPixelClockRange(s, clock, height);
+
+    I830SDVOGetActiveOutputs(s, 0);
+    I830SDVOSetActiveOutputs(s, 0);
+
+    I830SDVOSetTargetOutput(s);
+    I830SDVOSetOutputTimingsPart1(s, clock, out_timings[0], out_timings[1],
+				  out_timings[2]);
+
+    I830SDVOSetTargetOutput(s);
+    I830SDVOSetOutputTimingsPart2(s, out_timings[3], out_timings[4],
+				  out_timings[5]);
+
+    I830SDVOSetTargetInput(s);
+
+    I830SDVOCreatePreferredInputTiming(s, clock, width, height);
+    I830SDVOSetTargetInput(s);
+
+    I830SDVOGetPreferredInputTimingPart1(s);
+    I830SDVOSetTargetInput(s);
+
+    I830SDVOGetPreferredInputTimingPart2(s, clock, out_timings[0], out_timings[1],
+					 out_timings[2]);
+    I830SDVOSetTargetInput(s);
+
+    I830SDVOSetInputTimingsPart1(s, clock, curr_table[0], curr_table[1],
+				 curr_table[2]);
+
+    I830SDVOSetTargetInput(s);
+    I830SDVOSetInputTimingsPart2(s, curr_table[3], curr_table[4],
+				 out_timings[5]);
+
+    I830SDVOSetTargetInput(s);
+    /*if (mode->PrivFlags & I830_MFLAG_DOUBLE)
+	I830SDVOSetClockRateMult(s, 0x02);
+    else */
+	I830SDVOSetClockRateMult(s, 0x01);
+
+    return TRUE;
+}
+
+Bool
+I830SDVOPostSetMode(I830SDVOPtr s, DisplayModePtr mode)
+{
+    int clock = mode->Clock/10, height=mode->CrtcVDisplay;
+    Bool ret = TRUE;
+
+    /* the BIOS writes out 6 commands post mode set */
+    /* two 03s, 04 05, 10, 1d */
+    /* these contain the height and mode clock / 10 by the looks of it */
+
+    I830SDVOGetTrainedInputs(s, 1);
+    I830SDVOGetTrainedInputs(s, 0);
+
+    /* THIS IS A DIRTY HACK - sometimes for some reason on startup
+     * the BIOS doesn't find my DVI monitor -
+     * without this hack the driver doesn't work.. this causes the modesetting
+     * to be re-run
+     */
+    if (s->sdvo_regs[SDVO_I2C_RETURN_0] != 0x1) {
+	ret = FALSE;
+    }
+
+    I830SDVOGetActiveOutputs(s, 1);
+    I830SDVOSetActiveOutputs(s, 1);
+
+    I830SDVOSetTargetInput(s);
+    I830SDVOGetInputPixelClockRange(s, clock, height);
+
+    return ret;
+}
+
 I830SDVOPtr
 I830SDVOInit(I2CBusPtr b)
 {
@@ -92,7 +567,7 @@ I830I2CDetectSDVOController(ScrnInfoPtr 
     if (sdvo == NULL)
 	return FALSE;
 
-    for (i=0; i<0x40; i++) {
+    for (i = 0; i < 0x40; i++) {
 	if (!sReadByte(sdvo, i, &ch[i]))
 	    return FALSE;
     }
diff --git a/src/i830_sdvo_regs.h b/src/i830_sdvo_regs.h
new file mode 100644
index 0000000..5ad4ac9
--- /dev/null
+++ b/src/i830_sdvo_regs.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
+/* I2C registers for SDVO */
+#define SDVO_I2C_ARG_0				0x07
+#define SDVO_I2C_ARG_1				0x06
+#define SDVO_I2C_ARG_2				0x05
+#define SDVO_I2C_ARG_3				0x04
+#define SDVO_I2C_ARG_4				0x03
+#define SDVO_I2C_ARG_5				0x02
+#define SDVO_I2C_ARG_6				0x01
+#define SDVO_I2C_ARG_7				0x00
+#define SDVO_I2C_OPCODE				0x08
+#define SDVO_I2C_CMD_STATUS			0x09
+#define SDVO_I2C_RETURN_0			0x0a
+#define SDVO_I2C_RETURN_1			0x0b
+#define SDVO_I2C_RETURN_2			0x0c
+#define SDVO_I2C_RETURN_3			0x0d
+#define SDVO_I2C_RETURN_4			0x0e
+#define SDVO_I2C_RETURN_5			0x0f
+#define SDVO_I2C_RETURN_6			0x10
+#define SDVO_I2C_RETURN_7			0x11
+#define SDVO_I2C_VENDOR_BEGIN			0x20
+
+/* Status results */
+#define SDVO_CMD_STATUS_POWER_ON		0x0
+#define SDVO_CMD_STATUS_SUCCESS			0x1
+#define SDVO_CMD_STATUS_NOTSUPP			0x2
+#define SDVO_CMD_STATUS_INVALID_ARG		0x3
+#define SDVO_CMD_STATUS_PENDING			0x4
+#define SDVO_CMD_STATUS_TARGET_NOT_SUPP		0x5
+#define SDVO_CMD_STATUS_SCALING_NOT_SUPP	0x6
+
+/* SDVO commands, argument/result registers */
+#define SDVO_CMD_RESET					0x01
+#define SDVO_CMD_GET_DEVICE_CAPS			0x02
+# define SDVO_DEVICE_CAPS_VENDOR_ID			SDVO_I2C_RETURN_0
+# define SDVO_DEVICE_CAPS_DEVICE_ID			SDVO_I2C_RETURN_1
+# define SDVO_DEVICE_CAPS_DEVICE_REV_ID			SDVO_I2C_RETURN_2
+# define SDVO_DEVICE_CAPS_SDVOVERSION_MINOR		SDVO_I2C_RETURN_3
+# define SDVO_DEVICE_CAPS_SDVOVERSION_MAJOR		SDVO_I2C_RETURN_4
+# define SDVO_DEVICE_CAPS_CAPS				SDVO_I2C_RETURN_5
+# define SDVO_DEVICE_CAPS_INPUTS_MASK				(3 << 0)
+# define SDVO_DEVICE_CAPS_SMOOTH_SCALING			(1 << 2)
+# define SDVO_DEVICE_CAPS_SHARP_SCALING				(1 << 3)
+# define SDVO_DEVICE_CAPS_UP_SCALING				(1 << 4)
+# define SDVO_DEVICE_CAPS_DOWN_SCALING				(1 << 5)
+# define SDVO_DEVICE_CAPS_STALL_SUPPORT				(1 << 6)
+# define SDVO_DEVICE_CAPS_OUTPUT_0_SUPPORTED		SDVO_I2C_RETURN_6
+# define SDVO_DEVICE_CAPS_OUTPUT_1_SUPPORTED		SDVO_I2C_RETURN_7
+
+#define SDVO_CMD_GET_FIRMWARE_REV			0x86
+# define SDVO_DEVICE_FIRMWARE_MINOR			SDVO_I2C_RETURN_0
+# define SDVO_DEVICE_FIRMWARE_MAJOR			SDVO_I2C_RETURN_1
+
+#define SDVO_CMD_GET_TRAINED_INPUTS			0x03
+
+#define SDVO_CMD_GET_ACTIVE_OUTPUTS			0x04
+
+#define SDVO_CMD_SET_ACTIVE_OUTPUTS			0x05
+
+#define SDVO_CMD_GET_IN_OUT_MAP				0x06
+
+#define SDVO_CMD_SET_IN_OUT_MAP				0x07
+
+#define SDVO_CMD_GET_ATTACHED_DISPLAYS			0x0b
+
+#define SDVO_CMD_GET_HOT_PLUG_SUPPORT			0x0c
+
+#define SDVO_CMD_SET_ACTIVE_HOT_PLUG			0x0d
+
+#define SDVO_CMD_GET_ACTIVE_HOT_PLUG			0x0e
+
+#define SDVO_CMD_GET_INTR_EVENT_SOURCE			0x0f
+
+#define SDVO_CMD_SET_TARGET_INPUT			0x10
+
+#define SDVO_CMD_SET_TARGET_OUTPUT			0x11
+
+#define SDVO_CMD_GET_INPUT_TIMINGS_PART1		0x12
+#define SDVO_CMD_GET_INPUT_TIMINGS_PART2		0x13
+#define SDVO_CMD_SET_INPUT_TIMINGS_PART1		0x14
+#define SDVO_CMD_SET_INPUT_TIMINGS_PART2		0x15
+#define SDVO_CMD_SET_OUTPUT_TIMINGS_PART1		0x16
+#define SDVO_CMD_SET_OUTPUT_TIMINGS_PART2		0x17
+#define SDVO_CMD_GET_OUTPUT_TIMINGS_PART1		0x18
+#define SDVO_CMD_GET_OUTPUT_TIMINGS_PART2		0x19
+/* Part 1 */
+# define SDVO_DTD_CLOCK_LOW				SDVO_I2C_ARG_0
+# define SDVO_DTD_CLOCK_HIGH				SDVO_I2C_ARG_1
+# define SDVO_DTD_H_ACTIVE				SDVO_I2C_ARG_2
+# define SDVO_DTD_H_BLANK				SDVO_I2C_ARG_3
+# define SDVO_DTD_H_HIGH				SDVO_I2C_ARG_4
+# define SDVO_DTD_V_ACTIVE				SDVO_I2C_ARG_5
+# define SDVO_DTD_V_BLANK				SDVO_I2C_ARG_6
+# define SDVO_DTD_V_HIGH				SDVO_I2C_ARG_7
+/* Part 2 */
+# define SDVO_DTD_HSYNC_OFF				SDVO_I2C_ARG_0
+# define SDVO_DTD_HSYNC_WIDTH				SDVO_I2C_ARG_1
+# define SDVO_DTD_VSYNC_OFF_WIDTH			SDVO_I2C_ARG_2
+# define SDVO_DTD_SYSNC_OFF_WIDTH_HIGH			SDVO_I2C_ARG_3
+# define SDVO_DTD_DTD_FLAGS				SDVO_I2C_ARG_4
+# define SDVO_DTD_DTD_FLAG_INTERLACED				(1 << 7)
+# define SDVO_DTD_DTD_FLAG_STEREO_MASK				(3 << 5)
+# define SDVO_DTD_DTD_FLAG_INPUT_MASK				(3 << 3)
+# define SDVO_DTD_DTD_FLAG_SYNC_MASK				(3 << 1)
+# define SDVO_DTD_SDVO_FLAS				SDVO_I2C_ARG_5
+# define SDVO_DTD_SDVO_FLAG_STALL				(1 << 7)
+# define SDVO_DTD_SDVO_FLAG_NOT_CENTERED			(1 << 6)
+# define SDVO_DTD_SDVO_FLAG_SCALING_MASK			(3 << 4)
+# define SDVO_DTD_VSYNC_OFF_HIGH			SDVO_I2C_ARG_6
+
+#define SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING		0x1a
+# define SDVO_PREFERRED_INPUT_TIMING_CLOCK_LOW		SDVO_I2C_ARG_0
+# define SDVO_PREFERRED_INPUT_TIMING_CLOCK_HIGH		SDVO_I2C_ARG_1
+# define SDVO_PREFERRED_INPUT_TIMING_WIDTH_LOW		SDVO_I2C_ARG_2
+# define SDVO_PREFERRED_INPUT_TIMING_WIDTH_HIGH		SDVO_I2C_ARG_3
+# define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_LOW		SDVO_I2C_ARG_4
+# define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_HIGH	SDVO_I2C_ARG_5
+# define SDVO_PREFERRED_INPUT_TIMING_FLAGS		SDVO_I2C_ARG_6
+# define SDVO_PREFERRED_INPUT_TIMING_FLAGS_INTERLACED		(1 << 0)
+# define SDVO_PREFERRED_INPUT_TIMING_FLAGS_SCALED		(1 << 1)
+
+#define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1	0x1b
+#define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2	0x1c
+
+#define SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE		0x1d
+#define SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE		0x1e
+
+#define SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS		0x1f
+
+#define SDVO_CMD_GET_CLOCK_RATE_MULT			0x20
+
+#define SDVO_CMD_SET_CLOCK_RATE_MULT			0x21
+
+#define SDVO_CMD_GET_SUPPORTED_TV_FORMATS		0x27
+
+#define SDVO_CMD_GET_TV_FORMAT				0x28
+
+#define SDVO_CMD_SET_TV_FORMAT				0x29
+
+#define SDVO_CMD_SET_TV_RESOLUTION_SUPPORT		0x93
+
+#define SDVO_CMD_SET_CONTROL_BUS_SWITCH			0x7a
+# define SDVO_CONTROL_BUS_PROM				0x0
+# define SDVO_CONTROL_BUS_DDC1				0x1
+# define SDVO_CONTROL_BUS_DDC2				0x2
+# define SDVO_CONTROL_BUS_DDC3				0x3
+
diff-tree d8f7dfac769d7b03f069306b1296bb2e1e08b009 (from a371a04a57620b7128e3c4395bc7c2ac55effe19)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Wed Apr 19 10:45:13 2006 -0700

    Start bringing in some SDVO code, mostly from airlied.

diff --git a/src/Makefile.am b/src/Makefile.am
index 1789af2..da48149 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -61,7 +61,8 @@ i810_drv_la_SOURCES = \
          i830_modes.c \
          i830_video.c \
          i830_rotate.c \
-	 i830_randr.c
+	 i830_randr.c \
+	 i830_sdvo.c
 
 if DRI
 i810_drv_la_SOURCES += \
diff --git a/src/i810_reg.h b/src/i810_reg.h
index 92d9cf9..82571e0 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -745,6 +745,23 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 # define SDVOC_HOTPLUG_INT_STATUS		(1 << 7)
 # define SDVOB_HOTPLUG_INT_STATUS		(1 << 6)
 
+#define SDVOB			0x61140
+#define SDVOC			0x61160
+#define SDVO_ENABLE				(1 << 31)
+#define SDVO_PIPE_B_SELECT			(1 << 30)
+#define SDVO_STALL_SELECT			(1 << 29)
+#define SDVO_INTERRUPT_ENABLE			(1 << 26)
+/* Programmed value is multiplier - 1, up to 5x.  alv, gdg only */
+#define SDVO_PORT_MULTIPLY_MASK			(7 << 23)
+#define SDVO_PHASE_SELECT_MASK			(15 << 23)
+#define SDVO_PHASE_SELECT_DEFAULT		(6 << 23)
+#define SDVO_CLOCK_OUTPUT_INVERT		(1 << 18)
+#define SDVOC_GANG_MODE				(1 << 16)
+#define SDVO_BORDER_ENABLE			(1 << 7)
+#define SDVO_DETECTED				(1 << 2)
+/* Bits to be preserved when writing */
+#define SDVO_PRESERVE_MASK			(1 << 17)
+
 #define I830_HTOTAL_MASK 	0xfff0000
 #define I830_HACTIVE_MASK	0x7ff
 
diff --git a/src/i830.h b/src/i830.h
index babbe08..a631258 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -202,7 +202,7 @@ struct _I830OutputRec {
    I2CBusPtr pI2CBus;
    I2CBusPtr pDDCBus;
    struct _I830DVODriver *i2c_drv;
-   struct _I830SDVODriver *sdvo_drv;
+   I830SDVOPtr sdvo_drv;
 };
 
 typedef struct _I830Rec {
@@ -580,6 +580,10 @@ extern Bool I830RandRInit(ScreenPtr pScr
 extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg,
 			char *name);
 
+/* i830_sdvo.c */
+extern I830SDVOPtr I830SDVOInit(I2CBusPtr b);
+extern Bool I830I2CDetectSDVOController(ScrnInfoPtr pScrn, int output_index);
+
 /*
  * 12288 is set as the maximum, chosen because it is enough for
  * 1920x1440 at 32bpp with a 2048 pixel line pitch with some to spare.
diff --git a/src/i830_display.c b/src/i830_display.c
index 8eebfca..fd3c352 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -255,8 +255,8 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     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;
-    CARD32 pipesrc, dspsize, adpa;
-    Bool ok;
+    CARD32 pipesrc, dspsize, adpa, sdvoc = 0;
+    Bool ok, is_sdvo;
     int refclk, pixel_clock;
     int outputs;
 
@@ -283,6 +283,14 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 		   "Can't support LVDS on pipe A\n");
 	return FALSE;
     }
+    if ((outputs & PIPE_DFP_ACTIVE) || (outputs & PIPE_DFP2_ACTIVE)) {
+	/* We'll change how we control outputs soon, but to get the SDVO code up
+	 * and running, just check for these two possibilities.
+	 */
+	is_sdvo = TRUE;
+    } else {
+	is_sdvo = FALSE;
+    }
 
     htot = (pMode->CrtcHDisplay - 1) | ((pMode->CrtcHTotal - 1) << 16);
     hblank = (pMode->CrtcHBlankStart - 1) | ((pMode->CrtcHBlankEnd - 1) << 16);
@@ -378,6 +386,19 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	dpll |= PLL_REF_INPUT_DREFCLK;
     dpll |= SDV0_DEFAULT_MULTIPLIER;
 
+    if (is_sdvo) {
+	dpll |= DPLL_DVO_HIGH_SPEED;
+
+	ErrorF("DVOB: %08x\nDVOC: %08x\n", (int)INREG(SDVOB), (int)INREG(SDVOC));
+
+	sdvoc = INREG(SDVOC) & SDVO_PRESERVE_MASK;
+	sdvoc |= SDVO_ENABLE;
+	if (pipe == 1)
+	    sdvoc |= SDVO_PIPE_B_SELECT;
+	sdvoc |= SDVO_PHASE_SELECT_DEFAULT;
+	sdvoc |= SDVO_BORDER_ENABLE;
+    }
+
     fp = ((n - 2) << 16) | ((m1 - 2) << 8) | (m2 - 2);
 
 #if 1
@@ -532,6 +553,8 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 
     if (outputs & PIPE_CRT_ACTIVE)
 	OUTREG(ADPA, adpa);
+    if (is_sdvo)
+	OUTREG(SDVOC, sdvoc);
 
     return TRUE;
 }
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 8930db0..591605a 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1338,13 +1338,15 @@ static void
 I830SetupOutputBusses(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
+   int i = 0;
+   Bool ret;
 
    /* everyone has at least a single analog output */
-   pI830->num_outputs = 1;
-   pI830->output[0].type = I830_OUTPUT_ANALOG;
+   pI830->output[i].type = I830_OUTPUT_ANALOG;
 
    /* setup the DDC bus for the analog output */
-   I830I2CInit(pScrn, &pI830->output[0].pDDCBus, GPIOA, "CRTDDC_A");
+   I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOA, "CRTDDC_A");
+   i++;
 
    /* need to add the output busses for each device 
     * - this function is very incomplete
@@ -1355,35 +1357,44 @@ I830SetupOutputBusses(ScrnInfoPtr pScrn)
    case PCI_CHIP_845_G:
    case PCI_CHIP_I855_GM:
    case PCI_CHIP_I865_G:
-      pI830->num_outputs = 2;
-      pI830->output[1].type = I830_OUTPUT_DVO;
-      I830I2CInit(pScrn, &pI830->output[1].pDDCBus, GPIOD, "DVODDC_D");
-      I830I2CInit(pScrn, &pI830->output[1].pI2CBus, GPIOE, "DVOI2C_E");
+      pI830->output[i].type = I830_OUTPUT_DVO;
+      I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOD, "DVODDC_D");
+      I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "DVOI2C_E");
+      i++;
       break;
    case PCI_CHIP_E7221_G:
       /* ??? */
       break;
-   case PCI_CHIP_I915_G:
    case PCI_CHIP_I915_GM:
-      pI830->num_outputs = 2;
-      pI830->output[1].type = I830_OUTPUT_LVDS;
-      I830I2CInit(pScrn, &pI830->output[1].pDDCBus, GPIOC, "LVDSDDC_C");
+   case PCI_CHIP_I945_GM:
+      pI830->output[i].type = I830_OUTPUT_LVDS;
+      I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOC, "LVDSDDC_C");
+      i++;
       break;
-#if 0
+   case PCI_CHIP_I915_G:
    case PCI_CHIP_I945_G:
-   case PCI_CHIP_I945_GM:
-      /* SDVO ports have a single control bus */
-      pI830->num_outputs = 2;
-      pI830->output[1].type = I830_OUTPUT_SDVO;
-      I830I2CInit(pScrn, &pI830->output[1].pI2CBus, GPIOE, "SDVOCTRL_E");
+      /* Set up SDVOB */
+      pI830->output[i].type = I830_OUTPUT_SDVO;
+      I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "SDVOCTRL_E");
+
+      pI830->output[i].sdvo_drv = I830SDVOInit(pI830->output[i].pI2CBus);
+      ret = I830I2CDetectSDVOController(pScrn, i);
+      if (ret == TRUE)
+	 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found sDVOB\n");
+      i++;
+
+      /* Set up SDVOC */
+      pI830->output[i].type = I830_OUTPUT_SDVO;
+      I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "SDVOCTRL_E");
 
-      pI830->output[1].sdvo_drv = I830SDVOInit(pI830->output[1].pI2CBus);
-      ret = I830I2CDetectSDVOController(pScrn, 1);
+      pI830->output[i].sdvo_drv = I830SDVOInit(pI830->output[i].pI2CBus);
+      ret = I830I2CDetectSDVOController(pScrn, i);
       if (ret == TRUE)
-	 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found sDVO\n");
+	 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found sDVOC\n");
+      i++;
       break;
-#endif
    }
+   pI830->num_outputs = i;
 }
 
 void 
@@ -1442,8 +1453,8 @@ void I830DetectMonitors(ScrnInfoPtr pScr
 	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC DVO %d, %08lX\n", i,
 		    pI830->output[i].pDDCBus->DriverPrivate.uval);
 	 xf86PrintEDID(pI830->output[i].MonInfo);
-      
-#if 0
+
+#if 0      
 	 /* if we are on an i2C bus > 0 and we see a monitor - try to
 	  * find a controller chip
 	  */
@@ -1459,9 +1470,9 @@ void I830DetectMonitors(ScrnInfoPtr pScr
 	 }
 #endif
       break;
-#if 0
       case I830_OUTPUT_SDVO:
 	 if (pI830->output[i].sdvo_drv->found) {
+#if 0
 	    I830SDVOSetupDDC(pI830->output[i].sdvo_drv);
 
 	    pI830->output[i].MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex,
@@ -1470,9 +1481,9 @@ void I830DetectMonitors(ScrnInfoPtr pScr
 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC SDVO %d, %08X\n", i,
 		       pI830->output[i].pI2CBus->DriverPrivate.uval);
 	    xf86PrintEDID(pI830->output[i].MonInfo);
+#endif
 	 }
 	 break;
-#endif
       case I830_OUTPUT_UNUSED:
 	 break;
       default:
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
new file mode 100644
index 0000000..7f5549c
--- /dev/null
+++ b/src/i830_sdvo.c
@@ -0,0 +1,103 @@
+/**************************************************************************
+
+ Copyright 2006 Dave Airlie <airlied at linux.ie>
+ 
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#include "xf86.h"
+#include "xf86_ansic.h"
+#include "xf86_OSproc.h"
+#include "compiler.h"
+#include "i830.h"
+
+/* SDVO support for i9xx chipsets */
+static Bool sReadByte(I830SDVOPtr s, int addr, unsigned char *ch)
+{
+    if (!xf86I2CReadByte(&s->d, addr, ch)) {
+	xf86DrvMsg(s->d.pI2CBus->scrnIndex, X_ERROR,
+		   "Unable to read from %s Slave %d.\n", s->d.pI2CBus->BusName,
+		   s->d.SlaveAddr);
+	return FALSE;
+    }
+    return TRUE;
+}
+
+#if 0
+static Bool sWriteByte(I830SDVOPtr s, int addr, unsigned char ch)
+{
+    if (!xf86I2CWriteByte(&s->d, addr, ch)) {
+	xf86DrvMsg(s->d.pI2CBus->scrnIndex, X_ERROR,
+		   "Unable to write to %s Slave %d.\n", s->d.pI2CBus->BusName,
+		   s->d.SlaveAddr);
+	return FALSE;
+    }
+    return TRUE;
+}
+#endif
+
+I830SDVOPtr
+I830SDVOInit(I2CBusPtr b)
+{
+    I830SDVOPtr sdvo;
+
+    sdvo = xcalloc(1, sizeof(I830SDVORec));
+    if (sdvo == NULL)
+	return NULL;
+
+    sdvo->d.DevName = "SDVO Controller";
+    sdvo->d.SlaveAddr = 0x39 << 1;
+    sdvo->d.pI2CBus = b;
+    sdvo->d.StartTimeout = b->StartTimeout;
+    sdvo->d.BitTimeout = b->BitTimeout;
+    sdvo->d.AcknTimeout = b->AcknTimeout;
+    sdvo->d.ByteTimeout = b->ByteTimeout;
+    sdvo->d.DriverPrivate.ptr = sdvo;
+
+    if (!xf86I2CDevInit(&sdvo->d))
+	goto out;
+    return sdvo;
+
+out:
+    xfree(sdvo);
+    return NULL;
+}
+
+Bool
+I830I2CDetectSDVOController(ScrnInfoPtr pScrn, int output_index)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    unsigned char ch[64];
+    int i;
+    I830SDVOPtr sdvo = pI830->output[output_index].sdvo_drv;
+
+    if (sdvo == NULL)
+	return FALSE;
+
+    for (i=0; i<0x40; i++) {
+	if (!sReadByte(sdvo, i, &ch[i]))
+	    return FALSE;
+    }
+
+    pI830->output[output_index].sdvo_drv->found = 1;
+
+    return TRUE;
+}
diff-tree a371a04a57620b7128e3c4395bc7c2ac55effe19 (from 33413a3cf34b06e3207fe1cdb733d586d55a4337)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Apr 17 14:10:50 2006 -0700

    Use the IS_I9XX macro intead of >= i915G, since by PCI ID number, 855GM > 915.

diff --git a/src/i830_display.c b/src/i830_display.c
index 0e3bb47..8eebfca 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -68,7 +68,7 @@ i830PllIsValid(ScrnInfoPtr pScrn, int ou
     int min_m1, max_m1, min_m2, max_m2, min_m, max_m, min_n, max_n;
     int min_p1, max_p1, min_p, max_p, min_vco, max_vco, min_dot, max_dot;
 
-    if (pI830->PciInfo->chipType >= PCI_CHIP_I915_G) {
+    if (IS_I9XX(pI830)) {
 	min_m1 = 10;
 	max_m1 = 20;
 	min_m2 = 5;
@@ -153,7 +153,7 @@ i830FindBestPLL(ScrnInfoPtr pScrn, int o
     int err = target;
     int min_m1, max_m1, min_m2, max_m2, min_n, max_n, min_p1, max_p1;
 
-    if (pI830->PciInfo->chipType >= PCI_CHIP_I915_G) {
+    if (IS_I9XX(pI830)) {
 	min_m1 = 10;
 	max_m1 = 20;
 	min_m2 = 5;
@@ -332,7 +332,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	pixel_clock = pI830->panel_fixed_clock;
     }
 
-    if (pI830->PciInfo->chipType >= PCI_CHIP_I915_G) {
+    if (IS_I9XX(pI830)) {
 	refclk = 96000;
     } else {
 	refclk = 48000;
@@ -346,7 +346,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     }
 
     dpll = DPLL_VCO_ENABLE | DPLL_VGA_MODE_DIS;
-    if (pI830->PciInfo->chipType >= PCI_CHIP_I915_G) {
+    if (IS_I9XX(pI830)) {
 	if (outputs & PIPE_LCD_ACTIVE)
 	    dpll |= DPLLB_MODE_LVDS;
 	else
diff-tree 33413a3cf34b06e3207fe1cdb733d586d55a4337 (from 365b4a53ee965002a5452e6f6016b528e51cee69)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Apr 17 13:42:57 2006 -0700

    Remove some dead code and one particularly useless debug printf.

diff --git a/src/i830_display.c b/src/i830_display.c
index 4cdc2b1..0e3bb47 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -139,81 +139,6 @@ i830PllIsValid(ScrnInfoPtr pScrn, int ou
     return TRUE;
 }
 
-#if 0
-int
-i830ReadAndReportPLL(ScrnInfoPtr pScrn)
-{
-    I830Ptr pI830 = I830PTR(pScrn);
-    CARD32 temp, dpll;
-    int refclk, m1, m2, n, p1, p2;
-
-    refclk = 96000;	/* XXX: The refclk may be 100000 for the LVDS */
-
-    dpll = INREG(DPLL_A);
-    switch ((dpll & DPLL_FPA01_P1_POST_DIV_MASK) >> 16) {
-    case 0x01:
-	p1 = 1;
-	break;
-    case 0x02:
-	p1 = 2;
-	break;
-    case 0x04:
-	p1 = 3;
-	break;
-    case 0x08:
-	p1 = 4;
-	break;
-    case 0x10:
-	p1 = 5;
-	break;
-    case 0x20:
-	p1 = 6;
-	break;
-    case 0x40:
-	p1 = 7;
-	break;
-    case 0x80:
-	p1 = 8;
-	break;
-    default:
-	FatalError("Unknown p1 clock div: 0x%x\n",
-		   dpll & DPLL_FPA01_P1_POST_DIV_MASK);
-    }
-
-    switch (dpll & DPLL_P2_CLOCK_DIV_MASK) {
-    case DPLL_DAC_SERIAL_P2_CLOCK_DIV_5:
-	p2 = 5;
-	break;
-    case DPLL_DAC_SERIAL_P2_CLOCK_DIV_10:
-	p2 = 10;
-	break;
-/* XXX:
-    case DPLLB_LVDS_P2_CLOCK_DIV_7:
-	p2 = 7;
-	break;
-    case DPLLB_LVDS_P2_CLOCK_DIV_14:
-	p2 = 14;
-	break;
-*/
-    default:
-	FatalError("Unknown p2 clock div: 0x%x\n", dpll & DPLL_P2_CLOCK_DIV_MASK);
-    }
-
-    if (dpll & DISPLAY_RATE_SELECT_FPA1)
-	temp = INREG(FPA1);
-    else
-	temp = INREG(FPA0);
-    n = (temp & FP_N_DIV_MASK) >> 16;
-    m1 = (temp & FP_M1_DIV_MASK) >> 8;
-    m2 = (temp & FP_M2_DIV_MASK);
-
-    i830PrintPll("FPA", refclk, m1, m2, n, p1, p2);
-    ErrorF("clock settings for FPA0 look %s\n",
-	   i830PllIsValid(refclk, m1, m2, n, p1, p2) ? "good" : "bad");
-    ErrorF("clock regs: 0x%08x, 0x%08x\n", dpll, temp);    
-}
-#endif
-
 /**
  * Returns a set of divisors for the desired target clock with the given refclk,
  * or FALSE.  Divisor values are the actual divisors for
@@ -466,19 +391,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	(int)(vsync & 0xffff) + 1, (int)(vsync >> 16) + 1);
 #endif
 
-    adpa = INREG(ADPA);
-    adpa &= ~(ADPA_HSYNC_ACTIVE_HIGH | ADPA_VSYNC_ACTIVE_HIGH);
-    adpa &= ~(ADPA_VSYNC_CNTL_DISABLE | ADPA_HSYNC_CNTL_DISABLE);
-    adpa |= ADPA_DAC_ENABLE;
-    if (pMode->Flags & V_PHSYNC)
-	adpa |= ADPA_HSYNC_ACTIVE_HIGH;
-    if (pMode->Flags & V_PVSYNC)
-	adpa |= ADPA_VSYNC_ACTIVE_HIGH;
-
     i830PrintPll("chosen", refclk, m1, m2, n, p1, p2);
-    ErrorF("clock settings for chosen look %s\n",
-	   i830PllIsValid(pScrn, outputs, refclk, m1, m2, n, p1, p2) ?
-			  "good" : "bad");
     ErrorF("clock regs: 0x%08x, 0x%08x\n", (int)dpll, (int)fp);
 
     dspcntr = DISPLAY_PLANE_ENABLE;
diff-tree 365b4a53ee965002a5452e6f6016b528e51cee69 (from ee7be006b63b6b1ce7f786b045fb8f26d337433c)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Apr 17 01:12:28 2006 -0500

    Disable the BIOS dump-to-file since it's a trivial local DOS, and I can just ask
    people to turn it on and recompile when I need to.

diff --git a/src/i830_bios.c b/src/i830_bios.c
index 00cec52..19b1b5a 100644
--- a/src/i830_bios.c
+++ b/src/i830_bios.c
@@ -97,7 +97,9 @@ i830GetBIOS(ScrnInfoPtr pScrn)
 	xf86ReadPciBIOS(0, pI830->PciTag, 0, pI830->VBIOS, INTEL_VBIOS_SIZE);
     }
 
-    i830DumpBIOSToFile(pScrn);
+    if (0)
+	i830DumpBIOSToFile(pScrn);
+
     vbt_off = INTEL_BIOS_16(0x1a);
     if (vbt_off >= INTEL_VBIOS_SIZE) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Bad VBT offset: 0x%x\n",
diff-tree ee7be006b63b6b1ce7f786b045fb8f26d337433c (from 786ee3df1726f08953167d05f7fa1930452703bb)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Sun Apr 16 13:13:42 2006 -0500

    Bug #6589: Use alternate offsets to successfully get at the panel data for
    some broken video BIOSes.

diff --git a/src/i830_bios.c b/src/i830_bios.c
index c9ca881..00cec52 100644
--- a/src/i830_bios.c
+++ b/src/i830_bios.c
@@ -173,6 +173,21 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScr
 	    timing_ptr = pI830->VBIOS + bdb_off +
 	        lvds2->panels[panel_type].fp_edid_dtd_offset;
 
+	    if (fpparam->terminator != 0xffff) {
+		/* Apparently the offsets are wrong for some BIOSes, so we
+		 * try the other offsets if we find a bad terminator.
+		 */
+		fpparam = (struct lvds_bdb_2_fp_params *)(pI830->VBIOS +
+		    bdb_off + lvds2->panels[panel_type].fp_params_offset + 8);
+		fptiming = (struct lvds_bdb_2_fp_edid_dtd *)(pI830->VBIOS +
+		    bdb_off + lvds2->panels[panel_type].fp_edid_dtd_offset + 8);
+		timing_ptr = pI830->VBIOS + bdb_off +
+	            lvds2->panels[panel_type].fp_edid_dtd_offset + 8;
+
+		if (fpparam->terminator != 0xffff)
+		    continue;
+	    }
+
 	    pI830->PanelXRes = fpparam->x_res;
 	    pI830->PanelYRes = fpparam->y_res;
 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
diff-tree 786ee3df1726f08953167d05f7fa1930452703bb (from 62652127cd12f5a0fc9364285b81d2661372148a)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Sun Apr 16 13:05:35 2006 -0500

    Add a standalone program for parsing VBT.

diff --git a/configure.ac b/configure.ac
index 7882433..3467296 100644
--- a/configure.ac
+++ b/configure.ac
@@ -116,5 +116,6 @@ AC_OUTPUT([
 	Makefile
 	src/Makefile
 	src/xvmc/Makefile
+	src/bios_reader/Makefile
 	man/Makefile
 ])
diff --git a/src/Makefile.am b/src/Makefile.am
index 1b30c65..1789af2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -18,7 +18,7 @@
 #  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 #  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
-SUBDIRS = xvmc
+SUBDIRS = xvmc bios_reader
 # this is obnoxious:
 # -module lets us name the module exactly how we want
 # -avoid-version prevents gratuitous .0.0.0 version numbers on the end
diff --git a/src/bios_reader/.gitignore b/src/bios_reader/.gitignore
new file mode 100644
index 0000000..3e32507
--- /dev/null
+++ b/src/bios_reader/.gitignore
@@ -0,0 +1 @@
+bios_reader
diff --git a/src/bios_reader/Makefile.am b/src/bios_reader/Makefile.am
new file mode 100644
index 0000000..f18a00c
--- /dev/null
+++ b/src/bios_reader/Makefile.am
@@ -0,0 +1,4 @@
+AM_CFLAGS = @XORG_CFLAGS@
+
+noinst_PROGRAMS = bios_reader
+
diff --git a/src/bios_reader/bios_reader.c b/src/bios_reader/bios_reader.c
new file mode 100644
index 0000000..a52bcc7
--- /dev/null
+++ b/src/bios_reader/bios_reader.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#define _PARSE_EDID_
+#include "edid.h"
+
+/* Define some types so we can reuse i830_bios.h */
+typedef void *ScrnInfoPtr;
+typedef int Bool;
+#define TRUE 1
+#define FALSE 0
+#include "../i830_bios.h"
+
+
+/* Make a fake pI830 so we can easily pull i830_bios.c code in here. */
+struct _fake_i830 {
+    CARD8 *VBIOS;
+};
+struct _fake_i830 I830;
+struct _fake_i830 *pI830 = &I830;
+
+#define INTEL_BIOS_8(_addr)	(pI830->VBIOS[_addr])
+#define INTEL_BIOS_16(_addr)	(pI830->VBIOS[_addr] | \
+				 (pI830->VBIOS[_addr + 1] << 8))
+#define INTEL_BIOS_32(_addr)	(pI830->VBIOS[_addr] | \
+				 (pI830->VBIOS[_addr + 1] << 8) \
+				 (pI830->VBIOS[_addr + 2] << 16) \
+				 (pI830->VBIOS[_addr + 3] << 24))
+
+int main(int argc, char **argv)
+{
+    FILE *f;
+    int bios_size = 65536;
+    struct vbt_header *vbt;
+    struct bdb_header *bdb;
+    int vbt_off, bdb_off, bdb_block_off, block_size;
+    int panel_type = -1, i;
+    char *filename = "bios";
+
+    if (argc == 2)
+	filename = argv[1];
+
+    f = fopen(filename, "r");
+    if (!f) {
+	printf("Couldn't open %s\n", filename);
+	return 1;
+    }
+
+    pI830->VBIOS = calloc(1, bios_size);
+    if (fread(pI830->VBIOS, 1, bios_size, f) != bios_size)
+	return 1;
+
+    vbt_off = INTEL_BIOS_16(0x1a);
+    printf("VBT offset: %08x\n", vbt_off);
+    vbt = (struct vbt_header *)(pI830->VBIOS + vbt_off);
+    printf("VBT sig: %20s\n", vbt->signature);
+    printf("VBT vers: %d.%d\n", vbt->version / 100, vbt->version % 100);
+
+    bdb_off = vbt_off + vbt->bdb_offset;
+    bdb = (struct bdb_header *)(pI830->VBIOS + bdb_off);
+    printf("BDB sig: %16s\n", bdb->signature);
+    printf("BDB vers: %d.%d\n", bdb->version / 100, bdb->version % 100);
+    for (bdb_block_off = bdb->header_size; bdb_block_off < bdb->bdb_size;
+	 bdb_block_off += block_size)
+    {
+	int start = bdb_off + bdb_block_off;
+	int id;
+	struct lvds_bdb_1 *lvds1;
+	struct lvds_bdb_2 *lvds2;
+	struct lvds_bdb_2_fp_params *fpparam;
+	struct lvds_bdb_2_fp_edid_dtd *fptiming;
+	CARD8 *timing_ptr;
+
+	id = INTEL_BIOS_8(start);
+	block_size = INTEL_BIOS_16(start + 1) + 3;
+	printf("BDB block type %03d size %d\n", id, block_size);
+	switch (id) {
+	case 40:
+	    lvds1 = (struct lvds_bdb_1 *)(pI830->VBIOS + start);
+	    panel_type = lvds1->panel_type;
+	    printf("Panel type: %d, caps %04x\n", panel_type, lvds1->caps);
+	    break;
+	case 41:
+	    if (panel_type == -1) {
+		printf("Found panel block with no panel type\n");
+		break;
+	    }
+
+	    lvds2 = (struct lvds_bdb_2 *)(pI830->VBIOS + start);
+
+	    printf("Entries per table: %d\n", lvds2->table_size);
+	    for (i = 0; i < 16; i++) {
+		char marker;
+		fpparam = (struct lvds_bdb_2_fp_params *)(pI830->VBIOS +
+		    bdb_off + lvds2->panels[i].fp_params_offset);
+		fptiming = (struct lvds_bdb_2_fp_edid_dtd *)(pI830->VBIOS +
+		    bdb_off + lvds2->panels[i].fp_edid_dtd_offset);
+		timing_ptr = pI830->VBIOS + bdb_off +
+		    lvds2->panels[i].fp_edid_dtd_offset;
+		if (fpparam->terminator != 0xffff) {
+		    /* Apparently the offsets are wrong for some BIOSes, so we
+		     * try the other offsets if we find a bad terminator.
+		     */
+		    fpparam = (struct lvds_bdb_2_fp_params *)(pI830->VBIOS +
+			bdb_off + lvds2->panels[i].fp_params_offset + 8);
+		    fptiming = (struct lvds_bdb_2_fp_edid_dtd *)(pI830->VBIOS +
+			bdb_off + lvds2->panels[i].fp_edid_dtd_offset + 8);
+		    timing_ptr = pI830->VBIOS + bdb_off +
+			lvds2->panels[i].fp_edid_dtd_offset + 8;
+
+		    if (fpparam->terminator != 0xffff)
+			continue;
+		}
+		if (i == panel_type)
+		    marker = '*';
+		else
+		    marker = ' ';
+		printf("%c Panel index %02i xres %d yres %d clock %d\n", marker,
+		       i, fpparam->x_res, fpparam->y_res,
+		       _PIXEL_CLOCK(timing_ptr));
+		printf("        %d %d %d %d %d %d %d %d\n",
+		       _H_ACTIVE(timing_ptr), _H_BLANK(timing_ptr),
+		       _H_SYNC_OFF(timing_ptr), _H_SYNC_WIDTH(timing_ptr),
+		       _V_ACTIVE(timing_ptr), _V_BLANK(timing_ptr),
+		       _V_SYNC_OFF(timing_ptr), _V_SYNC_WIDTH(timing_ptr));
+	    }
+
+	    printf("Panel of size %dx%d\n", fpparam->x_res, fpparam->y_res);
+	    break;
+	}
+    }
+
+    return 0;
+}
diff-tree 62652127cd12f5a0fc9364285b81d2661372148a (from 830fa81792a613fe2127a2b89a3eaa326f56114c)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Sat Apr 15 12:16:46 2006 -0700

    Check for LVDS BIOS tables exactly once at startup.  While there, dump the BIOS
    data to /tmp/xf86-video-intel-VBIOS, for offline debugging.

diff --git a/src/i830_bios.c b/src/i830_bios.c
index 8e575df..c9ca881 100644
--- a/src/i830_bios.c
+++ b/src/i830_bios.c
@@ -47,6 +47,27 @@
 /* XXX */
 #define INTEL_VBIOS_SIZE (64 * 1024)
 
+static void
+i830DumpBIOSToFile(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    const char *filename = "/tmp/xf86-video-intel-VBIOS";
+    FILE *f;
+
+    f = fopen(filename, "w");
+    if (f == NULL) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Couldn't open %s\n", filename);
+	return;
+    }
+    if (fwrite(pI830->VBIOS, INTEL_VBIOS_SIZE, 1, f) != 1) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Couldn't write BIOS data\n");
+    }
+
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Wrote BIOS contents to %s\n",
+	       filename);
+    fclose(f);
+}
+
 /**
  * Loads the Video BIOS and checks that the VBT exists.
  *
@@ -76,6 +97,7 @@ i830GetBIOS(ScrnInfoPtr pScrn)
 	xf86ReadPciBIOS(0, pI830->PciTag, 0, pI830->VBIOS, INTEL_VBIOS_SIZE);
     }
 
+    i830DumpBIOSToFile(pScrn);
     vbt_off = INTEL_BIOS_16(0x1a);
     if (vbt_off >= INTEL_VBIOS_SIZE) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Bad VBT offset: 0x%x\n",
diff --git a/src/i830_display.c b/src/i830_display.c
index c55609d..4cdc2b1 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -368,8 +368,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     pipesrc = ((pMode->HDisplay - 1) << 16) | (pMode->VDisplay - 1);
     dspsize = ((pMode->VDisplay - 1) << 16) | (pMode->HDisplay - 1);
     pixel_clock = pMode->Clock;
-    if (outputs & PIPE_LCD_ACTIVE && i830GetLVDSInfoFromBIOS(pScrn) &&
-	pI830->panel_fixed_hactive != 0)
+    if (outputs & PIPE_LCD_ACTIVE && pI830->panel_fixed_hactive != 0)
     {
 	/* To enable panel fitting, we need to set the pipe timings to that of
 	 * the screen at its full resolution.  So, drop the timings from the
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 4d29907..8930db0 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2139,6 +2139,13 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
    pI830->MonType2 = PIPE_NONE;
    pI830->specifiedMonitor = FALSE;
 
+   /* Always check for LVDS info once at startup.  We hook in the BIOS data
+    * dumping here (this should be cleaner) and we get to rely on having the
+    * LVDS info later on.
+    */
+   if (!i830GetLVDSInfoFromBIOS(pScrn))
+      has_lvds = FALSE;
+
    if ((s = xf86GetOptValString(pI830->Options, OPTION_MONITOR_LAYOUT)) &&
       I830IsPrimary(pScrn)) {
       char *Mon1;
@@ -2227,7 +2234,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
       pI830->specifiedMonitor = TRUE;
    } else if (I830IsPrimary(pScrn)) {
       /* Choose a default set of outputs to use based on what we've detected. */
-      if (i830GetLVDSInfoFromBIOS(pScrn) && has_lvds) {
+      if (has_lvds) {
 	 pI830->MonType2 |= PIPE_LFP;
       }
 
@@ -2743,7 +2750,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
        * rely on the scaler so that we can display any mode smaller than or the
        * same size as the panel.
        */
-      if (!i830GetLVDSInfoFromBIOS(pScrn)) {
+      if (!has_lvds) {
 	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		    "Unable to locate panel information in BIOS VBT tables\n");
          PreInitCleanup(pScrn);
diff-tree 830fa81792a613fe2127a2b89a3eaa326f56114c (from d6edffee7d987ef551e1a94d9fac21beb72a9598)
Author: Alan Hourihane <alanh at jetpack.demon.co.uk>
Date:   Wed Apr 12 21:55:31 2006 +0100

    fix typo

diff --git a/src/i830_video.c b/src/i830_video.c
index afdc99a..0ae6860 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -1390,9 +1390,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
 
    /* When in dual head with different bpp setups we need to refresh the
     * color key, so let's reset the video parameters and refresh here */
-#if 0
    if (pI830->entityPrivate)
-#endif
       I830ResetVideo(pScrn);
 
    /* Ensure overlay is turned on with OVERLAY_ENABLE at 0 */
diff-tree d6edffee7d987ef551e1a94d9fac21beb72a9598 (from 59f88955f57cf0f98458b57418dae25cf53ca180)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Wed Apr 12 12:16:51 2006 -0700

    Initial support for pre-i915 PLL programming. Untested.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index 6976553..92d9cf9 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -705,16 +705,20 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 # define DPLL_DVO_HIGH_SPEED			(1 << 30)
 # define DPLL_SYNCLOCK_ENABLE			(1 << 29)
 # define DPLL_VGA_MODE_DIS			(1 << 28)
-# define DPLLB_MODE_DAC_SERIAL			(1 << 26)
-# define DPLLB_MODE_LVDS			(2 << 26)
-# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10	(0 << 24)
-# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5		(1 << 24)
-# define DPLLB_LVDS_P2_CLOCK_DIV_14		(0 << 24)
-# define DPLLB_LVDS_P2_CLOCK_DIV_7		(1 << 24)
-# define DPLL_P2_CLOCK_DIV_MASK			0x03000000
-# define DPLL_FPA01_P1_POST_DIV_MASK		0x00ff0000
+# define DPLLB_MODE_DAC_SERIAL			(1 << 26) /* i915 */
+# define DPLLB_MODE_LVDS			(2 << 26) /* i915 */
+# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10	(0 << 24) /* i915 */
+# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5		(1 << 24) /* i915 */
+# define DPLLB_LVDS_P2_CLOCK_DIV_14		(0 << 24) /* i915 */
+# define DPLLB_LVDS_P2_CLOCK_DIV_7		(1 << 24) /* i915 */
+# define DPLL_P2_CLOCK_DIV_MASK			0x03000000 /* i915 */
+# define DPLL_FPA01_P1_POST_DIV_MASK		0x00ff0000 /* i915 */
+# define PLL_P2_DIVIDE_BY_4			(1 << 23) /* i830, required in DVO non-gang */
+# define DPLL_FPA01_P1_POS_DIV_MASK_I830	0x001f0000 /* i830 */
+# define PLL_P1_DIVIDE_BY_TWO			(1 << 21) /* i830 */
 # define PLL_REF_INPUT_DREFCLK			(0 << 13)
-# define PLL_REF_INPUT_TVCLKIN			(2 << 13)
+# define PLL_REF_INPUT_TVCLKINA			(1 << 13) /* i830 */
+# define PLL_REF_INPUT_TVCLKINBC		(2 << 13)
 # define PLLB_REF_INPUT_SPREADSPECTRUMIN	(3 << 13)
 # define DISPLAY_RATE_SELECT_FPA1		(1 << 8)
 # define SDVO_MULTIPLIER_MASK			0x000000ff
diff --git a/src/i830_display.c b/src/i830_display.c
index 8b2c881..c55609d 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -66,10 +66,8 @@ i830PllIsValid(ScrnInfoPtr pScrn, int ou
     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;
-    int min_p, max_p;
+    int min_p1, max_p1, min_p, max_p, min_vco, max_vco, min_dot, max_dot;
 
-    min_p = 5;
-    max_p = 80;
     if (pI830->PciInfo->chipType >= PCI_CHIP_I915_G) {
 	min_m1 = 10;
 	max_m1 = 20;
@@ -79,23 +77,36 @@ i830PllIsValid(ScrnInfoPtr pScrn, int ou
 	max_m = 120;
 	min_n = 3;
 	max_n = 8;
+	min_p1 = 1;
+	max_p1 = 8;
 	if (outputs & PIPE_LCD_ACTIVE) {
 	    min_p = 7;
 	    max_p = 98;
+	} else {
+	    min_p = 5;
+	    max_p = 80;
 	}
+	min_vco = 1400000;
+	max_vco = 2800000;
+	min_dot = 20000;
+	max_dot = 400000;
     } else {
-	min_m1 = 16;
-	max_m1 = 24;
-	min_m2 = 7;
-	max_m2 = 11;
-	min_m = 90;
-	max_m = 130;
-	min_n = 4;
-	max_n = 8;
-	if (outputs & PIPE_LCD_ACTIVE) {
-	    min_n = 3;
-	    min_m = 88;
-	}
+	min_m1 = 18;
+	max_m1 = 26;
+	min_m2 = 6;
+	max_m2 = 16;
+	min_m = 96;
+	max_m = 140;
+	min_n = 3;
+	max_n = 16;
+	min_p1 = 2;
+	max_p1 = 18;
+	min_vco = 930000;
+	max_vco = 1400000;
+	min_dot = 20000;
+	max_dot = 350000;
+	min_p = 4;
+	max_p = 128;
     }
 
     p = p1 * p2;
@@ -103,7 +114,7 @@ i830PllIsValid(ScrnInfoPtr pScrn, int ou
     vco = refclk * m / n;
     dotclock = i830_clock(refclk, m1, m2, n, p1, p2);
 
-    if (p1 < 1 || p1 > 8)
+    if (p1 < min_p1 || p1 > max_p1)
 	return FALSE;
     if (p < min_p || p > max_p)
 	return FALSE;
@@ -117,12 +128,12 @@ i830PllIsValid(ScrnInfoPtr pScrn, int ou
 	return FALSE;
     if (n < min_n || n > max_n)
 	return FALSE;
-    if (vco < 1400000 || vco > 2800000)
+    if (vco < min_vco || vco > max_vco)
 	return FALSE;
     /* XXX: We may need to be checking "Dot clock" depending on the multiplier,
      * output, etc., rather than just a single range.
      */
-    if (dotclock < 20000 || dotclock > 400000)
+    if (dotclock < min_dot || dotclock > max_dot)
 	return FALSE;
 
     return TRUE;
@@ -215,36 +226,48 @@ i830FindBestPLL(ScrnInfoPtr pScrn, int o
     I830Ptr pI830 = I830PTR(pScrn);
     int m1, m2, n, p1, p2;
     int err = target;
-    int min_m1, max_m1, min_m2, max_m2;
+    int min_m1, max_m1, min_m2, max_m2, min_n, max_n, min_p1, max_p1;
 
     if (pI830->PciInfo->chipType >= PCI_CHIP_I915_G) {
 	min_m1 = 10;
 	max_m1 = 20;
 	min_m2 = 5;
 	max_m2 = 9;
+	min_n = 3;
+	max_n = 8;
+	min_p1 = 1;
+	max_p1 = 8;
+	if (outputs & PIPE_LCD_ACTIVE) {
+	    if (target < 200000) /* XXX: Is this the right cutoff? */
+		p2 = 14;
+	    else
+		p2 = 7;
+	} else {
+	    if (target < 200000)
+		p2 = 10;
+	    else
+		p2 = 5;
+	}
     } else {
-	min_m1 = 16;
-	max_m1 = 24;
-	min_m2 = 7;
-	max_m2 = 11;
-    }
-
-    if (outputs & PIPE_LCD_ACTIVE) {
-	if (target < 200000) /* XXX: Is this the right cutoff? */
-	    p2 = 14;
-	else
-	    p2 = 7;
-    } else {
-	if (target < 200000)
-	    p2 = 10;
+	min_m1 = 18;
+	max_m1 = 26;
+	min_m2 = 6;
+	max_m2 = 16;
+	min_n = 3;
+	max_n = 16;
+	min_p1 = 2;
+	max_p1 = 18;
+	if (target < 165000)
+	    p2 = 4;
 	else
-	    p2 = 5;
+	    p2 = 2;
     }
 
+
     for (m1 = min_m1; m1 <= max_m1; m1++) {
 	for (m2 = min_m2; m2 < max_m2; m2++) {
-	    for (n = 3; n <= 8; n++) {
-		for (p1 = 1; p1 <= 8; p1++) {
+	    for (n = min_n; n <= max_n; n++) {
+		for (p1 = min_p1; p1 <= max_p1; p1++) {
 		    int clock, this_err;
 
 		    if (!i830PllIsValid(pScrn, outputs, refclk, m1, m2, n,
@@ -309,7 +332,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     CARD32 htot, hblank, hsync, vtot, vblank, vsync, dspcntr;
     CARD32 pipesrc, dspsize, adpa;
     Bool ok;
-    int refclk = 96000, pixel_clock;
+    int refclk, pixel_clock;
     int outputs;
 
     ErrorF("Requested pix clock: %d\n", pMode->Clock);
@@ -385,6 +408,11 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	pixel_clock = pI830->panel_fixed_clock;
     }
 
+    if (pI830->PciInfo->chipType >= PCI_CHIP_I915_G) {
+	refclk = 96000;
+    } else {
+	refclk = 48000;
+    }
     ok = i830FindBestPLL(pScrn, outputs, pixel_clock, refclk, &m1, &m2, &n,
 			 &p1, &p2);
     if (!ok) {
@@ -394,28 +422,34 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     }
 
     dpll = DPLL_VCO_ENABLE | DPLL_VGA_MODE_DIS;
-    if (outputs & PIPE_LCD_ACTIVE)
-	dpll |= DPLLB_MODE_LVDS;
-    else
-	dpll |= DPLLB_MODE_DAC_SERIAL;
-
-    dpll |= (1 << (p1 - 1)) << 16;
-    switch (p2) {
-    case 5:
-	dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5;
-	break;
-    case 7:
-	dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7;
-	break;
-    case 10:
-	dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10;
-	break;
-    case 14:
-	dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
-	break;
+    if (pI830->PciInfo->chipType >= PCI_CHIP_I915_G) {
+	if (outputs & PIPE_LCD_ACTIVE)
+	    dpll |= DPLLB_MODE_LVDS;
+	else
+	    dpll |= DPLLB_MODE_DAC_SERIAL;
+	dpll |= (1 << (p1 - 1)) << 16;
+	switch (p2) {
+	case 5:
+	    dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5;
+	    break;
+	case 7:
+	    dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7;
+	    break;
+	case 10:
+	    dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10;
+	    break;
+	case 14:
+	    dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
+	    break;
+	}
+    } else {
+	dpll |= (p1 - 2) << 16;
+	if (p2 == 4)
+	    dpll |= PLL_P2_DIVIDE_BY_4;
     }
+
     if (outputs & (PIPE_TV_ACTIVE | PIPE_TV2_ACTIVE))
-	dpll |= PLL_REF_INPUT_TVCLKIN;
+	dpll |= PLL_REF_INPUT_TVCLKINBC;
     else
 	dpll |= PLL_REF_INPUT_DREFCLK;
     dpll |= SDV0_DEFAULT_MULTIPLIER;
diff-tree 59f88955f57cf0f98458b57418dae25cf53ca180 (from 185b5251419724fa9377421d67981daa674908c8)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Wed Apr 12 11:11:14 2006 -0700

    Automatically enable clone mode if we detect two active outputs.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 5ba1108..4d29907 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2256,6 +2256,12 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
       else
 	 pI830->pipe = 1;
       pI830->operatingDevices = (pI830->MonType2 << 8) | pI830->MonType1;
+
+      if (pI830->MonType1 != 0 && pI830->MonType2 != 0) {
+         xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
+ 		    "Enabling clone mode by default\n");
+	 pI830->Clone = TRUE;
+      }
    } else {
       I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
       pI830->operatingDevices = pI8301->operatingDevices;
@@ -2296,13 +2302,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
    }
 
    if ((pI830->entityPrivate && I830IsPrimary(pScrn)) || pI830->Clone) {
-      if ((!xf86GetOptValString(pI830->Options, OPTION_MONITOR_LAYOUT))) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "You must have a MonitorLayout "
-	 		"defined for use in a DualHead or Clone setup.\n");
-         PreInitCleanup(pScrn);
-         return FALSE;
-      }
-         
       if (pI830->MonType1 == PIPE_NONE || pI830->MonType2 == PIPE_NONE) {
          xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Monitor 1 or Monitor 2 "
 	 		"cannot be type NONE in Dual or Clone setup.\n");
diff-tree 185b5251419724fa9377421d67981daa674908c8 (from c0a2dc608d95f92b0f5a151c623745f09df3afc5)
Author: Eric Anholt <anholt at leguin.anholt.net>
Date:   Mon Apr 10 20:25:13 2006 -0700

    Add missing MIT copyright licenses, which should have been on all versions.

diff --git a/src/i830_debug.c b/src/i830_debug.c
index 96426c4..b544257 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -1,3 +1,30 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
diff --git a/src/i830_debug.h b/src/i830_debug.h
index c02ff25..269f03e 100644
--- a/src/i830_debug.h
+++ b/src/i830_debug.h
@@ -1,2 +1,29 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
 void i830TakeRegSnapshot(ScrnInfoPtr pScrn);
 void i830CompareRegsToSnapshot(ScrnInfoPtr pScrn);
diff --git a/src/i830_display.c b/src/i830_display.c
index e76c581..8b2c881 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -1,3 +1,30 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
diff --git a/src/i830_display.h b/src/i830_display.h
index 101d65b..d8e4e5e 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -1,3 +1,30 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
 Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
 Bool i830DetectCRT(ScrnInfoPtr pScrn);
 void i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on);
diff-tree c0a2dc608d95f92b0f5a151c623745f09df3afc5 (from 498abf474b90b04bc4085397a209cc493d98d15c)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Mon Apr 10 20:09:37 2006 -0700

    Save/restore PFIT_CONTROL. Eliminate compiler warnings

diff --git a/src/i830.h b/src/i830.h
index 743a72b..babbe08 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -268,7 +268,7 @@ typedef struct _I830Rec {
    I830MemRange *OverlayMem;
    I830MemRange LinearMem;
 #endif
-   unsigned int LinearAlloc;
+   unsigned long LinearAlloc;
   
    XF86ModReqInfo shadowReq; /* to test for later libshadow */
    I830MemRange RotatedMem;
@@ -481,6 +481,7 @@ typedef struct _I830Rec {
    CARD32 saveVCLK_POST_DIV;
    CARD32 saveVGACNTRL;
    CARD32 saveADPA;
+   CARD32 savePFIT_CONTROL;
 
 } I830Rec;
 
diff --git a/src/i830_bios.c b/src/i830_bios.c
index 4264803..8e575df 100644
--- a/src/i830_bios.c
+++ b/src/i830_bios.c
@@ -26,6 +26,7 @@
  */
 #ifdef HAVE_CONFIG_H
 #include "config.h"
+#undef VERSION	/* XXX edid.h has a VERSION too */
 #endif
 
 #define _PARSE_EDID_
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 61faad0..5ba1108 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2107,9 +2107,9 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
 #endif
 
    pI830->LinearAlloc = 0;
-   if (xf86GetOptValInteger(pI830->Options, OPTION_LINEARALLOC,
+   if (xf86GetOptValULong(pI830->Options, OPTION_LINEARALLOC,
 			    &(pI830->LinearAlloc))) {
-      xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Allocating %dKbytes of memory\n",
+      xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Allocating %luKbytes of memory\n",
 		 pI830->LinearAlloc);
    }
 
@@ -3252,6 +3252,8 @@ SaveHWState(ScrnInfoPtr pScrn)
 
    pI830->saveADPA = INREG(ADPA);
 
+   pI830->savePFIT_CONTROL = INREG(PFIT_CONTROL);
+   
    vgaHWUnlock(hwp);
    vgaHWSave(pScrn, vgaReg, VGA_SR_ALL);
 
@@ -3316,6 +3318,8 @@ RestoreHWState(ScrnInfoPtr pScrn)
    OUTREG(DSPBBASE, pI830->saveDSPBBASE);
    OUTREG(PIPEBSRC, pI830->savePIPEBSRC);
 
+   OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL);
+   
    OUTREG(VCLK_DIVISOR_VGA0, pI830->saveVCLK_DIVISOR_VGA0);
    OUTREG(VCLK_DIVISOR_VGA1, pI830->saveVCLK_DIVISOR_VGA1);
    OUTREG(VCLK_POST_DIV, pI830->saveVCLK_POST_DIV);
diff --git a/src/xvmc/I810XvMC.c b/src/xvmc/I810XvMC.c
index 89aa3ea..03be251 100644
--- a/src/xvmc/I810XvMC.c
+++ b/src/xvmc/I810XvMC.c
@@ -1558,6 +1558,11 @@ static __inline__ void renderDualPrimein
 // Description: inline function that sets hardware parameters for a Field
 //  encoded macroblock in a frame picture.
 ***************************************************************************/
+typedef union {
+  short	s[4];
+  uint  u[2];
+} su_t;
+
 static __inline__ void renderFieldinFrame(uint **datay,uint **datau,
 					  uint **datav,
 					  XvMCMacroBlock *mb,short *block_ptr,
@@ -1568,8 +1573,8 @@ static __inline__ void renderFieldinFram
   register uint *dv = *datav;
 
   /* Motion Vectors */
-  short fmv[4];
-  short bmv[4];
+  su_t fmv;
+  su_t bmv;
   /* gfxblock dword 1 */
   uint dw1[2];
 
@@ -1589,23 +1594,23 @@ static __inline__ void renderFieldinFram
     (((mb->coded_block_pattern & 0x3) |
       ((mb->coded_block_pattern & 0xc)<<2))<<22);
 
-  fmv[0] = mb->PMV[0][0][1]/2;
-  fmv[1] = mb->PMV[0][0][0];
-  fmv[2] = mb->PMV[1][0][1]/2;
-  fmv[3] = mb->PMV[1][0][0];
-  
-  bmv[0] = mb->PMV[0][1][1]/2;
-  bmv[1] = mb->PMV[0][1][0];
-  bmv[2] = mb->PMV[1][1][1]/2;
-  bmv[3] = mb->PMV[1][1][0];
+  fmv.s[0] = mb->PMV[0][0][1]/2;
+  fmv.s[1] = mb->PMV[0][0][0];
+  fmv.s[2] = mb->PMV[1][0][1]/2;
+  fmv.s[3] = mb->PMV[1][0][0];
+  
+  bmv.s[0] = mb->PMV[0][1][1]/2;
+  bmv.s[1] = mb->PMV[0][1][0];
+  bmv.s[2] = mb->PMV[1][1][1]/2;
+  bmv.s[3] = mb->PMV[1][1][0];
 
   /* First Y Block */
   *dy++ = GFXBLOCK + 4 + (y1size>>2);
   *dy++ = (1<<30) | (2<<28) | dw1[0];
   *dy++ = xy;
   *dy++ = (8<<16) | 16;
-  *dy++ = *(uint *)&fmv[0];
-  *dy++ = *(uint *)&bmv[0];
+  *dy++ = fmv.u[0];
+  *dy++ = bmv.u[0];
   PACK_CORR_DATA(dy,block_ptr,y1size);
   block_ptr = (short *)((unsigned long)block_ptr + y1size);
 
@@ -1614,21 +1619,21 @@ static __inline__ void renderFieldinFram
   *dy++ = (1<<30) | (2<<28) | dw1[1];
   *dy++ = xy;
   *dy++ = (8<<16) | 16;
-  *dy++ = *(uint *)&fmv[2];
-  *dy++ = *(uint *)&bmv[2];
+  *dy++ = fmv.u[1];
+  *dy++ = bmv.u[1];
   PACK_CORR_DATA(dy,block_ptr,y2size);
   block_ptr = (short *)((unsigned long)block_ptr + y2size);
   /* End Y Blocks */
 
-  fmv[0] /= 2;
-  fmv[1] /= 2;
-  fmv[2] /= 2;
-  fmv[3] /= 2;
-  
-  bmv[0] /= 2;
-  bmv[1] /= 2;
-  bmv[2] /= 2;
-  bmv[3] /= 2;
+  fmv.s[0] /= 2;
+  fmv.s[1] /= 2;
+  fmv.s[2] /= 2;
+  fmv.s[3] /= 2;
+  
+  bmv.s[0] /= 2;
+  bmv.s[1] /= 2;
+  bmv.s[2] /= 2;
+  bmv.s[3] /= 2;
 
   xy >>= 1;
 
@@ -1637,8 +1642,8 @@ static __inline__ void renderFieldinFram
   *du++ = (2<<30) | (1<<28) | dw1[0];
   *du++ = xy;
   *du++ = (4<<16) | 8;
-  *du++ = *(uint *)&fmv[0];
-  *du++ = *(uint *)&bmv[0];
+  *du++ = fmv.u[0];
+  *du++ = bmv.u[0];
   if(usize) {
     PACK_CORR_DATA_SHORT(du,block_ptr);
   }
@@ -1648,8 +1653,8 @@ static __inline__ void renderFieldinFram
   *du++ = (2<<30) | (1<<28) | dw1[1];
   *du++ = xy;
   *du++ = (4<<16) | 8;
-  *du++ = *(uint *)&fmv[2];
-  *du++ = *(uint *)&bmv[2];
+  *du++ = fmv.u[1];
+  *du++ = bmv.u[1];
   if(usize) {
     block_ptr = (short *)((unsigned long)block_ptr + 16);
     PACK_CORR_DATA_SHORT(du,block_ptr);
@@ -1662,8 +1667,8 @@ static __inline__ void renderFieldinFram
   *dv++ = (3<<30) | (1<<28) | dw1[0];
   *dv++ = xy;
   *dv++ = (4<<16) | 8;
-  *dv++ = *(uint *)&fmv[0];
-  *dv++ = *(uint *)&bmv[0];
+  *dv++ = fmv.u[0];
+  *dv++ = bmv.u[0];
   if(vsize) {
     PACK_CORR_DATA_SHORT(dv,block_ptr);
   }
@@ -1673,8 +1678,8 @@ static __inline__ void renderFieldinFram
   *dv++ = (3<<30) | (1<<28) | dw1[1];
   *dv++ = xy;
   *dv++ = (4<<16) | 8;
-  *dv++ = *(uint *)&fmv[2];
-  *dv++ = *(uint *)&bmv[2];
+  *dv++ = fmv.u[1];
+  *dv++ = bmv.u[1];
   if(vsize) {
     block_ptr = (short *)((unsigned long)block_ptr + 16);
     PACK_CORR_DATA_SHORT(dv,block_ptr);
@@ -1701,8 +1706,8 @@ static __inline__ void renderFieldinFram
   register uint *dv = *datav;
 
   /* Motion Vectors */
-  short fmv[4];
-  short bmv[4];
+  su_t fmv;
+  su_t bmv;
   /* CBP */
   uint cbp = (uint)mb->coded_block_pattern;
   /* gfxblock dword 1 */
@@ -1728,15 +1733,15 @@ static __inline__ void renderFieldinFram
     ((cbp | ((cbp<<2) & 0x30))<<22);
 
 
-  fmv[0] = mb->PMV[0][0][1]/2;
-  fmv[1] = mb->PMV[0][0][0];
-  fmv[2] = mb->PMV[1][0][1]/2;
-  fmv[3] = mb->PMV[1][0][0];
-  
-  bmv[0] = mb->PMV[0][1][1]/2;
-  bmv[1] = mb->PMV[0][1][0];
-  bmv[2] = mb->PMV[1][1][1]/2;
-  bmv[3] = mb->PMV[1][1][0];
+  fmv.s[0] = mb->PMV[0][0][1]/2;
+  fmv.s[1] = mb->PMV[0][0][0];
+  fmv.s[2] = mb->PMV[1][0][1]/2;
+  fmv.s[3] = mb->PMV[1][0][0];
+  
+  bmv.s[0] = mb->PMV[0][1][1]/2;
+  bmv.s[1] = mb->PMV[0][1][0];
+  bmv.s[2] = mb->PMV[1][1][1]/2;
+  bmv.s[3] = mb->PMV[1][1][0];
 
   /*
     The i810 cannot use DCT0 directly with field motion, we have to
@@ -1772,8 +1777,8 @@ static __inline__ void renderFieldinFram
   *dy++ = (1<<30) | (2<<28) | dw1[0];
   *dy++ = xy;
   *dy++ = (8<<16) | 16;
-  *dy++ = *(uint *)&fmv[0];
-  *dy++ = *(uint *)&bmv[0];
+  *dy++ = fmv.u[0];
+  *dy++ = bmv.u[0];
   if(dw1[0] & (1<<27)) {
     PACK_CORR_DATA_0to1(dy,top_left_b,bottom_left_b);
   }
@@ -1786,8 +1791,8 @@ static __inline__ void renderFieldinFram
   *dy++ = (1<<30) | (2<<28) | dw1[1];
   *dy++ = xy;
   *dy++ = (8<<16) | 16;
-  *dy++ = *(uint *)&fmv[2];
-  *dy++ = *(uint *)&bmv[2];
+  *dy++ = fmv.u[1];
+  *dy++ = bmv.u[1];
   if(dw1[1] & (1<<27)) {
     top_left_b = (short *)((unsigned long)top_left_b + 16);
     bottom_left_b = (short *)((unsigned long)bottom_left_b + 16);
@@ -1800,15 +1805,15 @@ static __inline__ void renderFieldinFram
   }
   /* End Y Blocks */
 
-  fmv[0] /= 2;
-  fmv[1] /= 2;
-  fmv[2] /= 2;
-  fmv[3] /= 2;
-  
-  bmv[0] /= 2;
-  bmv[1] /= 2;
-  bmv[2] /= 2;
-  bmv[3] /= 2;
+  fmv.s[0] /= 2;
+  fmv.s[1] /= 2;
+  fmv.s[2] /= 2;
+  fmv.s[3] /= 2;
+  
+  bmv.s[0] /= 2;
+  bmv.s[1] /= 2;
+  bmv.s[2] /= 2;
+  bmv.s[3] /= 2;
 
   xy >>= 1;
 
@@ -1817,8 +1822,8 @@ static __inline__ void renderFieldinFram
   *du++ = (2<<30) | (1<<28) | dw1[0];
   *du++ = xy;
   *du++ = (4<<16) | 8;
-  *du++ = *(uint *)&fmv[0];
-  *du++ = *(uint *)&bmv[0];
+  *du++ = fmv.u[0];
+  *du++ = bmv.u[0];
   if(usize) {
     PACK_CORR_DATA_SHORT(du,block_ptr);
   }
@@ -1828,8 +1833,8 @@ static __inline__ void renderFieldinFram
   *du++ = (2<<30) | (1<<28) | dw1[1];
   *du++ = xy;
   *du++ = (4<<16) | 8;
-  *du++ = *(uint *)&fmv[2];
-  *du++ = *(uint *)&bmv[2];
+  *du++ = fmv.u[1];
+  *du++ = bmv.u[1];
   if(usize) {
     block_ptr = (short *)((unsigned long)block_ptr + 16);
     PACK_CORR_DATA_SHORT(du,block_ptr);
@@ -1842,8 +1847,8 @@ static __inline__ void renderFieldinFram
   *dv++ = (3<<30) | (1<<28) | dw1[0];
   *dv++ = xy;
   *dv++ = (4<<16) | 8;
-  *dv++ = *(uint *)&fmv[0];
-  *dv++ = *(uint *)&bmv[0];
+  *dv++ = fmv.u[0];
+  *dv++ = bmv.u[0];
   if(vsize) {
     PACK_CORR_DATA_SHORT(dv,block_ptr);
   }
@@ -1853,8 +1858,8 @@ static __inline__ void renderFieldinFram
   *dv++ = (3<<30) | (1<<28) | dw1[1];
   *dv++ = xy;
   *dv++ = (4<<16) | 8;
-  *dv++ = *(uint *)&fmv[2];
-  *dv++ = *(uint *)&bmv[2];
+  *dv++ = fmv.u[1];
+  *dv++ = bmv.u[1];
   if(vsize) {
     block_ptr = (short *)((unsigned long)block_ptr + 16);
     PACK_CORR_DATA_SHORT(dv,block_ptr);
@@ -1882,8 +1887,8 @@ static __inline__ void renderFrameinFram
   register uint *dv = *datav;
 
   /* Motion Vectors */
-  short fmv[2];
-  short bmv[2];
+  su_t fmv;
+  su_t bmv;
   /* gfxblock dword 1 */
   uint dw1;
 
@@ -1897,28 +1902,28 @@ static __inline__ void renderFrameinFram
     (((uint)mb->coded_block_pattern)<<22);
 
 
-  fmv[0] = mb->PMV[0][0][1];
-  fmv[1] = mb->PMV[0][0][0];
+  fmv.s[0] = mb->PMV[0][0][1];
+  fmv.s[1] = mb->PMV[0][0][0];
   
-  bmv[0] = mb->PMV[0][1][1];
-  bmv[1] = mb->PMV[0][1][0];
+  bmv.s[0] = mb->PMV[0][1][1];
+  bmv.s[1] = mb->PMV[0][1][0];
 
   /* Y Block */
   *dy++ = GFXBLOCK + 4 + (ysize>>2);
   *dy++ = (1<<30) | (3<<28) | dw1;
   *dy++ = xy;
   *dy++ = (16<<16) | 16;
-  *dy++ = *(uint *)fmv;
-  *dy++ = *(uint *)bmv;
+  *dy++ = fmv.u[0];
+  *dy++ = bmv.u[0];
   PACK_CORR_DATA(dy,block_ptr,ysize);
   block_ptr = (short *)((unsigned long)block_ptr + ysize);
   /* End Y Blocks */
 
-  fmv[0] /= 2;
-  fmv[1] /= 2;
+  fmv.s[0] /= 2;
+  fmv.s[1] /= 2;
   
-  bmv[0] /= 2;
-  bmv[1] /= 2;
+  bmv.s[0] /= 2;
+  bmv.s[1] /= 2;
 
   xy >>= 1;
 
@@ -1927,8 +1932,8 @@ static __inline__ void renderFrameinFram
   *du++ = (2<<30) | (1<<28) | dw1;
   *du++ = xy;
   *du++ = (8<<16) | 8;
-  *du++ = *(uint *)fmv;
-  *du++ = *(uint *)bmv;
+  *du++ = fmv.u[0];
+  *du++ = bmv.u[0];
   PACK_CORR_DATA(du,block_ptr,usize);
   block_ptr = (short *)((unsigned long)block_ptr + usize);
   /* End U Block */
@@ -1938,8 +1943,8 @@ static __inline__ void renderFrameinFram
   *dv++ = (3<<30) | (1<<28) | dw1;
   *dv++ = xy;
   *dv++ = (8<<16) | 8;
-  *dv++ = *(uint *)fmv;
-  *dv++ = *(uint *)bmv;
+  *dv++ = fmv.u[0];
+  *dv++ = bmv.u[0];
   PACK_CORR_DATA(dv,block_ptr,vsize);
   block_ptr = (short *)((unsigned long)block_ptr + vsize);
   /* End V Block */
@@ -1963,8 +1968,8 @@ static __inline__ void renderFrameinFram
   register uint *dv = *datav;
 
   /* Motion Vectors */
-  short fmv[4];
-  short bmv[4];
+  su_t fmv;
+  su_t bmv;
 
   short * top_left_b = NULL;
   short * top_right_b = NULL;
@@ -1982,11 +1987,11 @@ static __inline__ void renderFrameinFram
   uint dw1 = type_table[mb->macroblock_type & 0xf] |
     (((uint)mb->coded_block_pattern)<<22);
 
-  fmv[0] = mb->PMV[0][0][1];
-  fmv[1] = mb->PMV[0][0][0];
+  fmv.s[0] = mb->PMV[0][0][1];
+  fmv.s[1] = mb->PMV[0][0][0];
   
-  bmv[0] = mb->PMV[0][1][1];
-  bmv[1] = mb->PMV[0][1][0];
+  bmv.s[0] = mb->PMV[0][1][1];
+  bmv.s[1] = mb->PMV[0][1][0];
 
   /*
     It is easiest to find out what blocks are in need of reading first
@@ -2026,8 +2031,8 @@ static __inline__ void renderFrameinFram
   *dy++ = (1<<30) | (3<<28) | dw1;
   *dy++ = xy;
   *dy++ = (16<<16) | 16;
-  *dy++ = *(uint *)fmv;
-  *dy++ = *(uint *)bmv;
+  *dy++ = fmv.u[0];
+  *dy++ = bmv.u[0];
   if(dw1 & (1<<27)) {
     PACK_CORR_DATA_1to0(dy,top_left_b,bottom_left_b);
     top_left_b = (short *)((unsigned long)top_left_b + 64);
@@ -2046,11 +2051,11 @@ static __inline__ void renderFrameinFram
   }
   /* End Y Block */
 
-  fmv[0] /= 2;
-  fmv[1] /= 2;
+  fmv.s[0] /= 2;
+  fmv.s[1] /= 2;
   
-  bmv[0] /= 2;
-  bmv[1] /= 2;
+  bmv.s[0] /= 2;
+  bmv.s[1] /= 2;
 
   xy >>= 1;
 
@@ -2059,8 +2064,8 @@ static __inline__ void renderFrameinFram
   *du++ = (2<<30) | (1<<28) | dw1;
   *du++ = xy;
   *du++ = (8<<16) | 8;
-  *du++ = *(uint *)fmv;
-  *du++ = *(uint *)bmv;
+  *du++ = fmv.u[0];
+  *du++ = bmv.u[0];
   PACK_CORR_DATA(du,block_ptr,usize);
   block_ptr = (short *)((unsigned long)block_ptr + usize);
 
@@ -2069,8 +2074,8 @@ static __inline__ void renderFrameinFram
   *dv++ = (3<<30) | (1<<28) | dw1;
   *dv++ = xy;
   *dv++ = (8<<16) | 8;
-  *dv++ = *(uint *)fmv;
-  *dv++ = *(uint *)bmv;
+  *dv++ = fmv.u[0];
+  *dv++ = bmv.u[0];
   PACK_CORR_DATA(dv,block_ptr,vsize);
   block_ptr = (short *)((unsigned long)block_ptr + vsize);
 
@@ -2093,8 +2098,8 @@ static __inline__ void renderDualPrimein
   register uint *dv = *datav;
 
   /* Motion Vectors */
-  short fmv[4];
-  short bmv[4];
+  su_t fmv;
+  su_t bmv;
   /* gfxblock dword 1 */
   uint dw1[2];
 
@@ -2115,23 +2120,23 @@ static __inline__ void renderDualPrimein
 	     ((mb->coded_block_pattern & 0xc)<<2))<<22) |
     3<<12 | 3<<6 | 3<<3 | 2;
   
-  fmv[0] = mb->PMV[0][0][1];
-  fmv[1] = mb->PMV[0][0][0];
-  bmv[0] = mb->PMV[1][0][1];
-  bmv[1] = mb->PMV[1][0][0];
-  
-  fmv[2] = mb->PMV[0][0][1];
-  fmv[3] = mb->PMV[0][0][0];
-  bmv[2] = mb->PMV[1][1][1];
-  bmv[3] = mb->PMV[1][1][0];
+  fmv.s[0] = mb->PMV[0][0][1];
+  fmv.s[1] = mb->PMV[0][0][0];
+  bmv.s[0] = mb->PMV[1][0][1];
+  bmv.s[1] = mb->PMV[1][0][0];
+  
+  fmv.s[2] = mb->PMV[0][0][1];
+  fmv.s[3] = mb->PMV[0][0][0];
+  bmv.s[2] = mb->PMV[1][1][1];
+  bmv.s[3] = mb->PMV[1][1][0];
 
   /* First Y Block */
   *dy++ = GFXBLOCK + 4 + (y1size>>2);
   *dy++ = (1<<30) | (2<<28) | dw1[0];
   *dy++ = xy;
   *dy++ = (8<<16) | 16;
-  *dy++ = *(uint *)fmv;
-  *dy++ = *(uint *)bmv;;
+  *dy++ = fmv.u[0];
+  *dy++ = bmv.u[0];;
   PACK_CORR_DATA(dy,block_ptr,y1size);
   block_ptr = (short *)((unsigned long)block_ptr + y1size);
 
@@ -2140,20 +2145,20 @@ static __inline__ void renderDualPrimein
   *dy++ = (1<<30) | (2<<28) | dw1[1];
   *dy++ = xy;
   *dy++ = (8<<16) | 16;
-  *dy++ = *(uint *)&fmv[2];
-  *dy++ = *(uint *)&bmv[2];
+  *dy++ = fmv.u[1];
+  *dy++ = bmv.u[1];
   PACK_CORR_DATA(dy,block_ptr,y2size);
   block_ptr = (short *)((unsigned long)block_ptr + y2size);
 
-  fmv[0] /= 2;
-  fmv[1] /= 2;
-  bmv[0] /= 2;
-  bmv[1] /= 2;
-  
-  fmv[2] /= 2;
-  fmv[3] /= 2;
-  bmv[2] /= 2;
-  bmv[3] /= 2;
+  fmv.s[0] /= 2;
+  fmv.s[1] /= 2;
+  bmv.s[0] /= 2;
+  bmv.s[1] /= 2;
+  
+  fmv.s[2] /= 2;
+  fmv.s[3] /= 2;
+  bmv.s[2] /= 2;
+  bmv.s[3] /= 2;
 
   xy >>= 1;
 
@@ -2162,8 +2167,8 @@ static __inline__ void renderDualPrimein
   *du++ = (2<<30) | (1<<28) | dw1[0];
   *du++ = xy;
   *du++ = (4<<16) | 8;
-  *du++ = *(uint *)fmv;
-  *du++ = *(uint *)bmv;
+  *du++ = fmv.u[0];
+  *du++ = bmv.u[0];
   if(dw1[0] & (1<<23)) {
     PACK_CORR_DATA_SHORT(du,block_ptr);
   }
@@ -2173,8 +2178,8 @@ static __inline__ void renderDualPrimein
   *du++ = (2<<30) | (1<<28) | dw1[1];
   *du++ = xy;
   *du++ = (4<<16) | 8;
-  *du++ = *(uint *)&fmv[2];
-  *du++ = *(uint *)&bmv[2];
+  *du++ = fmv.u[1];
+  *du++ = bmv.u[1];
   if(dw1[1] & (1<<23)) {
     block_ptr = (short *)((unsigned long)block_ptr + 16);
     PACK_CORR_DATA_SHORT(du,block_ptr);
@@ -2187,8 +2192,8 @@ static __inline__ void renderDualPrimein
   *dv++ = (3<<30) | (1<<28) | dw1[0];
   *dv++ = xy;
   *dv++ = (4<<16) | 8;
-  *dv++ = *(uint *)fmv;
-  *dv++ = *(uint *)bmv;
+  *dv++ = fmv.u[0];
+  *dv++ = bmv.u[0];
   if(dw1[0] & (1<<22)) {
     PACK_CORR_DATA_SHORT(dv,block_ptr);
   }
@@ -2198,8 +2203,8 @@ static __inline__ void renderDualPrimein
   *dv++ = (3<<30) | (1<<28) | dw1[1];
   *dv++ = xy;
   *dv++ = (4<<16) | 8;
-  *dv++ = *(uint *)&fmv[2];
-  *dv++ = *(uint *)&bmv[2];
+  *dv++ = fmv.u[1];
+  *dv++ = bmv.u[1];
   if(dw1[1] & (1<<22)) {
     block_ptr = (short *)((unsigned long)block_ptr + 16);
     PACK_CORR_DATA_SHORT(dv,block_ptr);
@@ -2228,8 +2233,8 @@ static __inline__ void renderDualPrimein
   register uint *dv = *datav;
 
   /* Motion Vectors */
-  short fmv[4];
-  short bmv[4];
+  su_t fmv;
+  su_t bmv;
   /* gfxblock dword 1 */
   uint dw1[2];
 
@@ -2255,15 +2260,15 @@ static __inline__ void renderDualPrimein
   dw1[1] = ((cbp | ((cbp<<2) & 0x30))<<22) |
     3<<12 | 3<<6 | 3<<3 | 2;
   
-  fmv[0] = mb->PMV[0][0][1];
-  fmv[1] = mb->PMV[0][0][0];
-  bmv[0] = mb->PMV[1][0][1];
-  bmv[1] = mb->PMV[1][0][0];
-  
-  fmv[2] = mb->PMV[0][0][1];
-  fmv[3] = mb->PMV[0][0][0];
-  bmv[2] = mb->PMV[1][1][1];
-  bmv[3] = mb->PMV[1][1][0];
+  fmv.s[0] = mb->PMV[0][0][1];
+  fmv.s[1] = mb->PMV[0][0][0];
+  bmv.s[0] = mb->PMV[1][0][1];
+  bmv.s[1] = mb->PMV[1][0][0];
+  
+  fmv.s[2] = mb->PMV[0][0][1];
+  fmv.s[3] = mb->PMV[0][0][0];
+  bmv.s[2] = mb->PMV[1][1][1];
+  bmv.s[3] = mb->PMV[1][1][0];
   
   /*
     The i810 cannot use DCT0 directly with field motion, we have to
@@ -2299,8 +2304,8 @@ static __inline__ void renderDualPrimein
   *dy++ = (1<<30) | (2<<28) | dw1[0];
   *dy++ = xy;
   *dy++ = (8<<16) | 16;
-  *dy++ = *(uint *)fmv;
-  *dy++ = *(uint *)bmv;
+  *dy++ = fmv.u[0];
+  *dy++ = bmv.u[0];
   if(cbp & 0x20) {
     PACK_CORR_DATA_0to1(dy,top_left_b,bottom_left_b);
   }
@@ -2313,8 +2318,8 @@ static __inline__ void renderDualPrimein
   *dy++ = (1<<30) | (2<<28) | dw1[1];
   *dy++ = xy;
   *dy++ = (8<<16) | 16;
-  *dy++ = *(uint *)&fmv[2];
-  *dy++ = *(uint *)&bmv[2];
+  *dy++ = fmv.u[1];
+  *dy++ = bmv.u[1];
   if(cbp & 0x20) {
     top_left_b = (short *)((unsigned long)top_left_b + 16);
     bottom_left_b = (short *)((unsigned long)bottom_left_b + 16);
@@ -2328,15 +2333,15 @@ static __inline__ void renderDualPrimein
   /* End Y Blocks */
 
 
-  fmv[0] /= 2;
-  fmv[1] /= 2;
-  bmv[0] /= 2;
-  bmv[1] /= 2;
-  
-  fmv[2] /= 2;
-  fmv[3] /= 2;
-  bmv[2] /= 2;
-  bmv[3] /= 2;
+  fmv.s[0] /= 2;
+  fmv.s[1] /= 2;
+  bmv.s[0] /= 2;
+  bmv.s[1] /= 2;
+  
+  fmv.s[2] /= 2;
+  fmv.s[3] /= 2;
+  bmv.s[2] /= 2;
+  bmv.s[3] /= 2;
 
   xy >>= 1;
 
@@ -2345,8 +2350,8 @@ static __inline__ void renderDualPrimein
   *du++ = (2<<30) | (1<<28) | dw1[0];
   *du++ = xy;
   *du++ = (4<<16) | 8;
-  *du++ = *(uint *)fmv;
-  *du++ = *(uint *)bmv;
+  *du++ = fmv.u[0];
+  *du++ = bmv.u[0];
   if(cbp & (1<<23)) {
     PACK_CORR_DATA_SHORT(du,block_ptr);
   }
@@ -2356,8 +2361,8 @@ static __inline__ void renderDualPrimein
   *du++ = (2<<30) | (1<<28) | dw1[1];
   *du++ = xy;
   *du++ = (4<<16) | 8;
-  *du++ = *(uint *)&fmv[2];
-  *du++ = *(uint *)&bmv[2];
+  *du++ = fmv.u[1];
+  *du++ = bmv.u[1];
   if(cbp & (1<<23)) {
     block_ptr = (short *)((unsigned long)block_ptr + 16);
     PACK_CORR_DATA_SHORT(du,block_ptr);
@@ -2370,8 +2375,8 @@ static __inline__ void renderDualPrimein
   *dv++ = (3<<30) | (1<<28) | dw1[0];
   *dv++ = xy;
   *dv++ = (4<<16) | 8;
-  *dv++ = *(uint *)fmv;
-  *dv++ = *(uint *)bmv;
+  *dv++ = fmv.u[0];
+  *dv++ = bmv.u[0];
   if(cbp & (1<<22)) {
     PACK_CORR_DATA_SHORT(dv,block_ptr);
   }
@@ -2381,8 +2386,8 @@ static __inline__ void renderDualPrimein
   *dv++ = (3<<30) | (1<<28) | dw1[1];
   *dv++ = xy;
   *dv++ = (4<<16) | 8;
-  *dv++ = *(uint *)&fmv[2];
-  *dv++ = *(uint *)&bmv[2];
+  *dv++ = fmv.u[1];
+  *dv++ = bmv.u[1];
   if(cbp & (1<<22)) {
     block_ptr = (short *)((unsigned long)block_ptr + 16);
     PACK_CORR_DATA_SHORT(dv,block_ptr);
diff-tree 498abf474b90b04bc4085397a209cc493d98d15c (from parents)
Merge: c26f0737e2c0f000f67f21ef6007b351160036a4 3de82ff3938c6559c90079be0c28dc507d62f79e
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Mon Apr 10 19:41:50 2006 -0700

    Merge branch 'modesetting-origin' into modesetting

diff-tree c26f0737e2c0f000f67f21ef6007b351160036a4 (from parents)
Merge: 11ad8a590d65849be00e1be4e9dd52c1159a4f24 692a4a4bafd4cab197b761cda22368581b78f996
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Mon Apr 10 19:41:41 2006 -0700

    Merge in master to modesetting

diff --cc src/i830_cursor.c
index ea472fa,e465b98..79d950e
@@@ -92,8 -93,8 +93,8 @@@
  		MCURSOR_PIPE_SELECT);
        temp |= CURSOR_MODE_DISABLE;
        temp |= (pI830->pipe << 28);
--      if(pI830->CursorIsARGB)
--         temp |= MCURSOR_GAMMA_ENABLE;
++/*      if(pI830->CursorIsARGB)
++         temp |= MCURSOR_GAMMA_ENABLE; */
        /* Need to set control, then address. */
        OUTREG(CURSOR_A_CONTROL, temp);
        if (pI830->CursorIsARGB)
@@@ -114,6 -115,8 +115,8 @@@
        temp &= ~(CURSOR_FORMAT_MASK | CURSOR_GAMMA_ENABLE |
  		CURSOR_ENABLE  | CURSOR_STRIDE_MASK);
        temp |= (CURSOR_FORMAT_3C);
 -      if (pI830->CursorIsARGB)
 -         temp |= CURSOR_GAMMA_ENABLE;
++/*      if (pI830->CursorIsARGB)
++         temp |= CURSOR_GAMMA_ENABLE;*/
        /* This initialises the format and leave the cursor disabled. */
        OUTREG(CURSOR_CONTROL, temp);
        /* Need to set address and size after disabling. */
@@@ -482,7 -485,7 +485,7 @@@
        temp = INREG(CURSOR_A_CONTROL);
        temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
        if (pI830->CursorIsARGB)
-          temp |= CURSOR_MODE_64_ARGB_AX;
 -         temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
++         temp |= CURSOR_MODE_64_ARGB_AX /* | MCURSOR_GAMMA_ENABLE*/;
        else
           temp |= CURSOR_MODE_64_4C_AX;
        temp |= (pI830->pipe << 28); /* Connect to correct pipe */
@@@ -506,7 -509,7 +509,7 @@@
        temp &= ~(CURSOR_FORMAT_MASK);
        temp |= CURSOR_ENABLE;
        if (pI830->CursorIsARGB)
-          temp |= CURSOR_FORMAT_ARGB;
 -         temp |= CURSOR_FORMAT_ARGB | CURSOR_GAMMA_ENABLE;
++         temp |= CURSOR_FORMAT_ARGB /* | CURSOR_GAMMA_ENABLE*/;
        else 
           temp |= CURSOR_FORMAT_3C;
        OUTREG(CURSOR_CONTROL, temp);
diff --cc src/i830_display.c
index 3b92e4f,0000000..0338e5e
mode 100644,000000..100644
@@@ -1,654 -1,0 +1,654 @@@
 +#ifdef HAVE_CONFIG_H
 +#include "config.h"
 +#endif
 +
 +#include "xf86.h"
 +#include "xf86_ansic.h"
 +#include "i830.h"
 +#include "i830_bios.h"
 +#include "i830_display.h"
 +
 +/** Returns the pixel clock for the given refclk and divisors. */
 +static int i830_clock(int refclk, int m1, int m2, int n, int p1, int p2)
 +{
 +    return refclk * (5 * m1 + m2) / n / (p1 * p2);
 +}
 +
 +static void
 +i830PrintPll(char *prefix, int refclk, int m1, int m2, int n, int p1, int p2)
 +{
 +    int dotclock;
 +
 +    dotclock = i830_clock(refclk, m1, m2, n, p1, p2);
 +
 +    ErrorF("%s: dotclock %d ((%d, %d), %d, (%d, %d))\n", prefix, dotclock,
 +	   m1, m2, n, p1, p2);
 +}
 +
 +/**
 + * Returns whether the given set of divisors are valid for a given refclk with
 + * the given outputs.
 + *
 + * The equation for these divisors would be:
 + * clk = refclk * (5 * m1 + m2) / n / (p1 * p2)
 + */
 +static Bool
 +i830PllIsValid(ScrnInfoPtr pScrn, int outputs, int refclk, int m1, int m2,
 +	       int n, int p1, int p2)
 +{
 +    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;
 +    int min_p, max_p;
 +
 +    min_p = 5;
 +    max_p = 80;
 +    if (pI830->PciInfo->chipType >= PCI_CHIP_I915_G) {
 +	min_m1 = 10;
 +	max_m1 = 20;
 +	min_m2 = 5;
 +	max_m2 = 9;
 +	min_m = 70;
 +	max_m = 120;
 +	min_n = 3;
 +	max_n = 8;
 +	if (outputs & PIPE_LCD_ACTIVE) {
 +	    min_p = 7;
 +	    max_p = 98;
 +	}
 +    } else {
 +	min_m1 = 16;
 +	max_m1 = 24;
 +	min_m2 = 7;
 +	max_m2 = 11;
 +	min_m = 90;
 +	max_m = 130;
 +	min_n = 4;
 +	max_n = 8;
 +	if (outputs & PIPE_LCD_ACTIVE) {
 +	    min_n = 3;
 +	    min_m = 88;
 +	}
 +    }
 +
 +    p = p1 * p2;
 +    m = 5 * m1 + m2;
 +    vco = refclk * m / n;
 +    dotclock = i830_clock(refclk, m1, m2, n, p1, p2);
 +
 +    if (p1 < 1 || p1 > 8)
 +	return FALSE;
 +    if (p < min_p || p > max_p)
 +	return FALSE;
 +    if (m2 < min_m2 || m2 > max_m2)
 +	return FALSE;
 +    if (m1 < min_m1 || m1 > max_m1)
 +	return FALSE;
 +    if (m1 <= m2)
 +	return FALSE;
 +    if (m < min_m || m > max_m)
 +	return FALSE;
 +    if (n < min_n || n > max_n)
 +	return FALSE;
 +    if (vco < 1400000 || vco > 2800000)
 +	return FALSE;
 +    /* XXX: We may need to be checking "Dot clock" depending on the multiplier,
 +     * output, etc., rather than just a single range.
 +     */
 +    if (dotclock < 20000 || dotclock > 400000)
 +	return FALSE;
 +
 +    return TRUE;
 +}
 +
 +#if 0
 +int
 +i830ReadAndReportPLL(ScrnInfoPtr pScrn)
 +{
 +    I830Ptr pI830 = I830PTR(pScrn);
 +    CARD32 temp, dpll;
 +    int refclk, m1, m2, n, p1, p2;
 +
 +    refclk = 96000;	/* XXX: The refclk may be 100000 for the LVDS */
 +
 +    dpll = INREG(DPLL_A);
 +    switch ((dpll & DPLL_FPA01_P1_POST_DIV_MASK) >> 16) {
 +    case 0x01:
 +	p1 = 1;
 +	break;
 +    case 0x02:
 +	p1 = 2;
 +	break;
 +    case 0x04:
 +	p1 = 3;
 +	break;
 +    case 0x08:
 +	p1 = 4;
 +	break;
 +    case 0x10:
 +	p1 = 5;
 +	break;
 +    case 0x20:
 +	p1 = 6;
 +	break;
 +    case 0x40:
 +	p1 = 7;
 +	break;
 +    case 0x80:
 +	p1 = 8;
 +	break;
 +    default:
 +	FatalError("Unknown p1 clock div: 0x%x\n",
 +		   dpll & DPLL_FPA01_P1_POST_DIV_MASK);
 +    }
 +
 +    switch (dpll & DPLL_P2_CLOCK_DIV_MASK) {
 +    case DPLL_DAC_SERIAL_P2_CLOCK_DIV_5:
 +	p2 = 5;
 +	break;
 +    case DPLL_DAC_SERIAL_P2_CLOCK_DIV_10:
 +	p2 = 10;
 +	break;
 +/* XXX:
 +    case DPLLB_LVDS_P2_CLOCK_DIV_7:
 +	p2 = 7;
 +	break;
 +    case DPLLB_LVDS_P2_CLOCK_DIV_14:
 +	p2 = 14;
 +	break;
 +*/
 +    default:
 +	FatalError("Unknown p2 clock div: 0x%x\n", dpll & DPLL_P2_CLOCK_DIV_MASK);
 +    }
 +
 +    if (dpll & DISPLAY_RATE_SELECT_FPA1)
 +	temp = INREG(FPA1);
 +    else
 +	temp = INREG(FPA0);
 +    n = (temp & FP_N_DIV_MASK) >> 16;
 +    m1 = (temp & FP_M1_DIV_MASK) >> 8;
 +    m2 = (temp & FP_M2_DIV_MASK);
 +
 +    i830PrintPll("FPA", refclk, m1, m2, n, p1, p2);
 +    ErrorF("clock settings for FPA0 look %s\n",
 +	   i830PllIsValid(refclk, m1, m2, n, p1, p2) ? "good" : "bad");
 +    ErrorF("clock regs: 0x%08x, 0x%08x\n", dpll, temp);    
 +}
 +#endif
 +
 +/**
 + * Returns a set of divisors for the desired target clock with the given refclk,
 + * or FALSE.  Divisor values are the actual divisors for
 + * clk = refclk * (5 * m1 + m2) / n / (p1 * p2)
 + */
 +static Bool
 +i830FindBestPLL(ScrnInfoPtr pScrn, int outputs, int target, int refclk,
 +		int *outm1, int *outm2, int *outn, int *outp1, int *outp2)
 +{
 +    I830Ptr pI830 = I830PTR(pScrn);
 +    int m1, m2, n, p1, p2;
 +    int err = target;
 +    int min_m1, max_m1, min_m2, max_m2;
 +
 +    if (pI830->PciInfo->chipType >= PCI_CHIP_I915_G) {
 +	min_m1 = 10;
 +	max_m1 = 20;
 +	min_m2 = 5;
 +	max_m2 = 9;
 +    } else {
 +	min_m1 = 16;
 +	max_m1 = 24;
 +	min_m2 = 7;
 +	max_m2 = 11;
 +    }
 +
 +    if (outputs & PIPE_LCD_ACTIVE) {
 +	if (target < 200000) /* XXX: Is this the right cutoff? */
 +	    p2 = 14;
 +	else
 +	    p2 = 7;
 +    } else {
 +	if (target < 200000)
 +	    p2 = 10;
 +	else
 +	    p2 = 5;
 +    }
 +
 +    for (m1 = min_m1; m1 <= max_m1; m1++) {
 +	for (m2 = min_m2; m2 < max_m2; m2++) {
 +	    for (n = 3; n <= 8; n++) {
 +		for (p1 = 1; p1 <= 8; p1++) {
 +		    int clock, this_err;
 +
 +		    if (!i830PllIsValid(pScrn, outputs, refclk, m1, m2, n,
 +					p1, p2)) {
 +			continue;
 +		    }
 +
 +		    clock = i830_clock(refclk, m1, m2, n, p1, p2);
 +		    this_err = abs(clock - target);
 +		    if (this_err < err) {
 +			*outm1 = m1;
 +			*outm2 = m2;
 +			*outn = n;
 +			*outp1 = p1;
 +			*outp2 = p2;
 +			err = this_err;
 +		    }
 +		}
 +	    }
 +	}
 +    }
 +
 +    return (err != target);
 +}
 +
 +static void
 +i830WaitForVblank(ScrnInfoPtr pScreen)
 +{
 +    /* Wait for 20ms, i.e. one cycle at 50hz. */
 +    usleep(20000);
 +}
 +
 +void
 +i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y)
 +{
 +    I830Ptr pI830 = I830PTR(pScrn);
 +    unsigned long Start;
 +
 +    if (I830IsPrimary(pScrn))
 +	Start = pI830->FrontBuffer.Start;
 +    else {
 +	I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
 +	Start = pI8301->FrontBuffer2.Start;
 +    }
 +
 +    if (pipe == 0)
 +	OUTREG(DSPABASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
 +    else
 +	OUTREG(DSPBBASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
 +}
 +
 +/**
 + * Sets the given video mode on the given pipe.  Assumes that plane A feeds
 + * pipe A, and plane B feeds pipe B.  Should not affect the other planes/pipes.
 + */
 +static Bool
 +i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe)
 +{
 +    I830Ptr pI830 = I830PTR(pScrn);
-     int m1, m2, n, p1, p2;
++    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;
 +    CARD32 pipesrc, dspsize, adpa;
 +    Bool ok;
 +    int refclk = 96000;
 +    int outputs;
 +
 +    ErrorF("Requested pix clock: %d\n", pMode->Clock);
 +
 +    if (pipe == 0)
 +	outputs = pI830->operatingDevices & 0xff;
 +    else
 +	outputs = (pI830->operatingDevices >> 8) & 0xff;
 +
 +    if ((outputs & PIPE_LCD_ACTIVE) && (outputs & ~PIPE_LCD_ACTIVE)) {
 +	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 +		   "Can't enable LVDS and non-LVDS on the same pipe\n");
 +	return FALSE;
 +    }
 +    if (((outputs & PIPE_TV_ACTIVE) && (outputs & ~PIPE_TV_ACTIVE)) ||
 +	((outputs & PIPE_TV2_ACTIVE) && (outputs & ~PIPE_TV2_ACTIVE))) {
 +	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 +		   "Can't enable a TV and any other output on the same pipe\n");
 +	return FALSE;
 +    }
 +    if (pipe == 0 && (outputs & PIPE_LCD_ACTIVE)) {
 +	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 +		   "Can't support LVDS on pipe A\n");
 +	return FALSE;
 +    }
 +
 +    ok = i830FindBestPLL(pScrn, outputs, pMode->Clock, refclk, &m1, &m2, &n,
 +			 &p1, &p2);
 +    if (!ok) {
 +	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 +		   "Couldn't find PLL settings for mode!\n");
 +	return FALSE;
 +    }
 +
 +    dpll = DPLL_VCO_ENABLE | DPLL_VGA_MODE_DIS;
 +    if (outputs & PIPE_LCD_ACTIVE)
 +	dpll |= DPLLB_MODE_LVDS;
 +    else
 +	dpll |= DPLLB_MODE_DAC_SERIAL;
 +
 +    dpll |= (1 << (p1 - 1)) << 16;
 +    switch (p2) {
 +    case 5:
 +	dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5;
 +	break;
 +    case 7:
 +	dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7;
 +	break;
 +    case 10:
 +	dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10;
 +	break;
 +    case 14:
 +	dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
 +	break;
 +    }
 +    if (outputs & (PIPE_TV_ACTIVE | PIPE_TV2_ACTIVE))
 +	dpll |= PLL_REF_INPUT_TVCLKIN;
 +    else
 +	dpll |= PLL_REF_INPUT_DREFCLK;
 +    dpll |= SDV0_DEFAULT_MULTIPLIER;
 +
 +    fp = ((n - 2) << 16) | ((m1 - 2) << 8) | (m2 - 2);
 +
 +    htot = (pMode->CrtcHDisplay - 1) | ((pMode->CrtcHTotal - 1) << 16);
 +    hblank = (pMode->CrtcHBlankStart - 1) | ((pMode->CrtcHBlankEnd - 1) << 16);
 +    hsync = (pMode->CrtcHSyncStart - 1) | ((pMode->CrtcHSyncEnd - 1) << 16);
 +    vtot = (pMode->CrtcVDisplay - 1) | ((pMode->CrtcVTotal - 1) << 16);
 +    vblank = (pMode->CrtcVBlankStart - 1) | ((pMode->CrtcVBlankEnd - 1) << 16);
 +    vsync = (pMode->CrtcVSyncStart - 1) | ((pMode->CrtcVSyncEnd - 1) << 16);
 +    pipesrc = ((pMode->HDisplay - 1) << 16) | (pMode->VDisplay - 1);
 +    dspsize = ((pMode->VDisplay - 1) << 16) | (pMode->HDisplay - 1);
 +    if (outputs & PIPE_LCD_ACTIVE && i830GetLVDSInfoFromBIOS(pScrn) &&
 +	pI830->panel_fixed_hactive != 0)
 +    {
 +	/* To enable panel fitting, we need to set the pipe timings to that of
 +	 * the screen at its full resolution.  So, drop the timings from the
 +	 * BIOS VBT tables here.
 +	 */
 +	htot = (pI830->panel_fixed_hactive - 1) |
 +		((pI830->panel_fixed_hactive + pI830->panel_fixed_hblank - 1)
 +		 << 16);
 +	hblank = (pI830->panel_fixed_hactive - 1) |
 +		((pI830->panel_fixed_hactive + pI830->panel_fixed_hblank - 1)
 +		 << 16);
 +	hsync = (pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff - 1) |
 +		((pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff +
 +		  pI830->panel_fixed_hsyncwidth - 1) << 16);
 +
 +	vtot = (pI830->panel_fixed_vactive - 1) |
 +		((pI830->panel_fixed_vactive + pI830->panel_fixed_vblank - 1)
 +		 << 16);
 +	vblank = (pI830->panel_fixed_vactive - 1) |
 +		((pI830->panel_fixed_vactive + pI830->panel_fixed_vblank - 1)
 +		 << 16);
 +	vsync = (pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff - 1) |
 +		((pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff +
 +		  pI830->panel_fixed_vsyncwidth - 1) << 16);
 +    }
 +#if 0
 +    ErrorF("htot: 0x%08x, hblank: 0x%08x, hsync: 0x%08x\n", htot, hblank, hsync);
 +    ErrorF("vtot: 0x%08x, vblank: 0x%08x, vsync: 0x%08x\n", vtot, vblank, vsync);
 +#endif
 +
 +    adpa = INREG(ADPA);
 +    adpa &= ~(ADPA_HSYNC_ACTIVE_HIGH | ADPA_VSYNC_ACTIVE_HIGH);
 +    adpa &= ~(ADPA_VSYNC_CNTL_DISABLE | ADPA_HSYNC_CNTL_DISABLE);
 +    adpa |= ADPA_DAC_ENABLE;
 +    if (pMode->Flags & V_PHSYNC)
 +	adpa |= ADPA_HSYNC_ACTIVE_HIGH;
 +    if (pMode->Flags & V_PVSYNC)
 +	adpa |= ADPA_VSYNC_ACTIVE_HIGH;
 +
 +    i830PrintPll("chosen", refclk, m1, m2, n, p1, p2);
 +    ErrorF("clock settings for chosen look %s\n",
 +	   i830PllIsValid(pScrn, outputs, refclk, m1, m2, n, p1, p2) ?
 +			  "good" : "bad");
 +    ErrorF("clock regs: 0x%08x, 0x%08x\n", (int)dpll, (int)fp);
 +
 +    dspcntr = DISPLAY_PLANE_ENABLE;
 +    switch (pScrn->bitsPerPixel) {
 +    case 8:
 +	dspcntr |= DISPPLANE_8BPP | DISPPLANE_GAMMA_ENABLE;
 +	break;
 +    case 16:
 +	if (pScrn->depth == 15)
 +	    dspcntr |= DISPPLANE_15_16BPP;
 +	else
 +	    dspcntr |= DISPPLANE_16BPP;
 +	break;
 +    case 32:
 +	dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
 +	break;
 +    default:
 +	FatalError("unknown display bpp\n");
 +    }
 +
 +    adpa = ADPA_DAC_ENABLE;
 +    if (pMode->Flags & V_PHSYNC)
 +	adpa |= ADPA_HSYNC_ACTIVE_HIGH;
 +    if (pMode->Flags & V_PVSYNC)
 +	adpa |= ADPA_VSYNC_ACTIVE_HIGH;
 +    
 +    if (pipe == 0) {
 +	dspcntr |= DISPPLANE_SEL_PIPE_A;
 +	adpa |= ADPA_PIPE_A_SELECT;
 +    } else {
 +	dspcntr |= DISPPLANE_SEL_PIPE_B;
 +	adpa |= ADPA_PIPE_B_SELECT;
 +    }
 +
 +    OUTREG(VGACNTRL, VGA_DISP_DISABLE);
 +
 +    /* Set up display timings and PLLs for the pipe. */
 +    if (pipe == 0) {
 +	/* First, disable display planes */
 +	temp = INREG(DSPACNTR);
 +	OUTREG(DSPACNTR, temp & ~DISPLAY_PLANE_ENABLE);
 +
 +	/* Wait for vblank for the disable to take effect */
 +	i830WaitForVblank(pScrn);
 +
 +	/* Next, disable display pipes */
 +	temp = INREG(PIPEACONF);
 +	OUTREG(PIPEACONF, temp & ~PIPEACONF_ENABLE);
 +
 +	OUTREG(FPA0, fp);
 +	OUTREG(DPLL_A, dpll);
 +	OUTREG(HTOTAL_A, htot);
 +	OUTREG(HBLANK_A, hblank);
 +	OUTREG(HSYNC_A, hsync);
 +	OUTREG(VTOTAL_A, vtot);
 +	OUTREG(VBLANK_A, vblank);
 +	OUTREG(VSYNC_A, vsync);
 +	OUTREG(DSPASTRIDE, pScrn->displayWidth * pI830->cpp);
 +	OUTREG(DSPASIZE, dspsize);
 +	OUTREG(DSPAPOS, 0);
 +	i830PipeSetBase(pScrn, pipe, pScrn->frameX0, pScrn->frameY0);
 +	OUTREG(PIPEASRC, pipesrc);
 +
 +	/* Then, turn the pipe on first */
 +	temp = INREG(PIPEACONF);
 +	OUTREG(PIPEACONF, temp | PIPEACONF_ENABLE);
 +
 +	/* And then turn the plane on */
 +	OUTREG(DSPACNTR, dspcntr);
 +    } else {
 +	/* Always make sure the LVDS is off before we play with DPLLs and pipe
 +	 * configuration.
 +	 */
 +	i830SetLVDSPanelPower(pScrn, FALSE);
 +
 +	/* First, disable display planes */
 +	temp = INREG(DSPBCNTR);
 +	OUTREG(DSPBCNTR, temp & ~DISPLAY_PLANE_ENABLE);
 +
 +	/* Wait for vblank for the disable to take effect */
 +	i830WaitForVblank(pScrn);
 +
 +	/* Next, disable display pipes */
 +	temp = INREG(PIPEBCONF);
 +	OUTREG(PIPEBCONF, temp & ~PIPEBCONF_ENABLE);
 +
 +	if (outputs & PIPE_LCD_ACTIVE) {
 +	    /* Disable the PLL before messing with LVDS enable */
 +	    OUTREG(FPB0, fp & ~DPLL_VCO_ENABLE);
 +
 +	    /* LVDS must be powered on before PLL is enabled and before power
 +	     * sequencing the panel.
 +	     */
 +	    temp = INREG(LVDS);
 +	    OUTREG(LVDS, temp | LVDS_PORT_EN | LVDS_PIPEB_SELECT);
 +	}
 +
 +	OUTREG(FPB0, fp);
 +	OUTREG(DPLL_B, dpll);
 +	OUTREG(HTOTAL_B, htot);
 +	OUTREG(HBLANK_B, hblank);
 +	OUTREG(HSYNC_B, hsync);
 +	OUTREG(VTOTAL_B, vtot);
 +	OUTREG(VBLANK_B, vblank);
 +	OUTREG(VSYNC_B, vsync);
 +	OUTREG(DSPBSTRIDE, pScrn->displayWidth * pI830->cpp);
 +	OUTREG(DSPBSIZE, dspsize);
 +	OUTREG(DSPBPOS, 0);
 +	i830PipeSetBase(pScrn, pipe, pScrn->frameX0, pScrn->frameY0);
 +	OUTREG(PIPEBSRC, pipesrc);
 +
 +	if (outputs & PIPE_LCD_ACTIVE) {
 +	    CARD32  pfit_control;
 +	    
 +	    /* Enable automatic panel scaling so that non-native modes fill the
 +	     * screen.
 +	     */
 +	    /* XXX: Allow (auto-?) enabling of 8-to-6 dithering */
 +	    pfit_control = (PFIT_ENABLE |
 +			    VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
 +			    VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR);
 +	    if (pI830->panel_wants_dither)
 +		pfit_control |= PANEL_8TO6_DITHER_ENABLE;
 +	    OUTREG(PFIT_CONTROL, pfit_control);
 +	}
 +
 +	/* Then, turn the pipe on first */
 +	temp = INREG(PIPEBCONF);
 +	OUTREG(PIPEBCONF, temp | PIPEBCONF_ENABLE);
 +
 +	/* And then turn the plane on */
 +	OUTREG(DSPBCNTR, dspcntr);
 +
 +	if (outputs & PIPE_LCD_ACTIVE) {
 +	    i830SetLVDSPanelPower(pScrn, TRUE);
 +	}
 +    }
 +
 +    if (outputs & PIPE_CRT_ACTIVE)
 +	OUTREG(ADPA, adpa);
 +
 +    return TRUE;
 +}
 +
 +/**
 + * This function sets the given mode on the active pipes.
 + */
 +Bool
 +i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
 +{
 +    I830Ptr pI830 = I830PTR(pScrn);
 +    Bool ok = TRUE;
 +    CARD32 planeA, planeB;
 +#ifdef XF86DRI
 +    Bool didLock = FALSE;
 +#endif
 +
 +    DPRINTF(PFX, "i830SetMode\n");
 +
 +#ifdef XF86DRI
 +    didLock = I830DRILock(pScrn);
 +#endif
 +
 +    if (pI830->operatingDevices & 0xff) {
 +	pI830->planeEnabled[0] = 1;
 +    } else {
 +	pI830->planeEnabled[0] = 0;
 +    }
 +
 +    if (pI830->operatingDevices & 0xff00) {
 +	pI830->planeEnabled[1] = 1;
 +    } else {
 +	pI830->planeEnabled[1] = 0;
 +    }
 +
 +    if (pI830->planeEnabled[0]) {
 +	ok = i830PipeSetMode(pScrn, pMode, 0);
 +	if (!ok)
 +	    goto done;
 +    }
 +    if (pI830->planeEnabled[1]) {
 +	ok = i830PipeSetMode(pScrn, pMode, 1);
 +	if (!ok)
 +	    goto done;
 +    }
 +
 +    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Mode bandwidth is %d Mpixel/s\n",
 +	       (int)(pMode->HDisplay * pMode->VDisplay *
 +		     pMode->VRefresh / 1000000));
 +
 +    planeA = INREG(DSPACNTR);
 +    planeB = INREG(DSPBCNTR);
 +
 +    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 +	       "Display plane A is now %s and connected to %s.\n",
 +	       pI830->planeEnabled[0] ? "enabled" : "disabled",
 +	       planeA & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A");
 +    if (pI830->availablePipes == 2)
 +	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 +		   "Display plane B is now %s and connected to %s.\n",
 +		   pI830->planeEnabled[1] ? "enabled" : "disabled",
 +		   planeB & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A");
 +
 +done:
 +#ifdef XF86DRI
 +    if (didLock)
 +	I830DRIUnlock(pScrn);
 +#endif
 +
 +    return ok;
 +}
 +
 +Bool
 +i830DetectCRT(ScrnInfoPtr pScrn)
 +{
 +    I830Ptr pI830 = I830PTR(pScrn);
 +    CARD32 temp;
 +
 +    temp = INREG(PORT_HOTPLUG_EN);
 +    OUTREG(PORT_HOTPLUG_EN, temp | CRT_HOTPLUG_FORCE_DETECT);
 +
 +    /* Wait for the bit to clear to signal detection finished. */
 +    while (INREG(PORT_HOTPLUG_EN) & CRT_HOTPLUG_FORCE_DETECT)
 +	;
 +
 +    return ((INREG(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_INT_STATUS));
 +}
 +
 +/**
 + * Sets the power state for the panel.
 + */
 +void
 +i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on)
 +{
 +    I830Ptr pI830 = I830PTR(pScrn);
 +    CARD32 pp_status, pp_control;
 +
 +    if (on) {
 +	OUTREG(PP_STATUS, INREG(PP_STATUS) | PP_ON);
 +	OUTREG(PP_CONTROL, INREG(PP_CONTROL) | POWER_TARGET_ON);
 +	do {
 +	    pp_status = INREG(PP_STATUS);
 +	    pp_control = INREG(PP_CONTROL);
 +	} while (!(pp_status & PP_ON) && !(pp_control & POWER_TARGET_ON));
 +    } else {
 +	OUTREG(PP_STATUS, INREG(PP_STATUS) & ~PP_ON);
 +	OUTREG(PP_CONTROL, INREG(PP_CONTROL) & ~POWER_TARGET_ON);
 +	do {
 +	    pp_status = INREG(PP_STATUS);
 +	    pp_control = INREG(PP_CONTROL);
 +	} while ((pp_status & PP_ON) || (pp_control & POWER_TARGET_ON));
 +    }
 +}
diff --cc src/i830_driver.c
index 23a0631,053ccd1..61faad0
@@@ -160,8 -160,11 +160,12 @@@
  #define PRINT_MODE_INFO 0
  #endif
  
+ #include <string.h>
+ #include <unistd.h>
+ #include <stdlib.h>
++#include <stdio.h>
+ 
  #include "xf86.h"
- #include "xf86_ansic.h"
  #include "xf86_OSproc.h"
  #include "xf86Resources.h"
  #include "xf86RAC.h"
@@@ -1327,153 -2005,6 +1332,156 @@@
  
     return mon_range->max_clock;
  }
 +#endif
 +
 +static void
 +I830SetupOutputBusses(ScrnInfoPtr pScrn)
 +{
 +   I830Ptr pI830 = I830PTR(pScrn);
 +
 +   /* everyone has at least a single analog output */
 +   pI830->num_outputs = 1;
 +   pI830->output[0].type = I830_OUTPUT_ANALOG;
 +
 +   /* setup the DDC bus for the analog output */
 +   I830I2CInit(pScrn, &pI830->output[0].pDDCBus, GPIOA, "CRTDDC_A");
 +
 +   /* need to add the output busses for each device 
 +    * - this function is very incomplete
 +    * - i915GM has LVDS and TVOUT for example
 +    */
 +   switch(pI830->PciInfo->chipType) {
 +   case PCI_CHIP_I830_M:
 +   case PCI_CHIP_845_G:
 +   case PCI_CHIP_I855_GM:
 +   case PCI_CHIP_I865_G:
 +      pI830->num_outputs = 2;
 +      pI830->output[1].type = I830_OUTPUT_DVO;
 +      I830I2CInit(pScrn, &pI830->output[1].pDDCBus, GPIOD, "DVODDC_D");
 +      I830I2CInit(pScrn, &pI830->output[1].pI2CBus, GPIOE, "DVOI2C_E");
 +      break;
 +   case PCI_CHIP_E7221_G:
 +      /* ??? */
 +      break;
 +   case PCI_CHIP_I915_G:
 +   case PCI_CHIP_I915_GM:
 +      pI830->num_outputs = 2;
 +      pI830->output[1].type = I830_OUTPUT_LVDS;
 +      I830I2CInit(pScrn, &pI830->output[1].pDDCBus, GPIOC, "LVDSDDC_C");
 +      break;
 +#if 0
 +   case PCI_CHIP_I945_G:
 +   case PCI_CHIP_I945_GM:
 +      /* SDVO ports have a single control bus */
 +      pI830->num_outputs = 2;
 +      pI830->output[1].type = I830_OUTPUT_SDVO;
 +      I830I2CInit(pScrn, &pI830->output[1].pI2CBus, GPIOE, "SDVOCTRL_E");
 +
 +      pI830->output[1].sdvo_drv = I830SDVOInit(pI830->output[1].pI2CBus);
 +      ret = I830I2CDetectSDVOController(pScrn, 1);
 +      if (ret == TRUE)
 +	 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found sDVO\n");
 +      break;
 +#endif
 +   }
 +}
 +
 +void 
 +I830PreInitDDC(ScrnInfoPtr pScrn)
 +{
 +   I830Ptr pI830 = I830PTR(pScrn);
 +
 +   if (!xf86LoadSubModule(pScrn, "ddc")) {
 +      pI830->ddc2 = FALSE;
 +   } else {
 +      xf86LoaderReqSymLists(I810ddcSymbols, NULL);
 +      pI830->ddc2 = TRUE;
 +   }
 +
 +   /* DDC can use I2C bus */
 +   /* Load I2C if we have the code to use it */
 +   if (pI830->ddc2) {
 +      if (xf86LoadSubModule(pScrn, "i2c")) {
 +	 xf86LoaderReqSymLists(I810i2cSymbols, NULL);
 +
 +	 I830SetupOutputBusses(pScrn);
 +
 +	 pI830->ddc2 = TRUE;
 +      } else {
 +	 pI830->ddc2 = FALSE;
 +      }
 +   }
 +}
 +
 +void I830DetectMonitors(ScrnInfoPtr pScrn)
 +{
 +   I830Ptr pI830 = I830PTR(pScrn);
-    int i, ret;
++   int i;
 +
 +   if (!pI830->ddc2)
 +      return;
 +
 +   for (i=0; i<pI830->num_outputs; i++) {
 +      switch (pI830->output[i].type) {
 +      case I830_OUTPUT_ANALOG:
 +      case I830_OUTPUT_LVDS:
 +	 /* for an analog/LVDS output, just do DDC */
 +	 pI830->output[i].MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex,
 +						    pI830->output[i].pDDCBus);
 +
 +	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC %s %d, %08lX\n",
 +		    output_type_names[pI830->output[i].type], i,
 +		    pI830->output[i].pDDCBus->DriverPrivate.uval);
 +	 xf86PrintEDID(pI830->output[i].MonInfo);
 +	 break;
 +      case I830_OUTPUT_DVO:
 +	 /* check for DDC */
 +	 pI830->output[i].MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex,
 +						    pI830->output[i].pDDCBus);
 +
 +	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC DVO %d, %08lX\n", i,
 +		    pI830->output[i].pDDCBus->DriverPrivate.uval);
 +	 xf86PrintEDID(pI830->output[i].MonInfo);
 +      
++#if 0
 +	 /* if we are on an i2C bus > 0 and we see a monitor - try to
 +	  * find a controller chip
 +	  */
 +	 if (pI830->output[i].MonInfo) {
++	    int ret;
 +	    ret = I830I2CDetectDVOControllers(pScrn, pI830->output[i].pI2CBus,
 +					      &pI830->output[i].i2c_drv);
 +	    if (ret==TRUE) {
 +	       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08lX\n",
 +			  pI830->output[i].i2c_drv->modulename,
 +			  pI830->output[i].pI2CBus->DriverPrivate.uval);
 +	    }
 +	 }
++#endif
 +      break;
 +#if 0
 +      case I830_OUTPUT_SDVO:
 +	 if (pI830->output[i].sdvo_drv->found) {
 +	    I830SDVOSetupDDC(pI830->output[i].sdvo_drv);
 +
 +	    pI830->output[i].MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex,
 +						       pI830->output[i].pI2CBus);
 +
 +	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC SDVO %d, %08X\n", i,
 +		       pI830->output[i].pI2CBus->DriverPrivate.uval);
 +	    xf86PrintEDID(pI830->output[i].MonInfo);
 +	 }
 +	 break;
 +#endif
 +      case I830_OUTPUT_UNUSED:
 +	 break;
 +      default:
 +	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 +		    "Unknown or unhandled output device at %d\n", i);
 +	 break;
 +      }
 +   }
 +}
  
  static void
  PreInitCleanup(ScrnInfoPtr pScrn)
@@@ -3046,255 -3603,800 +3071,266 @@@
   * Reset registers that it doesn't make sense to save/restore to a sane state.
   * This is basically the ring buffer and fence registers.  Restoring these
   * doesn't make sense without restoring GTT mappings.  This is something that
 - * whoever gets control next should do.
 - */
 -static void
 -ResetState(ScrnInfoPtr pScrn, Bool flush)
 -{
 -   I830Ptr pI830 = I830PTR(pScrn);
 -   int i;
 -   unsigned long temp;
 -
 -   DPRINTF(PFX, "ResetState: flush is %s\n", BOOLTOSTRING(flush));
 -
 -   if (!I830IsPrimary(pScrn)) return;
 -
 -   if (pI830->entityPrivate)
 -      pI830->entityPrivate->RingRunning = 0;
 -
 -   /* Reset the fence registers to 0 */
 -   for (i = 0; i < 8; i++)
 -      OUTREG(FENCE + i * 4, 0);
 -
 -   /* Flush the ring buffer (if enabled), then disable it. */
 -   if (pI830->AccelInfoRec != NULL && flush) {
 -      temp = INREG(LP_RING + RING_LEN);
 -      if (temp & 1) {
 -	 I830RefreshRing(pScrn);
 -	 I830Sync(pScrn);
 -	 DO_RING_IDLE();
 -      }
 -   }
 -   OUTREG(LP_RING + RING_LEN, 0);
 -   OUTREG(LP_RING + RING_HEAD, 0);
 -   OUTREG(LP_RING + RING_TAIL, 0);
 -   OUTREG(LP_RING + RING_START, 0);
 -  
 -   if (pI830->CursorInfoRec && pI830->CursorInfoRec->HideCursor)
 -      pI830->CursorInfoRec->HideCursor(pScrn);
 -}
 -
 -static void
 -SetFenceRegs(ScrnInfoPtr pScrn)
 -{
 -   I830Ptr pI830 = I830PTR(pScrn);
 -   int i;
 -
 -   DPRINTF(PFX, "SetFenceRegs\n");
 -
 -   if (!I830IsPrimary(pScrn)) return;
 -
 -   for (i = 0; i < 8; i++) {
 -      OUTREG(FENCE + i * 4, pI830->ModeReg.Fence[i]);
 -      if (I810_DEBUG & DEBUG_VERBOSE_VGA)
 -	 ErrorF("Fence Register : %x\n", pI830->ModeReg.Fence[i]);
 -   }
 -}
 -
 -static void
 -SetRingRegs(ScrnInfoPtr pScrn)
 -{
 -   I830Ptr pI830 = I830PTR(pScrn);
 -   unsigned int itemp;
 -
 -   DPRINTF(PFX, "SetRingRegs\n");
 -
 -   if (pI830->noAccel)
 -      return;
 -
 -   if (!I830IsPrimary(pScrn)) return;
 -
 -   if (pI830->entityPrivate)
 -      pI830->entityPrivate->RingRunning = 1;
 -
 -   OUTREG(LP_RING + RING_LEN, 0);
 -   OUTREG(LP_RING + RING_TAIL, 0);
 -   OUTREG(LP_RING + RING_HEAD, 0);
 -
 -   if ((long)(pI830->LpRing->mem.Start & I830_RING_START_MASK) !=
 -       pI830->LpRing->mem.Start) {
 -      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 -		 "I830SetRingRegs: Ring buffer start (%lx) violates its "
 -		 "mask (%x)\n", pI830->LpRing->mem.Start, I830_RING_START_MASK);
 -   }
 -   /* Don't care about the old value.  Reserved bits must be zero anyway. */
 -   itemp = pI830->LpRing->mem.Start & I830_RING_START_MASK;
 -   OUTREG(LP_RING + RING_START, itemp);
 -
 -   if (((pI830->LpRing->mem.Size - 4096) & I830_RING_NR_PAGES) !=
 -       pI830->LpRing->mem.Size - 4096) {
 -      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 -		 "I830SetRingRegs: Ring buffer size - 4096 (%lx) violates its "
 -		 "mask (%x)\n", pI830->LpRing->mem.Size - 4096,
 -		 I830_RING_NR_PAGES);
 -   }
 -   /* Don't care about the old value.  Reserved bits must be zero anyway. */
 -   itemp = (pI830->LpRing->mem.Size - 4096) & I830_RING_NR_PAGES;
 -   itemp |= (RING_NO_REPORT | RING_VALID);
 -   OUTREG(LP_RING + RING_LEN, itemp);
 -   I830RefreshRing(pScrn);
 -}
 -
 -/*
 - * This should be called everytime the X server gains control of the screen,
 - * before any video modes are programmed (ScreenInit, EnterVT).
 - */
 -static void
 -SetHWOperatingState(ScrnInfoPtr pScrn)
 -{
 -   I830Ptr pI830 = I830PTR(pScrn);
 -
 -   DPRINTF(PFX, "SetHWOperatingState\n");
 -
 -   if (!pI830->noAccel)
 -      SetRingRegs(pScrn);
 -   SetFenceRegs(pScrn);
 -   if (!pI830->SWCursor)
 -      I830InitHWCursor(pScrn);
 -}
 -
 -static Bool
 -SaveHWState(ScrnInfoPtr pScrn)
 -{
 -   I830Ptr pI830 = I830PTR(pScrn);
 -   vbeInfoPtr pVbe = pI830->pVbe;
 -   vgaHWPtr hwp = VGAHWPTR(pScrn);
 -   vgaRegPtr vgaReg = &hwp->SavedReg;
 -   VbeModeInfoBlock *modeInfo;
 -   VESAPtr pVesa;
 -
 -   DPRINTF(PFX, "SaveHWState\n");
 -
 -   if (I830IsPrimary(pScrn) && pI830->pipe != pI830->origPipe)
 -      SetBIOSPipe(pScrn, pI830->origPipe);
 -   else
 -      SetPipeAccess(pScrn);
 -
 -   pVesa = pI830->vesa;
 -
 -   /* Make sure we save at least this information in case of failure. */
 -   VBEGetVBEMode(pVbe, &pVesa->stateMode);
 -   pVesa->stateRefresh = GetRefreshRate(pScrn, pVesa->stateMode, NULL);
 -   modeInfo = VBEGetModeInfo(pVbe, pVesa->stateMode);
 -   pVesa->savedScanlinePitch = 0;
 -   if (modeInfo) {
 -      if (VBE_MODE_GRAPHICS(modeInfo)) {
 -         VBEGetLogicalScanline(pVbe, &pVesa->savedScanlinePitch, NULL, NULL);
 -      }
 -      VBEFreeModeInfo(modeInfo);
 -   }
 -
 -   vgaHWUnlock(hwp);
 -   vgaHWSave(pScrn, vgaReg, VGA_SR_FONTS);
 -
 -   pVesa = pI830->vesa;
 -   /*
 -    * This save/restore method doesn't work for 845G BIOS, or for some
 -    * other platforms.  Enable it in all cases.
 -    */
 -   /*
 -    * KW: This may have been because of the behaviour I've found on my
 -    * board: The 'save' command actually modifies the interrupt
 -    * registers, turning off the irq & breaking the kernel module
 -    * behaviour.
 -    */
 -   if (!pI830->vbeRestoreWorkaround) {
 -      CARD16 imr = INREG16(IMR);
 -      CARD16 ier = INREG16(IER);
 -      CARD16 hwstam = INREG16(HWSTAM);
 -
 -      if (!VBESaveRestore(pVbe, MODE_SAVE, &pVesa->state, &pVesa->stateSize,
 -			  &pVesa->statePage)) {
 -	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 -		    "SaveHWState: VBESaveRestore(MODE_SAVE) failed.\n");
 -	 return FALSE;
 -      }
 -
 -      OUTREG16(IMR, imr);
 -      OUTREG16(IER, ier);
 -      OUTREG16(HWSTAM, hwstam);
 -   }
 -
 -   pVesa->savedPal = VBESetGetPaletteData(pVbe, FALSE, 0, 256,
 -					     NULL, FALSE, FALSE);
 -   if (!pVesa->savedPal) {
 -      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 -		 "SaveHWState: VBESetGetPaletteData(GET) failed.\n");
 -      return FALSE;
 -   }
 -
 -   VBEGetDisplayStart(pVbe, &pVesa->x, &pVesa->y);
 -
 -   return TRUE;
 -}
 -
 -static Bool
 -RestoreHWState(ScrnInfoPtr pScrn)
 -{
 -   I830Ptr pI830 = I830PTR(pScrn);
 -   vbeInfoPtr pVbe = pI830->pVbe;
 -   vgaHWPtr hwp = VGAHWPTR(pScrn);
 -   vgaRegPtr vgaReg = &hwp->SavedReg;
 -   VESAPtr pVesa;
 -   Bool restored = FALSE;
 -
 -   DPRINTF(PFX, "RestoreHWState\n");
 -
 -   if (I830IsPrimary(pScrn) && pI830->pipe != pI830->origPipe)
 -      SetBIOSPipe(pScrn, pI830->origPipe);
 -   else
 -      SetPipeAccess(pScrn);
 -
 -   pVesa = pI830->vesa;
 -
 -   /*
 -    * Workaround for text mode restoration with some flat panels.
 -    * Temporarily program a 640x480 mode before switching back to
 -    * text mode.
 -    */
 -   if (pVesa->useDefaultRefresh)
 -      I830Set640x480(pScrn);
 -
 -   if (pVesa->state && pVesa->stateSize) {
 -      CARD16 imr = INREG16(IMR);
 -      CARD16 ier = INREG16(IER);
 -      CARD16 hwstam = INREG16(HWSTAM);
 -
 -      /* Make a copy of the state.  Don't rely on it not being touched. */
 -      if (!pVesa->pstate) {
 -	 pVesa->pstate = xalloc(pVesa->stateSize);
 -	 if (pVesa->pstate)
 -	    memcpy(pVesa->pstate, pVesa->state, pVesa->stateSize);
 -      }
 -      restored = VBESaveRestore(pVbe, MODE_RESTORE, &pVesa->state,
 -				   &pVesa->stateSize, &pVesa->statePage);
 -      if (!restored) {
 -	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -		    "RestoreHWState: VBESaveRestore failed.\n");
 -      }
 -      /* Copy back */
 -      if (pVesa->pstate)
 -	 memcpy(pVesa->state, pVesa->pstate, pVesa->stateSize);
 -
 -      OUTREG16(IMR, imr);
 -      OUTREG16(IER, ier);
 -      OUTREG16(HWSTAM, hwstam);
 -   }
 -   /* If that failed, restore the original mode. */
 -   if (!restored) {
 -      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -		 "Setting the original video mode instead of restoring\n\t"
 -		 "the saved state\n");
 -      I830VESASetVBEMode(pScrn, pVesa->stateMode, NULL);
 -      if (!pVesa->useDefaultRefresh && pI830->useExtendedRefresh) {
 -         SetRefreshRate(pScrn, pVesa->stateMode, pVesa->stateRefresh);
 -      }
 -   }
 -   if (pVesa->savedScanlinePitch)
 -       VBESetLogicalScanline(pVbe, pVesa->savedScanlinePitch);
 -
 -   if (pVesa->savedPal)
 -      VBESetGetPaletteData(pVbe, TRUE, 0, 256, pVesa->savedPal, FALSE, TRUE);
 -
 -   VBESetDisplayStart(pVbe, pVesa->x, pVesa->y, TRUE);
 -
 -   vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS);
 -   vgaHWLock(hwp);
 -
 -   return TRUE;
 -}
 -
 -static void I830SetCloneVBERefresh(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock * block, int refresh)
 -{
 -   I830Ptr pI830 = I830PTR(pScrn);
 -   DisplayModePtr p = NULL;
 -   int RefreshRate;
 -   int clock;
 -
 -   /* Search for our mode and get a refresh to match */
 -   for (p = pScrn->monitor->Modes; p != NULL; p = p->next) {
 -      if ((p->HDisplay != pI830->CloneHDisplay) ||
 -          (p->VDisplay != pI830->CloneVDisplay) ||
 -          (p->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2)))
 -         continue;
 -      RefreshRate = ((double)(p->Clock * 1000) /
 -                     (double)(p->HTotal * p->VTotal)) * 100;
 -      /* we could probably do better here that 2Hz boundaries */
 -      if (RefreshRate > (refresh - 200) && RefreshRate < (refresh + 200)) {
 -         block->HorizontalTotal = p->HTotal;
 -         block->HorizontalSyncStart = p->HSyncStart;
 -         block->HorizontalSyncEnd = p->HSyncEnd;
 -         block->VerticalTotal = p->VTotal;
 -         block->VerticalSyncStart = p->VSyncStart;
 -         block->VerticalSyncEnd = p->VSyncEnd;
 -         block->Flags = ((p->Flags & V_NHSYNC) ? CRTC_NHSYNC : 0) |
 -                        ((p->Flags & V_NVSYNC) ? CRTC_NVSYNC : 0);
 -         block->PixelClock = p->Clock * 1000;
 -         /* XXX May not have this. */
 -         clock = VBEGetPixelClock(pI830->pVbe, mode, block->PixelClock);
 -#ifdef DEBUG
 -         ErrorF("Setting clock %.2fMHz, closest is %.2fMHz\n",
 -                    (double)data->block->PixelClock / 1000000.0, 
 -                    (double)clock / 1000000.0);
 -#endif
 -         if (clock)
 -            block->PixelClock = clock;
 -         block->RefreshRate = RefreshRate;
 -         return;
 -      }
 -   }
 -}
 -
 -static Bool
 -I830VESASetVBEMode(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock * block)
 -{
 -   I830Ptr pI830 = I830PTR(pScrn);
 -   Bool ret = FALSE;
 -   int Mon;
 -
 -   DPRINTF(PFX, "Setting mode 0x%.8x\n", mode);
 -
 -#if 0
 -   /* Clear the framebuffer (could do this with VBIOS call) */
 -   if (I830IsPrimary(pScrn))
 -      memset(pI830->FbBase + pI830->FrontBuffer.Start, 0,
 -	  pScrn->virtualY * pI830->displayWidth * pI830->cpp);
 -   else
 -      memset(pI830->FbBase + pI830->FrontBuffer2.Start, 0,
 -	  pScrn->virtualY * pI830->displayWidth * pI830->cpp);
 -#endif
 -
 -   if (pI830->Clone && pI830->CloneHDisplay && pI830->CloneVDisplay &&
 -       !pI830->preinit && !pI830->closing) {
 -      VbeCRTCInfoBlock newblock;
 -      int newmode = mode;
 -
 -      if (pI830->pipe == 1)
 -         Mon = pI830->MonType1;
 -      else
 -         Mon = pI830->MonType2;
 -
 -      SetBIOSPipe(pScrn, !pI830->pipe);
 -
 -      /* Now recheck refresh operations we can use */
 -      pI830->useExtendedRefresh = FALSE;
 -      pI830->vesa->useDefaultRefresh = FALSE;
 + * whoever gets control next should do.
 + */
 +static void
 +ResetState(ScrnInfoPtr pScrn, Bool flush)
 +{
 +   I830Ptr pI830 = I830PTR(pScrn);
 +   int i;
 +   unsigned long temp;
  
 -      if (Mon != PIPE_CRT) {
 -	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 -		    "A non-CRT device is attached to Clone pipe %c.\n"
 -		    "\tNo refresh rate overrides will be attempted (0x%x).\n",
 -		    PIPE_NAME(!pI830->pipe), newmode);
 -	 pI830->vesa->useDefaultRefresh = TRUE;
 -      }
 -      /*
 -       * Some desktop platforms might not have 0x5f05, so useExtendedRefresh
 -       * would need to be set to FALSE for those cases.
 -       */
 -      if (!pI830->vesa->useDefaultRefresh) 
 -	 pI830->useExtendedRefresh = TRUE;
 +   DPRINTF(PFX, "ResetState: flush is %s\n", BOOLTOSTRING(flush));
  
 -      newmode |= 1 << 11;
 -      if (pI830->vesa->useDefaultRefresh)
 -            newmode &= ~(1 << 11);
 +   if (!I830IsPrimary(pScrn)) return;
  
 -      if (!SetRefreshRate(pScrn, newmode, 60)) {
 -	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 -		    "BIOS call 0x5f05 not supported on Clone Head, "
 -		    "setting refresh with VBE 3 method.\n");
 -	 pI830->useExtendedRefresh = FALSE;
 -      }
 +   if (pI830->entityPrivate)
 +      pI830->entityPrivate->RingRunning = 0;
  
 -      if (!pI830->vesa->useDefaultRefresh) {
 -         I830SetCloneVBERefresh(pScrn, newmode, &newblock, pI830->CloneRefresh * 100);
 -
 -         if (!VBESetVBEMode(pI830->pVbe, newmode, &newblock)) {
 -            if (!VBESetVBEMode(pI830->pVbe, (newmode & ~(1 << 11)), NULL))
 -               xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -		 "Failed to set mode for Clone head.\n");
 -         } else {
 -            xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 -		 "Setting refresh on clone head with VBE 3 method.\n");
 -            pI830->useExtendedRefresh = FALSE;
 -         }
 -      } else {
 -         if (!VBESetVBEMode(pI830->pVbe, (newmode & ~(1 << 11)), NULL))
 -            xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -		 "Failed to set mode for Clone head.\n");
 -      }
 +   /* Reset the fence registers to 0 */
 +   for (i = 0; i < 8; i++)
 +      OUTREG(FENCE + i * 4, 0);
  
 -      if (pI830->useExtendedRefresh && !pI830->vesa->useDefaultRefresh) {
 -         if (!SetRefreshRate(pScrn, newmode, pI830->CloneRefresh))
 -	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -		    "Failed to set refresh rate to %dHz on Clone head.\n",
 -		    pI830->CloneRefresh);
 -         else
 -	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 -		    "Set refresh rate to %dHz on Clone head.\n",
 -		    pI830->CloneRefresh);
 +   /* Flush the ring buffer (if enabled), then disable it. */
 +   if (pI830->AccelInfoRec != NULL && flush) {
 +      temp = INREG(LP_RING + RING_LEN);
 +      if (temp & 1) {
 +	 I830RefreshRing(pScrn);
 +	 I830Sync(pScrn);
 +	 DO_RING_IDLE();
        }
 -      SetPipeAccess(pScrn);
     }
 +   OUTREG(LP_RING + RING_LEN, 0);
 +   OUTREG(LP_RING + RING_HEAD, 0);
 +   OUTREG(LP_RING + RING_TAIL, 0);
 +   OUTREG(LP_RING + RING_START, 0);
 +  
 +   if (pI830->CursorInfoRec && pI830->CursorInfoRec->HideCursor)
 +      pI830->CursorInfoRec->HideCursor(pScrn);
 +}
  
 -   if (pI830->pipe == 0)
 -      Mon = pI830->MonType1;
 -   else
 -      Mon = pI830->MonType2;
 -
 -   /* Now recheck refresh operations we can use */
 -   pI830->useExtendedRefresh = FALSE;
 -   pI830->vesa->useDefaultRefresh = FALSE;
 -
 -   if (Mon != PIPE_CRT)
 -      pI830->vesa->useDefaultRefresh = TRUE;
 -
 -   mode |= 1 << 11;
 -   if (pI830->vesa->useDefaultRefresh)
 -      mode &= ~(1 << 11);
 -   /*
 -    * Some desktop platforms might not have 0x5f05, so useExtendedRefresh
 -    * would need to be set to FALSE for those cases.
 -    */
 -   if (!pI830->vesa->useDefaultRefresh) 
 -      pI830->useExtendedRefresh = TRUE;
 -
 -   if (!SetRefreshRate(pScrn, mode, 60)) {
 -      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 -		    "BIOS call 0x5f05 not supported, "
 -		    "setting refresh with VBE 3 method.\n");
 -      pI830->useExtendedRefresh = FALSE;
 -   }
 +static void
 +SetFenceRegs(ScrnInfoPtr pScrn)
 +{
 +   I830Ptr pI830 = I830PTR(pScrn);
 +   int i;
  
 -   if (!pI830->vesa->useDefaultRefresh && block) {
 -      ret = VBESetVBEMode(pI830->pVbe, mode, block);
 -      if (!ret)
 -         ret = VBESetVBEMode(pI830->pVbe, (mode & ~(1 << 11)), NULL);
 -      else {
 -         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 -		 "Setting refresh with VBE 3 method.\n");
 -	 pI830->useExtendedRefresh = FALSE;
 -      }
 -   } else {
 -      ret = VBESetVBEMode(pI830->pVbe, (mode & ~(1 << 11)), NULL);
 -   }
 +   DPRINTF(PFX, "SetFenceRegs\n");
  
 -   /* Might as well bail now if we've failed */
 -   if (!ret) return FALSE;
 +   if (!I830IsPrimary(pScrn)) return;
  
 -   if (pI830->useExtendedRefresh && !pI830->vesa->useDefaultRefresh && block) {
 -      if (!SetRefreshRate(pScrn, mode, block->RefreshRate / 100)) {
 -	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -		    "Failed to set refresh rate to %dHz.\n",
 -		    block->RefreshRate / 100);
 -	 pI830->useExtendedRefresh = FALSE;
 -      }
 +   for (i = 0; i < 8; i++) {
 +      OUTREG(FENCE + i * 4, pI830->ModeReg.Fence[i]);
 +      if (I810_DEBUG & DEBUG_VERBOSE_VGA)
 +	 ErrorF("Fence Register : %x\n", pI830->ModeReg.Fence[i]);
     }
 -
 -   return ret;
  }
  
 -static Bool
 -I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
 +static void
 +SetRingRegs(ScrnInfoPtr pScrn)
  {
     I830Ptr pI830 = I830PTR(pScrn);
 -   vbeInfoPtr pVbe = pI830->pVbe;
 -   VbeModeInfoData *data = (VbeModeInfoData *) pMode->Private;
 -   int mode, i;
 -   CARD32 planeA, planeB, temp;
 -   int refresh = 60;
 -#ifdef XF86DRI
 -   Bool didLock = FALSE;
 -#endif
 -
 -   DPRINTF(PFX, "I830VESASetMode\n");
 +   unsigned int itemp;
  
 -   /* Always Enable Linear Addressing */
 -   mode = data->mode | (1 << 15) | (1 << 14);
 +   DPRINTF(PFX, "SetRingRegs\n");
  
 -#ifdef XF86DRI
 -   didLock = I830DRILock(pScrn);
 -#endif
 +   if (pI830->noAccel)
 +      return;
  
 -   if (pI830->Clone) {
 -      pI830->CloneHDisplay = pMode->HDisplay;
 -      pI830->CloneVDisplay = pMode->VDisplay;
 -   }
 +   if (!I830IsPrimary(pScrn)) return;
  
 -#ifndef MODESWITCH_RESET_STATE
 -#define MODESWITCH_RESET_STATE 0
 -#endif
 -#if MODESWITCH_RESET_STATE
 -   ResetState(pScrn, TRUE);
 -#endif
 +   if (pI830->entityPrivate)
 +      pI830->entityPrivate->RingRunning = 1;
  
 -   SetPipeAccess(pScrn);
 +   OUTREG(LP_RING + RING_LEN, 0);
 +   OUTREG(LP_RING + RING_TAIL, 0);
 +   OUTREG(LP_RING + RING_HEAD, 0);
  
 -   if (I830VESASetVBEMode(pScrn, mode, data->block) == FALSE) {
 -      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Set VBE Mode failed!\n");
 -      return FALSE;
 +   if ((long)(pI830->LpRing->mem.Start & I830_RING_START_MASK) !=
 +       pI830->LpRing->mem.Start) {
 +      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 +		 "I830SetRingRegs: Ring buffer start (%lx) violates its "
 +		 "mask (%x)\n", pI830->LpRing->mem.Start, I830_RING_START_MASK);
     }
 +   /* Don't care about the old value.  Reserved bits must be zero anyway. */
 +   itemp = pI830->LpRing->mem.Start & I830_RING_START_MASK;
 +   OUTREG(LP_RING + RING_START, itemp);
  
 -   /*
 -    * The BIOS may not set a scanline pitch that would require more video
 -    * memory than it's aware of.  We check for this later, and set it
 -    * explicitly if necessary.
 -    */
 -   if (data->data->XResolution != pI830->displayWidth) {
 -      if (pI830->Clone) {
 -         SetBIOSPipe(pScrn, !pI830->pipe);
 -         VBESetLogicalScanline(pVbe, pI830->displayWidth);
 -      }
 -      SetPipeAccess(pScrn);
 -      VBESetLogicalScanline(pVbe, pI830->displayWidth);
 +   if (((pI830->LpRing->mem.Size - 4096) & I830_RING_NR_PAGES) !=
 +       pI830->LpRing->mem.Size - 4096) {
 +      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 +		 "I830SetRingRegs: Ring buffer size - 4096 (%lx) violates its "
 +		 "mask (%x)\n", pI830->LpRing->mem.Size - 4096,
 +		 I830_RING_NR_PAGES);
     }
 +   /* Don't care about the old value.  Reserved bits must be zero anyway. */
 +   itemp = (pI830->LpRing->mem.Size - 4096) & I830_RING_NR_PAGES;
 +   itemp |= (RING_NO_REPORT | RING_VALID);
 +   OUTREG(LP_RING + RING_LEN, itemp);
 +   I830RefreshRing(pScrn);
 +}
  
 -   if (pScrn->bitsPerPixel >= 8 && pI830->vbeInfo->Capabilities[0] & 0x01) {
 -      if (pI830->Clone) {
 -         SetBIOSPipe(pScrn, !pI830->pipe);
 -         VBESetGetDACPaletteFormat(pVbe, 8);
 -      }
 -      SetPipeAccess(pScrn);
 -      VBESetGetDACPaletteFormat(pVbe, 8);
 -   }
 +/*
 + * This should be called everytime the X server gains control of the screen,
 + * before any video modes are programmed (ScreenInit, EnterVT).
 + */
 +static void
 +SetHWOperatingState(ScrnInfoPtr pScrn)
 +{
 +   I830Ptr pI830 = I830PTR(pScrn);
  
 -   /* XXX Fix plane A with pipe A, and plane B with pipe B. */
 -   planeA = INREG(DSPACNTR);
 -   planeB = INREG(DSPBCNTR);
 -
 -   pI830->planeEnabled[0] = ((planeA & DISPLAY_PLANE_ENABLE) != 0);
 -   pI830->planeEnabled[1] = ((planeB & DISPLAY_PLANE_ENABLE) != 0);
 -
 -   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Display plane A is %s and connected to %s.\n",
 -	      pI830->planeEnabled[0] ? "enabled" : "disabled",
 -	      planeA & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A");
 -   if (pI830->availablePipes == 2)
 -      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Display plane B is %s and connected to %s.\n",
 -	      pI830->planeEnabled[1] ? "enabled" : "disabled",
 -	      planeB & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A");
 -   
 -   if (pI830->operatingDevices & 0xff) {
 -      pI830->planeEnabled[0] = 1;
 -   } else { 
 -      pI830->planeEnabled[0] = 0;
 -   }
 +   DPRINTF(PFX, "SetHWOperatingState\n");
  
 -   if (pI830->operatingDevices & 0xff00) {
 -      pI830->planeEnabled[1] = 1;
 -   } else {
 -      pI830->planeEnabled[1] = 0;
 -   }
 -   
 -   if (pI830->planeEnabled[0]) {
 -      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabling plane A.\n");
 -      planeA |= DISPLAY_PLANE_ENABLE;
 -      planeA &= ~DISPPLANE_SEL_PIPE_MASK;
 -      planeA |= DISPPLANE_SEL_PIPE_A;
 -      OUTREG(DSPACNTR, planeA);
 -      /* flush the change. */
 -      temp = INREG(DSPABASE);
 -      OUTREG(DSPABASE, temp);
 -   }
 -   if (pI830->planeEnabled[1]) {
 -      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabling plane B.\n");
 -      planeB |= DISPLAY_PLANE_ENABLE;
 -      planeB &= ~DISPPLANE_SEL_PIPE_MASK;
 -      planeB |= DISPPLANE_SEL_PIPE_B;
 -      OUTREG(DSPBCNTR, planeB);
 -      /* flush the change. */
 -      temp = INREG(DSPBADDR);
 -      OUTREG(DSPBADDR, temp);
 -   }
 -
 -   planeA = INREG(DSPACNTR);
 -   planeB = INREG(DSPBCNTR);
 -   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Display plane A is now %s and connected to %s.\n",
 -	      pI830->planeEnabled[0] ? "enabled" : "disabled",
 -	      planeA & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A");
 -   if (pI830->availablePipes == 2)
 -      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Display plane B is now %s and connected to %s.\n",
 -	      pI830->planeEnabled[1] ? "enabled" : "disabled",
 -	      planeB & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A");
 +   if (!pI830->noAccel)
 +      SetRingRegs(pScrn);
 +   SetFenceRegs(pScrn);
 +   if (!pI830->SWCursor)
 +      I830InitHWCursor(pScrn);
 +}
  
 -   /* XXX Plane C is ignored for now (overlay). */
 +static Bool
 +SaveHWState(ScrnInfoPtr pScrn)
 +{
 +   I830Ptr pI830 = I830PTR(pScrn);
 +   vgaHWPtr hwp = VGAHWPTR(pScrn);
 +   vgaRegPtr vgaReg = &hwp->SavedReg;
++   CARD32 temp;
  
-    DPRINTF(PFX, "SaveHWState\n");
+    /*
+     * Print out the PIPEACONF and PIPEBCONF registers.
+     */
+    temp = INREG(PIPEACONF);
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEACONF is 0x%08lx\n", 
+ 	      (unsigned long) temp);
+    if (pI830->availablePipes == 2) {
+       temp = INREG(PIPEBCONF);
+       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEBCONF is 0x%08lx\n", 
+ 		 (unsigned long) temp);
+    }
  
 -   if (xf86IsEntityShared(pScrn->entityList[0])) {
 -      /* Clean this up !! */
 -      if (I830IsPrimary(pScrn)) {
 -         CARD32 stridereg = !pI830->pipe ? DSPASTRIDE : DSPBSTRIDE;
 -         CARD32 basereg = !pI830->pipe ? DSPABASE : DSPBBASE;
 -         CARD32 sizereg = !pI830->pipe ? DSPASIZE : DSPBSIZE;
 -         I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
 -
 -         temp = INREG(stridereg);
 -         if (temp / pI8301->cpp != (CARD32)(pI830->displayWidth)) {
 -            xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -		    "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(!pI830->pipe),
 -		    (int)(temp / pI8301->cpp), pI830->displayWidth);
 -	    OUTREG(stridereg, pI830->displayWidth * pI8301->cpp);
 -         }
 -         OUTREG(sizereg, (pMode->HDisplay - 1) | ((pMode->VDisplay - 1) << 16));
 -         /* Trigger update */
 -         temp = INREG(basereg);
 -         OUTREG(basereg, temp);
 -
 -         if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) {
 -            I830Ptr pI8302 = I830PTR(pI830->entityPrivate->pScrn_2);
 -            stridereg = pI830->pipe ? DSPASTRIDE : DSPBSTRIDE;
 -            basereg = pI830->pipe ? DSPABASE : DSPBBASE;
 -            sizereg = pI830->pipe ? DSPASIZE : DSPBSIZE;
 -
 -            temp = INREG(stridereg);
 -            if (temp / pI8302->cpp != (CARD32)(pI8302->displayWidth)) {
 -	       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -		    "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(pI830->pipe),
 -		    (int)(temp / pI8302->cpp), pI8302->displayWidth);
 -	       OUTREG(stridereg, pI8302->displayWidth * pI8302->cpp);
 -            }
 -            OUTREG(sizereg, (pI830->entityPrivate->pScrn_2->currentMode->HDisplay - 1) | ((pI830->entityPrivate->pScrn_2->currentMode->VDisplay - 1) << 16));
 -            /* Trigger update */
 -            temp = INREG(basereg);
 -            OUTREG(basereg, temp);
 -         }
 -      } else {
 -         CARD32 stridereg = pI830->pipe ? DSPASTRIDE : DSPBSTRIDE;
 -         CARD32 basereg = pI830->pipe ? DSPABASE : DSPBBASE;
 -         CARD32 sizereg = pI830->pipe ? DSPASIZE : DSPBSIZE;
 -         I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
 -         I830Ptr pI8302 = I830PTR(pI830->entityPrivate->pScrn_2);
 -
 -         temp = INREG(stridereg);
 -         if (temp / pI8301->cpp != (CARD32)(pI8301->displayWidth)) {
 -	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -		    "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(pI830->pipe),
 -		    (int)(temp / pI8301->cpp), pI8301->displayWidth);
 -	    OUTREG(stridereg, pI8301->displayWidth * pI8301->cpp);
 -         }
 -         OUTREG(sizereg, (pI830->entityPrivate->pScrn_1->currentMode->HDisplay - 1) | ((pI830->entityPrivate->pScrn_1->currentMode->VDisplay - 1) << 16));
 -         /* Trigger update */
 -         temp = INREG(basereg);
 -         OUTREG(basereg, temp);
 -
 -         stridereg = !pI830->pipe ? DSPASTRIDE : DSPBSTRIDE;
 -         basereg = !pI830->pipe ? DSPABASE : DSPBBASE;
 -         sizereg = !pI830->pipe ? DSPASIZE : DSPBSIZE;
 +   i830TakeRegSnapshot(pScrn);
  
 -         temp = INREG(stridereg);
 -         if (temp / pI8302->cpp != ((CARD32)pI8302->displayWidth)) {
 -	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -		    "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(!pI830->pipe),
 -		    (int)(temp / pI8302->cpp), pI8302->displayWidth);
 -	    OUTREG(stridereg, pI8302->displayWidth * pI8302->cpp);
 -         }
 -         OUTREG(sizereg, (pMode->HDisplay - 1) | ((pMode->VDisplay - 1) << 16));
 -         /* Trigger update */
 -         temp = INREG(basereg);
 -         OUTREG(basereg, temp);
 -      }
 -   } else {
 -      for (i = 0; i < pI830->availablePipes; i++) {
 -         CARD32 stridereg = i ? DSPBSTRIDE : DSPASTRIDE;
 -         CARD32 basereg = i ? DSPBBASE : DSPABASE;
 -         CARD32 sizereg = i ? DSPBSIZE : DSPASIZE;
 +   /* Save video mode information for native mode-setting. */
 +   pI830->saveDSPACNTR = INREG(DSPACNTR);
 +   pI830->saveDSPBCNTR = INREG(DSPBCNTR);
 +   pI830->savePIPEACONF = INREG(PIPEACONF);
 +   pI830->savePIPEBCONF = INREG(PIPEBCONF);
 +   pI830->savePIPEASRC = INREG(PIPEASRC);
 +   pI830->savePIPEBSRC = INREG(PIPEBSRC);
 +   pI830->saveFPA0 = INREG(FPA0);
 +   pI830->saveFPA1 = INREG(FPA1);
 +   pI830->saveDPLL_A = INREG(DPLL_A);
 +   pI830->saveHTOTAL_A = INREG(HTOTAL_A);
 +   pI830->saveHBLANK_A = INREG(HBLANK_A);
 +   pI830->saveHSYNC_A = INREG(HSYNC_A);
 +   pI830->saveVTOTAL_A = INREG(VTOTAL_A);
 +   pI830->saveVBLANK_A = INREG(VBLANK_A);
 +   pI830->saveVSYNC_A = INREG(VSYNC_A);
 +   pI830->saveDSPASTRIDE = INREG(DSPASTRIDE);
 +   pI830->saveDSPASIZE = INREG(DSPASIZE);
 +   pI830->saveDSPAPOS = INREG(DSPAPOS);
 +   pI830->saveDSPABASE = INREG(DSPABASE);
 +
 +   pI830->saveFPB0 = INREG(FPB0);
 +   pI830->saveFPB1 = INREG(FPB1);
 +   pI830->saveDPLL_B = INREG(DPLL_B);
 +   pI830->saveHTOTAL_B = INREG(HTOTAL_B);
 +   pI830->saveHBLANK_B = INREG(HBLANK_B);
 +   pI830->saveHSYNC_B = INREG(HSYNC_B);
 +   pI830->saveVTOTAL_B = INREG(VTOTAL_B);
 +   pI830->saveVBLANK_B = INREG(VBLANK_B);
 +   pI830->saveVSYNC_B = INREG(VSYNC_B);
 +   pI830->saveDSPBSTRIDE = INREG(DSPBSTRIDE);
 +   pI830->saveDSPBSIZE = INREG(DSPBSIZE);
 +   pI830->saveDSPBPOS = INREG(DSPBPOS);
 +   pI830->saveDSPBBASE = INREG(DSPBBASE);
 +
 +   pI830->saveVCLK_DIVISOR_VGA0 = INREG(VCLK_DIVISOR_VGA0);
 +   pI830->saveVCLK_DIVISOR_VGA1 = INREG(VCLK_DIVISOR_VGA1);
 +   pI830->saveVCLK_POST_DIV = INREG(VCLK_POST_DIV);
 +   pI830->saveVGACNTRL = INREG(VGACNTRL);
  
 -         if (!pI830->planeEnabled[i])
 -	    continue;
 +   pI830->saveADPA = INREG(ADPA);
  
 -         temp = INREG(stridereg);
 -         if (temp / pI830->cpp != (CARD32)pI830->displayWidth) {
 -	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 -		    "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(i),
 -		    (int)(temp / pI830->cpp), pI830->displayWidth);
 -	    OUTREG(stridereg, pI830->displayWidth * pI830->cpp);
 -         }
 -         OUTREG(sizereg, (pMode->HDisplay - 1) | ((pMode->VDisplay - 1) << 16));
 -	 /* Trigger update */
 -	 temp = INREG(basereg);
 -	 OUTREG(basereg, temp);
 -      }
 -   }
 +   vgaHWUnlock(hwp);
 +   vgaHWSave(pScrn, vgaReg, VGA_SR_ALL);
  
 -#if 0
 -   /* Print out some CRTC/display information. */
 -   temp = INREG(HTOTAL_A);
 -   ErrorF("Horiz active: %d, Horiz total: %d\n", temp & 0x7ff,
 -	  (temp >> 16) & 0xfff);
 -   temp = INREG(HBLANK_A);
 -   ErrorF("Horiz blank start: %d, Horiz blank end: %d\n", temp & 0xfff,
 -	  (temp >> 16) & 0xfff);
 -   temp = INREG(HSYNC_A);
 -   ErrorF("Horiz sync start: %d, Horiz sync end: %d\n", temp & 0xfff,
 -	  (temp >> 16) & 0xfff);
 -   temp = INREG(VTOTAL_A);
 -   ErrorF("Vert active: %d, Vert total: %d\n", temp & 0x7ff,
 -	  (temp >> 16) & 0xfff);
 -   temp = INREG(VBLANK_A);
 -   ErrorF("Vert blank start: %d, Vert blank end: %d\n", temp & 0xfff,
 -	  (temp >> 16) & 0xfff);
 -   temp = INREG(VSYNC_A);
 -   ErrorF("Vert sync start: %d, Vert sync end: %d\n", temp & 0xfff,
 -	  (temp >> 16) & 0xfff);
 -   temp = INREG(PIPEASRC);
 -   ErrorF("Image size: %dx%d (%dx%d)\n",
 -          (temp >> 16) & 0x7ff, temp & 0x7ff,
 -	  (((temp >> 16) & 0x7ff) + 1), ((temp & 0x7ff) + 1));
 -   ErrorF("Pixel multiply is %d\n", (planeA >> 20) & 0x3);
 -   temp = INREG(DSPABASE);
 -   ErrorF("Plane A start offset is %d\n", temp);
 -   temp = INREG(DSPASTRIDE);
 -   ErrorF("Plane A stride is %d bytes (%d pixels)\n", temp, temp / pI830->cpp);
 -   temp = INREG(DSPAPOS);
 -   ErrorF("Plane A position %d %d\n", temp & 0xffff, (temp & 0xffff0000) >> 16);
 -   temp = INREG(DSPASIZE);
 -   ErrorF("Plane A size %d %d\n", temp & 0xffff, (temp & 0xffff0000) >> 16);
 -
 -   /* Print out some CRTC/display information. */
 -   temp = INREG(HTOTAL_B);
 -   ErrorF("Horiz active: %d, Horiz total: %d\n", temp & 0x7ff,
 -	  (temp >> 16) & 0xfff);
 -   temp = INREG(HBLANK_B);
 -   ErrorF("Horiz blank start: %d, Horiz blank end: %d\n", temp & 0xfff,
 -	  (temp >> 16) & 0xfff);
 -   temp = INREG(HSYNC_B);
 -   ErrorF("Horiz sync start: %d, Horiz sync end: %d\n", temp & 0xfff,
 -	  (temp >> 16) & 0xfff);
 -   temp = INREG(VTOTAL_B);
 -   ErrorF("Vert active: %d, Vert total: %d\n", temp & 0x7ff,
 -	  (temp >> 16) & 0xfff);
 -   temp = INREG(VBLANK_B);
 -   ErrorF("Vert blank start: %d, Vert blank end: %d\n", temp & 0xfff,
 -	  (temp >> 16) & 0xfff);
 -   temp = INREG(VSYNC_B);
 -   ErrorF("Vert sync start: %d, Vert sync end: %d\n", temp & 0xfff,
 -	  (temp >> 16) & 0xfff);
 -   temp = INREG(PIPEBSRC);
 -   ErrorF("Image size: %dx%d (%dx%d)\n",
 -          (temp >> 16) & 0x7ff, temp & 0x7ff,
 -	  (((temp >> 16) & 0x7ff) + 1), ((temp & 0x7ff) + 1));
 -   ErrorF("Pixel multiply is %d\n", (planeA >> 20) & 0x3);
 -   temp = INREG(DSPBBASE);
 -   ErrorF("Plane B start offset is %d\n", temp);
 -   temp = INREG(DSPBSTRIDE);
 -   ErrorF("Plane B stride is %d bytes (%d pixels)\n", temp, temp / pI830->cpp);
 -   temp = INREG(DSPBPOS);
 -   ErrorF("Plane B position %d %d\n", temp & 0xffff, (temp & 0xffff0000) >> 16);
 -   temp = INREG(DSPBSIZE);
 -   ErrorF("Plane B size %d %d\n", temp & 0xffff, (temp & 0xffff0000) >> 16);
 -#endif
 +   return TRUE;
 +}
  
 -   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Mode bandwidth is %d Mpixel/s\n",
 -	      pMode->HDisplay * pMode->VDisplay * refresh / 1000000);
 +static Bool
 +RestoreHWState(ScrnInfoPtr pScrn)
 +{
 +   I830Ptr pI830 = I830PTR(pScrn);
 +   vgaHWPtr hwp = VGAHWPTR(pScrn);
 +   vgaRegPtr vgaReg = &hwp->SavedReg;
 +   CARD32 temp;
  
 -   {
 -      int maxBandwidth, bandwidthA, bandwidthB;
 +   DPRINTF(PFX, "RestoreHWState\n");
  
 -      if (GetModeSupport(pScrn, 0x80, 0x80, 0x80, 0x80,
 -			&maxBandwidth, &bandwidthA, &bandwidthB)) {
 -	 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "maxBandwidth is %d Mbyte/s, "
 -		    "pipe bandwidths are %d Mbyte/s, %d Mbyte/s\n",
 -		    maxBandwidth, bandwidthA, bandwidthB);
 -      }
 -   }
 +   vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL);
 +   vgaHWLock(hwp);
  
 -#if 0
 -   {
 -      int ret;
 +   /* First, disable display planes */
 +   temp = INREG(DSPACNTR);
 +   OUTREG(DSPACNTR, temp & ~DISPLAY_PLANE_ENABLE);
 +   temp = INREG(DSPBCNTR);
 +   OUTREG(DSPBCNTR, temp & ~DISPLAY_PLANE_ENABLE);
  
 -      ret = GetLFPCompMode(pScrn);
 -      if (ret != -1) {
 -	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 -		    "LFP compensation mode: 0x%x\n", ret);
 -      }
 -   }
 -#endif
 +   /* Next, disable display pipes */
 +   temp = INREG(PIPEACONF);
 +   OUTREG(PIPEACONF, temp & ~PIPEACONF_ENABLE);
 +   temp = INREG(PIPEBCONF);
 +   OUTREG(PIPEBCONF, temp & ~PIPEBCONF_ENABLE);
 +
 +   /* XXX: Wait for a vblank */
 +   sleep(1);
 +
 +   OUTREG(FPA0, pI830->saveFPA0);
 +   OUTREG(FPA1, pI830->saveFPA1);
 +   OUTREG(DPLL_A, pI830->saveDPLL_A);
 +   OUTREG(HTOTAL_A, pI830->saveHTOTAL_A);
 +   OUTREG(HBLANK_A, pI830->saveHBLANK_A);
 +   OUTREG(HSYNC_A, pI830->saveHSYNC_A);
 +   OUTREG(VTOTAL_A, pI830->saveVTOTAL_A);
 +   OUTREG(VBLANK_A, pI830->saveVBLANK_A);
 +   OUTREG(VSYNC_A, pI830->saveVSYNC_A);
 +   OUTREG(DSPASTRIDE, pI830->saveDSPASTRIDE);
 +   OUTREG(DSPASIZE, pI830->saveDSPASIZE);
 +   OUTREG(DSPAPOS, pI830->saveDSPAPOS);
 +   OUTREG(DSPABASE, pI830->saveDSPABASE);
 +   OUTREG(PIPEASRC, pI830->savePIPEASRC);
 +
 +   OUTREG(FPB0, pI830->saveFPB0);
 +   OUTREG(FPB1, pI830->saveFPB1);
 +   OUTREG(DPLL_B, pI830->saveDPLL_B);
 +   OUTREG(HTOTAL_B, pI830->saveHTOTAL_B);
 +   OUTREG(HBLANK_B, pI830->saveHBLANK_B);
 +   OUTREG(HSYNC_B, pI830->saveHSYNC_B);
 +   OUTREG(VTOTAL_B, pI830->saveVTOTAL_B);
 +   OUTREG(VBLANK_B, pI830->saveVBLANK_B);
 +   OUTREG(VSYNC_B, pI830->saveVSYNC_B);
 +   OUTREG(DSPBSTRIDE, pI830->saveDSPBSTRIDE);
 +   OUTREG(DSPBSIZE, pI830->saveDSPBSIZE);
 +   OUTREG(DSPBPOS, pI830->saveDSPBPOS);
 +   OUTREG(DSPBBASE, pI830->saveDSPBBASE);
 +   OUTREG(PIPEBSRC, pI830->savePIPEBSRC);
 +
 +   OUTREG(VCLK_DIVISOR_VGA0, pI830->saveVCLK_DIVISOR_VGA0);
 +   OUTREG(VCLK_DIVISOR_VGA1, pI830->saveVCLK_DIVISOR_VGA1);
 +   OUTREG(VCLK_POST_DIV, pI830->saveVCLK_POST_DIV);
 +
 +   OUTREG(PIPEACONF, pI830->savePIPEACONF);
 +   OUTREG(PIPEBCONF, pI830->savePIPEBCONF);
 +
 +   OUTREG(VGACNTRL, pI830->saveVGACNTRL);
 +   OUTREG(DSPACNTR, pI830->saveDSPACNTR);
 +   OUTREG(DSPBCNTR, pI830->saveDSPBCNTR);
  
 -#if MODESWITCH_RESET_STATE
 -   ResetState(pScrn, TRUE);
 -   SetHWOperatingState(pScrn);
 -#endif
 +   OUTREG(ADPA, pI830->saveADPA);
  
 -#ifdef XF86DRI
 -   if (didLock)
 -      I830DRIUnlock(pScrn);
 -#endif
 +   i830CompareRegsToSnapshot(pScrn);
  
 -   pScrn->vtSema = TRUE;
     return TRUE;
  }
  
diff --cc src/i830_modes.c
index 617d1e6,97e40e0..16576bb
@@@ -38,12 -38,681 +38,14 @@@
  #include "config.h"
  #endif
  
+ #include <stdio.h>
+ #include <string.h>
+ 
  #include "xf86.h"
- #include "xf86_ansic.h"
 -#include "vbe.h"
 -#include "vbeModes.h"
  #include "i830.h"
  
 -#include <math.h>
 -
 -#define rint(x) floor(x)
 -
 -#define MARGIN_PERCENT    1.8   /* % of active vertical image                */
 -#define CELL_GRAN         8.0   /* assumed character cell granularity        */
 -#define MIN_PORCH         1     /* minimum front porch                       */
 -#define V_SYNC_RQD        3     /* width of vsync in lines                   */
 -#define H_SYNC_PERCENT    8.0   /* width of hsync as % of total line         */
 -#define MIN_VSYNC_PLUS_BP 550.0 /* min time of vsync + back porch (microsec) */
 -#define M                 600.0 /* blanking formula gradient                 */
 -#define C                 40.0  /* blanking formula offset                   */
 -#define K                 128.0 /* blanking formula scaling factor           */
 -#define J                 20.0  /* blanking formula scaling factor           */
 -
 -/* C' and M' are part of the Blanking Duty Cycle computation */
 -
 -#define C_PRIME           (((C - J) * K/256.0) + J)
 -#define M_PRIME           (K/256.0 * M)
 -
  extern const int i830refreshes[];
  
 -static DisplayModePtr
 -I830GetGTF (int h_pixels, int v_lines, float freq,
 -                    int interlaced, int margins)
 -{
 -    float h_pixels_rnd;
 -    float v_lines_rnd;
 -    float v_field_rate_rqd;
 -    float top_margin;
 -    float bottom_margin;
 -    float interlace;
 -    float h_period_est;
 -    float vsync_plus_bp;
 -    float v_back_porch;
 -    float total_v_lines;
 -    float v_field_rate_est;
 -    float h_period;
 -    float v_field_rate;
 -    float v_frame_rate;
 -    float left_margin;
 -    float right_margin;
 -    float total_active_pixels;
 -    float ideal_duty_cycle;
 -    float h_blank;
 -    float total_pixels;
 -    float pixel_freq;
 -    float h_freq;
 -
 -    float h_sync;
 -    float h_front_porch;
 -    float v_odd_front_porch_lines;
 -    char modename[20];
 -    DisplayModePtr m;
 -
 -    m = xnfcalloc(sizeof(DisplayModeRec), 1);
 -    
 -    
 -    /*  1. In order to give correct results, the number of horizontal
 -     *  pixels requested is first processed to ensure that it is divisible
 -     *  by the character size, by rounding it to the nearest character
 -     *  cell boundary:
 -     *
 -     *  [H PIXELS RND] = ((ROUND([H PIXELS]/[CELL GRAN RND],0))*[CELLGRAN RND])
 -     */
 -    
 -    h_pixels_rnd = rint((float) h_pixels / CELL_GRAN) * CELL_GRAN;
 -    
 -    
 -    /*  2. If interlace is requested, the number of vertical lines assumed
 -     *  by the calculation must be halved, as the computation calculates
 -     *  the number of vertical lines per field. In either case, the
 -     *  number of lines is rounded to the nearest integer.
 -     *   
 -     *  [V LINES RND] = IF([INT RQD?]="y", ROUND([V LINES]/2,0),
 -     *                                     ROUND([V LINES],0))
 -     */
 -
 -    v_lines_rnd = interlaced ?
 -            rint((float) v_lines) / 2.0 :
 -            rint((float) v_lines);
 -    
 -    /*  3. Find the frame rate required:
 -     *
 -     *  [V FIELD RATE RQD] = IF([INT RQD?]="y", [I/P FREQ RQD]*2,
 -     *                                          [I/P FREQ RQD])
 -     */
 -
 -    v_field_rate_rqd = interlaced ? (freq * 2.0) : (freq);
 -
 -    /*  4. Find number of lines in Top margin:
 -     *
 -     *  [TOP MARGIN (LINES)] = IF([MARGINS RQD?]="Y",
 -     *          ROUND(([MARGIN%]/100*[V LINES RND]),0),
 -     *          0)
 -     */
 -
 -    top_margin = margins ? rint(MARGIN_PERCENT / 100.0 * v_lines_rnd) : (0.0);
 -
 -    /*  5. Find number of lines in Bottom margin:
 -     *
 -     *  [BOT MARGIN (LINES)] = IF([MARGINS RQD?]="Y",
 -     *          ROUND(([MARGIN%]/100*[V LINES RND]),0),
 -     *          0)
 -     */
 -
 -    bottom_margin = margins ? rint(MARGIN_PERCENT/100.0 * v_lines_rnd) : (0.0);
 -
 -    /*  6. If interlace is required, then set variable [INTERLACE]=0.5:
 -     *   
 -     *  [INTERLACE]=(IF([INT RQD?]="y",0.5,0))
 -     */
 -
 -    interlace = interlaced ? 0.5 : 0.0;
 -
 -    /*  7. Estimate the Horizontal period
 -     *
 -     *  [H PERIOD EST] = ((1/[V FIELD RATE RQD]) - [MIN VSYNC+BP]/1000000) /
 -     *                    ([V LINES RND] + (2*[TOP MARGIN (LINES)]) +
 -     *                     [MIN PORCH RND]+[INTERLACE]) * 1000000
 -     */
 -
 -    h_period_est = (((1.0/v_field_rate_rqd) - (MIN_VSYNC_PLUS_BP/1000000.0))
 -                    / (v_lines_rnd + (2*top_margin) + MIN_PORCH + interlace)
 -                    * 1000000.0);
 -
 -    /*  8. Find the number of lines in V sync + back porch:
 -     *
 -     *  [V SYNC+BP] = ROUND(([MIN VSYNC+BP]/[H PERIOD EST]),0)
 -     */
 -
 -    vsync_plus_bp = rint(MIN_VSYNC_PLUS_BP/h_period_est);
 -
 -    /*  9. Find the number of lines in V back porch alone:
 -     *
 -     *  [V BACK PORCH] = [V SYNC+BP] - [V SYNC RND]
 -     *
 -     *  XXX is "[V SYNC RND]" a typo? should be [V SYNC RQD]?
 -     */
 -    
 -    v_back_porch = vsync_plus_bp - V_SYNC_RQD;
 -    
 -    /*  10. Find the total number of lines in Vertical field period:
 -     *
 -     *  [TOTAL V LINES] = [V LINES RND] + [TOP MARGIN (LINES)] +
 -     *                    [BOT MARGIN (LINES)] + [V SYNC+BP] + [INTERLACE] +
 -     *                    [MIN PORCH RND]
 -     */
 -
 -    total_v_lines = v_lines_rnd + top_margin + bottom_margin + vsync_plus_bp +
 -        interlace + MIN_PORCH;
 -    
 -    /*  11. Estimate the Vertical field frequency:
 -     *
 -     *  [V FIELD RATE EST] = 1 / [H PERIOD EST] / [TOTAL V LINES] * 1000000
 -     */
 -
 -    v_field_rate_est = 1.0 / h_period_est / total_v_lines * 1000000.0;
 -    
 -    /*  12. Find the actual horizontal period:
 -     *
 -     *  [H PERIOD] = [H PERIOD EST] / ([V FIELD RATE RQD] / [V FIELD RATE EST])
 -     */
 -
 -    h_period = h_period_est / (v_field_rate_rqd / v_field_rate_est);
 -    
 -    /*  13. Find the actual Vertical field frequency:
 -     *
 -     *  [V FIELD RATE] = 1 / [H PERIOD] / [TOTAL V LINES] * 1000000
 -     */
 -
 -    v_field_rate = 1.0 / h_period / total_v_lines * 1000000.0;
 -
 -    /*  14. Find the Vertical frame frequency:
 -     *
 -     *  [V FRAME RATE] = (IF([INT RQD?]="y", [V FIELD RATE]/2, [V FIELD RATE]))
 -     */
 -
 -    v_frame_rate = interlaced ? v_field_rate / 2.0 : v_field_rate;
 -
 -    /*  15. Find number of pixels in left margin:
 -     *
 -     *  [LEFT MARGIN (PIXELS)] = (IF( [MARGINS RQD?]="Y",
 -     *          (ROUND( ([H PIXELS RND] * [MARGIN%] / 100 /
 -     *                   [CELL GRAN RND]),0)) * [CELL GRAN RND],
 -     *          0))
 -     */
 -
 -    left_margin = margins ?
 -        rint(h_pixels_rnd * MARGIN_PERCENT / 100.0 / CELL_GRAN) * CELL_GRAN :
 -        0.0;
 -    
 -    /*  16. Find number of pixels in right margin:
 -     *
 -     *  [RIGHT MARGIN (PIXELS)] = (IF( [MARGINS RQD?]="Y",
 -     *          (ROUND( ([H PIXELS RND] * [MARGIN%] / 100 /
 -     *                   [CELL GRAN RND]),0)) * [CELL GRAN RND],
 -     *          0))
 -     */
 -    
 -    right_margin = margins ?
 -        rint(h_pixels_rnd * MARGIN_PERCENT / 100.0 / CELL_GRAN) * CELL_GRAN :
 -        0.0;
 -    
 -    /*  17. Find total number of active pixels in image and left and right
 -     *  margins:
 -     *
 -     *  [TOTAL ACTIVE PIXELS] = [H PIXELS RND] + [LEFT MARGIN (PIXELS)] +
 -     *                          [RIGHT MARGIN (PIXELS)]
 -     */
 -
 -    total_active_pixels = h_pixels_rnd + left_margin + right_margin;
 -    
 -    /*  18. Find the ideal blanking duty cycle from the blanking duty cycle
 -     *  equation:
 -     *
 -     *  [IDEAL DUTY CYCLE] = [C'] - ([M']*[H PERIOD]/1000)
 -     */
 -
 -    ideal_duty_cycle = C_PRIME - (M_PRIME * h_period / 1000.0);
 -    
 -    /*  19. Find the number of pixels in the blanking time to the nearest
 -     *  double character cell:
 -     *
 -     *  [H BLANK (PIXELS)] = (ROUND(([TOTAL ACTIVE PIXELS] *
 -     *                               [IDEAL DUTY CYCLE] /
 -     *                               (100-[IDEAL DUTY CYCLE]) /
 -     *                               (2*[CELL GRAN RND])), 0))
 -     *                       * (2*[CELL GRAN RND])
 -     */
 -
 -    h_blank = rint(total_active_pixels *
 -                   ideal_duty_cycle /
 -                   (100.0 - ideal_duty_cycle) /
 -                   (2.0 * CELL_GRAN)) * (2.0 * CELL_GRAN);
 -    
 -    /*  20. Find total number of pixels:
 -     *
 -     *  [TOTAL PIXELS] = [TOTAL ACTIVE PIXELS] + [H BLANK (PIXELS)]
 -     */
 -
 -    total_pixels = total_active_pixels + h_blank;
 -    
 -    /*  21. Find pixel clock frequency:
 -     *
 -     *  [PIXEL FREQ] = [TOTAL PIXELS] / [H PERIOD]
 -     */
 -    
 -    pixel_freq = total_pixels / h_period;
 -    
 -    /*  22. Find horizontal frequency:
 -     *
 -     *  [H FREQ] = 1000 / [H PERIOD]
 -     */
 -
 -    h_freq = 1000.0 / h_period;
 -    
 -
 -    /* Stage 1 computations are now complete; I should really pass
 -       the results to another function and do the Stage 2
 -       computations, but I only need a few more values so I'll just
 -       append the computations here for now */
 -
 -    
 -
 -    /*  17. Find the number of pixels in the horizontal sync period:
 -     *
 -     *  [H SYNC (PIXELS)] =(ROUND(([H SYNC%] / 100 * [TOTAL PIXELS] /
 -     *                             [CELL GRAN RND]),0))*[CELL GRAN RND]
 -     */
 -
 -    h_sync = rint(H_SYNC_PERCENT/100.0 * total_pixels / CELL_GRAN) * CELL_GRAN;
 -
 -    /*  18. Find the number of pixels in the horizontal front porch period:
 -     *
 -     *  [H FRONT PORCH (PIXELS)] = ([H BLANK (PIXELS)]/2)-[H SYNC (PIXELS)]
 -     */
 -
 -    h_front_porch = (h_blank / 2.0) - h_sync;
 -
 -    /*  36. Find the number of lines in the odd front porch period:
 -     *
 -     *  [V ODD FRONT PORCH(LINES)]=([MIN PORCH RND]+[INTERLACE])
 -     */
 -    
 -    v_odd_front_porch_lines = MIN_PORCH + interlace;
 -    
 -    /* finally, pack the results in the DisplayMode struct */
 -    
 -    m->HDisplay  = (int) (h_pixels_rnd);
 -    m->HSyncStart = (int) (h_pixels_rnd + h_front_porch);
 -    m->HSyncEnd = (int) (h_pixels_rnd + h_front_porch + h_sync);
 -    m->HTotal = (int) (total_pixels);
 -
 -    m->VDisplay  = (int) (v_lines_rnd);
 -    m->VSyncStart = (int) (v_lines_rnd + v_odd_front_porch_lines);
 -    m->VSyncEnd = (int) (int) (v_lines_rnd + v_odd_front_porch_lines + V_SYNC_RQD);
 -    m->VTotal = (int) (total_v_lines);
 -
 -    m->Clock   = (int)(pixel_freq * 1000);
 -    m->SynthClock   = m->Clock;
 -    m->HSync = h_freq;
 -    m->VRefresh = v_frame_rate /* freq */;
 -
 -    snprintf(modename, sizeof(modename), "%dx%d", m->HDisplay,m->VDisplay);
 -    m->name = xnfstrdup(modename);
 -
 -    return (m);
 -}
 -
 -static DisplayModePtr
 -CheckMode(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, VbeInfoBlock *vbe, int id,
 -	  int flags)
 -{
 -    CARD16 major, minor;
 -    VbeModeInfoBlock *mode;
 -    DisplayModePtr p = NULL, pMode = NULL;
 -    VbeModeInfoData *data;
 -    Bool modeOK = FALSE;
 -    ModeStatus status = MODE_OK;
 -
 -    major = (unsigned)(vbe->VESAVersion >> 8);
 -    minor = vbe->VESAVersion & 0xff;
 -
 -    if ((mode = VBEGetModeInfo(pVbe, id)) == NULL)
 -	return NULL;
 -
 -    /* Does the mode match the depth/bpp? */
 -    /* Some BIOS's set BitsPerPixel to 15 instead of 16 for 15/16 */
 -    if (VBE_MODE_USABLE(mode, flags) &&
 -	((pScrn->bitsPerPixel == 1 && !VBE_MODE_COLOR(mode)) ||
 -	 (mode->BitsPerPixel > 8 &&
 -	  (mode->RedMaskSize + mode->GreenMaskSize +
 -	   mode->BlueMaskSize) == pScrn->depth &&
 -	  mode->BitsPerPixel == pScrn->bitsPerPixel) ||
 -	 (mode->BitsPerPixel == 15 && pScrn->depth == 15) ||
 -	 (mode->BitsPerPixel <= 8 &&
 -	  mode->BitsPerPixel == pScrn->bitsPerPixel))) {
 -	modeOK = TRUE;
 -	xf86ErrorFVerb(DEBUG_VERB, "*");
 -    }
 -
 -    if (mode->XResolution && mode->YResolution &&
 -	!I830CheckModeSupport(pScrn, mode->XResolution, mode->YResolution, id)) 
 -	modeOK = FALSE;
 -
 -
 -    /*
 -     * Check if there's a valid monitor mode that this one can be matched
 -     * up with from the 'specified' modes list.
 -     */
 -    if (modeOK) {
 -	for (p = pScrn->monitor->Modes; p != NULL; p = p->next) {
 -	    if ((p->type != 0) ||
 -		(p->HDisplay != mode->XResolution) ||
 -		(p->VDisplay != mode->YResolution) ||
 -		(p->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2)))
 -		continue;
 -	    status = xf86CheckModeForMonitor(p, pScrn->monitor);
 -	    if (status == MODE_OK) {
 -		modeOK = TRUE;
 -		break;
 -	    }
 -	}
 -	if (p) {
 -    		pMode = xnfcalloc(sizeof(DisplayModeRec), 1);
 -		memcpy((char*)pMode,(char*)p,sizeof(DisplayModeRec));
 -    		pMode->name = xnfstrdup(p->name);
 -	}
 -    } 
 -
 -    /*
 -     * Now, check if there's a valid monitor mode that this one can be matched
 -     * up with from the default modes list. i.e. VESA modes in xf86DefModes.c
 -     */
 -    if (modeOK && !pMode) {
 -	int refresh = 0, calcrefresh = 0;
 -	DisplayModePtr newMode = NULL;
 -
 -	for (p = pScrn->monitor->Modes; p != NULL; p = p->next) {
 -	    calcrefresh = (int)(((double)(p->Clock * 1000) /
 -                       (double)(p->HTotal * p->VTotal)) * 100);
 -	    if ((p->type != M_T_DEFAULT) ||
 -		(p->HDisplay != mode->XResolution) ||
 -		(p->VDisplay != mode->YResolution) ||
 -		(p->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2)))
 -		continue;
 -	    status = xf86CheckModeForMonitor(p, pScrn->monitor);
 -	    if (status == MODE_OK) {
 -	    	if (calcrefresh > refresh) {
 -			refresh = calcrefresh;
 -			newMode = p;
 -		}
 -		modeOK = TRUE;
 -	    }
 -	}
 -	if (newMode) {
 -    		pMode = xnfcalloc(sizeof(DisplayModeRec), 1);
 -		memcpy((char*)pMode,(char*)newMode,sizeof(DisplayModeRec));
 -    		pMode->name = xnfstrdup(newMode->name);
 -	}
 -    } 
 -
 -    /*
 -     * Check if there's a valid monitor mode that this one can be matched
 -     * up with.  The actual matching is done later.
 -     */
 -    if (modeOK && !pMode) {
 -	float vrefresh = 0.0f;
 -	int i;
 -
 -	for (i=0;i<pScrn->monitor->nVrefresh;i++) {
 -
 -  	    for (vrefresh = pScrn->monitor->vrefresh[i].hi; 
 -		 vrefresh >= pScrn->monitor->vrefresh[i].lo; vrefresh -= 1.0f) {
 -
 -	        if (vrefresh != (float)0.0f) {
 -                    float best_vrefresh;
 -                    int int_vrefresh;
 - 
 -                    /* Find the best refresh for the Intel chipsets */
 -                    int_vrefresh = I830GetBestRefresh(pScrn, (int)vrefresh);
 -		    best_vrefresh = (float)i830refreshes[int_vrefresh];
 -
 -                    /* Now, grab the best mode from the available refresh */
 -		    pMode = I830GetGTF(mode->XResolution, mode->YResolution, 
 -							best_vrefresh, 0, 0);
 -
 -    	            pMode->type = M_T_BUILTIN;
 -
 -	            status = xf86CheckModeForMonitor(pMode, pScrn->monitor);
 -	            if (status == MODE_OK) {
 -			if (major >= 3) {
 -			    if (pMode->Clock * 1000 <= mode->MaxPixelClock)
 -				modeOK = TRUE;
 -			    else
 -				modeOK = FALSE;
 -			} else
 -			    modeOK = TRUE;
 -	            } else
 -	    	        modeOK = FALSE;
 -  	            pMode->status = status;
 -	        } else { 
 -	            modeOK = FALSE;
 -	        }
 -	        if (modeOK) break;
 -            }
 -	    if (modeOK) break;
 -        }
 -    }
 -
 -    xf86ErrorFVerb(DEBUG_VERB,
 -	    "Mode: %x (%dx%d)\n", id, mode->XResolution, mode->YResolution);
 -    xf86ErrorFVerb(DEBUG_VERB,
 -	    "	ModeAttributes: 0x%x\n", mode->ModeAttributes);
 -    xf86ErrorFVerb(DEBUG_VERB,
 -	    "	WinAAttributes: 0x%x\n", mode->WinAAttributes);
 -    xf86ErrorFVerb(DEBUG_VERB,
 -	    "	WinBAttributes: 0x%x\n", mode->WinBAttributes);
 -    xf86ErrorFVerb(DEBUG_VERB,
 -	    "	WinGranularity: %d\n", mode->WinGranularity);
 -    xf86ErrorFVerb(DEBUG_VERB,
 -	    "	WinSize: %d\n", mode->WinSize);
 -    xf86ErrorFVerb(DEBUG_VERB,
 -	    "	WinASegment: 0x%x\n", mode->WinASegment);
 -    xf86ErrorFVerb(DEBUG_VERB,
 -	    "	WinBSegment: 0x%x\n", mode->WinBSegment);
 -    xf86ErrorFVerb(DEBUG_VERB,
 -		   "	WinFuncPtr: 0x%lx\n", (unsigned long)mode->WinFuncPtr);
 -    xf86ErrorFVerb(DEBUG_VERB,
 -	    "	BytesPerScanline: %d\n", mode->BytesPerScanline);
 -    xf86ErrorFVerb(DEBUG_VERB,
 -	    "	XResolution: %d\n", mode->XResolution);
 -    xf86ErrorFVerb(DEBUG_VERB,
 -	    "	YResolution: %d\n", mode->YResolution);
 -    xf86ErrorFVerb(DEBUG_VERB,
 -	    "	XCharSize: %d\n", mode->XCharSize);
 -    xf86ErrorFVerb(DEBUG_VERB,
 -           "	YCharSize: %d\n", mode->YCharSize);
 -    xf86ErrorFVerb(DEBUG_VERB,
 -	    "	NumberOfPlanes: %d\n", mode->NumberOfPlanes);
 -    xf86ErrorFVerb(DEBUG_VERB,
 -	    "	BitsPerPixel: %d\n", mode->BitsPerPixel);
 -    xf86ErrorFVerb(DEBUG_VERB,
 -	    "	NumberOfBanks: %d\n", mode->NumberOfBanks);
 -    xf86ErrorFVerb(DEBUG_VERB,
 -	    "	MemoryModel: %d\n", mode->MemoryModel);
 -    xf86ErrorFVerb(DEBUG_VERB,
 -	    "	BankSize: %d\n", mode->BankSize);
 -    xf86ErrorFVerb(DEBUG_VERB,
 -	    "	NumberOfImages: %d\n", mode->NumberOfImages);
 -    xf86ErrorFVerb(DEBUG_VERB,
 -	    "	RedMaskSize: %d\n", mode->RedMaskSize);
 -    xf86ErrorFVerb(DEBUG_VERB,
 -	    "	RedFieldPosition: %d\n", mode->RedFieldPosition);
 -    xf86ErrorFVerb(DEBUG_VERB,
 -	    "	GreenMaskSize: %d\n", mode->GreenMaskSize);
 -    xf86ErrorFVerb(DEBUG_VERB,
 -	    "	GreenFieldPosition: %d\n", mode->GreenFieldPosition);
 -    xf86ErrorFVerb(DEBUG_VERB,
 -	    "	BlueMaskSize: %d\n", mode->BlueMaskSize);
 -    xf86ErrorFVerb(DEBUG_VERB,
 -	    "	BlueFieldPosition: %d\n", mode->BlueFieldPosition);
 -    xf86ErrorFVerb(DEBUG_VERB,
 -	    "	RsvdMaskSize: %d\n", mode->RsvdMaskSize);
 -    xf86ErrorFVerb(DEBUG_VERB,
 -	    "	RsvdFieldPosition: %d\n", mode->RsvdFieldPosition);
 -    xf86ErrorFVerb(DEBUG_VERB,
 -	    "	DirectColorModeInfo: %d\n", mode->DirectColorModeInfo);
 -    if (major >= 2) {
 -	xf86ErrorFVerb(DEBUG_VERB,
 -		       "	PhysBasePtr: 0x%lx\n", 
 -		       (unsigned long)mode->PhysBasePtr);
 -	if (major >= 3) {
 -	    xf86ErrorFVerb(DEBUG_VERB,
 -		    "	LinBytesPerScanLine: %d\n", mode->LinBytesPerScanLine);
 -	    xf86ErrorFVerb(DEBUG_VERB,
 -		    "	BnkNumberOfImagePages: %d\n", mode->BnkNumberOfImagePages);
 -	    xf86ErrorFVerb(DEBUG_VERB,
 -		    "	LinNumberOfImagePages: %d\n", mode->LinNumberOfImagePages);
 -	    xf86ErrorFVerb(DEBUG_VERB,
 -		    "	LinRedMaskSize: %d\n", mode->LinRedMaskSize);
 -	    xf86ErrorFVerb(DEBUG_VERB,
 -		    "	LinRedFieldPosition: %d\n", mode->LinRedFieldPosition);
 -	    xf86ErrorFVerb(DEBUG_VERB,
 -		    "	LinGreenMaskSize: %d\n", mode->LinGreenMaskSize);
 -	    xf86ErrorFVerb(DEBUG_VERB,
 -		    "	LinGreenFieldPosition: %d\n", mode->LinGreenFieldPosition);
 -	    xf86ErrorFVerb(DEBUG_VERB,
 -		    "	LinBlueMaskSize: %d\n", mode->LinBlueMaskSize);
 -	    xf86ErrorFVerb(DEBUG_VERB,
 -		    "	LinBlueFieldPosition: %d\n", mode->LinBlueFieldPosition);
 -	    xf86ErrorFVerb(DEBUG_VERB,
 -		    "	LinRsvdMaskSize: %d\n", mode->LinRsvdMaskSize);
 -	    xf86ErrorFVerb(DEBUG_VERB,
 -		    "	LinRsvdFieldPosition: %d\n", mode->LinRsvdFieldPosition);
 -	    xf86ErrorFVerb(DEBUG_VERB,
 -			   "	MaxPixelClock: %ld\n", (unsigned long)
 -			   mode->MaxPixelClock);
 -	}
 -    }
 -
 -    if (!modeOK) {
 -	VBEFreeModeInfo(mode);
 -	if (pMode)
 -	    xfree(pMode);
 -	return NULL;
 -    }
 -
 -    pMode->status = MODE_OK;
 -    pMode->type = M_T_BUILTIN;
 -
 -    /* for adjust frame */
 -    pMode->HDisplay = mode->XResolution;
 -    pMode->VDisplay = mode->YResolution;
 -
 -    data = xnfcalloc(sizeof(VbeModeInfoData), 1);
 -    data->mode = id;
 -    data->data = mode;
 -    pMode->PrivSize = sizeof(VbeModeInfoData);
 -    pMode->Private = (INT32*)data;
 -    pMode->next = NULL;
 -    return pMode;
 -}
 -
 -/*
 - * Check the available BIOS modes, and extract those that match the
 - * requirements into the modePool.  Note: modePool is a NULL-terminated
 - * list.
 - */
 -
 -DisplayModePtr
 -I830GetModePool(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, VbeInfoBlock *vbe)
 -{
 -   DisplayModePtr pMode, p = NULL, modePool = NULL;
 -   int i = 0;
 -
 -   for (i = 0; i < 0x7F; i++) {
 -      if ((pMode = CheckMode(pScrn, pVbe, vbe, i, V_MODETYPE_VGA)) != NULL) {
 -         ModeStatus status = MODE_OK;
 -
 -		/* Check the mode against a specified virtual size (if any) */
 -		if (pScrn->display->virtualX > 0 &&
 -		    pMode->HDisplay > pScrn->display->virtualX) {
 -		    status = MODE_VIRTUAL_X;
 -		}
 -		if (pScrn->display->virtualY > 0 &&
 -		    pMode->VDisplay > pScrn->display->virtualY) {
 -		    status = MODE_VIRTUAL_Y;
 -		}
 -		if (status != MODE_OK) {
 -		     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 -				"Not using mode \"%dx%d\" (%s)\n",
 -				pMode->HDisplay, pMode->VDisplay,
 -				xf86ModeStatusToString(status));
 -		} else {
 -		    if (p == NULL) {
 -			modePool = pMode;
 -		    } else {
 -			p->next = pMode;
 -		    }
 -		    pMode->prev = NULL;
 -		    p = pMode;
 -		}
 -	    }
 -	}
 -    return modePool;
 -}
 -
 -/*
 - * Go through the monitor modes and selecting the best set of
 - * parameters for each BIOS mode.  Note: This is only supported in
 - * VBE version 3.0 or later.
 - */
 -void
 -I830SetModeParameters(ScrnInfoPtr pScrn, vbeInfoPtr pVbe)
 -{
 -    DisplayModePtr pMode;
 -    VbeModeInfoData *data;
 -
 -    pMode = pScrn->modes;
 -    do {
 -	int clock;
 -
 -	data = (VbeModeInfoData*)pMode->Private;
 -	data->block = xcalloc(sizeof(VbeCRTCInfoBlock), 1);
 -	data->block->HorizontalTotal = pMode->HTotal;
 -	data->block->HorizontalSyncStart = pMode->HSyncStart;
 -	data->block->HorizontalSyncEnd = pMode->HSyncEnd;
 -	data->block->VerticalTotal = pMode->VTotal;
 -	data->block->VerticalSyncStart = pMode->VSyncStart;
 -	data->block->VerticalSyncEnd = pMode->VSyncEnd;
 -	data->block->Flags = ((pMode->Flags & V_NHSYNC) ? CRTC_NHSYNC : 0) |
 -				 ((pMode->Flags & V_NVSYNC) ? CRTC_NVSYNC : 0);
 -	data->block->PixelClock = pMode->Clock * 1000;
 -	/* XXX May not have this. */
 -	clock = VBEGetPixelClock(pVbe, data->mode, data->block->PixelClock);
 -	if (clock)
 -	    data->block->PixelClock = clock;
 -#ifdef DEBUG
 -	ErrorF("Setting clock %.2fMHz, closest is %.2fMHz\n",
 -		(double)data->block->PixelClock / 1000000.0, 
 -		(double)clock / 1000000.0);
 -#endif
 -	data->mode |= (1 << 11);
 -	if (pMode->VRefresh != 0) {
 -	    data->block->RefreshRate = pMode->VRefresh * 100;
 -	} else {
 -	    data->block->RefreshRate = (int)(((double)(data->block->PixelClock)/
 -                       (double)(pMode->HTotal * pMode->VTotal)) * 100);
 -	}
 -	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 -		       "Attempting to use %2.2fHz refresh for mode \"%s\" (%x)\n",
 -		       (float)(((double)(data->block->PixelClock) / (double)(pMode->HTotal * pMode->VTotal))), pMode->name, data->mode);
 -#ifdef DEBUG
 -	ErrorF("Video Modeline: ID: 0x%x Name: %s %i %i %i %i - "
 -	       "  %i %i %i %i %.2f MHz Refresh: %.2f Hz\n",
 -	       data->mode, pMode->name, pMode->HDisplay, pMode->HSyncStart,
 -	       pMode->HSyncEnd, pMode->HTotal, pMode->VDisplay,
 -	       pMode->VSyncStart,pMode->VSyncEnd,pMode->VTotal,
 -	       (double)data->block->PixelClock/1000000.0,
 -	       (double)data->block->RefreshRate/100);
 -#endif
 -	pMode = pMode->next;
 -    } while (pMode != pScrn->modes);
 -}
 -
  void
  I830PrintModes(ScrnInfoPtr scrp)
  {
diff-tree 3de82ff3938c6559c90079be0c28dc507d62f79e (from 11ad8a590d65849be00e1be4e9dd52c1159a4f24)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Apr 10 15:10:15 2006 -0700

    Improve LVDS modes when outputting a CRT+LVDS combo at larger than the LVDS's
    panel size.  This is a hack until we get better clone mode, but it correctly
    displays a subset of the root on the LVDS by using a correct pixel clock and
    pipe/display size.

diff --git a/src/i830_display.c b/src/i830_display.c
index 3b92e4f..681ba2c 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -282,7 +282,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     CARD32 htot, hblank, hsync, vtot, vblank, vsync, dspcntr;
     CARD32 pipesrc, dspsize, adpa;
     Bool ok;
-    int refclk = 96000;
+    int refclk = 96000, pixel_clock;
     int outputs;
 
     ErrorF("Requested pix clock: %d\n", pMode->Clock);
@@ -309,7 +309,56 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	return FALSE;
     }
 
-    ok = i830FindBestPLL(pScrn, outputs, pMode->Clock, refclk, &m1, &m2, &n,
+    htot = (pMode->CrtcHDisplay - 1) | ((pMode->CrtcHTotal - 1) << 16);
+    hblank = (pMode->CrtcHBlankStart - 1) | ((pMode->CrtcHBlankEnd - 1) << 16);
+    hsync = (pMode->CrtcHSyncStart - 1) | ((pMode->CrtcHSyncEnd - 1) << 16);
+    vtot = (pMode->CrtcVDisplay - 1) | ((pMode->CrtcVTotal - 1) << 16);
+    vblank = (pMode->CrtcVBlankStart - 1) | ((pMode->CrtcVBlankEnd - 1) << 16);
+    vsync = (pMode->CrtcVSyncStart - 1) | ((pMode->CrtcVSyncEnd - 1) << 16);
+    pipesrc = ((pMode->HDisplay - 1) << 16) | (pMode->VDisplay - 1);
+    dspsize = ((pMode->VDisplay - 1) << 16) | (pMode->HDisplay - 1);
+    pixel_clock = pMode->Clock;
+    if (outputs & PIPE_LCD_ACTIVE && i830GetLVDSInfoFromBIOS(pScrn) &&
+	pI830->panel_fixed_hactive != 0)
+    {
+	/* To enable panel fitting, we need to set the pipe timings to that of
+	 * the screen at its full resolution.  So, drop the timings from the
+	 * BIOS VBT tables here.
+	 */
+	htot = (pI830->panel_fixed_hactive - 1) |
+		((pI830->panel_fixed_hactive + pI830->panel_fixed_hblank - 1)
+		 << 16);
+	hblank = (pI830->panel_fixed_hactive - 1) |
+		((pI830->panel_fixed_hactive + pI830->panel_fixed_hblank - 1)
+		 << 16);
+	hsync = (pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff - 1) |
+		((pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff +
+		  pI830->panel_fixed_hsyncwidth - 1) << 16);
+
+	vtot = (pI830->panel_fixed_vactive - 1) |
+		((pI830->panel_fixed_vactive + pI830->panel_fixed_vblank - 1)
+		 << 16);
+	vblank = (pI830->panel_fixed_vactive - 1) |
+		((pI830->panel_fixed_vactive + pI830->panel_fixed_vblank - 1)
+		 << 16);
+	vsync = (pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff - 1) |
+		((pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff +
+		  pI830->panel_fixed_vsyncwidth - 1) << 16);
+	/* Hack until we get better clone-mode modesetting.  If the mode to be
+	 * programmed is larger than the size of the panel, only display the
+	 * size of the panel.
+	 */
+	if (pMode->HDisplay > pI830->panel_fixed_hactive || 
+	    pMode->VDisplay > pI830->panel_fixed_vactive) {
+	    dspsize = ((pI830->panel_fixed_vactive - 1) << 16) |
+		      (pI830->panel_fixed_hactive - 1);
+	    pipesrc = ((pI830->panel_fixed_hactive - 1) << 16) |
+		      (pI830->panel_fixed_vactive - 1);
+	}
+	pixel_clock = pI830->panel_fixed_clock;
+    }
+
+    ok = i830FindBestPLL(pScrn, outputs, pixel_clock, refclk, &m1, &m2, &n,
 			 &p1, &p2);
     if (!ok) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
@@ -346,44 +395,15 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 
     fp = ((n - 2) << 16) | ((m1 - 2) << 8) | (m2 - 2);
 
-    htot = (pMode->CrtcHDisplay - 1) | ((pMode->CrtcHTotal - 1) << 16);
-    hblank = (pMode->CrtcHBlankStart - 1) | ((pMode->CrtcHBlankEnd - 1) << 16);
-    hsync = (pMode->CrtcHSyncStart - 1) | ((pMode->CrtcHSyncEnd - 1) << 16);
-    vtot = (pMode->CrtcVDisplay - 1) | ((pMode->CrtcVTotal - 1) << 16);
-    vblank = (pMode->CrtcVBlankStart - 1) | ((pMode->CrtcVBlankEnd - 1) << 16);
-    vsync = (pMode->CrtcVSyncStart - 1) | ((pMode->CrtcVSyncEnd - 1) << 16);
-    pipesrc = ((pMode->HDisplay - 1) << 16) | (pMode->VDisplay - 1);
-    dspsize = ((pMode->VDisplay - 1) << 16) | (pMode->HDisplay - 1);
-    if (outputs & PIPE_LCD_ACTIVE && i830GetLVDSInfoFromBIOS(pScrn) &&
-	pI830->panel_fixed_hactive != 0)
-    {
-	/* To enable panel fitting, we need to set the pipe timings to that of
-	 * the screen at its full resolution.  So, drop the timings from the
-	 * BIOS VBT tables here.
-	 */
-	htot = (pI830->panel_fixed_hactive - 1) |
-		((pI830->panel_fixed_hactive + pI830->panel_fixed_hblank - 1)
-		 << 16);
-	hblank = (pI830->panel_fixed_hactive - 1) |
-		((pI830->panel_fixed_hactive + pI830->panel_fixed_hblank - 1)
-		 << 16);
-	hsync = (pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff - 1) |
-		((pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff +
-		  pI830->panel_fixed_hsyncwidth - 1) << 16);
-
-	vtot = (pI830->panel_fixed_vactive - 1) |
-		((pI830->panel_fixed_vactive + pI830->panel_fixed_vblank - 1)
-		 << 16);
-	vblank = (pI830->panel_fixed_vactive - 1) |
-		((pI830->panel_fixed_vactive + pI830->panel_fixed_vblank - 1)
-		 << 16);
-	vsync = (pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff - 1) |
-		((pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff +
-		  pI830->panel_fixed_vsyncwidth - 1) << 16);
-    }
-#if 0
-    ErrorF("htot: 0x%08x, hblank: 0x%08x, hsync: 0x%08x\n", htot, hblank, hsync);
-    ErrorF("vtot: 0x%08x, vblank: 0x%08x, vsync: 0x%08x\n", vtot, vblank, vsync);
+#if 1
+    ErrorF("hact: %d htot: %d hbstart: %d hbend: %d hsyncstart: %d hsyncend: %d\n",
+	(int)(htot & 0xffff) + 1, (int)(htot >> 16) + 1,
+	(int)(hblank & 0xffff) + 1, (int)(hblank >> 16) + 1,
+	(int)(hsync & 0xffff) + 1, (int)(hsync >> 16) + 1);
+    ErrorF("vact: %d vtot: %d vbstart: %d vbend: %d vsyncstart: %d vsyncend: %d\n",
+	(int)(vtot & 0xffff) + 1, (int)(vtot >> 16) + 1,
+	(int)(vblank & 0xffff) + 1, (int)(vblank >> 16) + 1,
+	(int)(vsync & 0xffff) + 1, (int)(vsync >> 16) + 1);
 #endif
 
     adpa = INREG(ADPA);
diff-tree 11ad8a590d65849be00e1be4e9dd52c1159a4f24 (from 4217ce18cec257cad435adf9ddc9258a3c8164ec)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Apr 10 09:39:24 2006 -0700

    Remove the int10 POST on EnterVT.  It has been reported to cause crashes now,
    and I believe it is the responsibility of the kernel to bring the device back to
    a mostly-sane state on resume anyway.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 7d9bfc2..23a0631 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -4341,37 +4341,6 @@ I830BIOSEnterVT(int scrnIndex, int flags
 	  pScrn->virtualY * pScrn->displayWidth * pI830->cpp);
 #endif
 
-   if (I830IsPrimary(pScrn)) {
-     /* 
-      * This is needed for restoring from ACPI modes (especially S3)
-      * so that we warmboot the Video BIOS. Some platforms have problems,
-      * warm booting when we don't need to, so check that we can call
-      * the Video BIOS with our saved devices, and only when that fails,
-      * we'll warm boot it.
-      */
-     /* Check Pipe conf registers or possibly HTOTAL/VTOTAL for 0x00000000)*/
-      CARD32 temp = pI830->pipe ? INREG(PIPEBCONF) : INREG(PIPEACONF);
-      if (temp & 0x80000000) {
-         xf86Int10InfoPtr pInt;
-
-         xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
-				"Detected resume, re-POSTing.\n");
-
-         pInt = xf86InitInt10(pI830->pEnt->index);
-
-         /* Now perform our warm boot */
-         if (pInt) {
-            pInt->num = 0xe6;
-            xf86ExecX86int10 (pInt);
-            xf86FreeInt10 (pInt);
-            xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Re-POSTing via int10.\n");
-         } else {
-            xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 
-		"Re-POSTing via int10 failed, trying to continue.\n");
-         }
-      }
-   }
-
    /* Setup for device monitoring status */
    pI830->monitorSwitch = pI830->toggleDevices = INREG(SWF0) & 0x0000FFFF;
 
diff-tree 4217ce18cec257cad435adf9ddc9258a3c8164ec (from 334512e0604c208ffec914374a76d85720c1dcf9)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Apr 10 09:37:02 2006 -0700

    Warnings cleanup.

diff --git a/src/i830_display.c b/src/i830_display.c
index 6cc914d..3b92e4f 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -5,6 +5,7 @@
 #include "xf86.h"
 #include "xf86_ansic.h"
 #include "i830.h"
+#include "i830_bios.h"
 #include "i830_display.h"
 
 /** Returns the pixel clock for the given refclk and divisors. */
@@ -398,7 +399,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     ErrorF("clock settings for chosen look %s\n",
 	   i830PllIsValid(pScrn, outputs, refclk, m1, m2, n, p1, p2) ?
 			  "good" : "bad");
-    ErrorF("clock regs: 0x%08x, 0x%08x\n", dpll, fp);
+    ErrorF("clock regs: 0x%08x, 0x%08x\n", (int)dpll, (int)fp);
 
     dspcntr = DISPLAY_PLANE_ENABLE;
     switch (pScrn->bitsPerPixel) {
diff --git a/src/i830_driver.c b/src/i830_driver.c
index fa1019f..7d9bfc2 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1424,7 +1424,7 @@ void I830DetectMonitors(ScrnInfoPtr pScr
 	 pI830->output[i].MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex,
 						    pI830->output[i].pDDCBus);
 
-	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC %s %d, %08X\n",
+	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC %s %d, %08lX\n",
 		    output_type_names[pI830->output[i].type], i,
 		    pI830->output[i].pDDCBus->DriverPrivate.uval);
 	 xf86PrintEDID(pI830->output[i].MonInfo);
@@ -1445,7 +1445,7 @@ void I830DetectMonitors(ScrnInfoPtr pScr
 	    ret = I830I2CDetectDVOControllers(pScrn, pI830->output[i].pI2CBus,
 					      &pI830->output[i].i2c_drv);
 	    if (ret==TRUE) {
-	       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08X\n",
+	       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08lX\n",
 			  pI830->output[i].i2c_drv->modulename,
 			  pI830->output[i].pI2CBus->DriverPrivate.uval);
 	    }
@@ -3167,11 +3167,8 @@ static Bool
 SaveHWState(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
-   vbeInfoPtr pVbe = pI830->pVbe;
    vgaHWPtr hwp = VGAHWPTR(pScrn);
    vgaRegPtr vgaReg = &hwp->SavedReg;
-   VbeModeInfoBlock *modeInfo;
-   VESAPtr pVesa;
 
    DPRINTF(PFX, "SaveHWState\n");
 
diff-tree 334512e0604c208ffec914374a76d85720c1dcf9 (from 69083a2fc3ca4a3d06c1985c8a630d5628c1110c)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Apr 10 09:32:45 2006 -0700

    Don't try to use LVDS by default on chipsets that won't have an LVDS attached.
    The BIOS tables may still exist, so we can't rely on their presence to indicate
    LVDS attachment.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index eb6370c..fa1019f 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1702,7 +1702,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
    char *s;
    ClockRangePtr clockRanges;
    pointer pVBEModule = NULL;
-   Bool enable;
+   Bool enable, has_lvds;
    const char *chipname;
    unsigned int ver;
    char v[5];
@@ -1845,6 +1845,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
       pI830->pVbe = pI8301->pVbe;
    }
 
+   has_lvds = TRUE;
    switch (pI830->PciInfo->chipType) {
    case PCI_CHIP_I830_M:
       chipname = "830M";
@@ -1878,9 +1879,11 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
       break;
    case PCI_CHIP_I865_G:
       chipname = "865G";
+      has_lvds = FALSE;
       break;
    case PCI_CHIP_I915_G:
       chipname = "915G";
+      has_lvds = FALSE;
       break;
    case PCI_CHIP_E7221_G:
       chipname = "E7221 (i915)";
@@ -1890,6 +1893,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
       break;
    case PCI_CHIP_I945_G:
       chipname = "945G";
+      has_lvds = FALSE;
       break;
    case PCI_CHIP_I945_GM:
       chipname = "945GM";
@@ -2215,7 +2219,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
       pI830->specifiedMonitor = TRUE;
    } else if (I830IsPrimary(pScrn)) {
       /* Choose a default set of outputs to use based on what we've detected. */
-      if (i830GetLVDSInfoFromBIOS(pScrn)) {
+      if (i830GetLVDSInfoFromBIOS(pScrn) && has_lvds) {
 	 pI830->MonType2 |= PIPE_LFP;
       }
 
diff-tree 69083a2fc3ca4a3d06c1985c8a630d5628c1110c (from 2e5d85fb83def483ab1fd96877aae4a89a962b7f)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Apr 3 16:29:14 2006 -0700

    Remove BIOS save/restore code, fixing VT switching. Removes some other dead
    code, too.

diff --git a/src/i830.h b/src/i830.h
index 1fc3336..87dda25 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -567,7 +567,6 @@ extern void I830ChangeFrontbuffer(ScrnIn
 extern Bool I830IsPrimary(ScrnInfoPtr pScrn);
 
 extern void I830PrintModes(ScrnInfoPtr pScrn);
-extern int I830GetBestRefresh(ScrnInfoPtr pScrn, int refresh);
 extern Bool I830CheckModeSupport(ScrnInfoPtr pScrn, int x, int y, int mode);
 extern Bool I830Rotate(ScrnInfoPtr pScrn, DisplayModePtr mode);
 extern Bool I830FixOffset(ScrnInfoPtr pScrn, I830MemRange *mem);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 20541e0..eb6370c 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -544,41 +544,6 @@ GetAttachableDisplayDeviceList(ScrnInfoP
    return pVbe->pInt10->cx & 0xffff;
 }
 
-static int
-BitToRefresh(int bits)
-{
-   int i;
-
-   for (i = 0; i < nrefreshes; i++)
-      if (bits & (1 << i))
-	 return i830refreshes[i];
-   return 0;
-}
-
-static int
-GetRefreshRate(ScrnInfoPtr pScrn, int mode, int *availRefresh)
-{
-   vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
-
-   DPRINTF(PFX, "GetRefreshRate\n");
-
-   /* Only 8-bit mode numbers are supported. */
-   if (mode & 0x100)
-      return 0;
-
-   pVbe->pInt10->num = 0x10;
-   pVbe->pInt10->ax = 0x5f05;
-   pVbe->pInt10->bx = (mode & 0xff) | 0x100;
-
-   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
-   if (Check5fStatus(pScrn, 0x5f05, pVbe->pInt10->ax)) {
-      if (availRefresh)
-         *availRefresh = pVbe->pInt10->bx;
-      return BitToRefresh(pVbe->pInt10->cx);
-   } else
-      return 0;
-}
-
 struct panelid {
 	short hsize;
 	short vsize;
@@ -592,28 +557,6 @@ struct panelid {
 	char reserved[14];
 };
 
-int 
-I830GetBestRefresh(ScrnInfoPtr pScrn, int refresh)
-{
-   int i;
-
-   for (i = nrefreshes - 1; i >= 0; i--) {
-      /*
-       * Look for the highest value that the requested (refresh + 2) is
-       * greater than or equal to.
-       */
-      if (i830refreshes[i] <= (refresh + 2))
-	 break;
-   }
-   /* i can be 0 if the requested refresh was higher than the max. */
-   if (i == 0) {
-      if (refresh >= i830refreshes[nrefreshes - 1])
-         i = nrefreshes - 1;
-   }
-
-   return i;
-}
-
 static Bool
 SetBIOSPipe(ScrnInfoPtr pScrn, int pipe)
 {
@@ -1538,8 +1481,6 @@ PreInitCleanup(ScrnInfoPtr pScrn)
    I830Ptr pI830 = I830PTR(pScrn);
 
    if (I830IsPrimary(pScrn)) {
-      SetPipeAccess(pScrn);
-
       pI830->entityPrivate->pScrn_1 = NULL;
       if (pI830->LpRing)
          xfree(pI830->LpRing);
@@ -2740,8 +2681,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
 	      "Maximum frambuffer space: %d kByte\n", pScrn->videoRam);
 
-   SetPipeAccess(pScrn);
-
    /* XXX Move this to a header. */
 #define VIDEO_BIOS_SCRATCH 0x18
 
@@ -2963,7 +2902,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
 
    pI830->displayWidth = pScrn->displayWidth;
 
-   SetPipeAccess(pScrn);
    I830PrintModes(pScrn);
 
    /* PreInit shouldn't leave any state changes, so restore this. */
@@ -3280,63 +3218,6 @@ SaveHWState(ScrnInfoPtr pScrn)
    vgaHWUnlock(hwp);
    vgaHWSave(pScrn, vgaReg, VGA_SR_ALL);
 
-   if (I830IsPrimary(pScrn) && pI830->pipe != pI830->origPipe)
-      SetBIOSPipe(pScrn, pI830->origPipe);
-   else
-      SetPipeAccess(pScrn);
-
-   pVesa = pI830->vesa;
-
-   /* Make sure we save at least this information in case of failure. */
-   VBEGetVBEMode(pVbe, &pVesa->stateMode);
-   pVesa->stateRefresh = GetRefreshRate(pScrn, pVesa->stateMode, NULL);
-   modeInfo = VBEGetModeInfo(pVbe, pVesa->stateMode);
-   pVesa->savedScanlinePitch = 0;
-   if (modeInfo) {
-      if (VBE_MODE_GRAPHICS(modeInfo)) {
-         VBEGetLogicalScanline(pVbe, &pVesa->savedScanlinePitch, NULL, NULL);
-      }
-      VBEFreeModeInfo(modeInfo);
-   }
-
-   pVesa = pI830->vesa;
-   /*
-    * This save/restore method doesn't work for 845G BIOS, or for some
-    * other platforms.  Enable it in all cases.
-    */
-   /*
-    * KW: This may have been because of the behaviour I've found on my
-    * board: The 'save' command actually modifies the interrupt
-    * registers, turning off the irq & breaking the kernel module
-    * behaviour.
-    */
-   if (!pI830->vbeRestoreWorkaround) {
-      CARD16 imr = INREG16(IMR);
-      CARD16 ier = INREG16(IER);
-      CARD16 hwstam = INREG16(HWSTAM);
-
-      if (!VBESaveRestore(pVbe, MODE_SAVE, &pVesa->state, &pVesa->stateSize,
-			  &pVesa->statePage)) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		    "SaveHWState: VBESaveRestore(MODE_SAVE) failed.\n");
-	 return FALSE;
-      }
-
-      OUTREG16(IMR, imr);
-      OUTREG16(IER, ier);
-      OUTREG16(HWSTAM, hwstam);
-   }
-
-   pVesa->savedPal = VBESetGetPaletteData(pVbe, FALSE, 0, 256,
-					     NULL, FALSE, FALSE);
-   if (!pVesa->savedPal) {
-      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		 "SaveHWState: VBESetGetPaletteData(GET) failed.\n");
-      return FALSE;
-   }
-
-   VBEGetDisplayStart(pVbe, &pVesa->x, &pVesa->y);
-
    return TRUE;
 }
 
@@ -3344,64 +3225,12 @@ static Bool
 RestoreHWState(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
-   vbeInfoPtr pVbe = pI830->pVbe;
    vgaHWPtr hwp = VGAHWPTR(pScrn);
    vgaRegPtr vgaReg = &hwp->SavedReg;
-   VESAPtr pVesa;
-   Bool restored = FALSE;
    CARD32 temp;
 
    DPRINTF(PFX, "RestoreHWState\n");
 
-   if (I830IsPrimary(pScrn) && pI830->pipe != pI830->origPipe)
-      SetBIOSPipe(pScrn, pI830->origPipe);
-   else
-      SetPipeAccess(pScrn);
-
-   pVesa = pI830->vesa;
-
-   if (pVesa->state && pVesa->stateSize) {
-      CARD16 imr = INREG16(IMR);
-      CARD16 ier = INREG16(IER);
-      CARD16 hwstam = INREG16(HWSTAM);
-
-      /* Make a copy of the state.  Don't rely on it not being touched. */
-      if (!pVesa->pstate) {
-	 pVesa->pstate = xalloc(pVesa->stateSize);
-	 if (pVesa->pstate)
-	    memcpy(pVesa->pstate, pVesa->state, pVesa->stateSize);
-      }
-      restored = VBESaveRestore(pVbe, MODE_RESTORE, &pVesa->state,
-				   &pVesa->stateSize, &pVesa->statePage);
-      if (!restored) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		    "RestoreHWState: VBESaveRestore failed.\n");
-      }
-      /* Copy back */
-      if (pVesa->pstate)
-	 memcpy(pVesa->state, pVesa->pstate, pVesa->stateSize);
-
-      OUTREG16(IMR, imr);
-      OUTREG16(IER, ier);
-      OUTREG16(HWSTAM, hwstam);
-   }
-   /* If that failed, restore the original mode. */
-   if (!restored) {
-      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		 "Setting the original video mode instead of restoring\n\t"
-		 "the saved state\n");
-#if 0
-      I830VESASetVBEMode(pScrn, pVesa->stateMode, NULL);
-#endif
-   }
-   if (pVesa->savedScanlinePitch)
-       VBESetLogicalScanline(pVbe, pVesa->savedScanlinePitch);
-
-   if (pVesa->savedPal)
-      VBESetGetPaletteData(pVbe, TRUE, 0, 256, pVesa->savedPal, FALSE, TRUE);
-
-   VBESetDisplayStart(pVbe, pVesa->x, pVesa->y, TRUE);
-
    vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL);
    vgaHWLock(hwp);
 
diff-tree 2e5d85fb83def483ab1fd96877aae4a89a962b7f (from ceb08d28f4a4e9f42c9417938b8541bf1b4e8245)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Apr 3 16:27:24 2006 -0700

    Turn off the VGA plane when we're setting our native modes.

diff --git a/src/i830_display.c b/src/i830_display.c
index ebe0aa3..6cc914d 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -432,6 +432,8 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	adpa |= ADPA_PIPE_B_SELECT;
     }
 
+    OUTREG(VGACNTRL, VGA_DISP_DISABLE);
+
     /* Set up display timings and PLLs for the pipe. */
     if (pipe == 0) {
 	/* First, disable display planes */
diff-tree ceb08d28f4a4e9f42c9417938b8541bf1b4e8245 (from 1f0ba458d02f7d4777c1669aae02138f3a6628c1)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Apr 3 15:32:41 2006 -0700

    Remove the hacky-looking Set640x480. I'll be removing things it depends on
    (setpipe), and I suspect we'll end up with different hacks for resume, anyway.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 99a4c29..20541e0 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -658,27 +658,6 @@ SetPipeAccess(ScrnInfoPtr pScrn)
 }
 
 static Bool
-I830Set640x480(ScrnInfoPtr pScrn)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   int m = 0x30; /* 640x480 8bpp */
-
-   switch (pScrn->depth) {
-   case 15:
-	 m = 0x40;
-	 break;
-   case 16:
-	 m = 0x41;
-	 break;
-   case 24:
-	 m = 0x50;
-	 break;
-   }
-   m |= (1 << 15) | (1 << 14);
-   return VBESetVBEMode(pI830->pVbe, m, NULL);
-}
-
-static Bool
 GetBIOSVersion(ScrnInfoPtr pScrn, unsigned int *version)
 {
    vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
@@ -4542,7 +4521,7 @@ I830BIOSEnterVT(int scrnIndex, int flags
       */
      /* Check Pipe conf registers or possibly HTOTAL/VTOTAL for 0x00000000)*/
       CARD32 temp = pI830->pipe ? INREG(PIPEBCONF) : INREG(PIPEACONF);
-      if (!I830Set640x480(pScrn) || !(temp & 0x80000000)) {
+      if (temp & 0x80000000) {
          xf86Int10InfoPtr pInt;
 
          xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
diff-tree 1f0ba458d02f7d4777c1669aae02138f3a6628c1 (from b20b466aaed54708ae9e4676623c8c394a6f00d5)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Apr 3 15:28:47 2006 -0700

    Remove more BIOS stuff, particularly Get/SetDisplayDevices. Now, if there's no
    hardcoding in the config file, we default to LFP if we detect it from BIOS, and
    LFP or CRT if we can get EDID out of them.

diff --git a/src/i830.h b/src/i830.h
index d96e5aa..1fc3336 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -391,7 +391,6 @@ typedef struct _I830Rec {
    int monitorSwitch;
    int operatingDevices;
    int toggleDevices;
-   int savedDevices;
    int lastDevice0, lastDevice1, lastDevice2;
 
    /* These are indexed by the display types */
@@ -402,7 +401,6 @@ typedef struct _I830Rec {
    int availablePipes;
    int pipeDevices[MAX_DISPLAY_PIPES];
    /* [0] is display plane A, [1] is display plane B. */
-   Bool pipeEnabled[MAX_DISPLAY_PIPES];
    int planeEnabled[MAX_DISPLAY_PIPES];
 
    /* Driver phase/state information */
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 06f14d7..99a4c29 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -614,81 +614,6 @@ I830GetBestRefresh(ScrnInfoPtr pScrn, in
    return i;
 }
 
-static int
-GetDisplayDevices(ScrnInfoPtr pScrn)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   vbeInfoPtr pVbe = pI830->pVbe;
-
-   DPRINTF(PFX, "GetDisplayDevices\n");
-
-#if 0
-   {
-      CARD32 temp;
-      ErrorF("ADPA is 0x%08x\n", INREG(ADPA));
-      ErrorF("DVOA is 0x%08x\n", INREG(DVOA));
-      ErrorF("DVOB is 0x%08x\n", INREG(DVOB));
-      ErrorF("DVOC is 0x%08x\n", INREG(DVOC));
-      ErrorF("LVDS is 0x%08x\n", INREG(LVDS));
-      temp = INREG(DVOA_SRCDIM);
-      ErrorF("DVOA_SRCDIM is 0x%08x (%d x %d)\n", temp,
-	     (temp >> 12) & 0xfff, temp & 0xfff);
-      temp = INREG(DVOB_SRCDIM);
-      ErrorF("DVOB_SRCDIM is 0x%08x (%d x %d)\n", temp,
-	     (temp >> 12) & 0xfff, temp & 0xfff);
-      temp = INREG(DVOC_SRCDIM);
-      ErrorF("DVOC_SRCDIM is 0x%08x (%d x %d)\n", temp,
-	     (temp >> 12) & 0xfff, temp & 0xfff);
-      ErrorF("SWF0 is 0x%08x\n", INREG(SWF0));
-      ErrorF("SWF4 is 0x%08x\n", INREG(SWF4));
-   }
-#endif
-
-   pVbe->pInt10->num = 0x10;
-   pVbe->pInt10->ax = 0x5f64;
-   pVbe->pInt10->bx = 0x100;
-
-   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
-   if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) {
-      return pVbe->pInt10->cx & 0xffff;
-   } else {
-      if (pI830->PciInfo->chipType == PCI_CHIP_E7221_G) /* FIXED CONFIG */
-         return PIPE_CRT;
-      else
-         return -1;
-   }
-}
-
-static int
-GetBIOSPipe(ScrnInfoPtr pScrn)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   vbeInfoPtr pVbe = pI830->pVbe;
-   int pipe;
-
-   DPRINTF(PFX, "GetBIOSPipe:\n");
-
-   /* single pipe machines should always return Pipe A */
-   if (pI830->availablePipes == 1) return 0;
-
-   pVbe->pInt10->num = 0x10;
-   pVbe->pInt10->ax = 0x5f1c;
-   pVbe->pInt10->bx = 0x100;
-
-   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
-   if (Check5fStatus(pScrn, 0x5f1c, pVbe->pInt10->ax)) {
-      if (pI830->newPipeSwitch) {
-         pipe = ((pVbe->pInt10->bx & 0x0001));
-      } else {
-         pipe = ((pVbe->pInt10->cx & 0x0100) >> 8);
-      }
-      return pipe;
-   }
-
-   /* failed, assume pipe A */
-   return 0;
-}
-
 static Bool
 SetBIOSPipe(ScrnInfoPtr pScrn, int pipe)
 {
@@ -753,185 +678,6 @@ I830Set640x480(ScrnInfoPtr pScrn)
    return VBESetVBEMode(pI830->pVbe, m, NULL);
 }
 
-/* This is needed for SetDisplayDevices to work correctly on I915G.
- * Enable for all chipsets now as it has no bad side effects, apart
- * from slightly longer startup time.
- */
-#define I915G_WORKAROUND
-
-static Bool
-SetDisplayDevices(ScrnInfoPtr pScrn, int devices)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   vbeInfoPtr pVbe = pI830->pVbe;
-   CARD32 temp;
-   int singlepipe = 0;
-#ifdef I915G_WORKAROUND
-   int getmode1;
-   Bool setmode = FALSE;
-#endif
-
-   DPRINTF(PFX, "SetDisplayDevices: devices 0x%x\n", devices);
-
-   if (!pI830->specifiedMonitor)
-      return TRUE;
-
-#ifdef I915G_WORKAROUND
-   if (pI830->preinit)
-      setmode = TRUE;
-   if (pI830->leaving)
-      setmode = FALSE;
-   if (pI830->closing)
-      setmode = FALSE;
-
-   if (setmode) {
-      VBEGetVBEMode(pVbe, &getmode1);
-      I830Set640x480(pScrn);
-   }
-#endif
-
-   pVbe->pInt10->num = 0x10;
-   pVbe->pInt10->ax = 0x5f64;
-   pVbe->pInt10->bx = 0x1;
-   pVbe->pInt10->cx = devices;
-
-   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
-   if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) {
-#ifdef I915G_WORKAROUND
-      if (setmode) {
-  	 VBESetVBEMode(pI830->pVbe, getmode1 | 1<<15, NULL);
-      }
-#endif
-      pI830->pipeEnabled[0] = (devices & 0xff) ? TRUE : FALSE;
-      pI830->pipeEnabled[1] = (devices & 0xff00) ? TRUE : FALSE;
-
-      return TRUE;
-   }
-
-#ifdef I915G_WORKAROUND
-   if (setmode)
-      VBESetVBEMode(pI830->pVbe, getmode1 | 1<<15, NULL);
-#endif
-
-   if (devices & 0xff) {
-      pVbe->pInt10->num = 0x10;
-      pVbe->pInt10->ax = 0x5f64;
-      pVbe->pInt10->bx = 0x1;
-      pVbe->pInt10->cx = devices & 0xff;
-
-      xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
-      if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) {
-         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-	 	"Successfully set display devices to 0x%x.\n",devices & 0xff);
-         singlepipe = devices & 0xff00; /* set alternate */
-      } else {
-         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-	 	"Failed to set display devices to 0x%x.\n",devices & 0xff);
-         singlepipe = devices;
-      }
-   } else
-      singlepipe = devices; 
-
-   if (singlepipe == devices && devices & 0xff00) {
-      pVbe->pInt10->num = 0x10;
-      pVbe->pInt10->ax = 0x5f64;
-      pVbe->pInt10->bx = 0x1;
-      pVbe->pInt10->cx = devices & 0xff00;
-
-      xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
-      if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) {
-         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-	 	"Successfully set display devices to 0x%x.\n",devices & 0xff00);
-         singlepipe = devices & 0xff; /* set alternate */
-      } else {
-         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-	 	"Failed to set display devices to 0x%x.\n",devices & 0xff00);
-         singlepipe = devices;
-      }
-   } 
-
-   /* LVDS doesn't exist on these */
-   if (IS_I830(pI830) || IS_845G(pI830) || IS_I865G(pI830))
-      singlepipe &= ~(PIPE_LFP | (PIPE_LFP<<8));
-
-   if (pI830->availablePipes == 1) 
-      singlepipe &= 0xFF;
-
-   /* Disable LVDS */
-   if (singlepipe & PIPE_LFP)  {
-      /* LFP on PipeA is unlikely! */
-      i830SetLVDSPanelPower(pScrn, FALSE);
-      temp = INREG(LVDS) & ~LVDS_PIPEB_SELECT;
-      temp |= LVDS_PORT_EN | LVDS_CLKA_POWER_UP;
-      OUTREG(LVDS, temp);
-      i830SetLVDSPanelPower(pScrn, TRUE);
-      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-	 	"Enabling LVDS directly. Pipe A.\n");
-   } else
-   if (singlepipe & (PIPE_LFP << 8))  {
-      i830SetLVDSPanelPower(pScrn, FALSE);
-      temp = INREG(LVDS) | LVDS_PIPEB_SELECT;
-      temp |= LVDS_PORT_EN | LVDS_CLKA_POWER_UP;
-      OUTREG(LVDS, temp);
-      i830SetLVDSPanelPower(pScrn, TRUE);
-      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-	 	"Enabling LVDS directly. Pipe B.\n");
-   }
-   else if (!(IS_I830(pI830) || IS_845G(pI830) || IS_I865G(pI830))) {
-      if (!(devices & (PIPE_LFP | PIPE_LFP<<8))) {
-	 i830SetLVDSPanelPower(pScrn, FALSE);
-         /* Fix up LVDS */
-	 temp = INREG(LVDS) | LVDS_PIPEB_SELECT;
-	 temp &= ~(LVDS_PORT_EN | LVDS_CLKA_POWER_UP);
-	 OUTREG(LVDS, temp);
-         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-	 	"Disabling LVDS directly.\n");
-      }
-   }
-
-   /* Now try to program the registers directly if the BIOS failed. */
-   temp = INREG(ADPA);
-   temp &= ~(ADPA_DAC_ENABLE | ADPA_PIPE_SELECT_MASK);
-   temp &= ~(ADPA_VSYNC_CNTL_DISABLE | ADPA_HSYNC_CNTL_DISABLE);
-   /* Turn on ADPA */
-   if (singlepipe & PIPE_CRT)  {
-      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-	 	"Enabling ADPA directly. Pipe A.\n");
-      temp |= ADPA_DAC_ENABLE | ADPA_PIPE_A_SELECT;
-      OUTREG(ADPA, temp);
-   } else
-   if (singlepipe & (PIPE_CRT << 8)) {
-      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-	 	"Enabling ADPA directly. Pipe B.\n");
-      temp |= ADPA_DAC_ENABLE | ADPA_PIPE_B_SELECT;
-      OUTREG(ADPA, temp);
-   } 
-   else {
-      if (!(devices & (PIPE_CRT | PIPE_CRT<<8))) {
-         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-	 	"Disabling ADPA directly.\n");
-         temp |= ADPA_VSYNC_CNTL_DISABLE | ADPA_HSYNC_CNTL_DISABLE;
-         OUTREG(ADPA, temp);
-      }
-   }
-
-   xf86DrvMsg(pScrn->scrnIndex, X_WARNING,"Writing config directly to SWF0.\n");
-   temp = INREG(SWF0);
-   OUTREG(SWF0, (temp & ~(0xffff)) | (devices & 0xffff));
-
-   if (GetDisplayDevices(pScrn) != devices) {
-      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		 "SetDisplayDevices failed with devices 0x%x instead of 0x%x\n",
-	         GetDisplayDevices(pScrn), devices);
-      return FALSE;
-   }
-
-   pI830->pipeEnabled[0] = (devices & 0xff) ? TRUE : FALSE;
-   pI830->pipeEnabled[1] = (devices & 0xff00) ? TRUE : FALSE;
-
-   return TRUE;
-}
-
 static Bool
 GetBIOSVersion(ScrnInfoPtr pScrn, unsigned int *version)
 {
@@ -977,52 +723,6 @@ GetDevicePresence(ScrnInfoPtr pScrn, Boo
       return FALSE;
 }
 
-static Bool
-GetDisplayInfo(ScrnInfoPtr pScrn, int device, Bool *attached, Bool *present,
-	       short *x, short *y)
-{
-   vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
-
-   DPRINTF(PFX, "GetDisplayInfo: device: 0x%x\n", device);
-
-   switch (device & 0xff) {
-   case 0x01:
-   case 0x02:
-   case 0x04:
-   case 0x08:
-   case 0x10:
-   case 0x20:
-      break;
-   default:
-      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		 "GetDisplayInfo: invalid device: 0x%x\n", device & 0xff);
-      return FALSE;
-   }
-
-   pVbe->pInt10->num = 0x10;
-   pVbe->pInt10->ax = 0x5f64;
-   pVbe->pInt10->bx = 0x300;
-   pVbe->pInt10->cx = device & 0xff;
-
-   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
-   if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) {
-      if (attached)
-	 *attached = ((pVbe->pInt10->bx & 0x2) != 0);
-      if (present)
-	 *present = ((pVbe->pInt10->bx & 0x1) != 0);
-      if (pVbe->pInt10->cx != (device & 0xff)) {
-	 if (y) {
-	    *y = pVbe->pInt10->cx & 0xffff;
-	 }
-	 if (x) {
-	    *x = (pVbe->pInt10->cx >> 16) & 0xffff;
-	 }
-      }
-      return TRUE;
-   } else
-      return FALSE;
-}
-
 /*
  * Returns a string matching the device corresponding to the first bit set
  * in "device".  savedDevice is then set to device with that bit cleared.
@@ -1109,46 +809,6 @@ PrintDisplayDeviceInfo(ScrnInfoPtr pScrn
    }
 }
 
-static Bool
-I830DetectDisplayDevice(ScrnInfoPtr pScrn)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   int pipe, n;
-   DisplayType i;
-   
-   /* This seems to lockup some Dell BIOS'. So it's on option to turn on */
-   if (pI830->displayInfo) {
-       xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		  "Broken BIOSes cause the system to hang here.\n"
-		  "\t      If you encounter this problem please add \n"
-		  "\t\t Option \"DisplayInfo\" \"FALSE\"\n"
-		  "\t      to the Device section of your XF86Config file.\n");
-      for (i = 0; i < NumKnownDisplayTypes; i++) {
-	 int unusedx, unusedy;
-         if (GetDisplayInfo(pScrn, 1 << i, &pI830->displayAttached[i],
-			 &pI830->displayPresent[i],
-			 &unusedx, &unusedy)) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		    "Display Info: %s: attached: %s, present: %s: "
-		    "(%d,%d)\n", displayDevices[i],
-		    BOOLTOSTRING(pI830->displayAttached[i]),
-		    BOOLTOSTRING(pI830->displayPresent[i]));
-         }
-      }
-   }
-
-   /* Check for active devices connected to each display pipe. */
-   for (n = 0; n < pI830->availablePipes; n++) {
-      pipe = ((pI830->operatingDevices >> PIPE_SHIFT(n)) & PIPE_ACTIVE_MASK);
-      if (pipe)
-	 pI830->pipeEnabled[n] = TRUE;
-      else
-	 pI830->pipeEnabled[n] = FALSE;
-   }
-
-   return TRUE;
-}
-
 static int
 I830DetectMemory(ScrnInfoPtr pScrn)
 {
@@ -1680,6 +1340,7 @@ I830LoadPalette(ScrnInfoPtr pScrn, int n
    }
 }
 
+#if 0
 static int
 I830UseDDC(ScrnInfoPtr pScrn)
 {
@@ -1744,6 +1405,7 @@ I830UseDDC(ScrnInfoPtr pScrn)
 
    return mon_range->max_clock;
 }
+#endif
 
 static void
 I830SetupOutputBusses(ScrnInfoPtr pScrn)
@@ -2624,7 +2286,50 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
             return FALSE;
       }
 
+      if (pI830->MonType1 != PIPE_NONE)
+	 pI830->pipe = 0;
+      else
+	 pI830->pipe = 1;
+
+      pI830->operatingDevices = (pI830->MonType2 << 8) | pI830->MonType1;
       pI830->specifiedMonitor = TRUE;
+   } else if (I830IsPrimary(pScrn)) {
+      /* Choose a default set of outputs to use based on what we've detected. */
+      if (i830GetLVDSInfoFromBIOS(pScrn)) {
+	 pI830->MonType2 |= PIPE_LFP;
+      }
+
+      for (i=0; i<pI830->num_outputs; i++) {
+	 if (pI830->output[i].MonInfo == NULL)
+	    continue;
+
+	 switch (pI830->output[i].type) {
+	 case I830_OUTPUT_ANALOG:
+	 case I830_OUTPUT_DVO:
+	    pI830->MonType1 |= PIPE_CRT;
+	    break;
+	 case I830_OUTPUT_LVDS:
+	    pI830->MonType2 |= PIPE_LFP;
+	    break;
+	 case I830_OUTPUT_SDVO:
+	    /* XXX DVO */
+	    break;
+	 case I830_OUTPUT_UNUSED:
+	    break;
+	 }
+      }
+
+      if (pI830->MonType1 != PIPE_NONE)
+	 pI830->pipe = 0;
+      else
+	 pI830->pipe = 1;
+      pI830->operatingDevices = (pI830->MonType2 << 8) | pI830->MonType1;
+   } else {
+      I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
+      pI830->operatingDevices = pI8301->operatingDevices;
+      pI830->pipe = !pI8301->pipe;
+      pI830->MonType1 = pI8301->MonType1;
+      pI830->MonType2 = pI8301->MonType2;
    }
 
    if (xf86ReturnOptValBool(pI830->Options, OPTION_CLONE, FALSE)) {
@@ -2955,58 +2660,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
       }
    }
 
-   /* Save old configuration of detected devices */
-   pI830->savedDevices = GetDisplayDevices(pScrn);
-
-   if (I830IsPrimary(pScrn)) {
-      pI830->pipe = pI830->origPipe = GetBIOSPipe(pScrn);
-
-      /* Override */
-      if (pI830->fixedPipe != -1) {
-         if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone) {
-            pI830->pipe = pI830->fixedPipe; 
-            xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-	        "Fixed Pipe setting primary to pipe %s.\n", 
-                	pI830->fixedPipe ? "B" : "A");
-         }
-      }
-      
-      /* If the monitors aren't setup, read from the current config */
-      if (pI830->MonType1 == PIPE_NONE && pI830->MonType2 == PIPE_NONE) {
-         pI830->MonType1 = pI830->savedDevices & 0xff;
-         pI830->MonType2 = (pI830->savedDevices & 0xff00) >> 8;
-      } else {
-         /* Here, we've switched pipes from our primary */
-         if (pI830->MonType1 == PIPE_NONE && pI830->pipe == 0)
-            pI830->pipe = 1;
-         if (pI830->MonType2 == PIPE_NONE && pI830->pipe == 1)
-            pI830->pipe = 0;
-      }
-   
-      pI830->operatingDevices = (pI830->MonType2 << 8) | pI830->MonType1;
-
-      if (!xf86IsEntityShared(pScrn->entityList[0]) && !pI830->Clone) {
-	  /* If we're not dual head or clone, turn off the second head,
-          * if monitorlayout is also specified. */
-
-         if (pI830->pipe == 0)
-            pI830->operatingDevices = pI830->MonType1;
-         else
-            pI830->operatingDevices = pI830->MonType2 << 8;
-      }
-
-      if (pI830->pipe != pI830->origPipe)
-         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-	     "Primary Pipe has been switched from original pipe (%s to %s)\n",
-             pI830->origPipe ? "B" : "A", pI830->pipe ? "B" : "A");
-   } else {
-      I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
-      pI830->operatingDevices = pI8301->operatingDevices;
-      pI830->pipe = !pI8301->pipe;
-      pI830->MonType1 = pI8301->MonType1;
-      pI830->MonType2 = pI8301->MonType2;
-   }
-
    /* Buggy BIOS 3066 is known to cause this, so turn this off */
    if (pI830->bios_version == 3066) {
       pI830->displayInfo = FALSE;
@@ -3025,27 +2678,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
    xf86DrvMsg(pScrn->scrnIndex, from, "Display Info: %s.\n",
 	      pI830->displayInfo ? "enabled" : "disabled");
 
-   if (!I830DetectDisplayDevice(pScrn)) {
-      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		 "Couldn't detect display devices.\n");
-      PreInitCleanup(pScrn);
-      return FALSE;
-   }
-
-   if (I830IsPrimary(pScrn)) {
-      if (!SetDisplayDevices(pScrn, pI830->operatingDevices)) {
-         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- 		 "Failed to switch to monitor configuration (0x%x)\n",
-                 pI830->operatingDevices);
-         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		 "Please check the devices specified in your MonitorLayout\n");
-         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		 "is configured correctly.\n");
-         PreInitCleanup(pScrn);
-         return FALSE;
-      }
-   }
-
    PrintDisplayDeviceInfo(pScrn);
 
    if (xf86IsEntityShared(pScrn->entityList[0])) {
@@ -4718,35 +4350,12 @@ I830BIOSLeaveVT(int scrnIndex, int flags
 
    ResetState(pScrn, TRUE);
 
-   if (I830IsPrimary(pScrn)) {
-      if (!SetDisplayDevices(pScrn, pI830->savedDevices)) {
-         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		 "Failed to switch back to original display devices (0x%x)\n",
-		 pI830->savedDevices);
-      } else {
-         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		 "Successfully set original devices\n");
-      }
-   }
-
    RestoreHWState(pScrn);
    RestoreBIOSMemSize(pScrn);
    if (I830IsPrimary(pScrn))
       I830UnbindAGPMemory(pScrn);
    if (pI830->AccelInfoRec)
       pI830->AccelInfoRec->NeedToSync = FALSE;
-
-   /* DO IT AGAIN! AS IT SEEMS THAT SOME LFPs FLICKER OTHERWISE */
-   if (I830IsPrimary(pScrn)) {
-      if (!SetDisplayDevices(pScrn, pI830->savedDevices)) {
-         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		 "Failed to switch back to original display devices (0x%x) (2)\n",
-		 pI830->savedDevices);
-      } else {
-         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		 "Successfully set original devices (2)\n");
-      }
-   }
 }
 
 static Bool
@@ -4952,13 +4561,6 @@ I830BIOSEnterVT(int scrnIndex, int flags
 		"Re-POSTing via int10 failed, trying to continue.\n");
          }
       }
-
-      /* Finally, re-setup the display devices */
-      if (!SetDisplayDevices(pScrn, pI830->operatingDevices)) {
-         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- 		 "Failed to switch to configured display devices\n");
-         return FALSE;
-      }
    }
 
    /* Setup for device monitoring status */
@@ -5534,6 +5136,7 @@ I830CheckDevicesTimer(OsTimerPtr timer, 
             pI830->cursorOn = on;
          }
 
+#if 0 /* Disable -- I'll need to look at this whole function later. */
          /* double check the display devices are what's configured and try
           * not to do it twice because of dual heads with the code above */
          if (!SetDisplayDevices(pScrn, temp)) {
@@ -5552,6 +5155,7 @@ I830CheckDevicesTimer(OsTimerPtr timer, 
                }
             }
          }
+#endif
 
          pI8301->monitorSwitch = temp;
 	 pI8301->operatingDevices = temp;
diff-tree b20b466aaed54708ae9e4676623c8c394a6f00d5 (from d960c3ca1512a58a53b5c24702cb5c97124817ee)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Apr 3 14:28:55 2006 -0700

    Remove the now-unused displaySize and pipeDisplaySize.

diff --git a/src/i830.h b/src/i830.h
index a6cd040..d96e5aa 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -397,14 +397,12 @@ typedef struct _I830Rec {
    /* These are indexed by the display types */
    Bool displayAttached[NumDisplayTypes];
    Bool displayPresent[NumDisplayTypes];
-   BoxRec displaySize[NumDisplayTypes];
 
    /* [0] is Pipe A, [1] is Pipe B. */
    int availablePipes;
    int pipeDevices[MAX_DISPLAY_PIPES];
    /* [0] is display plane A, [1] is display plane B. */
    Bool pipeEnabled[MAX_DISPLAY_PIPES];
-   BoxRec pipeDisplaySize[MAX_DISPLAY_PIPES];
    int planeEnabled[MAX_DISPLAY_PIPES];
 
    /* Driver phase/state information */
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 813b20e..06f14d7 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1106,54 +1106,6 @@ PrintDisplayDeviceInfo(ScrnInfoPtr pScrn
 	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		    "No active displays on Pipe %c.\n", PIPE_NAME(n));
       }
-
-      if (pI830->pipeDisplaySize[n].x2 != 0) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		    "Lowest common panel size for pipe %c is %d x %d\n",
-		    PIPE_NAME(n), pI830->pipeDisplaySize[n].x2,
-		    pI830->pipeDisplaySize[n].y2);
-      } else if (pI830->pipeEnabled[n] && pipe & ~PIPE_CRT_ACTIVE) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		    "No display size information available for pipe %c.\n",
-		    PIPE_NAME(n));
-      }
-   }
-}
-
-static void
-GetPipeSizes(ScrnInfoPtr pScrn)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   int pipe, n;
-   DisplayType i;
-
-   DPRINTF(PFX, "GetPipeSizes\n");
-
-
-   for (n = 0; n < pI830->availablePipes; n++) {
-      pipe = (pI830->operatingDevices >> PIPE_SHIFT(n)) & PIPE_ACTIVE_MASK;
-      pI830->pipeDisplaySize[n].x1 = pI830->pipeDisplaySize[n].y1 = 0;
-      pI830->pipeDisplaySize[n].x2 = pI830->pipeDisplaySize[n].y2 = 4096;
-      for (i = 0; i < NumKnownDisplayTypes; i++) {
-         if (pipe & (1 << i) & PIPE_SIZED_DISP_MASK) {
-	    if (pI830->displaySize[i].x2 != 0) {
-	       xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		          "Size of device %s is %d x %d\n",
-		          displayDevices[i],
-		          pI830->displaySize[i].x2,
-		          pI830->displaySize[i].y2);
-	       if (pI830->displaySize[i].x2 < pI830->pipeDisplaySize[n].x2)
-	          pI830->pipeDisplaySize[n].x2 = pI830->displaySize[i].x2;
-	       if (pI830->displaySize[i].y2 < pI830->pipeDisplaySize[n].y2)
-	          pI830->pipeDisplaySize[n].y2 = pI830->displaySize[i].y2;
-	    }
-         }
-      }
-
-      if (pI830->pipeDisplaySize[n].x2 == 4096)
-         pI830->pipeDisplaySize[n].x2 = 0;
-      if (pI830->pipeDisplaySize[n].y2 == 4096)
-         pI830->pipeDisplaySize[n].y2 = 0;
    }
 }
 
@@ -1172,16 +1124,15 @@ I830DetectDisplayDevice(ScrnInfoPtr pScr
 		  "\t\t Option \"DisplayInfo\" \"FALSE\"\n"
 		  "\t      to the Device section of your XF86Config file.\n");
       for (i = 0; i < NumKnownDisplayTypes; i++) {
+	 int unusedx, unusedy;
          if (GetDisplayInfo(pScrn, 1 << i, &pI830->displayAttached[i],
 			 &pI830->displayPresent[i],
-			 &pI830->displaySize[i].x2,
-			 &pI830->displaySize[i].y2)) {
+			 &unusedx, &unusedy)) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		    "Display Info: %s: attached: %s, present: %s, size: "
+		    "Display Info: %s: attached: %s, present: %s: "
 		    "(%d,%d)\n", displayDevices[i],
 		    BOOLTOSTRING(pI830->displayAttached[i]),
-		    BOOLTOSTRING(pI830->displayPresent[i]),
-		    pI830->displaySize[i].x2, pI830->displaySize[i].y2);
+		    BOOLTOSTRING(pI830->displayPresent[i]));
          }
       }
    }
@@ -1195,8 +1146,6 @@ I830DetectDisplayDevice(ScrnInfoPtr pScr
 	 pI830->pipeEnabled[n] = FALSE;
    }
 
-   GetPipeSizes(pScrn);
-
    return TRUE;
 }
 
@@ -4946,32 +4895,6 @@ I830DetectMonitorChange(ScrnInfoPtr pScr
 #endif /* 0 */
 }
 
-Bool
-I830CheckModeSupport(ScrnInfoPtr pScrn, int x, int y, int mode)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   Bool ret = TRUE;
-
-   if (pI830->Clone) {
-      if (pI830->pipeDisplaySize[0].x2 != 0) {
-	 if (x > pI830->pipeDisplaySize[0].x2 ||
-             y > pI830->pipeDisplaySize[0].y2) {
-	 	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Bad Clone Mode removing\n");
-		return FALSE;
-         }
-      }
-      if (pI830->pipeDisplaySize[1].x2 != 0) {
-	 if (x > pI830->pipeDisplaySize[1].x2 ||
-             y > pI830->pipeDisplaySize[1].y2) {
-	 	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Bad Clone Mode removing\n");
-		return FALSE;
-         }
-      }
-   }
-
-   return ret;
-}
-		
 /*
  * This gets called when gaining control of the VT, and from ScreenInit().
  */
diff-tree d960c3ca1512a58a53b5c24702cb5c97124817ee (from 4e3a4827007d624aa3da1a9f5a299837bd601a33)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Apr 3 14:12:29 2006 -0700

    Remove more BIOS modesetting stuff.

diff --git a/src/i830.h b/src/i830.h
index ea3d9e6..a6cd040 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -570,10 +570,6 @@ extern void I830ReadAllRegisters(I830Ptr
 extern void I830ChangeFrontbuffer(ScrnInfoPtr pScrn,int buffer);
 extern Bool I830IsPrimary(ScrnInfoPtr pScrn);
 
-extern DisplayModePtr I830GetModePool(ScrnInfoPtr pScrn, vbeInfoPtr pVbe,
-					VbeInfoBlock *vbe);
-extern void I830SetModeParameters(ScrnInfoPtr pScrn, vbeInfoPtr pVbe);
-extern void I830UnsetModeParameters(ScrnInfoPtr pScrn, vbeInfoPtr pVbe);
 extern void I830PrintModes(ScrnInfoPtr pScrn);
 extern int I830GetBestRefresh(ScrnInfoPtr pScrn, int refresh);
 extern Bool I830CheckModeSupport(ScrnInfoPtr pScrn, int x, int y, int mode);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index fccef4a..813b20e 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -614,42 +614,6 @@ I830GetBestRefresh(ScrnInfoPtr pScrn, in
    return i;
 }
 
-#if 0
-static int
-GetLFPCompMode(ScrnInfoPtr pScrn)
-{
-   vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
-
-   DPRINTF(PFX, "GetLFPCompMode\n");
-
-   pVbe->pInt10->num = 0x10;
-   pVbe->pInt10->ax = 0x5f61;
-   pVbe->pInt10->bx = 0x100;
-
-   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
-   if (Check5fStatus(pScrn, 0x5f61, pVbe->pInt10->ax))
-      return pVbe->pInt10->cx & 0xffff;
-   else
-      return -1;
-}
-
-static Bool
-SetLFPCompMode(ScrnInfoPtr pScrn, int compMode)
-{
-   vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
-
-   DPRINTF(PFX, "SetLFPCompMode: compMode %d\n", compMode);
-
-   pVbe->pInt10->num = 0x10;
-   pVbe->pInt10->ax = 0x5f61;
-   pVbe->pInt10->bx = 0;
-   pVbe->pInt10->cx = compMode;
-
-   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
-   return Check5fStatus(pScrn, 0x5f61, pVbe->pInt10->ax);
-}
-#endif
-
 static int
 GetDisplayDevices(ScrnInfoPtr pScrn)
 {
@@ -4839,6 +4803,8 @@ I830BIOSLeaveVT(int scrnIndex, int flags
 static Bool
 I830DetectMonitorChange(ScrnInfoPtr pScrn)
 {
+   return FALSE;
+#if 0 /* Disabled until we rewrite this natively */
    I830Ptr pI830 = I830PTR(pScrn);
    pointer pDDCModule = NULL;
    DisplayModePtr p, pMon;
@@ -4977,6 +4943,7 @@ I830DetectMonitorChange(ScrnInfoPtr pScr
    }
 
    return TRUE;
+#endif /* 0 */
 }
 
 Bool
diff --git a/src/i830_modes.c b/src/i830_modes.c
index a992bb6..617d1e6 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -40,675 +40,10 @@
 
 #include "xf86.h"
 #include "xf86_ansic.h"
-#include "vbe.h"
-#include "vbeModes.h"
 #include "i830.h"
 
-#include <math.h>
-
-#define rint(x) floor(x)
-
-#define MARGIN_PERCENT    1.8   /* % of active vertical image                */
-#define CELL_GRAN         8.0   /* assumed character cell granularity        */
-#define MIN_PORCH         1     /* minimum front porch                       */
-#define V_SYNC_RQD        3     /* width of vsync in lines                   */
-#define H_SYNC_PERCENT    8.0   /* width of hsync as % of total line         */
-#define MIN_VSYNC_PLUS_BP 550.0 /* min time of vsync + back porch (microsec) */
-#define M                 600.0 /* blanking formula gradient                 */
-#define C                 40.0  /* blanking formula offset                   */
-#define K                 128.0 /* blanking formula scaling factor           */
-#define J                 20.0  /* blanking formula scaling factor           */
-
-/* C' and M' are part of the Blanking Duty Cycle computation */
-
-#define C_PRIME           (((C - J) * K/256.0) + J)
-#define M_PRIME           (K/256.0 * M)
-
 extern const int i830refreshes[];
 
-static DisplayModePtr
-I830GetGTF (int h_pixels, int v_lines, float freq,
-                    int interlaced, int margins)
-{
-    float h_pixels_rnd;
-    float v_lines_rnd;
-    float v_field_rate_rqd;
-    float top_margin;
-    float bottom_margin;
-    float interlace;
-    float h_period_est;
-    float vsync_plus_bp;
-    float v_back_porch;
-    float total_v_lines;
-    float v_field_rate_est;
-    float h_period;
-    float v_field_rate;
-    float v_frame_rate;
-    float left_margin;
-    float right_margin;
-    float total_active_pixels;
-    float ideal_duty_cycle;
-    float h_blank;
-    float total_pixels;
-    float pixel_freq;
-    float h_freq;
-
-    float h_sync;
-    float h_front_porch;
-    float v_odd_front_porch_lines;
-    char modename[20];
-    DisplayModePtr m;
-
-    m = xnfcalloc(sizeof(DisplayModeRec), 1);
-    
-    
-    /*  1. In order to give correct results, the number of horizontal
-     *  pixels requested is first processed to ensure that it is divisible
-     *  by the character size, by rounding it to the nearest character
-     *  cell boundary:
-     *
-     *  [H PIXELS RND] = ((ROUND([H PIXELS]/[CELL GRAN RND],0))*[CELLGRAN RND])
-     */
-    
-    h_pixels_rnd = rint((float) h_pixels / CELL_GRAN) * CELL_GRAN;
-    
-    
-    /*  2. If interlace is requested, the number of vertical lines assumed
-     *  by the calculation must be halved, as the computation calculates
-     *  the number of vertical lines per field. In either case, the
-     *  number of lines is rounded to the nearest integer.
-     *   
-     *  [V LINES RND] = IF([INT RQD?]="y", ROUND([V LINES]/2,0),
-     *                                     ROUND([V LINES],0))
-     */
-
-    v_lines_rnd = interlaced ?
-            rint((float) v_lines) / 2.0 :
-            rint((float) v_lines);
-    
-    /*  3. Find the frame rate required:
-     *
-     *  [V FIELD RATE RQD] = IF([INT RQD?]="y", [I/P FREQ RQD]*2,
-     *                                          [I/P FREQ RQD])
-     */
-
-    v_field_rate_rqd = interlaced ? (freq * 2.0) : (freq);
-
-    /*  4. Find number of lines in Top margin:
-     *
-     *  [TOP MARGIN (LINES)] = IF([MARGINS RQD?]="Y",
-     *          ROUND(([MARGIN%]/100*[V LINES RND]),0),
-     *          0)
-     */
-
-    top_margin = margins ? rint(MARGIN_PERCENT / 100.0 * v_lines_rnd) : (0.0);
-
-    /*  5. Find number of lines in Bottom margin:
-     *
-     *  [BOT MARGIN (LINES)] = IF([MARGINS RQD?]="Y",
-     *          ROUND(([MARGIN%]/100*[V LINES RND]),0),
-     *          0)
-     */
-
-    bottom_margin = margins ? rint(MARGIN_PERCENT/100.0 * v_lines_rnd) : (0.0);
-
-    /*  6. If interlace is required, then set variable [INTERLACE]=0.5:
-     *   
-     *  [INTERLACE]=(IF([INT RQD?]="y",0.5,0))
-     */
-
-    interlace = interlaced ? 0.5 : 0.0;
-
-    /*  7. Estimate the Horizontal period
-     *
-     *  [H PERIOD EST] = ((1/[V FIELD RATE RQD]) - [MIN VSYNC+BP]/1000000) /
-     *                    ([V LINES RND] + (2*[TOP MARGIN (LINES)]) +
-     *                     [MIN PORCH RND]+[INTERLACE]) * 1000000
-     */
-
-    h_period_est = (((1.0/v_field_rate_rqd) - (MIN_VSYNC_PLUS_BP/1000000.0))
-                    / (v_lines_rnd + (2*top_margin) + MIN_PORCH + interlace)
-                    * 1000000.0);
-
-    /*  8. Find the number of lines in V sync + back porch:
-     *
-     *  [V SYNC+BP] = ROUND(([MIN VSYNC+BP]/[H PERIOD EST]),0)
-     */
-
-    vsync_plus_bp = rint(MIN_VSYNC_PLUS_BP/h_period_est);
-
-    /*  9. Find the number of lines in V back porch alone:
-     *
-     *  [V BACK PORCH] = [V SYNC+BP] - [V SYNC RND]
-     *
-     *  XXX is "[V SYNC RND]" a typo? should be [V SYNC RQD]?
-     */
-    
-    v_back_porch = vsync_plus_bp - V_SYNC_RQD;
-    
-    /*  10. Find the total number of lines in Vertical field period:
-     *
-     *  [TOTAL V LINES] = [V LINES RND] + [TOP MARGIN (LINES)] +
-     *                    [BOT MARGIN (LINES)] + [V SYNC+BP] + [INTERLACE] +
-     *                    [MIN PORCH RND]
-     */
-
-    total_v_lines = v_lines_rnd + top_margin + bottom_margin + vsync_plus_bp +
-        interlace + MIN_PORCH;
-    
-    /*  11. Estimate the Vertical field frequency:
-     *
-     *  [V FIELD RATE EST] = 1 / [H PERIOD EST] / [TOTAL V LINES] * 1000000
-     */
-
-    v_field_rate_est = 1.0 / h_period_est / total_v_lines * 1000000.0;
-    
-    /*  12. Find the actual horizontal period:
-     *
-     *  [H PERIOD] = [H PERIOD EST] / ([V FIELD RATE RQD] / [V FIELD RATE EST])
-     */
-
-    h_period = h_period_est / (v_field_rate_rqd / v_field_rate_est);
-    
-    /*  13. Find the actual Vertical field frequency:
-     *
-     *  [V FIELD RATE] = 1 / [H PERIOD] / [TOTAL V LINES] * 1000000
-     */
-
-    v_field_rate = 1.0 / h_period / total_v_lines * 1000000.0;
-
-    /*  14. Find the Vertical frame frequency:
-     *
-     *  [V FRAME RATE] = (IF([INT RQD?]="y", [V FIELD RATE]/2, [V FIELD RATE]))
-     */
-
-    v_frame_rate = interlaced ? v_field_rate / 2.0 : v_field_rate;
-
-    /*  15. Find number of pixels in left margin:
-     *
-     *  [LEFT MARGIN (PIXELS)] = (IF( [MARGINS RQD?]="Y",
-     *          (ROUND( ([H PIXELS RND] * [MARGIN%] / 100 /
-     *                   [CELL GRAN RND]),0)) * [CELL GRAN RND],
-     *          0))
-     */
-
-    left_margin = margins ?
-        rint(h_pixels_rnd * MARGIN_PERCENT / 100.0 / CELL_GRAN) * CELL_GRAN :
-        0.0;
-    
-    /*  16. Find number of pixels in right margin:
-     *
-     *  [RIGHT MARGIN (PIXELS)] = (IF( [MARGINS RQD?]="Y",
-     *          (ROUND( ([H PIXELS RND] * [MARGIN%] / 100 /
-     *                   [CELL GRAN RND]),0)) * [CELL GRAN RND],
-     *          0))
-     */
-    
-    right_margin = margins ?
-        rint(h_pixels_rnd * MARGIN_PERCENT / 100.0 / CELL_GRAN) * CELL_GRAN :
-        0.0;
-    
-    /*  17. Find total number of active pixels in image and left and right
-     *  margins:
-     *
-     *  [TOTAL ACTIVE PIXELS] = [H PIXELS RND] + [LEFT MARGIN (PIXELS)] +
-     *                          [RIGHT MARGIN (PIXELS)]
-     */
-
-    total_active_pixels = h_pixels_rnd + left_margin + right_margin;
-    
-    /*  18. Find the ideal blanking duty cycle from the blanking duty cycle
-     *  equation:
-     *
-     *  [IDEAL DUTY CYCLE] = [C'] - ([M']*[H PERIOD]/1000)
-     */
-
-    ideal_duty_cycle = C_PRIME - (M_PRIME * h_period / 1000.0);
-    
-    /*  19. Find the number of pixels in the blanking time to the nearest
-     *  double character cell:
-     *
-     *  [H BLANK (PIXELS)] = (ROUND(([TOTAL ACTIVE PIXELS] *
-     *                               [IDEAL DUTY CYCLE] /
-     *                               (100-[IDEAL DUTY CYCLE]) /
-     *                               (2*[CELL GRAN RND])), 0))
-     *                       * (2*[CELL GRAN RND])
-     */
-
-    h_blank = rint(total_active_pixels *
-                   ideal_duty_cycle /
-                   (100.0 - ideal_duty_cycle) /
-                   (2.0 * CELL_GRAN)) * (2.0 * CELL_GRAN);
-    
-    /*  20. Find total number of pixels:
-     *
-     *  [TOTAL PIXELS] = [TOTAL ACTIVE PIXELS] + [H BLANK (PIXELS)]
-     */
-
-    total_pixels = total_active_pixels + h_blank;
-    
-    /*  21. Find pixel clock frequency:
-     *
-     *  [PIXEL FREQ] = [TOTAL PIXELS] / [H PERIOD]
-     */
-    
-    pixel_freq = total_pixels / h_period;
-    
-    /*  22. Find horizontal frequency:
-     *
-     *  [H FREQ] = 1000 / [H PERIOD]
-     */
-
-    h_freq = 1000.0 / h_period;
-    
-
-    /* Stage 1 computations are now complete; I should really pass
-       the results to another function and do the Stage 2
-       computations, but I only need a few more values so I'll just
-       append the computations here for now */
-
-    
-
-    /*  17. Find the number of pixels in the horizontal sync period:
-     *
-     *  [H SYNC (PIXELS)] =(ROUND(([H SYNC%] / 100 * [TOTAL PIXELS] /
-     *                             [CELL GRAN RND]),0))*[CELL GRAN RND]
-     */
-
-    h_sync = rint(H_SYNC_PERCENT/100.0 * total_pixels / CELL_GRAN) * CELL_GRAN;
-
-    /*  18. Find the number of pixels in the horizontal front porch period:
-     *
-     *  [H FRONT PORCH (PIXELS)] = ([H BLANK (PIXELS)]/2)-[H SYNC (PIXELS)]
-     */
-
-    h_front_porch = (h_blank / 2.0) - h_sync;
-
-    /*  36. Find the number of lines in the odd front porch period:
-     *
-     *  [V ODD FRONT PORCH(LINES)]=([MIN PORCH RND]+[INTERLACE])
-     */
-    
-    v_odd_front_porch_lines = MIN_PORCH + interlace;
-    
-    /* finally, pack the results in the DisplayMode struct */
-    
-    m->HDisplay  = (int) (h_pixels_rnd);
-    m->HSyncStart = (int) (h_pixels_rnd + h_front_porch);
-    m->HSyncEnd = (int) (h_pixels_rnd + h_front_porch + h_sync);
-    m->HTotal = (int) (total_pixels);
-
-    m->VDisplay  = (int) (v_lines_rnd);
-    m->VSyncStart = (int) (v_lines_rnd + v_odd_front_porch_lines);
-    m->VSyncEnd = (int) (int) (v_lines_rnd + v_odd_front_porch_lines + V_SYNC_RQD);
-    m->VTotal = (int) (total_v_lines);
-
-    m->Clock   = (int)(pixel_freq * 1000);
-    m->SynthClock   = m->Clock;
-    m->HSync = h_freq;
-    m->VRefresh = v_frame_rate /* freq */;
-
-    snprintf(modename, sizeof(modename), "%dx%d", m->HDisplay,m->VDisplay);
-    m->name = xnfstrdup(modename);
-
-    return (m);
-}
-
-static DisplayModePtr
-CheckMode(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, VbeInfoBlock *vbe, int id,
-	  int flags)
-{
-    CARD16 major, minor;
-    VbeModeInfoBlock *mode;
-    DisplayModePtr p = NULL, pMode = NULL;
-    VbeModeInfoData *data;
-    Bool modeOK = FALSE;
-    ModeStatus status = MODE_OK;
-
-    major = (unsigned)(vbe->VESAVersion >> 8);
-    minor = vbe->VESAVersion & 0xff;
-
-    if ((mode = VBEGetModeInfo(pVbe, id)) == NULL)
-	return NULL;
-
-    /* Does the mode match the depth/bpp? */
-    /* Some BIOS's set BitsPerPixel to 15 instead of 16 for 15/16 */
-    if (VBE_MODE_USABLE(mode, flags) &&
-	((pScrn->bitsPerPixel == 1 && !VBE_MODE_COLOR(mode)) ||
-	 (mode->BitsPerPixel > 8 &&
-	  (mode->RedMaskSize + mode->GreenMaskSize +
-	   mode->BlueMaskSize) == pScrn->depth &&
-	  mode->BitsPerPixel == pScrn->bitsPerPixel) ||
-	 (mode->BitsPerPixel == 15 && pScrn->depth == 15) ||
-	 (mode->BitsPerPixel <= 8 &&
-	  mode->BitsPerPixel == pScrn->bitsPerPixel))) {
-	modeOK = TRUE;
-	xf86ErrorFVerb(DEBUG_VERB, "*");
-    }
-
-    if (mode->XResolution && mode->YResolution &&
-	!I830CheckModeSupport(pScrn, mode->XResolution, mode->YResolution, id)) 
-	modeOK = FALSE;
-
-
-    /*
-     * Check if there's a valid monitor mode that this one can be matched
-     * up with from the 'specified' modes list.
-     */
-    if (modeOK) {
-	for (p = pScrn->monitor->Modes; p != NULL; p = p->next) {
-	    if ((p->type != 0) ||
-		(p->HDisplay != mode->XResolution) ||
-		(p->VDisplay != mode->YResolution) ||
-		(p->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2)))
-		continue;
-	    status = xf86CheckModeForMonitor(p, pScrn->monitor);
-	    if (status == MODE_OK) {
-		modeOK = TRUE;
-		break;
-	    }
-	}
-	if (p) {
-    		pMode = xnfcalloc(sizeof(DisplayModeRec), 1);
-		memcpy((char*)pMode,(char*)p,sizeof(DisplayModeRec));
-    		pMode->name = xnfstrdup(p->name);
-	}
-    } 
-
-    /*
-     * Now, check if there's a valid monitor mode that this one can be matched
-     * up with from the default modes list. i.e. VESA modes in xf86DefModes.c
-     */
-    if (modeOK && !pMode) {
-	int refresh = 0, calcrefresh = 0;
-	DisplayModePtr newMode = NULL;
-
-	for (p = pScrn->monitor->Modes; p != NULL; p = p->next) {
-	    calcrefresh = (int)(((double)(p->Clock * 1000) /
-                       (double)(p->HTotal * p->VTotal)) * 100);
-	    if ((p->type != M_T_DEFAULT) ||
-		(p->HDisplay != mode->XResolution) ||
-		(p->VDisplay != mode->YResolution) ||
-		(p->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2)))
-		continue;
-	    status = xf86CheckModeForMonitor(p, pScrn->monitor);
-	    if (status == MODE_OK) {
-	    	if (calcrefresh > refresh) {
-			refresh = calcrefresh;
-			newMode = p;
-		}
-		modeOK = TRUE;
-	    }
-	}
-	if (newMode) {
-    		pMode = xnfcalloc(sizeof(DisplayModeRec), 1);
-		memcpy((char*)pMode,(char*)newMode,sizeof(DisplayModeRec));
-    		pMode->name = xnfstrdup(newMode->name);
-	}
-    } 
-
-    /*
-     * Check if there's a valid monitor mode that this one can be matched
-     * up with.  The actual matching is done later.
-     */
-    if (modeOK && !pMode) {
-	float vrefresh = 0.0f;
-	int i;
-
-	for (i=0;i<pScrn->monitor->nVrefresh;i++) {
-
-  	    for (vrefresh = pScrn->monitor->vrefresh[i].hi; 
-		 vrefresh >= pScrn->monitor->vrefresh[i].lo; vrefresh -= 1.0f) {
-
-	        if (vrefresh != (float)0.0f) {
-                    float best_vrefresh;
-                    int int_vrefresh;
- 
-                    /* Find the best refresh for the Intel chipsets */
-                    int_vrefresh = I830GetBestRefresh(pScrn, (int)vrefresh);
-		    best_vrefresh = (float)i830refreshes[int_vrefresh];
-
-                    /* Now, grab the best mode from the available refresh */
-		    pMode = I830GetGTF(mode->XResolution, mode->YResolution, 
-							best_vrefresh, 0, 0);
-
-    	            pMode->type = M_T_BUILTIN;
-
-	            status = xf86CheckModeForMonitor(pMode, pScrn->monitor);
-	            if (status == MODE_OK) {
-			if (major >= 3) {
-			    if (pMode->Clock * 1000 <= mode->MaxPixelClock)
-				modeOK = TRUE;
-			    else
-				modeOK = FALSE;
-			} else
-			    modeOK = TRUE;
-	            } else
-	    	        modeOK = FALSE;
-  	            pMode->status = status;
-	        } else { 
-	            modeOK = FALSE;
-	        }
-	        if (modeOK) break;
-            }
-	    if (modeOK) break;
-        }
-    }
-
-    xf86ErrorFVerb(DEBUG_VERB,
-	    "Mode: %x (%dx%d)\n", id, mode->XResolution, mode->YResolution);
-    xf86ErrorFVerb(DEBUG_VERB,
-	    "	ModeAttributes: 0x%x\n", mode->ModeAttributes);
-    xf86ErrorFVerb(DEBUG_VERB,
-	    "	WinAAttributes: 0x%x\n", mode->WinAAttributes);
-    xf86ErrorFVerb(DEBUG_VERB,
-	    "	WinBAttributes: 0x%x\n", mode->WinBAttributes);
-    xf86ErrorFVerb(DEBUG_VERB,
-	    "	WinGranularity: %d\n", mode->WinGranularity);
-    xf86ErrorFVerb(DEBUG_VERB,
-	    "	WinSize: %d\n", mode->WinSize);
-    xf86ErrorFVerb(DEBUG_VERB,
-	    "	WinASegment: 0x%x\n", mode->WinASegment);
-    xf86ErrorFVerb(DEBUG_VERB,
-	    "	WinBSegment: 0x%x\n", mode->WinBSegment);
-    xf86ErrorFVerb(DEBUG_VERB,
-	    "	WinFuncPtr: 0x%lx\n", mode->WinFuncPtr);
-    xf86ErrorFVerb(DEBUG_VERB,
-	    "	BytesPerScanline: %d\n", mode->BytesPerScanline);
-    xf86ErrorFVerb(DEBUG_VERB,
-	    "	XResolution: %d\n", mode->XResolution);
-    xf86ErrorFVerb(DEBUG_VERB,
-	    "	YResolution: %d\n", mode->YResolution);
-    xf86ErrorFVerb(DEBUG_VERB,
-	    "	XCharSize: %d\n", mode->XCharSize);
-    xf86ErrorFVerb(DEBUG_VERB,
-           "	YCharSize: %d\n", mode->YCharSize);
-    xf86ErrorFVerb(DEBUG_VERB,
-	    "	NumberOfPlanes: %d\n", mode->NumberOfPlanes);
-    xf86ErrorFVerb(DEBUG_VERB,
-	    "	BitsPerPixel: %d\n", mode->BitsPerPixel);
-    xf86ErrorFVerb(DEBUG_VERB,
-	    "	NumberOfBanks: %d\n", mode->NumberOfBanks);
-    xf86ErrorFVerb(DEBUG_VERB,
-	    "	MemoryModel: %d\n", mode->MemoryModel);
-    xf86ErrorFVerb(DEBUG_VERB,
-	    "	BankSize: %d\n", mode->BankSize);
-    xf86ErrorFVerb(DEBUG_VERB,
-	    "	NumberOfImages: %d\n", mode->NumberOfImages);
-    xf86ErrorFVerb(DEBUG_VERB,
-	    "	RedMaskSize: %d\n", mode->RedMaskSize);
-    xf86ErrorFVerb(DEBUG_VERB,
-	    "	RedFieldPosition: %d\n", mode->RedFieldPosition);
-    xf86ErrorFVerb(DEBUG_VERB,
-	    "	GreenMaskSize: %d\n", mode->GreenMaskSize);
-    xf86ErrorFVerb(DEBUG_VERB,
-	    "	GreenFieldPosition: %d\n", mode->GreenFieldPosition);
-    xf86ErrorFVerb(DEBUG_VERB,
-	    "	BlueMaskSize: %d\n", mode->BlueMaskSize);
-    xf86ErrorFVerb(DEBUG_VERB,
-	    "	BlueFieldPosition: %d\n", mode->BlueFieldPosition);
-    xf86ErrorFVerb(DEBUG_VERB,
-	    "	RsvdMaskSize: %d\n", mode->RsvdMaskSize);
-    xf86ErrorFVerb(DEBUG_VERB,
-	    "	RsvdFieldPosition: %d\n", mode->RsvdFieldPosition);
-    xf86ErrorFVerb(DEBUG_VERB,
-	    "	DirectColorModeInfo: %d\n", mode->DirectColorModeInfo);
-    if (major >= 2) {
-	xf86ErrorFVerb(DEBUG_VERB,
-		"	PhysBasePtr: 0x%lx\n", mode->PhysBasePtr);
-	if (major >= 3) {
-	    xf86ErrorFVerb(DEBUG_VERB,
-		    "	LinBytesPerScanLine: %d\n", mode->LinBytesPerScanLine);
-	    xf86ErrorFVerb(DEBUG_VERB,
-		    "	BnkNumberOfImagePages: %d\n", mode->BnkNumberOfImagePages);
-	    xf86ErrorFVerb(DEBUG_VERB,
-		    "	LinNumberOfImagePages: %d\n", mode->LinNumberOfImagePages);
-	    xf86ErrorFVerb(DEBUG_VERB,
-		    "	LinRedMaskSize: %d\n", mode->LinRedMaskSize);
-	    xf86ErrorFVerb(DEBUG_VERB,
-		    "	LinRedFieldPosition: %d\n", mode->LinRedFieldPosition);
-	    xf86ErrorFVerb(DEBUG_VERB,
-		    "	LinGreenMaskSize: %d\n", mode->LinGreenMaskSize);
-	    xf86ErrorFVerb(DEBUG_VERB,
-		    "	LinGreenFieldPosition: %d\n", mode->LinGreenFieldPosition);
-	    xf86ErrorFVerb(DEBUG_VERB,
-		    "	LinBlueMaskSize: %d\n", mode->LinBlueMaskSize);
-	    xf86ErrorFVerb(DEBUG_VERB,
-		    "	LinBlueFieldPosition: %d\n", mode->LinBlueFieldPosition);
-	    xf86ErrorFVerb(DEBUG_VERB,
-		    "	LinRsvdMaskSize: %d\n", mode->LinRsvdMaskSize);
-	    xf86ErrorFVerb(DEBUG_VERB,
-		    "	LinRsvdFieldPosition: %d\n", mode->LinRsvdFieldPosition);
-	    xf86ErrorFVerb(DEBUG_VERB,
-		    "	MaxPixelClock: %ld\n", mode->MaxPixelClock);
-	}
-    }
-
-    if (!modeOK) {
-	VBEFreeModeInfo(mode);
-	if (pMode)
-	    xfree(pMode);
-	return NULL;
-    }
-
-    pMode->status = MODE_OK;
-    pMode->type = M_T_BUILTIN;
-
-    /* for adjust frame */
-    pMode->HDisplay = mode->XResolution;
-    pMode->VDisplay = mode->YResolution;
-
-    data = xnfcalloc(sizeof(VbeModeInfoData), 1);
-    data->mode = id;
-    data->data = mode;
-    pMode->PrivSize = sizeof(VbeModeInfoData);
-    pMode->Private = (INT32*)data;
-    pMode->next = NULL;
-    return pMode;
-}
-
-/*
- * Check the available BIOS modes, and extract those that match the
- * requirements into the modePool.  Note: modePool is a NULL-terminated
- * list.
- */
-
-DisplayModePtr
-I830GetModePool(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, VbeInfoBlock *vbe)
-{
-   DisplayModePtr pMode, p = NULL, modePool = NULL;
-   int i = 0;
-
-   for (i = 0; i < 0x7F; i++) {
-      if ((pMode = CheckMode(pScrn, pVbe, vbe, i, V_MODETYPE_VGA)) != NULL) {
-         ModeStatus status = MODE_OK;
-
-		/* Check the mode against a specified virtual size (if any) */
-		if (pScrn->display->virtualX > 0 &&
-		    pMode->HDisplay > pScrn->display->virtualX) {
-		    status = MODE_VIRTUAL_X;
-		}
-		if (pScrn->display->virtualY > 0 &&
-		    pMode->VDisplay > pScrn->display->virtualY) {
-		    status = MODE_VIRTUAL_Y;
-		}
-		if (status != MODE_OK) {
-		     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-				"Not using mode \"%dx%d\" (%s)\n",
-				pMode->HDisplay, pMode->VDisplay,
-				xf86ModeStatusToString(status));
-		} else {
-		    if (p == NULL) {
-			modePool = pMode;
-		    } else {
-			p->next = pMode;
-		    }
-		    pMode->prev = NULL;
-		    p = pMode;
-		}
-	    }
-	}
-    return modePool;
-}
-
-/*
- * Go through the monitor modes and selecting the best set of
- * parameters for each BIOS mode.  Note: This is only supported in
- * VBE version 3.0 or later.
- */
-void
-I830SetModeParameters(ScrnInfoPtr pScrn, vbeInfoPtr pVbe)
-{
-    DisplayModePtr pMode;
-    VbeModeInfoData *data;
-
-    pMode = pScrn->modes;
-    do {
-	int clock;
-
-	data = (VbeModeInfoData*)pMode->Private;
-	data->block = xcalloc(sizeof(VbeCRTCInfoBlock), 1);
-	data->block->HorizontalTotal = pMode->HTotal;
-	data->block->HorizontalSyncStart = pMode->HSyncStart;
-	data->block->HorizontalSyncEnd = pMode->HSyncEnd;
-	data->block->VerticalTotal = pMode->VTotal;
-	data->block->VerticalSyncStart = pMode->VSyncStart;
-	data->block->VerticalSyncEnd = pMode->VSyncEnd;
-	data->block->Flags = ((pMode->Flags & V_NHSYNC) ? CRTC_NHSYNC : 0) |
-				 ((pMode->Flags & V_NVSYNC) ? CRTC_NVSYNC : 0);
-	data->block->PixelClock = pMode->Clock * 1000;
-	/* XXX May not have this. */
-	clock = VBEGetPixelClock(pVbe, data->mode, data->block->PixelClock);
-	if (clock)
-	    data->block->PixelClock = clock;
-#ifdef DEBUG
-	ErrorF("Setting clock %.2fMHz, closest is %.2fMHz\n",
-		(double)data->block->PixelClock / 1000000.0, 
-		(double)clock / 1000000.0);
-#endif
-	data->mode |= (1 << 11);
-	if (pMode->VRefresh != 0) {
-	    data->block->RefreshRate = pMode->VRefresh * 100;
-	} else {
-	    data->block->RefreshRate = (int)(((double)(data->block->PixelClock)/
-                       (double)(pMode->HTotal * pMode->VTotal)) * 100);
-	}
-	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		       "Attempting to use %2.2fHz refresh for mode \"%s\" (%x)\n",
-		       (float)(((double)(data->block->PixelClock) / (double)(pMode->HTotal * pMode->VTotal))), pMode->name, data->mode);
-#ifdef DEBUG
-	ErrorF("Video Modeline: ID: 0x%x Name: %s %i %i %i %i - "
-	       "  %i %i %i %i %.2f MHz Refresh: %.2f Hz\n",
-	       data->mode, pMode->name, pMode->HDisplay, pMode->HSyncStart,
-	       pMode->HSyncEnd, pMode->HTotal, pMode->VDisplay,
-	       pMode->VSyncStart,pMode->VSyncEnd,pMode->VTotal,
-	       (double)data->block->PixelClock/1000000.0,
-	       (double)data->block->RefreshRate/100);
-#endif
-	pMode = pMode->next;
-    } while (pMode != pScrn->modes);
-}
-
 void
 I830PrintModes(ScrnInfoPtr scrp)
 {
diff-tree 4e3a4827007d624aa3da1a9f5a299837bd601a33 (from 8d27f8246ed5a73f7a78043e128b47be784186c0)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Fri Mar 31 14:05:46 2006 -0800

    autodetect LVDS dither. Fix 16bpp depth selection

diff --git a/src/i830.h b/src/i830.h
index 019c1d3..ea3d9e6 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -444,6 +444,8 @@ typedef struct _I830Rec {
    int panel_fixed_vsyncoff;
    int panel_fixed_vsyncwidth;
 
+   Bool panel_wants_dither;
+
    unsigned char *VBIOS;
 
    CARD32 saveDSPACNTR;
diff --git a/src/i830_bios.c b/src/i830_bios.c
index eb810fc..4264803 100644
--- a/src/i830_bios.c
+++ b/src/i830_bios.c
@@ -135,6 +135,8 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScr
 	case 40:
 	    lvds1 = (struct lvds_bdb_1 *)(pI830->VBIOS + start);
 	    panel_type = lvds1->panel_type;
+	    if (lvds1->caps & LVDS_CAP_DITHER)
+		pI830->panel_wants_dither = TRUE;
 	    break;
 	case 41:
 	    if (panel_type == -1)
diff --git a/src/i830_display.c b/src/i830_display.c
index 224e82c..ebe0aa3 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -407,9 +407,9 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	break;
     case 16:
 	if (pScrn->depth == 15)
-	    dspcntr |= DISPPLANE_16BPP;
-	else
 	    dspcntr |= DISPPLANE_15_16BPP;
+	else
+	    dspcntr |= DISPPLANE_16BPP;
 	break;
     case 32:
 	dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
@@ -508,13 +508,18 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	OUTREG(PIPEBSRC, pipesrc);
 
 	if (outputs & PIPE_LCD_ACTIVE) {
+	    CARD32  pfit_control;
+	    
 	    /* Enable automatic panel scaling so that non-native modes fill the
 	     * screen.
 	     */
 	    /* XXX: Allow (auto-?) enabling of 8-to-6 dithering */
-	    OUTREG(PFIT_CONTROL, PFIT_ENABLE |
-		   VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
-		   VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR);
+	    pfit_control = (PFIT_ENABLE |
+			    VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
+			    VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR);
+	    if (pI830->panel_wants_dither)
+		pfit_control |= PANEL_8TO6_DITHER_ENABLE;
+	    OUTREG(PFIT_CONTROL, pfit_control);
 	}
 
 	/* Then, turn the pipe on first */
diff-tree 8d27f8246ed5a73f7a78043e128b47be784186c0 (from e45581cd073b23a62719f20783d617bd35316fec)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Tue Mar 28 13:49:41 2006 -0800

    Clean up (and I believe fix a couple of bugs in) the divisor selection code.

diff --git a/src/i830_display.c b/src/i830_display.c
index f9f596f..224e82c 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -7,9 +7,10 @@
 #include "i830.h"
 #include "i830_display.h"
 
+/** Returns the pixel clock for the given refclk and divisors. */
 static int i830_clock(int refclk, int m1, int m2, int n, int p1, int p2)
 {
-    return (refclk * (5 * (m1 + 2) + (m2 + 2)) / (n + 2)) / (p1 * p2);
+    return refclk * (5 * m1 + m2) / n / (p1 * p2);
 }
 
 static void
@@ -23,6 +24,13 @@ i830PrintPll(char *prefix, int refclk, i
 	   m1, m2, n, p1, p2);
 }
 
+/**
+ * Returns whether the given set of divisors are valid for a given refclk with
+ * the given outputs.
+ *
+ * The equation for these divisors would be:
+ * clk = refclk * (5 * m1 + m2) / n / (p1 * p2)
+ */
 static Bool
 i830PllIsValid(ScrnInfoPtr pScrn, int outputs, int refclk, int m1, int m2,
 	       int n, int p1, int p2)
@@ -62,9 +70,9 @@ i830PllIsValid(ScrnInfoPtr pScrn, int ou
 	}
     }
 
-    p = p1 + p2;
-    m = 5 * (m1 + 2) + (m2 + 2);
-    vco = refclk * m / (n + 2);
+    p = p1 * p2;
+    m = 5 * m1 + m2;
+    vco = refclk * m / n;
     dotclock = i830_clock(refclk, m1, m2, n, p1, p2);
 
     if (p1 < 1 || p1 > 8)
@@ -79,7 +87,7 @@ i830PllIsValid(ScrnInfoPtr pScrn, int ou
 	return FALSE;
     if (m < min_m || m > max_m)
 	return FALSE;
-    if (n + 2 < min_n || n + 2 > max_n)	/*XXX: Is the +2 right? */
+    if (n < min_n || n > max_n)
 	return FALSE;
     if (vco < 1400000 || vco > 2800000)
 	return FALSE;
@@ -167,6 +175,11 @@ i830ReadAndReportPLL(ScrnInfoPtr pScrn)
 }
 #endif
 
+/**
+ * Returns a set of divisors for the desired target clock with the given refclk,
+ * or FALSE.  Divisor values are the actual divisors for
+ * clk = refclk * (5 * m1 + m2) / n / (p1 * p2)
+ */
 static Bool
 i830FindBestPLL(ScrnInfoPtr pScrn, int outputs, int target, int refclk,
 		int *outm1, int *outm2, int *outn, int *outp1, int *outp2)
@@ -202,7 +215,7 @@ i830FindBestPLL(ScrnInfoPtr pScrn, int o
 
     for (m1 = min_m1; m1 <= max_m1; m1++) {
 	for (m2 = min_m2; m2 < max_m2; m2++) {
-	    for (n = 1; n <= 6; n++) {
+	    for (n = 3; n <= 8; n++) {
 		for (p1 = 1; p1 <= 8; p1++) {
 		    int clock, this_err;
 
@@ -330,7 +343,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	dpll |= PLL_REF_INPUT_DREFCLK;
     dpll |= SDV0_DEFAULT_MULTIPLIER;
 
-    fp = (n << 16) | (m1 << 8) | m2;
+    fp = ((n - 2) << 16) | ((m1 - 2) << 8) | (m2 - 2);
 
     htot = (pMode->CrtcHDisplay - 1) | ((pMode->CrtcHTotal - 1) << 16);
     hblank = (pMode->CrtcHBlankStart - 1) | ((pMode->CrtcHBlankEnd - 1) << 16);
diff-tree e45581cd073b23a62719f20783d617bd35316fec (from 33977d23830b5f9bb7d9e2e9c141f91cb127b7de)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Tue Mar 28 13:40:32 2006 -0800

    Fill in clock information from VBT table, so that a good clock value gets
    requested for choosing divisors.

diff --git a/src/i830.h b/src/i830.h
index 3fba456..019c1d3 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -434,6 +434,7 @@ typedef struct _I830Rec {
    int PanelXRes, PanelYRes;
 
    /* The BIOS's fixed timings for the LVDS */
+   int panel_fixed_clock;
    int panel_fixed_hactive;
    int panel_fixed_hblank;
    int panel_fixed_hsyncoff;
diff --git a/src/i830_bios.c b/src/i830_bios.c
index 47c39ec..eb810fc 100644
--- a/src/i830_bios.c
+++ b/src/i830_bios.c
@@ -157,6 +157,7 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScr
 	    /* Since lvds_bdb_2_fp_edid_dtd is just an EDID detailed timing
 	     * block, pull the contents out using EDID macros.
 	     */
+	    pI830->panel_fixed_clock = _PIXEL_CLOCK(timing_ptr) / 1000;
 	    pI830->panel_fixed_hactive = _H_ACTIVE(timing_ptr);
 	    pI830->panel_fixed_hblank = _H_BLANK(timing_ptr);
 	    pI830->panel_fixed_hsyncoff = _H_SYNC_OFF(timing_ptr);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index c6b5970..fccef4a 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2043,7 +2043,7 @@ i830SetModeToPanelParameters(ScrnInfoPtr
    pMode->VTotal     = pI830->panel_fixed_vactive;
    pMode->VSyncStart = pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff;
    pMode->VSyncEnd   = pMode->VSyncStart + pI830->panel_fixed_vsyncwidth;
-   pMode->Clock      = 0; /* XXX */
+   pMode->Clock      = pI830->panel_fixed_clock;
 }
 
 /**
diff-tree 33977d23830b5f9bb7d9e2e9c141f91cb127b7de (from febdfa967dbe1df487db71ba5f677ef37450bf7a)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Mar 27 18:50:53 2006 -0800

    Port code from radeon driver for panel mode validation, which will hopefully get
    the right mode chosen on the VAIO.  Untested.

diff --git a/src/i830.h b/src/i830.h
index d41da79..3fba456 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -430,6 +430,9 @@ typedef struct _I830Rec {
    struct _I830OutputRec output[MAX_OUTPUTS];
    I830SDVOPtr sdvo;
 
+   /* Panel size pulled from the BIOS */
+   int PanelXRes, PanelYRes;
+
    /* The BIOS's fixed timings for the LVDS */
    int panel_fixed_hactive;
    int panel_fixed_hblank;
diff --git a/src/i830_bios.c b/src/i830_bios.c
index 31e89b5..47c39ec 100644
--- a/src/i830_bios.c
+++ b/src/i830_bios.c
@@ -102,6 +102,7 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScr
     struct bdb_header *bdb;
     int vbt_off, bdb_off, bdb_block_off, block_size;
     int panel_type = -1;
+    Bool found_panel_info = FALSE;
 
     if (!i830GetBIOS(pScrn))
 	return FALSE;
@@ -147,9 +148,11 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScr
 	    timing_ptr = pI830->VBIOS + bdb_off +
 	        lvds2->panels[panel_type].fp_edid_dtd_offset;
 
+	    pI830->PanelXRes = fpparam->x_res;
+	    pI830->PanelYRes = fpparam->y_res;
 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		       "Found panel of size %dx%d in BIOS VBT tables\n",
-		       fpparam->x_res, fpparam->y_res);
+		       pI830->PanelXRes, pI830->PanelYRes);
 
 	    /* Since lvds_bdb_2_fp_edid_dtd is just an EDID detailed timing
 	     * block, pull the contents out using EDID macros.
@@ -163,8 +166,11 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScr
 	    pI830->panel_fixed_vblank = _V_BLANK(timing_ptr);
 	    pI830->panel_fixed_vsyncoff = _V_SYNC_OFF(timing_ptr);
 	    pI830->panel_fixed_vsyncwidth = _V_SYNC_WIDTH(timing_ptr);
+
+	    found_panel_info = TRUE;
 	    break;
 	}
     }
-    return TRUE;
+
+    return found_panel_info;
 }
diff --git a/src/i830_driver.c b/src/i830_driver.c
index ca46ec9..c6b5970 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -183,6 +183,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "i830.h"
 #include "i830_display.h"
 #include "i830_debug.h"
+#include "i830_bios.h"
 
 #ifdef XF86DRI
 #include "dri.h"
@@ -591,100 +592,6 @@ struct panelid {
 	char reserved[14];
 };
 
-static void
-I830InterpretPanelID(int scrnIndex, unsigned char *tmp)
-{
-    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
-    struct panelid *block = (struct panelid *)tmp;
-
-#define PANEL_DEFAULT_HZ 60
-
-   xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-	 "PanelID returned panel resolution : %dx%d\n", 
-						block->hsize, block->vsize);
-
-   /* If we get bogus values from this, don't accept it */
-   if (block->hsize == 0 || block->vsize == 0) {
-   	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-	 "Bad Panel resolution - ignoring panelID\n");
-	
-	return;
-   }
-
-   /* If we have monitor timings then don't overwrite them */
-   if (pScrn->monitor->nHsync > 0 &&
-	pScrn->monitor->nVrefresh > 0)
-	return;
-
-   /* With panels, we're always assuming a refresh of 60Hz */
-
-   pScrn->monitor->nHsync = 1;
-   pScrn->monitor->nVrefresh = 1;
-
-   /* Give a little tolerance for the selected panel */
-   pScrn->monitor->hsync[0].lo = (float)((PANEL_DEFAULT_HZ/1.05)*block->vsize)/1000;
-   pScrn->monitor->hsync[0].hi = (float)((PANEL_DEFAULT_HZ/0.95)*block->vsize)/1000;
-   pScrn->monitor->vrefresh[0].lo = (float)PANEL_DEFAULT_HZ;
-   pScrn->monitor->vrefresh[0].hi = (float)PANEL_DEFAULT_HZ;
-}
-
-/* This should probably go into the VBE layer */
-static unsigned char *
-vbeReadPanelID(vbeInfoPtr pVbe)
-{
-    int RealOff = pVbe->real_mode_base;
-    pointer page = pVbe->memory;
-    unsigned char *tmp = NULL;
-    int screen = pVbe->pInt10->scrnIndex;
-
-    pVbe->pInt10->ax = 0x4F11;
-    pVbe->pInt10->bx = 0x01;
-    pVbe->pInt10->cx = 0;
-    pVbe->pInt10->dx = 0;
-    pVbe->pInt10->es = SEG_ADDR(RealOff);
-    pVbe->pInt10->di = SEG_OFF(RealOff);
-    pVbe->pInt10->num = 0x10;
-
-    xf86ExecX86int10(pVbe->pInt10);
-
-    if ((pVbe->pInt10->ax & 0xff) != 0x4f) {
-        xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID invalid\n");
-	goto error;
-    }
-    switch (pVbe->pInt10->ax & 0xff00) {
-    case 0x0:
-	xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID read successfully\n");
-  	tmp = (unsigned char *)xnfalloc(32); 
-  	memcpy(tmp,page,32); 
-	break;
-    case 0x100:
-	xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID read failed\n");	
-	break;
-    default:
-	xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID unknown failure %i\n",
-		       pVbe->pInt10->ax & 0xff00);
-	break;
-    }
-
- error:
-    return tmp;
-}
-
-static void
-vbeDoPanelID(vbeInfoPtr pVbe)
-{
-    unsigned char *PanelID_data;
-    
-    if (!pVbe) return;
-
-    PanelID_data = vbeReadPanelID(pVbe);
-
-    if (!PanelID_data) 
-	return;
-    
-    I830InterpretPanelID(pVbe->pInt10->scrnIndex, PanelID_data);
-}
-
 int 
 I830GetBestRefresh(ScrnInfoPtr pScrn, int refresh)
 {
@@ -2125,6 +2032,166 @@ I830IsPrimary(ScrnInfoPtr pScrn)
    return TRUE;
 }
 
+static void
+i830SetModeToPanelParameters(ScrnInfoPtr pScrn, DisplayModePtr pMode)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+
+   pMode->HTotal     = pI830->panel_fixed_hactive;
+   pMode->HSyncStart = pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff;
+   pMode->HSyncEnd   = pMode->HSyncStart + pI830->panel_fixed_hsyncwidth;
+   pMode->VTotal     = pI830->panel_fixed_vactive;
+   pMode->VSyncStart = pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff;
+   pMode->VSyncEnd   = pMode->VSyncStart + pI830->panel_fixed_vsyncwidth;
+   pMode->Clock      = 0; /* XXX */
+}
+
+/**
+ * This function returns a default mode for flat panels using the timing
+ * information provided by the BIOS.
+ */
+static DisplayModePtr i830FPNativeMode(ScrnInfoPtr pScrn)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+   DisplayModePtr  new;
+   char            stmp[32];
+
+   if (pI830->PanelXRes == 0 || pI830->PanelYRes == 0)
+      return NULL;
+
+   /* Add native panel size */
+   new             = xnfcalloc(1, sizeof (DisplayModeRec));
+   sprintf(stmp, "%dx%d", pI830->PanelXRes, pI830->PanelYRes);
+   new->name       = xnfalloc(strlen(stmp) + 1);
+   strcpy(new->name, stmp);
+   new->HDisplay   = pI830->PanelXRes;
+   new->VDisplay   = pI830->PanelYRes;
+   i830SetModeToPanelParameters(pScrn, new);
+   new->type       = M_T_USERDEF;
+
+   pScrn->virtualX = MAX(pScrn->virtualX, pI830->PanelXRes);
+   pScrn->virtualY = MAX(pScrn->virtualY, pI830->PanelYRes);
+   pScrn->display->virtualX = pScrn->virtualX;
+   pScrn->display->virtualY = pScrn->virtualY;
+
+   xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+	      "No valid mode specified, force to native mode\n");
+
+   return new;
+}
+
+/* FP mode validation routine for using panel fitting.
+ */
+static int i830ValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+   DisplayModePtr  last       = NULL;
+   DisplayModePtr  new        = NULL;
+   DisplayModePtr  first      = NULL;
+   DisplayModePtr  p, tmp;
+   int             count      = 0;
+   int             i, width, height;
+
+   pScrn->virtualX = pScrn->display->virtualX;
+   pScrn->virtualY = pScrn->display->virtualY;
+
+   /* We have a flat panel connected to the primary display, and we
+    * don't have any DDC info.
+    */
+   for (i = 0; ppModeName[i] != NULL; i++) {
+
+      if (sscanf(ppModeName[i], "%dx%d", &width, &height) != 2)
+	 continue;
+
+      /* Note: We allow all non-standard modes as long as they do not
+       * exceed the native resolution of the panel.  Since these modes
+       * need the internal RMX unit in the video chips (and there is
+       * only one per card), this will only apply to the primary head.
+       */
+      if (width < 320 || width > pI830->PanelXRes ||
+	 height < 200 || height > pI830->PanelYRes) {
+	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Mode %s is out of range.\n",
+		    ppModeName[i]);
+	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		    "Valid modes must be between 320x200-%dx%d\n",
+		    pI830->PanelXRes, pI830->PanelYRes);
+	 continue;
+      }
+
+      new             = xnfcalloc(1, sizeof(DisplayModeRec));
+      new->name       = xnfalloc(strlen(ppModeName[i]) + 1);
+      strcpy(new->name, ppModeName[i]);
+      new->HDisplay   = width;
+      new->VDisplay   = height;
+      new->type      |= M_T_USERDEF;
+
+      i830SetModeToPanelParameters(pScrn, new);
+
+      new->next       = NULL;
+      new->prev       = last;
+
+      if (last)
+	 last->next = new;
+      last = new;
+      if (!first)
+	 first = new;
+
+      pScrn->display->virtualX = pScrn->virtualX = MAX(pScrn->virtualX, width);
+      pScrn->display->virtualY = pScrn->virtualY = MAX(pScrn->virtualY, height);
+      count++;
+      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		 "Valid mode using panel fitting: %s\n", new->name);
+   }
+
+   /* If all else fails, add the native mode */
+   if (!count) {
+      first = last = i830FPNativeMode(pScrn);
+      if (first)
+	 count = 1;
+   }
+
+   /* add in all default vesa modes smaller than panel size, used for randr*/
+   for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) {
+      if ((p->HDisplay <= pI830->PanelXRes) && (p->VDisplay <= pI830->PanelYRes)) {
+	 tmp = first;
+	 while (tmp) {
+	    if ((p->HDisplay == tmp->HDisplay) && (p->VDisplay == tmp->VDisplay)) break;
+	       tmp = tmp->next;
+	 }
+	 if (!tmp) {
+	    new             = xnfcalloc(1, sizeof(DisplayModeRec));
+	    new->name       = xnfalloc(strlen(p->name) + 1);
+	    strcpy(new->name, p->name);
+	    new->HDisplay   = p->HDisplay;
+	    new->VDisplay   = p->VDisplay;
+	    i830SetModeToPanelParameters(pScrn, new);
+	    new->type      |= M_T_DEFAULT;
+
+	    new->next       = NULL;
+	    new->prev       = last;
+
+	    if (last)
+	       last->next = new;
+	    last = new;
+	    if (!first)
+	       first = new;
+	 }
+      }
+   }
+
+   /* Close the doubly-linked mode list, if we found any usable modes */
+   if (last) {
+      last->next   = first;
+      first->prev  = last;
+      pScrn->modes = first;
+   }
+
+   xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+	      "Total number of valid FP mode(s) found: %d\n", count);
+
+   return count;
+}
+
 static Bool
 I830BIOSPreInit(ScrnInfoPtr pScrn, int flags)
 {
@@ -3151,12 +3218,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
 
    SetPipeAccess(pScrn);
 
-   /* Check we have an LFP connected, before trying to
-    * read PanelID information. */
-   if ( (pI830->pipe == 1 && pI830->operatingDevices & (PIPE_LFP << 8)) ||
-        (pI830->pipe == 0 && pI830->operatingDevices & PIPE_LFP) )
-   	vbeDoPanelID(pI830->pVbe);
-
    /* XXX Move this to a header. */
 #define VIDEO_BIOS_SCRATCH 0x18
 
@@ -3202,28 +3263,36 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
     clockRanges->interlaceAllowed = TRUE;	/* XXX check this */
     clockRanges->doubleScanAllowed = FALSE;	/* XXX check this */
 
-   /*
-    * XXX DDC information: There's code in xf86ValidateModes
-    * (VBEValidateModes) to set monitor defaults based on DDC information
-    * where available.  If we need something that does better than this,
-    * there's code in vesa/vesa.c.
-    */
-
-   /* XXX minPitch, minHeight are random numbers. */
-   n = xf86ValidateModes(pScrn,
-			 pScrn->monitor->Modes, /* availModes */
-			 pScrn->display->modes, /* modeNames */
-			 clockRanges, /* clockRanges */
-			 NULL, /* linePitches */
-			 256, /* minPitch */
-			 MAX_DISPLAY_PITCH, /* maxPitch */
-			 64, /* pitchInc */
-			 pScrn->bitsPerPixel, /* minHeight */
-			 MAX_DISPLAY_HEIGHT, /* maxHeight */
-			 pScrn->display->virtualX, /* virtualX */
-			 pScrn->display->virtualY, /* virtualY */
-			 pI830->FbMapSize, /* apertureSize */
-			 LOOKUP_BEST_REFRESH /* strategy */);
+   if ( (pI830->pipe == 1 && pI830->operatingDevices & (PIPE_LFP << 8)) ||
+        (pI830->pipe == 0 && pI830->operatingDevices & PIPE_LFP) ) {
+      /* If we're outputting to an LFP, use the LFP mode validation that will
+       * rely on the scaler so that we can display any mode smaller than or the
+       * same size as the panel.
+       */
+      if (!i830GetLVDSInfoFromBIOS(pScrn)) {
+	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		    "Unable to locate panel information in BIOS VBT tables\n");
+         PreInitCleanup(pScrn);
+	 return FALSE;
+      }
+      n = i830ValidateFPModes(pScrn, pScrn->display->modes);
+   } else {
+      /* XXX minPitch, minHeight are random numbers. */
+      n = xf86ValidateModes(pScrn,
+			    pScrn->monitor->Modes, /* availModes */
+			    pScrn->display->modes, /* modeNames */
+			    clockRanges, /* clockRanges */
+			    NULL, /* linePitches */
+			    256, /* minPitch */
+			    MAX_DISPLAY_PITCH, /* maxPitch */
+			    64, /* pitchInc */
+			    pScrn->bitsPerPixel, /* minHeight */
+			    MAX_DISPLAY_HEIGHT, /* maxHeight */
+			    pScrn->display->virtualX, /* virtualX */
+			    pScrn->display->virtualY, /* virtualY */
+			    pI830->FbMapSize, /* apertureSize */
+			    LOOKUP_BEST_REFRESH /* strategy */);
+   }
    if (n <= 0) {
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
       PreInitCleanup(pScrn);
diff-tree febdfa967dbe1df487db71ba5f677ef37450bf7a (from f86892c9163473a683ab591adeb9fb1c0be2ef99)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Mar 27 15:19:52 2006 -0800

    Remove some VBE DDC code that I believe is OBE.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 48d2d0a..ca46ec9 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2136,13 +2136,10 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
    I830EntPtr pI830Ent = NULL;					
    int mem, memsize;
    int flags24;
-   int defmon = 0;
    int i, n;
-   int DDCclock = 0;
    char *s;
-   DisplayModePtr p, pMon;
    ClockRangePtr clockRanges;
-   pointer pDDCModule = NULL, pVBEModule = NULL;
+   pointer pVBEModule = NULL;
    Bool enable;
    const char *chipname;
    unsigned int ver;
@@ -2559,6 +2556,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
    for (i = 0; i < MAX_OUTPUTS; i++) {
      if (pI830->output[i].MonInfo) {
        pScrn->monitor->DDC = pI830->output[i].MonInfo;
+       xf86SetDDCproperties(pScrn, pI830->output[i].MonInfo);
        break;
      }
    }
@@ -3159,16 +3157,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
         (pI830->pipe == 0 && pI830->operatingDevices & PIPE_LFP) )
    	vbeDoPanelID(pI830->pVbe);
 
-   pDDCModule = xf86LoadSubModule(pScrn, "ddc");
-
-   pI830->vesa->monitor = vbeDoEDID(pI830->pVbe, pDDCModule);
-
-   if ((pScrn->monitor->DDC = pI830->vesa->monitor) != NULL) {
-      xf86PrintEDID(pI830->vesa->monitor);
-      xf86SetDDCproperties(pScrn, pI830->vesa->monitor);
-   }
-   xf86UnloadSubModule(pDDCModule);
-
    /* XXX Move this to a header. */
 #define VIDEO_BIOS_SCRATCH 0x18
 
@@ -3202,34 +3190,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
 	      "Maximum space available for video modes: %d kByte\n", memsize);
 
-   /* By now, we should have had some monitor settings, but if not, we
-    * need to setup some defaults. These are used in common/xf86Modes.c
-    * so we'll use them here for GetModePool, and that's all. 
-    * We unset them after the call, so we can report 'defaults' as being
-    * used through the common layer.
-    */
-#define DEFAULT_HSYNC_LO 28
-#define DEFAULT_HSYNC_HI 33
-#define DEFAULT_VREFRESH_LO 43
-#define DEFAULT_VREFRESH_HI 72
-
-   if (pScrn->monitor->nHsync == 0) {
-      pScrn->monitor->hsync[0].lo = DEFAULT_HSYNC_LO;
-      pScrn->monitor->hsync[0].hi = DEFAULT_HSYNC_HI;
-      pScrn->monitor->nHsync = 1;
-      defmon |= 1;
-   }
-
-   if (pScrn->monitor->nVrefresh == 0) {
-      pScrn->monitor->vrefresh[0].lo = DEFAULT_VREFRESH_LO;
-      pScrn->monitor->vrefresh[0].hi = DEFAULT_VREFRESH_HI;
-      pScrn->monitor->nVrefresh = 1;
-      defmon |= 2;
-   }
-
-   DDCclock = I830UseDDC(pScrn);
-
-#if 1
    /*
      * Setup the ClockRanges, which describe what clock ranges are available,
      * and what sort of modes they can be used for.
@@ -3241,7 +3201,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
     clockRanges->clockIndex = -1;		/* programmable */
     clockRanges->interlaceAllowed = TRUE;	/* XXX check this */
     clockRanges->doubleScanAllowed = FALSE;	/* XXX check this */
-#endif
 
    /*
     * XXX DDC information: There's code in xf86ValidateModes
@@ -3269,38 +3228,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
       PreInitCleanup(pScrn);
       return FALSE;
-   }
-
-   /* Only use this if we've got DDC available */
-   if (DDCclock > 0) {
-      p = pScrn->modes;
-      if (p == NULL)
-         return FALSE;
-      do {
-         int Clock = 100000000; /* incredible value */
-
-	 if (p->status == MODE_OK) {
-            for (pMon = pScrn->monitor->Modes; pMon != NULL; pMon = pMon->next) {
-               if ((pMon->HDisplay != p->HDisplay) ||
-                   (pMon->VDisplay != p->VDisplay) ||
-                   (pMon->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2)))
-                   continue;
-
-               /* Find lowest supported Clock for this resolution */
-               if (Clock > pMon->Clock)
-                  Clock = pMon->Clock;
-            } 
-
-            if (Clock != 100000000 && DDCclock < 2550 && Clock / 1000.0 > DDCclock) {
-               ErrorF("(%s,%s) mode clock %gMHz exceeds DDC maximum %dMHz\n",
-		   p->name, pScrn->monitor->id,
-		   Clock/1000.0, DDCclock);
-               p->status = MODE_BAD;
-            } 
- 	 }
-         p = p->next;
-      } while (p != NULL && p != pScrn->modes);
-   }
+   }	
 
    xf86PruneDriverModes(pScrn);
 
diff-tree f86892c9163473a683ab591adeb9fb1c0be2ef99 (from f6a3243f40074aee471ec1cda2cc8e5f05116284)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Fri Mar 24 16:00:30 2006 -0800

    Make auto panel fitting work by pulling LVDS timing EDID info out of the static
    BIOS table, and always using that.

diff --git a/src/i830.h b/src/i830.h
index fb86887..d41da79 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -430,6 +430,16 @@ typedef struct _I830Rec {
    struct _I830OutputRec output[MAX_OUTPUTS];
    I830SDVOPtr sdvo;
 
+   /* The BIOS's fixed timings for the LVDS */
+   int panel_fixed_hactive;
+   int panel_fixed_hblank;
+   int panel_fixed_hsyncoff;
+   int panel_fixed_hsyncwidth;
+   int panel_fixed_vactive;
+   int panel_fixed_vblank;
+   int panel_fixed_vsyncoff;
+   int panel_fixed_vsyncwidth;
+
    unsigned char *VBIOS;
 
    CARD32 saveDSPACNTR;
diff --git a/src/i830_bios.c b/src/i830_bios.c
index cae76c8..31e89b5 100644
--- a/src/i830_bios.c
+++ b/src/i830_bios.c
@@ -28,10 +28,12 @@
 #include "config.h"
 #endif
 
+#define _PARSE_EDID_
 #include "xf86.h"
 #include "xf86_ansic.h"
 #include "i830.h"
 #include "i830_bios.h"
+#include "edid.h"
 
 #define INTEL_BIOS_8(_addr)	(pI830->VBIOS[_addr])
 #define INTEL_BIOS_16(_addr)	(pI830->VBIOS[_addr] | \
@@ -121,7 +123,9 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScr
 	int id;
 	struct lvds_bdb_1 *lvds1;
 	struct lvds_bdb_2 *lvds2;
-	struct lvds_bdb_2_fp_params *lvds2fpparam;
+	struct lvds_bdb_2_fp_params *fpparam;
+	struct lvds_bdb_2_fp_edid_dtd *fptiming;
+	CARD8 *timing_ptr;
 
 	id = INTEL_BIOS_8(start);
 	block_size = INTEL_BIOS_16(start + 1) + 3;
@@ -134,12 +138,31 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScr
 	case 41:
 	    if (panel_type == -1)
 		break;
+
 	    lvds2 = (struct lvds_bdb_2 *)(pI830->VBIOS + start);
-	    lvds2fpparam = (struct lvds_bdb_2_fp_params *)(pI830->VBIOS +
+	    fpparam = (struct lvds_bdb_2_fp_params *)(pI830->VBIOS +
 		bdb_off + lvds2->panels[panel_type].fp_params_offset);
+	    fptiming = (struct lvds_bdb_2_fp_edid_dtd *)(pI830->VBIOS +
+		bdb_off + lvds2->panels[panel_type].fp_edid_dtd_offset);
+	    timing_ptr = pI830->VBIOS + bdb_off +
+	        lvds2->panels[panel_type].fp_edid_dtd_offset;
+
 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		       "Found panel of size %dx%d in BIOS VBT tables\n",
-		       lvds2fpparam->x_res, lvds2fpparam->y_res);
+		       fpparam->x_res, fpparam->y_res);
+
+	    /* Since lvds_bdb_2_fp_edid_dtd is just an EDID detailed timing
+	     * block, pull the contents out using EDID macros.
+	     */
+	    pI830->panel_fixed_hactive = _H_ACTIVE(timing_ptr);
+	    pI830->panel_fixed_hblank = _H_BLANK(timing_ptr);
+	    pI830->panel_fixed_hsyncoff = _H_SYNC_OFF(timing_ptr);
+	    pI830->panel_fixed_hsyncwidth = _H_SYNC_WIDTH(timing_ptr);
+
+	    pI830->panel_fixed_vactive = _V_ACTIVE(timing_ptr);
+	    pI830->panel_fixed_vblank = _V_BLANK(timing_ptr);
+	    pI830->panel_fixed_vsyncoff = _V_SYNC_OFF(timing_ptr);
+	    pI830->panel_fixed_vsyncwidth = _V_SYNC_WIDTH(timing_ptr);
 	    break;
 	}
     }
diff --git a/src/i830_display.c b/src/i830_display.c
index 57038df..f9f596f 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -340,13 +340,37 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     vsync = (pMode->CrtcVSyncStart - 1) | ((pMode->CrtcVSyncEnd - 1) << 16);
     pipesrc = ((pMode->HDisplay - 1) << 16) | (pMode->VDisplay - 1);
     dspsize = ((pMode->VDisplay - 1) << 16) | (pMode->HDisplay - 1);
-    if (outputs & PIPE_LCD_ACTIVE) {
+    if (outputs & PIPE_LCD_ACTIVE && i830GetLVDSInfoFromBIOS(pScrn) &&
+	pI830->panel_fixed_hactive != 0)
+    {
 	/* To enable panel fitting, we need to set the pipe timings to that of
-	 * the screen at its full resolution.  So, pull the timings out of the
-	 * BIOS tables and drop them in here.
+	 * the screen at its full resolution.  So, drop the timings from the
+	 * BIOS VBT tables here.
 	 */
-	i830GetLVDSInfoFromBIOS(pScrn);
+	htot = (pI830->panel_fixed_hactive - 1) |
+		((pI830->panel_fixed_hactive + pI830->panel_fixed_hblank - 1)
+		 << 16);
+	hblank = (pI830->panel_fixed_hactive - 1) |
+		((pI830->panel_fixed_hactive + pI830->panel_fixed_hblank - 1)
+		 << 16);
+	hsync = (pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff - 1) |
+		((pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff +
+		  pI830->panel_fixed_hsyncwidth - 1) << 16);
+
+	vtot = (pI830->panel_fixed_vactive - 1) |
+		((pI830->panel_fixed_vactive + pI830->panel_fixed_vblank - 1)
+		 << 16);
+	vblank = (pI830->panel_fixed_vactive - 1) |
+		((pI830->panel_fixed_vactive + pI830->panel_fixed_vblank - 1)
+		 << 16);
+	vsync = (pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff - 1) |
+		((pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff +
+		  pI830->panel_fixed_vsyncwidth - 1) << 16);
     }
+#if 0
+    ErrorF("htot: 0x%08x, hblank: 0x%08x, hsync: 0x%08x\n", htot, hblank, hsync);
+    ErrorF("vtot: 0x%08x, vblank: 0x%08x, vsync: 0x%08x\n", vtot, vblank, vsync);
+#endif
 
     adpa = INREG(ADPA);
     adpa &= ~(ADPA_HSYNC_ACTIVE_HIGH | ADPA_VSYNC_ACTIVE_HIGH);
@@ -475,9 +499,9 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	     * screen.
 	     */
 	    /* XXX: Allow (auto-?) enabling of 8-to-6 dithering */
-	    OUTREG(PFIT_CONTROL, PFIT_ENABLE /*|
+	    OUTREG(PFIT_CONTROL, PFIT_ENABLE |
 		   VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
-		   VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR*/);
+		   VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR);
 	}
 
 	/* Then, turn the pipe on first */
diff-tree f6a3243f40074aee471ec1cda2cc8e5f05116284 (from 64756e215016730b5cc2e174f08d47c0288c0ba4)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Fri Mar 24 13:49:10 2006 -0800

    Add more VBT reading, so we find the panel size.

diff --git a/src/i830_bios.c b/src/i830_bios.c
index a5b7fcd..cae76c8 100644
--- a/src/i830_bios.c
+++ b/src/i830_bios.c
@@ -98,14 +98,16 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScr
     I830Ptr pI830 = I830PTR(pScrn);
     struct vbt_header *vbt;
     struct bdb_header *bdb;
-    int vbt_off, bdb_block_off, block_size;
+    int vbt_off, bdb_off, bdb_block_off, block_size;
+    int panel_type = -1;
 
     if (!i830GetBIOS(pScrn))
 	return FALSE;
 
     vbt_off = INTEL_BIOS_16(0x1a);
     vbt = (struct vbt_header *)(pI830->VBIOS + vbt_off);
-    bdb = (struct bdb_header *)(pI830->VBIOS + vbt_off + vbt->bdb_offset);
+    bdb_off = vbt_off + vbt->bdb_offset;
+    bdb = (struct bdb_header *)(pI830->VBIOS + bdb_off);
 
     if (memcmp(bdb->signature, "BIOS_DATA_BLOCK ", 16) != 0) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Bad BDB signature\n");
@@ -115,12 +117,31 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScr
     for (bdb_block_off = bdb->header_size; bdb_block_off < bdb->bdb_size;
 	 bdb_block_off += block_size)
     {
-	int start = vbt_off + vbt->bdb_offset + bdb_block_off;
+	int start = bdb_off + bdb_block_off;
 	int id;
+	struct lvds_bdb_1 *lvds1;
+	struct lvds_bdb_2 *lvds2;
+	struct lvds_bdb_2_fp_params *lvds2fpparam;
 
 	id = INTEL_BIOS_8(start);
 	block_size = INTEL_BIOS_16(start + 1) + 3;
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found BDB block type %d\n", id);
+	switch (id) {
+	case 40:
+	    lvds1 = (struct lvds_bdb_1 *)(pI830->VBIOS + start);
+	    panel_type = lvds1->panel_type;
+	    break;
+	case 41:
+	    if (panel_type == -1)
+		break;
+	    lvds2 = (struct lvds_bdb_2 *)(pI830->VBIOS + start);
+	    lvds2fpparam = (struct lvds_bdb_2_fp_params *)(pI830->VBIOS +
+		bdb_off + lvds2->panels[panel_type].fp_params_offset);
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		       "Found panel of size %dx%d in BIOS VBT tables\n",
+		       lvds2fpparam->x_res, lvds2fpparam->y_res);
+	    break;
+	}
     }
     return TRUE;
 }
diff --git a/src/i830_bios.h b/src/i830_bios.h
index ed3f182..9bd0db8 100644
--- a/src/i830_bios.h
+++ b/src/i830_bios.h
@@ -26,7 +26,7 @@
  */
 
 struct vbt_header {
-    char signature[20];			/**< Always 'BIOS_DATA_BLOCK' */
+    char signature[20];			/**< Always starts with 'VBT$' */
     CARD16 version;			/**< decimal */
     CARD16 header_size;			/**< in bytes */
     CARD16 vbt_size;			/**< in bytes */
@@ -37,14 +37,83 @@ struct vbt_header {
     CARD32 aim2_offset;			/**< from beginning of VBT */
     CARD32 aim3_offset;			/**< from beginning of VBT */
     CARD32 aim4_offset;			/**< from beginning of VBT */
-};
+} __attribute__((packed));
 
 struct bdb_header {
     char signature[16];			/**< Always 'BIOS_DATA_BLOCK' */
     CARD16 version;			/**< decimal */
     CARD16 header_size;			/**< in bytes */
     CARD16 bdb_size;			/**< in bytes */
-};
+} __attribute__((packed));
+
+#define LVDS_CAP_EDID			(1 << 6)
+#define LVDS_CAP_DITHER			(1 << 5)
+#define LVDS_CAP_PFIT_AUTO_RATIO	(1 << 4)
+#define LVDS_CAP_PFIT_GRAPHICS_MODE	(1 << 3)
+#define LVDS_CAP_PFIT_TEXT_MODE		(1 << 2)
+#define LVDS_CAP_PFIT_GRAPHICS		(1 << 1)
+#define LVDS_CAP_PFIT_TEXT		(1 << 0)
+struct lvds_bdb_1 {
+    CARD8 id;				/**< 40 */
+    CARD16 size;
+    CARD8 panel_type;
+    CARD8 reserved0;
+    CARD16 caps;
+} __attribute__((packed));
+
+struct lvds_bdb_2_fp_params {
+    CARD16 x_res;
+    CARD16 y_res;
+    CARD32 lvds_reg;
+    CARD32 lvds_reg_val;
+    CARD32 pp_on_reg;
+    CARD32 pp_on_reg_val;
+    CARD32 pp_off_reg;
+    CARD32 pp_off_reg_val;
+    CARD32 pp_cycle_reg;
+    CARD32 pp_cycle_reg_val;
+    CARD32 pfit_reg;
+    CARD32 pfit_reg_val;
+    CARD16 terminator;
+} __attribute__((packed));
+
+struct lvds_bdb_2_fp_edid_dtd {
+    CARD16 dclk;		/**< In 10khz */
+    CARD8 hactive;
+    CARD8 hblank;
+    CARD8 high_h;		/**< 7:4 = hactive 11:8, 3:0 = hblank 11:8 */
+    CARD8 vactive;
+    CARD8 vblank;
+    CARD8 high_v;		/**< 7:4 = vactive 11:8, 3:0 = vblank 11:8 */
+    CARD8 hsync_off;
+    CARD8 hsync_pulse_width;
+    CARD8 vsync_off;
+    CARD8 high_hsync_off;	/**< 7:6 = hsync off 9:8 */
+    CARD8 h_image;
+    CARD8 v_image;
+    CARD8 max_hv;
+    CARD8 h_border;
+    CARD8 v_border;
+    CARD8 flags;
+#define FP_EDID_FLAG_VSYNC_POSITIVE	(1 << 2)
+#define FP_EDID_FLAG_HSYNC_POSITIVE	(1 << 1)
+} __attribute__((packed));
+
+struct lvds_bdb_2_entry {
+    CARD16 fp_params_offset;		/**< From beginning of BDB */
+    CARD8 fp_params_size;
+    CARD16 fp_edid_dtd_offset;
+    CARD8 fp_edid_dtd_size;
+    CARD16 fp_edid_pid_offset;
+    CARD8 fp_edid_pid_size;
+} __attribute__((packed));
+
+struct lvds_bdb_2 {
+    CARD8 id;			/**< 41 */
+    CARD16 size;
+    CARD8 table_size;	/* not sure on this one */
+    struct lvds_bdb_2_entry panels[16];
+} __attribute__((packed));
 
 Bool
 i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScrn);
diff-tree 64756e215016730b5cc2e174f08d47c0288c0ba4 (from c2d554be671f5368bd98867b8ecf9428e4560a81)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Fri Mar 24 11:55:01 2006 -0800

    Start interpreting VBT information with the goal of pulling out LVDS timings
    for panel fitting.

diff --git a/src/Makefile.am b/src/Makefile.am
index 37682eb..1b30c65 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -44,6 +44,8 @@ i810_drv_la_SOURCES = \
          i810_video.c \
          i810_wmark.c \
          i830_accel.c \
+         i830_bios.c \
+         i830_bios.h \
          i830_common.h \
          i830_cursor.c \
 	 i830_debug.c \
diff --git a/src/i830.h b/src/i830.h
index eb75f45..fb86887 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -430,6 +430,8 @@ typedef struct _I830Rec {
    struct _I830OutputRec output[MAX_OUTPUTS];
    I830SDVOPtr sdvo;
 
+   unsigned char *VBIOS;
+
    CARD32 saveDSPACNTR;
    CARD32 saveDSPBCNTR;
    CARD32 savePIPEACONF;
diff --git a/src/i830_bios.c b/src/i830_bios.c
new file mode 100644
index 0000000..a5b7fcd
--- /dev/null
+++ b/src/i830_bios.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "xf86_ansic.h"
+#include "i830.h"
+#include "i830_bios.h"
+
+#define INTEL_BIOS_8(_addr)	(pI830->VBIOS[_addr])
+#define INTEL_BIOS_16(_addr)	(pI830->VBIOS[_addr] | \
+				 (pI830->VBIOS[_addr + 1] << 8))
+#define INTEL_BIOS_32(_addr)	(pI830->VBIOS[_addr] | \
+				 (pI830->VBIOS[_addr + 1] << 8) \
+				 (pI830->VBIOS[_addr + 2] << 16) \
+				 (pI830->VBIOS[_addr + 3] << 24))
+
+/* XXX */
+#define INTEL_VBIOS_SIZE (64 * 1024)
+
+/**
+ * Loads the Video BIOS and checks that the VBT exists.
+ *
+ * VBT existence is a sanity check that is relied on by other i830_bios.c code.
+ * Note that it would be better to use a BIOS call to get the VBT, as BIOSes may
+ * feed an updated VBT back through that, compared to what we'll fetch using
+ * this method of groping around in the BIOS data.
+ */
+static Bool
+i830GetBIOS(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    struct vbt_header *vbt;
+    int vbt_off;
+
+    if (pI830->VBIOS != NULL)
+	return TRUE;
+
+    pI830->VBIOS = xalloc(INTEL_VBIOS_SIZE);
+    if (pI830->VBIOS == NULL)
+	return FALSE;
+
+    if (pI830->pVbe != NULL) {
+	memcpy(pI830->VBIOS, (void *)(pI830->pVbe->pInt10->BIOSseg << 4),
+	       INTEL_VBIOS_SIZE);
+    } else {
+	xf86ReadPciBIOS(0, pI830->PciTag, 0, pI830->VBIOS, INTEL_VBIOS_SIZE);
+    }
+
+    vbt_off = INTEL_BIOS_16(0x1a);
+    if (vbt_off >= INTEL_VBIOS_SIZE) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Bad VBT offset: 0x%x\n",
+		   vbt_off);
+	xfree(pI830->VBIOS);
+	return FALSE;
+    }
+
+    vbt = (struct vbt_header *)(pI830->VBIOS + vbt_off);
+
+    if (memcmp(vbt->signature, "$VBT", 4) != 0) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Bad VBT signature\n");
+	xfree(pI830->VBIOS);
+	return FALSE;
+    }
+
+    return TRUE;
+}
+
+Bool
+i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    struct vbt_header *vbt;
+    struct bdb_header *bdb;
+    int vbt_off, bdb_block_off, block_size;
+
+    if (!i830GetBIOS(pScrn))
+	return FALSE;
+
+    vbt_off = INTEL_BIOS_16(0x1a);
+    vbt = (struct vbt_header *)(pI830->VBIOS + vbt_off);
+    bdb = (struct bdb_header *)(pI830->VBIOS + vbt_off + vbt->bdb_offset);
+
+    if (memcmp(bdb->signature, "BIOS_DATA_BLOCK ", 16) != 0) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Bad BDB signature\n");
+	return FALSE;
+    }
+
+    for (bdb_block_off = bdb->header_size; bdb_block_off < bdb->bdb_size;
+	 bdb_block_off += block_size)
+    {
+	int start = vbt_off + vbt->bdb_offset + bdb_block_off;
+	int id;
+
+	id = INTEL_BIOS_8(start);
+	block_size = INTEL_BIOS_16(start + 1) + 3;
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found BDB block type %d\n", id);
+    }
+    return TRUE;
+}
diff --git a/src/i830_bios.h b/src/i830_bios.h
new file mode 100644
index 0000000..ed3f182
--- /dev/null
+++ b/src/i830_bios.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
+struct vbt_header {
+    char signature[20];			/**< Always 'BIOS_DATA_BLOCK' */
+    CARD16 version;			/**< decimal */
+    CARD16 header_size;			/**< in bytes */
+    CARD16 vbt_size;			/**< in bytes */
+    CARD8 vbt_checksum;
+    CARD8 reserved0;
+    CARD32 bdb_offset;			/**< from beginning of VBT */
+    CARD32 aim1_offset;			/**< from beginning of VBT */
+    CARD32 aim2_offset;			/**< from beginning of VBT */
+    CARD32 aim3_offset;			/**< from beginning of VBT */
+    CARD32 aim4_offset;			/**< from beginning of VBT */
+};
+
+struct bdb_header {
+    char signature[16];			/**< Always 'BIOS_DATA_BLOCK' */
+    CARD16 version;			/**< decimal */
+    CARD16 header_size;			/**< in bytes */
+    CARD16 bdb_size;			/**< in bytes */
+};
+
+Bool
+i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScrn);
diff --git a/src/i830_display.c b/src/i830_display.c
index 5386ac8..57038df 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -340,6 +340,13 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     vsync = (pMode->CrtcVSyncStart - 1) | ((pMode->CrtcVSyncEnd - 1) << 16);
     pipesrc = ((pMode->HDisplay - 1) << 16) | (pMode->VDisplay - 1);
     dspsize = ((pMode->VDisplay - 1) << 16) | (pMode->HDisplay - 1);
+    if (outputs & PIPE_LCD_ACTIVE) {
+	/* To enable panel fitting, we need to set the pipe timings to that of
+	 * the screen at its full resolution.  So, pull the timings out of the
+	 * BIOS tables and drop them in here.
+	 */
+	i830GetLVDSInfoFromBIOS(pScrn);
+    }
 
     adpa = INREG(ADPA);
     adpa &= ~(ADPA_HSYNC_ACTIVE_HIGH | ADPA_VSYNC_ACTIVE_HIGH);
diff-tree c2d554be671f5368bd98867b8ecf9428e4560a81 (from 8411c126ae66239f8b3a2261e338a723c36aa44f)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Thu Mar 23 14:33:04 2006 -0800

    Save/restore a couple of important VGA plane registers, and have vgahw
    save/restore everything it knows about.  Also moves the save to just after the
    other reg saves, above the VBE save stuff which may have side effects.

diff --git a/src/i830.h b/src/i830.h
index f971638..eb75f45 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -462,6 +462,10 @@ typedef struct _I830Rec {
    CARD32 saveDSPBSIZE;
    CARD32 saveDSPBPOS;
    CARD32 saveDSPBBASE;
+   CARD32 saveVCLK_DIVISOR_VGA0;
+   CARD32 saveVCLK_DIVISOR_VGA1;
+   CARD32 saveVCLK_POST_DIV;
+   CARD32 saveVGACNTRL;
    CARD32 saveADPA;
 
 } I830Rec;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index ee5c635..48d2d0a 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3749,8 +3749,16 @@ SaveHWState(ScrnInfoPtr pScrn)
    pI830->saveDSPBPOS = INREG(DSPBPOS);
    pI830->saveDSPBBASE = INREG(DSPBBASE);
 
+   pI830->saveVCLK_DIVISOR_VGA0 = INREG(VCLK_DIVISOR_VGA0);
+   pI830->saveVCLK_DIVISOR_VGA1 = INREG(VCLK_DIVISOR_VGA1);
+   pI830->saveVCLK_POST_DIV = INREG(VCLK_POST_DIV);
+   pI830->saveVGACNTRL = INREG(VGACNTRL);
+
    pI830->saveADPA = INREG(ADPA);
 
+   vgaHWUnlock(hwp);
+   vgaHWSave(pScrn, vgaReg, VGA_SR_ALL);
+
    if (I830IsPrimary(pScrn) && pI830->pipe != pI830->origPipe)
       SetBIOSPipe(pScrn, pI830->origPipe);
    else
@@ -3770,9 +3778,6 @@ SaveHWState(ScrnInfoPtr pScrn)
       VBEFreeModeInfo(modeInfo);
    }
 
-   vgaHWUnlock(hwp);
-   vgaHWSave(pScrn, vgaReg, VGA_SR_FONTS);
-
    pVesa = pI830->vesa;
    /*
     * This save/restore method doesn't work for 845G BIOS, or for some
@@ -3876,7 +3881,7 @@ RestoreHWState(ScrnInfoPtr pScrn)
 
    VBESetDisplayStart(pVbe, pVesa->x, pVesa->y, TRUE);
 
-   vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS);
+   vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL);
    vgaHWLock(hwp);
 
    /* First, disable display planes */
@@ -3924,9 +3929,14 @@ RestoreHWState(ScrnInfoPtr pScrn)
    OUTREG(DSPBBASE, pI830->saveDSPBBASE);
    OUTREG(PIPEBSRC, pI830->savePIPEBSRC);
 
+   OUTREG(VCLK_DIVISOR_VGA0, pI830->saveVCLK_DIVISOR_VGA0);
+   OUTREG(VCLK_DIVISOR_VGA1, pI830->saveVCLK_DIVISOR_VGA1);
+   OUTREG(VCLK_POST_DIV, pI830->saveVCLK_POST_DIV);
+
    OUTREG(PIPEACONF, pI830->savePIPEACONF);
    OUTREG(PIPEBCONF, pI830->savePIPEBCONF);
 
+   OUTREG(VGACNTRL, pI830->saveVGACNTRL);
    OUTREG(DSPACNTR, pI830->saveDSPACNTR);
    OUTREG(DSPBCNTR, pI830->saveDSPBCNTR);
 
diff-tree 8411c126ae66239f8b3a2261e338a723c36aa44f (from 6414ad89b9d368a032adf2358a65404f5443ef35)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Thu Mar 23 11:31:24 2006 -0800

    Update to newer airlied DDC code, and do some cleanups as well. Now tries DDC
    on LVDS, though my current LVDS gives no results.

diff --git a/src/i830.h b/src/i830.h
index d3d1f5a..f971638 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -157,41 +157,55 @@ typedef struct {
 /* store information about an Ixxx DVO */
 /* The i830->i865 use multiple DVOs with multiple i2cs */
 /* the i915, i945 have a single sDVO i2c bus - which is different */
-#define MAX_DVOS 4
+#define MAX_OUTPUTS 6
 
 #define I830_I2C_BUS_DVO 1
 #define I830_I2C_BUS_SDVO 2
 
+/* these are outputs from the chip - integrated only 
+   external chips are via DVO or SDVO output */
+#define I830_OUTPUT_UNUSED 0
+#define I830_OUTPUT_ANALOG 1
+#define I830_OUTPUT_DVO 2
+#define I830_OUTPUT_SDVO 3
+#define I830_OUTPUT_LVDS 4
+#define I830_OUTPUT_TVOUT 5
+
 #define I830_DVO_CHIP_NONE 0
 #define I830_DVO_CHIP_LVDS 1
 #define I830_DVO_CHIP_TMDS 2
 #define I830_DVO_CHIP_TVOUT 4
 
-struct _I830RegI2CDriver {
+struct _I830DVODriver {
    int type;
    char *modulename;
    char *fntablename;
    int address;
    const char **symbols;
+#if 0
+   I830I2CVidOutputRec *vid_rec;
+#endif
    void *devpriv;
    pointer modhandle;
 };
-  
-struct _I830DVORec {
-   int bus_type;
-   int flags;
-   I2CBusPtr pI2CBus;
-   I2CBusPtr pDDCBus;
-   xf86MonPtr MonInfo;
-   struct _I830RegI2CDriver *i2c_drv;
-};
 
-typedef struct _I830SDVORec {
+typedef struct _I830SDVODriver {
    int found;
    I2CDevRec d;
    unsigned char sdvo_regs[20];
 } I830SDVORec, *I830SDVOPtr;
 
+struct _I830OutputRec {
+   int type;
+   int pipe;
+   int flags;
+   xf86MonPtr MonInfo;
+   I2CBusPtr pI2CBus;
+   I2CBusPtr pDDCBus;
+   struct _I830DVODriver *i2c_drv;
+   struct _I830SDVODriver *sdvo_drv;
+};
+
 typedef struct _I830Rec {
    unsigned char *MMIOBase;
    unsigned char *FbBase;
@@ -412,9 +426,8 @@ typedef struct _I830Rec {
    OsTimerPtr devicesTimer;
 
    int ddc2;
-   int num_dvos;
-
-   struct _I830DVORec dvos[MAX_DVOS];
+   int num_outputs;
+   struct _I830OutputRec output[MAX_OUTPUTS];
    I830SDVOPtr sdvo;
 
    CARD32 saveDSPACNTR;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index f05e273..ee5c635 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -269,6 +269,15 @@ static OptionInfoRec I830BIOSOptions[] =
 };
 /* *INDENT-ON* */
 
+static const char *output_type_names[] = {
+   "Unused",
+   "Analog",
+   "DVO",
+   "SDVO",
+   "LVDS",
+   "TVOUT",
+};
+
 static void I830DisplayPowerManagementSet(ScrnInfoPtr pScrn,
 					  int PowerManagementMode, int flags);
 static void i830AdjustFrame(int scrnIndex, int x, int y, int flags);
@@ -1916,6 +1925,58 @@ I830UseDDC(ScrnInfoPtr pScrn)
    return mon_range->max_clock;
 }
 
+static void
+I830SetupOutputBusses(ScrnInfoPtr pScrn)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+
+   /* everyone has at least a single analog output */
+   pI830->num_outputs = 1;
+   pI830->output[0].type = I830_OUTPUT_ANALOG;
+
+   /* setup the DDC bus for the analog output */
+   I830I2CInit(pScrn, &pI830->output[0].pDDCBus, GPIOA, "CRTDDC_A");
+
+   /* need to add the output busses for each device 
+    * - this function is very incomplete
+    * - i915GM has LVDS and TVOUT for example
+    */
+   switch(pI830->PciInfo->chipType) {
+   case PCI_CHIP_I830_M:
+   case PCI_CHIP_845_G:
+   case PCI_CHIP_I855_GM:
+   case PCI_CHIP_I865_G:
+      pI830->num_outputs = 2;
+      pI830->output[1].type = I830_OUTPUT_DVO;
+      I830I2CInit(pScrn, &pI830->output[1].pDDCBus, GPIOD, "DVODDC_D");
+      I830I2CInit(pScrn, &pI830->output[1].pI2CBus, GPIOE, "DVOI2C_E");
+      break;
+   case PCI_CHIP_E7221_G:
+      /* ??? */
+      break;
+   case PCI_CHIP_I915_G:
+   case PCI_CHIP_I915_GM:
+      pI830->num_outputs = 2;
+      pI830->output[1].type = I830_OUTPUT_LVDS;
+      I830I2CInit(pScrn, &pI830->output[1].pDDCBus, GPIOC, "LVDSDDC_C");
+      break;
+#if 0
+   case PCI_CHIP_I945_G:
+   case PCI_CHIP_I945_GM:
+      /* SDVO ports have a single control bus */
+      pI830->num_outputs = 2;
+      pI830->output[1].type = I830_OUTPUT_SDVO;
+      I830I2CInit(pScrn, &pI830->output[1].pI2CBus, GPIOE, "SDVOCTRL_E");
+
+      pI830->output[1].sdvo_drv = I830SDVOInit(pI830->output[1].pI2CBus);
+      ret = I830I2CDetectSDVOController(pScrn, 1);
+      if (ret == TRUE)
+	 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found sDVO\n");
+      break;
+#endif
+   }
+}
+
 void 
 I830PreInitDDC(ScrnInfoPtr pScrn)
 {
@@ -1932,41 +1993,9 @@ I830PreInitDDC(ScrnInfoPtr pScrn)
    /* Load I2C if we have the code to use it */
    if (pI830->ddc2) {
       if (xf86LoadSubModule(pScrn, "i2c")) {
-	 xf86LoaderReqSymLists(I810i2cSymbols,NULL);
+	 xf86LoaderReqSymLists(I810i2cSymbols, NULL);
 
-	 pI830->num_dvos = 1;
-	 pI830->dvos[0].bus_type = I830_I2C_BUS_DVO;
-	 /* setup the common CRT DVO */
-	 pI830->ddc2 = I830I2CInit(pScrn, &pI830->dvos[0].pDDCBus, GPIOA, "DDCGPIOA");
-	 if (pI830->ddc2 == FALSE)
-	    return;
-	 pI830->ddc2 = I830I2CInit(pScrn, &pI830->dvos[0].pI2CBus, GPIOB, "I2CGPIOB");
-	 if (pI830->ddc2 == FALSE)
-	    return;
-	    
-	 if (!(IS_I9XX(pI830))) {
-	    pI830->dvos[1].bus_type = I830_I2C_BUS_DVO;
-	    pI830->num_dvos = 2;
-	      
-	    pI830->ddc2 = I830I2CInit(pScrn, &pI830->dvos[1].pDDCBus, GPIOD, "DDCGPIOD");
-	    if (pI830->ddc2 == FALSE)
-	       return;
-	    pI830->ddc2 = I830I2CInit(pScrn, &pI830->dvos[1].pI2CBus, GPIOE, "I2CGPIOE");
-	    if (pI830->ddc2 == FALSE)
-	       return;
-	 }
-#if 0
-	 else {
-	 pointer ret_p;
-	 pI830->num_dvos = 2;
-	 pI830->dvos[1].bus_type = I830_I2C_BUS_SDVO;
-	 /* i915 has sDVO */
-	 pI830->ddc2 = I830I2CInit(pScrn, &pI830->dvos[1].pI2CBus, GPIOE, "SDVOCTRL");
-	 if (pI830->ddc2 = FALSE)
-	    return;
-	 pI830->sdvo=I830SDVOInit(pI830->dvos[1].pI2CBus);
-	 }
-#endif
+	 I830SetupOutputBusses(pScrn);
 
 	 pI830->ddc2 = TRUE;
       } else {
@@ -1978,42 +2007,67 @@ I830PreInitDDC(ScrnInfoPtr pScrn)
 void I830DetectMonitors(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
-   int i;
+   int i, ret;
 
    if (!pI830->ddc2)
       return;
 
-   for (i=0; i<pI830->num_dvos; i++) {
-      /* we can't do EDID on sDVO yet */
-      if (pI830->dvos[i].bus_type == I830_I2C_BUS_DVO) {
-	 pI830->dvos[i].MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex,
-						  pI830->dvos[i].pDDCBus);
-
-	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "checking DVO %d, %08X\n", i,
-		    pI830->dvos[i].pDDCBus->DriverPrivate.uval);
-	 xf86PrintEDID(pI830->dvos[i].MonInfo);
-
-#if 0
+   for (i=0; i<pI830->num_outputs; i++) {
+      switch (pI830->output[i].type) {
+      case I830_OUTPUT_ANALOG:
+      case I830_OUTPUT_LVDS:
+	 /* for an analog/LVDS output, just do DDC */
+	 pI830->output[i].MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex,
+						    pI830->output[i].pDDCBus);
+
+	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC %s %d, %08X\n",
+		    output_type_names[pI830->output[i].type], i,
+		    pI830->output[i].pDDCBus->DriverPrivate.uval);
+	 xf86PrintEDID(pI830->output[i].MonInfo);
+	 break;
+      case I830_OUTPUT_DVO:
+	 /* check for DDC */
+	 pI830->output[i].MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex,
+						    pI830->output[i].pDDCBus);
+
+	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC DVO %d, %08lX\n", i,
+		    pI830->output[i].pDDCBus->DriverPrivate.uval);
+	 xf86PrintEDID(pI830->output[i].MonInfo);
+      
 	 /* if we are on an i2C bus > 0 and we see a monitor - try to
 	  * find a controller chip
 	  */
-	 if (i > 0 && pI830->dvos[i].MonInfo) {
-	    ret = I830I2CDetectControllers(pScrn, pI830->dvos[i].pI2CBus,
-					   &pI830->dvos[i].i2c_drv);
+	 if (pI830->output[i].MonInfo) {
+	    ret = I830I2CDetectDVOControllers(pScrn, pI830->output[i].pI2CBus,
+					      &pI830->output[i].i2c_drv);
 	    if (ret==TRUE) {
-	       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08X\n", pI830->dvos[i].i2c_drv->modulename, pI830->dvos[i].pI2CBus->DriverPrivate.uval);
+	       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08X\n",
+			  pI830->output[i].i2c_drv->modulename,
+			  pI830->output[i].pI2CBus->DriverPrivate.uval);
 	    }
 	 }
-#endif
-      }
+      break;
 #if 0
-      else {
-	 ret = I830I2CDetectSDVOController(pScrn, pI830->dvos[i].pI2CBus);
-	 if (ret==TRUE) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found sDVO\n");
+      case I830_OUTPUT_SDVO:
+	 if (pI830->output[i].sdvo_drv->found) {
+	    I830SDVOSetupDDC(pI830->output[i].sdvo_drv);
+
+	    pI830->output[i].MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex,
+						       pI830->output[i].pI2CBus);
+
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC SDVO %d, %08X\n", i,
+		       pI830->output[i].pI2CBus->DriverPrivate.uval);
+	    xf86PrintEDID(pI830->output[i].MonInfo);
 	 }
-      }
+	 break;
 #endif
+      case I830_OUTPUT_UNUSED:
+	 break;
+      default:
+	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		    "Unknown or unhandled output device at %d\n", i);
+	 break;
+      }
    }
 }
 
@@ -2502,9 +2556,9 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
 
    I830DetectMonitors(pScrn);
 
-   for (i=0; i<MAX_DVOS; i++) {
-     if (pI830->dvos[i].MonInfo) {
-       pScrn->monitor->DDC = pI830->dvos[i].MonInfo;
+   for (i = 0; i < MAX_OUTPUTS; i++) {
+     if (pI830->output[i].MonInfo) {
+       pScrn->monitor->DDC = pI830->output[i].MonInfo;
        break;
      }
    }
diff-tree 6414ad89b9d368a032adf2358a65404f5443ef35 (from 5215e19af58f5c2746c8d281e33ecee86e55f0a5)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Thu Mar 23 09:48:18 2006 -0800

    Add enough of airlied's DDC/I2C work to pull EDID info from my CRT.

diff --git a/src/Makefile.am b/src/Makefile.am
index f0f6691..37682eb 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -53,6 +53,7 @@ i810_drv_la_SOURCES = \
 	 i830_display.h \
          i830_driver.c \
          i830.h \
+         i830_i2c.c \
          i830_io.c \
          i830_memory.c \
          i830_modes.c \
diff --git a/src/common.h b/src/common.h
index e9debe5..6e68767 100644
--- a/src/common.h
+++ b/src/common.h
@@ -85,6 +85,7 @@ extern const char *I810driSymbols[];
 extern const char *I810drmSymbols[];
 extern const char *I810shadowSymbols[];
 #endif
+extern const char *I810i2cSymbols[];
 
 extern void I830DPRINTF_stub(const char *filename, int line,
 			     const char *function, const char *fmt, ...);
diff --git a/src/i810_driver.c b/src/i810_driver.c
index 54395a7..f7247f4 100644
--- a/src/i810_driver.c
+++ b/src/i810_driver.c
@@ -332,6 +332,12 @@ const char *I810shadowSymbols[] = {
     NULL
 };
 
+const char *I810i2cSymbols[] = {
+    "xf86CreateI2CBusRec",
+    "xf86I2CBusInit",
+    NULL
+};
+
 #ifndef I810_DEBUG
 int I810_DEBUG = (0
 /*     		  | DEBUG_ALWAYS_SYNC  */
diff --git a/src/i810_reg.h b/src/i810_reg.h
index 3316fed..6976553 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -258,7 +258,24 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define HSYNC_ON               0x00
 #define HSYNC_OFF              0x02
 
-
+#define GPIOA			0x5010
+#define GPIOB			0x5014
+#define GPIOC			0x5018
+#define GPIOD			0x501c
+#define GPIOE			0x5020
+#define GPIOF			0x5024
+#define GPIOG			0x5028
+#define GPIOH			0x502c
+# define GPIO_CLOCK_DIR_MASK		(1 << 0)
+# define GPIO_CLOCK_DIR			(1 << 1)
+# define GPIO_CLOCK_VAL_MASK		(1 << 2)
+# define GPIO_CLOCK_VAL_OUT		(1 << 3)
+# define GPIO_CLOCK_VAL_IN		(1 << 4)
+# define GPIO_DATA_DIR_MASK		(1 << 8)
+# define GPIO_DATA_DIR			(1 << 9)
+# define GPIO_DATA_VAL_MASK		(1 << 10)
+# define GPIO_DATA_VAL_OUT		(1 << 11)
+# define GPIO_DATA_VAL_IN		(1 << 12)
 
 /* p317, 319
  */
diff --git a/src/i830.h b/src/i830.h
index 4effcd5..d3d1f5a 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -154,6 +154,44 @@ typedef struct {
 #endif
 } I830EntRec, *I830EntPtr;
 
+/* store information about an Ixxx DVO */
+/* The i830->i865 use multiple DVOs with multiple i2cs */
+/* the i915, i945 have a single sDVO i2c bus - which is different */
+#define MAX_DVOS 4
+
+#define I830_I2C_BUS_DVO 1
+#define I830_I2C_BUS_SDVO 2
+
+#define I830_DVO_CHIP_NONE 0
+#define I830_DVO_CHIP_LVDS 1
+#define I830_DVO_CHIP_TMDS 2
+#define I830_DVO_CHIP_TVOUT 4
+
+struct _I830RegI2CDriver {
+   int type;
+   char *modulename;
+   char *fntablename;
+   int address;
+   const char **symbols;
+   void *devpriv;
+   pointer modhandle;
+};
+  
+struct _I830DVORec {
+   int bus_type;
+   int flags;
+   I2CBusPtr pI2CBus;
+   I2CBusPtr pDDCBus;
+   xf86MonPtr MonInfo;
+   struct _I830RegI2CDriver *i2c_drv;
+};
+
+typedef struct _I830SDVORec {
+   int found;
+   I2CDevRec d;
+   unsigned char sdvo_regs[20];
+} I830SDVORec, *I830SDVOPtr;
+
 typedef struct _I830Rec {
    unsigned char *MMIOBase;
    unsigned char *FbBase;
@@ -373,6 +411,12 @@ typedef struct _I830Rec {
 
    OsTimerPtr devicesTimer;
 
+   int ddc2;
+   int num_dvos;
+
+   struct _I830DVORec dvos[MAX_DVOS];
+   I830SDVOPtr sdvo;
+
    CARD32 saveDSPACNTR;
    CARD32 saveDSPBCNTR;
    CARD32 savePIPEACONF;
@@ -506,6 +550,8 @@ extern Bool I830RandRSetConfig(ScreenPtr
 			       int rate, RRScreenSizePtr pSize);
 extern Rotation I830GetRotation(ScreenPtr pScreen);
 extern Bool I830RandRInit(ScreenPtr pScreen, int rotation);
+extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg,
+			char *name);
 
 /*
  * 12288 is set as the maximum, chosen because it is enough for
diff --git a/src/i830_driver.c b/src/i830_driver.c
index cdcea29..f05e273 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1916,6 +1916,107 @@ I830UseDDC(ScrnInfoPtr pScrn)
    return mon_range->max_clock;
 }
 
+void 
+I830PreInitDDC(ScrnInfoPtr pScrn)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+
+   if (!xf86LoadSubModule(pScrn, "ddc")) {
+      pI830->ddc2 = FALSE;
+   } else {
+      xf86LoaderReqSymLists(I810ddcSymbols, NULL);
+      pI830->ddc2 = TRUE;
+   }
+
+   /* DDC can use I2C bus */
+   /* Load I2C if we have the code to use it */
+   if (pI830->ddc2) {
+      if (xf86LoadSubModule(pScrn, "i2c")) {
+	 xf86LoaderReqSymLists(I810i2cSymbols,NULL);
+
+	 pI830->num_dvos = 1;
+	 pI830->dvos[0].bus_type = I830_I2C_BUS_DVO;
+	 /* setup the common CRT DVO */
+	 pI830->ddc2 = I830I2CInit(pScrn, &pI830->dvos[0].pDDCBus, GPIOA, "DDCGPIOA");
+	 if (pI830->ddc2 == FALSE)
+	    return;
+	 pI830->ddc2 = I830I2CInit(pScrn, &pI830->dvos[0].pI2CBus, GPIOB, "I2CGPIOB");
+	 if (pI830->ddc2 == FALSE)
+	    return;
+	    
+	 if (!(IS_I9XX(pI830))) {
+	    pI830->dvos[1].bus_type = I830_I2C_BUS_DVO;
+	    pI830->num_dvos = 2;
+	      
+	    pI830->ddc2 = I830I2CInit(pScrn, &pI830->dvos[1].pDDCBus, GPIOD, "DDCGPIOD");
+	    if (pI830->ddc2 == FALSE)
+	       return;
+	    pI830->ddc2 = I830I2CInit(pScrn, &pI830->dvos[1].pI2CBus, GPIOE, "I2CGPIOE");
+	    if (pI830->ddc2 == FALSE)
+	       return;
+	 }
+#if 0
+	 else {
+	 pointer ret_p;
+	 pI830->num_dvos = 2;
+	 pI830->dvos[1].bus_type = I830_I2C_BUS_SDVO;
+	 /* i915 has sDVO */
+	 pI830->ddc2 = I830I2CInit(pScrn, &pI830->dvos[1].pI2CBus, GPIOE, "SDVOCTRL");
+	 if (pI830->ddc2 = FALSE)
+	    return;
+	 pI830->sdvo=I830SDVOInit(pI830->dvos[1].pI2CBus);
+	 }
+#endif
+
+	 pI830->ddc2 = TRUE;
+      } else {
+	 pI830->ddc2 = FALSE;
+      }
+   }
+}
+
+void I830DetectMonitors(ScrnInfoPtr pScrn)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+   int i;
+
+   if (!pI830->ddc2)
+      return;
+
+   for (i=0; i<pI830->num_dvos; i++) {
+      /* we can't do EDID on sDVO yet */
+      if (pI830->dvos[i].bus_type == I830_I2C_BUS_DVO) {
+	 pI830->dvos[i].MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex,
+						  pI830->dvos[i].pDDCBus);
+
+	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "checking DVO %d, %08X\n", i,
+		    pI830->dvos[i].pDDCBus->DriverPrivate.uval);
+	 xf86PrintEDID(pI830->dvos[i].MonInfo);
+
+#if 0
+	 /* if we are on an i2C bus > 0 and we see a monitor - try to
+	  * find a controller chip
+	  */
+	 if (i > 0 && pI830->dvos[i].MonInfo) {
+	    ret = I830I2CDetectControllers(pScrn, pI830->dvos[i].pI2CBus,
+					   &pI830->dvos[i].i2c_drv);
+	    if (ret==TRUE) {
+	       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08X\n", pI830->dvos[i].i2c_drv->modulename, pI830->dvos[i].pI2CBus->DriverPrivate.uval);
+	    }
+	 }
+#endif
+      }
+#if 0
+      else {
+	 ret = I830I2CDetectSDVOController(pScrn, pI830->dvos[i].pI2CBus);
+	 if (ret==TRUE) {
+	 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found sDVO\n");
+	 }
+      }
+#endif
+   }
+}
+
 static void
 PreInitCleanup(ScrnInfoPtr pScrn)
 {
@@ -2397,6 +2498,17 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
          pI830->fixedPipe = 1;
    }
 
+   I830PreInitDDC(pScrn);
+
+   I830DetectMonitors(pScrn);
+
+   for (i=0; i<MAX_DVOS; i++) {
+     if (pI830->dvos[i].MonInfo) {
+       pScrn->monitor->DDC = pI830->dvos[i].MonInfo;
+       break;
+     }
+   }
+
    pI830->MonType1 = PIPE_NONE;
    pI830->MonType2 = PIPE_NONE;
    pI830->specifiedMonitor = FALSE;
diff --git a/src/i830_i2c.c b/src/i830_i2c.c
new file mode 100644
index 0000000..8c80a0a
--- /dev/null
+++ b/src/i830_i2c.c
@@ -0,0 +1,286 @@
+/**************************************************************************
+
+ Copyright 2006 Dave Airlie <airlied at linux.ie>
+ 
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "xf86_ansic.h"
+#include "xf86_OSproc.h"
+#include "xf86Resources.h"
+#include "xf86RAC.h"
+#include "xf86cmap.h"
+#include "compiler.h"
+#include "mibstore.h"
+#include "vgaHW.h"
+#include "mipointer.h"
+#include "micmap.h"
+#include "shadowfb.h"
+#include <X11/extensions/randr.h>
+#include "fb.h"
+#include "miscstruct.h"
+#include "xf86xv.h"
+#include <X11/extensions/Xv.h>
+#include "shadow.h"
+#include "i830.h"
+
+#define I2C_TIMEOUT(x)	/*(x)*/  /* Report timeouts */
+#define I2C_TRACE(x)    /*(x)*/  /* Report progress */
+
+static void i830_setscl(I2CBusPtr b, int state)
+{
+    ScrnInfoPtr    pScrn      = xf86Screens[b->scrnIndex];
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD32 val;
+
+    OUTREG(b->DriverPrivate.uval,
+	(state ? GPIO_CLOCK_VAL_OUT : 0) |
+	GPIO_CLOCK_DIR |
+	GPIO_CLOCK_DIR_MASK |
+	GPIO_CLOCK_VAL_MASK);
+    val = INREG(b->DriverPrivate.uval);
+}
+
+static void i830_setsda(I2CBusPtr b, int state)
+{
+    ScrnInfoPtr    pScrn      = xf86Screens[b->scrnIndex];
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD32 val;
+
+    OUTREG(b->DriverPrivate.uval, (state ? GPIO_DATA_VAL_OUT : 0) |
+	GPIO_DATA_DIR |
+	GPIO_DATA_DIR_MASK |
+	GPIO_DATA_VAL_MASK);
+    val = INREG(b->DriverPrivate.uval);
+}
+
+static void i830_getscl(I2CBusPtr b, int *state)
+{
+    ScrnInfoPtr    pScrn      = xf86Screens[b->scrnIndex];
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD32 val;
+
+    OUTREG(b->DriverPrivate.uval, GPIO_CLOCK_DIR_MASK);
+    OUTREG(b->DriverPrivate.uval, 0);
+    val = INREG(b->DriverPrivate.uval);
+    *state = ((val & GPIO_CLOCK_VAL_IN) != 0);
+}
+
+static int i830_getsda(I2CBusPtr b)
+{
+    ScrnInfoPtr    pScrn      = xf86Screens[b->scrnIndex];
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD32 val;
+
+    OUTREG(b->DriverPrivate.uval, GPIO_DATA_DIR_MASK);
+    OUTREG(b->DriverPrivate.uval, 0);
+    val = INREG(b->DriverPrivate.uval);
+    return ((val & GPIO_DATA_VAL_IN) != 0);
+}
+
+static inline void sdalo(I2CBusPtr b)
+{
+    i830_setsda(b, 0);
+    b->I2CUDelay(b, b->RiseFallTime);
+}
+
+static inline void sdahi(I2CBusPtr b)
+{
+    i830_setsda(b, 1);
+    b->I2CUDelay(b, b->RiseFallTime);
+}
+
+static inline void scllo(I2CBusPtr b)
+{
+    i830_setscl(b, 0);
+    b->I2CUDelay(b, b->RiseFallTime);
+}
+
+static inline int sclhi(I2CBusPtr b, int timeout)
+{
+    int scl = 0;
+    int i;
+
+    i830_setscl(b, 1);
+    b->I2CUDelay(b, b->RiseFallTime);
+  
+    for (i = timeout; i > 0; i -= b->RiseFallTime) {
+	i830_getscl(b, &scl);
+	if (scl) break;
+	b->I2CUDelay(b, b->RiseFallTime);
+    }
+
+    if (i <= 0) {
+	I2C_TIMEOUT(ErrorF("[I2CRaiseSCL(<%s>, %d) timeout]", b->BusName, timeout));    
+	return FALSE;
+    }
+    return TRUE;
+}
+
+static Bool
+I830I2CGetByte(I2CDevPtr d, I2CByte *data, Bool last)
+{
+    I2CBusPtr b = d->pI2CBus;
+    int i;
+    unsigned char indata = 0;
+
+    sdahi(b);
+
+    for (i = 0; i < 8; i++) {
+      if (sclhi(b, d->BitTimeout)==FALSE) {
+	I2C_TRACE(ErrorF("timeout at bit #%d\n", 7-i));
+	return FALSE;
+      }
+      indata*=2;
+      if ( i830_getsda (b) ) {
+	indata |= 0x01;
+      }
+      scllo(b);
+    }
+
+    if (last)
+      sdahi(b);
+    else
+      sdalo(b);
+
+    if (sclhi(b, d->BitTimeout) == FALSE) {
+      sdahi(b);
+      return FALSE;
+    }
+
+    scllo(b);
+    sdahi(b);
+
+    *data = indata & 0xff;
+    I2C_TRACE(ErrorF("R%02x ", (int) *data));
+    
+    return TRUE;
+}
+
+static Bool
+I830I2CPutByte(I2CDevPtr d, I2CByte c)
+{
+    int i;
+    int sb, ack;
+    I2CBusPtr b = d->pI2CBus;
+
+    for (i = 7; i>=0; i--) {
+      sb = c & (1 << i);
+      i830_setsda(b, sb);
+      b->I2CUDelay(b, b->RiseFallTime);
+
+      if (sclhi(b, d->ByteTimeout) == FALSE) {
+	sdahi(b);
+	return FALSE;
+      }
+
+      i830_setscl(b, 0);
+      b->I2CUDelay(b, b->RiseFallTime);
+    }
+    sdahi(b);
+    if (sclhi(b, d->ByteTimeout) == FALSE) {
+      I2C_TIMEOUT(ErrorF("[I2CPutByte(<%s>, 0x%02x, %d, %d, %d) timeout]", 
+			 b->BusName, c, d->BitTimeout, 
+			 d->ByteTimeout, d->AcknTimeout));
+      return FALSE;
+    }
+    ack = i830_getsda(b);
+    I2C_TRACE(ErrorF("Put byte 0x%02x , getsda() = %d\n", c & 0xff, ack));
+
+    scllo(b);
+    return 0 == ack;
+}
+
+static Bool
+I830I2CStart(I2CBusPtr b, int timeout)
+{
+    if (sclhi(b, timeout) == FALSE)
+	return FALSE;
+
+    sdalo(b);
+    scllo(b);
+    
+    return TRUE;
+}
+
+static void
+I830I2CStop(I2CDevPtr d)
+{
+    I2CBusPtr b = d->pI2CBus;
+
+    sdalo(b);
+    sclhi(b, d->ByteTimeout);
+    sdahi(b);
+}
+
+static Bool
+I830I2CAddress(I2CDevPtr d, I2CSlaveAddr addr)
+{
+    if (I830I2CStart(d->pI2CBus, d->StartTimeout)) {
+	if (I830I2CPutByte(d, addr & 0xFF)) {
+	    if ((addr & 0xF8) != 0xF0 &&
+		(addr & 0xFE) != 0x00)
+		return TRUE;
+
+	    if (I830I2CPutByte(d, (addr >> 8) & 0xFF))
+		return TRUE;
+	}
+
+	I830I2CStop(d);
+    }
+
+    return FALSE;
+}
+
+
+/* the i830 has a number of I2C Buses */
+Bool
+I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg, char *name)
+{
+    I2CBusPtr pI2CBus;
+
+    pI2CBus = xf86CreateI2CBusRec();
+
+    if (!pI2CBus)
+	return FALSE;
+
+    pI2CBus->BusName = name;
+    pI2CBus->scrnIndex = pScrn->scrnIndex;
+    pI2CBus->I2CGetByte = I830I2CGetByte;
+    pI2CBus->I2CPutByte = I830I2CPutByte;
+    pI2CBus->I2CStart = I830I2CStart;
+    pI2CBus->I2CStop = I830I2CStop;
+    pI2CBus->I2CAddress = I830I2CAddress;
+    pI2CBus->DriverPrivate.uval = i2c_reg;
+
+    if (!xf86I2CBusInit(pI2CBus))
+	return FALSE;
+
+    *bus_ptr = pI2CBus;
+    return TRUE;
+}
diff-tree 5215e19af58f5c2746c8d281e33ecee86e55f0a5 (from b77bdc2c15640a3b15233f2190179d66bc8b2a4b)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Mar 13 10:29:51 2006 -0800

    Add some register information for VGACNTRL, and do the reg-debug thing on it.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index f781b93..3316fed 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -837,6 +837,11 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define DSPBPOS			0x7118C
 #define DSPBSIZE		0x71190
 
+#define VGACNTRL		0x71400
+# define VGA_DISP_DISABLE			(1 << 31)
+# define VGA_2X_MODE				(1 << 30)
+# define VGA_PIPE_B_SELECT			(1 << 29)
+
 /* Various masks for reserved bits, etc. */
 #define I830_FWATER1_MASK        (~((1<<11)|(1<<10)|(1<<9)|      \
         (1<<8)|(1<<26)|(1<<25)|(1<<24)|(1<<5)|(1<<4)|(1<<3)|    \
diff --git a/src/i830_debug.c b/src/i830_debug.c
index 0695f06..96426c4 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -70,6 +70,7 @@ static struct i830SnapshotRec {
     DEFINEREG(VCLK_DIVISOR_VGA0),
     DEFINEREG(VCLK_DIVISOR_VGA1),
     DEFINEREG(VCLK_POST_DIV),
+    DEFINEREG(VGACNTRL),
 };
 #undef DEFINEREG
 #define NUM_I830_SNAPSHOTREGS (sizeof(i830_snapshot) / sizeof(i830_snapshot[0]))
diff-tree b77bdc2c15640a3b15233f2190179d66bc8b2a4b (from de4a9e4a7891daa1488d17bf4c22283759f97373)
Author: Eric Anholt <anholt at debian-sony.jf.intel.com>
Date:   Wed Mar 8 15:08:06 2006 -0800

    Move the PFIT enabling before the enabling of the pipe, as the specs say we
    should.  This doesn't work yet, as we apparently need to adjust the pipe to
    output at the full resolution of the panel, not the displayed image size,
    because PFIT controls scaling between the display planes and the pipe.

diff --git a/src/i830_display.c b/src/i830_display.c
index a7a0144..5386ac8 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -463,6 +463,16 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	i830PipeSetBase(pScrn, pipe, pScrn->frameX0, pScrn->frameY0);
 	OUTREG(PIPEBSRC, pipesrc);
 
+	if (outputs & PIPE_LCD_ACTIVE) {
+	    /* Enable automatic panel scaling so that non-native modes fill the
+	     * screen.
+	     */
+	    /* XXX: Allow (auto-?) enabling of 8-to-6 dithering */
+	    OUTREG(PFIT_CONTROL, PFIT_ENABLE /*|
+		   VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
+		   VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR*/);
+	}
+
 	/* Then, turn the pipe on first */
 	temp = INREG(PIPEBCONF);
 	OUTREG(PIPEBCONF, temp | PIPEBCONF_ENABLE);
@@ -471,14 +481,6 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	OUTREG(DSPBCNTR, dspcntr);
 
 	if (outputs & PIPE_LCD_ACTIVE) {
-	    /* Enable automatic panel scaling so that non-native modes fill the
-	     * screen.
-	     */
-	    /* XXX: Allow (auto-?) enabling of 8-to-6 dithering */
-	    OUTREG(PFIT_CONTROL, PFIT_ENABLE |
-		   VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
-		   VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR);
-
 	    i830SetLVDSPanelPower(pScrn, TRUE);
 	}
     }
diff-tree de4a9e4a7891daa1488d17bf4c22283759f97373 (from 02341aa68cf2171e037196019f2553f0d1b1bd0d)
Author: Eric Anholt <anholt at debian-sony.jf.intel.com>
Date:   Wed Mar 8 12:54:14 2006 -0800

    Add a couple more bits to panel auto-fitting, though it isn't working yet.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index c9b3f5a..f781b93 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -680,6 +680,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 # define PFIT_VERT_SCALE_MASK			0xfff00000
 # define PFIT_HORIZ_SCALE_MASK			0x0000fff0
 
+#define PFIT_AUTO_RATIOS	0x61238
+
 #define DPLL_A		0x06014
 #define DPLL_B		0x06018
 # define DPLL_VCO_ENABLE			(1 << 31)
diff --git a/src/i830_display.c b/src/i830_display.c
index cfff47e..a7a0144 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -475,8 +475,10 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	     * screen.
 	     */
 	    /* XXX: Allow (auto-?) enabling of 8-to-6 dithering */
-	    OUTREG(PFIT_CONTROL, PFIT_ENABLE | VERT_AUTO_SCALE |
-		   HORIZ_AUTO_SCALE);
+	    OUTREG(PFIT_CONTROL, PFIT_ENABLE |
+		   VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
+		   VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR);
+
 	    i830SetLVDSPanelPower(pScrn, TRUE);
 	}
     }
diff-tree 02341aa68cf2171e037196019f2553f0d1b1bd0d (from 2b6fc7ddb020a5511f6f599a2f5c37db27eddbcc)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Mar 6 13:23:29 2006 -0800

    Make the reg-snapshot code work, add a couple more registers, and use it on VT
    switching to hopefully help point out where we aren't restoring enough.
    Currently doesn't reveal anything.

diff --git a/src/i830_debug.c b/src/i830_debug.c
index 37c0e04..0695f06 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -20,7 +20,6 @@ static struct i830SnapshotRec {
     DEFINEREG(DVOA),
     DEFINEREG(DVOB),
     DEFINEREG(DVOC),
-    DEFINEREG(DVO_ENABLE),
     DEFINEREG(DVOA_SRCDIM),
     DEFINEREG(DVOB_SRCDIM),
     DEFINEREG(DVOC_SRCDIM),
@@ -68,7 +67,9 @@ static struct i830SnapshotRec {
     DEFINEREG(VBLANK_B),
     DEFINEREG(VSYNC_B),
 
-    { 0, NULL, 0}
+    DEFINEREG(VCLK_DIVISOR_VGA0),
+    DEFINEREG(VCLK_DIVISOR_VGA1),
+    DEFINEREG(VCLK_POST_DIV),
 };
 #undef DEFINEREG
 #define NUM_I830_SNAPSHOTREGS (sizeof(i830_snapshot) / sizeof(i830_snapshot[0]))
@@ -88,6 +89,8 @@ void i830CompareRegsToSnapshot(ScrnInfoP
     I830Ptr pI830 = I830PTR(pScrn);
     int i;
 
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+	       "Comparing regs before/after X's VT usage\n");
     for (i = 0; i < NUM_I830_SNAPSHOTREGS; i++) {
 	CARD32 val = INREG(i830_snapshot[i].reg);
 	if (i830_snapshot[i].regval != val) {
diff --git a/src/i830_driver.c b/src/i830_driver.c
index ede9cb8..cdcea29 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -182,6 +182,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "shadow.h"
 #include "i830.h"
 #include "i830_display.h"
+#include "i830_debug.h"
 
 #ifdef XF86DRI
 #include "dri.h"
@@ -3545,6 +3546,8 @@ SaveHWState(ScrnInfoPtr pScrn)
 
    DPRINTF(PFX, "SaveHWState\n");
 
+   i830TakeRegSnapshot(pScrn);
+
    /* Save video mode information for native mode-setting. */
    pI830->saveDSPACNTR = INREG(DSPACNTR);
    pI830->saveDSPBCNTR = INREG(DSPBCNTR);
@@ -3763,6 +3766,8 @@ RestoreHWState(ScrnInfoPtr pScrn)
 
    OUTREG(ADPA, pI830->saveADPA);
 
+   i830CompareRegsToSnapshot(pScrn);
+
    return TRUE;
 }
 
diff-tree 2b6fc7ddb020a5511f6f599a2f5c37db27eddbcc (from 12ce799818722473dde2f82739d50ba4ec7f6ecd)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Fri Mar 3 15:42:15 2006 -0800

    Add missed save/restore of DSP*SIZE registers.

diff --git a/src/i830.h b/src/i830.h
index 321827a..4effcd5 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -389,6 +389,7 @@ typedef struct _I830Rec {
    CARD32 saveVBLANK_A;
    CARD32 saveVSYNC_A;
    CARD32 saveDSPASTRIDE;
+   CARD32 saveDSPASIZE;
    CARD32 saveDSPAPOS;
    CARD32 saveDSPABASE;
    CARD32 saveFPB0;
@@ -401,6 +402,7 @@ typedef struct _I830Rec {
    CARD32 saveVBLANK_B;
    CARD32 saveVSYNC_B;
    CARD32 saveDSPBSTRIDE;
+   CARD32 saveDSPBSIZE;
    CARD32 saveDSPBPOS;
    CARD32 saveDSPBBASE;
    CARD32 saveADPA;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index f3bc682..ede9cb8 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3562,6 +3562,7 @@ SaveHWState(ScrnInfoPtr pScrn)
    pI830->saveVBLANK_A = INREG(VBLANK_A);
    pI830->saveVSYNC_A = INREG(VSYNC_A);
    pI830->saveDSPASTRIDE = INREG(DSPASTRIDE);
+   pI830->saveDSPASIZE = INREG(DSPASIZE);
    pI830->saveDSPAPOS = INREG(DSPAPOS);
    pI830->saveDSPABASE = INREG(DSPABASE);
 
@@ -3575,6 +3576,7 @@ SaveHWState(ScrnInfoPtr pScrn)
    pI830->saveVBLANK_B = INREG(VBLANK_B);
    pI830->saveVSYNC_B = INREG(VSYNC_B);
    pI830->saveDSPBSTRIDE = INREG(DSPBSTRIDE);
+   pI830->saveDSPBSIZE = INREG(DSPBSIZE);
    pI830->saveDSPBPOS = INREG(DSPBPOS);
    pI830->saveDSPBBASE = INREG(DSPBBASE);
 
@@ -3733,6 +3735,7 @@ RestoreHWState(ScrnInfoPtr pScrn)
    OUTREG(VBLANK_A, pI830->saveVBLANK_A);
    OUTREG(VSYNC_A, pI830->saveVSYNC_A);
    OUTREG(DSPASTRIDE, pI830->saveDSPASTRIDE);
+   OUTREG(DSPASIZE, pI830->saveDSPASIZE);
    OUTREG(DSPAPOS, pI830->saveDSPAPOS);
    OUTREG(DSPABASE, pI830->saveDSPABASE);
    OUTREG(PIPEASRC, pI830->savePIPEASRC);
@@ -3747,6 +3750,7 @@ RestoreHWState(ScrnInfoPtr pScrn)
    OUTREG(VBLANK_B, pI830->saveVBLANK_B);
    OUTREG(VSYNC_B, pI830->saveVSYNC_B);
    OUTREG(DSPBSTRIDE, pI830->saveDSPBSTRIDE);
+   OUTREG(DSPBSIZE, pI830->saveDSPBSIZE);
    OUTREG(DSPBPOS, pI830->saveDSPBPOS);
    OUTREG(DSPBBASE, pI830->saveDSPBBASE);
    OUTREG(PIPEBSRC, pI830->savePIPEBSRC);
diff-tree 12ce799818722473dde2f82739d50ba4ec7f6ecd (from 585cc5f256b8e91460414a26409d0e484a86718c)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Fri Mar 3 15:38:31 2006 -0800

    Add some untested debugging code to for helping figure out VT switch issues.

diff --git a/src/Makefile.am b/src/Makefile.am
index 16e9812..f0f6691 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -46,6 +46,8 @@ i810_drv_la_SOURCES = \
          i830_accel.c \
          i830_common.h \
          i830_cursor.c \
+	 i830_debug.c \
+	 i830_debug.h \
          i830_dga.c \
 	 i830_display.c \
 	 i830_display.h \
diff --git a/src/i830_debug.c b/src/i830_debug.c
new file mode 100644
index 0000000..37c0e04
--- /dev/null
+++ b/src/i830_debug.c
@@ -0,0 +1,100 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "xf86_ansic.h"
+#include "i830.h"
+
+/* XXX: What was the syntax for sticking quotes around the "reg" argument? */
+#define DEFINEREG(reg) \
+	{ reg, NULL, 0 }
+
+static struct i830SnapshotRec {
+    int reg;
+    char *name;
+    CARD32 regval;
+} i830_snapshot[] = {
+    DEFINEREG(ADPA),
+    DEFINEREG(LVDS),
+    DEFINEREG(DVOA),
+    DEFINEREG(DVOB),
+    DEFINEREG(DVOC),
+    DEFINEREG(DVO_ENABLE),
+    DEFINEREG(DVOA_SRCDIM),
+    DEFINEREG(DVOB_SRCDIM),
+    DEFINEREG(DVOC_SRCDIM),
+
+    DEFINEREG(PP_CONTROL),
+    DEFINEREG(PP_STATUS),
+    DEFINEREG(PFIT_CONTROL),
+    DEFINEREG(PFIT_PGM_RATIOS),
+    DEFINEREG(PORT_HOTPLUG_EN),
+    DEFINEREG(PORT_HOTPLUG_STAT),
+
+    DEFINEREG(DSPACNTR),
+    DEFINEREG(DSPASTRIDE),
+    DEFINEREG(DSPAPOS),
+    DEFINEREG(DSPASIZE),
+    DEFINEREG(DSPABASE),
+    DEFINEREG(PIPEACONF),
+    DEFINEREG(PIPEASRC),
+
+    DEFINEREG(FPA0),
+    DEFINEREG(FPA1),
+    DEFINEREG(DPLL_A),
+    DEFINEREG(HTOTAL_A),
+    DEFINEREG(HBLANK_A),
+    DEFINEREG(HSYNC_A),
+    DEFINEREG(VTOTAL_A),
+    DEFINEREG(VBLANK_A),
+    DEFINEREG(VSYNC_A),
+
+    DEFINEREG(DSPBCNTR),
+    DEFINEREG(DSPBSTRIDE),
+    DEFINEREG(DSPBPOS),
+    DEFINEREG(DSPBSIZE),
+    DEFINEREG(DSPBBASE),
+    DEFINEREG(PIPEBCONF),
+    DEFINEREG(PIPEBSRC),
+
+    DEFINEREG(FPB0),
+    DEFINEREG(FPB1),
+    DEFINEREG(DPLL_B),
+    DEFINEREG(HTOTAL_B),
+    DEFINEREG(HBLANK_B),
+    DEFINEREG(HSYNC_B),
+    DEFINEREG(VTOTAL_B),
+    DEFINEREG(VBLANK_B),
+    DEFINEREG(VSYNC_B),
+
+    { 0, NULL, 0}
+};
+#undef DEFINEREG
+#define NUM_I830_SNAPSHOTREGS (sizeof(i830_snapshot) / sizeof(i830_snapshot[0]))
+
+void i830TakeRegSnapshot(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    int i;
+
+    for (i = 0; i < NUM_I830_SNAPSHOTREGS; i++) {
+	i830_snapshot[i].regval = INREG(i830_snapshot[i].reg);
+    }
+}
+
+void i830CompareRegsToSnapshot(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    int i;
+
+    for (i = 0; i < NUM_I830_SNAPSHOTREGS; i++) {
+	CARD32 val = INREG(i830_snapshot[i].reg);
+	if (i830_snapshot[i].regval != val) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		       "Register 0x%x (%s) changed from 0x%08x to 0x%08x\n",
+		       i830_snapshot[i].reg, i830_snapshot[i].name,
+		       (int)i830_snapshot[i].regval, (int)val);
+	}
+    }
+}
diff --git a/src/i830_debug.h b/src/i830_debug.h
new file mode 100644
index 0000000..c02ff25
--- /dev/null
+++ b/src/i830_debug.h
@@ -0,0 +1,2 @@
+void i830TakeRegSnapshot(ScrnInfoPtr pScrn);
+void i830CompareRegsToSnapshot(ScrnInfoPtr pScrn);
diff-tree 585cc5f256b8e91460414a26409d0e484a86718c (from 33c62e8e654fa2228bc3fd31ec0fe010703f363a)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Fri Mar 3 10:37:26 2006 -0800

    Add more integrated LVDS support code.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index 8785b06..c9b3f5a 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -664,6 +664,22 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define PP_CONTROL	0x61204
 # define POWER_TARGET_ON			(1 << 0)
 
+#define PFIT_CONTROL	0x61230
+# define PFIT_ENABLE				(1 << 31)
+# define VERT_INTERP_DISABLE			(0 << 10)
+# define VERT_INTERP_BILINEAR			(1 << 10)
+# define VERT_INTERP_MASK			(3 << 10)
+# define VERT_AUTO_SCALE			(1 << 9)
+# define HORIZ_INTERP_DISABLE			(0 << 6)
+# define HORIZ_INTERP_BILINEAR			(1 << 6)
+# define HORIZ_INTERP_MASK			(3 << 6)
+# define HORIZ_AUTO_SCALE			(1 << 5)
+# define PANEL_8TO6_DITHER_ENABLE		(1 << 3)
+
+#define PFIT_PGM_RATIOS	0x61234
+# define PFIT_VERT_SCALE_MASK			0xfff00000
+# define PFIT_HORIZ_SCALE_MASK			0x0000fff0
+
 #define DPLL_A		0x06014
 #define DPLL_B		0x06018
 # define DPLL_VCO_ENABLE			(1 << 31)
diff --git a/src/i830_display.c b/src/i830_display.c
index 354f20b..cfff47e 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -438,6 +438,17 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	temp = INREG(PIPEBCONF);
 	OUTREG(PIPEBCONF, temp & ~PIPEBCONF_ENABLE);
 
+	if (outputs & PIPE_LCD_ACTIVE) {
+	    /* Disable the PLL before messing with LVDS enable */
+	    OUTREG(FPB0, fp & ~DPLL_VCO_ENABLE);
+
+	    /* LVDS must be powered on before PLL is enabled and before power
+	     * sequencing the panel.
+	     */
+	    temp = INREG(LVDS);
+	    OUTREG(LVDS, temp | LVDS_PORT_EN | LVDS_PIPEB_SELECT);
+	}
+
 	OUTREG(FPB0, fp);
 	OUTREG(DPLL_B, dpll);
 	OUTREG(HTOTAL_B, htot);
@@ -459,8 +470,15 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	/* And then turn the plane on */
 	OUTREG(DSPBCNTR, dspcntr);
 
-	if (outputs & PIPE_LCD_ACTIVE)
+	if (outputs & PIPE_LCD_ACTIVE) {
+	    /* Enable automatic panel scaling so that non-native modes fill the
+	     * screen.
+	     */
+	    /* XXX: Allow (auto-?) enabling of 8-to-6 dithering */
+	    OUTREG(PFIT_CONTROL, PFIT_ENABLE | VERT_AUTO_SCALE |
+		   HORIZ_AUTO_SCALE);
 	    i830SetLVDSPanelPower(pScrn, TRUE);
+	}
     }
 
     if (outputs & PIPE_CRT_ACTIVE)
diff-tree 33c62e8e654fa2228bc3fd31ec0fe010703f363a (from 7f4dc09dcafc7f0423b7f3e970a0b19fbbf515dd)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Thu Mar 2 17:53:38 2006 -0800

    Change the order of reg writes for restore, possibly increasing chances of
    success.  Also save and restore ADPA.

diff --git a/src/i830.h b/src/i830.h
index 199416a..321827a 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -403,6 +403,7 @@ typedef struct _I830Rec {
    CARD32 saveDSPBSTRIDE;
    CARD32 saveDSPBPOS;
    CARD32 saveDSPBBASE;
+   CARD32 saveADPA;
 
 } I830Rec;
 
diff --git a/src/i830_driver.c b/src/i830_driver.c
index f418439..f3bc682 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3578,6 +3578,8 @@ SaveHWState(ScrnInfoPtr pScrn)
    pI830->saveDSPBPOS = INREG(DSPBPOS);
    pI830->saveDSPBBASE = INREG(DSPBBASE);
 
+   pI830->saveADPA = INREG(ADPA);
+
    if (I830IsPrimary(pScrn) && pI830->pipe != pI830->origPipe)
       SetBIOSPipe(pScrn, pI830->origPipe);
    else
@@ -3733,6 +3735,7 @@ RestoreHWState(ScrnInfoPtr pScrn)
    OUTREG(DSPASTRIDE, pI830->saveDSPASTRIDE);
    OUTREG(DSPAPOS, pI830->saveDSPAPOS);
    OUTREG(DSPABASE, pI830->saveDSPABASE);
+   OUTREG(PIPEASRC, pI830->savePIPEASRC);
 
    OUTREG(FPB0, pI830->saveFPB0);
    OUTREG(FPB1, pI830->saveFPB1);
@@ -3746,13 +3749,15 @@ RestoreHWState(ScrnInfoPtr pScrn)
    OUTREG(DSPBSTRIDE, pI830->saveDSPBSTRIDE);
    OUTREG(DSPBPOS, pI830->saveDSPBPOS);
    OUTREG(DSPBBASE, pI830->saveDSPBBASE);
+   OUTREG(PIPEBSRC, pI830->savePIPEBSRC);
 
-   OUTREG(DSPACNTR, pI830->saveDSPACNTR);
-   OUTREG(DSPBCNTR, pI830->saveDSPBCNTR);
    OUTREG(PIPEACONF, pI830->savePIPEACONF);
    OUTREG(PIPEBCONF, pI830->savePIPEBCONF);
-   OUTREG(PIPEASRC, pI830->savePIPEASRC);
-   OUTREG(PIPEBSRC, pI830->savePIPEBSRC);
+
+   OUTREG(DSPACNTR, pI830->saveDSPACNTR);
+   OUTREG(DSPBCNTR, pI830->saveDSPBCNTR);
+
+   OUTREG(ADPA, pI830->saveADPA);
 
    return TRUE;
 }
diff-tree 7f4dc09dcafc7f0423b7f3e970a0b19fbbf515dd (from f3ec8653ab4c9b26d249bcf4393326de37ac8321)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Thu Mar 2 15:55:18 2006 -0800

    Remove some dead VBE code.

diff --git a/TODO b/TODO
index ef2bab6..17e1449 100644
--- a/TODO
+++ b/TODO
@@ -1,2 +1,3 @@
 - licensing of new files
 - Figure out what exactly doublescan, interlace mean, and see if we support them.
+- Remove VbeModeInfoData
diff --git a/src/i830.h b/src/i830.h
index a02bda7..199416a 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -95,8 +95,6 @@ typedef struct _VESARec {
    CARD32 *savedPal;
    int savedScanlinePitch;
    xf86MonPtr monitor;
-   /* Don't try to set the refresh rate for any modes. */
-   Bool useDefaultRefresh;
    /* display start */
    int x, y;
 } VESARec, *VESAPtr;
@@ -337,9 +335,6 @@ typedef struct _I830Rec {
    CARD32 saveSWF0;
    CARD32 saveSWF4;
 
-   /* Use BIOS call 0x5f05 to set the refresh rate. */
-   Bool useExtendedRefresh;
-
    Bool checkDevices;
    int monitorSwitch;
    int operatingDevices;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 26ad98d..f418439 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -699,88 +699,6 @@ I830GetBestRefresh(ScrnInfoPtr pScrn, in
 
 #if 0
 static int
-SetRefreshRate(ScrnInfoPtr pScrn, int mode, int refresh)
-{
-   vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
-   int i = I830GetBestRefresh(pScrn, refresh);
-
-   DPRINTF(PFX, "SetRefreshRate: mode 0x%x, refresh: %d\n", mode, refresh);
-
-   DPRINTF(PFX, "Setting refresh rate to %dHz for mode 0x%02x\n",
-	   i830refreshes[i], mode & 0xff);
-
-   /* Only 8-bit mode numbers are supported. */
-   if (mode & 0x100)
-      return 0;
-
-   pVbe->pInt10->num = 0x10;
-   pVbe->pInt10->ax = 0x5f05;
-   pVbe->pInt10->bx = mode & 0xff;
-
-   pVbe->pInt10->cx = 1 << i;
-   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
-   if (Check5fStatus(pScrn, 0x5f05, pVbe->pInt10->ax))
-      return i830refreshes[i];
-   else
-      return 0;
-}
-
-static Bool
-SetPowerStatus(ScrnInfoPtr pScrn, int mode)
-{
-   vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
-
-   pVbe->pInt10->num = 0x10;
-   pVbe->pInt10->ax = 0x5f64;
-   pVbe->pInt10->bx = 0x0800 | mode;
-   pVbe->pInt10->cx = 0x0000;
-
-   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
-   if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax))
-      return TRUE;
-  
-   return FALSE;
-}
-#endif
-
-static Bool
-GetModeSupport(ScrnInfoPtr pScrn, int modePipeA, int modePipeB,
-	       int devicesPipeA, int devicesPipeB, int *maxBandwidth,
-	       int *bandwidthPipeA, int *bandwidthPipeB)
-{
-   vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
-
-   DPRINTF(PFX, "GetModeSupport: modes 0x%x, 0x%x, devices: 0x%x, 0x%x\n",
-	   modePipeA, modePipeB, devicesPipeA, devicesPipeB);
-
-   /* Only 8-bit mode numbers are supported. */
-   if ((modePipeA & 0x100) || (modePipeB & 0x100))
-      return FALSE;
-
-   pVbe->pInt10->num = 0x10;
-   pVbe->pInt10->ax = 0x5f28;
-   pVbe->pInt10->bx = (modePipeA & 0xff) | ((modePipeB & 0xff) << 8);
-   if ((devicesPipeA & 0x80) || (devicesPipeB & 0x80))
-      pVbe->pInt10->cx = 0x8000;
-   else
-      pVbe->pInt10->cx = (devicesPipeA & 0xff) | ((devicesPipeB & 0xff) << 8);
-
-   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
-   if (Check5fStatus(pScrn, 0x5f28, pVbe->pInt10->ax)) {
-      if (maxBandwidth)
-	 *maxBandwidth = pVbe->pInt10->cx;
-      if (bandwidthPipeA)
-	 *bandwidthPipeA = pVbe->pInt10->dx & 0xffff;
-      /* XXX For XFree86 4.2.0 and earlier, ->dx is truncated to 16 bits. */
-      if (bandwidthPipeB)
-	 *bandwidthPipeB = (pVbe->pInt10->dx >> 16) & 0xffff;
-      return TRUE;
-   } else
-      return FALSE;
-}
-
-#if 0
-static int
 GetLFPCompMode(ScrnInfoPtr pScrn)
 {
    vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
@@ -3106,49 +3024,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
    }
 #endif
 
-   pI830->useExtendedRefresh = FALSE;
-
-   if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone) {
-      int pipe =
-	  (pI830->operatingDevices >> PIPE_SHIFT(pI830->pipe)) & PIPE_ACTIVE_MASK;
-      if (pipe & ~PIPE_CRT_ACTIVE) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
-		    "A non-CRT device is attached to pipe %c.\n"
-		    "\tNo refresh rate overrides will be attempted.\n",
-		    PIPE_NAME(pI830->pipe));
-	 pI830->vesa->useDefaultRefresh = TRUE;
-      }
-      /*
-       * Some desktop platforms might not have 0x5f05, so useExtendedRefresh
-       * would need to be set to FALSE for those cases.
-       */
-      if (!pI830->vesa->useDefaultRefresh) 
-	 pI830->useExtendedRefresh = TRUE;
-   } else {
-      for (i = 0; i < pI830->availablePipes; i++) {
-         int pipe =
-	  (pI830->operatingDevices >> PIPE_SHIFT(i)) & PIPE_ACTIVE_MASK;
-         if (pipe & ~PIPE_CRT_ACTIVE) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
-		    "A non-CRT device is attached to pipe %c.\n"
-		    "\tNo refresh rate overrides will be attempted.\n",
-		    PIPE_NAME(i));
-	    pI830->vesa->useDefaultRefresh = TRUE;
-         }
-         /*
-          * Some desktop platforms might not have 0x5f05, so useExtendedRefresh
-          * would need to be set to FALSE for those cases.
-          */
-         if (!pI830->vesa->useDefaultRefresh) 
-	    pI830->useExtendedRefresh = TRUE;
-      }
-   }
-
-   if (pI830->useExtendedRefresh && !pI830->vesa->useDefaultRefresh) {
-      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		 "Will use BIOS call 0x5f05 to set refresh rates for CRTs.\n");
-   }
-
    /*
     * Limit videoram available for mode selection to what the video
     * BIOS can see.
@@ -3403,18 +3278,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
    SetPipeAccess(pScrn);
    I830PrintModes(pScrn);
 
-   if (!pI830->vesa->useDefaultRefresh) {
-      /*
-       * This sets the parameters for the VBE modes according to the best
-       * usable parameters from the Monitor sections modes (usually the
-       * default VESA modes), allowing for better than default refresh rates.
-       * This only works for VBE 3.0 and later.  Also, we only do this
-       * if there are no non-CRT devices attached.
-       */
-      SetPipeAccess(pScrn);
-      I830SetModeParameters(pScrn, pI830->pVbe);
-   }
-
    /* PreInit shouldn't leave any state changes, so restore this. */
    RestoreBIOSMemSize(pScrn);
 
@@ -3798,14 +3661,6 @@ RestoreHWState(ScrnInfoPtr pScrn)
 
    pVesa = pI830->vesa;
 
-   /*
-    * Workaround for text mode restoration with some flat panels.
-    * Temporarily program a 640x480 mode before switching back to
-    * text mode.
-    */
-   if (pVesa->useDefaultRefresh)
-      I830Set640x480(pScrn);
-
    if (pVesa->state && pVesa->stateSize) {
       CARD16 imr = INREG16(IMR);
       CARD16 ier = INREG16(IER);
@@ -3838,9 +3693,6 @@ RestoreHWState(ScrnInfoPtr pScrn)
 		 "the saved state\n");
 #if 0
       I830VESASetVBEMode(pScrn, pVesa->stateMode, NULL);
-      if (!pVesa->useDefaultRefresh && pI830->useExtendedRefresh) {
-         SetRefreshRate(pScrn, pVesa->stateMode, pVesa->stateRefresh);
-      }
 #endif
    }
    if (pVesa->savedScanlinePitch)
@@ -3905,197 +3757,6 @@ RestoreHWState(ScrnInfoPtr pScrn)
    return TRUE;
 }
 
-#if 0
-static void I830SetCloneVBERefresh(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock * block, int refresh)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   DisplayModePtr p = NULL;
-   int RefreshRate;
-   int clock;
-
-   /* Search for our mode and get a refresh to match */
-   for (p = pScrn->monitor->Modes; p != NULL; p = p->next) {
-      if ((p->HDisplay != pI830->CloneHDisplay) ||
-          (p->VDisplay != pI830->CloneVDisplay) ||
-          (p->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2)))
-         continue;
-      RefreshRate = ((double)(p->Clock * 1000) /
-                     (double)(p->HTotal * p->VTotal)) * 100;
-      /* we could probably do better here that 2Hz boundaries */
-      if (RefreshRate > (refresh - 200) && RefreshRate < (refresh + 200)) {
-         block->HorizontalTotal = p->HTotal;
-         block->HorizontalSyncStart = p->HSyncStart;
-         block->HorizontalSyncEnd = p->HSyncEnd;
-         block->VerticalTotal = p->VTotal;
-         block->VerticalSyncStart = p->VSyncStart;
-         block->VerticalSyncEnd = p->VSyncEnd;
-         block->Flags = ((p->Flags & V_NHSYNC) ? CRTC_NHSYNC : 0) |
-                        ((p->Flags & V_NVSYNC) ? CRTC_NVSYNC : 0);
-         block->PixelClock = p->Clock * 1000;
-         /* XXX May not have this. */
-         clock = VBEGetPixelClock(pI830->pVbe, mode, block->PixelClock);
-#ifdef DEBUG
-         ErrorF("Setting clock %.2fMHz, closest is %.2fMHz\n",
-                    (double)data->block->PixelClock / 1000000.0, 
-                    (double)clock / 1000000.0);
-#endif
-         if (clock)
-            block->PixelClock = clock;
-         block->RefreshRate = RefreshRate;
-         return;
-      }
-   }
-}
-
-static Bool
-I830VESASetVBEMode(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock * block)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   Bool ret = FALSE;
-   int Mon;
-
-   DPRINTF(PFX, "Setting mode 0x%.8x\n", mode);
-
-#if 0
-   /* Clear the framebuffer (could do this with VBIOS call) */
-   if (I830IsPrimary(pScrn))
-      memset(pI830->FbBase + pI830->FrontBuffer.Start, 0,
-	  pScrn->virtualY * pI830->displayWidth * pI830->cpp);
-   else
-      memset(pI830->FbBase + pI830->FrontBuffer2.Start, 0,
-	  pScrn->virtualY * pI830->displayWidth * pI830->cpp);
-#endif
-
-   if (pI830->Clone && pI830->CloneHDisplay && pI830->CloneVDisplay &&
-       !pI830->preinit && !pI830->closing) {
-      VbeCRTCInfoBlock newblock;
-      int newmode = mode;
-
-      if (pI830->pipe == 1)
-         Mon = pI830->MonType1;
-      else
-         Mon = pI830->MonType2;
-
-      SetBIOSPipe(pScrn, !pI830->pipe);
-
-      /* Now recheck refresh operations we can use */
-      pI830->useExtendedRefresh = FALSE;
-      pI830->vesa->useDefaultRefresh = FALSE;
-
-      if (Mon != PIPE_CRT) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		    "A non-CRT device is attached to Clone pipe %c.\n"
-		    "\tNo refresh rate overrides will be attempted (0x%x).\n",
-		    PIPE_NAME(!pI830->pipe), newmode);
-	 pI830->vesa->useDefaultRefresh = TRUE;
-      }
-      /*
-       * Some desktop platforms might not have 0x5f05, so useExtendedRefresh
-       * would need to be set to FALSE for those cases.
-       */
-      if (!pI830->vesa->useDefaultRefresh) 
-	 pI830->useExtendedRefresh = TRUE;
-
-      newmode |= 1 << 11;
-      if (pI830->vesa->useDefaultRefresh)
-            newmode &= ~(1 << 11);
-
-      if (!SetRefreshRate(pScrn, newmode, 60)) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		    "BIOS call 0x5f05 not supported on Clone Head, "
-		    "setting refresh with VBE 3 method.\n");
-	 pI830->useExtendedRefresh = FALSE;
-      }
-
-      if (!pI830->vesa->useDefaultRefresh) {
-         I830SetCloneVBERefresh(pScrn, newmode, &newblock, pI830->CloneRefresh * 100);
-
-         if (!VBESetVBEMode(pI830->pVbe, newmode, &newblock)) {
-            if (!VBESetVBEMode(pI830->pVbe, (newmode & ~(1 << 11)), NULL))
-               xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		 "Failed to set mode for Clone head.\n");
-         } else {
-            xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		 "Setting refresh on clone head with VBE 3 method.\n");
-            pI830->useExtendedRefresh = FALSE;
-         }
-      } else {
-         if (!VBESetVBEMode(pI830->pVbe, (newmode & ~(1 << 11)), NULL))
-            xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		 "Failed to set mode for Clone head.\n");
-      }
-
-      if (pI830->useExtendedRefresh && !pI830->vesa->useDefaultRefresh) {
-         if (!SetRefreshRate(pScrn, newmode, pI830->CloneRefresh))
-	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		    "Failed to set refresh rate to %dHz on Clone head.\n",
-		    pI830->CloneRefresh);
-         else
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		    "Set refresh rate to %dHz on Clone head.\n",
-		    pI830->CloneRefresh);
-      }
-      SetPipeAccess(pScrn);
-   }
-
-   if (pI830->pipe == 0)
-      Mon = pI830->MonType1;
-   else
-      Mon = pI830->MonType2;
-
-   /* Now recheck refresh operations we can use */
-   pI830->useExtendedRefresh = FALSE;
-   pI830->vesa->useDefaultRefresh = FALSE;
-
-   if (Mon != PIPE_CRT)
-      pI830->vesa->useDefaultRefresh = TRUE;
-
-   mode |= 1 << 11;
-   if (pI830->vesa->useDefaultRefresh)
-      mode &= ~(1 << 11);
-   /*
-    * Some desktop platforms might not have 0x5f05, so useExtendedRefresh
-    * would need to be set to FALSE for those cases.
-    */
-   if (!pI830->vesa->useDefaultRefresh) 
-      pI830->useExtendedRefresh = TRUE;
-
-   if (!SetRefreshRate(pScrn, mode, 60)) {
-      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		    "BIOS call 0x5f05 not supported, "
-		    "setting refresh with VBE 3 method.\n");
-      pI830->useExtendedRefresh = FALSE;
-   }
-
-   if (!pI830->vesa->useDefaultRefresh && block) {
-      ret = VBESetVBEMode(pI830->pVbe, mode, block);
-      if (!ret)
-         ret = VBESetVBEMode(pI830->pVbe, (mode & ~(1 << 11)), NULL);
-      else {
-         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		 "Setting refresh with VBE 3 method.\n");
-	 pI830->useExtendedRefresh = FALSE;
-      }
-   } else {
-      ret = VBESetVBEMode(pI830->pVbe, (mode & ~(1 << 11)), NULL);
-   }
-
-   /* Might as well bail now if we've failed */
-   if (!ret) return FALSE;
-
-   if (pI830->useExtendedRefresh && !pI830->vesa->useDefaultRefresh && block) {
-      if (!SetRefreshRate(pScrn, mode, block->RefreshRate / 100)) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		    "Failed to set refresh rate to %dHz.\n",
-		    block->RefreshRate / 100);
-	 pI830->useExtendedRefresh = FALSE;
-      }
-   }
-
-   return ret;
-}
-#endif
-
 static void
 InitRegisterRec(ScrnInfoPtr pScrn)
 {
@@ -5086,9 +4747,6 @@ I830DetectMonitorChange(ScrnInfoPtr pScr
    xf86PruneDriverModes(pScrn);
    I830PrintModes(pScrn);
 
-   if (!pI830->vesa->useDefaultRefresh)
-      I830SetModeParameters(pScrn, pI830->pVbe);
-
    /* Now check if the previously used mode is o.k. for the current monitor.
     * This allows VT switching to continue happily when not disconnecting
     * and reconnecting monitors */
diff-tree f3ec8653ab4c9b26d249bcf4393326de37ac8321 (from 84fc3971d76f78546a0bb7dd57dba52dd893a921)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Thu Mar 2 14:31:39 2006 -0800

    Include config.h, fixing many issues with reading from pI830.

diff --git a/src/i830_display.c b/src/i830_display.c
index 741dcd2..354f20b 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -1,3 +1,7 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include "xf86.h"
 #include "xf86_ansic.h"
 #include "i830.h"
diff-tree 84fc3971d76f78546a0bb7dd57dba52dd893a921 (from aca0f942f377d997c5c0b5be790ee7f255d6e046)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Thu Mar 2 13:35:40 2006 -0800

    Turn off panel power before poking pipe B, and turn it back on if we're doing
    LVDS.  Also, refuse to do LVDS on pipe A, as the docs say you can't.

diff --git a/src/i830_display.c b/src/i830_display.c
index 9a5a9ca..741dcd2 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -1,6 +1,7 @@
 #include "xf86.h"
 #include "xf86_ansic.h"
 #include "i830.h"
+#include "i830_display.h"
 
 static int i830_clock(int refclk, int m1, int m2, int n, int p1, int p2)
 {
@@ -284,6 +285,11 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 		   "Can't enable a TV and any other output on the same pipe\n");
 	return FALSE;
     }
+    if (pipe == 0 && (outputs & PIPE_LCD_ACTIVE)) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "Can't support LVDS on pipe A\n");
+	return FALSE;
+    }
 
     ok = i830FindBestPLL(pScrn, outputs, pMode->Clock, refclk, &m1, &m2, &n,
 			 &p1, &p2);
@@ -412,6 +418,11 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	/* And then turn the plane on */
 	OUTREG(DSPACNTR, dspcntr);
     } else {
+	/* Always make sure the LVDS is off before we play with DPLLs and pipe
+	 * configuration.
+	 */
+	i830SetLVDSPanelPower(pScrn, FALSE);
+
 	/* First, disable display planes */
 	temp = INREG(DSPBCNTR);
 	OUTREG(DSPBCNTR, temp & ~DISPLAY_PLANE_ENABLE);
@@ -443,6 +454,9 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 
 	/* And then turn the plane on */
 	OUTREG(DSPBCNTR, dspcntr);
+
+	if (outputs & PIPE_LCD_ACTIVE)
+	    i830SetLVDSPanelPower(pScrn, TRUE);
     }
 
     if (outputs & PIPE_CRT_ACTIVE)
diff-tree aca0f942f377d997c5c0b5be790ee7f255d6e046 (from df6347139bc9de22af981f776d711ac9d44fad1c)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Thu Mar 2 13:31:51 2006 -0800

    Fix prototype for i830DetectCRT.

diff --git a/src/i830_display.h b/src/i830_display.h
index 946e418..101d65b 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -1,4 +1,4 @@
 Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
-Bool i830DetectCRT(ScreenPtr pScrn);
+Bool i830DetectCRT(ScrnInfoPtr pScrn);
 void i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on);
 void i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y);
diff-tree df6347139bc9de22af981f776d711ac9d44fad1c (from 8e819ced8397f0330fd44efa60fef89bd10ff70e)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Thu Mar 2 12:52:19 2006 -0800

    Use DISPPLANE_32BPP_NO_ALPHA for depth 24, else the empty alpha channel results
    in a black display plane.

diff --git a/src/i830_display.c b/src/i830_display.c
index 7d01c58..9a5a9ca 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -358,7 +358,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	    dspcntr |= DISPPLANE_15_16BPP;
 	break;
     case 32:
-	dspcntr |= DISPPLANE_32BPP;
+	dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
 	break;
     default:
 	FatalError("unknown display bpp\n");
diff-tree 8e819ced8397f0330fd44efa60fef89bd10ff70e (from ee2410b965321e3d9d64fc500fdcfa6d6dc3a039)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Thu Mar 2 11:55:00 2006 -0800

    It appears from the specs that you have to wait for vblank after disabling the
    plane, not the pipe.

diff --git a/src/i830_display.c b/src/i830_display.c
index d4c144f..7d01c58 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -384,13 +384,13 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	temp = INREG(DSPACNTR);
 	OUTREG(DSPACNTR, temp & ~DISPLAY_PLANE_ENABLE);
 
+	/* Wait for vblank for the disable to take effect */
+	i830WaitForVblank(pScrn);
+
 	/* Next, disable display pipes */
 	temp = INREG(PIPEACONF);
 	OUTREG(PIPEACONF, temp & ~PIPEACONF_ENABLE);
 
-	/* Wait for vblank for the disable to take effect */
-	i830WaitForVblank(pScrn);
-
 	OUTREG(FPA0, fp);
 	OUTREG(DPLL_A, dpll);
 	OUTREG(HTOTAL_A, htot);
@@ -416,13 +416,13 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	temp = INREG(DSPBCNTR);
 	OUTREG(DSPBCNTR, temp & ~DISPLAY_PLANE_ENABLE);
 
+	/* Wait for vblank for the disable to take effect */
+	i830WaitForVblank(pScrn);
+
 	/* Next, disable display pipes */
 	temp = INREG(PIPEBCONF);
 	OUTREG(PIPEBCONF, temp & ~PIPEBCONF_ENABLE);
 
-	/* Wait for vblank for the disable to take effect */
-	i830WaitForVblank(pScrn);
-
 	OUTREG(FPB0, fp);
 	OUTREG(DPLL_B, dpll);
 	OUTREG(HTOTAL_B, htot);
diff-tree ee2410b965321e3d9d64fc500fdcfa6d6dc3a039 (from 980fb78e759b752a6cae3c87d188c50ab131ba80)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Thu Mar 2 11:43:41 2006 -0800

    Move display base setting to a separate function and use it from both mode setup
    and AdjustFrame.  Rename AdjustFrame to reflect the fact that it doesn't touch
    the BIOS.

diff --git a/src/i830_display.c b/src/i830_display.c
index 3c961fa..d4c144f 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -231,6 +231,25 @@ i830WaitForVblank(ScrnInfoPtr pScreen)
     usleep(20000);
 }
 
+void
+i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    unsigned long Start;
+
+    if (I830IsPrimary(pScrn))
+	Start = pI830->FrontBuffer.Start;
+    else {
+	I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
+	Start = pI8301->FrontBuffer2.Start;
+    }
+
+    if (pipe == 0)
+	OUTREG(DSPABASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
+    else
+	OUTREG(DSPBBASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
+}
+
 /**
  * Sets the given video mode on the given pipe.  Assumes that plane A feeds
  * pipe A, and plane B feeds pipe B.  Should not affect the other planes/pipes.
@@ -383,8 +402,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	OUTREG(DSPASTRIDE, pScrn->displayWidth * pI830->cpp);
 	OUTREG(DSPASIZE, dspsize);
 	OUTREG(DSPAPOS, 0);
-	/* XXX: Deal with adjustframe down here */
-	OUTREG(DSPABASE, 0); /* triggers update of display registers */
+	i830PipeSetBase(pScrn, pipe, pScrn->frameX0, pScrn->frameY0);
 	OUTREG(PIPEASRC, pipesrc);
 
 	/* Then, turn the pipe on first */
@@ -416,8 +434,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	OUTREG(DSPBSTRIDE, pScrn->displayWidth * pI830->cpp);
 	OUTREG(DSPBSIZE, dspsize);
 	OUTREG(DSPBPOS, 0);
-	/* XXX: Deal with adjustframe down here */
-	OUTREG(DSPBBASE, 0); /* triggers update of display registers */
+	i830PipeSetBase(pScrn, pipe, pScrn->frameX0, pScrn->frameY0);
 	OUTREG(PIPEBSRC, pipesrc);
 
 	/* Then, turn the pipe on first */
diff --git a/src/i830_display.h b/src/i830_display.h
index 823e27c..946e418 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -1,3 +1,4 @@
 Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
 Bool i830DetectCRT(ScreenPtr pScrn);
 void i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on);
+void i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 699d462..26ad98d 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -270,7 +270,7 @@ static OptionInfoRec I830BIOSOptions[] =
 
 static void I830DisplayPowerManagementSet(ScrnInfoPtr pScrn,
 					  int PowerManagementMode, int flags);
-static void I830BIOSAdjustFrame(int scrnIndex, int x, int y, int flags);
+static void i830AdjustFrame(int scrnIndex, int x, int y, int flags);
 static Bool I830BIOSCloseScreen(int scrnIndex, ScreenPtr pScreen);
 static Bool I830BIOSSaveScreen(ScreenPtr pScreen, int unblack);
 static Bool I830BIOSEnterVT(int scrnIndex, int flags);
@@ -4850,18 +4850,14 @@ I830BIOSScreenInit(int scrnIndex, Screen
 }
 
 static void
-I830BIOSAdjustFrame(int scrnIndex, int x, int y, int flags)
+i830AdjustFrame(int scrnIndex, int x, int y, int flags)
 {
-   ScrnInfoPtr pScrn;
+   ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
    I830Ptr pI830;
-   vbeInfoPtr pVbe;
-   unsigned long Start;
 
-   pScrn = xf86Screens[scrnIndex];
    pI830 = I830PTR(pScrn);
-   pVbe = pI830->pVbe;
 
-   DPRINTF(PFX, "I830BIOSAdjustFrame: y = %d (+ %d), x = %d (+ %d)\n",
+   DPRINTF(PFX, "i830AdjustFrame: y = %d (+ %d), x = %d (+ %d)\n",
 	   x, pI830->xoffset, y, pI830->yoffset);
 
    /* Sync the engine before adjust frame */
@@ -4870,31 +4866,9 @@ I830BIOSAdjustFrame(int scrnIndex, int x
       pI830->AccelInfoRec->NeedToSync = FALSE;
    }
 
-   if (I830IsPrimary(pScrn))
-      Start = pI830->FrontBuffer.Start;
-   else {
-      I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
-      Start = pI8301->FrontBuffer2.Start;
-   }
-
-   /* Sigh...
-    * It seems that there are quite a few Video BIOS' that get this wrong.
-    * So, we'll bypass the VBE call and hit the hardware directly.
-    */
-
-   if (pI830->Clone) {
-      if (!pI830->pipe == 0) {
-         OUTREG(DSPABASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
-      } else {
-         OUTREG(DSPBBASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
-      }
-   }
-
-   if (pI830->pipe == 0) {
-      OUTREG(DSPABASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
-   } else {
-      OUTREG(DSPBBASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
-   }
+   i830PipeSetBase(pScrn, pI830->pipe, x, y);
+   if (pI830->Clone)
+      i830PipeSetBase(pScrn, !pI830->pipe, x, y);
 }
 
 static void
@@ -5878,7 +5852,7 @@ I830CheckDevicesTimer(OsTimerPtr timer, 
             xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 			                       "Fixing display offsets.\n");
 
-            I830BIOSAdjustFrame(pScrn->pScreen->myNum, pScrn->frameX0, pScrn->frameY0, 0);
+            i830AdjustFrame(pScrn->pScreen->myNum, pScrn->frameX0, pScrn->frameY0, 0);
          }
       }
 
@@ -5903,7 +5877,7 @@ I830CheckDevicesTimer(OsTimerPtr timer, 
 
          pI830->currentMode = NULL;
          I830BIOSSwitchMode(pScrn->pScreen->myNum, pScrn->currentMode, 0);
-         I830BIOSAdjustFrame(pScrn->pScreen->myNum, pScrn->frameX0, pScrn->frameY0, 0);
+         i830AdjustFrame(pScrn->pScreen->myNum, pScrn->frameX0, pScrn->frameY0, 0);
 
          if (xf86IsEntityShared(pScrn->entityList[0])) {
 	    ScrnInfoPtr pScrn2;
@@ -5922,7 +5896,7 @@ I830CheckDevicesTimer(OsTimerPtr timer, 
 
             pI8302->currentMode = NULL;
             I830BIOSSwitchMode(pScrn2->pScreen->myNum, pScrn2->currentMode, 0);
-            I830BIOSAdjustFrame(pScrn2->pScreen->myNum, pScrn2->frameX0, pScrn2->frameY0, 0);
+            i830AdjustFrame(pScrn2->pScreen->myNum, pScrn2->frameX0, pScrn2->frameY0, 0);
 
  	    (*pScrn2->EnableDisableFBAccess) (pScrn2->pScreen->myNum, FALSE);
  	    (*pScrn2->EnableDisableFBAccess) (pScrn2->pScreen->myNum, TRUE);
@@ -5971,7 +5945,7 @@ I830InitpScrn(ScrnInfoPtr pScrn)
    pScrn->PreInit = I830BIOSPreInit;
    pScrn->ScreenInit = I830BIOSScreenInit;
    pScrn->SwitchMode = I830BIOSSwitchMode;
-   pScrn->AdjustFrame = I830BIOSAdjustFrame;
+   pScrn->AdjustFrame = i830AdjustFrame;
    pScrn->EnterVT = I830BIOSEnterVT;
    pScrn->LeaveVT = I830BIOSLeaveVT;
    pScrn->FreeScreen = I830BIOSFreeScreen;
diff-tree 980fb78e759b752a6cae3c87d188c50ab131ba80 (from 2b842c7ee3f9c33cabf16561f11bf1c3a2502d4a)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Thu Mar 2 10:49:31 2006 -0800

    Correct capitalization of i830SetMode.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 1e55656..699d462 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -5272,7 +5272,7 @@ I830BIOSEnterVT(int scrnIndex, int flags
    if (!pI830->starting)
       I830DetectMonitorChange(pScrn);
 	    
-   if (!I830SetMode(pScrn, pScrn->currentMode))
+   if (!i830SetMode(pScrn, pScrn->currentMode))
       return FALSE;
    
 #ifdef I830_XV
@@ -5342,7 +5342,7 @@ I830BIOSSwitchMode(int scrnIndex, Displa
     * are rotating, we don't need to call the mode setup again.
     */
    if (pI830->currentMode != mode) {
-      if (!I830SetMode(pScrn, mode))
+      if (!i830SetMode(pScrn, mode))
          ret = FALSE;
    }
 
@@ -5363,7 +5363,7 @@ I830BIOSSwitchMode(int scrnIndex, Displa
     * video mode here, as we'll have already re-instated the original rotation.
     */
    if (!ret) {
-      if (!I830SetMode(pScrn, pI830->currentMode)) {
+      if (!i830SetMode(pScrn, pI830->currentMode)) {
 	 xf86DrvMsg(scrnIndex, X_INFO,
 		    "Failed to restore previous mode (SwitchMode)\n");
       }
diff-tree 2b842c7ee3f9c33cabf16561f11bf1c3a2502d4a (from a09d9cf27af7016bbd9e562c7b1c338154fd3d40)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Thu Mar 2 10:08:20 2006 -0800

    Start implementing support for setting modes for multiple output devices,
    particularly LVDS.  Untested.

diff --git a/src/i830_display.c b/src/i830_display.c
index 78a44ef..3c961fa 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -19,8 +19,8 @@ i830PrintPll(char *prefix, int refclk, i
 }
 
 static Bool
-i830PllIsValid(ScrnInfoPtr pScrn, int refclk, int m1, int m2, int n, int p1,
-	       int p2)
+i830PllIsValid(ScrnInfoPtr pScrn, int outputs, int refclk, int m1, int m2,
+	       int n, int p1, int p2)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     int p, m, vco, dotclock;
@@ -38,7 +38,7 @@ i830PllIsValid(ScrnInfoPtr pScrn, int re
 	max_m = 120;
 	min_n = 3;
 	max_n = 8;
-	if (0) { /* lvds */
+	if (outputs & PIPE_LCD_ACTIVE) {
 	    min_p = 7;
 	    max_p = 98;
 	}
@@ -51,7 +51,7 @@ i830PllIsValid(ScrnInfoPtr pScrn, int re
 	max_m = 130;
 	min_n = 4;
 	max_n = 8;
-	if (0) { /* lvds */
+	if (outputs & PIPE_LCD_ACTIVE) {
 	    min_n = 3;
 	    min_m = 88;
 	}
@@ -163,8 +163,8 @@ i830ReadAndReportPLL(ScrnInfoPtr pScrn)
 #endif
 
 static Bool
-i830FindBestPLL(ScrnInfoPtr pScrn, int target, int refclk, int *outm1,
-		int *outm2, int *outn, int *outp1, int *outp2)
+i830FindBestPLL(ScrnInfoPtr pScrn, int outputs, int target, int refclk,
+		int *outm1, int *outm2, int *outn, int *outp1, int *outp2)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     int m1, m2, n, p1, p2;
@@ -183,18 +183,28 @@ i830FindBestPLL(ScrnInfoPtr pScrn, int t
 	max_m2 = 11;
     }
 
-    if (target < 200000)	/* XXX: LVDS */
-	p2 = 10;
-    else
-	p2 = 5;
+    if (outputs & PIPE_LCD_ACTIVE) {
+	if (target < 200000) /* XXX: Is this the right cutoff? */
+	    p2 = 14;
+	else
+	    p2 = 7;
+    } else {
+	if (target < 200000)
+	    p2 = 10;
+	else
+	    p2 = 5;
+    }
+
     for (m1 = min_m1; m1 <= max_m1; m1++) {
 	for (m2 = min_m2; m2 < max_m2; m2++) {
 	    for (n = 1; n <= 6; n++) {
 		for (p1 = 1; p1 <= 8; p1++) {
 		    int clock, this_err;
 
-		    if (!i830PllIsValid(pScrn, refclk, m1, m2, n, p1, p2))
+		    if (!i830PllIsValid(pScrn, outputs, refclk, m1, m2, n,
+					p1, p2)) {
 			continue;
+		    }
 
 		    clock = i830_clock(refclk, m1, m2, n, p1, p2);
 		    this_err = abs(clock - target);
@@ -235,10 +245,29 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     CARD32 pipesrc, dspsize, adpa;
     Bool ok;
     int refclk = 96000;
+    int outputs;
 
     ErrorF("Requested pix clock: %d\n", pMode->Clock);
 
-    ok = i830FindBestPLL(pScrn, pMode->Clock, refclk, &m1, &m2, &n, &p1, &p2);
+    if (pipe == 0)
+	outputs = pI830->operatingDevices & 0xff;
+    else
+	outputs = (pI830->operatingDevices >> 8) & 0xff;
+
+    if ((outputs & PIPE_LCD_ACTIVE) && (outputs & ~PIPE_LCD_ACTIVE)) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "Can't enable LVDS and non-LVDS on the same pipe\n");
+	return FALSE;
+    }
+    if (((outputs & PIPE_TV_ACTIVE) && (outputs & ~PIPE_TV_ACTIVE)) ||
+	((outputs & PIPE_TV2_ACTIVE) && (outputs & ~PIPE_TV2_ACTIVE))) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "Can't enable a TV and any other output on the same pipe\n");
+	return FALSE;
+    }
+
+    ok = i830FindBestPLL(pScrn, outputs, pMode->Clock, refclk, &m1, &m2, &n,
+			 &p1, &p2);
     if (!ok) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		   "Couldn't find PLL settings for mode!\n");
@@ -246,7 +275,11 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     }
 
     dpll = DPLL_VCO_ENABLE | DPLL_VGA_MODE_DIS;
-    dpll |= DPLLB_MODE_DAC_SERIAL; /* XXX: LVDS */
+    if (outputs & PIPE_LCD_ACTIVE)
+	dpll |= DPLLB_MODE_LVDS;
+    else
+	dpll |= DPLLB_MODE_DAC_SERIAL;
+
     dpll |= (1 << (p1 - 1)) << 16;
     switch (p2) {
     case 5:
@@ -262,7 +295,10 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
 	break;
     }
-    dpll |= PLL_REF_INPUT_DREFCLK; /* XXX: TV/LVDS */
+    if (outputs & (PIPE_TV_ACTIVE | PIPE_TV2_ACTIVE))
+	dpll |= PLL_REF_INPUT_TVCLKIN;
+    else
+	dpll |= PLL_REF_INPUT_DREFCLK;
     dpll |= SDV0_DEFAULT_MULTIPLIER;
 
     fp = (n << 16) | (m1 << 8) | m2;
@@ -287,7 +323,8 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 
     i830PrintPll("chosen", refclk, m1, m2, n, p1, p2);
     ErrorF("clock settings for chosen look %s\n",
-	   i830PllIsValid(pScrn, refclk, m1, m2, n, p1, p2) ? "good" : "bad");
+	   i830PllIsValid(pScrn, outputs, refclk, m1, m2, n, p1, p2) ?
+			  "good" : "bad");
     ErrorF("clock regs: 0x%08x, 0x%08x\n", dpll, fp);
 
     dspcntr = DISPLAY_PLANE_ENABLE;
@@ -307,10 +344,20 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     default:
 	FatalError("unknown display bpp\n");
     }
-    if (pipe == 0)
+
+    adpa = ADPA_DAC_ENABLE;
+    if (pMode->Flags & V_PHSYNC)
+	adpa |= ADPA_HSYNC_ACTIVE_HIGH;
+    if (pMode->Flags & V_PVSYNC)
+	adpa |= ADPA_VSYNC_ACTIVE_HIGH;
+    
+    if (pipe == 0) {
 	dspcntr |= DISPPLANE_SEL_PIPE_A;
-    else
+	adpa |= ADPA_PIPE_A_SELECT;
+    } else {
 	dspcntr |= DISPPLANE_SEL_PIPE_B;
+	adpa |= ADPA_PIPE_B_SELECT;
+    }
 
     /* Set up display timings and PLLs for the pipe. */
     if (pipe == 0) {
@@ -381,6 +428,9 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	OUTREG(DSPBCNTR, dspcntr);
     }
 
+    if (outputs & PIPE_CRT_ACTIVE)
+	OUTREG(ADPA, adpa);
+
     return TRUE;
 }
 
diff-tree a09d9cf27af7016bbd9e562c7b1c338154fd3d40 (from 7edb25789bd13f26134e8f5bf493897c8df322e0)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Thu Mar 2 09:05:13 2006 -0800

    Replace I830VESASetMode with simpler i830SetMode, which is all native and
    doesn't have BIOS-setup workarounds.  Multihead behavior may be wrong, and it is
    all untested.

diff --git a/src/i830_display.c b/src/i830_display.c
index aa02a42..78a44ef 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -225,8 +225,8 @@ i830WaitForVblank(ScrnInfoPtr pScreen)
  * Sets the given video mode on the given pipe.  Assumes that plane A feeds
  * pipe A, and plane B feeds pipe B.  Should not affect the other planes/pipes.
  */
-void
-i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe)
+static Bool
+i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     int m1, m2, n, p1, p2;
@@ -239,8 +239,11 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
     ErrorF("Requested pix clock: %d\n", pMode->Clock);
 
     ok = i830FindBestPLL(pScrn, pMode->Clock, refclk, &m1, &m2, &n, &p1, &p2);
-    if (!ok)
-	FatalError("Couldn't find PLL settings for mode!\n");
+    if (!ok) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "Couldn't find PLL settings for mode!\n");
+	return FALSE;
+    }
 
     dpll = DPLL_VCO_ENABLE | DPLL_VGA_MODE_DIS;
     dpll |= DPLLB_MODE_DAC_SERIAL; /* XXX: LVDS */
@@ -377,6 +380,76 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
 	/* And then turn the plane on */
 	OUTREG(DSPBCNTR, dspcntr);
     }
+
+    return TRUE;
+}
+
+/**
+ * This function sets the given mode on the active pipes.
+ */
+Bool
+i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    Bool ok = TRUE;
+    CARD32 planeA, planeB;
+#ifdef XF86DRI
+    Bool didLock = FALSE;
+#endif
+
+    DPRINTF(PFX, "i830SetMode\n");
+
+#ifdef XF86DRI
+    didLock = I830DRILock(pScrn);
+#endif
+
+    if (pI830->operatingDevices & 0xff) {
+	pI830->planeEnabled[0] = 1;
+    } else {
+	pI830->planeEnabled[0] = 0;
+    }
+
+    if (pI830->operatingDevices & 0xff00) {
+	pI830->planeEnabled[1] = 1;
+    } else {
+	pI830->planeEnabled[1] = 0;
+    }
+
+    if (pI830->planeEnabled[0]) {
+	ok = i830PipeSetMode(pScrn, pMode, 0);
+	if (!ok)
+	    goto done;
+    }
+    if (pI830->planeEnabled[1]) {
+	ok = i830PipeSetMode(pScrn, pMode, 1);
+	if (!ok)
+	    goto done;
+    }
+
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Mode bandwidth is %d Mpixel/s\n",
+	       (int)(pMode->HDisplay * pMode->VDisplay *
+		     pMode->VRefresh / 1000000));
+
+    planeA = INREG(DSPACNTR);
+    planeB = INREG(DSPBCNTR);
+
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+	       "Display plane A is now %s and connected to %s.\n",
+	       pI830->planeEnabled[0] ? "enabled" : "disabled",
+	       planeA & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A");
+    if (pI830->availablePipes == 2)
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		   "Display plane B is now %s and connected to %s.\n",
+		   pI830->planeEnabled[1] ? "enabled" : "disabled",
+		   planeB & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A");
+
+done:
+#ifdef XF86DRI
+    if (didLock)
+	I830DRIUnlock(pScrn);
+#endif
+
+    return ok;
 }
 
 Bool
diff --git a/src/i830_display.h b/src/i830_display.h
index 66811ae..823e27c 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -1,3 +1,3 @@
-void i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe);
+Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
 Bool i830DetectCRT(ScreenPtr pScrn);
 void i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 2dd545e..1e55656 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -4096,350 +4096,6 @@ I830VESASetVBEMode(ScrnInfoPtr pScrn, in
 }
 #endif
 
-static Bool
-I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-#if 0
-   vbeInfoPtr pVbe = pI830->pVbe;
-#endif
-   VbeModeInfoData *data = (VbeModeInfoData *) pMode->Private;
-   int mode, i;
-   CARD32 planeA, planeB, temp;
-   int refresh = 60;
-#ifdef XF86DRI
-   Bool didLock = FALSE;
-#endif
-
-   DPRINTF(PFX, "I830VESASetMode\n");
-
-   /* Always Enable Linear Addressing */
-   mode = data->mode | (1 << 15) | (1 << 14);
-
-#ifdef XF86DRI
-   didLock = I830DRILock(pScrn);
-#endif
-
-   if (pI830->Clone) {
-      pI830->CloneHDisplay = pMode->HDisplay;
-      pI830->CloneVDisplay = pMode->VDisplay;
-   }
-
-#ifndef MODESWITCH_RESET_STATE
-#define MODESWITCH_RESET_STATE 0
-#endif
-#if MODESWITCH_RESET_STATE
-   ResetState(pScrn, TRUE);
-#endif
-
-   SetPipeAccess(pScrn);
-
-#if 0
-   if (I830VESASetVBEMode(pScrn, mode, data->block) == FALSE) {
-      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Set VBE Mode failed!\n");
-      return FALSE;
-   }
-
-   /*
-    * The BIOS may not set a scanline pitch that would require more video
-    * memory than it's aware of.  We check for this later, and set it
-    * explicitly if necessary.
-    */
-   if (data->data->XResolution != pI830->displayWidth) {
-      if (pI830->Clone) {
-         SetBIOSPipe(pScrn, !pI830->pipe);
-         VBESetLogicalScanline(pVbe, pI830->displayWidth);
-      }
-      SetPipeAccess(pScrn);
-      VBESetLogicalScanline(pVbe, pI830->displayWidth);
-   }
-
-   if (pScrn->bitsPerPixel >= 8 && pI830->vbeInfo->Capabilities[0] & 0x01) {
-      if (pI830->Clone) {
-         SetBIOSPipe(pScrn, !pI830->pipe);
-         VBESetGetDACPaletteFormat(pVbe, 8);
-      }
-      SetPipeAccess(pScrn);
-      VBESetGetDACPaletteFormat(pVbe, 8);
-   }
-#endif
-
-   /* XXX Fix plane A with pipe A, and plane B with pipe B. */
-   planeA = INREG(DSPACNTR);
-   planeB = INREG(DSPBCNTR);
-
-   pI830->planeEnabled[0] = ((planeA & DISPLAY_PLANE_ENABLE) != 0);
-   pI830->planeEnabled[1] = ((planeB & DISPLAY_PLANE_ENABLE) != 0);
-
-   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Display plane A is %s and connected to %s.\n",
-	      pI830->planeEnabled[0] ? "enabled" : "disabled",
-	      planeA & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A");
-   if (pI830->availablePipes == 2)
-      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Display plane B is %s and connected to %s.\n",
-	      pI830->planeEnabled[1] ? "enabled" : "disabled",
-	      planeB & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A");
-   
-   if (pI830->operatingDevices & 0xff) {
-      pI830->planeEnabled[0] = 1;
-   } else { 
-      pI830->planeEnabled[0] = 0;
-   }
-
-   if (pI830->operatingDevices & 0xff00) {
-      pI830->planeEnabled[1] = 1;
-   } else {
-      pI830->planeEnabled[1] = 0;
-   }
-   
-   if (pI830->planeEnabled[0]) {
-      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabling plane A.\n");
-      planeA |= DISPLAY_PLANE_ENABLE;
-      planeA &= ~DISPPLANE_SEL_PIPE_MASK;
-      planeA |= DISPPLANE_SEL_PIPE_A;
-      OUTREG(DSPACNTR, planeA);
-      /* flush the change. */
-      temp = INREG(DSPABASE);
-      OUTREG(DSPABASE, temp);
-   }
-   if (pI830->planeEnabled[1]) {
-      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabling plane B.\n");
-      planeB |= DISPLAY_PLANE_ENABLE;
-      planeB &= ~DISPPLANE_SEL_PIPE_MASK;
-      planeB |= DISPPLANE_SEL_PIPE_B;
-      OUTREG(DSPBCNTR, planeB);
-      /* flush the change. */
-      temp = INREG(DSPBADDR);
-      OUTREG(DSPBADDR, temp);
-   }
-
-   planeA = INREG(DSPACNTR);
-   planeB = INREG(DSPBCNTR);
-   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Display plane A is now %s and connected to %s.\n",
-	      pI830->planeEnabled[0] ? "enabled" : "disabled",
-	      planeA & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A");
-   if (pI830->availablePipes == 2)
-      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Display plane B is now %s and connected to %s.\n",
-	      pI830->planeEnabled[1] ? "enabled" : "disabled",
-	      planeB & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A");
-
-   /* XXX Plane C is ignored for now (overlay). */
-
-   /*
-    * Print out the PIPEACONF and PIPEBCONF registers.
-    */
-   temp = INREG(PIPEACONF);
-   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEACONF is 0x%08lx\n", temp);
-   if (pI830->availablePipes == 2) {
-      temp = INREG(PIPEBCONF);
-      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEBCONF is 0x%08lx\n", temp);
-   }
-
-   if (xf86IsEntityShared(pScrn->entityList[0])) {
-      /* Clean this up !! */
-      if (I830IsPrimary(pScrn)) {
-         CARD32 stridereg = !pI830->pipe ? DSPASTRIDE : DSPBSTRIDE;
-         CARD32 basereg = !pI830->pipe ? DSPABASE : DSPBBASE;
-         CARD32 sizereg = !pI830->pipe ? DSPASIZE : DSPBSIZE;
-         I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
-
-         temp = INREG(stridereg);
-         if (temp / pI8301->cpp != (CARD32)(pI830->displayWidth)) {
-            xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		    "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(!pI830->pipe),
-		    (int)(temp / pI8301->cpp), pI830->displayWidth);
-	    OUTREG(stridereg, pI830->displayWidth * pI8301->cpp);
-         }
-         OUTREG(sizereg, (pMode->HDisplay - 1) | ((pMode->VDisplay - 1) << 16));
-         /* Trigger update */
-         temp = INREG(basereg);
-         OUTREG(basereg, temp);
-
-         if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) {
-            I830Ptr pI8302 = I830PTR(pI830->entityPrivate->pScrn_2);
-            stridereg = pI830->pipe ? DSPASTRIDE : DSPBSTRIDE;
-            basereg = pI830->pipe ? DSPABASE : DSPBBASE;
-            sizereg = pI830->pipe ? DSPASIZE : DSPBSIZE;
-
-            temp = INREG(stridereg);
-            if (temp / pI8302->cpp != (CARD32)(pI8302->displayWidth)) {
-	       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		    "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(pI830->pipe),
-		    (int)(temp / pI8302->cpp), pI8302->displayWidth);
-	       OUTREG(stridereg, pI8302->displayWidth * pI8302->cpp);
-            }
-            OUTREG(sizereg, (pI830->entityPrivate->pScrn_2->currentMode->HDisplay - 1) | ((pI830->entityPrivate->pScrn_2->currentMode->VDisplay - 1) << 16));
-            /* Trigger update */
-            temp = INREG(basereg);
-            OUTREG(basereg, temp);
-         }
-      } else {
-         CARD32 stridereg = pI830->pipe ? DSPASTRIDE : DSPBSTRIDE;
-         CARD32 basereg = pI830->pipe ? DSPABASE : DSPBBASE;
-         CARD32 sizereg = pI830->pipe ? DSPASIZE : DSPBSIZE;
-         I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
-         I830Ptr pI8302 = I830PTR(pI830->entityPrivate->pScrn_2);
-
-         temp = INREG(stridereg);
-         if (temp / pI8301->cpp != (CARD32)(pI8301->displayWidth)) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		    "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(pI830->pipe),
-		    (int)(temp / pI8301->cpp), pI8301->displayWidth);
-	    OUTREG(stridereg, pI8301->displayWidth * pI8301->cpp);
-         }
-         OUTREG(sizereg, (pI830->entityPrivate->pScrn_1->currentMode->HDisplay - 1) | ((pI830->entityPrivate->pScrn_1->currentMode->VDisplay - 1) << 16));
-         /* Trigger update */
-         temp = INREG(basereg);
-         OUTREG(basereg, temp);
-
-         stridereg = !pI830->pipe ? DSPASTRIDE : DSPBSTRIDE;
-         basereg = !pI830->pipe ? DSPABASE : DSPBBASE;
-         sizereg = !pI830->pipe ? DSPASIZE : DSPBSIZE;
-
-         temp = INREG(stridereg);
-         if (temp / pI8302->cpp != ((CARD32)pI8302->displayWidth)) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		    "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(!pI830->pipe),
-		    (int)(temp / pI8302->cpp), pI8302->displayWidth);
-	    OUTREG(stridereg, pI8302->displayWidth * pI8302->cpp);
-         }
-         OUTREG(sizereg, (pMode->HDisplay - 1) | ((pMode->VDisplay - 1) << 16));
-         /* Trigger update */
-         temp = INREG(basereg);
-         OUTREG(basereg, temp);
-      }
-   } else {
-      for (i = 0; i < pI830->availablePipes; i++) {
-         CARD32 stridereg = i ? DSPBSTRIDE : DSPASTRIDE;
-         CARD32 basereg = i ? DSPBBASE : DSPABASE;
-         CARD32 sizereg = i ? DSPBSIZE : DSPASIZE;
-
-         if (!pI830->planeEnabled[i])
-	    continue;
-
-         temp = INREG(stridereg);
-         if (temp / pI830->cpp != (CARD32)pI830->displayWidth) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		    "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(i),
-		    (int)(temp / pI830->cpp), pI830->displayWidth);
-	    OUTREG(stridereg, pI830->displayWidth * pI830->cpp);
-         }
-         OUTREG(sizereg, (pMode->HDisplay - 1) | ((pMode->VDisplay - 1) << 16));
-	 /* Trigger update */
-	 temp = INREG(basereg);
-	 OUTREG(basereg, temp);
-      }
-   }
-
-#if 0
-   /* Print out some CRTC/display information. */
-   temp = INREG(HTOTAL_A);
-   ErrorF("Horiz active: %d, Horiz total: %d\n", temp & 0x7ff,
-	  (temp >> 16) & 0xfff);
-   temp = INREG(HBLANK_A);
-   ErrorF("Horiz blank start: %d, Horiz blank end: %d\n", temp & 0xfff,
-	  (temp >> 16) & 0xfff);
-   temp = INREG(HSYNC_A);
-   ErrorF("Horiz sync start: %d, Horiz sync end: %d\n", temp & 0xfff,
-	  (temp >> 16) & 0xfff);
-   temp = INREG(VTOTAL_A);
-   ErrorF("Vert active: %d, Vert total: %d\n", temp & 0x7ff,
-	  (temp >> 16) & 0xfff);
-   temp = INREG(VBLANK_A);
-   ErrorF("Vert blank start: %d, Vert blank end: %d\n", temp & 0xfff,
-	  (temp >> 16) & 0xfff);
-   temp = INREG(VSYNC_A);
-   ErrorF("Vert sync start: %d, Vert sync end: %d\n", temp & 0xfff,
-	  (temp >> 16) & 0xfff);
-   temp = INREG(PIPEASRC);
-   ErrorF("Image size: %dx%d (%dx%d)\n",
-          (temp >> 16) & 0x7ff, temp & 0x7ff,
-	  (((temp >> 16) & 0x7ff) + 1), ((temp & 0x7ff) + 1));
-   ErrorF("Pixel multiply is %d\n", (planeA >> 20) & 0x3);
-   temp = INREG(DSPABASE);
-   ErrorF("Plane A start offset is %d\n", temp);
-   temp = INREG(DSPASTRIDE);
-   ErrorF("Plane A stride is %d bytes (%d pixels)\n", temp, temp / pI830->cpp);
-   temp = INREG(DSPAPOS);
-   ErrorF("Plane A position %d %d\n", temp & 0xffff, (temp & 0xffff0000) >> 16);
-   temp = INREG(DSPASIZE);
-   ErrorF("Plane A size %d %d\n", temp & 0xffff, (temp & 0xffff0000) >> 16);
-
-   /* Print out some CRTC/display information. */
-   temp = INREG(HTOTAL_B);
-   ErrorF("Horiz active: %d, Horiz total: %d\n", temp & 0x7ff,
-	  (temp >> 16) & 0xfff);
-   temp = INREG(HBLANK_B);
-   ErrorF("Horiz blank start: %d, Horiz blank end: %d\n", temp & 0xfff,
-	  (temp >> 16) & 0xfff);
-   temp = INREG(HSYNC_B);
-   ErrorF("Horiz sync start: %d, Horiz sync end: %d\n", temp & 0xfff,
-	  (temp >> 16) & 0xfff);
-   temp = INREG(VTOTAL_B);
-   ErrorF("Vert active: %d, Vert total: %d\n", temp & 0x7ff,
-	  (temp >> 16) & 0xfff);
-   temp = INREG(VBLANK_B);
-   ErrorF("Vert blank start: %d, Vert blank end: %d\n", temp & 0xfff,
-	  (temp >> 16) & 0xfff);
-   temp = INREG(VSYNC_B);
-   ErrorF("Vert sync start: %d, Vert sync end: %d\n", temp & 0xfff,
-	  (temp >> 16) & 0xfff);
-   temp = INREG(PIPEBSRC);
-   ErrorF("Image size: %dx%d (%dx%d)\n",
-          (temp >> 16) & 0x7ff, temp & 0x7ff,
-	  (((temp >> 16) & 0x7ff) + 1), ((temp & 0x7ff) + 1));
-   ErrorF("Pixel multiply is %d\n", (planeA >> 20) & 0x3);
-   temp = INREG(DSPBBASE);
-   ErrorF("Plane B start offset is %d\n", temp);
-   temp = INREG(DSPBSTRIDE);
-   ErrorF("Plane B stride is %d bytes (%d pixels)\n", temp, temp / pI830->cpp);
-   temp = INREG(DSPBPOS);
-   ErrorF("Plane B position %d %d\n", temp & 0xffff, (temp & 0xffff0000) >> 16);
-   temp = INREG(DSPBSIZE);
-   ErrorF("Plane B size %d %d\n", temp & 0xffff, (temp & 0xffff0000) >> 16);
-#endif
-
-   i830SetMode(pScrn, pMode, pI830->pipe);
-
-   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Mode bandwidth is %d Mpixel/s\n",
-	      pMode->HDisplay * pMode->VDisplay * refresh / 1000000);
-
-   {
-      int maxBandwidth, bandwidthA, bandwidthB;
-
-      if (GetModeSupport(pScrn, 0x80, 0x80, 0x80, 0x80,
-			&maxBandwidth, &bandwidthA, &bandwidthB)) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "maxBandwidth is %d Mbyte/s, "
-		    "pipe bandwidths are %d Mbyte/s, %d Mbyte/s\n",
-		    maxBandwidth, bandwidthA, bandwidthB);
-      }
-   }
-
-#if 0
-   {
-      int ret;
-
-      ret = GetLFPCompMode(pScrn);
-      if (ret != -1) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		    "LFP compensation mode: 0x%x\n", ret);
-      }
-   }
-#endif
-
-#if MODESWITCH_RESET_STATE
-   ResetState(pScrn, TRUE);
-   SetHWOperatingState(pScrn);
-#endif
-
-#ifdef XF86DRI
-   if (didLock)
-      I830DRIUnlock(pScrn);
-#endif
-
-   pScrn->vtSema = TRUE;
-   return TRUE;
-}
-
 static void
 InitRegisterRec(ScrnInfoPtr pScrn)
 {
@@ -5616,7 +5272,7 @@ I830BIOSEnterVT(int scrnIndex, int flags
    if (!pI830->starting)
       I830DetectMonitorChange(pScrn);
 	    
-   if (!I830VESASetMode(pScrn, pScrn->currentMode))
+   if (!I830SetMode(pScrn, pScrn->currentMode))
       return FALSE;
    
 #ifdef I830_XV
@@ -5686,7 +5342,7 @@ I830BIOSSwitchMode(int scrnIndex, Displa
     * are rotating, we don't need to call the mode setup again.
     */
    if (pI830->currentMode != mode) {
-      if (!I830VESASetMode(pScrn, mode))
+      if (!I830SetMode(pScrn, mode))
          ret = FALSE;
    }
 
@@ -5707,7 +5363,7 @@ I830BIOSSwitchMode(int scrnIndex, Displa
     * video mode here, as we'll have already re-instated the original rotation.
     */
    if (!ret) {
-      if (!I830VESASetMode(pScrn, pI830->currentMode)) {
+      if (!I830SetMode(pScrn, pI830->currentMode)) {
 	 xf86DrvMsg(scrnIndex, X_INFO,
 		    "Failed to restore previous mode (SwitchMode)\n");
       }
diff-tree 7edb25789bd13f26134e8f5bf493897c8df322e0 (from b5915ac77a3887cd3aa4ce0bb77b8a36e1aa5a1b)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Wed Mar 1 14:02:51 2006 -0800

    Start making i830SetMode aware of multiple pipes.

diff --git a/src/i830_display.c b/src/i830_display.c
index 6bf823a..aa02a42 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -214,13 +214,24 @@ i830FindBestPLL(ScrnInfoPtr pScrn, int t
     return (err != target);
 }
 
+static void
+i830WaitForVblank(ScrnInfoPtr pScreen)
+{
+    /* Wait for 20ms, i.e. one cycle at 50hz. */
+    usleep(20000);
+}
+
+/**
+ * Sets the given video mode on the given pipe.  Assumes that plane A feeds
+ * pipe A, and plane B feeds pipe B.  Should not affect the other planes/pipes.
+ */
 void
-i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
+i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     int m1, m2, n, p1, p2;
     CARD32 dpll = 0, fp = 0, temp;
-    CARD32 htot, hblank, hsync, vtot, vblank, vsync;
+    CARD32 htot, hblank, hsync, vtot, vblank, vsync, dspcntr;
     CARD32 pipesrc, dspsize, adpa;
     Bool ok;
     int refclk = 96000;
@@ -276,51 +287,96 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
 	   i830PllIsValid(pScrn, refclk, m1, m2, n, p1, p2) ? "good" : "bad");
     ErrorF("clock regs: 0x%08x, 0x%08x\n", dpll, fp);
 
-    /* First, disable display planes */
-    temp = INREG(DSPACNTR);
-    OUTREG(DSPACNTR, temp & ~DISPLAY_PLANE_ENABLE);
-    temp = INREG(DSPBCNTR);
-    OUTREG(DSPBCNTR, temp & ~DISPLAY_PLANE_ENABLE);
-
-    /* Next, disable display pipes */
-    temp = INREG(PIPEACONF);
-    OUTREG(PIPEACONF, temp & ~PIPEACONF_ENABLE);
-    temp = INREG(PIPEBCONF);
-    OUTREG(PIPEBCONF, temp & ~PIPEBCONF_ENABLE);
-
-    /* XXX: Wait for a vblank */
-    sleep(1);
-
-    /* Set up display timings and PLLs for the pipe.  XXX: Choose pipe! */
-    OUTREG(FPA0, fp);
-    OUTREG(DPLL_A, dpll);
-    OUTREG(HTOTAL_A, htot);
-    OUTREG(HBLANK_A, hblank);
-    OUTREG(HSYNC_A, hsync);
-    OUTREG(VTOTAL_A, vtot);
-    OUTREG(VBLANK_A, vblank);
-    OUTREG(VSYNC_A, vsync);
-    OUTREG(DSPABASE, 0); /* XXX: Base placed elsewhere? */
-    /*OUTREG(DSPASTRIDE, pScrn->displayWidth);*/
-    /*OUTREG(DSPAPOS, 0);*/
-    OUTREG(PIPEASRC, pipesrc);
-    OUTREG(DSPASIZE, dspsize);
-    OUTREG(ADPA, adpa);
+    dspcntr = DISPLAY_PLANE_ENABLE;
+    switch (pScrn->bitsPerPixel) {
+    case 8:
+	dspcntr |= DISPPLANE_8BPP | DISPPLANE_GAMMA_ENABLE;
+	break;
+    case 16:
+	if (pScrn->depth == 15)
+	    dspcntr |= DISPPLANE_16BPP;
+	else
+	    dspcntr |= DISPPLANE_15_16BPP;
+	break;
+    case 32:
+	dspcntr |= DISPPLANE_32BPP;
+	break;
+    default:
+	FatalError("unknown display bpp\n");
+    }
+    if (pipe == 0)
+	dspcntr |= DISPPLANE_SEL_PIPE_A;
+    else
+	dspcntr |= DISPPLANE_SEL_PIPE_B;
+
+    /* Set up display timings and PLLs for the pipe. */
+    if (pipe == 0) {
+	/* First, disable display planes */
+	temp = INREG(DSPACNTR);
+	OUTREG(DSPACNTR, temp & ~DISPLAY_PLANE_ENABLE);
 
-    /* Turn pipes and planes back on */
-    /*if (pI830->planeEnabled[0]) {*/
+	/* Next, disable display pipes */
+	temp = INREG(PIPEACONF);
+	OUTREG(PIPEACONF, temp & ~PIPEACONF_ENABLE);
+
+	/* Wait for vblank for the disable to take effect */
+	i830WaitForVblank(pScrn);
+
+	OUTREG(FPA0, fp);
+	OUTREG(DPLL_A, dpll);
+	OUTREG(HTOTAL_A, htot);
+	OUTREG(HBLANK_A, hblank);
+	OUTREG(HSYNC_A, hsync);
+	OUTREG(VTOTAL_A, vtot);
+	OUTREG(VBLANK_A, vblank);
+	OUTREG(VSYNC_A, vsync);
+	OUTREG(DSPASTRIDE, pScrn->displayWidth * pI830->cpp);
+	OUTREG(DSPASIZE, dspsize);
+	OUTREG(DSPAPOS, 0);
+	/* XXX: Deal with adjustframe down here */
+	OUTREG(DSPABASE, 0); /* triggers update of display registers */
+	OUTREG(PIPEASRC, pipesrc);
+
+	/* Then, turn the pipe on first */
 	temp = INREG(PIPEACONF);
 	OUTREG(PIPEACONF, temp | PIPEACONF_ENABLE);
-	temp = INREG(DSPACNTR);
-	OUTREG(DSPACNTR, temp | DISPLAY_PLANE_ENABLE);
-    /*}
 
-    if (pI830->planeEnabled[1]) {
+	/* And then turn the plane on */
+	OUTREG(DSPACNTR, dspcntr);
+    } else {
+	/* First, disable display planes */
+	temp = INREG(DSPBCNTR);
+	OUTREG(DSPBCNTR, temp & ~DISPLAY_PLANE_ENABLE);
+
+	/* Next, disable display pipes */
+	temp = INREG(PIPEBCONF);
+	OUTREG(PIPEBCONF, temp & ~PIPEBCONF_ENABLE);
+
+	/* Wait for vblank for the disable to take effect */
+	i830WaitForVblank(pScrn);
+
+	OUTREG(FPB0, fp);
+	OUTREG(DPLL_B, dpll);
+	OUTREG(HTOTAL_B, htot);
+	OUTREG(HBLANK_B, hblank);
+	OUTREG(HSYNC_B, hsync);
+	OUTREG(VTOTAL_B, vtot);
+	OUTREG(VBLANK_B, vblank);
+	OUTREG(VSYNC_B, vsync);
+	OUTREG(DSPBSTRIDE, pScrn->displayWidth * pI830->cpp);
+	OUTREG(DSPBSIZE, dspsize);
+	OUTREG(DSPBPOS, 0);
+	/* XXX: Deal with adjustframe down here */
+	OUTREG(DSPBBASE, 0); /* triggers update of display registers */
+	OUTREG(PIPEBSRC, pipesrc);
+
+	/* Then, turn the pipe on first */
 	temp = INREG(PIPEBCONF);
 	OUTREG(PIPEBCONF, temp | PIPEBCONF_ENABLE);
-	temp = INREG(DSPBCNTR);
-	OUTREG(DSPBCNTR, temp | DISPLAY_PLANE_ENABLE);
-    }*/
+
+	/* And then turn the plane on */
+	OUTREG(DSPBCNTR, dspcntr);
+    }
 }
 
 Bool
diff --git a/src/i830_display.h b/src/i830_display.h
index 894148c..66811ae 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -1,3 +1,3 @@
-void i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
+void i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe);
 Bool i830DetectCRT(ScreenPtr pScrn);
 void i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 5b45231..2dd545e 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -4398,7 +4398,7 @@ I830VESASetMode(ScrnInfoPtr pScrn, Displ
    ErrorF("Plane B size %d %d\n", temp & 0xffff, (temp & 0xffff0000) >> 16);
 #endif
 
-   i830SetMode(pScrn, pMode);
+   i830SetMode(pScrn, pMode, pI830->pipe);
 
    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Mode bandwidth is %d Mpixel/s\n",
 	      pMode->HDisplay * pMode->VDisplay * refresh / 1000000);
diff-tree b5915ac77a3887cd3aa4ce0bb77b8a36e1aa5a1b (from c20e15fbe4daeb7288f5c56cf5467eed13686080)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Wed Mar 1 13:12:25 2006 -0800

    Clean up a couple of warnings.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 50ab3ab..5b45231 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3905,6 +3905,7 @@ RestoreHWState(ScrnInfoPtr pScrn)
    return TRUE;
 }
 
+#if 0
 static void I830SetCloneVBERefresh(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock * block, int refresh)
 {
    I830Ptr pI830 = I830PTR(pScrn);
@@ -3946,7 +3947,6 @@ static void I830SetCloneVBERefresh(ScrnI
    }
 }
 
-#if 0
 static Bool
 I830VESASetVBEMode(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock * block)
 {
@@ -4100,7 +4100,9 @@ static Bool
 I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
 {
    I830Ptr pI830 = I830PTR(pScrn);
+#if 0
    vbeInfoPtr pVbe = pI830->pVbe;
+#endif
    VbeModeInfoData *data = (VbeModeInfoData *) pMode->Private;
    int mode, i;
    CARD32 planeA, planeB, temp;
diff-tree c20e15fbe4daeb7288f5c56cf5467eed13686080 (from 7d37c5036956609d0c7ae874d0dc1c616f76f849)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Wed Mar 1 13:08:38 2006 -0800

    Disable I830VESASetVBEMode on restore, since I've removed that code. Note that
    this means that VT switching is broken.  We're fine with that for now, but at
    least now we get a bad display rather than X crashing about an undefined symbol.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 0befd2b..50ab3ab 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3836,10 +3836,12 @@ RestoreHWState(ScrnInfoPtr pScrn)
       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		 "Setting the original video mode instead of restoring\n\t"
 		 "the saved state\n");
+#if 0
       I830VESASetVBEMode(pScrn, pVesa->stateMode, NULL);
       if (!pVesa->useDefaultRefresh && pI830->useExtendedRefresh) {
          SetRefreshRate(pScrn, pVesa->stateMode, pVesa->stateRefresh);
       }
+#endif
    }
    if (pVesa->savedScanlinePitch)
        VBESetLogicalScanline(pVbe, pVesa->savedScanlinePitch);
diff-tree 7d37c5036956609d0c7ae874d0dc1c616f76f849 (from 2538cbeb5014e40280a3ae782a755512b1dc85fa)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Wed Mar 1 13:06:04 2006 -0800

    Re-disable chatty debug code.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 88f89d1..0befd2b 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -4326,7 +4326,7 @@ I830VESASetMode(ScrnInfoPtr pScrn, Displ
       }
    }
 
-#if 1
+#if 0
    /* Print out some CRTC/display information. */
    temp = INREG(HTOTAL_A);
    ErrorF("Horiz active: %d, Horiz total: %d\n", temp & 0x7ff,
diff-tree 2538cbeb5014e40280a3ae782a755512b1dc85fa (from 7746da3b346968ab8d2534fc158d026da67cc7b5)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Wed Mar 1 13:01:52 2006 -0800

    Enable -Wall on GCC, and do a cleanup of existing warnings.

diff --git a/configure.ac b/configure.ac
index 665b76a..5626c4e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -39,6 +39,10 @@ AC_DISABLE_STATIC
 AC_PROG_LIBTOOL
 AC_PROG_CC
 
+if test "x$GCC" = "xyes"; then
+    CFLAGS="$CFLAGS -Wall"
+fi
+
 AH_TOP([#include "xorg-server.h"])
 
 AC_ARG_WITH(xorg-module-dir,
diff --git a/src/i830.h b/src/i830.h
index 00d0386..a02bda7 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -502,6 +502,12 @@ extern int I830GetBestRefresh(ScrnInfoPt
 extern Bool I830CheckModeSupport(ScrnInfoPtr pScrn, int x, int y, int mode);
 extern Bool I830Rotate(ScrnInfoPtr pScrn, DisplayModePtr mode);
 extern Bool I830FixOffset(ScrnInfoPtr pScrn, I830MemRange *mem);
+extern Bool I830BindAGPMemory(ScrnInfoPtr pScrn);
+extern Bool I830UnbindAGPMemory(ScrnInfoPtr pScrn);
+extern Bool I830RandRSetConfig(ScreenPtr pScreen, Rotation rotation,
+			       int rate, RRScreenSizePtr pSize);
+extern Rotation I830GetRotation(ScreenPtr pScreen);
+extern Bool I830RandRInit(ScreenPtr pScreen, int rotation);
 
 /*
  * 12288 is set as the maximum, chosen because it is enough for
diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index dfed8cd..ea472fa 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -359,7 +359,9 @@ I830SetCursorPosition(ScrnInfoPtr pScrn,
 {
    I830Ptr pI830 = I830PTR(pScrn);
    CARD32 temp = 0;
+#if 0
    static Bool outsideViewport = FALSE;
+#endif
    Bool hide = FALSE, show = FALSE;
    int oldx = x, oldy = y;
    int hotspotx = 0, hotspoty = 0;
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 06bcccc..f9f9a2c 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -101,7 +101,9 @@ static void I830DRITransitionTo3d(Screen
 static void I830DRITransitionMultiToSingle3d(ScreenPtr pScreen);
 static void I830DRITransitionSingleToMulti3d(ScreenPtr pScreen);
 
+#if 0
 static void I830DRIShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf);
+#endif
 
 extern void GlxSetVisualConfigs(int nconfigs,
 				__GLXvisualConfig * configs,
diff --git a/src/i830_randr.c b/src/i830_randr.c
index be790c9..0311f2b 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -313,7 +313,6 @@ I830RandRInit (ScreenPtr    pScreen, int
 {
     rrScrPrivPtr	rp;
     XF86RandRInfoPtr	randrp;
-    ScrnInfoPtr		scrp = XF86SCRNINFO(pScreen);
     
 #ifdef PANORAMIX
     /* XXX disable RandR when using Xinerama */
diff-tree 7746da3b346968ab8d2534fc158d026da67cc7b5 (from 142bc4f91a5d776e7ab44cc5fb2328e3f7267557)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Wed Mar 1 12:49:06 2006 -0800

    Move LVDS panel power state setting to a separate function, and reduce magic
    numbers.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index 1194c23..8785b06 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -756,6 +756,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 #define LVDS			0x61180
 # define LVDS_PORT_EN			(1 << 31)
+# define LVDS_PIPEB_SELECT		(1 << 30)
+# define LVDS_CLKA_POWER_DOWN		(0 << 8)
+# define LVDS_CLKA_POWER_UP		(3 << 8)
 
 #define PIPEACONF 0x70008
 #define PIPEACONF_ENABLE	(1<<31)
diff --git a/src/i830_display.c b/src/i830_display.c
index e4ef477..6bf823a 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -338,3 +338,29 @@ i830DetectCRT(ScrnInfoPtr pScrn)
 
     return ((INREG(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_INT_STATUS));
 }
+
+/**
+ * Sets the power state for the panel.
+ */
+void
+i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD32 pp_status, pp_control;
+
+    if (on) {
+	OUTREG(PP_STATUS, INREG(PP_STATUS) | PP_ON);
+	OUTREG(PP_CONTROL, INREG(PP_CONTROL) | POWER_TARGET_ON);
+	do {
+	    pp_status = INREG(PP_STATUS);
+	    pp_control = INREG(PP_CONTROL);
+	} while (!(pp_status & PP_ON) && !(pp_control & POWER_TARGET_ON));
+    } else {
+	OUTREG(PP_STATUS, INREG(PP_STATUS) & ~PP_ON);
+	OUTREG(PP_CONTROL, INREG(PP_CONTROL) & ~POWER_TARGET_ON);
+	do {
+	    pp_status = INREG(PP_STATUS);
+	    pp_control = INREG(PP_CONTROL);
+	} while ((pp_status & PP_ON) || (pp_control & POWER_TARGET_ON));
+    }
+}
diff --git a/src/i830_display.h b/src/i830_display.h
index 6ad150a..894148c 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -1,2 +1,3 @@
 void i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
 Bool i830DetectCRT(ScreenPtr pScrn);
+void i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 2fd391e..88f89d1 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1061,40 +1061,30 @@ SetDisplayDevices(ScrnInfoPtr pScrn, int
    /* Disable LVDS */
    if (singlepipe & PIPE_LFP)  {
       /* LFP on PipeA is unlikely! */
-      OUTREG(PP_STATUS, INREG(PP_STATUS) & ~PP_ON);
-      OUTREG(PP_CONTROL, INREG(PP_CONTROL) & ~POWER_TARGET_ON);
-      while ((INREG(PP_STATUS) & PP_ON) || (INREG(PP_CONTROL) & 1));
-      /* Fix up LVDS */
-      OUTREG(LVDS, (INREG(LVDS) & ~1<<30) | 0x80000300);
-      /* Enable LVDS */
-      OUTREG(PP_STATUS, INREG(PP_STATUS) | PP_ON);
-      OUTREG(PP_CONTROL, INREG(PP_CONTROL) | POWER_TARGET_ON);
-      while (!(INREG(PP_STATUS) & PP_ON) && !(INREG(PP_CONTROL) & 1));
+      i830SetLVDSPanelPower(pScrn, FALSE);
+      temp = INREG(LVDS) & ~LVDS_PIPEB_SELECT;
+      temp |= LVDS_PORT_EN | LVDS_CLKA_POWER_UP;
+      OUTREG(LVDS, temp);
+      i830SetLVDSPanelPower(pScrn, TRUE);
       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 	 	"Enabling LVDS directly. Pipe A.\n");
    } else
    if (singlepipe & (PIPE_LFP << 8))  {
-      OUTREG(PP_STATUS, INREG(PP_STATUS) & ~PP_ON);
-      OUTREG(PP_CONTROL, INREG(PP_CONTROL) & ~POWER_TARGET_ON);
-      while ((INREG(PP_STATUS) & PP_ON) || (INREG(PP_CONTROL) & 1));
-      /* Fix up LVDS */
-      OUTREG(LVDS, (INREG(LVDS) | 1<<30) | 0x80000300);
-      /* Enable LVDS */
-      OUTREG(PP_STATUS, INREG(PP_STATUS) | PP_ON);
-      OUTREG(PP_CONTROL, INREG(PP_CONTROL) | POWER_TARGET_ON);
-      while (!(INREG(PP_STATUS) & PP_ON) &&
-	     !(INREG(PP_CONTROL) & POWER_TARGET_ON));
+      i830SetLVDSPanelPower(pScrn, FALSE);
+      temp = INREG(LVDS) | LVDS_PIPEB_SELECT;
+      temp |= LVDS_PORT_EN | LVDS_CLKA_POWER_UP;
+      OUTREG(LVDS, temp);
+      i830SetLVDSPanelPower(pScrn, TRUE);
       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 	 	"Enabling LVDS directly. Pipe B.\n");
    }
    else if (!(IS_I830(pI830) || IS_845G(pI830) || IS_I865G(pI830))) {
       if (!(devices & (PIPE_LFP | PIPE_LFP<<8))) {
-         OUTREG(PP_STATUS, INREG(PP_STATUS) & ~PP_ON);
-         OUTREG(PP_CONTROL, INREG(PP_CONTROL) & ~POWER_TARGET_ON);
-         while ((INREG(PP_STATUS) & PP_ON) ||
-		(INREG(PP_CONTROL) & POWER_TARGET_ON));
+	 i830SetLVDSPanelPower(pScrn, FALSE);
          /* Fix up LVDS */
-         OUTREG(LVDS, (INREG(LVDS) | 1<<30) & ~0x80000300);
+	 temp = INREG(LVDS) | LVDS_PIPEB_SELECT;
+	 temp &= ~(LVDS_PORT_EN | LVDS_CLKA_POWER_UP);
+	 OUTREG(LVDS, temp);
          xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 	 	"Disabling LVDS directly.\n");
       }
diff-tree 142bc4f91a5d776e7ab44cc5fb2328e3f7267557 (from 6877f532c5f41a445d41eb6a9982bf6bcf691bf2)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Tue Feb 28 18:50:57 2006 -0800

    Write the ADPA (CRTC) register on mode setup. Obtained from airlied.

diff --git a/src/i830_display.c b/src/i830_display.c
index 73f2d9f..e4ef477 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -221,7 +221,7 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
     int m1, m2, n, p1, p2;
     CARD32 dpll = 0, fp = 0, temp;
     CARD32 htot, hblank, hsync, vtot, vblank, vsync;
-    CARD32 pipesrc, dspsize;
+    CARD32 pipesrc, dspsize, adpa;
     Bool ok;
     int refclk = 96000;
 
@@ -262,6 +262,15 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
     pipesrc = ((pMode->HDisplay - 1) << 16) | (pMode->VDisplay - 1);
     dspsize = ((pMode->VDisplay - 1) << 16) | (pMode->HDisplay - 1);
 
+    adpa = INREG(ADPA);
+    adpa &= ~(ADPA_HSYNC_ACTIVE_HIGH | ADPA_VSYNC_ACTIVE_HIGH);
+    adpa &= ~(ADPA_VSYNC_CNTL_DISABLE | ADPA_HSYNC_CNTL_DISABLE);
+    adpa |= ADPA_DAC_ENABLE;
+    if (pMode->Flags & V_PHSYNC)
+	adpa |= ADPA_HSYNC_ACTIVE_HIGH;
+    if (pMode->Flags & V_PVSYNC)
+	adpa |= ADPA_VSYNC_ACTIVE_HIGH;
+
     i830PrintPll("chosen", refclk, m1, m2, n, p1, p2);
     ErrorF("clock settings for chosen look %s\n",
 	   i830PllIsValid(pScrn, refclk, m1, m2, n, p1, p2) ? "good" : "bad");
@@ -296,6 +305,7 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
     /*OUTREG(DSPAPOS, 0);*/
     OUTREG(PIPEASRC, pipesrc);
     OUTREG(DSPASIZE, dspsize);
+    OUTREG(ADPA, adpa);
 
     /* Turn pipes and planes back on */
     /*if (pI830->planeEnabled[0]) {*/
diff-tree 6877f532c5f41a445d41eb6a9982bf6bcf691bf2 (from a085813714818a23aa8d326804f642cd699e0f17)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Tue Feb 28 15:56:06 2006 -0800

    Add untested CRT detection code.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index 7af23e7..1194c23 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -693,6 +693,19 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 # define FP_M1_DIV_MASK				0x00003f00
 # define FP_M2_DIV_MASK				0x0000003f
 
+#define PORT_HOTPLUG_EN		0x61110
+# define SDVOB_HOTPLUG_INT_EN			(1 << 26)
+# define SDVOC_HOTPLUG_INT_EN			(1 << 25)
+# define TV_HOTPLUG_INT_EN			(1 << 18)
+# define CRT_HOTPLUG_INT_EN			(1 << 9)
+# define CRT_HOTPLUG_FORCE_DETECT		(1 << 3)
+
+#define PORT_HOTPLUG_STAT	0x61114
+# define CRT_HOTPLUG_INT_STATUS			(1 << 11)
+# define TV_HOTPLUG_INT_STATUS			(1 << 10)
+# define SDVOC_HOTPLUG_INT_STATUS		(1 << 7)
+# define SDVOB_HOTPLUG_INT_STATUS		(1 << 6)
+
 #define I830_HTOTAL_MASK 	0xfff0000
 #define I830_HACTIVE_MASK	0x7ff
 
diff --git a/src/i830_display.c b/src/i830_display.c
index 84379ac..73f2d9f 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -312,3 +312,19 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
 	OUTREG(DSPBCNTR, temp | DISPLAY_PLANE_ENABLE);
     }*/
 }
+
+Bool
+i830DetectCRT(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD32 temp;
+
+    temp = INREG(PORT_HOTPLUG_EN);
+    OUTREG(PORT_HOTPLUG_EN, temp | CRT_HOTPLUG_FORCE_DETECT);
+
+    /* Wait for the bit to clear to signal detection finished. */
+    while (INREG(PORT_HOTPLUG_EN) & CRT_HOTPLUG_FORCE_DETECT)
+	;
+
+    return ((INREG(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_INT_STATUS));
+}
diff --git a/src/i830_display.h b/src/i830_display.h
index 6cadd75..6ad150a 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -1 +1,2 @@
 void i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
+Bool i830DetectCRT(ScreenPtr pScrn);
diff-tree a085813714818a23aa8d326804f642cd699e0f17 (from 2d4415ff1729554537b20be2b6c878444485e406)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Tue Feb 28 15:16:59 2006 -0800

    Add adjustments of PLL divisor limits for "Almador".

diff --git a/src/i830_display.c b/src/i830_display.c
index a09ed60..84379ac 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -19,9 +19,43 @@ i830PrintPll(char *prefix, int refclk, i
 }
 
 static Bool
-i830PllIsValid(int refclk, int m1, int m2, int n, int p1, int p2)
+i830PllIsValid(ScrnInfoPtr pScrn, int refclk, int m1, int m2, int n, int p1,
+	       int p2)
 {
+    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;
+    int min_p, max_p;
+
+    min_p = 5;
+    max_p = 80;
+    if (pI830->PciInfo->chipType >= PCI_CHIP_I915_G) {
+	min_m1 = 10;
+	max_m1 = 20;
+	min_m2 = 5;
+	max_m2 = 9;
+	min_m = 70;
+	max_m = 120;
+	min_n = 3;
+	max_n = 8;
+	if (0) { /* lvds */
+	    min_p = 7;
+	    max_p = 98;
+	}
+    } else {
+	min_m1 = 16;
+	max_m1 = 24;
+	min_m2 = 7;
+	max_m2 = 11;
+	min_m = 90;
+	max_m = 130;
+	min_n = 4;
+	max_n = 8;
+	if (0) { /* lvds */
+	    min_n = 3;
+	    min_m = 88;
+	}
+    }
 
     p = p1 + p2;
     m = 5 * (m1 + 2) + (m2 + 2);
@@ -30,17 +64,17 @@ i830PllIsValid(int refclk, int m1, int m
 
     if (p1 < 1 || p1 > 8)
 	return FALSE;
-    if (p < 5 || p > 80) /* XXX: 7-98 for LVDS */
+    if (p < min_p || p > max_p)
 	return FALSE;
-    if (m2 < 5 || m2 > 9)
+    if (m2 < min_m2 || m2 > max_m2)
 	return FALSE;
-    if (m1 < 10 || m1 > 20)
+    if (m1 < min_m1 || m1 > max_m1)
 	return FALSE;
     if (m1 <= m2)
 	return FALSE;
-    if (m < 70 || m > 120)
+    if (m < min_m || m > max_m)
 	return FALSE;
-    if (n + 2 < 3 || n + 2 > 8)	/*XXX: Is the +2 right? */
+    if (n + 2 < min_n || n + 2 > max_n)	/*XXX: Is the +2 right? */
 	return FALSE;
     if (vco < 1400000 || vco > 2800000)
 	return FALSE;
@@ -129,23 +163,37 @@ i830ReadAndReportPLL(ScrnInfoPtr pScrn)
 #endif
 
 static Bool
-i830FindBestPLL(int target, int refclk, int *outm1, int *outm2, int *outn,
-		int *outp1, int *outp2)
+i830FindBestPLL(ScrnInfoPtr pScrn, int target, int refclk, int *outm1,
+		int *outm2, int *outn, int *outp1, int *outp2)
 {
+    I830Ptr pI830 = I830PTR(pScrn);
     int m1, m2, n, p1, p2;
     int err = target;
+    int min_m1, max_m1, min_m2, max_m2;
+
+    if (pI830->PciInfo->chipType >= PCI_CHIP_I915_G) {
+	min_m1 = 10;
+	max_m1 = 20;
+	min_m2 = 5;
+	max_m2 = 9;
+    } else {
+	min_m1 = 16;
+	max_m1 = 24;
+	min_m2 = 7;
+	max_m2 = 11;
+    }
 
     if (target < 200000)	/* XXX: LVDS */
 	p2 = 10;
     else
 	p2 = 5;
-    for (m1 = 10; m1 <= 20; m1++) {
-	for (m2 = 5; m2 < 9; m2++) {
+    for (m1 = min_m1; m1 <= max_m1; m1++) {
+	for (m2 = min_m2; m2 < max_m2; m2++) {
 	    for (n = 1; n <= 6; n++) {
 		for (p1 = 1; p1 <= 8; p1++) {
 		    int clock, this_err;
 
-		    if (!i830PllIsValid(refclk, m1, m2, n, p1, p2))
+		    if (!i830PllIsValid(pScrn, refclk, m1, m2, n, p1, p2))
 			continue;
 
 		    clock = i830_clock(refclk, m1, m2, n, p1, p2);
@@ -179,7 +227,7 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
 
     ErrorF("Requested pix clock: %d\n", pMode->Clock);
 
-    ok = i830FindBestPLL(pMode->Clock, refclk, &m1, &m2, &n, &p1, &p2);
+    ok = i830FindBestPLL(pScrn, pMode->Clock, refclk, &m1, &m2, &n, &p1, &p2);
     if (!ok)
 	FatalError("Couldn't find PLL settings for mode!\n");
 
@@ -216,7 +264,7 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
 
     i830PrintPll("chosen", refclk, m1, m2, n, p1, p2);
     ErrorF("clock settings for chosen look %s\n",
-	   i830PllIsValid(refclk, m1, m2, n, p1, p2) ? "good" : "bad");
+	   i830PllIsValid(pScrn, refclk, m1, m2, n, p1, p2) ? "good" : "bad");
     ErrorF("clock regs: 0x%08x, 0x%08x\n", dpll, fp);
 
     /* First, disable display planes */
diff-tree 2d4415ff1729554537b20be2b6c878444485e406 (from 611264ab9b82bca6648a9b27e5ba4b7457c46aa6)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Feb 27 16:57:43 2006 -0800

    Remove the hacked local xf86SetModeCRTC now that xf86SetCrtcForModes is taking
    effect on all of our modes.

diff --git a/src/i830_display.c b/src/i830_display.c
index 0fa0405..a09ed60 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -166,97 +166,6 @@ i830FindBestPLL(int target, int refclk, 
     return (err != target);
 }
 
-/*
- * xf86SetModeCrtc
- *
- * Copied from xf86Mode.c because it's static there, and i830 likes to hand us
- * these hand-rolled modes.
- *
- * Initialises the Crtc parameters for a mode.  The initialisation includes
- * adjustments for interlaced and double scan modes.
- */
-static void
-xf86SetModeCrtc(DisplayModePtr p, int adjustFlags)
-{
-    if ((p == NULL) /* XXX: || ((p->type & M_T_CRTC_C) == M_T_BUILTIN)*/)
-	return;
-
-    p->CrtcHDisplay             = p->HDisplay;
-    p->CrtcHSyncStart           = p->HSyncStart;
-    p->CrtcHSyncEnd             = p->HSyncEnd;
-    p->CrtcHTotal               = p->HTotal;
-    p->CrtcHSkew                = p->HSkew;
-    p->CrtcVDisplay             = p->VDisplay;
-    p->CrtcVSyncStart           = p->VSyncStart;
-    p->CrtcVSyncEnd             = p->VSyncEnd;
-    p->CrtcVTotal               = p->VTotal;
-    if (p->Flags & V_INTERLACE) {
-	if (adjustFlags & INTERLACE_HALVE_V) {
-	    p->CrtcVDisplay         /= 2;
-	    p->CrtcVSyncStart       /= 2;
-	    p->CrtcVSyncEnd         /= 2;
-	    p->CrtcVTotal           /= 2;
-	}
-	/* Force interlaced modes to have an odd VTotal */
-	/* maybe we should only do this when INTERLACE_HALVE_V is set? */
-	p->CrtcVTotal |= 1;
-    }
-
-    if (p->Flags & V_DBLSCAN) {
-        p->CrtcVDisplay         *= 2;
-        p->CrtcVSyncStart       *= 2;
-        p->CrtcVSyncEnd         *= 2;
-        p->CrtcVTotal           *= 2;
-    }
-    if (p->VScan > 1) {
-        p->CrtcVDisplay         *= p->VScan;
-        p->CrtcVSyncStart       *= p->VScan;
-        p->CrtcVSyncEnd         *= p->VScan;
-        p->CrtcVTotal           *= p->VScan;
-    }
-    p->CrtcHAdjusted = FALSE;
-    p->CrtcVAdjusted = FALSE;
-
-    /*
-     * XXX
-     *
-     * The following is taken from VGA, but applies to other cores as well.
-     */
-    p->CrtcVBlankStart = min(p->CrtcVSyncStart, p->CrtcVDisplay);
-    p->CrtcVBlankEnd = max(p->CrtcVSyncEnd, p->CrtcVTotal);
-    if ((p->CrtcVBlankEnd - p->CrtcVBlankStart) >= 127) {
-        /* 
-         * V Blanking size must be < 127.
-         * Moving blank start forward is safer than moving blank end
-         * back, since monitors clamp just AFTER the sync pulse (or in
-         * the sync pulse), but never before.
-         */
-        p->CrtcVBlankStart = p->CrtcVBlankEnd - 127;
-	/*
-	 * If VBlankStart is now > VSyncStart move VBlankStart
-	 * to VSyncStart using the maximum width that fits into
-	 * VTotal.
-	 */
-	if (p->CrtcVBlankStart > p->CrtcVSyncStart) {
-	    p->CrtcVBlankStart = p->CrtcVSyncStart;
-	    p->CrtcVBlankEnd = min(p->CrtcHBlankStart + 127, p->CrtcVTotal);
-	}
-    }
-    p->CrtcHBlankStart = min(p->CrtcHSyncStart, p->CrtcHDisplay);
-    p->CrtcHBlankEnd = max(p->CrtcHSyncEnd, p->CrtcHTotal);
-
-    if ((p->CrtcHBlankEnd - p->CrtcHBlankStart) >= 63 * 8) {
-        /*
-         * H Blanking size must be < 63*8. Same remark as above.
-         */
-        p->CrtcHBlankStart = p->CrtcHBlankEnd - 63 * 8;
-	if (p->CrtcHBlankStart > p->CrtcHSyncStart) {
-	    p->CrtcHBlankStart = p->CrtcHSyncStart;
-	    p->CrtcHBlankEnd = min(p->CrtcHBlankStart + 63 * 8, p->CrtcHTotal);
-	}
-    }
-}
-
 void
 i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
 {
@@ -268,8 +177,6 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
     Bool ok;
     int refclk = 96000;
 
-    xf86SetModeCrtc(pMode, 0);
-
     ErrorF("Requested pix clock: %d\n", pMode->Clock);
 
     ok = i830FindBestPLL(pMode->Clock, refclk, &m1, &m2, &n, &p1, &p2);
diff-tree 611264ab9b82bca6648a9b27e5ba4b7457c46aa6 (from 9838f639911e8c165ab615fdd9a00e02fa4b3f8a)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Feb 27 15:44:11 2006 -0800

    Remove more VBE stuff and start using xf86ValidateModes. Guessed some params to
    xf86ValidateModes.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index b7d1322..2fd391e 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3197,38 +3197,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
 
    DDCclock = I830UseDDC(pScrn);
 
-   /*
-    * Note: VBE modes (> 0x7f) won't work with Intel's extended BIOS
-    * functions. 
-    */
-   pScrn->modePool = I830GetModePool(pScrn, pI830->pVbe, pI830->vbeInfo);
-
-   if (!pScrn->modePool) {
-      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		 "No Video BIOS modes for chosen depth.\n");
-      PreInitCleanup(pScrn);
-      return FALSE;
-   }
-
-   /* This may look a little weird, but to notify that we're using the
-    * default hsync/vrefresh we need to unset what we just set .....
-    */
-   if (defmon & 1) {
-      pScrn->monitor->hsync[0].lo = 0;
-      pScrn->monitor->hsync[0].hi = 0;
-      pScrn->monitor->nHsync = 0;
-   }
-
-   if (defmon & 2) {
-      pScrn->monitor->vrefresh[0].lo = 0;
-      pScrn->monitor->vrefresh[0].hi = 0;
-      pScrn->monitor->nVrefresh = 0;
-   }
-
-   SetPipeAccess(pScrn);
-   VBESetModeNames(pScrn->modePool);
-
-#if 0
+#if 1
    /*
      * Setup the ClockRanges, which describe what clock ranges are available,
      * and what sort of modes they can be used for.
@@ -3249,26 +3218,21 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
     * there's code in vesa/vesa.c.
     */
 
-   /* XXX Need to get relevant modes and virtual parameters. */
-   /* Do the mode validation without regard to special scanline pitches. */
-   SetPipeAccess(pScrn);
-#if 1
-   n = VBEValidateModes(pScrn, NULL, pScrn->display->modes, NULL,
-			NULL, 0, MAX_DISPLAY_PITCH, 1,
-			0, MAX_DISPLAY_HEIGHT,
-			pScrn->display->virtualX,
-			pScrn->display->virtualY,
-			memsize, LOOKUP_BEST_REFRESH);
-#else
-    n = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
-			  pScrn->display->modes, clockRanges,
-			  NULL, 256, 4096,
-			  pScrn->bitsPerPixel, 128, 4096,
-			  pScrn->display->virtualX,
-			  pScrn->display->virtualY,
-			  pI830->FbMapSize,
-			  LOOKUP_BEST_REFRESH);
-#endif
+   /* XXX minPitch, minHeight are random numbers. */
+   n = xf86ValidateModes(pScrn,
+			 pScrn->monitor->Modes, /* availModes */
+			 pScrn->display->modes, /* modeNames */
+			 clockRanges, /* clockRanges */
+			 NULL, /* linePitches */
+			 256, /* minPitch */
+			 MAX_DISPLAY_PITCH, /* maxPitch */
+			 64, /* pitchInc */
+			 pScrn->bitsPerPixel, /* minHeight */
+			 MAX_DISPLAY_HEIGHT, /* maxHeight */
+			 pScrn->display->virtualX, /* virtualX */
+			 pScrn->display->virtualY, /* virtualY */
+			 pI830->FbMapSize, /* apertureSize */
+			 LOOKUP_BEST_REFRESH /* strategy */);
    if (n <= 0) {
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
       PreInitCleanup(pScrn);
@@ -3314,22 +3278,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
       return FALSE;
    }
 
-   /* Now we check the VESA BIOS's displayWidth and reset if necessary */
-   p = pScrn->modes;
-   do {
-      VbeModeInfoData *data = (VbeModeInfoData *) p->Private;
-      VbeModeInfoBlock *modeInfo;
-
-      /* Get BytesPerScanline so we can reset displayWidth */
-      if ((modeInfo = VBEGetModeInfo(pI830->pVbe, data->mode))) {
-         if (pScrn->displayWidth < modeInfo->BytesPerScanline / pI830->cpp) {
-            xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Correcting stride (%d -> %d)\n", pScrn->displayWidth, modeInfo->BytesPerScanline);
-	    pScrn->displayWidth = modeInfo->BytesPerScanline / pI830->cpp;
-	 }
-      } 
-      p = p->next;
-   } while (p != NULL && p != pScrn->modes);
-
    xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
 
    pScrn->currentMode = pScrn->modes;
diff-tree 9838f639911e8c165ab615fdd9a00e02fa4b3f8a (from 767944e3782f9941e9fc72a6705cc3115a6e24ac)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Feb 27 14:12:50 2006 -0800

    Always ErrorF output debugging info when doing BIOS calls, including file/line.

diff --git a/src/common.h b/src/common.h
index bb89dd2..e9debe5 100644
--- a/src/common.h
+++ b/src/common.h
@@ -101,8 +101,8 @@ extern void I830DPRINTF_stub(const char 
 
 /* BIOS debug macro */
 #define xf86ExecX86int10_wrapper(pInt, pScrn) do {			\
+   ErrorF("Executing (ax == 0x%x) BIOS call at %s:%d\n", pInt->ax, __FILE__, __LINE__);	\
    if (I810_DEBUG & DEBUG_VERBOSE_BIOS) {				\
-      ErrorF("\n\n\n\nExecuting (ax == 0x%x) BIOS call\n", pInt->ax);	\
       ErrorF("Checking Error state before execution\n");		\
       PrintErrorState(pScrn);						\
    }									\
diff-tree 767944e3782f9941e9fc72a6705cc3115a6e24ac (from 4955cd267e7f8ed70e90b2a3de6f93de2ef859c8)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Feb 27 13:08:46 2006 -0800

    Replace a few magic numbers with symbolic names. Reviewed by md5.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index 8afe855..7af23e7 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -658,6 +658,12 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define PIPEBSRC	0x6101c
 #define BCLRPAT_B	0x61020
 
+#define PP_STATUS	0x61200
+# define PP_ON					(1 << 31)
+
+#define PP_CONTROL	0x61204
+# define POWER_TARGET_ON			(1 << 0)
+
 #define DPLL_A		0x06014
 #define DPLL_B		0x06018
 # define DPLL_VCO_ENABLE			(1 << 31)
@@ -736,6 +742,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define DVOC_SRCDIM		0x61164
 
 #define LVDS			0x61180
+# define LVDS_PORT_EN			(1 << 31)
 
 #define PIPEACONF 0x70008
 #define PIPEACONF_ENABLE	(1<<31)
diff --git a/src/i830_driver.c b/src/i830_driver.c
index b1beafd..b7d1322 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1061,36 +1061,38 @@ SetDisplayDevices(ScrnInfoPtr pScrn, int
    /* Disable LVDS */
    if (singlepipe & PIPE_LFP)  {
       /* LFP on PipeA is unlikely! */
-      OUTREG(0x61200, INREG(0x61200) & ~0x80000000);
-      OUTREG(0x61204, INREG(0x61204) & ~0x00000001);
-      while ((INREG(0x61200) & 0x80000000) || (INREG(0x61204) & 1));
+      OUTREG(PP_STATUS, INREG(PP_STATUS) & ~PP_ON);
+      OUTREG(PP_CONTROL, INREG(PP_CONTROL) & ~POWER_TARGET_ON);
+      while ((INREG(PP_STATUS) & PP_ON) || (INREG(PP_CONTROL) & 1));
       /* Fix up LVDS */
       OUTREG(LVDS, (INREG(LVDS) & ~1<<30) | 0x80000300);
       /* Enable LVDS */
-      OUTREG(0x61200, INREG(0x61200) | 0x80000000);
-      OUTREG(0x61204, INREG(0x61204) | 0x00000001);
-      while (!(INREG(0x61200) & 0x80000000) && !(INREG(0x61204) & 1));
+      OUTREG(PP_STATUS, INREG(PP_STATUS) | PP_ON);
+      OUTREG(PP_CONTROL, INREG(PP_CONTROL) | POWER_TARGET_ON);
+      while (!(INREG(PP_STATUS) & PP_ON) && !(INREG(PP_CONTROL) & 1));
       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 	 	"Enabling LVDS directly. Pipe A.\n");
    } else
    if (singlepipe & (PIPE_LFP << 8))  {
-      OUTREG(0x61200, INREG(0x61200) & ~0x80000000);
-      OUTREG(0x61204, INREG(0x61204) & ~0x00000001);
-      while ((INREG(0x61200) & 0x80000000) || (INREG(0x61204) & 1));
+      OUTREG(PP_STATUS, INREG(PP_STATUS) & ~PP_ON);
+      OUTREG(PP_CONTROL, INREG(PP_CONTROL) & ~POWER_TARGET_ON);
+      while ((INREG(PP_STATUS) & PP_ON) || (INREG(PP_CONTROL) & 1));
       /* Fix up LVDS */
       OUTREG(LVDS, (INREG(LVDS) | 1<<30) | 0x80000300);
       /* Enable LVDS */
-      OUTREG(0x61200, INREG(0x61200) | 0x80000000);
-      OUTREG(0x61204, INREG(0x61204) | 0x00000001);
-      while (!(INREG(0x61200) & 0x80000000) && !(INREG(0x61204) & 1));
+      OUTREG(PP_STATUS, INREG(PP_STATUS) | PP_ON);
+      OUTREG(PP_CONTROL, INREG(PP_CONTROL) | POWER_TARGET_ON);
+      while (!(INREG(PP_STATUS) & PP_ON) &&
+	     !(INREG(PP_CONTROL) & POWER_TARGET_ON));
       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 	 	"Enabling LVDS directly. Pipe B.\n");
    }
    else if (!(IS_I830(pI830) || IS_845G(pI830) || IS_I865G(pI830))) {
       if (!(devices & (PIPE_LFP | PIPE_LFP<<8))) {
-         OUTREG(0x61200, INREG(0x61200) & ~0x80000000);
-         OUTREG(0x61204, INREG(0x61204) & ~0x00000001);
-         while ((INREG(0x61200) & 0x80000000) || (INREG(0x61204) & 1));
+         OUTREG(PP_STATUS, INREG(PP_STATUS) & ~PP_ON);
+         OUTREG(PP_CONTROL, INREG(PP_CONTROL) & ~POWER_TARGET_ON);
+         while ((INREG(PP_STATUS) & PP_ON) ||
+		(INREG(PP_CONTROL) & POWER_TARGET_ON));
          /* Fix up LVDS */
          OUTREG(LVDS, (INREG(LVDS) | 1<<30) & ~0x80000300);
          xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
diff-tree 4955cd267e7f8ed70e90b2a3de6f93de2ef859c8 (from 73496b765c9783a8a271b4774a44fa263dd47684)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Feb 27 09:37:47 2006 -0800

    Add untested save/restore code, and starting on not using VBEValidateModes

diff --git a/TODO b/TODO
index 0dcae97..ef2bab6 100644
--- a/TODO
+++ b/TODO
@@ -1 +1,2 @@
 - licensing of new files
+- Figure out what exactly doublescan, interlace mean, and see if we support them.
diff --git a/src/i830.h b/src/i830.h
index 11695a2..00d0386 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -377,6 +377,38 @@ typedef struct _I830Rec {
    Bool devicePresence;
 
    OsTimerPtr devicesTimer;
+
+   CARD32 saveDSPACNTR;
+   CARD32 saveDSPBCNTR;
+   CARD32 savePIPEACONF;
+   CARD32 savePIPEBCONF;
+   CARD32 savePIPEASRC;
+   CARD32 savePIPEBSRC;
+   CARD32 saveFPA0;
+   CARD32 saveFPA1;
+   CARD32 saveDPLL_A;
+   CARD32 saveHTOTAL_A;
+   CARD32 saveHBLANK_A;
+   CARD32 saveHSYNC_A;
+   CARD32 saveVTOTAL_A;
+   CARD32 saveVBLANK_A;
+   CARD32 saveVSYNC_A;
+   CARD32 saveDSPASTRIDE;
+   CARD32 saveDSPAPOS;
+   CARD32 saveDSPABASE;
+   CARD32 saveFPB0;
+   CARD32 saveFPB1;
+   CARD32 saveDPLL_B;
+   CARD32 saveHTOTAL_B;
+   CARD32 saveHBLANK_B;
+   CARD32 saveHSYNC_B;
+   CARD32 saveVTOTAL_B;
+   CARD32 saveVBLANK_B;
+   CARD32 saveVSYNC_B;
+   CARD32 saveDSPBSTRIDE;
+   CARD32 saveDSPBPOS;
+   CARD32 saveDSPBBASE;
+
 } I830Rec;
 
 #define I830PTR(p) ((I830Ptr)((p)->driverPrivate))
diff --git a/src/i830_driver.c b/src/i830_driver.c
index de31b6e..b1beafd 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -697,6 +697,7 @@ I830GetBestRefresh(ScrnInfoPtr pScrn, in
    return i;
 }
 
+#if 0
 static int
 SetRefreshRate(ScrnInfoPtr pScrn, int mode, int refresh)
 {
@@ -724,7 +725,6 @@ SetRefreshRate(ScrnInfoPtr pScrn, int mo
       return 0;
 }
 
-#if 0
 static Bool
 SetPowerStatus(ScrnInfoPtr pScrn, int mode)
 {
@@ -2075,6 +2075,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
    int DDCclock = 0;
    char *s;
    DisplayModePtr p, pMon;
+   ClockRangePtr clockRanges;
    pointer pDDCModule = NULL, pVBEModule = NULL;
    Bool enable;
    const char *chipname;
@@ -3225,6 +3226,20 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
    SetPipeAccess(pScrn);
    VBESetModeNames(pScrn->modePool);
 
+#if 0
+   /*
+     * Setup the ClockRanges, which describe what clock ranges are available,
+     * and what sort of modes they can be used for.
+     */
+    clockRanges = xnfcalloc(sizeof(ClockRange), 1);
+    clockRanges->next = NULL;
+    clockRanges->minClock = 12000;	/* XXX: Random number */
+    clockRanges->maxClock = 400000;	/* XXX: May be lower */
+    clockRanges->clockIndex = -1;		/* programmable */
+    clockRanges->interlaceAllowed = TRUE;	/* XXX check this */
+    clockRanges->doubleScanAllowed = FALSE;	/* XXX check this */
+#endif
+
    /*
     * XXX DDC information: There's code in xf86ValidateModes
     * (VBEValidateModes) to set monitor defaults based on DDC information
@@ -3235,12 +3250,23 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
    /* XXX Need to get relevant modes and virtual parameters. */
    /* Do the mode validation without regard to special scanline pitches. */
    SetPipeAccess(pScrn);
+#if 1
    n = VBEValidateModes(pScrn, NULL, pScrn->display->modes, NULL,
 			NULL, 0, MAX_DISPLAY_PITCH, 1,
 			0, MAX_DISPLAY_HEIGHT,
 			pScrn->display->virtualX,
 			pScrn->display->virtualY,
 			memsize, LOOKUP_BEST_REFRESH);
+#else
+    n = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
+			  pScrn->display->modes, clockRanges,
+			  NULL, 256, 4096,
+			  pScrn->bitsPerPixel, 128, 4096,
+			  pScrn->display->virtualX,
+			  pScrn->display->virtualY,
+			  pI830->FbMapSize,
+			  LOOKUP_BEST_REFRESH);
+#endif
    if (n <= 0) {
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
       PreInitCleanup(pScrn);
@@ -3716,6 +3742,39 @@ SaveHWState(ScrnInfoPtr pScrn)
 
    DPRINTF(PFX, "SaveHWState\n");
 
+   /* Save video mode information for native mode-setting. */
+   pI830->saveDSPACNTR = INREG(DSPACNTR);
+   pI830->saveDSPBCNTR = INREG(DSPBCNTR);
+   pI830->savePIPEACONF = INREG(PIPEACONF);
+   pI830->savePIPEBCONF = INREG(PIPEBCONF);
+   pI830->savePIPEASRC = INREG(PIPEASRC);
+   pI830->savePIPEBSRC = INREG(PIPEBSRC);
+   pI830->saveFPA0 = INREG(FPA0);
+   pI830->saveFPA1 = INREG(FPA1);
+   pI830->saveDPLL_A = INREG(DPLL_A);
+   pI830->saveHTOTAL_A = INREG(HTOTAL_A);
+   pI830->saveHBLANK_A = INREG(HBLANK_A);
+   pI830->saveHSYNC_A = INREG(HSYNC_A);
+   pI830->saveVTOTAL_A = INREG(VTOTAL_A);
+   pI830->saveVBLANK_A = INREG(VBLANK_A);
+   pI830->saveVSYNC_A = INREG(VSYNC_A);
+   pI830->saveDSPASTRIDE = INREG(DSPASTRIDE);
+   pI830->saveDSPAPOS = INREG(DSPAPOS);
+   pI830->saveDSPABASE = INREG(DSPABASE);
+
+   pI830->saveFPB0 = INREG(FPB0);
+   pI830->saveFPB1 = INREG(FPB1);
+   pI830->saveDPLL_B = INREG(DPLL_B);
+   pI830->saveHTOTAL_B = INREG(HTOTAL_B);
+   pI830->saveHBLANK_B = INREG(HBLANK_B);
+   pI830->saveHSYNC_B = INREG(HSYNC_B);
+   pI830->saveVTOTAL_B = INREG(VTOTAL_B);
+   pI830->saveVBLANK_B = INREG(VBLANK_B);
+   pI830->saveVSYNC_B = INREG(VSYNC_B);
+   pI830->saveDSPBSTRIDE = INREG(DSPBSTRIDE);
+   pI830->saveDSPBPOS = INREG(DSPBPOS);
+   pI830->saveDSPBBASE = INREG(DSPBBASE);
+
    if (I830IsPrimary(pScrn) && pI830->pipe != pI830->origPipe)
       SetBIOSPipe(pScrn, pI830->origPipe);
    else
@@ -3788,6 +3847,7 @@ RestoreHWState(ScrnInfoPtr pScrn)
    vgaRegPtr vgaReg = &hwp->SavedReg;
    VESAPtr pVesa;
    Bool restored = FALSE;
+   CARD32 temp;
 
    DPRINTF(PFX, "RestoreHWState\n");
 
@@ -3852,6 +3912,54 @@ RestoreHWState(ScrnInfoPtr pScrn)
    vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS);
    vgaHWLock(hwp);
 
+   /* First, disable display planes */
+   temp = INREG(DSPACNTR);
+   OUTREG(DSPACNTR, temp & ~DISPLAY_PLANE_ENABLE);
+   temp = INREG(DSPBCNTR);
+   OUTREG(DSPBCNTR, temp & ~DISPLAY_PLANE_ENABLE);
+
+   /* Next, disable display pipes */
+   temp = INREG(PIPEACONF);
+   OUTREG(PIPEACONF, temp & ~PIPEACONF_ENABLE);
+   temp = INREG(PIPEBCONF);
+   OUTREG(PIPEBCONF, temp & ~PIPEBCONF_ENABLE);
+
+   /* XXX: Wait for a vblank */
+   sleep(1);
+
+   OUTREG(FPA0, pI830->saveFPA0);
+   OUTREG(FPA1, pI830->saveFPA1);
+   OUTREG(DPLL_A, pI830->saveDPLL_A);
+   OUTREG(HTOTAL_A, pI830->saveHTOTAL_A);
+   OUTREG(HBLANK_A, pI830->saveHBLANK_A);
+   OUTREG(HSYNC_A, pI830->saveHSYNC_A);
+   OUTREG(VTOTAL_A, pI830->saveVTOTAL_A);
+   OUTREG(VBLANK_A, pI830->saveVBLANK_A);
+   OUTREG(VSYNC_A, pI830->saveVSYNC_A);
+   OUTREG(DSPASTRIDE, pI830->saveDSPASTRIDE);
+   OUTREG(DSPAPOS, pI830->saveDSPAPOS);
+   OUTREG(DSPABASE, pI830->saveDSPABASE);
+
+   OUTREG(FPB0, pI830->saveFPB0);
+   OUTREG(FPB1, pI830->saveFPB1);
+   OUTREG(DPLL_B, pI830->saveDPLL_B);
+   OUTREG(HTOTAL_B, pI830->saveHTOTAL_B);
+   OUTREG(HBLANK_B, pI830->saveHBLANK_B);
+   OUTREG(HSYNC_B, pI830->saveHSYNC_B);
+   OUTREG(VTOTAL_B, pI830->saveVTOTAL_B);
+   OUTREG(VBLANK_B, pI830->saveVBLANK_B);
+   OUTREG(VSYNC_B, pI830->saveVSYNC_B);
+   OUTREG(DSPBSTRIDE, pI830->saveDSPBSTRIDE);
+   OUTREG(DSPBPOS, pI830->saveDSPBPOS);
+   OUTREG(DSPBBASE, pI830->saveDSPBBASE);
+
+   OUTREG(DSPACNTR, pI830->saveDSPACNTR);
+   OUTREG(DSPBCNTR, pI830->saveDSPBCNTR);
+   OUTREG(PIPEACONF, pI830->savePIPEACONF);
+   OUTREG(PIPEBCONF, pI830->savePIPEBCONF);
+   OUTREG(PIPEASRC, pI830->savePIPEASRC);
+   OUTREG(PIPEBSRC, pI830->savePIPEBSRC);
+
    return TRUE;
 }
 
diff-tree 73496b765c9783a8a271b4774a44fa263dd47684 (from 9fe316da7390918dd88940087567314b6f253981)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Feb 27 09:26:51 2006 -0800

    Change an if statement to a more obvious but equivalent case statement.

diff --git a/src/i830_display.c b/src/i830_display.c
index 340a51b..0fa0405 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -279,8 +279,20 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
     dpll = DPLL_VCO_ENABLE | DPLL_VGA_MODE_DIS;
     dpll |= DPLLB_MODE_DAC_SERIAL; /* XXX: LVDS */
     dpll |= (1 << (p1 - 1)) << 16;
-    if (p2 == 5 || p2 == 7)
+    switch (p2) {
+    case 5:
 	dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5;
+	break;
+    case 7:
+	dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7;
+	break;
+    case 10:
+	dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10;
+	break;
+    case 14:
+	dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
+	break;
+    }
     dpll |= PLL_REF_INPUT_DREFCLK; /* XXX: TV/LVDS */
     dpll |= SDV0_DEFAULT_MULTIPLIER;
 
diff-tree 9fe316da7390918dd88940087567314b6f253981 (from 1555229f29fa7479d6a7a51f451d04a5ef3460bd)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Thu Feb 23 13:49:31 2006 -0800

    Add the manpage's possible names when generated.

diff --git a/man/.gitignore b/man/.gitignore
index 282522d..77b4362 100644
--- a/man/.gitignore
+++ b/man/.gitignore
@@ -1,2 +1,4 @@
 Makefile
 Makefile.in
+i810.4
+i810.4x
diff-tree 1555229f29fa7479d6a7a51f451d04a5ef3460bd (from 139d33ac807fb0fc35c37c3689a6e80238199442)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Thu Feb 23 13:48:26 2006 -0800

    Move .cvsignore to .gitignore

diff --git a/.cvsignore b/.cvsignore
deleted file mode 100644
index c7bcbee..0000000
--- a/.cvsignore
+++ /dev/null
@@ -1,20 +0,0 @@
-Makefile
-Makefile.in
-*.la
-*.lo
-aclocal.m4
-autom4te.cache
-compile
-config.guess
-config.h
-config.h.in
-config.log
-config.status
-config.sub
-configure
-depcomp
-install-sh
-libtool
-ltmain.sh
-missing
-stamp-h1
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c7bcbee
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,20 @@
+Makefile
+Makefile.in
+*.la
+*.lo
+aclocal.m4
+autom4te.cache
+compile
+config.guess
+config.h
+config.h.in
+config.log
+config.status
+config.sub
+configure
+depcomp
+install-sh
+libtool
+ltmain.sh
+missing
+stamp-h1
diff --git a/man/.cvsignore b/man/.cvsignore
deleted file mode 100644
index 282522d..0000000
--- a/man/.cvsignore
+++ /dev/null
@@ -1,2 +0,0 @@
-Makefile
-Makefile.in
diff --git a/man/.gitignore b/man/.gitignore
new file mode 100644
index 0000000..282522d
--- /dev/null
+++ b/man/.gitignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/src/.cvsignore b/src/.cvsignore
deleted file mode 100644
index 9730646..0000000
--- a/src/.cvsignore
+++ /dev/null
@@ -1,6 +0,0 @@
-.deps
-.libs
-Makefile
-Makefile.in
-*.la
-*.lo
diff --git a/src/.gitignore b/src/.gitignore
new file mode 100644
index 0000000..9730646
--- /dev/null
+++ b/src/.gitignore
@@ -0,0 +1,6 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.la
+*.lo
diff --git a/src/xvmc/.cvsignore b/src/xvmc/.cvsignore
deleted file mode 100644
index 9730646..0000000
--- a/src/xvmc/.cvsignore
+++ /dev/null
@@ -1,6 +0,0 @@
-.deps
-.libs
-Makefile
-Makefile.in
-*.la
-*.lo
diff --git a/src/xvmc/.gitignore b/src/xvmc/.gitignore
new file mode 100644
index 0000000..9730646
--- /dev/null
+++ b/src/xvmc/.gitignore
@@ -0,0 +1,6 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.la
+*.lo
diff-tree 139d33ac807fb0fc35c37c3689a6e80238199442 (from be6216cd8c6a47dd053240f7a5d1445b61f79038)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Thu Feb 23 13:46:30 2006 -0800

    Initial add of native CRT modesetting code.

diff --git a/TODO b/TODO
new file mode 100644
index 0000000..0dcae97
--- /dev/null
+++ b/TODO
@@ -0,0 +1 @@
+- licensing of new files
diff --git a/src/Makefile.am b/src/Makefile.am
index c64c203..16e9812 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -47,6 +47,8 @@ i810_drv_la_SOURCES = \
          i830_common.h \
          i830_cursor.c \
          i830_dga.c \
+	 i830_display.c \
+	 i830_display.h \
          i830_driver.c \
          i830.h \
          i830_io.c \
diff --git a/src/i810_reg.h b/src/i810_reg.h
index e52375f..8afe855 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -660,8 +660,32 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 #define DPLL_A		0x06014
 #define DPLL_B		0x06018
+# define DPLL_VCO_ENABLE			(1 << 31)
+# define DPLL_DVO_HIGH_SPEED			(1 << 30)
+# define DPLL_SYNCLOCK_ENABLE			(1 << 29)
+# define DPLL_VGA_MODE_DIS			(1 << 28)
+# define DPLLB_MODE_DAC_SERIAL			(1 << 26)
+# define DPLLB_MODE_LVDS			(2 << 26)
+# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10	(0 << 24)
+# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5		(1 << 24)
+# define DPLLB_LVDS_P2_CLOCK_DIV_14		(0 << 24)
+# define DPLLB_LVDS_P2_CLOCK_DIV_7		(1 << 24)
+# define DPLL_P2_CLOCK_DIV_MASK			0x03000000
+# define DPLL_FPA01_P1_POST_DIV_MASK		0x00ff0000
+# define PLL_REF_INPUT_DREFCLK			(0 << 13)
+# define PLL_REF_INPUT_TVCLKIN			(2 << 13)
+# define PLLB_REF_INPUT_SPREADSPECTRUMIN	(3 << 13)
+# define DISPLAY_RATE_SELECT_FPA1		(1 << 8)
+# define SDVO_MULTIPLIER_MASK			0x000000ff
+# define SDV0_DEFAULT_MULTIPLIER		0x00000003
+
 #define FPA0		0x06040
 #define FPA1		0x06044
+#define FPB0		0x06048
+#define FPB1		0x0604c
+# define FP_N_DIV_MASK				0x003f0000
+# define FP_M1_DIV_MASK				0x00003f00
+# define FP_M2_DIV_MASK				0x0000003f
 
 #define I830_HTOTAL_MASK 	0xfff0000
 #define I830_HACTIVE_MASK	0x7ff
diff --git a/src/i830_display.c b/src/i830_display.c
new file mode 100644
index 0000000..340a51b
--- /dev/null
+++ b/src/i830_display.c
@@ -0,0 +1,347 @@
+#include "xf86.h"
+#include "xf86_ansic.h"
+#include "i830.h"
+
+static int i830_clock(int refclk, int m1, int m2, int n, int p1, int p2)
+{
+    return (refclk * (5 * (m1 + 2) + (m2 + 2)) / (n + 2)) / (p1 * p2);
+}
+
+static void
+i830PrintPll(char *prefix, int refclk, int m1, int m2, int n, int p1, int p2)
+{
+    int dotclock;
+
+    dotclock = i830_clock(refclk, m1, m2, n, p1, p2);
+
+    ErrorF("%s: dotclock %d ((%d, %d), %d, (%d, %d))\n", prefix, dotclock,
+	   m1, m2, n, p1, p2);
+}
+
+static Bool
+i830PllIsValid(int refclk, int m1, int m2, int n, int p1, int p2)
+{
+    int p, m, vco, dotclock;
+
+    p = p1 + p2;
+    m = 5 * (m1 + 2) + (m2 + 2);
+    vco = refclk * m / (n + 2);
+    dotclock = i830_clock(refclk, m1, m2, n, p1, p2);
+
+    if (p1 < 1 || p1 > 8)
+	return FALSE;
+    if (p < 5 || p > 80) /* XXX: 7-98 for LVDS */
+	return FALSE;
+    if (m2 < 5 || m2 > 9)
+	return FALSE;
+    if (m1 < 10 || m1 > 20)
+	return FALSE;
+    if (m1 <= m2)
+	return FALSE;
+    if (m < 70 || m > 120)
+	return FALSE;
+    if (n + 2 < 3 || n + 2 > 8)	/*XXX: Is the +2 right? */
+	return FALSE;
+    if (vco < 1400000 || vco > 2800000)
+	return FALSE;
+    /* XXX: We may need to be checking "Dot clock" depending on the multiplier,
+     * output, etc., rather than just a single range.
+     */
+    if (dotclock < 20000 || dotclock > 400000)
+	return FALSE;
+
+    return TRUE;
+}
+
+#if 0
+int
+i830ReadAndReportPLL(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD32 temp, dpll;
+    int refclk, m1, m2, n, p1, p2;
+
+    refclk = 96000;	/* XXX: The refclk may be 100000 for the LVDS */
+
+    dpll = INREG(DPLL_A);
+    switch ((dpll & DPLL_FPA01_P1_POST_DIV_MASK) >> 16) {
+    case 0x01:
+	p1 = 1;
+	break;
+    case 0x02:
+	p1 = 2;
+	break;
+    case 0x04:
+	p1 = 3;
+	break;
+    case 0x08:
+	p1 = 4;
+	break;
+    case 0x10:
+	p1 = 5;
+	break;
+    case 0x20:
+	p1 = 6;
+	break;
+    case 0x40:
+	p1 = 7;
+	break;
+    case 0x80:
+	p1 = 8;
+	break;
+    default:
+	FatalError("Unknown p1 clock div: 0x%x\n",
+		   dpll & DPLL_FPA01_P1_POST_DIV_MASK);
+    }
+
+    switch (dpll & DPLL_P2_CLOCK_DIV_MASK) {
+    case DPLL_DAC_SERIAL_P2_CLOCK_DIV_5:
+	p2 = 5;
+	break;
+    case DPLL_DAC_SERIAL_P2_CLOCK_DIV_10:
+	p2 = 10;
+	break;
+/* XXX:
+    case DPLLB_LVDS_P2_CLOCK_DIV_7:
+	p2 = 7;
+	break;
+    case DPLLB_LVDS_P2_CLOCK_DIV_14:
+	p2 = 14;
+	break;
+*/
+    default:
+	FatalError("Unknown p2 clock div: 0x%x\n", dpll & DPLL_P2_CLOCK_DIV_MASK);
+    }
+
+    if (dpll & DISPLAY_RATE_SELECT_FPA1)
+	temp = INREG(FPA1);
+    else
+	temp = INREG(FPA0);
+    n = (temp & FP_N_DIV_MASK) >> 16;
+    m1 = (temp & FP_M1_DIV_MASK) >> 8;
+    m2 = (temp & FP_M2_DIV_MASK);
+
+    i830PrintPll("FPA", refclk, m1, m2, n, p1, p2);
+    ErrorF("clock settings for FPA0 look %s\n",
+	   i830PllIsValid(refclk, m1, m2, n, p1, p2) ? "good" : "bad");
+    ErrorF("clock regs: 0x%08x, 0x%08x\n", dpll, temp);    
+}
+#endif
+
+static Bool
+i830FindBestPLL(int target, int refclk, int *outm1, int *outm2, int *outn,
+		int *outp1, int *outp2)
+{
+    int m1, m2, n, p1, p2;
+    int err = target;
+
+    if (target < 200000)	/* XXX: LVDS */
+	p2 = 10;
+    else
+	p2 = 5;
+    for (m1 = 10; m1 <= 20; m1++) {
+	for (m2 = 5; m2 < 9; m2++) {
+	    for (n = 1; n <= 6; n++) {
+		for (p1 = 1; p1 <= 8; p1++) {
+		    int clock, this_err;
+
+		    if (!i830PllIsValid(refclk, m1, m2, n, p1, p2))
+			continue;
+
+		    clock = i830_clock(refclk, m1, m2, n, p1, p2);
+		    this_err = abs(clock - target);
+		    if (this_err < err) {
+			*outm1 = m1;
+			*outm2 = m2;
+			*outn = n;
+			*outp1 = p1;
+			*outp2 = p2;
+			err = this_err;
+		    }
+		}
+	    }
+	}
+    }
+
+    return (err != target);
+}
+
+/*
+ * xf86SetModeCrtc
+ *
+ * Copied from xf86Mode.c because it's static there, and i830 likes to hand us
+ * these hand-rolled modes.
+ *
+ * Initialises the Crtc parameters for a mode.  The initialisation includes
+ * adjustments for interlaced and double scan modes.
+ */
+static void
+xf86SetModeCrtc(DisplayModePtr p, int adjustFlags)
+{
+    if ((p == NULL) /* XXX: || ((p->type & M_T_CRTC_C) == M_T_BUILTIN)*/)
+	return;
+
+    p->CrtcHDisplay             = p->HDisplay;
+    p->CrtcHSyncStart           = p->HSyncStart;
+    p->CrtcHSyncEnd             = p->HSyncEnd;
+    p->CrtcHTotal               = p->HTotal;
+    p->CrtcHSkew                = p->HSkew;
+    p->CrtcVDisplay             = p->VDisplay;
+    p->CrtcVSyncStart           = p->VSyncStart;
+    p->CrtcVSyncEnd             = p->VSyncEnd;
+    p->CrtcVTotal               = p->VTotal;
+    if (p->Flags & V_INTERLACE) {
+	if (adjustFlags & INTERLACE_HALVE_V) {
+	    p->CrtcVDisplay         /= 2;
+	    p->CrtcVSyncStart       /= 2;
+	    p->CrtcVSyncEnd         /= 2;
+	    p->CrtcVTotal           /= 2;
+	}
+	/* Force interlaced modes to have an odd VTotal */
+	/* maybe we should only do this when INTERLACE_HALVE_V is set? */
+	p->CrtcVTotal |= 1;
+    }
+
+    if (p->Flags & V_DBLSCAN) {
+        p->CrtcVDisplay         *= 2;
+        p->CrtcVSyncStart       *= 2;
+        p->CrtcVSyncEnd         *= 2;
+        p->CrtcVTotal           *= 2;
+    }
+    if (p->VScan > 1) {
+        p->CrtcVDisplay         *= p->VScan;
+        p->CrtcVSyncStart       *= p->VScan;
+        p->CrtcVSyncEnd         *= p->VScan;
+        p->CrtcVTotal           *= p->VScan;
+    }
+    p->CrtcHAdjusted = FALSE;
+    p->CrtcVAdjusted = FALSE;
+
+    /*
+     * XXX
+     *
+     * The following is taken from VGA, but applies to other cores as well.
+     */
+    p->CrtcVBlankStart = min(p->CrtcVSyncStart, p->CrtcVDisplay);
+    p->CrtcVBlankEnd = max(p->CrtcVSyncEnd, p->CrtcVTotal);
+    if ((p->CrtcVBlankEnd - p->CrtcVBlankStart) >= 127) {
+        /* 
+         * V Blanking size must be < 127.
+         * Moving blank start forward is safer than moving blank end
+         * back, since monitors clamp just AFTER the sync pulse (or in
+         * the sync pulse), but never before.
+         */
+        p->CrtcVBlankStart = p->CrtcVBlankEnd - 127;
+	/*
+	 * If VBlankStart is now > VSyncStart move VBlankStart
+	 * to VSyncStart using the maximum width that fits into
+	 * VTotal.
+	 */
+	if (p->CrtcVBlankStart > p->CrtcVSyncStart) {
+	    p->CrtcVBlankStart = p->CrtcVSyncStart;
+	    p->CrtcVBlankEnd = min(p->CrtcHBlankStart + 127, p->CrtcVTotal);
+	}
+    }
+    p->CrtcHBlankStart = min(p->CrtcHSyncStart, p->CrtcHDisplay);
+    p->CrtcHBlankEnd = max(p->CrtcHSyncEnd, p->CrtcHTotal);
+
+    if ((p->CrtcHBlankEnd - p->CrtcHBlankStart) >= 63 * 8) {
+        /*
+         * H Blanking size must be < 63*8. Same remark as above.
+         */
+        p->CrtcHBlankStart = p->CrtcHBlankEnd - 63 * 8;
+	if (p->CrtcHBlankStart > p->CrtcHSyncStart) {
+	    p->CrtcHBlankStart = p->CrtcHSyncStart;
+	    p->CrtcHBlankEnd = min(p->CrtcHBlankStart + 63 * 8, p->CrtcHTotal);
+	}
+    }
+}
+
+void
+i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    int m1, m2, n, p1, p2;
+    CARD32 dpll = 0, fp = 0, temp;
+    CARD32 htot, hblank, hsync, vtot, vblank, vsync;
+    CARD32 pipesrc, dspsize;
+    Bool ok;
+    int refclk = 96000;
+
+    xf86SetModeCrtc(pMode, 0);
+
+    ErrorF("Requested pix clock: %d\n", pMode->Clock);
+
+    ok = i830FindBestPLL(pMode->Clock, refclk, &m1, &m2, &n, &p1, &p2);
+    if (!ok)
+	FatalError("Couldn't find PLL settings for mode!\n");
+
+    dpll = DPLL_VCO_ENABLE | DPLL_VGA_MODE_DIS;
+    dpll |= DPLLB_MODE_DAC_SERIAL; /* XXX: LVDS */
+    dpll |= (1 << (p1 - 1)) << 16;
+    if (p2 == 5 || p2 == 7)
+	dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5;
+    dpll |= PLL_REF_INPUT_DREFCLK; /* XXX: TV/LVDS */
+    dpll |= SDV0_DEFAULT_MULTIPLIER;
+
+    fp = (n << 16) | (m1 << 8) | m2;
+
+    htot = (pMode->CrtcHDisplay - 1) | ((pMode->CrtcHTotal - 1) << 16);
+    hblank = (pMode->CrtcHBlankStart - 1) | ((pMode->CrtcHBlankEnd - 1) << 16);
+    hsync = (pMode->CrtcHSyncStart - 1) | ((pMode->CrtcHSyncEnd - 1) << 16);
+    vtot = (pMode->CrtcVDisplay - 1) | ((pMode->CrtcVTotal - 1) << 16);
+    vblank = (pMode->CrtcVBlankStart - 1) | ((pMode->CrtcVBlankEnd - 1) << 16);
+    vsync = (pMode->CrtcVSyncStart - 1) | ((pMode->CrtcVSyncEnd - 1) << 16);
+    pipesrc = ((pMode->HDisplay - 1) << 16) | (pMode->VDisplay - 1);
+    dspsize = ((pMode->VDisplay - 1) << 16) | (pMode->HDisplay - 1);
+
+    i830PrintPll("chosen", refclk, m1, m2, n, p1, p2);
+    ErrorF("clock settings for chosen look %s\n",
+	   i830PllIsValid(refclk, m1, m2, n, p1, p2) ? "good" : "bad");
+    ErrorF("clock regs: 0x%08x, 0x%08x\n", dpll, fp);
+
+    /* First, disable display planes */
+    temp = INREG(DSPACNTR);
+    OUTREG(DSPACNTR, temp & ~DISPLAY_PLANE_ENABLE);
+    temp = INREG(DSPBCNTR);
+    OUTREG(DSPBCNTR, temp & ~DISPLAY_PLANE_ENABLE);
+
+    /* Next, disable display pipes */
+    temp = INREG(PIPEACONF);
+    OUTREG(PIPEACONF, temp & ~PIPEACONF_ENABLE);
+    temp = INREG(PIPEBCONF);
+    OUTREG(PIPEBCONF, temp & ~PIPEBCONF_ENABLE);
+
+    /* XXX: Wait for a vblank */
+    sleep(1);
+
+    /* Set up display timings and PLLs for the pipe.  XXX: Choose pipe! */
+    OUTREG(FPA0, fp);
+    OUTREG(DPLL_A, dpll);
+    OUTREG(HTOTAL_A, htot);
+    OUTREG(HBLANK_A, hblank);
+    OUTREG(HSYNC_A, hsync);
+    OUTREG(VTOTAL_A, vtot);
+    OUTREG(VBLANK_A, vblank);
+    OUTREG(VSYNC_A, vsync);
+    OUTREG(DSPABASE, 0); /* XXX: Base placed elsewhere? */
+    /*OUTREG(DSPASTRIDE, pScrn->displayWidth);*/
+    /*OUTREG(DSPAPOS, 0);*/
+    OUTREG(PIPEASRC, pipesrc);
+    OUTREG(DSPASIZE, dspsize);
+
+    /* Turn pipes and planes back on */
+    /*if (pI830->planeEnabled[0]) {*/
+	temp = INREG(PIPEACONF);
+	OUTREG(PIPEACONF, temp | PIPEACONF_ENABLE);
+	temp = INREG(DSPACNTR);
+	OUTREG(DSPACNTR, temp | DISPLAY_PLANE_ENABLE);
+    /*}
+
+    if (pI830->planeEnabled[1]) {
+	temp = INREG(PIPEBCONF);
+	OUTREG(PIPEBCONF, temp | PIPEBCONF_ENABLE);
+	temp = INREG(DSPBCNTR);
+	OUTREG(DSPBCNTR, temp | DISPLAY_PLANE_ENABLE);
+    }*/
+}
diff --git a/src/i830_display.h b/src/i830_display.h
new file mode 100644
index 0000000..6cadd75
--- /dev/null
+++ b/src/i830_display.h
@@ -0,0 +1 @@
+void i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 622565c..de31b6e 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -181,6 +181,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "vbeModes.h"
 #include "shadow.h"
 #include "i830.h"
+#include "i830_display.h"
 
 #ifdef XF86DRI
 #include "dri.h"
@@ -273,8 +274,10 @@ static void I830BIOSAdjustFrame(int scrn
 static Bool I830BIOSCloseScreen(int scrnIndex, ScreenPtr pScreen);
 static Bool I830BIOSSaveScreen(ScreenPtr pScreen, int unblack);
 static Bool I830BIOSEnterVT(int scrnIndex, int flags);
+#if 0
 static Bool I830VESASetVBEMode(ScrnInfoPtr pScrn, int mode,
 			       VbeCRTCInfoBlock *block);
+#endif
 static CARD32 I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg);
 static Bool SetPipeAccess(ScrnInfoPtr pScrn);
 
@@ -3299,6 +3302,8 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
       p = p->next;
    } while (p != NULL && p != pScrn->modes);
 
+   xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
+
    pScrn->currentMode = pScrn->modes;
 
 #ifndef USE_PITCHES
@@ -3891,6 +3896,7 @@ static void I830SetCloneVBERefresh(ScrnI
    }
 }
 
+#if 0
 static Bool
 I830VESASetVBEMode(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock * block)
 {
@@ -4038,6 +4044,7 @@ I830VESASetVBEMode(ScrnInfoPtr pScrn, in
 
    return ret;
 }
+#endif
 
 static Bool
 I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
@@ -4075,6 +4082,7 @@ I830VESASetMode(ScrnInfoPtr pScrn, Displ
 
    SetPipeAccess(pScrn);
 
+#if 0
    if (I830VESASetVBEMode(pScrn, mode, data->block) == FALSE) {
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Set VBE Mode failed!\n");
       return FALSE;
@@ -4102,6 +4110,7 @@ I830VESASetMode(ScrnInfoPtr pScrn, Displ
       SetPipeAccess(pScrn);
       VBESetGetDACPaletteFormat(pVbe, 8);
    }
+#endif
 
    /* XXX Fix plane A with pipe A, and plane B with pipe B. */
    planeA = INREG(DSPACNTR);
@@ -4269,7 +4278,7 @@ I830VESASetMode(ScrnInfoPtr pScrn, Displ
       }
    }
 
-#if 0
+#if 1
    /* Print out some CRTC/display information. */
    temp = INREG(HTOTAL_A);
    ErrorF("Horiz active: %d, Horiz total: %d\n", temp & 0x7ff,
@@ -4337,6 +4346,8 @@ I830VESASetMode(ScrnInfoPtr pScrn, Displ
    ErrorF("Plane B size %d %d\n", temp & 0xffff, (temp & 0xffff0000) >> 16);
 #endif
 
+   i830SetMode(pScrn, pMode);
+
    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Mode bandwidth is %d Mpixel/s\n",
 	      pMode->HDisplay * pMode->VDisplay * refresh / 1000000);
 



More information about the xorg-commit mailing list