xf86-video-intel: Branch 'exa' - 1090 commits - ChangeLog configure.ac .gitignore Makefile.am man/.cvsignore man/i810.man man/intel.man man/Makefile.am README README.sgml 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_sf_rotation.g4a src/exa_sf_rotation_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/exa_wm_rotation.g4a src/exa_wm_rotation_prog.h src/fix.5c src/.gitignore src/i2c_vid.h src/i810_accel.c src/i810_dri.c src/i810_dri.h src/i810_driver.c src/i810.h src/i810_reg.h src/i810_video.c src/i810_wmark.c src/i830_accel.c src/i830_bios.c src/i830_bios.h src/i830_common.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_dri.h src/i830_driver.c src/i830_dvo.c src/i830_exa.c src/i830_exa_render.c src/i830.h src/i830_i2c.c src/i830_lvds.c src/i830_memory.c src/i830_modes.c src/i830_quirks.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_exa_render.c 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/packed_yuv_sf.g4a src/packed_yuv_wm.g4a 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/tfp410/Makefile.am src/tfp410/tfp410.c src/tfp410/tfp410.h src/tfp410/tfp410_module.c src/tfp410/tfp410_reg.h src/tv.5c src/wm_prog.h src/xvmc/.cvsignore src/xvmc/.gitignore src/xvmc/I810XvMC.c src/xvmc/I810XvMC.h src/xvmc/Makefile.am

Zhenyu Wang zhen at kemper.freedesktop.org
Thu Sep 27 19:00:13 PDT 2007


 .gitignore                        |    5 
 ChangeLog                         |  138 
 Makefile.am                       |    7 
 README                            |  281 -
 README.sgml                       |  133 
 configure.ac                      |  123 
 man/.cvsignore                    |    2 
 man/Makefile.am                   |   13 
 man/i810.man                      |  223 
 man/intel.man                     |  215 
 src/Makefile.am                   |  148 
 src/bios_reader/.gitignore        |    2 
 src/bios_reader/Makefile.am       |   13 
 src/bios_reader/bios_dumper.c     |   99 
 src/bios_reader/bios_reader.c     |  158 
 src/brw_structs.h                 |    2 
 src/ch7017/Makefile.am            |   15 
 src/ch7017/ch7017.c               |  304 +
 src/ch7017/ch7017_module.c        |   36 
 src/ch7017/ch7017_reg.h           |  150 
 src/ch7xxx/Makefile.am            |   16 
 src/ch7xxx/ch7xxx.c               |  309 +
 src/ch7xxx/ch7xxx.h               |   31 
 src/ch7xxx/ch7xxx_module.c        |   35 
 src/ch7xxx/ch7xxx_reg.h           |   80 
 src/common.h                      |  158 
 src/exa_sf.g4a                    |   45 
 src/exa_sf_mask.g4a               |   78 
 src/exa_sf_mask_prog.h            |   25 
 src/exa_sf_prog.h                 |   17 
 src/exa_sf_rotation.g4a           |   55 
 src/exa_sf_rotation_prog.h        |   20 
 src/exa_wm_maskca.g4a             |  228 
 src/exa_wm_maskca_prog.h          |   95 
 src/exa_wm_maskca_srcalpha.g4a    |  228 
 src/exa_wm_maskca_srcalpha_prog.h |   95 
 src/exa_wm_masknoca.g4a           |  228 
 src/exa_wm_masknoca_prog.h        |   95 
 src/exa_wm_nomask.g4a             |  169 
 src/exa_wm_nomask_prog.h          |   70 
 src/exa_wm_rotation.g4a           |  184 
 src/exa_wm_rotation_prog.h        |   70 
 src/fix.5c                        |   14 
 src/i2c_vid.h                     |  136 
 src/i810.h                        |   18 
 src/i810_accel.c                  |    3 
 src/i810_dri.c                    |   50 
 src/i810_dri.h                    |    4 
 src/i810_driver.c                 |  371 +
 src/i810_reg.h                    | 1316 +++++
 src/i810_video.c                  |    4 
 src/i810_wmark.c                  |   17 
 src/i830.h                        |  703 +-
 src/i830_accel.c                  |   79 
 src/i830_bios.c                   |  298 +
 src/i830_bios.h                   |  157 
 src/i830_common.h                 |   30 
 src/i830_crt.c                    |  434 +
 src/i830_cursor.c                 |  796 ---
 src/i830_debug.c                  |  974 +++
 src/i830_debug.h                  |   34 
 src/i830_dga.c                    |  446 -
 src/i830_display.c                | 1712 ++++++
 src/i830_display.h                |   42 
 src/i830_dri.c                    |  869 ++-
 src/i830_dri.h                    |    4 
 src/i830_driver.c                 | 9780 ++++++++------------------------------
 src/i830_dvo.c                    |  516 ++
 src/i830_exa.c                    |  519 +-
 src/i830_exa_render.c             |  514 -
 src/i830_i2c.c                    |  387 +
 src/i830_lvds.c                   |  636 ++
 src/i830_memory.c                 | 3617 ++++++--------
 src/i830_modes.c                  |  815 ---
 src/i830_quirks.c                 |   94 
 src/i830_randr.c                  |  355 -
 src/i830_reg.h                    |   34 
 src/i830_render.c                 |  637 ++
 src/i830_rotate.c                 | 1164 ----
 src/i830_sdvo.c                   | 1335 +++++
 src/i830_sdvo.h                   |   35 
 src/i830_sdvo_regs.h              |  329 +
 src/i830_tv.c                     | 1736 ++++++
 src/i830_video.c                  | 5478 ++++++++-------------
 src/i830_video.h                  |   22 
 src/i830_xaa.c                    |  293 -
 src/i915_reg.h                    |   11 
 src/i915_render.c                 |  274 -
 src/i915_video.c                  |  218 
 src/i965_render.c                 | 1134 ++++
 src/i965_video.c                  |  855 +++
 src/ivch/Makefile.am              |   15 
 src/ivch/ivch.c                   |  361 +
 src/ivch/ivch_module.c            |   64 
 src/ivch/ivch_reg.h               |  291 +
 src/local_xf86Rename.h            |   23 
 src/packed_yuv_sf.g4a             |   28 
 src/packed_yuv_wm.g4a             |   30 
 src/reg_dumper/.gitignore         |    1 
 src/reg_dumper/Makefile.am        |   12 
 src/reg_dumper/main.c             |  111 
 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/tfp410/Makefile.am            |   16 
 src/tfp410/tfp410.c               |  265 +
 src/tfp410/tfp410.h               |   33 
 src/tfp410/tfp410_module.c        |   38 
 src/tfp410/tfp410_reg.h           |  104 
 src/tv.5c                         |  128 
 src/wm_prog.h                     |    2 
 src/xvmc/I810XvMC.c               |  325 -
 src/xvmc/I810XvMC.h               |    1 
 src/xvmc/Makefile.am              |    6 
 118 files changed, 27418 insertions(+), 18686 deletions(-)

New commits:
diff-tree 5e04510b3bb2b78b980bd273c68bfc7204384011 (from 64756fb6344b9871d57ed1c2ebf89165193c7665)
Author: Zhenyu Wang <zhenyu.z.wang at intel.com>
Date:   Fri Sep 28 17:49:42 2007 +0800

    don't bother to memcpy for some small updates

diff --git a/src/i965_render.c b/src/i965_render.c
index 9fe5bdd..792fe1a 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -765,7 +765,7 @@ i965_prepare_composite(int op, PicturePt
 			&src_blend, &dst_blend);
     cc_state_local.cc6.src_blend_factor = src_blend;
     cc_state_local.cc6.dest_blend_factor = dst_blend;
-    memcpy (&cc_state->cc6, &cc_state_local.cc6, sizeof (cc_state_local.cc6));
+    cc_state->cc6 = cc_state_local.cc6;
 
     /* Set up the state buffer for the destination surface */
     i965_get_dest_format(pDstPicture, &dst_format);
@@ -866,9 +866,8 @@ i965_prepare_composite(int op, PicturePt
     else
 	sf_kernel_num = 0;
 
-    sf_state_local.thread0.kernel_start_pointer =
+    sf_state->thread0.kernel_start_pointer =
 	(state_base_offset + sf_kernel_offset[sf_kernel_num]) >> 6;
-    memcpy(&sf_state->thread0, &sf_state_local.thread0, sizeof(sf_state_local.thread0));
 
    /* Set up the PS kernel (dispatched by WM) */
     if (pMask) {
diff-tree 64756fb6344b9871d57ed1c2ebf89165193c7665 (from 53c3d217fe45af4e38bf1c2efedb27e2b2879706)
Author: Zhenyu Wang <zhenyu.z.wang at intel.com>
Date:   Fri Sep 28 17:34:20 2007 +0800

    move i965 static state setup
    
    It should also be used in XAA case, and initialize it early.

diff --git a/src/i830.h b/src/i830.h
index b1f1f68..548bab2 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -83,6 +83,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 Bool I830EXAInit(ScreenPtr pScreen);
 #define EXA_LINEAR_EXTRA	(64*1024)
 unsigned long long I830TexOffsetStart(PixmapPtr pPix);
+void i965_setup_state_static(ScrnInfoPtr);
 #endif
 
 #ifdef I830_USE_XAA
diff --git a/src/i830_driver.c b/src/i830_driver.c
index dc27170..449c788 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2767,7 +2767,11 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       }
    }
 
-    if (pScrn->virtualX > pScrn->displayWidth)
+   /* i965 static state buffer */
+   if (IS_I965G(pI830) && pI830->useEXA)
+       i965_setup_state_static(pScrn);
+
+   if (pScrn->virtualX > pScrn->displayWidth)
 	pScrn->displayWidth = pScrn->virtualX;
 
    DPRINTF(PFX, "assert( if(!fbScreenInit(pScreen, ...) )\n");
diff --git a/src/i965_render.c b/src/i965_render.c
index af5c950..9fe5bdd 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -387,9 +387,11 @@ i965_check_rotation_transform(PictTransf
 	return FALSE;
 }
 
-static void
-i965_state_buffer_setup(I830Ptr pI830)
+/* Setup i965 state buffer static for once */
+void
+i965_setup_state_static(ScrnInfoPtr pScrn)
 {
+    I830Ptr pI830 = I830PTR(pScrn);
     int i;
     /* Set up our layout of state in framebuffer.  First the general state: */
     next_offset = 0;
@@ -707,18 +709,11 @@ i965_prepare_composite(int op, PicturePt
     CARD32 dst_format, dst_offset, dst_pitch, dst_tile_format = 0,
 	dst_tiled = 0;
     Bool rotation_program = FALSE;
-    static int firsttime = 1;
     int sf_kernel_num, ps_kernel_num;
 
     IntelEmitInvarientState(pScrn);
     *pI830->last_3d = LAST_3D_RENDER;
 
-    /* we want to setup only once for all state offset */
-    if (firsttime) {
-	i965_state_buffer_setup(pI830);
-	firsttime = 0;
-    }
-
     src_offset = intel_get_pixmap_offset(pSrc);
     src_pitch = intel_get_pixmap_pitch(pSrc);
     if (i830_pixmap_tiled(pSrc)) {
diff-tree 53c3d217fe45af4e38bf1c2efedb27e2b2879706 (from d60c897bb2baccf17ab14c5cd9a409c9ca67bfce)
Author: Zhenyu Wang <zhenyu.z.wang at intel.com>
Date:   Fri Sep 28 00:41:19 2007 +0800

    remove sync in i965_composite
    
    vb state doesn't damage, rendercheck passed fine.

diff --git a/src/i965_render.c b/src/i965_render.c
index 782e831..af5c950 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -1084,11 +1084,6 @@ i965_composite(PixmapPtr pDst, int srcX,
 					 &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++] = (float)(dstX + w);
diff-tree d60c897bb2baccf17ab14c5cd9a409c9ca67bfce (from 9d0c26747de97a417c5fd0bcdcb388b1dac9adc1)
Author: root <root at debian-wzy.(none)>
Date:   Thu Sep 27 23:22:45 2007 +0800

    more cleanups
    
    also remove extra sync commands.

diff --git a/src/i965_render.c b/src/i965_render.c
index 4fd66a5..782e831 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -664,8 +664,7 @@ i965_state_buffer_setup(I830Ptr pI830)
     wm_state = &wm_state_local;
     memset(wm_state, 0, sizeof (*wm_state));
     wm_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(PS_KERNEL_NUM_GRF);
-    //XXX
-    wm_state->thread1.single_program_flow = 1;
+    wm_state->thread1.single_program_flow = 0;
     wm_state->thread2.scratch_space_base_pointer = (state_base_offset +
 						    wm_scratch_offset)>>10;
     wm_state->thread2.per_thread_scratch_space = 0;
@@ -767,116 +766,98 @@ i965_prepare_composite(int op, PicturePt
     i830WaitSync(pScrn);
 
     /* Color calculator state */
-//    cc_state = &cc_state_local;
-
     i965_get_blend_cntl(op, pMaskPicture, pDstPicture->format,
 			&src_blend, &dst_blend);
-    cc_state->cc6.src_blend_factor = src_blend;
-    cc_state->cc6.dest_blend_factor = dst_blend;
-
- //   cc_state = (void *)(state_base + cc_offset);
- //   memcpy (cc_state, &cc_state_local, sizeof (cc_state_local));
+    cc_state_local.cc6.src_blend_factor = src_blend;
+    cc_state_local.cc6.dest_blend_factor = dst_blend;
+    memcpy (&cc_state->cc6, &cc_state_local.cc6, sizeof (cc_state_local.cc6));
 
     /* Set up the state buffer for the destination surface */
-   // dest_surf_state = &dest_surf_state_local;
     i965_get_dest_format(pDstPicture, &dst_format);
-    dest_surf_state->ss0.surface_format = dst_format;
-    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->ss3.pitch = dst_pitch - 1;
-    dest_surf_state->ss3.tile_walk = dst_tile_format;
-    dest_surf_state->ss3.tiled_surface = dst_tiled;
-    //dest_surf_state = (void *)(state_base + dest_surf_offset);
-    //memcpy (dest_surf_state, &dest_surf_state_local, sizeof (dest_surf_state_local));
+    dest_surf_state_local.ss0.surface_format = dst_format;
+    dest_surf_state_local.ss1.base_addr = dst_offset;
+    dest_surf_state_local.ss2.height = pDst->drawable.height - 1;
+    dest_surf_state_local.ss2.width = pDst->drawable.width - 1;
+    dest_surf_state_local.ss3.pitch = dst_pitch - 1;
+    dest_surf_state_local.ss3.tile_walk = dst_tile_format;
+    dest_surf_state_local.ss3.tiled_surface = dst_tiled;
+    memcpy (dest_surf_state, &dest_surf_state_local, sizeof (dest_surf_state_local));
 
     /* Set up the source surface state buffer */
-    //src_surf_state = &src_surf_state_local;
-    //memset(src_surf_state, 0, sizeof(*src_surf_state));
-    src_surf_state->ss0.surface_format = i965_get_card_format(pSrcPicture);
-    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->ss3.pitch = src_pitch - 1;
-    src_surf_state->ss3.tile_walk = src_tile_format;
-    src_surf_state->ss3.tiled_surface = src_tiled;
-    //src_surf_state = (void *)(state_base + src_surf_offset);
-    //memcpy (src_surf_state, &src_surf_state_local, sizeof (src_surf_state_local));
+    src_surf_state_local.ss0.surface_format = i965_get_card_format(pSrcPicture);
+    src_surf_state_local.ss1.base_addr = src_offset;
+    src_surf_state_local.ss2.width = pSrc->drawable.width - 1;
+    src_surf_state_local.ss2.height = pSrc->drawable.height - 1;
+    src_surf_state_local.ss3.pitch = src_pitch - 1;
+    src_surf_state_local.ss3.tile_walk = src_tile_format;
+    src_surf_state_local.ss3.tiled_surface = src_tiled;
+    memcpy (src_surf_state, &src_surf_state_local, sizeof (src_surf_state_local));
 
     /* setup mask surface */
     if (pMask) {
-	//mask_surf_state = &mask_surf_state_local;
-   	//memset(mask_surf_state, 0, sizeof(*mask_surf_state));
-   	mask_surf_state->ss0.surface_format =
+	mask_surf_state_local.ss0.surface_format =
 	    i965_get_card_format(pMaskPicture);
-   	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->ss3.pitch = mask_pitch - 1;
-	mask_surf_state->ss3.tile_walk = mask_tile_format;
-	mask_surf_state->ss3.tiled_surface = mask_tiled;
-	//mask_surf_state = (void *)(state_base + mask_surf_offset);
-	//memcpy (mask_surf_state, &mask_surf_state_local, sizeof (mask_surf_state_local));
+	mask_surf_state_local.ss1.base_addr = mask_offset;
+	mask_surf_state_local.ss2.width = pMask->drawable.width - 1;
+	mask_surf_state_local.ss2.height = pMask->drawable.height - 1;
+	mask_surf_state_local.ss3.pitch = mask_pitch - 1;
+	mask_surf_state_local.ss3.tile_walk = mask_tile_format;
+	mask_surf_state_local.ss3.tiled_surface = mask_tiled;
+	memcpy (mask_surf_state, &mask_surf_state_local, sizeof (mask_surf_state_local));
     }
 
     /* PS kernel use this sampler */
-    //src_sampler_state = &src_sampler_state_local;
-    //memset(src_sampler_state, 0, sizeof(*src_sampler_state));
     switch(pSrcPicture->filter) {
     case PictFilterNearest:
-   	src_sampler_state->ss0.min_filter = BRW_MAPFILTER_NEAREST;
-   	src_sampler_state->ss0.mag_filter = BRW_MAPFILTER_NEAREST;
+	src_sampler_state_local.ss0.min_filter = BRW_MAPFILTER_NEAREST;
+	src_sampler_state_local.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;
+	src_sampler_state_local.ss0.min_filter = BRW_MAPFILTER_LINEAR;
+	src_sampler_state_local.ss0.mag_filter = BRW_MAPFILTER_LINEAR;
 	break;
     default:
 	I830FALLBACK("Bad filter 0x%x\n", pSrcPicture->filter);
     }
 
     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_local.ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER;
+	src_sampler_state_local.ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER;
+	src_sampler_state_local.ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER;
     } 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_local.ss1.r_wrap_mode = BRW_TEXCOORDMODE_WRAP;
+	src_sampler_state_local.ss1.s_wrap_mode = BRW_TEXCOORDMODE_WRAP;
+	src_sampler_state_local.ss1.t_wrap_mode = BRW_TEXCOORDMODE_WRAP;
     }
-//    src_sampler_state = (void *)(state_base + src_sampler_offset);
-//    memcpy (src_sampler_state, &src_sampler_state_local, sizeof (src_sampler_state_local));
+    memcpy (src_sampler_state, &src_sampler_state_local, sizeof (src_sampler_state_local));
 
     if (pMask) {
-//	mask_sampler_state = &mask_sampler_state_local;
- //  	memset(mask_sampler_state, 0, sizeof(*mask_sampler_state));
-   	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);
-   	}
+	switch(pMaskPicture->filter) {
+	    case PictFilterNearest:
+		mask_sampler_state_local.ss0.min_filter = BRW_MAPFILTER_NEAREST;
+		mask_sampler_state_local.ss0.mag_filter = BRW_MAPFILTER_NEAREST;
+		break;
+	    case PictFilterBilinear:
+		mask_sampler_state_local.ss0.min_filter = BRW_MAPFILTER_LINEAR;
+		mask_sampler_state_local.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 =
+	if (!pMaskPicture->repeat) {
+	    mask_sampler_state_local.ss1.r_wrap_mode =
 		BRW_TEXCOORDMODE_CLAMP_BORDER;
-   	    mask_sampler_state->ss1.s_wrap_mode =
+	    mask_sampler_state_local.ss1.s_wrap_mode =
 		BRW_TEXCOORDMODE_CLAMP_BORDER;
-   	    mask_sampler_state->ss1.t_wrap_mode =
+	    mask_sampler_state_local.ss1.t_wrap_mode =
 		BRW_TEXCOORDMODE_CLAMP_BORDER;
-   	} 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 = (void *)(state_base + mask_sampler_offset);
-//	memcpy (mask_sampler_state, &mask_sampler_state_local, sizeof (mask_sampler_state_local));
+	} else {
+	    mask_sampler_state_local.ss1.r_wrap_mode = BRW_TEXCOORDMODE_WRAP;
+	    mask_sampler_state_local.ss1.s_wrap_mode = BRW_TEXCOORDMODE_WRAP;
+	    mask_sampler_state_local.ss1.t_wrap_mode = BRW_TEXCOORDMODE_WRAP;
+	}
+	memcpy (mask_sampler_state, &mask_sampler_state_local, sizeof (mask_sampler_state_local));
     }
 
     /* Set up the SF kernel to do coord interp: for each attribute,
@@ -890,16 +871,15 @@ i965_prepare_composite(int op, PicturePt
     else
 	sf_kernel_num = 0;
 
-    //sf_state = &sf_state_local;
-    //memset(sf_state, 0, sizeof(*sf_state));
-    sf_state->thread0.kernel_start_pointer =
+    sf_state_local.thread0.kernel_start_pointer =
 	(state_base_offset + sf_kernel_offset[sf_kernel_num]) >> 6;
+    memcpy(&sf_state->thread0, &sf_state_local.thread0, sizeof(sf_state_local.thread0));
 
    /* Set up the PS kernel (dispatched by WM) */
     if (pMask) {
-	if (pMaskPicture->componentAlpha && 
+	if (pMaskPicture->componentAlpha &&
                 PICT_FORMAT_RGB(pMaskPicture->format)) {
-            if (i965_blend_op[op].src_alpha) 
+            if (i965_blend_op[op].src_alpha)
 		ps_kernel_num = 3;
             else
 		ps_kernel_num = 2;
@@ -910,34 +890,22 @@ i965_prepare_composite(int op, PicturePt
     else
 	ps_kernel_num = 0;
 
-    //wm_state = &wm_state_local;
-    //memset(wm_state, 0, sizeof (*wm_state));
-    wm_state->thread0.kernel_start_pointer =
+    wm_state_local.thread0.kernel_start_pointer =
 	(state_base_offset + ps_kernel_offset[ps_kernel_num]) >> 6;
     if (!pMask)
-	wm_state->thread1.binding_table_entry_count = 2; /* 1 tex and fb */
+	wm_state_local.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_local.thread1.binding_table_entry_count = 3; /* 2 tex and fb */
     /* Each pair of attributes (src/mask coords) is one URB entry */
     if (pMask)
-	wm_state->thread3.urb_entry_read_length = 2;
+	wm_state_local.thread3.urb_entry_read_length = 2;
     else
-	wm_state->thread3.urb_entry_read_length = 1;
-    //wm_state = (void *)(state_base + wm_offset);
-    //memcpy (wm_state, &wm_state_local, sizeof (wm_state_local));
+	wm_state_local.thread3.urb_entry_read_length = 1;
+    memcpy (wm_state, &wm_state_local, sizeof (wm_state_local));
 
     /* Begin the long sequence of commands needed to set up the 3D
      * rendering pipe
      */
-    // EXA render state tracker
-    {
-	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);
 
@@ -966,16 +934,9 @@ i965_prepare_composite(int op, PicturePt
 	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 */
+	BEGIN_LP_RING(22);
 
 	/* Binding table pointers */
    	OUT_RING(BRW_3DSTATE_BINDING_TABLE_POINTERS | 4);
@@ -986,15 +947,6 @@ i965_prepare_composite(int op, PicturePt
 	/* 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(DRAW_YMAX(pDst->drawable.height - 1) |
-		 DRAW_XMAX(pDst->drawable.width - 1)); /* ymax, xmax */
-   	OUT_RING(0x00000000);	/* yorigin, xorigin */
-
 	/* skip the depth buffer */
 	/* skip the polygon stipple */
 	/* skip the polygon stipple offset */
@@ -1027,8 +979,18 @@ i965_prepare_composite(int op, PicturePt
    	OUT_RING(BRW_CS_URB_STATE | 0);
    	OUT_RING(((URB_CS_ENTRY_SIZE - 1) << 4) |
 	    	 (URB_CS_ENTRIES << 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(DRAW_YMAX(pDst->drawable.height - 1) |
+		 DRAW_XMAX(pDst->drawable.width - 1)); /* ymax, xmax */
+   	OUT_RING(0x00000000);	/* yorigin, xorigin */
 	ADVANCE_LP_RING();
     }
+
     {
         int nelem = pMask ? 3: 2;
    	BEGIN_LP_RING(pMask?12:10);
@@ -1176,24 +1138,6 @@ i965_composite(PixmapPtr pDst, int srcX,
     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*/
-#if 0
-    {
-	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();
-    }
-#endif
-
     /* Mark sync so we can wait for it before setting up the VB on the next
      * rectangle.
      */
diff-tree 9d0c26747de97a417c5fd0bcdcb388b1dac9adc1 (from d466dc04cc3ea314e4ae8f7c9bd40cc9c63c6138)
Author: root <root at debian-wzy.(none)>
Date:   Thu Sep 27 21:27:04 2007 +0800

    clean up state buffer setup

diff --git a/src/i965_render.c b/src/i965_render.c
index cf500e4..4fd66a5 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -391,7 +391,6 @@ static void
 i965_state_buffer_setup(I830Ptr pI830)
 {
     int i;
-    ErrorF("zhen: state buffer setup\n");
     /* Set up our layout of state in framebuffer.  First the general state: */
     next_offset = 0;
     vs_offset = ALIGN(next_offset, 64);
@@ -474,10 +473,6 @@ i965_state_buffer_setup(I830Ptr pI830)
 
     total_state_size = next_offset;
     assert(total_state_size < pI830->exa_965_state->size);
-    if (total_state_size > pI830->exa_965_state->size) {
-	ErrorF("zhen: increase exa state buffer size!\n");
-	return;
-    }
 
     state_base_offset = pI830->exa_965_state->offset;
     state_base_offset = ALIGN(state_base_offset, 64);
@@ -539,7 +534,7 @@ i965_state_buffer_setup(I830Ptr pI830)
     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.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 */
     cc_state->cc4.cc_viewport_state_offset = (state_base_offset +
@@ -547,19 +542,7 @@ i965_state_buffer_setup(I830Ptr pI830)
     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;
- //   XXX
- //   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;
-    /* default not care much */
-//    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] */
@@ -593,6 +576,7 @@ i965_state_buffer_setup(I830Ptr pI830)
     src_surf_state = &src_surf_state_local;
     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;
     src_surf_state->ss0.color_blend = 1;
     src_surf_state = (void *)(state_base + src_surf_offset);
     memcpy (src_surf_state, &src_surf_state_local, sizeof (src_surf_state_local));
@@ -601,7 +585,8 @@ i965_state_buffer_setup(I830Ptr pI830)
     mask_surf_state = &mask_surf_state_local;
     memset(mask_surf_state, 0, sizeof(*mask_surf_state));
     mask_surf_state->ss0.surface_type = BRW_SURFACE_2D;
-    mask_surf_state->ss0.color_blend = 1;
+    mask_surf_state->ss0.data_return_format = BRW_SURFACERETURNFORMAT_FLOAT32;
+    mask_surf_state->ss0.color_blend = 0;
     mask_surf_state = (void *)(state_base + mask_surf_offset);
     memcpy (mask_surf_state, &mask_surf_state_local, sizeof (mask_surf_state_local));
 
@@ -646,8 +631,6 @@ i965_state_buffer_setup(I830Ptr pI830)
 
     sf_state = &sf_state_local;
     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;
@@ -668,7 +651,7 @@ i965_state_buffer_setup(I830Ptr pI830)
     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->thread4.stats_enable = 0;
     sf_state->sf5.viewport_transform = FALSE; /* skip viewport */
     sf_state->sf6.cull_mode = BRW_CULLMODE_NONE;
     sf_state->sf6.scissor = 0;
@@ -680,9 +663,8 @@ i965_state_buffer_setup(I830Ptr pI830)
 
     wm_state = &wm_state_local;
     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);
+    //XXX
     wm_state->thread1.single_program_flow = 1;
     wm_state->thread2.scratch_space_base_pointer = (state_base_offset +
 						    wm_scratch_offset)>>10;
@@ -692,7 +674,7 @@ i965_state_buffer_setup(I830Ptr pI830)
     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.stats_enable = 0;  /* statistic */
     /* src_sampler_offset is where all sampler states starts */
     wm_state->wm4.sampler_state_pointer = (state_base_offset +
 					   src_sampler_offset) >> 5;
@@ -736,7 +718,6 @@ i965_prepare_composite(int op, PicturePt
     if (firsttime) {
 	i965_state_buffer_setup(pI830);
 	firsttime = 0;
-	ErrorF("zhen: first time\n");
     }
 
     src_offset = intel_get_pixmap_offset(pSrc);
@@ -752,7 +733,6 @@ i965_prepare_composite(int op, PicturePt
 	dst_tile_format = 0; /* Tiled X */
     }
     if (pMask) {
-	ErrorF("zhen: mask\n");
 	mask_offset = intel_get_pixmap_offset(pMask);
 	mask_pitch = intel_get_pixmap_pitch(pMask);
 	if (i830_pixmap_tiled(pMask)) {
@@ -784,21 +764,13 @@ i965_prepare_composite(int op, PicturePt
     /* Because we only have a single static buffer for our state currently,
      * we have to sync before updating it every time.
      */
-//    i830WaitSync(pScrn);
+    i830WaitSync(pScrn);
 
     /* Color calculator state */
 //    cc_state = &cc_state_local;
 
-//    cc_state->cc3.ia_blend_enable = 1;  /* blend alpha just like colors */
- //   cc_state->cc5.ia_blend_function = BRW_BLENDFUNCTION_ADD;
- //   XXX
     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.src_blend_factor = src_blend;
     cc_state->cc6.dest_blend_factor = dst_blend;
 
@@ -809,14 +781,12 @@ i965_prepare_composite(int op, PicturePt
    // dest_surf_state = &dest_surf_state_local;
     i965_get_dest_format(pDstPicture, &dst_format);
     dest_surf_state->ss0.surface_format = dst_format;
-
     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->ss3.pitch = dst_pitch - 1;
     dest_surf_state->ss3.tile_walk = dst_tile_format;
     dest_surf_state->ss3.tiled_surface = dst_tiled;
-
     //dest_surf_state = (void *)(state_base + dest_surf_offset);
     //memcpy (dest_surf_state, &dest_surf_state_local, sizeof (dest_surf_state_local));
 
@@ -824,14 +794,12 @@ i965_prepare_composite(int op, PicturePt
     //src_surf_state = &src_surf_state_local;
     //memset(src_surf_state, 0, sizeof(*src_surf_state));
     src_surf_state->ss0.surface_format = i965_get_card_format(pSrcPicture);
-
     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->ss3.pitch = src_pitch - 1;
     src_surf_state->ss3.tile_walk = src_tile_format;
     src_surf_state->ss3.tiled_surface = src_tiled;
-
     //src_surf_state = (void *)(state_base + src_surf_offset);
     //memcpy (src_surf_state, &src_surf_state_local, sizeof (src_surf_state_local));
 
@@ -841,14 +809,12 @@ i965_prepare_composite(int op, PicturePt
    	//memset(mask_surf_state, 0, sizeof(*mask_surf_state));
    	mask_surf_state->ss0.surface_format =
 	    i965_get_card_format(pMaskPicture);
-
    	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->ss3.pitch = mask_pitch - 1;
 	mask_surf_state->ss3.tile_walk = mask_tile_format;
 	mask_surf_state->ss3.tiled_surface = mask_tiled;
-
 	//mask_surf_state = (void *)(state_base + mask_surf_offset);
 	//memcpy (mask_surf_state, &mask_surf_state_local, sizeof (mask_surf_state_local));
     }
@@ -878,7 +844,6 @@ i965_prepare_composite(int op, PicturePt
    	src_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_WRAP;
    	src_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_WRAP;
     }
-
 //    src_sampler_state = (void *)(state_base + src_sampler_offset);
 //    memcpy (src_sampler_state, &src_sampler_state_local, sizeof (src_sampler_state_local));
 
@@ -910,7 +875,6 @@ i965_prepare_composite(int op, PicturePt
    	    mask_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_WRAP;
    	    mask_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_WRAP;
     	}
-
 //	mask_sampler_state = (void *)(state_base + mask_sampler_offset);
 //	memcpy (mask_sampler_state, &mask_sampler_state_local, sizeof (mask_sampler_state_local));
     }
@@ -928,7 +892,6 @@ i965_prepare_composite(int op, PicturePt
 
     //sf_state = &sf_state_local;
     //memset(sf_state, 0, sizeof(*sf_state));
-    ErrorF("zhen: sf_kernel %d\n", sf_kernel_num);
     sf_state->thread0.kernel_start_pointer =
 	(state_base_offset + sf_kernel_offset[sf_kernel_num]) >> 6;
 
@@ -947,7 +910,6 @@ i965_prepare_composite(int op, PicturePt
     else
 	ps_kernel_num = 0;
 
-    ErrorF("zhen: ps_kernel_num %d\n", ps_kernel_num);
     //wm_state = &wm_state_local;
     //memset(wm_state, 0, sizeof (*wm_state));
     wm_state->thread0.kernel_start_pointer =
@@ -967,6 +929,7 @@ i965_prepare_composite(int op, PicturePt
     /* Begin the long sequence of commands needed to set up the 3D
      * rendering pipe
      */
+    // EXA render state tracker
     {
 	BEGIN_LP_RING(2);
    	OUT_RING(MI_FLUSH |
diff-tree d466dc04cc3ea314e4ae8f7c9bd40cc9c63c6138 (from 44d38353225a4a44d50afdbfd6e3b64f6238ab4f)
Author: root <root at debian-wzy.(none)>
Date:   Thu Sep 27 18:38:47 2007 +0800

    fix sf kernel offset for transform program

diff --git a/src/i965_render.c b/src/i965_render.c
index 65d13a8..cf500e4 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -419,7 +419,7 @@ i965_state_buffer_setup(I830Ptr pI830)
     next_offset = sf_kernel_offset[1] + sizeof(sf_kernel_static_mask);
 
     sf_kernel_offset[2] = ALIGN(next_offset, 64);
-    next_offset = sf_kernel_offset[1] + sizeof(sf_kernel_static_rotation);
+    next_offset = sf_kernel_offset[2] + sizeof(sf_kernel_static_rotation);
 
     ps_kernel_offset[0] = ALIGN(next_offset, 64);
     next_offset = ps_kernel_offset[0] + sizeof (ps_kernel_static_nomask);
diff-tree 44d38353225a4a44d50afdbfd6e3b64f6238ab4f (from bbf69c7446aa9748dacecccfe0b63d803f865b00)
Author: root <root at debian-wzy.(none)>
Date:   Thu Sep 27 18:29:51 2007 +0800

    commit current i965 exa state buffer work

diff --git a/src/i965_render.c b/src/i965_render.c
index ad3b53e..65d13a8 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -267,8 +267,8 @@ static struct brw_wm_unit_state *wm_stat
 static struct brw_cc_unit_state *cc_state, cc_state_local;
 static struct brw_cc_viewport *cc_viewport;
 
-static struct brw_instruction *sf_kernel;
-static struct brw_instruction *ps_kernel;
+static struct brw_instruction *sf_kernel[3];
+static struct brw_instruction *ps_kernel[5];
 static struct brw_instruction *sip_kernel;
 
 static CARD32 *binding_table;
@@ -277,7 +277,9 @@ 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 sf_kernel_offset[3];
+static int ps_kernel_offset[5];
+static int sip_kernel_offset;
 static int wm_scratch_offset;
 static int binding_table_offset;
 static int default_color_offset;
@@ -340,6 +342,10 @@ static const CARD32 ps_kernel_static_nom
 #include "exa_wm_nomask_prog.h"
 };
 
+static const CARD32 ps_kernel_static_masknoca [][4] = {
+#include "exa_wm_masknoca_prog.h"
+};
+
 static const CARD32 ps_kernel_static_maskca [][4] = {
 #include "exa_wm_maskca_prog.h"
 };
@@ -348,10 +354,6 @@ static const CARD32 ps_kernel_static_mas
 #include "exa_wm_maskca_srcalpha_prog.h"
 };
 
-static const CARD32 ps_kernel_static_masknoca [][4] = {
-#include "exa_wm_masknoca_prog.h"
-};
-
 static const CARD32 ps_kernel_static_rotation [][4] = {
 #include "exa_wm_rotation_prog.h"
 };
@@ -385,67 +387,11 @@ i965_check_rotation_transform(PictTransf
 	return FALSE;
 }
 
-Bool
-i965_prepare_composite(int op, PicturePtr pSrcPicture,
-		       PicturePtr pMaskPicture, PicturePtr pDstPicture,
-		       PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
+static void
+i965_state_buffer_setup(I830Ptr pI830)
 {
-    ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum];
-    I830Ptr pI830 = I830PTR(pScrn);
-    CARD32 src_offset, src_pitch, src_tile_format = 0, src_tiled = 0;
-    CARD32 mask_offset = 0, mask_pitch = 0, mask_tile_format = 0,
-	mask_tiled = 0;
-    CARD32 dst_format, dst_offset, dst_pitch, dst_tile_format = 0,
-	dst_tiled = 0;
-    Bool rotation_program = FALSE;
-
-    IntelEmitInvarientState(pScrn);
-    *pI830->last_3d = LAST_3D_RENDER;
-
-    src_offset = intel_get_pixmap_offset(pSrc);
-    src_pitch = intel_get_pixmap_pitch(pSrc);
-    if (i830_pixmap_tiled(pSrc)) {
-	src_tiled = 1;
-	src_tile_format = 0; /* Tiled X */
-    }
-    dst_offset = intel_get_pixmap_offset(pDst);
-    dst_pitch = intel_get_pixmap_pitch(pDst);
-    if (i830_pixmap_tiled(pDst)) {
-	dst_tiled = 1;
-	dst_tile_format = 0; /* Tiled X */
-    }
-    if (pMask) {
-	mask_offset = intel_get_pixmap_offset(pMask);
-	mask_pitch = intel_get_pixmap_pitch(pMask);
-	if (i830_pixmap_tiled(pMask)) {
-	    mask_tiled = 1;
-	    mask_tile_format = 0; /* Tiled X */
-	}
-    }
-    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;
-	if (pI830->transform[0] && 
-		i965_check_rotation_transform(pI830->transform[0]))
-	    rotation_program = TRUE;
-    } else {
-	pI830->transform[1] = pMaskPicture->transform;
-	if (pI830->transform[1])
-	    I830FALLBACK("i965 mask transform not implemented!\n");
-	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 */
-
+    int i;
+    ErrorF("zhen: state buffer setup\n");
     /* Set up our layout of state in framebuffer.  First the general state: */
     next_offset = 0;
     vs_offset = ALIGN(next_offset, 64);
@@ -466,33 +412,29 @@ i965_prepare_composite(int op, PicturePt
     /* 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 if (rotation_program)
-	next_offset = sf_kernel_offset + sizeof (sf_kernel_static_rotation);
-    else 
-	next_offset = sf_kernel_offset + sizeof (sf_kernel_static);
+    sf_kernel_offset[0] = ALIGN(next_offset, 64);
+    next_offset = sf_kernel_offset[0] + sizeof(sf_kernel_static);
 
-    ps_kernel_offset = ALIGN(next_offset, 64);
-    if (pMask) {
-	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 if (rotation_program) {
-   	next_offset = ps_kernel_offset + sizeof (ps_kernel_static_rotation);
-    } else {
-   	next_offset = ps_kernel_offset + sizeof (ps_kernel_static_nomask);
-    }
+    sf_kernel_offset[1] = ALIGN(next_offset, 64);
+    next_offset = sf_kernel_offset[1] + sizeof(sf_kernel_static_mask);
+
+    sf_kernel_offset[2] = ALIGN(next_offset, 64);
+    next_offset = sf_kernel_offset[1] + sizeof(sf_kernel_static_rotation);
+
+    ps_kernel_offset[0] = ALIGN(next_offset, 64);
+    next_offset = ps_kernel_offset[0] + sizeof (ps_kernel_static_nomask);
+
+    ps_kernel_offset[1] = ALIGN(next_offset, 64);
+    next_offset = ps_kernel_offset[1] + sizeof(ps_kernel_static_masknoca);
+
+    ps_kernel_offset[2] = ALIGN(next_offset, 64);
+    next_offset = ps_kernel_offset[2] + sizeof(ps_kernel_static_maskca);
+
+    ps_kernel_offset[3] = ALIGN(next_offset, 64);
+    next_offset = ps_kernel_offset[3] + sizeof(ps_kernel_static_maskca_srcalpha);
+
+    ps_kernel_offset[4] = ALIGN(next_offset, 64);
+    next_offset = ps_kernel_offset[4] + sizeof (ps_kernel_static_rotation);
 
     sip_kernel_offset = ALIGN(next_offset, 64);
     next_offset = sip_kernel_offset + sizeof (sip_kernel_static);
@@ -505,10 +447,9 @@ i965_prepare_composite(int op, PicturePt
     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);
-    }
+    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, 32);
     next_offset = vb_offset + vb_size;
@@ -520,11 +461,10 @@ i965_prepare_composite(int op, PicturePt
     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;
-    }
+    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);
@@ -534,13 +474,22 @@ i965_prepare_composite(int op, PicturePt
 
     total_state_size = next_offset;
     assert(total_state_size < pI830->exa_965_state->size);
+    if (total_state_size > pI830->exa_965_state->size) {
+	ErrorF("zhen: increase exa state buffer size!\n");
+	return;
+    }
 
     state_base_offset = pI830->exa_965_state->offset;
     state_base_offset = ALIGN(state_base_offset, 64);
     state_base = (char *)(pI830->FbBase + state_base_offset);
 
-    sf_kernel = (void *)(state_base + sf_kernel_offset);
-    ps_kernel = (void *)(state_base + ps_kernel_offset);
+    memset(state_base, 0, total_state_size);
+
+    for (i = 0; i < 3; i++)
+	sf_kernel[i] = (void *)(state_base + sf_kernel_offset[i]);
+    for (i = 0; i < 5; i++)
+	ps_kernel[i] = (void *)(state_base + ps_kernel_offset[i]);
+
     sip_kernel = (void *)(state_base + sip_kernel_offset);
 
     cc_viewport = (void *)(state_base + cc_viewport_offset);
@@ -580,11 +529,6 @@ 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;
 
-    /* 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;
     cc_viewport->max_depth = 1.e35;
@@ -595,7 +539,7 @@ i965_prepare_composite(int op, PicturePt
     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.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 +
@@ -603,17 +547,19 @@ i965_prepare_composite(int op, PicturePt
     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);
+ //   cc_state->cc5.ia_blend_function = BRW_BLENDFUNCTION_ADD;
+ //   XXX
+ //   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->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;
+    /* default not care much */
+//    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] */
@@ -622,107 +568,294 @@ i965_prepare_composite(int op, PicturePt
     memcpy (cc_state, &cc_state_local, sizeof (cc_state_local));
 
     /* Upload system kernel */
-    memcpy (sip_kernel, sip_kernel_static, sizeof (sip_kernel_static));
+    memcpy(sip_kernel, sip_kernel_static, sizeof (sip_kernel_static));
+
+    memcpy(sf_kernel[0], sf_kernel_static, sizeof(sf_kernel_static));
+    memcpy(sf_kernel[1], sf_kernel_static_mask, sizeof(sf_kernel_static_mask));
+    memcpy(sf_kernel[2], sf_kernel_static_rotation, sizeof(sf_kernel_static_rotation));
+
+    memcpy(ps_kernel[0], ps_kernel_static_nomask, sizeof(ps_kernel_static_nomask));
+    memcpy(ps_kernel[1], ps_kernel_static_masknoca, sizeof(ps_kernel_static_masknoca));
+    memcpy(ps_kernel[2], ps_kernel_static_maskca, sizeof(ps_kernel_static_maskca));
+    memcpy(ps_kernel[3], ps_kernel_static_maskca_srcalpha, sizeof(ps_kernel_static_maskca_srcalpha));
+    memcpy(ps_kernel[4], ps_kernel_static_rotation, sizeof(ps_kernel_static_rotation));
 
     /* Set up the state buffer for the destination surface */
     dest_surf_state = &dest_surf_state_local;
     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;
+    dest_surf_state->ss0.color_blend = 1;
+    dest_surf_state = (void *)(state_base + dest_surf_offset);
+    memcpy (dest_surf_state, &dest_surf_state_local, sizeof (dest_surf_state_local));
+
+    /* Set up the source surface state buffer */
+    src_surf_state = &src_surf_state_local;
+    memset(src_surf_state, 0, sizeof(*src_surf_state));
+    src_surf_state->ss0.surface_type = BRW_SURFACE_2D;
+    src_surf_state->ss0.color_blend = 1;
+    src_surf_state = (void *)(state_base + src_surf_offset);
+    memcpy (src_surf_state, &src_surf_state_local, sizeof (src_surf_state_local));
+
+    /* setup mask surface */
+    mask_surf_state = &mask_surf_state_local;
+    memset(mask_surf_state, 0, sizeof(*mask_surf_state));
+    mask_surf_state->ss0.surface_type = BRW_SURFACE_2D;
+    mask_surf_state->ss0.color_blend = 1;
+    mask_surf_state = (void *)(state_base + mask_surf_offset);
+    memcpy (mask_surf_state, &mask_surf_state_local, sizeof (mask_surf_state_local));
+
+    /* 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;
+    binding_table[2] = state_base_offset + mask_surf_offset;
+
+    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] = 0.0; /* A */
+
+    /* PS kernel use this sampler */
+    src_sampler_state = &src_sampler_state_local;
+    memset(src_sampler_state, 0, sizeof(*src_sampler_state));
+    src_sampler_state->ss0.lod_preclamp = 1; /* GL mode */
+    src_sampler_state->ss0.default_color_mode = 0; /* GL mode */
+    src_sampler_state->ss2.default_color_pointer =
+	(state_base_offset + default_color_offset) >> 5;
+    src_sampler_state = (void *)(state_base + src_sampler_offset);
+    memcpy (src_sampler_state, &src_sampler_state_local, sizeof (src_sampler_state_local));
+
+    mask_sampler_state = &mask_sampler_state_local;
+    memset(mask_sampler_state, 0, sizeof(*mask_sampler_state));
+    mask_sampler_state->ss0.lod_preclamp = 1; /* GL mode */
+    mask_sampler_state->ss2.default_color_pointer =
+	(state_base_offset + default_color_offset)>>5;
+    mask_sampler_state = (void *)(state_base + mask_sampler_offset);
+    memcpy (mask_sampler_state, &mask_sampler_state_local, sizeof (mask_sampler_state_local));
+
+    /* Set up the vertex shader to be disabled (passthrough) */
+    vs_state = &vs_state_local;
+    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;
+    vs_state = (void *)(state_base + vs_offset);
+    memcpy (vs_state, &vs_state_local, sizeof (vs_state_local));
+
+    sf_state = &sf_state_local;
+    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 */
+    /* don't smash vertex header, read start from dw8 */
+    sf_state->thread3.urb_entry_read_offset = 1;
+    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;
+    sf_state = (void *)(state_base + sf_offset);
+    memcpy (sf_state, &sf_state_local, sizeof (sf_state_local));
+
+    wm_state = &wm_state_local;
+    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;
+    wm_state->thread2.scratch_space_base_pointer = (state_base_offset +
+						    wm_scratch_offset)>>10;
+    wm_state->thread2.per_thread_scratch_space = 0;
+    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 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 */
+    /* src_sampler_offset is where all sampler states starts */
+    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;
+    wm_state = (void *)(state_base + wm_offset);
+    memcpy (wm_state, &wm_state_local, sizeof (wm_state_local));
+
+    /* ok we have updated with default states, then we just need
+     * to fill some variable fields for composite objects and ops */
+
+}
+
+Bool
+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);
+    CARD32 src_offset, src_pitch, src_tile_format = 0, src_tiled = 0;
+    CARD32 mask_offset = 0, mask_pitch = 0, mask_tile_format = 0,
+	mask_tiled = 0;
+    CARD32 dst_format, dst_offset, dst_pitch, dst_tile_format = 0,
+	dst_tiled = 0;
+    Bool rotation_program = FALSE;
+    static int firsttime = 1;
+    int sf_kernel_num, ps_kernel_num;
+
+    IntelEmitInvarientState(pScrn);
+    *pI830->last_3d = LAST_3D_RENDER;
+
+    /* we want to setup only once for all state offset */
+    if (firsttime) {
+	i965_state_buffer_setup(pI830);
+	firsttime = 0;
+	ErrorF("zhen: first time\n");
+    }
+
+    src_offset = intel_get_pixmap_offset(pSrc);
+    src_pitch = intel_get_pixmap_pitch(pSrc);
+    if (i830_pixmap_tiled(pSrc)) {
+	src_tiled = 1;
+	src_tile_format = 0; /* Tiled X */
+    }
+    dst_offset = intel_get_pixmap_offset(pDst);
+    dst_pitch = intel_get_pixmap_pitch(pDst);
+    if (i830_pixmap_tiled(pDst)) {
+	dst_tiled = 1;
+	dst_tile_format = 0; /* Tiled X */
+    }
+    if (pMask) {
+	ErrorF("zhen: mask\n");
+	mask_offset = intel_get_pixmap_offset(pMask);
+	mask_pitch = intel_get_pixmap_pitch(pMask);
+	if (i830_pixmap_tiled(pMask)) {
+	    mask_tiled = 1;
+	    mask_tile_format = 0; /* Tiled X */
+	}
+    }
+    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;
+	if (pI830->transform[0] && 
+		i965_check_rotation_transform(pI830->transform[0]))
+	    rotation_program = TRUE;
+    } else {
+	pI830->transform[1] = pMaskPicture->transform;
+	if (pI830->transform[1])
+	    I830FALLBACK("i965 mask transform not implemented!\n");
+	pI830->scale_units[1][0] = pMask->drawable.width;
+	pI830->scale_units[1][1] = pMask->drawable.height;
+    }
+
+
+    /* Because we only have a single static buffer for our state currently,
+     * we have to sync before updating it every time.
+     */
+//    i830WaitSync(pScrn);
+
+    /* Color calculator state */
+//    cc_state = &cc_state_local;
+
+//    cc_state->cc3.ia_blend_enable = 1;  /* blend alpha just like colors */
+ //   cc_state->cc5.ia_blend_function = BRW_BLENDFUNCTION_ADD;
+ //   XXX
+    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.src_blend_factor = src_blend;
+    cc_state->cc6.dest_blend_factor = dst_blend;
+
+ //   cc_state = (void *)(state_base + cc_offset);
+ //   memcpy (cc_state, &cc_state_local, sizeof (cc_state_local));
+
+    /* Set up the state buffer for the destination surface */
+   // dest_surf_state = &dest_surf_state_local;
     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;
     dest_surf_state->ss3.tile_walk = dst_tile_format;
     dest_surf_state->ss3.tiled_surface = dst_tiled;
 
-    dest_surf_state = (void *)(state_base + dest_surf_offset);
-    memcpy (dest_surf_state, &dest_surf_state_local, sizeof (dest_surf_state_local));
+    //dest_surf_state = (void *)(state_base + dest_surf_offset);
+    //memcpy (dest_surf_state, &dest_surf_state_local, sizeof (dest_surf_state_local));
 
     /* Set up the source surface state buffer */
-    src_surf_state = &src_surf_state_local;
-    memset(src_surf_state, 0, sizeof(*src_surf_state));
-    src_surf_state->ss0.surface_type = BRW_SURFACE_2D;
+    //src_surf_state = &src_surf_state_local;
+    //memset(src_surf_state, 0, sizeof(*src_surf_state));
     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;
     src_surf_state->ss3.tile_walk = src_tile_format;
     src_surf_state->ss3.tiled_surface = src_tiled;
 
-    src_surf_state = (void *)(state_base + src_surf_offset);
-    memcpy (src_surf_state, &src_surf_state_local, sizeof (src_surf_state_local));
+    //src_surf_state = (void *)(state_base + src_surf_offset);
+    //memcpy (src_surf_state, &src_surf_state_local, sizeof (src_surf_state_local));
 
     /* setup mask surface */
     if (pMask) {
-	mask_surf_state = &mask_surf_state_local;
-   	memset(mask_surf_state, 0, sizeof(*mask_surf_state));
-	mask_surf_state->ss0.surface_type = BRW_SURFACE_2D;
+	//mask_surf_state = &mask_surf_state_local;
+   	//memset(mask_surf_state, 0, sizeof(*mask_surf_state));
    	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;
 	mask_surf_state->ss3.tile_walk = mask_tile_format;
 	mask_surf_state->ss3.tiled_surface = mask_tiled;
 
-	mask_surf_state = (void *)(state_base + mask_surf_offset);
-	memcpy (mask_surf_state, &mask_surf_state_local, sizeof (mask_surf_state_local));
+	//mask_surf_state = (void *)(state_base + mask_surf_offset);
+	//memcpy (mask_surf_state, &mask_surf_state_local, sizeof (mask_surf_state_local));
     }
 
-    /* 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 */
-    src_sampler_state = &src_sampler_state_local;
-    memset(src_sampler_state, 0, sizeof(*src_sampler_state));
-    src_sampler_state->ss0.lod_preclamp = 1; /* GL mode */
+    //src_sampler_state = &src_sampler_state_local;
+    //memset(src_sampler_state, 0, sizeof(*src_sampler_state));
     switch(pSrcPicture->filter) {
     case PictFilterNearest:
    	src_sampler_state->ss0.min_filter = BRW_MAPFILTER_NEAREST;
@@ -736,34 +869,22 @@ i965_prepare_composite(int op, PicturePt
 	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] = 0.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 */
 
-    src_sampler_state = (void *)(state_base + src_sampler_offset);
-    memcpy (src_sampler_state, &src_sampler_state_local, sizeof (src_sampler_state_local));
+//    src_sampler_state = (void *)(state_base + src_sampler_offset);
+//    memcpy (src_sampler_state, &src_sampler_state_local, sizeof (src_sampler_state_local));
 
     if (pMask) {
-	mask_sampler_state = &mask_sampler_state_local;
-   	memset(mask_sampler_state, 0, sizeof(*mask_sampler_state));
-   	mask_sampler_state->ss0.lod_preclamp = 1; /* GL mode */
+//	mask_sampler_state = &mask_sampler_state_local;
+ //  	memset(mask_sampler_state, 0, sizeof(*mask_sampler_state));
    	switch(pMaskPicture->filter) {
    	case PictFilterNearest:
    	    mask_sampler_state->ss0.min_filter = BRW_MAPFILTER_NEAREST;
@@ -784,139 +905,64 @@ i965_prepare_composite(int op, PicturePt
 		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 */
 
-	mask_sampler_state = (void *)(state_base + mask_sampler_offset);
-	memcpy (mask_sampler_state, &mask_sampler_state_local, sizeof (mask_sampler_state_local));
+//	mask_sampler_state = (void *)(state_base + mask_sampler_offset);
+//	memcpy (mask_sampler_state, &mask_sampler_state_local, sizeof (mask_sampler_state_local));
     }
 
-    /* Set up the vertex shader to be disabled (passthrough) */
-    vs_state = &vs_state_local;
-    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;
-
-    vs_state = (void *)(state_base + vs_offset);
-    memcpy (vs_state, &vs_state_local, sizeof (vs_state_local));
-
     /* 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_mask));
+	sf_kernel_num = 1;
     else if (rotation_program)
-	memcpy(sf_kernel, sf_kernel_static_rotation, 
-		sizeof (sf_kernel_static_rotation));
+	sf_kernel_num = 2;
     else
-	memcpy(sf_kernel, sf_kernel_static, sizeof (sf_kernel_static));
+	sf_kernel_num = 0;
 
-    sf_state = &sf_state_local;
-    memset(sf_state, 0, sizeof(*sf_state));
+    //sf_state = &sf_state_local;
+    //memset(sf_state, 0, sizeof(*sf_state));
+    ErrorF("zhen: sf_kernel %d\n", sf_kernel_num);
     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 */
-    /* don't smash vertex header, read start from dw8 */
-    sf_state->thread3.urb_entry_read_offset = 1;
-    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;
-
-    sf_state = (void *)(state_base + sf_offset);
-    memcpy (sf_state, &sf_state_local, sizeof (sf_state_local));
+	(state_base_offset + sf_kernel_offset[sf_kernel_num]) >> 6;
 
    /* Set up the PS kernel (dispatched by WM) */
     if (pMask) {
 	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));
+		ps_kernel_num = 3;
             else
-                memcpy(ps_kernel, ps_kernel_static_maskca,
-                        sizeof (ps_kernel_static_maskca));
+		ps_kernel_num = 2;
         } else
-   	    memcpy(ps_kernel, ps_kernel_static_masknoca,
-		   sizeof (ps_kernel_static_masknoca));
-    } else if (rotation_program) {
-   	memcpy(ps_kernel, ps_kernel_static_rotation,
-	       sizeof (ps_kernel_static_rotation));
-    } else {
-   	memcpy(ps_kernel, ps_kernel_static_nomask,
-	       sizeof (ps_kernel_static_nomask));
-    }
+	    ps_kernel_num = 1;
+    } else if (rotation_program)
+	ps_kernel_num = 4;
+    else
+	ps_kernel_num = 0;
 
-    wm_state = &wm_state_local;
-    memset(wm_state, 0, sizeof (*wm_state));
+    ErrorF("zhen: ps_kernel_num %d\n", ps_kernel_num);
+    //wm_state = &wm_state_local;
+    //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;
+	(state_base_offset + ps_kernel_offset[ps_kernel_num]) >> 6;
     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;
-    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;
-
-    wm_state = (void *)(state_base + wm_offset);
-    memcpy (wm_state, &wm_state_local, sizeof (wm_state_local));
+    //wm_state = (void *)(state_base + wm_offset);
+    //memcpy (wm_state, &wm_state_local, sizeof (wm_state_local));
 
     /* Begin the long sequence of commands needed to set up the 3D
      * rendering pipe
@@ -1169,6 +1215,7 @@ i965_composite(PixmapPtr pDst, int srcX,
 #endif
     /* we must be sure that the pipeline is flushed before next exa draw,
        because that will be new state, binding state and instructions*/
+#if 0
     {
 	BEGIN_LP_RING(4);
    	OUT_RING(BRW_PIPE_CONTROL |
@@ -1182,6 +1229,7 @@ i965_composite(PixmapPtr pDst, int srcX,
    	OUT_RING(0); /* Immediate data high DW */
 	ADVANCE_LP_RING();
     }
+#endif
 
     /* Mark sync so we can wait for it before setting up the VB on the next
      * rectangle.
diff-tree bbf69c7446aa9748dacecccfe0b63d803f865b00 (from ca67fa767dc762dac369e84b27a7ef15673d527c)
Author: Zhenyu Wang <zhenyu.z.wang at intel.com>
Date:   Thu Sep 27 17:37:19 2007 +0800

    Pin cursor, overlay(no physical) and exa state buffers
    
    And cursor mem counting for dri mem manager is not relate
    to overlay.

diff --git a/src/i830_memory.c b/src/i830_memory.c
index 42e88a6..7ae2332 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -392,10 +392,10 @@ i830_allocator_init(ScrnInfoPtr pScrn, u
 	/* Overlay is always set up as fixed, currently. */
 	if (!OVERLAY_NOPHYSICAL(pI830) && !IS_I965G(pI830)) {
 	    mmsize -= ROUND_TO(OVERLAY_SIZE, GTT_PAGE_SIZE);
-	    if (pI830->CursorNeedsPhysical) {
-		mmsize -= 2 * (ROUND_TO(HWCURSOR_SIZE, GTT_PAGE_SIZE) +
-			     ROUND_TO(HWCURSOR_SIZE_ARGB, GTT_PAGE_SIZE));
-	    }
+	}
+	if (pI830->CursorNeedsPhysical) {
+	    mmsize -= 2 * (ROUND_TO(HWCURSOR_SIZE, GTT_PAGE_SIZE) +
+		    ROUND_TO(HWCURSOR_SIZE_ARGB, GTT_PAGE_SIZE));
 	}
 	if (pI830->fb_compression)
 	    mmsize -= MB(6);
@@ -992,7 +992,7 @@ i830_allocate_overlay(ScrnInfoPtr pScrn)
 	return TRUE;
 
     if (OVERLAY_NOPHYSICAL(pI830))
-	flags = 0;
+	flags &= ~NEED_PHYSICAL_ADDR;
 
     if (!IS_I965G(pI830)) {
 	/* XXX: The lifetime fixed offset for overlay register is bogus, and we
@@ -1193,7 +1193,7 @@ i830_allocate_cursor_buffers(ScrnInfoPtr
 {
     I830Ptr pI830 = I830PTR(pScrn);
     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-    int flags = pI830->CursorNeedsPhysical ? NEED_PHYSICAL_ADDR : 0;
+    int flags = pI830->CursorNeedsPhysical ? NEED_PHYSICAL_ADDR : NEED_LIFETIME_FIXED;
     int i;
     long size;
 
@@ -1381,7 +1381,7 @@ i830_allocate_2d_memory(ScrnInfoPtr pScr
     if (IS_I965G(pI830) && !pI830->noAccel && pI830->exa_965_state == NULL) {
 	pI830->exa_965_state =
 	    i830_allocate_memory(pScrn, "exa G965 state buffer",
-		    EXA_LINEAR_EXTRA, GTT_PAGE_SIZE, 0);
+		    EXA_LINEAR_EXTRA, GTT_PAGE_SIZE, NEED_LIFETIME_FIXED);
 	if (pI830->exa_965_state == NULL) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		    "Failed to allocate exa state buffer for 965.\n");
diff-tree ca67fa767dc762dac369e84b27a7ef15673d527c (from 130f79613bfe6a8cfa7f431c8cce06cbb93cc91a)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Sep 24 11:12:22 2007 -0700

    Remove logic for supporting i915tex_dri.so vs. i915_dri.so.
    
    There can be only one.

diff --git a/src/i830_dri.c b/src/i830_dri.c
index bff885e..6fe75e5 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -102,11 +102,6 @@ typedef struct drm_i915_flip {
 
 #include "dristruct.h"
 
-static char I830KernelDriverName[] = "i915";
-static char I830ClientDriverName[] = "i915tex";
-static char I965ClientDriverName[] = "i965";
-static char I830LegacyClientDriverName[] = "i915";
-
 static Bool I830InitVisualConfigs(ScreenPtr pScreen);
 static Bool I830CreateContext(ScreenPtr pScreen, VisualPtr visual,
 			      drm_context_t hwContext, void *pVisualConfigPriv,
@@ -538,11 +533,11 @@ I830DRIScreenInit(ScreenPtr pScreen)
    pI830->pDRIInfo = pDRIInfo;
    pI830->LockHeld = 0;
 
-   pDRIInfo->drmDriverName = I830KernelDriverName;
+   pDRIInfo->drmDriverName = "i915";
    if (IS_I965G(pI830))
-      pDRIInfo->clientDriverName = I965ClientDriverName;
-   else 
-      pDRIInfo->clientDriverName = I830ClientDriverName;
+      pDRIInfo->clientDriverName = "i965";
+   else
+      pDRIInfo->clientDriverName = "i915";
 
    if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) {
       pDRIInfo->busIdString = DRICreatePCIBusID(pI830->PciInfo);
@@ -719,9 +714,15 @@ I830DRIScreenInit(ScreenPtr pScreen)
 	    drmFreeVersion(version);
 	    return FALSE;
 	 }
-	 if (strncmp(version->name, I830KernelDriverName, strlen(I830KernelDriverName))) {
-	    xf86DrvMsg(pScreen->myNum, X_WARNING, 
-			"i830 Kernel module detected, Use the i915 Kernel module instead, aborting DRI init.\n");
+	 /* Check whether the kernel module attached to the device isn't the
+	  * one we expected (meaning it's the old i830 module).
+	  */
+	 if (strncmp(version->name, pDRIInfo->drmDriverName,
+		     strlen(pDRIInfo->drmDriverName)))
+	 {
+	    xf86DrvMsg(pScreen->myNum, X_WARNING,
+		       "Detected i830 kernel module.  The i915 kernel module "
+		       "is required for DRI.  Aborting.\n");
 	    I830DRICloseScreen(pScreen);
 	    drmFreeVersion(version);
 	    return FALSE;
@@ -739,15 +740,6 @@ I830DRIScreenInit(ScreenPtr pScreen)
       }
    }
 
-   /*
-    * Backwards compatibility
-    */
-
-   if ((pDRIInfo->clientDriverName == I830ClientDriverName) && 
-       (pI830->allocate_classic_textures)) {
-      pDRIInfo->clientDriverName = I830LegacyClientDriverName;
-   }
-
    return TRUE;
 }
 
diff-tree 130f79613bfe6a8cfa7f431c8cce06cbb93cc91a (from parents)
Merge: b73235f40497cfb10792ba191d4f6eac3a5df009 126031655c3c1db9881ad17d712461533eb59632
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Sep 21 17:14:44 2007 -0700

    Merge branch 'buffer-objects'
    
    This branch changes i830_memory.c's allocator to use TTM when available to
    allocate memory, which also allows TTM to control almost the entire aperture.
    As a result, our front/back/depth buffers are created as real buffer objects,
    which may be used by the DRI driver instead of the fake buffer type in TTM.
    The updated DRM with bo_set_pin ioctl is required, to allow us to pin and
    unpin our buffers as needed.

diff-tree 126031655c3c1db9881ad17d712461533eb59632 (from parents)
Merge: c3438356d6b7b63ad9d0086efb084be8e048980e bda3c69a7a044869ea63514b97f8aa9260d6b5a7
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Sep 20 08:57:58 2007 -0700

    Merge remote branch 'origin/master' into buffer-objects
    
    Conflicts:
    
    	src/i830.h
    	src/i830_driver.c

diff --cc src/i830.h
index a39514b,71c46b4..b1f1f68
@@@ -294,14 -291,9 +295,15 @@@
  
     /* These are set in PreInit and never changed. */
     long FbMapSize;
+    long GTTMapSize;
  
 -   i830_memory *memory_list;	/**< Linked list of video memory allocations */
 +   /**
 +    * Linked list of video memory allocations.  The head and tail are
 +    * dummy entries that bound the allocation area.
 +    */
 +   i830_memory *memory_list;
 +   /** Linked list of buffer object memory allocations */
 +   i830_memory *bo_list;
     long stolen_size;		/**< bytes of pre-bound stolen memory */
     int gtt_acquired;		/**< whether we currently own the AGP */
  
@@@ -649,7 -646,14 +655,15 @@@
  
  Bool i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset,
  			 unsigned long size);
 +void i830_allocator_fini(ScrnInfoPtr pScrn);
+ i830_memory * i830_allocate_memory(ScrnInfoPtr pScrn, const char *name,
+ 				   unsigned long size, unsigned long alignment,
+ 				   int flags);
+ 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);
  void i830_describe_allocations(ScrnInfoPtr pScrn, int verbosity,
  			       const char *prefix);
  void i830_reset_allocations(ScrnInfoPtr pScrn);
diff --cc src/i830_driver.c
index 1fbf9d5,1db511b..dc27170
@@@ -2155,9 -2247,16 +2266,13 @@@
     VisualPtr visual;
     I830Ptr pI8301 = NULL;
     unsigned long sys_mem;
-    int i;
+    int i, c;
     Bool allocation_done = FALSE;
     MessageType from;
+ #ifdef XF86DRI
+    Bool driDisabled;
+    xf86CrtcConfigPtr config;
 -#ifdef XF86DRI_MM
 -   unsigned long savedMMSize;
 -#endif
+ #endif
  
     pScrn = xf86Screens[pScreen->myNum];
     pI830 = I830PTR(pScrn);
@@@ -2573,13 -2695,41 +2688,38 @@@
 -	 i830_free_3d_memory(pScrn);
        }
     }
  
 -   driDisabled = !pI830->directRenderingEnabled;
 -
     if (pI830->directRenderingEnabled)
 -      pI830->directRenderingEnabled = I830DRIScreenInit(pScreen);
 +      pI830->directRenderingEnabled = I830DRIDoMappings(pScreen);
  
 -   if (!pI830->directRenderingEnabled) {
 +   /* If we failed for any reason, free DRI memory. */
 +   if (!pI830->directRenderingEnabled)
        i830_free_3d_memory(pScrn);
 -   }
  
+    config = XF86_CRTC_CONFIG_PTR(pScrn);
+ 
+    /*
+     * If an LVDS display is present, swap the plane/pipe mappings so we can
+     * use FBC on the builtin display.
+     * Note: 965+ chips can compress either plane, so we leave the mapping
+     *       alone in that case.
+     * Also make sure the DRM can handle the swap.
+     */
+    if (I830LVDSPresent(pScrn) && !IS_I965GM(pI830) &&
+        (!pI830->directRenderingEnabled ||
+ 	(pI830->directRenderingEnabled && pI830->drmMinor >= 10))) {
+        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "adjusting plane->pipe mappings "
+ 		  "to allow for framebuffer compression\n");
+        for (c = 0; c < config->num_crtc; c++) {
+ 	   xf86CrtcPtr	      crtc = config->crtc[c];
+ 	   I830CrtcPrivatePtr   intel_crtc = crtc->driver_private;
+ 
+ 	   if (intel_crtc->pipe == 0)
+ 	       intel_crtc->plane = 1;
+ 	   else if (intel_crtc->pipe == 1)
+ 	       intel_crtc->plane = 0;
+       }
+    }
+ 
  #else
     pI830->directRenderingEnabled = FALSE;
  #endif
diff --cc src/i830_exa.c
index 353ab8f,273c626..c97e514
@@@ -456,16 -472,21 +472,26 @@@
  
      pI830->bufferOffset = 0;
      pI830->EXADriverPtr->exa_major = 2;
+     /* If compiled against EXA 2.2, require 2.2 so we can use the
+      * PixmapIsOffscreen hook.
+      */
+ #if EXA_VERSION_MINOR >= 2
+     pI830->EXADriverPtr->exa_minor = 2;
+ #else
      pI830->EXADriverPtr->exa_minor = 1;
+     xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ 	       "EXA compatibility mode.  Output rotation rendering "
+ 	       "performance may suffer\n");
+ #endif
      pI830->EXADriverPtr->memoryBase = pI830->FbBase;
 -    pI830->EXADriverPtr->offScreenBase = pI830->exa_offscreen->offset;
 -    pI830->EXADriverPtr->memorySize = pI830->exa_offscreen->offset +
 +    if (pI830->exa_offscreen) {
 +	pI830->EXADriverPtr->offScreenBase = pI830->exa_offscreen->offset;
 +	pI830->EXADriverPtr->memorySize = pI830->exa_offscreen->offset +
  	pI830->exa_offscreen->size;
 +    } else {
 +	pI830->EXADriverPtr->offScreenBase = pI830->FbMapSize;
 +	pI830->EXADriverPtr->memorySize = pI830->FbMapSize;
 +    }
      pI830->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS;
  
      DPRINTF(PFX, "EXA Mem: memoryBase 0x%x, end 0x%x, offscreen base 0x%x, "
diff --cc src/i830_memory.c
index 902ca2d,3da489d..42e88a6
@@@ -725,22 -513,9 +725,22 @@@
  /* Allocates video memory at the given size and alignment.
   *
   * The memory will be bound automatically when the driver is in control of the
 - * VT.
 + * VT.  When the kernel memory manager is available and compatible with flags
 + * (that is, flags doesn't say that the allocation must include a physical
 + * address), that will be used for the allocation.
 + *
 + * flags:
 + * - NEED_PHYSICAL_ADDR: Allocates the memory physically contiguous, and return
 + *   the bus address for that memory.
 + * - ALIGN_BOTH_ENDS: after choosing the alignment, align the end offset to
 + *   @alignment as well.
 + * - NEED_NON-STOLEN: don't allow any part of the memory allocation to lie
 + *   within stolen memory
 + * - NEED_LIFETIME_FIXED: don't allow the buffer object to move throughout
 + *   the entire Screen lifetime.  This means not using buffer objects, which
 + *   get their offsets chosen at each EnterVT time.
   */
- static i830_memory *
+ i830_memory *
  i830_allocate_memory(ScrnInfoPtr pScrn, const char *name,
  		     unsigned long size, unsigned long alignment, int flags)
  {
@@@ -1424,16 -1146,10 +1423,15 @@@
  	     * memory if a low videoRam is specified.
  	     */
  	    size = 3 * pitch * pScrn->virtualY;
- 	    size += 1920 * 1088 * 2 * 2;
  	    size = ROUND_TO_PAGE(size);
  
 -	    pI830->exa_offscreen = i830_allocate_memory(pScrn, "exa offscreen",
 -							size, 1, 0);
 +	    /* EXA has no way to tell it that the offscreen memory manager has
 +	     * moved its base and all the contents with it, so we have to have
 +	     * it locked in place for the whole driver instance.
 +	     */
 +	    pI830->exa_offscreen =
 +		i830_allocate_memory(pScrn, "exa offscreen",
 +				     size, 1, NEED_LIFETIME_FIXED);
  	    if (pI830->exa_offscreen == NULL) {
  		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
  			   "Failed to allocate EXA offscreen memory.");
diff-tree b73235f40497cfb10792ba191d4f6eac3a5df009 (from bda3c69a7a044869ea63514b97f8aa9260d6b5a7)
Author: Hong Liu <hong.liu at intel.com>
Date:   Thu Sep 20 11:28:52 2007 +0800

    Fix pixmap offset
    
    Use consistent interface for counting pixmap offset.

diff --git a/src/i830_exa.c b/src/i830_exa.c
index 273c626..8850382 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -112,9 +112,7 @@ i830_pixmap_tiled(PixmapPtr pPixmap)
     I830Ptr pI830 = I830PTR(pScrn);
     unsigned long offset;
 
-    /* Don't use exaGetPixmapOffset becuase we might be called from XAA code. */
-    offset = (long)pPixmap->devPrivate.ptr -
-	(long)pI830->FbBase;
+    offset = intel_get_pixmap_offset(pPixmap);
     if (offset == pI830->front_buffer->offset &&
 	pI830->front_buffer->tiling != TILE_NONE)
     {
diff --git a/src/i830_video.c b/src/i830_video.c
index 2128eb8..beec03e 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -2402,9 +2402,10 @@ I830PutImage(ScrnInfoPtr pScrn,
     }
 #endif
 
-    if (((char *)pPixmap->devPrivate.ptr < (char *)pI830->FbBase) ||
-	((char *)pPixmap->devPrivate.ptr >= (char *)pI830->FbBase +
-	 pI830->FbMapSize)) {
+    if (!pI830->useEXA &&
+	    (((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.
 	 */
diff --git a/src/i915_video.c b/src/i915_video.c
index a6447b1..00494a7 100644
--- a/src/i915_video.c
+++ b/src/i915_video.c
@@ -127,8 +127,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 |
-	    BUF_3D_PITCH(pPixmap->devKind));
-   OUT_RING(BUF_3D_ADDR((long)pPixmap->devPrivate.ptr - (long)pI830->FbBase));
+	    BUF_3D_PITCH(intel_get_pixmap_pitch(pPixmap)));
+   OUT_RING(BUF_3D_ADDR(intel_get_pixmap_offset(pPixmap)));
    ADVANCE_LP_RING();
 
    if (!planar) {
diff --git a/src/i965_video.c b/src/i965_video.c
index 6ed7f01..0357270 100644
--- a/src/i965_video.c
+++ b/src/i965_video.c
@@ -371,13 +371,12 @@ 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 = (long)pPixmap->devPrivate.ptr -
-	(long)pI830->FbBase;
+    dest_surf_state->ss1.base_addr = intel_get_pixmap_offset(pPixmap);
     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 = pPixmap->devKind - 1;
+    dest_surf_state->ss3.pitch = intel_get_pixmap_pitch(pPixmap) - 1;
     dest_surf_state->ss3.tiled_surface = i830_pixmap_tiled(pPixmap);
     dest_surf_state->ss3.tile_walk = 0; /* TileX */
 
diff-tree bda3c69a7a044869ea63514b97f8aa9260d6b5a7 (from 445a59d262b93bd9d2c16cee9934ce77a103776b)
Author: Dmitry Babrovich <dmitry.babrovich at densitrongaming.com>
Date:   Tue Sep 18 09:34:34 2007 -0700

    Bug #12457: Let the ch7xxx driver probe the 7301
    
    Looking at the 7304, this chipset likely requires slightly different
    programming.  However, this change allows for at least some functionality.

diff --git a/src/ch7xxx/ch7xxx.c b/src/ch7xxx/ch7xxx.c
index 09a9627..3ef9612 100644
--- a/src/ch7xxx/ch7xxx.c
+++ b/src/ch7xxx/ch7xxx.c
@@ -56,6 +56,7 @@ static struct ch7xxx_id_struct {
 	{ CH7011_VID, "CH7011" },
 	{ CH7009A_VID, "CH7009A" },
 	{ CH7009B_VID, "CH7009B" },
+	{ CH7301_VID, "CH7301" },
 };
 
 #define ID_ARRAY_SIZE (sizeof(ch7xxx_ids) / sizeof(ch7xxx_ids[0]))
diff-tree 445a59d262b93bd9d2c16cee9934ce77a103776b (from d02336290bea30de3c390b8121046c38fd6b0f62)
Author: Jesse Barnes <jesse.barnes at intel.com>
Date:   Wed Sep 12 09:32:41 2007 -0700

    Remove unused plane->pipe mappings from SAREA private
    
    Turns out we can get away without this, so remove it, fix a crash, and only
    swap planes/pipes if the DRM can support it.

diff --git a/src/i830_common.h b/src/i830_common.h
index a652428..391ace1 100644
--- a/src/i830_common.h
+++ b/src/i830_common.h
@@ -133,9 +133,6 @@ typedef struct {
 	int planeB_w;
 	int planeB_h;
 
-	int planeA_pipe;
-	int planeB_pipe;
-
 	/* Triple buffering */
 	drm_handle_t third_handle;
 	int third_offset;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 4786195..1db511b 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2252,7 +2252,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    MessageType from;
 #ifdef XF86DRI
    Bool driDisabled;
-   drmI830Sarea *sPriv;
    xf86CrtcConfigPtr config;
 #ifdef XF86DRI_MM
    unsigned long savedMMSize;
@@ -2707,14 +2706,13 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    }
 
    config = XF86_CRTC_CONFIG_PTR(pScrn);
-   sPriv = DRIGetSAREAPrivate(pScreen);
 
    /*
     * If an LVDS display is present, swap the plane/pipe mappings so we can
     * use FBC on the builtin display.
     * Note: 965+ chips can compress either plane, so we leave the mapping
     *       alone in that case.
-    * Also, only flip the pipes if the DRM can support it.
+    * Also make sure the DRM can handle the swap.
     */
    if (I830LVDSPresent(pScrn) && !IS_I965GM(pI830) &&
        (!pI830->directRenderingEnabled ||
@@ -2725,19 +2723,13 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 	   xf86CrtcPtr	      crtc = config->crtc[c];
 	   I830CrtcPrivatePtr   intel_crtc = crtc->driver_private;
 
-	   if (intel_crtc->pipe == 0) {
+	   if (intel_crtc->pipe == 0)
 	       intel_crtc->plane = 1;
-	       sPriv->planeB_pipe = 0;
-	   } else if (intel_crtc->pipe == 1) {
+	   else if (intel_crtc->pipe == 1)
 	       intel_crtc->plane = 0;
-	       sPriv->planeA_pipe = 1;
-	   }
       }
    }
 
-   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "drm planeA pipe: %d, "
-	      "planeB pipe: %d\n", sPriv->planeA_pipe, sPriv->planeB_pipe);
-
 #else
    pI830->directRenderingEnabled = FALSE;
 #endif
diff-tree d02336290bea30de3c390b8121046c38fd6b0f62 (from d9f2b3c0d2d08a4b7fad865dab7deb6224b57999)
Author: Jesse Barnes <jbarnes at nietzche.virtuousgeek.org>
Date:   Tue Sep 11 04:28:14 2007 -0700

    Fix plane/pipe mapping compat code
    
    Move plane->pipe mapping adjustment to ScreenInit so we can check
    against the DRM driver version accurately.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 27ec918..4786195 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -850,35 +850,24 @@ I830SetupOutputs(ScrnInfoPtr pScrn)
       output->possible_crtcs = crtc_mask;
       output->possible_clones = i830_output_clones (pScrn, intel_output->clone_mask);
    }
+}
 
-   /* Only recent DRM drivers can support plane<->pipe reversal */
-   if (pI830->directRenderingEnabled && pI830->drmMinor < 10)
-       goto out;
+static int
+I830LVDSPresent(ScrnInfoPtr pScrn)
+{
+   xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR (pScrn);
+   int o, lvds_detected = FALSE;
 
-   /*
-    * If an LVDS display is present, swap the plane/pipe mappings so we can
-    * use FBC on the builtin display.
-    * Note: 965+ chips can compress either plane, so we leave the mapping
-    *       alone in that case.
-    */
-   if (lvds_detected && !IS_I965GM(pI830)) {
-       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "adjusting plane->pipe mappings "
-		  "to allow for framebuffer compression\n");
-       for (c = 0; c < config->num_crtc; c++) {
-	   xf86CrtcPtr	      crtc = config->crtc[c];
-	   I830CrtcPrivatePtr   intel_crtc = crtc->driver_private;
+   for (o = 0; o < config->num_output; o++) {
+      xf86OutputPtr	   output = config->output[o];
+      I830OutputPrivatePtr intel_output = output->driver_private;
 
-	   if (intel_crtc->pipe == 0)
-	       intel_crtc->plane = 1;
-	   else if (intel_crtc->pipe == 1)
-	       intel_crtc->plane = 0;
-      }
+      if (intel_output->type == I830_OUTPUT_LVDS)
+	  lvds_detected = TRUE;
    }
 
-out:
-   return;
+   return lvds_detected;
 }
-
 /**
  * Setup the CRTCs
  */
@@ -2719,15 +2708,31 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 
    config = XF86_CRTC_CONFIG_PTR(pScrn);
    sPriv = DRIGetSAREAPrivate(pScreen);
-   /* Setup pipe->plane mappings for DRI & DRM */
-   for (c = 0; c < config->num_crtc; c++) {
-       xf86CrtcPtr crtc = config->crtc[c];
-       I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
-
-       if (intel_crtc->plane == 0)
-	   sPriv->planeA_pipe = intel_crtc->pipe;
-       else if (intel_crtc->plane == 1)
-	   sPriv->planeB_pipe = intel_crtc->pipe;
+
+   /*
+    * If an LVDS display is present, swap the plane/pipe mappings so we can
+    * use FBC on the builtin display.
+    * Note: 965+ chips can compress either plane, so we leave the mapping
+    *       alone in that case.
+    * Also, only flip the pipes if the DRM can support it.
+    */
+   if (I830LVDSPresent(pScrn) && !IS_I965GM(pI830) &&
+       (!pI830->directRenderingEnabled ||
+	(pI830->directRenderingEnabled && pI830->drmMinor >= 10))) {
+       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "adjusting plane->pipe mappings "
+		  "to allow for framebuffer compression\n");
+       for (c = 0; c < config->num_crtc; c++) {
+	   xf86CrtcPtr	      crtc = config->crtc[c];
+	   I830CrtcPrivatePtr   intel_crtc = crtc->driver_private;
+
+	   if (intel_crtc->pipe == 0) {
+	       intel_crtc->plane = 1;
+	       sPriv->planeB_pipe = 0;
+	   } else if (intel_crtc->pipe == 1) {
+	       intel_crtc->plane = 0;
+	       sPriv->planeA_pipe = 1;
+	   }
+      }
    }
 
    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "drm planeA pipe: %d, "
diff-tree d9f2b3c0d2d08a4b7fad865dab7deb6224b57999 (from 4c7542ef43a5267e470ca1608a2ae57abf9783ec)
Author: Jesse Barnes <jbarnes at nietzche.virtuousgeek.org>
Date:   Mon Sep 10 23:49:34 2007 -0700

    Fix crash in ScreenInit
    
    Use pScreen directly when getting at the SAREA private, since
    pScrn->pScreen may not be initialized yet.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index ea22855..27ec918 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2718,7 +2718,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    }
 
    config = XF86_CRTC_CONFIG_PTR(pScrn);
-   sPriv = DRIGetSAREAPrivate(pScrn->pScreen);
+   sPriv = DRIGetSAREAPrivate(pScreen);
    /* Setup pipe->plane mappings for DRI & DRM */
    for (c = 0; c < config->num_crtc; c++) {
        xf86CrtcPtr crtc = config->crtc[c];
diff-tree 4c7542ef43a5267e470ca1608a2ae57abf9783ec (from 286f5df0b62f571cbb4dbf120679d3af029b8775)
Author: Jesse Barnes <jesse.barnes at intel.com>
Date:   Mon Sep 10 23:30:50 2007 -0700

    Only swap planes and pipes if DRM supports it
    
    We want to associate plane A with pipe B on pre-965 mobile chips, since that's
    the only way to get framebuffer compression on the builtin LVDS on those
    platforms.  However, if we do this swapping and DRM isn't aware of it, we may
    end up requesting vblank events for the wrong pipe, or setting up SAREA buffer
    swap state incorrectly.
    
    This mod checks whether DRM supports the new plane->pipe swapping behavior, and
    only enables the swapping if so.  This should fix the bugs Lukas found and
    debugged.  Reviewed by Michel Danzer.

diff --git a/src/i830_common.h b/src/i830_common.h
index 9c8616c..a652428 100644
--- a/src/i830_common.h
+++ b/src/i830_common.h
@@ -124,14 +124,17 @@ typedef struct {
         unsigned int rotated_tiled;
         unsigned int rotated2_tiled;
 
-	int pipeA_x;
-	int pipeA_y;
-	int pipeA_w;
-	int pipeA_h;
-	int pipeB_x;
-	int pipeB_y;
-	int pipeB_w;
-	int pipeB_h;
+	int planeA_x;
+	int planeA_y;
+	int planeA_w;
+	int planeA_h;
+	int planeB_x;
+	int planeB_y;
+	int planeB_w;
+	int planeB_h;
+
+	int planeA_pipe;
+	int planeB_pipe;
 
 	/* Triple buffering */
 	drm_handle_t third_handle;
diff --git a/src/i830_display.c b/src/i830_display.c
index d8be8d9..92e52ed 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -414,14 +414,14 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x,
 	if (!sPriv)
 	    return;
 
-	switch (pipe) {
+	switch (plane) {
 	case 0:
-	    sPriv->pipeA_x = x;
-	    sPriv->pipeA_y = y;
+	    sPriv->planeA_x = x;
+	    sPriv->planeA_y = y;
 	    break;
 	case 1:
-	    sPriv->pipeB_x = x;
-	    sPriv->pipeB_y = y;
+	    sPriv->planeB_x = x;
+	    sPriv->planeB_y = y;
 	    break;
 	default:
 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
@@ -763,14 +763,14 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mod
 	if (!sPriv)
 	    return;
 
-	switch (pipe) {
+	switch (plane) {
 	case 0:
-	    sPriv->pipeA_w = enabled ? crtc->mode.HDisplay : 0;
-	    sPriv->pipeA_h = enabled ? crtc->mode.VDisplay : 0;
+	    sPriv->planeA_w = enabled ? crtc->mode.HDisplay : 0;
+	    sPriv->planeA_h = enabled ? crtc->mode.VDisplay : 0;
 	    break;
 	case 1:
-	    sPriv->pipeB_w = enabled ? crtc->mode.HDisplay : 0;
-	    sPriv->pipeB_h = enabled ? crtc->mode.VDisplay : 0;
+	    sPriv->planeB_w = enabled ? crtc->mode.HDisplay : 0;
+	    sPriv->planeB_h = enabled ? crtc->mode.VDisplay : 0;
 	    break;
 	default:
 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 32f6510..2654ae6 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -91,7 +91,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define DRM_VBLANK_FLIP 0x8000000
 
 typedef struct drm_i915_flip {
-   int pipes;
+   int planes;
 } drm_i915_flip_t;
 
 #undef DRM_IOCTL_I915_FLIP
@@ -1288,20 +1288,20 @@ I830DRISwapContext(ScreenPtr pScreen, DR
 #ifdef DAMAGE
       /* Try flipping back to the front page if necessary */
       if (sPriv && !sPriv->pf_enabled && sPriv->pf_current_page != 0) {
-	 drm_i915_flip_t flip = { .pipes = 0 };
+	 drm_i915_flip_t flip = { .planes = 0 };
 
 	 if (sPriv->pf_current_page & (0x3 << 2)) {
 	    sPriv->pf_current_page = sPriv->pf_current_page & 0x3;
 	    sPriv->pf_current_page |= (sPriv->third_handle ? 2 : 1) << 2;
 
-	    flip.pipes |= 0x2;
+	    flip.planes |= 0x2;
 	 }
 
 	 if (sPriv->pf_current_page & 0x3) {
 	    sPriv->pf_current_page = sPriv->pf_current_page & (0x3 << 2);
 	    sPriv->pf_current_page |= sPriv->third_handle ? 2 : 1;
 
-	    flip.pipes |= 0x1;
+	    flip.planes |= 0x1;
 	 }
 
 	 drmCommandWrite(pI830->drmSubFD, DRM_I915_FLIP, &flip, sizeof(flip));
@@ -1634,14 +1634,14 @@ I830DRIClipNotify(ScreenPtr pScreen, Win
       unsigned numvisible[2] = { 0, 0 };
       int i, j;
 
-      crtcBox[0].x1 = sPriv->pipeA_x;
-      crtcBox[0].y1 = sPriv->pipeA_y;
-      crtcBox[0].x2 = crtcBox[0].x1 + sPriv->pipeA_w;
-      crtcBox[0].y2 = crtcBox[0].y1 + sPriv->pipeA_h;
-      crtcBox[1].x1 = sPriv->pipeB_x;
-      crtcBox[1].y1 = sPriv->pipeB_y;
-      crtcBox[1].x2 = crtcBox[1].x1 + sPriv->pipeB_w;
-      crtcBox[1].y2 = crtcBox[1].y1 + sPriv->pipeB_h;
+      crtcBox[0].x1 = sPriv->planeA_x;
+      crtcBox[0].y1 = sPriv->planeA_y;
+      crtcBox[0].x2 = crtcBox[0].x1 + sPriv->planeA_w;
+      crtcBox[0].y2 = crtcBox[0].y1 + sPriv->planeA_h;
+      crtcBox[1].x1 = sPriv->planeB_x;
+      crtcBox[1].y1 = sPriv->planeB_y;
+      crtcBox[1].x2 = crtcBox[1].x1 + sPriv->planeB_w;
+      crtcBox[1].y2 = crtcBox[1].y1 + sPriv->planeB_h;
 
       for (i = 0; i < 2; i++) {
 	 for (j = 0; j < num; j++) {
diff --git a/src/i830_driver.c b/src/i830_driver.c
index b168fd4..ea22855 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -851,6 +851,10 @@ I830SetupOutputs(ScrnInfoPtr pScrn)
       output->possible_clones = i830_output_clones (pScrn, intel_output->clone_mask);
    }
 
+   /* Only recent DRM drivers can support plane<->pipe reversal */
+   if (pI830->directRenderingEnabled && pI830->drmMinor < 10)
+       goto out;
+
    /*
     * If an LVDS display is present, swap the plane/pipe mappings so we can
     * use FBC on the builtin display.
@@ -858,6 +862,8 @@ I830SetupOutputs(ScrnInfoPtr pScrn)
     *       alone in that case.
     */
    if (lvds_detected && !IS_I965GM(pI830)) {
+       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "adjusting plane->pipe mappings "
+		  "to allow for framebuffer compression\n");
        for (c = 0; c < config->num_crtc; c++) {
 	   xf86CrtcPtr	      crtc = config->crtc[c];
 	   I830CrtcPrivatePtr   intel_crtc = crtc->driver_private;
@@ -868,6 +874,9 @@ I830SetupOutputs(ScrnInfoPtr pScrn)
 	       intel_crtc->plane = 0;
       }
    }
+
+out:
+   return;
 }
 
 /**
@@ -2249,11 +2258,13 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    VisualPtr visual;
    I830Ptr pI8301 = NULL;
    unsigned long sys_mem;
-   int i;
+   int i, c;
    Bool allocation_done = FALSE;
    MessageType from;
 #ifdef XF86DRI
    Bool driDisabled;
+   drmI830Sarea *sPriv;
+   xf86CrtcConfigPtr config;
 #ifdef XF86DRI_MM
    unsigned long savedMMSize;
 #endif
@@ -2706,6 +2717,22 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       i830_free_3d_memory(pScrn);
    }
 
+   config = XF86_CRTC_CONFIG_PTR(pScrn);
+   sPriv = DRIGetSAREAPrivate(pScrn->pScreen);
+   /* Setup pipe->plane mappings for DRI & DRM */
+   for (c = 0; c < config->num_crtc; c++) {
+       xf86CrtcPtr crtc = config->crtc[c];
+       I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+
+       if (intel_crtc->plane == 0)
+	   sPriv->planeA_pipe = intel_crtc->pipe;
+       else if (intel_crtc->plane == 1)
+	   sPriv->planeB_pipe = intel_crtc->pipe;
+   }
+
+   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "drm planeA pipe: %d, "
+	      "planeB pipe: %d\n", sPriv->planeA_pipe, sPriv->planeB_pipe);
+
 #else
    pI830->directRenderingEnabled = FALSE;
 #endif
diff-tree 286f5df0b62f571cbb4dbf120679d3af029b8775 (from 2a8592f2ebcba86b1127aa889155d58a3dc186ca)
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Thu Sep 6 14:31:55 2007 -0700

    Switch to pci_device_map_range/pci_device_unmap_range APIs.
    
    With the libpciaccess change that added these new APIs, use them
    for all mapping.

diff --git a/src/i810.h b/src/i810.h
index 2031408..8023c38 100644
--- a/src/i810.h
+++ b/src/i810.h
@@ -190,8 +190,6 @@ typedef struct _I810Rec {
    IOADDRESS ioBase;
    EntityInfoPtr pEnt;
 #if XSERVER_LIBPCIACCESS
-   int mmio_bar;
-   int fb_bar;
    struct pci_device *PciInfo;
 #else
    pciVideoPtr PciInfo;
diff --git a/src/i810_driver.c b/src/i810_driver.c
index e55f942..a6c13ed 100644
--- a/src/i810_driver.c
+++ b/src/i810_driver.c
@@ -1080,8 +1080,7 @@ I810PreInit(ScrnInfoPtr pScrn, int flags
 	      (pScrn->chipset != NULL) ? pScrn->chipset : "Unknown i810");
 
 #if XSERVER_LIBPCIACCESS
-   pI810->fb_bar = 0;
-   pI810->LinearAddr = pI810->PciInfo->regions[pI810->fb_bar].base_addr;
+   pI810->LinearAddr = pI810->PciInfo->regions[0].base_addr;
 #else
    if (pI810->pEnt->device->MemBase != 0) {
       pI810->LinearAddr = pI810->pEnt->device->MemBase;
@@ -1102,8 +1101,7 @@ I810PreInit(ScrnInfoPtr pScrn, int flags
 	      (unsigned long)pI810->LinearAddr);
 
 #if XSERVER_LIBPCIACCESS
-   pI810->mmio_bar = 1;
-   pI810->MMIOAddr = pI810->PciInfo->regions[pI810->mmio_bar].base_addr;
+   pI810->MMIOAddr = pI810->PciInfo->regions[1].base_addr;
 #else
    if (pI810->pEnt->device->IOBase != 0) {
       pI810->MMIOAddr = pI810->pEnt->device->IOBase;
@@ -1409,7 +1407,11 @@ I810MapMMIO(ScrnInfoPtr pScrn)
 #endif
 
 #if XSERVER_LIBPCIACCESS
-   err = pci_device_map_region (device, pI810->mmio_bar, TRUE);
+   err = pci_device_map_range (device,
+			       pI810->MMIOAddr,
+			       I810_REG_SIZE,
+			       PCI_DEV_MAP_FLAG_WRITABLE,
+			       (void **) &pI810->MMIOBase);
    if (err) 
    {
       xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
@@ -1417,7 +1419,6 @@ I810MapMMIO(ScrnInfoPtr pScrn)
 		  strerror (err), err);
       return FALSE;
    }
-   pI810->MMIOBase = device->regions[pI810->mmio_bar].memory;
 #else
    pI810->MMIOBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags,
 				   pI810->PciTag,
@@ -1432,19 +1433,22 @@ static Bool
 I810MapMem(ScrnInfoPtr pScrn)
 {
    I810Ptr pI810 = I810PTR(pScrn);
-   long i;
 #if XSERVER_LIBPCIACCESS
    struct pci_device *const device = pI810->PciInfo;
    int err;
+#else
+   long i;
 #endif
 
-   for (i = 2; i < pI810->FbMapSize; i <<= 1) ;
-
    if (!I810MapMMIO(pScrn))
       return FALSE;
 
 #if XSERVER_LIBPCIACCESS
-   err = pci_device_map_region (device, pI810->fb_bar, TRUE);
+   err = pci_device_map_range (device,
+			       pI810->LinearAddr,
+			       pI810->FbMapSize,
+			       PCI_DEV_MAP_FLAG_WRITABLE | PCI_DEV_MAP_FLAG_WRITE_COMBINE,
+			       (void **) &pI810->FbBase);
    if (err) 
    {
       xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
@@ -1452,9 +1456,9 @@ I810MapMem(ScrnInfoPtr pScrn)
 		  strerror (err), err);
       return FALSE;
    }
-   pI810->FbBase = device->regions[pI810->fb_bar].memory;
-   pI810->FbMapSize = device->regions[pI810->fb_bar].size;
 #else
+   for (i = 2; i < pI810->FbMapSize; i <<= 1) ;
+
    pI810->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
 				 pI810->PciTag,
 				 pI810->LinearAddr, i);
@@ -1473,7 +1477,7 @@ I810UnmapMMIO(ScrnInfoPtr pScrn)
    I810Ptr pI810 = I810PTR(pScrn);
 
 #if XSERVER_LIBPCIACCESS
-   pci_device_unmap_region (pI810->PciInfo, pI810->mmio_bar);
+   pci_device_unmap_range (pI810->PciInfo, pI810->MMIOBase, I810_REG_SIZE);
 #else
    xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pI810->MMIOBase,
 		   I810_REG_SIZE);
@@ -1487,7 +1491,7 @@ I810UnmapMem(ScrnInfoPtr pScrn)
    I810Ptr pI810 = I810PTR(pScrn);
 
 #if XSERVER_LIBPCIACCESS
-   pci_device_unmap_region (pI810->PciInfo, pI810->fb_bar);
+   pci_device_unmap_range (pI810->PciInfo, pI810->FbBase, pI810->FbMapSize);
 #else
    xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pI810->FbBase,
 		   pI810->FbMapSize);
diff --git a/src/i830.h b/src/i830.h
index 4f176f8..71c46b4 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -291,6 +291,7 @@ typedef struct _I830Rec {
 
    /* These are set in PreInit and never changed. */
    long FbMapSize;
+   long GTTMapSize;
 
    i830_memory *memory_list;	/**< Linked list of video memory allocations */
    long stolen_size;		/**< bytes of pre-bound stolen memory */
@@ -367,9 +368,6 @@ typedef struct _I830Rec {
    EntityInfoPtr pEnt;
 #if XSERVER_LIBPCIACCESS
    struct pci_device *PciInfo;
-   int mmio_bar;
-   int fb_bar;
-   int gtt_bar;
 #else
    pciVideoPtr PciInfo;
    PCITAG PciTag;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 983be76..b168fd4 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -565,41 +565,19 @@ I830MapMMIO(ScrnInfoPtr pScrn)
    I830Ptr pI830 = I830PTR(pScrn);
 
 #if XSERVER_LIBPCIACCESS
-   pI830->GTTBase = NULL;
    device = pI830->PciInfo;
-   err = pci_device_map_region (device, pI830->mmio_bar, TRUE);
+   err = pci_device_map_range (device,
+			       pI830->MMIOAddr,
+			       I810_REG_SIZE,
+			       PCI_DEV_MAP_FLAG_WRITABLE,
+			       (void **) &pI830->MMIOBase);
    if (err) 
    {
       xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
-		  "Unable to map mmio BAR. %s (%d)\n",
+		  "Unable to map mmio range. %s (%d)\n",
 		  strerror (err), err);
       return FALSE;
    }
-   pI830->MMIOBase = device->regions[pI830->mmio_bar].memory;
-   pI830->gtt_bar = -1;
-	
-   /* XXX GTT aperture base needs figuring out */
-   if (IS_I9XX(pI830)) 
-   {
-      if (IS_I965G(pI830))
-      {
-	 pI830->GTTBase = (unsigned char *) pI830->MMIOBase + (512 * 1024);
-      }
-      else
-      {
-	 pI830->gtt_bar = 3;
-	 err = pci_device_map_region (device, pI830->gtt_bar, TRUE);
-	 if (err)
-	 {
-	    xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
-			"Unable to map GTT BAR. %s (%d)\n",
-			strerror (err), err);
-	    pI830->GTTBase = NULL;
-	 }
-	 else
-	    pI830->GTTBase = device->regions[pI830->gtt_bar].memory;
-      }
-   }
 #else
 
 #if !defined(__alpha__)
@@ -613,35 +591,50 @@ I830MapMMIO(ScrnInfoPtr pScrn)
 				   pI830->MMIOAddr, I810_REG_SIZE);
    if (!pI830->MMIOBase)
       return FALSE;
+#endif
 
    /* Set up the GTT mapping for the various places it has been moved over
     * time.
     */
    if (IS_I9XX(pI830)) {
-      if (IS_I965G(pI830)) {
-	 pI830->GTTBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags,
-					pI830->PciTag,
-					pI830->MMIOAddr + (512 * 1024),
-					512 * 1024);
-	 if (pI830->GTTBase == NULL)
-	    return FALSE;
-      } else {
-	 CARD32 gttaddr = pI830->PciInfo->memBase[3] & 0xFFFFFF00;
-
-	 pI830->GTTBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags,
-					pI830->PciTag,
-					gttaddr,
-					pI830->FbMapSize / 1024);
-	 if (pI830->GTTBase == NULL)
-	    return FALSE;
+      CARD32   gttaddr;
+      
+      if (IS_I965G(pI830)) 
+      {
+	 gttaddr = pI830->MMIOAddr + (512 * 1024);
+	 pI830->GTTMapSize = 512 * 1024;
       }
+      else
+      {
+	 gttaddr = I810_MEMBASE(pI830->PciInfo, 3) & 0xFFFFFF00;
+	 pI830->GTTMapSize = pI830->FbMapSize / 1024;
+      }
+#if XSERVER_LIBPCIACCESS
+      err = pci_device_map_range (device,
+				  gttaddr, pI830->GTTMapSize,
+				  PCI_DEV_MAP_FLAG_WRITABLE,
+				  (void **) &pI830->GTTBase);
+      if (err)
+      {
+	 xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
+		     "Unable to map GTT range. %s (%d)\n",
+		     strerror (err), err);
+	 return FALSE;
+      }
+#else
+      pI830->GTTBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags,
+				     pI830->PciTag,
+				     gttaddr, pI830->GTTMapSize);
+      if (pI830->GTTBase == NULL)
+	 return FALSE;
+#endif
    } else {
       /* The GTT aperture on i830 is write-only.  We could probably map the
        * actual physical pages that back it, but leave it alone for now.
        */
       pI830->GTTBase = NULL;
+      pI830->GTTMapSize = 0;
    }
-#endif /* else HAVE_PCI_ACCESS */
 
    return TRUE;
 }
@@ -663,16 +656,9 @@ I830MapMem(ScrnInfoPtr pScrn)
       return FALSE;
 
 #if XSERVER_LIBPCIACCESS
-   err = pci_device_map_region (device, pI830->fb_bar, TRUE);
-   if (err) 
-   {
-      xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
-		  "Unable to map frame buffer BAR. %s (%d)\n",
-		  strerror (err), err);
-      return FALSE;
-   }
-   pI830->FbBase = device->regions[pI830->fb_bar].memory;
-   pI830->FbMapSize = device->regions[pI830->fb_bar].size;
+   err = pci_device_map_range (device, pI830->LinearAddr, pI830->FbMapSize,
+			       PCI_DEV_MAP_FLAG_WRITABLE | PCI_DEV_MAP_FLAG_WRITE_COMBINE,
+			       (void **) &pI830->FbBase);
 #else
    pI830->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
 				 pI830->PciTag,
@@ -695,7 +681,7 @@ I830UnmapMMIO(ScrnInfoPtr pScrn)
    I830Ptr pI830 = I830PTR(pScrn);
 
 #if XSERVER_LIBPCIACCESS
-   pci_device_unmap_region (pI830->PciInfo, pI830->mmio_bar);
+   pci_device_unmap_range (pI830->PciInfo, pI830->MMIOBase, I810_REG_SIZE);
 #else
    xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pI830->MMIOBase,
 		   I810_REG_SIZE);
@@ -703,23 +689,12 @@ I830UnmapMMIO(ScrnInfoPtr pScrn)
    pI830->MMIOBase = NULL;
 
    if (IS_I9XX(pI830)) {
-      if (IS_I965G(pI830))
-      {
 #if XSERVER_LIBPCIACCESS
-	 ;
+      pci_device_unmap_range (pI830->PciInfo, pI830->GTTBase, pI830->GTTMapSize);
 #else
-	 xf86UnMapVidMem(pScrn->scrnIndex, pI830->GTTBase, 512 * 1024);
+      xf86UnMapVidMem(pScrn->scrnIndex, pI830->GTTBase, pI830->GTTMapSize);
 #endif
-      }
-      else 
-      {
-#if XSERVER_LIBPCIACCESS
-	 pci_device_unmap_region (pI830->PciInfo, pI830->gtt_bar);
-#else
-	 xf86UnMapVidMem(pScrn->scrnIndex, pI830->GTTBase,
-			 pI830->FbMapSize / 1024);
-#endif
-      }
+      pI830->GTTBase = NULL;
    }
 }
 
@@ -728,8 +703,12 @@ I830UnmapMem(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
 
+#if XSERVER_LIBPCIACCESS
+   pci_device_unmap_range (pI830->PciInfo, pI830->FbBase, pI830->FbMapSize);
+#else
    xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pI830->FbBase,
 		   pI830->FbMapSize);
+#endif
    pI830->FbBase = NULL;
    I830UnmapMMIO(pScrn);
    return TRUE;
@@ -1017,6 +996,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    int num_pipe;
    int max_width, max_height;
    uint32_t	capid;
+   int fb_bar, mmio_bar;
 
    if (pScrn->numEntities != 1)
       return FALSE;
@@ -1266,61 +1246,45 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n",
 	      (pScrn->chipset != NULL) ? pScrn->chipset : "Unknown i8xx");
 
-#if XSERVER_LIBPCIACCESS
    if (IS_I9XX(pI830))
-      pI830->fb_bar = 2;
+   {
+      fb_bar = 2;
+      mmio_bar = 0;
+   }
    else
-      pI830->fb_bar = 0;
-   pI830->LinearAddr = pI830->PciInfo->regions[pI830->fb_bar].base_addr;
-#else
+   {
+      fb_bar = 0;
+      mmio_bar = 1;
+   }
+
    if (pI830->pEnt->device->MemBase != 0) {
       pI830->LinearAddr = pI830->pEnt->device->MemBase;
       from = X_CONFIG;
    } else {
-      if (IS_I9XX(pI830)) {
-	 pI830->LinearAddr = pI830->PciInfo->memBase[2] & 0xFF000000;
-	 from = X_PROBED;
-      } else if (pI830->PciInfo->memBase[1] != 0) {
-	 /* XXX Check mask. */
-	 pI830->LinearAddr = pI830->PciInfo->memBase[0] & 0xFF000000;
-	 from = X_PROBED;
-      } else {
+      pI830->LinearAddr = I810_MEMBASE (pI830->PciInfo, fb_bar);
+      if (pI830->LinearAddr == 0) {
 	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		    "No valid FB address in PCI config space\n");
 	 PreInitCleanup(pScrn);
 	 return FALSE;
       }
    }
-#endif
 
    xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n",
 	      (unsigned long)pI830->LinearAddr);
 
-#if XSERVER_LIBPCIACCESS
-   if (IS_I9XX(pI830))
-      pI830->mmio_bar = 0;
-   else
-      pI830->mmio_bar = 1;
-   pI830->MMIOAddr = pI830->PciInfo->regions[pI830->mmio_bar].base_addr;
-#else
    if (pI830->pEnt->device->IOBase != 0) {
       pI830->MMIOAddr = pI830->pEnt->device->IOBase;
       from = X_CONFIG;
    } else {
-      if (IS_I9XX(pI830)) {
-	 pI830->MMIOAddr = pI830->PciInfo->memBase[0] & 0xFFF80000;
-	 from = X_PROBED;
-      } else if (pI830->PciInfo->memBase[1]) {
-	 pI830->MMIOAddr = pI830->PciInfo->memBase[1] & 0xFFF80000;
-	 from = X_PROBED;
-      } else {
+      pI830->MMIOAddr = I810_MEMBASE (pI830->PciInfo, mmio_bar);
+      if (pI830->MMIOAddr == 0) {
 	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		    "No valid MMIO address in PCI config space\n");
 	 PreInitCleanup(pScrn);
 	 return FALSE;
       }
    }
-#endif
 
    xf86DrvMsg(pScrn->scrnIndex, from, "IO registers at addr 0x%lX\n",
 	      (unsigned long)pI830->MMIOAddr);
@@ -1365,7 +1329,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    } else {
       if (IS_I9XX(pI830)) {
 #if XSERVER_LIBPCIACCESS
-	 pI830->FbMapSize = pI830->PciInfo->regions[pI830->fb_bar].size;
+	 pI830->FbMapSize = pI830->PciInfo->regions[fb_bar].size;
 #else
 	 pI830->FbMapSize = 1UL << pciGetBaseSize(pI830->PciTag, 2, TRUE,
 						  NULL);
diff --git a/src/reg_dumper/main.c b/src/reg_dumper/main.c
index b3c50de..5c8ef9e 100644
--- a/src/reg_dumper/main.c
+++ b/src/reg_dumper/main.c
@@ -40,6 +40,7 @@ int main(int argc, char **argv)
     I830Rec i830;
     ScrnInfoRec scrn;
     int err, mmio_bar;
+    void *mmio;
 
     err = pci_system_init();
     if (err != 0) {
@@ -68,12 +69,17 @@ int main(int argc, char **argv)
 
     mmio_bar = IS_I9XX((&i830)) ? 0 : 1;
 
-    err = pci_device_map_region(dev, mmio_bar, 1);
+    err = pci_device_map_range (dev,
+				dev->regions[mmio_bar].base_addr,
+				dev->regions[mmio_bar].size, 
+				PCI_DEV_MAP_FLAG_WRITABLE,
+				&mmio);
+    
     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;
+    i830.mmio = mmio;
 
     scrn.scrnIndex = 0;
     scrn.pI830 = &i830;
diff-tree 2a8592f2ebcba86b1127aa889155d58a3dc186ca (from 7fd9a98178cdebda4213796fdc452a8a265a1197)
Author: Zhenyu Wang <zhenyu.z.wang at intel.com>
Date:   Wed Sep 5 14:52:56 2007 +0800

    Fix G33 GTT stolen mem range
    
    G33 GTT table lives in seperate stolen mem with
    graphics data stolen mem.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 9fa231d..983be76 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -483,6 +483,9 @@ I830DetectMemory(ScrnInfoPtr pScrn)
    range = gtt_size + 4;
 
    if (IS_I85X(pI830) || IS_I865G(pI830) || IS_I9XX(pI830)) {
+      /* G33 has seperate GTT stolen mem */
+      if (IS_G33CLASS(pI830))
+	  range = 0;
       switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
       case I855_GMCH_GMS_STOLEN_1M:
 	 memsize = MB(1) - KB(range);
diff-tree 7fd9a98178cdebda4213796fdc452a8a265a1197 (from c6e637cd683dc60567b3b4f69b7f2b4c338c89ea)
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Tue Aug 28 16:00:01 2007 -0700

    Don't set supported TV formats until after RandR initialized.
    
    The TV format property cannot be configured until RandR has been
    initialized.

diff --git a/src/i830_tv.c b/src/i830_tv.c
index d86e984..940250e 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -1507,6 +1507,9 @@ i830_tv_format_configure_property (xf86O
     int			    num_atoms = 0;
     int			    i;
     
+    if (!output->randr_output)
+	return Success;
+
     for (i = 0; i < NUM_TV_MODES; i++)
 	if (!tv_modes[i].component_only || dev_priv->type == TV_TYPE_COMPONENT)
 	    current_atoms[num_atoms++] = tv_format_name_atoms[i];
diff-tree c6e637cd683dc60567b3b4f69b7f2b4c338c89ea (from ddd6053987b9ca9bd3722ddbdfd412a3d8d252cf)
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Tue Aug 28 12:17:15 2007 -0700

    Limit TV formats to those supported by current connection

diff --git a/src/i830_exa.c b/src/i830_exa.c
index fa50da0..273c626 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -124,7 +124,7 @@ i830_pixmap_tiled(PixmapPtr pPixmap)
     return FALSE;
 }
 
-Bool
+static Bool
 i830_exa_pixmap_is_offscreen(PixmapPtr pPixmap)
 {
     ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
diff --git a/src/i830_tv.c b/src/i830_tv.c
index c90d41e..d86e984 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -1264,14 +1264,13 @@ static const DisplayModeRec reported_mod
  * \return TRUE if TV is connected.
  * \return FALSE if TV is disconnected.
  */
-static void
+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;
@@ -1337,9 +1336,14 @@ i830_tv_detect_type (xf86CrtcPtr    crtc
 	type = TV_TYPE_NONE;
     }
 
-    dev_priv->type = type;
+    return type;
 }
 
+#ifdef RANDR_12_INTERFACE
+static int
+i830_tv_format_configure_property (xf86OutputPtr output);
+#endif
+
 /**
  * Detect the TV connection.
  *
@@ -1354,17 +1358,26 @@ i830_tv_detect(xf86OutputPtr output)
     I830OutputPrivatePtr    intel_output = output->driver_private;
     struct i830_tv_priv	    *dev_priv = intel_output->dev_priv;
     int			    dpms_mode;
+    int			    type = dev_priv->type;
 
     mode = reported_modes[0];
     xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
     crtc = i830GetLoadDetectPipe (output, &mode, &dpms_mode);
     if (crtc)
     {
-        i830_tv_detect_type (crtc, output);
+        type = i830_tv_detect_type (crtc, output);
         i830ReleaseLoadDetectPipe (output, dpms_mode);
     }
 
-    switch (dev_priv->type) {
+    if (type != dev_priv->type)
+    {
+	dev_priv->type = type;
+#ifdef RANDR_12_INTERFACE
+	i830_tv_format_configure_property (output);
+#endif
+    }
+	
+    switch (type) {
     case TV_TYPE_NONE:
         return XF86OutputStatusDisconnected;
     case TV_TYPE_UNKNOWN:
@@ -1477,6 +1490,32 @@ i830_tv_format_set_property (xf86OutputP
     return err == Success;
 }
 
+    
+/**
+ * Configure the TV_FORMAT property to list only supported formats
+ *
+ * Unless the connector is component, list only the formats supported by
+ * svideo and composite
+ */
+
+static int
+i830_tv_format_configure_property (xf86OutputPtr output)
+{
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    struct i830_tv_priv	    *dev_priv = intel_output->dev_priv;
+    Atom		    current_atoms[NUM_TV_MODES];
+    int			    num_atoms = 0;
+    int			    i;
+    
+    for (i = 0; i < NUM_TV_MODES; i++)
+	if (!tv_modes[i].component_only || dev_priv->type == TV_TYPE_COMPONENT)
+	    current_atoms[num_atoms++] = tv_format_name_atoms[i];
+    
+    return RRConfigureOutputProperty(output->randr_output, tv_format_atom,
+				     TRUE, FALSE, FALSE, 
+				     num_atoms, (INT32 *) current_atoms);
+}
+
 #endif /* RANDR_12_INTERFACE */
 
 static void
@@ -1500,10 +1539,8 @@ i830_tv_create_resources(xf86OutputPtr o
 					    strlen (tv_modes[i].name),
 					    TRUE);
 
-    err = RRConfigureOutputProperty(output->randr_output, tv_format_atom,
-				    TRUE, FALSE, FALSE, 
-				    NUM_TV_MODES, (INT32 *) tv_format_name_atoms);
-    
+    err = i830_tv_format_configure_property (output);
+
     if (err != 0) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		   "RRConfigureOutputProperty error, %d\n", err);
diff --git a/src/xvmc/I810XvMC.h b/src/xvmc/I810XvMC.h
index ba8c792..dc2cab8 100644
--- a/src/xvmc/I810XvMC.h
+++ b/src/xvmc/I810XvMC.h
@@ -41,6 +41,7 @@ THE USE OR OTHER DEALINGS IN THE SOFTWAR
 /* #define XVMC_DEBUG(x) do {x; }while(0); */
 #define XVMC_DEBUG(x)
 
+#include <stdint.h>
 #include "xf86drm.h"
 #include "i810_common.h"
 #include <X11/Xlibint.h>
diff-tree ddd6053987b9ca9bd3722ddbdfd412a3d8d252cf (from 3fbbd0afde49c53a5a8661f75c8c8c4be3020c30)
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Tue Aug 28 12:30:46 2007 -0700

    Add register defines for hw binning

diff --git a/src/i810_reg.h b/src/i810_reg.h
index 03e10d6..598fc8c 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -346,19 +346,33 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define IPEIR                  0x2088
 #define IPEHR                  0x208C
 #define INST_DONE                0x2090
+#define SCPD0                    0x209c	/* debug */
 #define INST_PS                  0x20c4
 #define IPEIR_I965                  0x2064 /* i965 */
 #define IPEHR_I965                  0x2068 /* i965 */
 #define INST_DONE_I965              0x206c
 #define INST_PS_I965                0x2070
+
+/* Current active ring head address: 
+ */
 #define ACTHD                 0x2074
+
+/* Current primary/secondary DMA fetch addresses:
+ */
 #define DMA_FADD_P             0x2078
+#define DMA_FADD_S               0x20d4
 #define INST_DONE_1              0x207c
 
 #define CACHE_MODE_0           0x2120
 #define CACHE_MODE_1           0x2124
 #define MI_ARB_STATE           0x20e4
 
+/* Start addresses for each of the primary rings:
+ */
+#define PR0_STR                  0x20f0
+#define PR1_STR                  0x20f4
+#define PR2_STR                  0x20f8
+
 #define WIZ_CTL                0x7c00
 #define WIZ_CTL_SINGLE_SUBSPAN  (1<<6)
 #define WIZ_CTL_IGNORE_STALLS  (1<<5)
diff-tree 3fbbd0afde49c53a5a8661f75c8c8c4be3020c30 (from 0fdbf64b34e4114c2b89d696b268b9c7464f1efd)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Tue Aug 28 17:48:20 2007 +0200

    Fix build against pre-pci-rework xserver.

diff --git a/src/common.h b/src/common.h
index cfe00fc..40ea038 100644
--- a/src/common.h
+++ b/src/common.h
@@ -444,7 +444,9 @@ extern int I810_DEBUG;
 
 #define PIPE_NAME(n)			('A' + (n))
 
+#if XSERVER_LIBPCIACCESS
 struct pci_device *
 intel_host_bridge (void);
+#endif
    
 #endif /* _INTEL_COMMON_H_ */
diff-tree 0fdbf64b34e4114c2b89d696b268b9c7464f1efd (from 3411eb0dbae470b910af3116a4ab960c821b9b20)
Author: Zhenyu Wang <zhenyu.z.wang at intel.com>
Date:   Tue Aug 28 21:56:21 2007 +0800

    Fix i915 a8 color buffer blending
    
    From spec, i915 engine uses green channel when reading from 8bit
    color buffer for blending, and also writes back green channel.
    Fix blend factor in dest alpha case by using dest color instead.
    Now rendercheck can pass a8 tests.

diff --git a/src/i915_render.c b/src/i915_render.c
index 7546dfd..ca85bf7 100644
--- a/src/i915_render.c
+++ b/src/i915_render.c
@@ -123,6 +123,17 @@ static CARD32 i915_get_blend_cntl(int op
             sblend = BLENDFACT_ZERO;
     }
 
+    /* i915 engine reads 8bit color buffer into green channel in cases
+       like color buffer blending .etc, and also writes back green channel.
+       So with dst_alpha blend we should use color factor. See spec on
+       "8-bit rendering" */
+    if ((dst_format == PICT_a8) && i915_blend_op[op].dst_alpha) {
+        if (sblend == BLENDFACT_DST_ALPHA)
+            sblend = BLENDFACT_DST_COLR;
+        else if (sblend == BLENDFACT_INV_DST_ALPHA)
+            sblend = BLENDFACT_INV_DST_COLR;
+    }
+
     /* 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.
diff-tree 3411eb0dbae470b910af3116a4ab960c821b9b20 (from 387fed6daa7426e4a85d30ba7cf608b5f41d24bb)
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Sun Aug 26 23:09:01 2007 -0700

    i830_driver.c changes for libpciaccess.
    
    Change to use libpciaccess APIs, including computing and using BAR indices
    for various mapping activities.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index ab42fd9..9fa231d 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -201,6 +201,9 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "dri.h"
 #include <sys/ioctl.h>
 #include <errno.h>
+#ifdef XF86DRI_MM
+#include "xf86mm.h"
+#endif
 #endif
 
 #ifdef I830_USE_EXA
@@ -418,16 +421,23 @@ static int
 I830DetectMemory(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
+#if !XSERVER_LIBPCIACCESS
    PCITAG bridge;
-   CARD16 gmch_ctrl;
+#endif
+   uint16_t gmch_ctrl;
    int memsize = 0, gtt_size;
    int range;
 #if 0
    VbeInfoBlock *vbeInfo;
 #endif
 
+#if XSERVER_LIBPCIACCESS
+   struct pci_device *bridge = intel_host_bridge ();
+   pci_device_cfg_read_u16(bridge, & gmch_ctrl, I830_GMCH_CTRL);
+#else
    bridge = pciTag(0, 0, 0);		/* This is always the host bridge */
    gmch_ctrl = pciReadWord(bridge, I830_GMCH_CTRL);
+#endif
 
    if (IS_I965G(pI830)) {
       /* The 965 may have a GTT that is actually larger than is necessary
@@ -543,9 +553,52 @@ I830DetectMemory(ScrnInfoPtr pScrn)
 static Bool
 I830MapMMIO(ScrnInfoPtr pScrn)
 {
+#if XSERVER_LIBPCIACCESS
+   int err;
+   struct pci_device *device;
+#else
    int mmioFlags;
+#endif
    I830Ptr pI830 = I830PTR(pScrn);
 
+#if XSERVER_LIBPCIACCESS
+   pI830->GTTBase = NULL;
+   device = pI830->PciInfo;
+   err = pci_device_map_region (device, pI830->mmio_bar, TRUE);
+   if (err) 
+   {
+      xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
+		  "Unable to map mmio BAR. %s (%d)\n",
+		  strerror (err), err);
+      return FALSE;
+   }
+   pI830->MMIOBase = device->regions[pI830->mmio_bar].memory;
+   pI830->gtt_bar = -1;
+	
+   /* XXX GTT aperture base needs figuring out */
+   if (IS_I9XX(pI830)) 
+   {
+      if (IS_I965G(pI830))
+      {
+	 pI830->GTTBase = (unsigned char *) pI830->MMIOBase + (512 * 1024);
+      }
+      else
+      {
+	 pI830->gtt_bar = 3;
+	 err = pci_device_map_region (device, pI830->gtt_bar, TRUE);
+	 if (err)
+	 {
+	    xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
+			"Unable to map GTT BAR. %s (%d)\n",
+			strerror (err), err);
+	    pI830->GTTBase = NULL;
+	 }
+	 else
+	    pI830->GTTBase = device->regions[pI830->gtt_bar].memory;
+      }
+   }
+#else
+
 #if !defined(__alpha__)
    mmioFlags = VIDMEM_MMIO | VIDMEM_READSIDEEFFECT;
 #else
@@ -585,6 +638,7 @@ I830MapMMIO(ScrnInfoPtr pScrn)
        */
       pI830->GTTBase = NULL;
    }
+#endif /* else HAVE_PCI_ACCESS */
 
    return TRUE;
 }
@@ -594,6 +648,10 @@ I830MapMem(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
    long i;
+#if XSERVER_LIBPCIACCESS
+   struct pci_device *const device = pI830->PciInfo;
+   int err;
+#endif
 
    for (i = 2; i < pI830->FbMapSize; i <<= 1) ;
    pI830->FbMapSize = i;
@@ -601,11 +659,24 @@ I830MapMem(ScrnInfoPtr pScrn)
    if (!I830MapMMIO(pScrn))
       return FALSE;
 
+#if XSERVER_LIBPCIACCESS
+   err = pci_device_map_region (device, pI830->fb_bar, TRUE);
+   if (err) 
+   {
+      xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
+		  "Unable to map frame buffer BAR. %s (%d)\n",
+		  strerror (err), err);
+      return FALSE;
+   }
+   pI830->FbBase = device->regions[pI830->fb_bar].memory;
+   pI830->FbMapSize = device->regions[pI830->fb_bar].size;
+#else
    pI830->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
 				 pI830->PciTag,
 				 pI830->LinearAddr, pI830->FbMapSize);
    if (!pI830->FbBase)
       return FALSE;
+#endif
 
    if (I830IsPrimary(pScrn) && pI830->LpRing->mem != NULL) {
       pI830->LpRing->virtual_start =
@@ -620,16 +691,31 @@ I830UnmapMMIO(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
 
+#if XSERVER_LIBPCIACCESS
+   pci_device_unmap_region (pI830->PciInfo, pI830->mmio_bar);
+#else
    xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pI830->MMIOBase,
 		   I810_REG_SIZE);
+#endif
    pI830->MMIOBase = NULL;
 
    if (IS_I9XX(pI830)) {
       if (IS_I965G(pI830))
+      {
+#if XSERVER_LIBPCIACCESS
+	 ;
+#else
 	 xf86UnMapVidMem(pScrn->scrnIndex, pI830->GTTBase, 512 * 1024);
-      else {
+#endif
+      }
+      else 
+      {
+#if XSERVER_LIBPCIACCESS
+	 pci_device_unmap_region (pI830->PciInfo, pI830->gtt_bar);
+#else
 	 xf86UnMapVidMem(pScrn->scrnIndex, pI830->GTTBase,
 			 pI830->FbMapSize / 1024);
+#endif
       }
    }
 }
@@ -927,6 +1013,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    const char *chipname;
    int num_pipe;
    int max_width, max_height;
+   uint32_t	capid;
 
    if (pScrn->numEntities != 1)
       return FALSE;
@@ -971,8 +1058,10 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       return FALSE;
 
    pI830->PciInfo = xf86GetPciInfoForEntity(pI830->pEnt->index);
+#if !XSERVER_LIBPCIACCESS
    pI830->PciTag = pciTag(pI830->PciInfo->bus, pI830->PciInfo->device,
 			  pI830->PciInfo->func);
+#endif
 
     /* Allocate an entity private if necessary */
     if (xf86IsEntityShared(pScrn->entityList[0])) {
@@ -1061,7 +1150,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    /* We have to use PIO to probe, because we haven't mapped yet. */
    I830SetPIOAccess(pI830);
 
-   switch (pI830->PciInfo->chipType) {
+   switch (DEVICE_ID(pI830->PciInfo)) {
    case PCI_CHIP_I830_M:
       chipname = "830M";
       break;
@@ -1070,8 +1159,12 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       break;
    case PCI_CHIP_I855_GM:
       /* Check capid register to find the chipset variant */
-      pI830->variant = (pciReadLong(pI830->PciTag, I85X_CAPID)
-				>> I85X_VARIANT_SHIFT) & I85X_VARIANT_MASK;
+#if XSERVER_LIBPCIACCESS
+      pci_device_cfg_read_u32 (pI830->PciInfo, &capid, I85X_CAPID);
+#else
+      capid = pciReadLong (pI830->PciTag, I85X_CAPID);
+#endif
+      pI830->variant = (capid >> I85X_VARIANT_SHIFT) & I85X_VARIANT_MASK;
       switch (pI830->variant) {
       case I855_GM:
 	 chipname = "855GM";
@@ -1155,11 +1248,11 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       from = X_CONFIG;
       xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
 		 pI830->pEnt->device->chipID);
-      pI830->PciInfo->chipType = pI830->pEnt->device->chipID;
+      DEVICE_ID(pI830->PciInfo) = pI830->pEnt->device->chipID;
    } else {
       from = X_PROBED;
       pScrn->chipset = (char *)xf86TokenToString(I830Chipsets,
-						 pI830->PciInfo->chipType);
+						 DEVICE_ID(pI830->PciInfo));
    }
 
    if (pI830->pEnt->device->chipRev >= 0) {
@@ -1170,6 +1263,13 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n",
 	      (pScrn->chipset != NULL) ? pScrn->chipset : "Unknown i8xx");
 
+#if XSERVER_LIBPCIACCESS
+   if (IS_I9XX(pI830))
+      pI830->fb_bar = 2;
+   else
+      pI830->fb_bar = 0;
+   pI830->LinearAddr = pI830->PciInfo->regions[pI830->fb_bar].base_addr;
+#else
    if (pI830->pEnt->device->MemBase != 0) {
       pI830->LinearAddr = pI830->pEnt->device->MemBase;
       from = X_CONFIG;
@@ -1188,10 +1288,18 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 	 return FALSE;
       }
    }
+#endif
 
    xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n",
 	      (unsigned long)pI830->LinearAddr);
 
+#if XSERVER_LIBPCIACCESS
+   if (IS_I9XX(pI830))
+      pI830->mmio_bar = 0;
+   else
+      pI830->mmio_bar = 1;
+   pI830->MMIOAddr = pI830->PciInfo->regions[pI830->mmio_bar].base_addr;
+#else
    if (pI830->pEnt->device->IOBase != 0) {
       pI830->MMIOAddr = pI830->pEnt->device->IOBase;
       from = X_CONFIG;
@@ -1209,6 +1317,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 	 return FALSE;
       }
    }
+#endif
 
    xf86DrvMsg(pScrn->scrnIndex, from, "IO registers at addr 0x%lX\n",
 	      (unsigned long)pI830->MMIOAddr);
@@ -1232,11 +1341,19 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    xf86CrtcSetSizeRange (pScrn, 320, 200, max_width, max_height);
 
    if (IS_I830(pI830) || IS_845G(pI830)) {
+#if XSERVER_LIBPCIACCESS
+      uint16_t		gmch_ctrl;
+      struct pci_device *bridge;
+
+      bridge = intel_host_bridge ();
+      pci_device_cfg_read_u16 (bridge, &gmch_ctrl, I830_GMCH_CTRL);
+#else
       PCITAG bridge;
       CARD16 gmch_ctrl;
 
       bridge = pciTag(0, 0, 0);		/* This is always the host bridge */
       gmch_ctrl = pciReadWord(bridge, I830_GMCH_CTRL);
+#endif
       if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_128M) {
 	 pI830->FbMapSize = 0x8000000;
       } else {
@@ -1244,8 +1361,12 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       }
    } else {
       if (IS_I9XX(pI830)) {
+#if XSERVER_LIBPCIACCESS
+	 pI830->FbMapSize = pI830->PciInfo->regions[pI830->fb_bar].size;
+#else
 	 pI830->FbMapSize = 1UL << pciGetBaseSize(pI830->PciTag, 2, TRUE,
 						  NULL);
+#endif
       } else {
 	 /* 128MB aperture for later i8xx series. */
 	 pI830->FbMapSize = 0x8000000;
@@ -1275,7 +1396,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 		(1 << 23) | (2 << 16));
 #endif
 
-   if (pI830->PciInfo->chipType == PCI_CHIP_E7221_G)
+   if (DEVICE_ID(pI830->PciInfo) == PCI_CHIP_E7221_G)
       num_pipe = 1;
    else
    if (IS_MOBILE(pI830) || IS_I9XX(pI830))
diff-tree 387fed6daa7426e4a85d30ba7cf608b5f41d24bb (from 2c794192052ca55c3263e27e13d16aafe8caa92c)
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Sun Aug 26 23:06:57 2007 -0700

    i810_driver.c changes for libpciaccess.
    
    This includes new probe code (intel_pci_probe) and changes for i810 to
    use BAR indices to refer to suitable portions of the device mappings.

diff --git a/src/i810_driver.c b/src/i810_driver.c
index 972b6d5..e55f942 100644
--- a/src/i810_driver.c
+++ b/src/i810_driver.c
@@ -94,7 +94,16 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 /* Required Functions: */
 
 static void I810Identify(int flags);
+
+#if XSERVER_LIBPCIACCESS
+static Bool intel_pci_probe (DriverPtr		drv,
+			     int		entity_num,
+			     struct pci_device	*dev,
+			     intptr_t		match_data);
+#else
 static Bool I810Probe(DriverPtr drv, int flags);
+#endif
+
 #ifndef I830_ONLY
 static Bool I810PreInit(ScrnInfoPtr pScrn, int flags);
 static Bool I810ScreenInit(int Index, ScreenPtr pScreen, int argc,
@@ -112,14 +121,59 @@ static ModeStatus I810ValidMode(int scrn
 #endif /* I830_ONLY */
 
 
+#if XSERVER_LIBPCIACCESS
+
+#define INTEL_DEVICE_MATCH(d,i) \
+    { 0x8086, (d), PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, (i) }
+
+static const struct pci_id_match intel_device_match[] = {
+#ifndef I830_ONLY
+   INTEL_DEVICE_MATCH (PCI_CHIP_I810, 0 ),
+   INTEL_DEVICE_MATCH (PCI_CHIP_I810_DC100, 0 ),
+   INTEL_DEVICE_MATCH (PCI_CHIP_I810_E, 0 ),
+   INTEL_DEVICE_MATCH (PCI_CHIP_I815, 0 ),
+#endif
+   INTEL_DEVICE_MATCH (PCI_CHIP_I830_M, 0 ),
+   INTEL_DEVICE_MATCH (PCI_CHIP_845_G, 0 ),
+   INTEL_DEVICE_MATCH (PCI_CHIP_I855_GM, 0 ),
+   INTEL_DEVICE_MATCH (PCI_CHIP_I865_G, 0 ),
+   INTEL_DEVICE_MATCH (PCI_CHIP_I915_G, 0 ),
+   INTEL_DEVICE_MATCH (PCI_CHIP_E7221_G, 0 ),
+   INTEL_DEVICE_MATCH (PCI_CHIP_I915_GM, 0 ),
+   INTEL_DEVICE_MATCH (PCI_CHIP_I945_G, 0 ),
+   INTEL_DEVICE_MATCH (PCI_CHIP_I945_GM, 0 ),
+   INTEL_DEVICE_MATCH (PCI_CHIP_I945_GME, 0 ),
+   INTEL_DEVICE_MATCH (PCI_CHIP_I965_G, 0 ),
+   INTEL_DEVICE_MATCH (PCI_CHIP_I965_G_1, 0 ),
+   INTEL_DEVICE_MATCH (PCI_CHIP_I965_Q, 0 ),
+   INTEL_DEVICE_MATCH (PCI_CHIP_I946_GZ, 0 ),
+   INTEL_DEVICE_MATCH (PCI_CHIP_I965_GM, 0 ),
+   INTEL_DEVICE_MATCH (PCI_CHIP_I965_GME, 0 ),
+   INTEL_DEVICE_MATCH (PCI_CHIP_G33_G, 0 ),
+   INTEL_DEVICE_MATCH (PCI_CHIP_Q35_G, 0 ),
+   INTEL_DEVICE_MATCH (PCI_CHIP_Q33_G, 0 ),
+    { 0, 0, 0 },
+};
+
+#endif /* XSERVER_LIBPCIACCESS */
+
 _X_EXPORT DriverRec I810 = {
    I810_VERSION,
    I810_DRIVER_NAME,
    I810Identify,
+#if XSERVER_LIBPCIACCESS
+   NULL,
+#else
    I810Probe,
+#endif
    I810AvailableOptions,
    NULL,
-   0
+   0,
+   NULL,
+#if XSERVER_LIBPCIACCESS
+   intel_device_match,
+   intel_pci_probe
+#endif
 };
 
 /* *INDENT-OFF* */
@@ -429,7 +483,13 @@ i810Setup(pointer module, pointer opts, 
     */
    if (!setupDone) {
       setupDone = 1;
-      xf86AddDriver(&I810, module, 0);
+      xf86AddDriver(&I810, module,
+#if XSERVER_LIBPCIACCESS
+		    HaveDriverFuncs
+#else
+		    0
+#endif
+		    );
 
       /*
        * Tell the loader about symbols from other modules that this module
@@ -517,6 +577,113 @@ I810AvailableOptions(int chipid, int bus
 #endif
 }
 
+#if XSERVER_LIBPCIACCESS
+struct pci_device *
+intel_host_bridge (void)
+{
+    static const struct pci_slot_match bridge_match = {
+	0, 0, 0, PCI_MATCH_ANY, 0
+    };
+    struct pci_device_iterator	*slot_iterator;
+    struct pci_device		*bridge;
+
+    slot_iterator = pci_slot_match_iterator_create (&bridge_match);
+    bridge = pci_device_next (slot_iterator);
+    pci_iterator_destroy (slot_iterator);
+    return bridge;
+}
+
+/*
+ * intel_pci_probe --
+ *
+ * Look through the PCI bus to find cards that are intel boards.
+ * Setup the dispatch table for the rest of the driver functions.
+ *
+ */
+static Bool intel_pci_probe (DriverPtr		driver,
+			     int		entity_num,
+			     struct pci_device	*device,
+			     intptr_t		match_data)
+{
+    ScrnInfoPtr	    scrn = NULL;
+    EntityInfoPtr   entity;
+    I830EntPtr	    i830_ent = NULL;
+    DevUnion	    *private;
+
+    scrn = xf86ConfigPciEntity (scrn, 0, entity_num, I810PciChipsets,
+				NULL,
+				NULL, NULL, NULL, NULL);
+    if (scrn != NULL)
+    {
+	scrn->driverVersion = I810_VERSION;
+	scrn->driverName = I810_DRIVER_NAME;
+	scrn->name = I810_NAME;
+	scrn->Probe = NULL;
+
+	entity = xf86GetEntityInfo (entity_num);
+	
+	switch (DEVICE_ID(device)) {
+#ifndef I830_ONLY
+	case PCI_CHIP_I810:
+	case PCI_CHIP_I810_DC100:
+	case PCI_CHIP_I810_E:
+	case PCI_CHIP_I815:
+	    scrn->PreInit = I810PreInit;
+	    scrn->ScreenInit = I810ScreenInit;
+	    scrn->SwitchMode = I810SwitchMode;
+	    scrn->AdjustFrame = I810AdjustFrame;
+	    scrn->EnterVT = I810EnterVT;
+	    scrn->LeaveVT = I810LeaveVT;
+	    scrn->FreeScreen = I810FreeScreen;
+	    scrn->ValidMode = I810ValidMode;
+	    break;
+#endif
+	case PCI_CHIP_845_G:
+	case PCI_CHIP_I865_G:
+	    /*
+	     * These two chips have only one pipe, and
+	     * cannot do dual-head
+	     */
+	    I830InitpScrn(scrn);
+	    break;
+	default:
+	    /*
+	     * Everything else is an i830-ish dual-pipe chip
+	     */
+	    xf86SetEntitySharable(entity_num);
+
+	    /* Allocate an entity private if necessary */		
+	    if (I830EntityIndex < 0)					
+		I830EntityIndex = xf86AllocateEntityPrivateIndex();	
+
+	    private = xf86GetEntityPrivate(scrn->entityList[0],
+					   I830EntityIndex);	
+	    i830_ent = private->ptr;
+	    if (!i830_ent)
+	    {
+		private->ptr = xnfcalloc(sizeof(I830EntRec), 1);
+		i830_ent = private->ptr;
+		i830_ent->lastInstance = -1;
+	    }
+
+	    /*
+	     * 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".
+	     */
+	    i830_ent->lastInstance++;
+	    xf86SetEntityInstanceForScreen(scrn,			
+					   scrn->entityList[0],
+					   i830_ent->lastInstance);	
+	    I830InitpScrn(scrn);
+	    break;
+	}
+    }
+    return scrn != NULL;
+}
+#else /* XSERVER_LIBPCIACCESS */
+
 /*
  * I810Probe --
  *
@@ -678,6 +845,7 @@ I810Probe(DriverPtr drv, int flags)
 
    return foundScreen;
 }
+#endif /* else XSERVER_LIBPCIACCESS */
 
 #ifndef I830_ONLY
 static void
@@ -769,8 +937,10 @@ I810PreInit(ScrnInfoPtr pScrn, int flags
    pI810->ioBase = hwp->PIOOffset;
 
    pI810->PciInfo = xf86GetPciInfoForEntity(pI810->pEnt->index);
+#if !XSERVER_LIBPCIACCESS
    pI810->PciTag = pciTag(pI810->PciInfo->bus, pI810->PciInfo->device,
 			  pI810->PciInfo->func);
+#endif
 
    if (xf86RegisterResources(pI810->pEnt->index, NULL, ResNone))
       return FALSE;
@@ -899,7 +1069,7 @@ I810PreInit(ScrnInfoPtr pScrn, int flags
    } else {
       from = X_PROBED;
       pScrn->chipset = (char *)xf86TokenToString(I810Chipsets,
-						 pI810->PciInfo->chipType);
+						 DEVICE_ID(pI810->PciInfo));
    }
    if (pI810->pEnt->device->chipRev >= 0) {
       xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
@@ -909,6 +1079,10 @@ I810PreInit(ScrnInfoPtr pScrn, int flags
    xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n",
 	      (pScrn->chipset != NULL) ? pScrn->chipset : "Unknown i810");
 
+#if XSERVER_LIBPCIACCESS
+   pI810->fb_bar = 0;
+   pI810->LinearAddr = pI810->PciInfo->regions[pI810->fb_bar].base_addr;
+#else
    if (pI810->pEnt->device->MemBase != 0) {
       pI810->LinearAddr = pI810->pEnt->device->MemBase;
       from = X_CONFIG;
@@ -923,9 +1097,14 @@ I810PreInit(ScrnInfoPtr pScrn, int flags
 	 return FALSE;
       }
    }
+#endif
    xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n",
 	      (unsigned long)pI810->LinearAddr);
 
+#if XSERVER_LIBPCIACCESS
+   pI810->mmio_bar = 1;
+   pI810->MMIOAddr = pI810->PciInfo->regions[pI810->mmio_bar].base_addr;
+#else
    if (pI810->pEnt->device->IOBase != 0) {
       pI810->MMIOAddr = pI810->pEnt->device->IOBase;
       from = X_CONFIG;
@@ -940,6 +1119,7 @@ I810PreInit(ScrnInfoPtr pScrn, int flags
 	 return FALSE;
       }
    }
+#endif
    xf86DrvMsg(pScrn->scrnIndex, from, "IO registers at addr 0x%lX\n",
 	      (unsigned long)pI810->MMIOAddr);
 
@@ -956,8 +1136,13 @@ I810PreInit(ScrnInfoPtr pScrn, int flags
    /* Find out memory bus frequency.
     */
    {
-      unsigned long whtcfg_pamr_drp = pciReadLong(pI810->PciTag,
-						  WHTCFG_PAMR_DRP);
+      uint32_t whtcfg_pamr_drp;
+    
+#if XSERVER_LIBPCIACCESS
+      pci_device_cfg_read_u32(pI810->PciInfo, & whtcfg_pamr_drp, WHTCFG_PAMR_DRP);
+#else
+      whtcfg_pamr_drp = pciReadLong(pI810->PciTag, WHTCFG_PAMR_DRP);
+#endif
 
       /* Need this for choosing watermarks.
        */
@@ -1010,11 +1195,19 @@ I810PreInit(ScrnInfoPtr pScrn, int flags
 
    /* Calculate Fixed Offsets depending on graphics aperture size */
    {
+#if XSERVER_LIBPCIACCESS
+      struct pci_device *bridge = intel_host_bridge ();
+      uint32_t   smram_miscc;
+      
+      pci_device_cfg_read_u32 (bridge, & smram_miscc, SMRAM_MISCC);
+#else
       PCITAG bridge;
       long smram_miscc;
 
       bridge = pciTag(0, 0, 0);		/* This is always the host bridge */
       smram_miscc = pciReadLong(bridge, SMRAM_MISCC);
+#endif
+
       if ((smram_miscc & GFX_MEM_WIN_SIZE) == GFX_MEM_WIN_32M) {
 	 pI810->FbMapSize = 0x1000000;
 	 pI810->DepthOffset = 0x1000000;
@@ -1204,6 +1397,10 @@ I810MapMMIO(ScrnInfoPtr pScrn)
 {
    int mmioFlags;
    I810Ptr pI810 = I810PTR(pScrn);
+#if XSERVER_LIBPCIACCESS
+   struct pci_device *const device = pI810->PciInfo;
+   int err;
+#endif
 
 #if !defined(__alpha__)
    mmioFlags = VIDMEM_MMIO | VIDMEM_READSIDEEFFECT;
@@ -1211,11 +1408,23 @@ I810MapMMIO(ScrnInfoPtr pScrn)
    mmioFlags = VIDMEM_MMIO | VIDMEM_READSIDEEFFECT | VIDMEM_SPARSE;
 #endif
 
+#if XSERVER_LIBPCIACCESS
+   err = pci_device_map_region (device, pI810->mmio_bar, TRUE);
+   if (err) 
+   {
+      xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
+		  "Unable to map mmio BAR. %s (%d)\n",
+		  strerror (err), err);
+      return FALSE;
+   }
+   pI810->MMIOBase = device->regions[pI810->mmio_bar].memory;
+#else
    pI810->MMIOBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags,
 				   pI810->PciTag,
 				   pI810->MMIOAddr, I810_REG_SIZE);
    if (!pI810->MMIOBase)
       return FALSE;
+#endif
    return TRUE;
 }
 
@@ -1224,17 +1433,34 @@ I810MapMem(ScrnInfoPtr pScrn)
 {
    I810Ptr pI810 = I810PTR(pScrn);
    long i;
+#if XSERVER_LIBPCIACCESS
+   struct pci_device *const device = pI810->PciInfo;
+   int err;
+#endif
 
    for (i = 2; i < pI810->FbMapSize; i <<= 1) ;
 
    if (!I810MapMMIO(pScrn))
       return FALSE;
 
+#if XSERVER_LIBPCIACCESS
+   err = pci_device_map_region (device, pI810->fb_bar, TRUE);
+   if (err) 
+   {
+      xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
+		  "Unable to map frame buffer BAR. %s (%d)\n",
+		  strerror (err), err);
+      return FALSE;
+   }
+   pI810->FbBase = device->regions[pI810->fb_bar].memory;
+   pI810->FbMapSize = device->regions[pI810->fb_bar].size;
+#else
    pI810->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
 				 pI810->PciTag,
 				 pI810->LinearAddr, i);
    if (!pI810->FbBase)
       return FALSE;
+#endif
 
    pI810->LpRing->virtual_start = pI810->FbBase + pI810->LpRing->mem.Start;
 
@@ -1246,8 +1472,12 @@ I810UnmapMMIO(ScrnInfoPtr pScrn)
 {
    I810Ptr pI810 = I810PTR(pScrn);
 
+#if XSERVER_LIBPCIACCESS
+   pci_device_unmap_region (pI810->PciInfo, pI810->mmio_bar);
+#else
    xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pI810->MMIOBase,
 		   I810_REG_SIZE);
+#endif
    pI810->MMIOBase = NULL;
 }
 
@@ -1256,8 +1486,12 @@ I810UnmapMem(ScrnInfoPtr pScrn)
 {
    I810Ptr pI810 = I810PTR(pScrn);
 
+#if XSERVER_LIBPCIACCESS
+   pci_device_unmap_region (pI810->PciInfo, pI810->fb_bar);
+#else
    xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pI810->FbBase,
 		   pI810->FbMapSize);
+#endif
    pI810->FbBase = NULL;
    I810UnmapMMIO(pScrn);
    return TRUE;
diff-tree 2c794192052ca55c3263e27e13d16aafe8caa92c (from 70e8e5957200401474967a467663ae049e9080f2)
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Sun Aug 26 22:46:19 2007 -0700

    Mechanical API conversions for libpciaccess.
    
    Uncomplicated API transistions for libpciaccess usage:
    
    	Legacy xf86 API		libpciaccess API
    	---------------		----------------
    	xf86ReadPciBIOS 	pci_device_read_rom
    	pciReadWord 		pci_device_cfg_read_u16
    	pciWriteByte 		pci_device_cfg_write_u8
    
    And, more use of the API-independent DEVICE_ID/SUBVENDOR_ID/SUBSYS_ID macros
    to pull PCI identification data from the underlying structure.

diff --git a/src/i830_bios.c b/src/i830_bios.c
index 7703c80..7ed791e 100644
--- a/src/i830_bios.c
+++ b/src/i830_bios.c
@@ -97,7 +97,11 @@ i830_bios_get (ScrnInfoPtr pScrn)
 	       INTEL_VBIOS_SIZE);
 	vbeFree (pVbe);
     } else {
+#if XSERVER_LIBPCIACCESS
+	pci_device_read_rom (pI830->PciInfo, bios);
+#else
 	xf86ReadPciBIOS(0, pI830->PciTag, 0, bios, INTEL_VBIOS_SIZE);
+#endif
     }
 
     if (0)
diff --git a/src/i830_display.c b/src/i830_display.c
index 0ab0de7..d8be8d9 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -868,9 +868,14 @@ i830_get_core_clock_speed(ScrnInfoPtr pS
     else if (IS_I945GM(pI830) || IS_845G(pI830))
 	return 200000;
     else if (IS_I915GM(pI830)) {
-	CARD16 gcfgc = pciReadWord(pI830->PciTag, I915_GCFGC);
+	uint16_t gcfgc;
 
-	if (gcfgc & I915_LOW_FREQUENCY_ENABLE)
+#if XSERVER_LIBPCIACCESS
+      pci_device_cfg_read_u16 (pI830->PciInfo, &gcfgc, I915_GCFGC);
+#else
+      gcfgc = pciReadWord(pI830->PciTag, I915_GCFGC);
+#endif
+      if (gcfgc & I915_LOW_FREQUENCY_ENABLE)
 	    return 133000;
 	else {
 	    switch (gcfgc & I915_DISPLAY_CLOCK_MASK) {
@@ -884,8 +889,14 @@ i830_get_core_clock_speed(ScrnInfoPtr pS
     } else if (IS_I865G(pI830))
 	return 266000;
     else if (IS_I855(pI830)) {
+#if XSERVER_LIBPCIACCESS
+        struct pci_device *bridge = intel_host_bridge ();
+	uint16_t hpllcc;
+	pci_device_cfg_read_u16 (bridge, &hpllcc, I855_HPLLCC);
+#else
 	PCITAG bridge = pciTag(0, 0, 0); /* This is always the host bridge */
 	CARD16 hpllcc = pciReadWord(bridge, I855_HPLLCC);
+#endif
 
 	/* Assume that the hardware is in the high speed state.  This
 	 * should be the default.
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index 18e5c2b..0b6b192 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -84,7 +84,11 @@ i830_lvds_set_backlight(xf86OutputPtr ou
     CARD32 blc_pwm_ctl;
 
     if (i830_lvds_backlight_legacy(pI830))
+#if XSERVER_LIBPCIACCESS
+	pci_device_cfg_write_u8 (pI830->PciInfo, 0xfe, LEGACY_BACKLIGHT_BRIGHTNESS);
+#else
 	pciWriteByte(pI830->PciTag, LEGACY_BACKLIGHT_BRIGHTNESS, 0xfe);
+#endif
 
     blc_pwm_ctl = INREG(BLC_PWM_CTL);
     blc_pwm_ctl &= ~BACKLIGHT_DUTY_CYCLE_MASK;
diff --git a/src/i830_quirks.c b/src/i830_quirks.c
index fb10570..28b8ff9 100644
--- a/src/i830_quirks.c
+++ b/src/i830_quirks.c
@@ -84,9 +84,9 @@ void i830_fixup_devices(ScrnInfoPtr scrn
     i830_quirk_ptr p = i830_quirk_list;
 
     while (p && p->chipType != 0) {
-	if (pI830->PciInfo->chipType == p->chipType &&
-		pI830->PciInfo->subsysVendor == p->subsysVendor &&
-		(pI830->PciInfo->subsysCard == p->subsysCard ||
+	if (DEVICE_ID(pI830->PciInfo) == p->chipType &&
+		SUBVENDOR_ID(pI830->PciInfo) == p->subsysVendor &&
+		(SUBSYS_ID(pI830->PciInfo) == p->subsysCard ||
 		 p->subsysCard == SUBSYS_ANY))
 	    p->hook(pI830);
 	++p;
diff --git a/src/i830_tv.c b/src/i830_tv.c
index a77bf98..c90d41e 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -1138,7 +1138,7 @@ i830_tv_mode_set(xf86OutputPtr output, D
 	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)
+    if (DEVICE_ID(pI830->PciInfo) < PCI_CHIP_I945_G)
 	tv_ctl |= TV_ENC_C0_FIX | TV_ENC_SDP_FIX;
 
     OUTREG(TV_H_CTL_1, hctl1);
diff-tree 70e8e5957200401474967a467663ae049e9080f2 (from 5516cc781bd488c936af225123812a61ed5874b8)
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Sun Aug 26 22:40:25 2007 -0700

    Change DRI interface to fill in PCI data from new libpciaccess structure.
    
    The DRI interface requires bus identification for each DRI object; pull that
    data from the libpciaccess structures as necessary.

diff --git a/src/i810_dri.c b/src/i810_dri.c
index 72718d3..e5e1565 100644
--- a/src/i810_dri.c
+++ b/src/i810_dri.c
@@ -354,9 +354,15 @@ I810DRIScreenInit(ScreenPtr pScreen)
    } else {
       pDRIInfo->busIdString = xalloc(64);
       sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d",
+#if XSERVER_LIBPCIACCESS
+	      ((pI810->PciInfo->domain << 8) | pI810->PciInfo->bus),
+	      pI810->PciInfo->dev, pI810->PciInfo->func
+#else
 	      ((pciConfigPtr) pI810->PciInfo->thisCard)->busnum,
 	      ((pciConfigPtr) pI810->PciInfo->thisCard)->devnum,
-	      ((pciConfigPtr) pI810->PciInfo->thisCard)->funcnum);
+	      ((pciConfigPtr) pI810->PciInfo->thisCard)->funcnum
+#endif
+	      );
    }
    pDRIInfo->ddxDriverMajorVersion = I810_MAJOR_VERSION;
    pDRIInfo->ddxDriverMinorVersion = I810_MINOR_VERSION;
@@ -972,12 +978,20 @@ I810DRIScreenInit(ScreenPtr pScreen)
 
    if (!pI810DRI->irq) {
       pI810DRI->irq = drmGetInterruptFromBusID(pI810->drmSubFD,
+#if XSERVER_LIBPCIACCESS
+					       ((pI810->PciInfo->domain << 8) |
+						pI810->PciInfo->bus),
+					       pI810->PciInfo->dev,
+					       pI810->PciInfo->func
+#else
 					       ((pciConfigPtr) pI810->
 						PciInfo->thisCard)->busnum,
 					       ((pciConfigPtr) pI810->
 						PciInfo->thisCard)->devnum,
 					       ((pciConfigPtr) pI810->
-						PciInfo->thisCard)->funcnum);
+						PciInfo->thisCard)->funcnum
+#endif
+					       );
       if ((drmCtlInstHandler(pI810->drmSubFD, pI810DRI->irq)) != 0) {
 	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		    "[drm] failure adding irq handler, there is a device "
@@ -991,7 +1005,7 @@ I810DRIScreenInit(ScreenPtr pScreen)
    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 	      "[drm] dma control initialized, using IRQ %d\n", pI810DRI->irq);
 
-   pI810DRI->deviceID = pI810->PciInfo->chipType;
+   pI810DRI->deviceID = DEVICE_ID(pI810->PciInfo);
    pI810DRI->width = pScrn->virtualX;
    pI810DRI->height = pScrn->virtualY;
    pI810DRI->mem = pScrn->videoRam * 1024;
diff --git a/src/i830_dri.c b/src/i830_dri.c
index e2b42b4..32f6510 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -539,9 +539,15 @@ I830DRIScreenInit(ScreenPtr pScreen)
    } else {
       pDRIInfo->busIdString = xalloc(64);
       sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d",
+#if XSERVER_LIBPCIACCESS
+	      ((pI830->PciInfo->domain << 8) | pI830->PciInfo->bus),
+	      pI830->PciInfo->dev, pI830->PciInfo->func
+#else
 	      ((pciConfigPtr) pI830->PciInfo->thisCard)->busnum,
 	      ((pciConfigPtr) pI830->PciInfo->thisCard)->devnum,
-	      ((pciConfigPtr) pI830->PciInfo->thisCard)->funcnum);
+	      ((pciConfigPtr) pI830->PciInfo->thisCard)->funcnum
+#endif
+	      );
    }
    pDRIInfo->ddxDriverMajorVersion = I830_MAJOR_VERSION;
    pDRIInfo->ddxDriverMinorVersion = I830_MINOR_VERSION;
@@ -978,13 +984,13 @@ I830DRIDoMappings(ScreenPtr pScreen)
       return FALSE;
    }
 
-   if (pI830->PciInfo->chipType != PCI_CHIP_845_G &&
-       pI830->PciInfo->chipType != PCI_CHIP_I830_M) {
+   if (DEVICE_ID(pI830->PciInfo) != PCI_CHIP_845_G &&
+       DEVICE_ID(pI830->PciInfo) != PCI_CHIP_I830_M) {
       I830SetParam(pScrn, I830_SETPARAM_USE_MI_BATCHBUFFER_START, 1 );
    }
 
    pI830DRI = (I830DRIPtr) pI830->pDRIInfo->devPrivate;
-   pI830DRI->deviceID = pI830->PciInfo->chipType;
+   pI830DRI->deviceID = DEVICE_ID(pI830->PciInfo);
    pI830DRI->width = pScrn->virtualX;
    pI830DRI->height = pScrn->virtualY;
    pI830DRI->mem = pScrn->videoRam * 1024;
@@ -1020,12 +1026,20 @@ I830DRIResume(ScreenPtr pScreen)
 
    {
       pI830DRI->irq = drmGetInterruptFromBusID(pI830->drmSubFD,
+#if XSERVER_LIBPCIACCESS
+					       ((pI830->PciInfo->domain << 8) |
+						pI830->PciInfo->bus),
+					       pI830->PciInfo->dev,
+					       pI830->PciInfo->func
+#else
 					       ((pciConfigPtr) pI830->
 						PciInfo->thisCard)->busnum,
 					       ((pciConfigPtr) pI830->
 						PciInfo->thisCard)->devnum,
 					       ((pciConfigPtr) pI830->
-						PciInfo->thisCard)->funcnum);
+						PciInfo->thisCard)->funcnum
+#endif
+					       );
 
       if (drmCtlInstHandler(pI830->drmSubFD, pI830DRI->irq)) {
 	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
@@ -1108,12 +1122,20 @@ I830DRIFinishScreenInit(ScreenPtr pScree
       I830DRIPtr pI830DRI = (I830DRIPtr) pI830->pDRIInfo->devPrivate;
 
       pI830DRI->irq = drmGetInterruptFromBusID(pI830->drmSubFD,
+#if XSERVER_LIBPCIACCESS
+					       ((pI830->PciInfo->domain << 8) |
+						pI830->PciInfo->bus),
+					       pI830->PciInfo->dev,
+					       pI830->PciInfo->func
+#else
 					       ((pciConfigPtr) pI830->
 						PciInfo->thisCard)->busnum,
 					       ((pciConfigPtr) pI830->
 						PciInfo->thisCard)->devnum,
 					       ((pciConfigPtr) pI830->
-						PciInfo->thisCard)->funcnum);
+						PciInfo->thisCard)->funcnum
+#endif
+					       );
 
       if (drmCtlInstHandler(pI830->drmSubFD, pI830DRI->irq)) {
 	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
diff-tree 5516cc781bd488c936af225123812a61ed5874b8 (from daada59b5f8c2294b524a4b5920dc6b1c213642f)
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Sun Aug 26 22:37:38 2007 -0700

    Add libpciaccess declarations to I810Rec and I830Rec.
    
    Using libpciaccess requires a different type for PciInfo (struct pci_device
    instead of pciVideoPtr) and it requires knowing which BAR each memory region
    needs to be mapped from. Add these definitions to the driver private record
    along with the includes necessary to use libpciaccess.

diff --git a/src/i810.h b/src/i810.h
index ff9134e..2031408 100644
--- a/src/i810.h
+++ b/src/i810.h
@@ -50,6 +50,11 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "vbe.h"
 #include "vgaHW.h"
 
+#include "xorg-server.h"
+#ifdef XSERVER_LIBPCIACCESS
+#include <pciaccess.h>
+#endif
+
 #ifdef XF86DRI
 #include "xf86drm.h"
 #include "sarea.h"
@@ -184,8 +189,14 @@ typedef struct _I810Rec {
    unsigned long MMIOAddr;
    IOADDRESS ioBase;
    EntityInfoPtr pEnt;
+#if XSERVER_LIBPCIACCESS
+   int mmio_bar;
+   int fb_bar;
+   struct pci_device *PciInfo;
+#else
    pciVideoPtr PciInfo;
    PCITAG PciTag;
+#endif
 
    I810RingBuffer *LpRing;
    unsigned int BR[20];
diff --git a/src/i830.h b/src/i830.h
index b0c8f0f..4f176f8 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -61,6 +61,11 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "xf86Crtc.h"
 #include "xf86RandR12.h"
 
+#include "xorg-server.h"
+#ifdef XSERVER_LIBPCIACCESS
+#include <pciaccess.h>
+#endif
+
 #ifdef XF86DRI
 #include "xf86drm.h"
 #include "sarea.h"
@@ -360,8 +365,15 @@ typedef struct _I830Rec {
    unsigned long MMIOAddr;
    IOADDRESS ioBase;
    EntityInfoPtr pEnt;
+#if XSERVER_LIBPCIACCESS
+   struct pci_device *PciInfo;
+   int mmio_bar;
+   int fb_bar;
+   int gtt_bar;
+#else
    pciVideoPtr PciInfo;
    PCITAG PciTag;
+#endif
    CARD8 variant;
 
    unsigned int BR[20];
diff-tree daada59b5f8c2294b524a4b5920dc6b1c213642f (from 3d3bf493a3973f4067433d27a4d7ddfecaa18f1c)
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Sun Aug 26 22:32:39 2007 -0700

    Change IS_Ixxx tests to work with or without libpciaccess.
    
    libpciaccess has a new structure that holds the PCI identifier data; borrow
    macros from the mga driver to work with either the old xf86-specific
    structure or the new libpciaccess structure.

diff --git a/src/common.h b/src/common.h
index fa96a5d..cfe00fc 100644
--- a/src/common.h
+++ b/src/common.h
@@ -384,26 +384,42 @@ extern int I810_DEBUG;
 #define PCI_CHIP_Q33_G_BRIDGE 	0x29D0
 #endif
 
-#define IS_I810(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I810 ||	\
-			pI810->PciInfo->chipType == PCI_CHIP_I810_DC100 || \
-			pI810->PciInfo->chipType == PCI_CHIP_I810_E)
-#define IS_I815(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I815)
-#define IS_I830(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I830_M)
-#define IS_845G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_845_G)
-#define IS_I85X(pI810)  (pI810->PciInfo->chipType == PCI_CHIP_I855_GM)
-#define IS_I852(pI810)  (pI810->PciInfo->chipType == PCI_CHIP_I855_GM && (pI810->variant == I852_GM || pI810->variant == I852_GME))
-#define IS_I855(pI810)  (pI810->PciInfo->chipType == PCI_CHIP_I855_GM && (pI810->variant == I855_GM || pI810->variant == I855_GME))
-#define IS_I865G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I865_G)
-
-#define IS_I915G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I915_G || pI810->PciInfo->chipType == PCI_CHIP_E7221_G)
-#define IS_I915GM(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I915_GM)
-#define IS_I945G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I945_G)
-#define IS_I945GM(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I945_GM || pI810->PciInfo->chipType == PCI_CHIP_I945_GME)
-#define IS_I965GM(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I965_GM || pI810->PciInfo->chipType == PCI_CHIP_I965_GME)
-#define IS_I965G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I965_G || pI810->PciInfo->chipType == PCI_CHIP_I965_G_1 || pI810->PciInfo->chipType == PCI_CHIP_I965_Q || pI810->PciInfo->chipType == PCI_CHIP_I946_GZ || pI810->PciInfo->chipType == PCI_CHIP_I965_GM || pI810->PciInfo->chipType == PCI_CHIP_I965_GME)
-#define IS_G33CLASS(pI810) (pI810->PciInfo->chipType == PCI_CHIP_G33_G ||\
- 			    pI810->PciInfo->chipType == PCI_CHIP_Q35_G ||\
- 			    pI810->PciInfo->chipType == PCI_CHIP_Q33_G)
+#if XSERVER_LIBPCIACCESS
+#define I810_MEMBASE(p,n) (p)->regions[(n)].base_addr
+#define VENDOR_ID(p)      (p)->vendor_id
+#define DEVICE_ID(p)      (p)->device_id
+#define SUBVENDOR_ID(p)	  (p)->subvendor_id
+#define SUBSYS_ID(p)      (p)->subdevice_id
+#define CHIP_REVISION(p)  (p)->revision
+#else
+#define I810_MEMBASE(p,n) (p)->memBase[n]
+#define VENDOR_ID(p)      (p)->vendor
+#define DEVICE_ID(p)      (p)->chipType
+#define SUBVENDOR_ID(p)	  (p)->subsysVendor
+#define SUBSYS_ID(p)      (p)->subsysCard
+#define CHIP_REVISION(p)  (p)->chipRev
+#endif
+
+#define IS_I810(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I810 ||	\
+			DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I810_DC100 || \
+			DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I810_E)
+#define IS_I815(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I815)
+#define IS_I830(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I830_M)
+#define IS_845G(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_845_G)
+#define IS_I85X(pI810)  (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I855_GM)
+#define IS_I852(pI810)  (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I855_GM && (pI810->variant == I852_GM || pI810->variant == I852_GME))
+#define IS_I855(pI810)  (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I855_GM && (pI810->variant == I855_GM || pI810->variant == I855_GME))
+#define IS_I865G(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I865_G)
+
+#define IS_I915G(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I915_G || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_E7221_G)
+#define IS_I915GM(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I915_GM)
+#define IS_I945G(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I945_G)
+#define IS_I945GM(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I945_GM || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I945_GME)
+#define IS_I965GM(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I965_GM || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I965_GME)
+#define IS_I965G(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I965_G || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I965_G_1 || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I965_Q || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I946_GZ || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I965_GM || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I965_GME)
+#define IS_G33CLASS(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_G33_G ||\
+ 			    DEVICE_ID(pI810->PciInfo) == PCI_CHIP_Q35_G ||\
+ 			    DEVICE_ID(pI810->PciInfo) == PCI_CHIP_Q33_G)
 #define IS_I9XX(pI810) (IS_I915G(pI810) || IS_I915GM(pI810) || IS_I945G(pI810) || IS_I945GM(pI810) || IS_I965G(pI810) || IS_G33CLASS(pI810))
 
 #define IS_MOBILE(pI810) (IS_I830(pI810) || IS_I85X(pI810) || IS_I915GM(pI810) || IS_I945GM(pI810) || IS_I965GM(pI810))
@@ -428,4 +444,7 @@ extern int I810_DEBUG;
 
 #define PIPE_NAME(n)			('A' + (n))
 
+struct pci_device *
+intel_host_bridge (void);
+   
 #endif /* _INTEL_COMMON_H_ */
diff-tree 3d3bf493a3973f4067433d27a4d7ddfecaa18f1c (from 5faf9cc6afe1c30fa88bc6446088a6fa47fc5d0b)
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Sun Aug 26 22:27:34 2007 -0700

    Intel driver configuration (only) changes for X server libpciaccess usage.
    
    Detect whether the target X server uses libpciaccess, using it in the driver
    compilation as necessary. This change means that utilities that used to use
    libpciaccess will not do so unless the driver itself uses libpciaccess. Yes,
    that could be fixed, but it doesn't seem that important.
    
    This patch does not include any code changes necessary to actually have the
    driver build against an X server using libpciaccess.

diff --git a/configure.ac b/configure.ac
index 8c2b5ec..1c7ad04 100644
--- a/configure.ac
+++ b/configure.ac
@@ -78,9 +78,6 @@ 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.
@@ -112,8 +109,16 @@ AC_MSG_RESULT([$DRI])
 save_CFLAGS="$CFLAGS"
 CFLAGS="$XORG_CFLAGS"
 AC_CHECK_HEADER(xf86Modes.h,[XMODES=yes],[XMODES=no],[#include "xorg-server.h"])
+AC_CHECK_DECL(XSERVER_LIBPCIACCESS,
+	      [XSERVER_LIBPCIACCESS=yes],[XSERVER_LIBPCIACCESS=no],
+	      [#include "xorg-server.h"])
 CFLAGS="$save_CFLAGS"
 
+if test x$XSERVER_LIBPCIACCESS = xyes; then
+	PKG_CHECK_MODULES([PCIACCESS], [pciaccess >= 0.8.0])
+fi
+
+AM_CONDITIONAL(XSERVER_LIBPCIACCESS, test "x$XSERVER_LIBPCIACCESS" = xyes)
 AM_CONDITIONAL(XMODES, test "x$XMODES" = xno)
 
 if test "x$XSERVER_SOURCE" = x; then
diff --git a/src/Makefile.am b/src/Makefile.am
index 50e913e..13cbf91 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.
 
-if HAVE_PCIACCESS
+if XSERVER_LIBPCIACCESS
 REGDUMPER = reg_dumper
 endif
 
diff --git a/src/bios_reader/Makefile.am b/src/bios_reader/Makefile.am
index 8e03693..a4adecb 100644
--- a/src/bios_reader/Makefile.am
+++ b/src/bios_reader/Makefile.am
@@ -2,7 +2,7 @@ AM_CFLAGS = @WARN_CFLAGS@ @XORG_CFLAGS@ 
 
 noinst_PROGRAMS = bios_reader  $(BIOS_DUMPER)
 
-if HAVE_PCIACCESS
+if XSERVER_LIBPCIACCESS
 BIOS_DUMPER = bios_dumper
 
 bios_dumper_SOURCES = bios_dumper.c
diff-tree 5faf9cc6afe1c30fa88bc6446088a6fa47fc5d0b (from a9e1d42a47cef79d8bbde2afd89d26aed964e344)
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Sun Aug 26 09:34:06 2007 -0700

    Sort quirk table, add Dell Latitude X1

diff --git a/src/i830_quirks.c b/src/i830_quirks.c
index 89fb11e..fb10570 100644
--- a/src/i830_quirks.c
+++ b/src/i830_quirks.c
@@ -54,19 +54,27 @@ static void quirk_mac_mini (I830Ptr pI83
     pI830->quirk_flag |= QUIRK_IGNORE_MACMINI_LVDS;
 }
 
+/* keep this list sorted by OEM, then by chip ID */
 static i830_quirk i830_quirk_list[] = {
-    /* Lenovo T61 has no TV output */
-    { PCI_CHIP_I965_GM, 0x17aa, 0x20b5, quirk_ignore_tv },
+    /* Aopen mini pc */
+    { PCI_CHIP_I945_GM, 0xa0a0, SUBSYS_ANY, quirk_ignore_lvds },
+    
+    /* Apple Mac mini has no lvds, but macbook pro does */
+    { PCI_CHIP_I945_GM, 0x8086, 0x7270, quirk_mac_mini },
+    
+    /* Dell Latitude X1 */
+    { PCI_CHIP_I945_GM, 0x1028, 0x01a3, quirk_ignore_tv },
+    
     /* Lenovo X60s has no TV output */
     { PCI_CHIP_I945_GM, 0x17aa, 0x201a, quirk_ignore_tv },
-    /* Panasonic Toughbook CF-Y4 has no TV output */
-    { PCI_CHIP_I915_GM, 0x10f7, 0x8338, quirk_ignore_tv },
+    /* Lenovo T61 has no TV output */
+    { PCI_CHIP_I965_GM, 0x17aa, 0x20b5, quirk_ignore_tv },
     /* Lenovo 3000 v200 */
     { PCI_CHIP_I965_GM, 0x17aa, 0x3c18, quirk_ignore_tv },
-    /* Aopen mini pc */
-    { PCI_CHIP_I945_GM, 0xa0a0, SUBSYS_ANY, quirk_ignore_lvds },
-    /* Mac mini has no lvds, but macbook pro does */
-    { PCI_CHIP_I945_GM, 0x8086, 0x7270, quirk_mac_mini },
+    
+    /* Panasonic Toughbook CF-Y4 has no TV output */
+    { PCI_CHIP_I915_GM, 0x10f7, 0x8338, quirk_ignore_tv },
+    
     { 0, 0, 0, NULL },
 };
 
diff-tree a9e1d42a47cef79d8bbde2afd89d26aed964e344 (from ffc2907f7f2eb039004eff0014c5563a01463fb0)
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Sat Aug 25 12:54:11 2007 -0700

    Lenovo 201a is x60s, not x61s

diff --git a/src/i830_quirks.c b/src/i830_quirks.c
index 3176cd4..89fb11e 100644
--- a/src/i830_quirks.c
+++ b/src/i830_quirks.c
@@ -57,8 +57,8 @@ static void quirk_mac_mini (I830Ptr pI83
 static i830_quirk i830_quirk_list[] = {
     /* Lenovo T61 has no TV output */
     { PCI_CHIP_I965_GM, 0x17aa, 0x20b5, quirk_ignore_tv },
-    /* Lenovo X61s has no TV output */
-    { PCI_CHIP_I965_GM, 0x17aa, 0x201a, quirk_ignore_tv },
+    /* Lenovo X60s has no TV output */
+    { PCI_CHIP_I945_GM, 0x17aa, 0x201a, quirk_ignore_tv },
     /* Panasonic Toughbook CF-Y4 has no TV output */
     { PCI_CHIP_I915_GM, 0x10f7, 0x8338, quirk_ignore_tv },
     /* Lenovo 3000 v200 */
diff-tree ffc2907f7f2eb039004eff0014c5563a01463fb0 (from 0c20fbabd18c19b2753cb60280f89e240ce5645f)
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Sat Aug 25 12:31:21 2007 -0700

    Thinkpad X61s has no TV out

diff --git a/src/i830_quirks.c b/src/i830_quirks.c
index b75baef..3176cd4 100644
--- a/src/i830_quirks.c
+++ b/src/i830_quirks.c
@@ -57,6 +57,8 @@ static void quirk_mac_mini (I830Ptr pI83
 static i830_quirk i830_quirk_list[] = {
     /* Lenovo T61 has no TV output */
     { PCI_CHIP_I965_GM, 0x17aa, 0x20b5, quirk_ignore_tv },
+    /* Lenovo X61s has no TV output */
+    { PCI_CHIP_I965_GM, 0x17aa, 0x201a, quirk_ignore_tv },
     /* Panasonic Toughbook CF-Y4 has no TV output */
     { PCI_CHIP_I915_GM, 0x10f7, 0x8338, quirk_ignore_tv },
     /* Lenovo 3000 v200 */
diff-tree 0c20fbabd18c19b2753cb60280f89e240ce5645f (from e443f83dd6f110156743c93f7d793cdddb8195a1)
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Fri Aug 17 22:21:47 2007 -0700

    Make sure XV_PIPE is used whenever possible.
    
    The code was not consistently using XV_PIPE when the desired crtc contained
    any portion of the video output.

diff --git a/src/i830_video.c b/src/i830_video.c
index 926e122..2128eb8 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -1712,11 +1712,14 @@ i830_covering_crtc (ScrnInfoPtr pScrn,
 	i830_crtc_box (crtc, &crtc_box);
 	i830_box_intersect (&cover_box, &crtc_box, box);
 	coverage = i830_box_area (&cover_box);
+	if (coverage && crtc == desired)
+	{
+	    *crtc_box_ret = crtc_box;
+	    return crtc;
+	}
 	if (coverage > best_coverage)
 	{
 	    *crtc_box_ret = crtc_box;
-	    if (crtc == desired)
-		return crtc;
 	    best_crtc = crtc;
 	    best_coverage = coverage;
 	}
diff-tree e443f83dd6f110156743c93f7d793cdddb8195a1 (from bd874b11bbfe582aebd3115771f90807e75afc31)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Aug 17 18:13:49 2007 -0700

    Tune acceleration architecture allocator sizes down.

diff --git a/src/i830_memory.c b/src/i830_memory.c
index 99315db..3da489d 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -849,7 +849,6 @@ i830_allocate_framebuffer(ScrnInfoPtr pS
 	    int size;
 
 	    size = 3 * pitch * pScrn->virtualY;
-	    size += 1920 * 1088 * 2 * 2;
 	    size = ROUND_TO_PAGE(size);
 
 	    cacheLines = (size + pitch - 1) / pitch;
@@ -1140,14 +1139,13 @@ i830_allocate_2d_memory(ScrnInfoPtr pScr
     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.
+	     * (for pixmaps).
 	     *
 	     * 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 * pitch * pScrn->virtualY;
-	    size += 1920 * 1088 * 2 * 2;
 	    size = ROUND_TO_PAGE(size);
 
 	    pI830->exa_offscreen = i830_allocate_memory(pScrn, "exa offscreen",
diff-tree bd874b11bbfe582aebd3115771f90807e75afc31 (from 9ad33dd65a79277ef75a6e95373614852725f5a9)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Aug 17 17:49:21 2007 -0700

    Replace AA allocator usage with i830_memory.c for RandR rotation.
    
    This requires EXA 2.2 (server 1.3) for rotated performance with EXA, because
    the i830_memory.c allocation may not fall within what EXA considers the
    offscreen area, so the PixmapIsOffscreen hook is needed.

diff --git a/src/i830.h b/src/i830.h
index 6888a9b..b0c8f0f 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -234,12 +234,7 @@ typedef struct _I830CrtcPrivateRec {
     /* Lookup table values to be set when the CRTC is enabled */
     CARD8 lut_r[256], lut_g[256], lut_b[256];
 
-#ifdef I830_USE_XAA
-    FBLinearPtr rotate_mem_xaa;
-#endif
-#ifdef I830_USE_EXA
-    ExaOffscreenArea *rotate_mem_exa;
-#endif
+    i830_memory *rotate_mem;
     /* Card virtual address of the cursor */
     unsigned long cursor_offset;
     unsigned long cursor_argb_offset;
@@ -689,14 +684,6 @@ Bool i830_unbind_all_memory(ScrnInfoPtr 
 
 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 a076446..0ab0de7 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -1291,59 +1291,24 @@ 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;
-    unsigned long rotate_offset;
     int align = KB(4), size;
 
     rotate_pitch = pScrn->displayWidth * pI830->cpp;
     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->front_buffer->offset +
-	    intel_crtc->rotate_mem_xaa->offset * pI830->cpp;
+    assert(intel_crtc->rotate_mem == NULL);
+    intel_crtc->rotate_mem = i830_allocate_memory(pScrn, "rotated crtc",
+						  size, align, 0);
+    if (intel_crtc->rotate_mem == NULL) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "Couldn't allocate shadow memory for rotated CRTC\n");
+	return NULL;
     }
-#endif /* I830_USE_XAA */
 
-    return pI830->FbBase + rotate_offset;
+    return pI830->FbBase + intel_crtc->rotate_mem->offset;
 }
     
 /**
@@ -1380,26 +1345,16 @@ static void
 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;
 
     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;
-	}
-#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 */
+
+    if (data) {
+	/* Be sure to sync acceleration before the memory gets unbound. */
+	I830Sync(pScrn);
+	i830_free_memory(pScrn, intel_crtc->rotate_mem);
+	intel_crtc->rotate_mem = NULL;
     }
 }
 
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 81e8118..ab42fd9 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1562,7 +1562,11 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 
       memset(&req, 0, sizeof(req));
       req.majorversion = 2;
+#if EXA_VERSION_MINOR >= 2
+      req.minorversion = 2;
+#else
       req.minorversion = 1;
+#endif
       if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL, &req,
 		&errmaj, &errmin)) {
 	 LoaderErrorMsg(NULL, "exa", errmaj, errmin);
diff --git a/src/i830_exa.c b/src/i830_exa.c
index fdf94d7..fa50da0 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -124,6 +124,22 @@ i830_pixmap_tiled(PixmapPtr pPixmap)
     return FALSE;
 }
 
+Bool
+i830_exa_pixmap_is_offscreen(PixmapPtr pPixmap)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    if ((void *)pPixmap->devPrivate.ptr >= (void *)pI830->FbBase &&
+	(void *)pPixmap->devPrivate.ptr <
+	(void *)(pI830->FbBase + pI830->FbMapSize))
+    {
+	return TRUE;
+    } else {
+	return FALSE;
+    }
+}
+
 /**
  * I830EXASync - wait for a command to finish
  * @pScreen: current screen
@@ -456,7 +472,17 @@ I830EXAInit(ScreenPtr pScreen)
 
     pI830->bufferOffset = 0;
     pI830->EXADriverPtr->exa_major = 2;
+    /* If compiled against EXA 2.2, require 2.2 so we can use the
+     * PixmapIsOffscreen hook.
+     */
+#if EXA_VERSION_MINOR >= 2
+    pI830->EXADriverPtr->exa_minor = 2;
+#else
     pI830->EXADriverPtr->exa_minor = 1;
+    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+	       "EXA compatibility mode.  Output rotation rendering "
+	       "performance may suffer\n");
+#endif
     pI830->EXADriverPtr->memoryBase = pI830->FbBase;
     pI830->EXADriverPtr->offScreenBase = pI830->exa_offscreen->offset;
     pI830->EXADriverPtr->memorySize = pI830->exa_offscreen->offset +
@@ -552,6 +578,9 @@ I830EXAInit(ScreenPtr pScreen)
  	pI830->EXADriverPtr->Composite = i965_composite;
  	pI830->EXADriverPtr->DoneComposite = i830_done_composite;
     }
+#if EXA_VERSION_MINOR >= 2
+    pI830->EXADriverPtr->PixmapIsOffscreen = i830_exa_pixmap_is_offscreen;
+#endif
 
     /* UploadToScreen/DownloadFromScreen */
     if (0)
diff --git a/src/i830_memory.c b/src/i830_memory.c
index d6fa852..99315db 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -1684,41 +1684,3 @@ 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-tree 9ad33dd65a79277ef75a6e95373614852725f5a9 (from 3655a1ecb62f6c387a16fa87cf6f00bf7835dce4)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Aug 17 16:46:48 2007 -0700

    Use i830_memory.c instead of the AA's allocator for XV buffers.
    
    This should fix issues with XV being allocated into XAA's tiled pixmap
    cache and resulting bad rendering.  Its also brings us closer to being able
    to shrink the size of the pixmap cache on XAA, which is of limited utility.

diff --git a/src/i830.h b/src/i830.h
index 1cfcb9a..6888a9b 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -641,6 +641,14 @@ extern void I830SubsequentSolidFillRect(
 
 Bool i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset,
 			 unsigned long size);
+i830_memory * i830_allocate_memory(ScrnInfoPtr pScrn, const char *name,
+				   unsigned long size, unsigned long alignment,
+				   int flags);
+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);
 void i830_describe_allocations(ScrnInfoPtr pScrn, int verbosity,
 			       const char *prefix);
 void i830_reset_allocations(ScrnInfoPtr pScrn);
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 15d3a48..d6fa852 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -515,7 +515,7 @@ i830_allocate_agp_memory(ScrnInfoPtr pSc
  * The memory will be bound automatically when the driver is in control of the
  * VT.
  */
-static i830_memory *
+i830_memory *
 i830_allocate_memory(ScrnInfoPtr pScrn, const char *name,
 		     unsigned long size, unsigned long alignment, int flags)
 {
@@ -544,7 +544,7 @@ i830_allocate_memory(ScrnInfoPtr pScrn, 
  * some search across all allocation options to fix this, probably, but that
  * would be another rewrite.
  */
-static i830_memory *
+i830_memory *
 i830_allocate_memory_tiled(ScrnInfoPtr pScrn, const char *name,
 			   unsigned long size, unsigned long pitch,
 			   unsigned long alignment, int flags,
diff --git a/src/i830_video.c b/src/i830_video.c
index b4f9e74..926e122 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -107,9 +107,6 @@ static int I830QueryImageAttributesTextu
 
 static void I830BlockHandler(int, pointer, pointer, pointer);
 
-static void
-I830FreeMemory(ScrnInfoPtr pScrn, struct linear_alloc *linear);
-
 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
 
 static Atom xvBrightness, xvContrast, xvSaturation, xvColorKey, xvPipe, xvDoubleBuffer;
@@ -841,7 +838,7 @@ I830SetupImageVideoOverlay(ScreenPtr pSc
     pPriv->saturation = 128;
     pPriv->current_crtc = NULL;
     pPriv->desired_crtc = NULL;
-    memset(&pPriv->linear, 0, sizeof(pPriv->linear));
+    pPriv->buf = NULL;
     pPriv->currentBuf = 0;
     pPriv->gamma5 = 0xc0c0c0;
     pPriv->gamma4 = 0x808080;
@@ -955,7 +952,7 @@ I830SetupImageVideoTextured(ScreenPtr pS
 
 	pPriv->textured = TRUE;
 	pPriv->videoStatus = 0;
-	memset(&pPriv->linear, 0, sizeof(pPriv->linear));
+	pPriv->buf = NULL;
 	pPriv->currentBuf = 0;
 	pPriv->doubleBuffer = 0;
 
@@ -1015,7 +1012,10 @@ I830StopVideo(ScrnInfoPtr pScrn, pointer
 	    if (pI830->entityPrivate)
 		pI830->entityPrivate->XvInUse = -1;
 	}
-	I830FreeMemory(pScrn, &pPriv->linear);
+	/* Sync before freeing the buffer, because the pages will be unbound.
+	 */
+	I830Sync(pScrn);
+	i830_free_memory(pScrn, pPriv->buf);
 	pPriv->videoStatus = 0;
     } else {
 	if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
@@ -2075,112 +2075,6 @@ i830_display_video(ScrnInfoPtr pScrn, xf
     i830_overlay_continue (pScrn, scaleChanged);
 }
 
-#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 byte offset of the allocated memory from the start of framebuffer.
- */
-static void
-I830AllocateMemory(ScrnInfoPtr pScrn, struct linear_alloc *linear, int size,
-		   int align)
-{
-    ScreenPtr pScreen = pScrn->pScreen;
-    I830Ptr pI830 = I830PTR(pScrn);
-
-#ifdef I830_USE_EXA
-    if (pI830->useEXA) {
-	if (linear->exa != NULL) {
-	    if (linear->exa->size >= size)
-		return;
-
-	    exaOffscreenFree(pScreen, linear->exa);
-	    linear->offset = 0;
-	}
-
-	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) {
-	/* Converts an offset from XAA's linear allocator to an offset from the
-	 * start of fb.
-	 */
-#define XAA_OFFSET_TO_OFFSET(x) \
-	(pI830->front_buffer->offset + (x * pI830->cpp))
-
-	/* 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;
-
-	if (linear->xaa != NULL) {
-	    if (linear->xaa->size >= size) {
-		linear->offset = XAA_OFFSET_TO_OFFSET(linear->xaa->offset);
-		return;
-	    }
-
-	    if (xf86ResizeOffscreenLinear(linear->xaa, size)) {
-		linear->offset = XAA_OFFSET_TO_OFFSET(linear->xaa->offset);
-		return;
-	    }
-
-	    xf86FreeOffscreenLinear(linear->xaa);
-	}
-
-	linear->xaa = i830_xf86AllocateOffscreenLinear(pScreen, size, align,
-						       NULL, NULL, NULL);
-	if (linear->xaa == NULL)
-	    return;
-
-	linear->offset = XAA_OFFSET_TO_OFFSET(linear->xaa->offset);
-    }
-#endif /* I830_USE_XAA */
-}
-
-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;
-}
-
 static Bool
 i830_clip_video_helper (ScrnInfoPtr pScrn,
 			xf86CrtcPtr *crtc_ret,
@@ -2293,7 +2187,7 @@ I830PutImage(ScrnInfoPtr pScrn,
     int top, left, npixels, nlines, size;
     BoxRec dstBox;
     int pitchAlignMask;
-    int extraLinear;
+    int alloc_size, extraLinear;
     xf86CrtcPtr	crtc;
 
     if (pPriv->textured)
@@ -2410,19 +2304,38 @@ I830PutImage(ScrnInfoPtr pScrn,
     else
 	extraLinear = 0;
 
-    /* size is multiplied by 2 because we have two buffers that are flipping */
-    I830AllocateMemory(pScrn, &pPriv->linear,
-		       extraLinear + (pPriv->doubleBuffer ? size * 2 : size),
-		       16);
+    alloc_size = size;
+    if (pPriv->doubleBuffer)
+	alloc_size *= 2;
+    alloc_size += extraLinear;
+
+    if (pPriv->buf) {
+	/* Wait for any previous acceleration to the buffer to have completed.
+	 * When we start using BOs for rendering, we won't have to worry
+	 * because mapping or freeing will take care of it automatically.
+	 */
+	I830Sync(pScrn);
+    }
+
+    /* Free the current buffer if we're going to have to reallocate */
+    if (pPriv->buf && pPriv->buf->size < alloc_size) {
+	i830_free_memory(pScrn, pPriv->buf);
+	pPriv->buf = NULL;
+    }
 
-    if (pPriv->linear.offset == 0)
+    if (pPriv->buf == NULL) {
+	pPriv->buf = i830_allocate_memory(pScrn, "xv buffer", alloc_size, 16,
+					  0);
+    }
+
+    if (pPriv->buf == NULL)
 	return BadAlloc;
 
-    pPriv->extra_offset = pPriv->linear.offset +
+    pPriv->extra_offset = pPriv->buf->offset +
     (pPriv->doubleBuffer ? size * 2 : size);
 
     /* fixup pointers */
-    pPriv->YBuf0offset = pPriv->linear.offset;
+    pPriv->YBuf0offset = pPriv->buf->offset;
     if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
 	pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * width);
 	pPriv->VBuf0offset = pPriv->UBuf0offset + (dstPitch * width / 2);
@@ -2654,7 +2567,11 @@ I830BlockHandler(int i,
 	    }
 	} else {				/* FREE_TIMER */
 	    if (pPriv->freeTime < now) {
-		I830FreeMemory(pScrn, &pPriv->linear);
+		/* Sync before freeing the buffer, because the pages will be
+		 * unbound.
+		 */
+		I830Sync(pScrn);
+		i830_free_memory(pScrn, pPriv->buf);
 		pPriv->videoStatus = 0;
 	    }
 	}
@@ -2666,7 +2583,7 @@ I830BlockHandler(int i,
  ***************************************************************************/
 
 typedef struct {
-    struct linear_alloc linear;
+    i830_memory *buf;
     Bool isOn;
 } OffscreenPrivRec, *OffscreenPrivPtr;
 
@@ -2711,8 +2628,8 @@ I830AllocateSurface(ScrnInfoPtr pScrn,
     fbpitch = pI830->cpp * pScrn->displayWidth;
     size = pitch * h;
 
-    I830AllocateMemory(pScrn, &pPriv->linear, size, 16);
-    if (pPriv->linear.offset == 0) {
+    pPriv->buf = i830_allocate_memory(pScrn, "xv surface buffer", size, 16, 0);
+    if (pPriv->buf == NULL) {
 	xfree(surface->pitches);
 	xfree(surface->offsets);
 	xfree(pPriv);
@@ -2727,7 +2644,7 @@ I830AllocateSurface(ScrnInfoPtr pScrn,
     surface->pScrn = pScrn;
     surface->id = id;
     surface->pitches[0] = pitch;
-    surface->offsets[0] = pPriv->linear.offset;
+    surface->offsets[0] = pPriv->buf->offset;
     surface->devPrivate.ptr = (pointer) pPriv;
 
     memset(pI830->FbBase + surface->offsets[0], 0, size);
@@ -2760,10 +2677,13 @@ I830StopSurface(XF86SurfacePtr surface)
 static int
 I830FreeSurface(XF86SurfacePtr surface)
 {
+    ScrnInfoPtr pScrn = surface->pScrn;
     OffscreenPrivPtr pPriv = (OffscreenPrivPtr) surface->devPrivate.ptr;
 
     I830StopSurface(surface);
-    I830FreeMemory(surface->pScrn, &pPriv->linear);
+    /* Sync before freeing the buffer, because the pages will be unbound. */
+    I830Sync(pScrn);
+    i830_free_memory(surface->pScrn, pPriv->buf);
     xfree(surface->pitches);
     xfree(surface->offsets);
     xfree(surface->devPrivate.ptr);
diff --git a/src/i830_video.h b/src/i830_video.h
index 7e2d149..23954e1 100644
--- a/src/i830_video.h
+++ b/src/i830_video.h
@@ -27,18 +27,6 @@ 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;
@@ -70,7 +58,7 @@ typedef struct {
    CARD32 videoStatus;
    Time offTime;
    Time freeTime;
-   struct linear_alloc linear;
+   i830_memory *buf; /** YUV data buffer */
    unsigned int extra_offset;
 
    Bool overlayOK;
diff-tree 3655a1ecb62f6c387a16fa87cf6f00bf7835dce4 (from parents)
Merge: e5c336eaa32be8f9379a2c1dd51006b85bc8b270 2231cdcd8f1ee81b3e59cc5e3a325c22ee0f40e4
Author: Jesse Barnes <jbarnes at nietzche.virtuousgeek.org>
Date:   Thu Aug 16 12:04:20 2007 -0700

    Merge branch 'master' of ssh://git.freedesktop.org/git/xorg/driver/xf86-video-intel

diff-tree e5c336eaa32be8f9379a2c1dd51006b85bc8b270 (from 5126a71f82767b9e23cd590453718f3364789740)
Author: Jesse Barnes <jbarnes at nietzche.virtuousgeek.org>
Date:   Thu Aug 16 12:04:02 2007 -0700

    Disambiguate plane and pipe mapping, use plane A on pipe B on pre-965 LVDS
    
    Add a new 'plane' field to the intel_crtc private structure for tracking
    planes separate from pipes.  This allows pre-965 chips to use plane A
    on pipe B, enabling framebuffer compression for builtin LVDS displays.

diff --git a/src/i830.h b/src/i830.h
index ca48b52..1cfcb9a 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -225,6 +225,7 @@ extern const char *i830_output_type_name
 
 typedef struct _I830CrtcPrivateRec {
     int			    pipe;
+    int			    plane;
 
     Bool    		    enabled;
     
diff --git a/src/i830_display.c b/src/i830_display.c
index 706b9ba..a076446 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -372,10 +372,11 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x,
     I830Ptr pI830 = I830PTR(pScrn);
     I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
     int pipe = intel_crtc->pipe;
+    int plane = intel_crtc->plane;
     unsigned long Start, Offset;
-    int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE);
-    int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
-    int dsptileoff = (pipe == 0 ? DSPATILEOFF : DSPBTILEOFF);
+    int dspbase = (plane == 0 ? DSPABASE : DSPBBASE);
+    int dspsurf = (plane == 0 ? DSPASURF : DSPBSURF);
+    int dsptileoff = (plane == 0 ? DSPATILEOFF : DSPBTILEOFF);
 
     Offset = ((y * pScrn->displayWidth + x) * pI830->cpp);
     if (pI830->front_buffer == NULL) {
@@ -523,8 +524,7 @@ i830_use_fb_compression(xf86CrtcPtr crtc
     ScrnInfoPtr pScrn = crtc->scrn;
     I830Ptr pI830 = I830PTR(pScrn);
     I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
-    int pipe = intel_crtc->pipe;
-    int plane = (pipe == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB);
+    int plane = (intel_crtc->plane == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB);
 
     if (!pI830->fb_compression)
 	return FALSE;
@@ -569,17 +569,15 @@ i830_enable_fb_compression(xf86CrtcPtr c
     I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
     uint32_t fbc_ctl = 0;
     unsigned long compressed_stride;
-    int pipe = intel_crtc->pipe;
-    /* FIXME: plane & pipe might not always be equal */
-    int plane = (pipe == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB);
+    int plane = (intel_crtc->plane == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB);
     unsigned long uncompressed_stride = pScrn->displayWidth * pI830->cpp;
     unsigned long interval = 1000;
 
     if (INREG(FBC_CONTROL) & FBC_CTL_EN) {
-	char cur_pipe = (INREG(FBC_CONTROL2) & 1) ? 'b' : 'a';
+	char cur_plane = (INREG(FBC_CONTROL2) & 1) ? 'b' : 'a';
 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "fbc already enabled on "
-		   "pipe %c, not enabling on pipe %c\n", cur_pipe, pipe ? 'b' :
-		   'a');
+		   "plane %c, not enabling on plane %c\n", cur_plane,
+		   plane ? 'b' : 'a');
 	return;
     }
 
@@ -615,7 +613,7 @@ i830_enable_fb_compression(xf86CrtcPtr c
     fbc_ctl |= FBC_CTL_UNCOMPRESSIBLE;
     OUTREG(FBC_CONTROL, fbc_ctl);
 
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "fbc enabled on plane %c\n", pipe ?
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "fbc enabled on plane %c\n", plane ?
 	       'b' : 'a');
 }
 
@@ -625,7 +623,7 @@ i830_disable_fb_compression(xf86CrtcPtr 
     ScrnInfoPtr pScrn = crtc->scrn;
     I830Ptr pI830 = I830PTR(pScrn);
     uint32_t fbc_ctl;
-    char pipe = (INREG(FBC_CONTROL2) & 1) ? 'b' : 'a';
+    char plane = (INREG(FBC_CONTROL2) & 1) ? 'b' : 'a';
 
     /* Disable compression */
     fbc_ctl = INREG(FBC_CONTROL);
@@ -635,7 +633,7 @@ i830_disable_fb_compression(xf86CrtcPtr 
     /* Wait for compressing bit to clear */
     while (INREG(FBC_STATUS) & FBC_STAT_COMPRESSING)
 	; /* nothing */
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "fbc disabled on pipe %c\n", pipe);
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "fbc disabled on pipe %c\n", plane);
 }
 
 /**
@@ -651,10 +649,11 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mod
     I830Ptr pI830 = I830PTR(pScrn);
     I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
     int pipe = intel_crtc->pipe;
+    int plane = intel_crtc->plane;
     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;
+    int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
+    int dspbase_reg = (plane == 0) ? DSPABASE : DSPBBASE;
     CARD32 temp;
 
     /* XXX: When our outputs are all unaware of DPMS modes other than off and
@@ -951,10 +950,10 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
     I830Ptr pI830 = I830PTR(pScrn);
     I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
     int pipe = intel_crtc->pipe;
+    int plane = intel_crtc->plane;
     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 dpll_md_reg = (pipe == 0) ? DPLL_A_MD : DPLL_B_MD;
     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;
@@ -962,10 +961,11 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
     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;
+    int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
+    int dspstride_reg = (plane == 0) ? DSPASTRIDE : DSPBSTRIDE;
+    int dsppos_reg = (plane == 0) ? DSPAPOS : DSPBPOS;
+    int dspsize_reg = (plane == 0) ? DSPASIZE : DSPBSIZE;
     int i;
     int refclk;
     intel_clock_t clock;
@@ -1415,8 +1415,11 @@ i830DescribeOutputConfiguration(ScrnInfo
 
     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);
+	I830CrtcPrivatePtr intel_crtc = crtc ? crtc->driver_private : NULL;
+	CARD32 dspcntr = intel_crtc->plane == 0 ? INREG(DSPACNTR) :
+	    INREG(DSPBCNTR);
+	CARD32 pipeconf = i == 0 ? INREG(PIPEACONF) :
+	    INREG(PIPEBCONF);
 	Bool hw_plane_enable = (dspcntr & DISPLAY_PLANE_ENABLE) != 0;
 	Bool hw_pipe_enable = (pipeconf & PIPEACONF_ENABLE) != 0;
 
@@ -1425,8 +1428,8 @@ i830DescribeOutputConfiguration(ScrnInfo
 		   '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,
-		   crtc->enabled ? "enabled" : "disabled",
+		   'A' + intel_crtc->plane,
+		   hw_plane_enable ? "enabled" : "disabled",
 		   dspcntr & DISPPLANE_SEL_PIPE_MASK ? 'B' : 'A');
 	if (hw_pipe_enable != crtc->enabled) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
@@ -1730,6 +1733,7 @@ i830_crtc_init(ScrnInfoPtr pScrn, int pi
     intel_crtc = xnfcalloc (sizeof (I830CrtcPrivateRec), 1);
     intel_crtc->pipe = pipe;
     intel_crtc->dpms_mode = DPMSModeOff;
+    intel_crtc->plane = pipe;
 
     /* Initialize the LUTs for when we turn on the CRTC. */
     for (i = 0; i < 256; i++) {
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 712b2dd..81e8118 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -742,7 +742,8 @@ I830SetupOutputs(ScrnInfoPtr pScrn)
 {
    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR (pScrn);
    I830Ptr  pI830 = I830PTR(pScrn);
-   int	    o;
+   int	    o, c;
+   Bool	    lvds_detected = FALSE;
 
    /* everyone has at least a single analog output */
    i830_crt_init(pScrn);
@@ -765,7 +766,9 @@ I830SetupOutputs(ScrnInfoPtr pScrn)
       xf86OutputPtr	   output = config->output[o];
       I830OutputPrivatePtr intel_output = output->driver_private;
       int		   crtc_mask;
-      int		   c;
+
+      if (intel_output->type == I830_OUTPUT_LVDS)
+	  lvds_detected = TRUE;
       
       crtc_mask = 0;
       for (c = 0; c < config->num_crtc; c++)
@@ -779,6 +782,24 @@ I830SetupOutputs(ScrnInfoPtr pScrn)
       output->possible_crtcs = crtc_mask;
       output->possible_clones = i830_output_clones (pScrn, intel_output->clone_mask);
    }
+
+   /*
+    * If an LVDS display is present, swap the plane/pipe mappings so we can
+    * use FBC on the builtin display.
+    * Note: 965+ chips can compress either plane, so we leave the mapping
+    *       alone in that case.
+    */
+   if (lvds_detected && !IS_I965GM(pI830)) {
+       for (c = 0; c < config->num_crtc; c++) {
+	   xf86CrtcPtr	      crtc = config->crtc[c];
+	   I830CrtcPrivatePtr   intel_crtc = crtc->driver_private;
+
+	   if (intel_crtc->pipe == 0)
+	       intel_crtc->plane = 1;
+	   else if (intel_crtc->pipe == 1)
+	       intel_crtc->plane = 0;
+      }
+   }
 }
 
 /**
diff --git a/src/i830_tv.c b/src/i830_tv.c
index e3aeaf9..a77bf98 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -878,11 +878,11 @@ i830_tv_restore(xf86OutputPtr output)
     OUTREG(TV_CLR_LEVEL, dev_priv->save_TV_CLR_LEVEL);
 
     {
-	int pipeconf_reg = (intel_crtc->pipe == 0)?PIPEACONF:PIPEBCONF;
-	int dspcntr_reg = (intel_crtc->pipe == 0)?DSPACNTR : DSPBCNTR;
+	int pipeconf_reg = (intel_crtc->pipe == 0) ? PIPEACONF : PIPEBCONF;
+	int dspcntr_reg = (intel_crtc->plane == 0) ? DSPACNTR : DSPBCNTR;
 	int pipeconf = INREG(pipeconf_reg);
 	int dspcntr = INREG(dspcntr_reg);
-	int dspbase_reg = (intel_crtc->pipe == 0) ? DSPABASE : DSPBBASE;
+	int dspbase_reg = (intel_crtc->plane == 0) ? DSPABASE : DSPBBASE;
 	/* Pipe must be off here */
 	OUTREG(dspcntr_reg, dspcntr & ~DISPLAY_PLANE_ENABLE);
 	/* Flush the plane changes */
@@ -1182,11 +1182,11 @@ i830_tv_mode_set(xf86OutputPtr output, D
     OUTREG(TV_CLR_LEVEL, ((video_levels->black << TV_BLACK_LEVEL_SHIFT) |
 		(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_reg = (intel_crtc->pipe == 0) ? PIPEACONF : PIPEBCONF;
+	int dspcntr_reg = (intel_crtc->plane == 0) ? DSPACNTR : DSPBCNTR;
 	int pipeconf = INREG(pipeconf_reg);
 	int dspcntr = INREG(dspcntr_reg);
-	int dspbase_reg = (intel_crtc->pipe == 0) ? DSPABASE : DSPBBASE;
+	int dspbase_reg = (intel_crtc->plane == 0) ? DSPABASE : DSPBBASE;
 	int xpos = 0x0, ypos = 0x0;
 	unsigned int xsize, ysize;
 	/* Pipe must be off here */
diff-tree c3438356d6b7b63ad9d0086efb084be8e048980e (from 0c9e4aeea84e20a18e3b76d8cf8e802af004df57)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Aug 16 11:34:02 2007 -0700

    Add tiling information to BO layout description.

diff --git a/src/i830_memory.c b/src/i830_memory.c
index 2328858..902ca2d 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -926,15 +926,22 @@ i830_describe_allocations(ScrnInfoPtr pS
 		       "%s0x%08lx:            start of memory manager\n",
 		       prefix, pI830->memory_manager->offset);
 	for (mem = pI830->bo_list; mem != NULL; mem = mem->next) {
+	    char *tile_suffix = "";
+
+	    if (mem->tiling == TILE_XMAJOR)
+		tile_suffix = " X tiled";
+	    else if (mem->tiling == TILE_YMAJOR)
+		tile_suffix = " Y tiled";
+
 	    if (mem->bound) {
 		xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-			       "%s0x%08lx-0x%08lx: %s (%ld kB)\n", prefix,
+			       "%s0x%08lx-0x%08lx: %s (%ld kB)%s\n", prefix,
 			       mem->offset, mem->end - 1, mem->name,
-			       mem->size / 1024);
+			       mem->size / 1024, tile_suffix);
 	    } else {
 		xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-			       "%sunpinned          : %s (%ld kB)\n", prefix,
-			       mem->name, mem->size / 1024);
+			       "%sunpinned          : %s (%ld kB)%s\n", prefix,
+			       mem->name, mem->size / 1024, tile_suffix);
 	    }
 	}
 	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
diff-tree 0c9e4aeea84e20a18e3b76d8cf8e802af004df57 (from parents)
Merge: 79d9a309b19e22561e000a47b732c67479c2e6d4 2231cdcd8f1ee81b3e59cc5e3a325c22ee0f40e4
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Aug 16 11:30:16 2007 -0700

    Merge branch 'master' into buffer-objects
    
    Conflicts:
    
    	src/i830_dri.c
    	src/i830_memory.c

diff --cc src/i830.h
index ccbae4f,ca48b52..a39514b
@@@ -338,12 -334,9 +344,8 @@@
  
     int TexGranularity;
     int drmMinor;
 -   int mmModeFlags;
 -   int mmSize;
 +   Bool allocate_classic_textures;
  
-    unsigned int back_tiled;
-    unsigned int third_tiled;
-    unsigned int depth_tiled;
- 
     Bool want_vblank_interrupts;
  #ifdef DAMAGE
     DamagePtr pDamage;
diff --cc src/i830_dri.c
index f97edd7,e2b42b4..c25a084
@@@ -591,30 -591,29 +591,31 @@@
     pDRIInfo->MoveBuffers = I830DRIMoveBuffers;
     pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
  
 -   {
 -#if DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1
 -      int major, minor, patch;
 -
 -      DRIQueryVersion(&major, &minor, &patch);
 -
 -#if DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 3
 -      if (minor >= 3)
 -#endif
  #if DRIINFO_MAJOR_VERSION > 5 || \
      (DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 3)
-       pDRIInfo->texOffsetStart = I830TexOffsetStart;
+       if (pI830->useEXA)
+ 	 pDRIInfo->texOffsetStart = I830TexOffsetStart;
  #endif
  
 -#if DRI_SUPPORTS_CLIP_NOTIFY && DRIINFO_MAJOR_VERSION == 5
 -      if (minor >= 1)
 -#endif
  #if DRI_SUPPORTS_CLIP_NOTIFY
 -	 pDRIInfo->ClipNotify = I830DRIClipNotify;
 +      pDRIInfo->ClipNotify = I830DRIClipNotify;
 +#endif
 +
 +#if DRI_DRIVER_FRAMEBUFFER_MAP
 +   /* DRI version is high enough that we can get the DRI code to not
 +    * try to manage the framebuffer.
 +    */
 +   pDRIInfo->frameBufferPhysicalAddress = 0;
 +   pDRIInfo->frameBufferSize = 0;
 +   pDRIInfo->frameBufferStride = 0;
 +   pDRIInfo->dontMapFrameBuffer = TRUE;
 +#else
 +   /* Supply a dummy mapping info required by DRI setup.
 +    */
 +   pDRIInfo->frameBufferPhysicalAddress = (char *) pI830->LinearAddr;
 +   pDRIInfo->frameBufferSize = GTT_PAGE_SIZE;
 +   pDRIInfo->frameBufferStride = 1;
  #endif
 -#endif /* DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1 */
 -   }
  
     pDRIInfo->TransitionTo2d = I830DRITransitionTo2d;
     pDRIInfo->TransitionTo3d = I830DRITransitionTo3d;
diff --cc src/i830_exa.c
index e801d50,fdf94d7..353ab8f
@@@ -405,21 -458,17 +458,22 @@@
      pI830->EXADriverPtr->exa_major = 2;
      pI830->EXADriverPtr->exa_minor = 1;
      pI830->EXADriverPtr->memoryBase = pI830->FbBase;
 -    pI830->EXADriverPtr->offScreenBase = pI830->exa_offscreen->offset;
 -    pI830->EXADriverPtr->memorySize = pI830->exa_offscreen->offset +
 +    if (pI830->exa_offscreen) {
 +	pI830->EXADriverPtr->offScreenBase = pI830->exa_offscreen->offset;
 +	pI830->EXADriverPtr->memorySize = pI830->exa_offscreen->offset +
  	pI830->exa_offscreen->size;
 +    } else {
 +	pI830->EXADriverPtr->offScreenBase = pI830->FbMapSize;
 +	pI830->EXADriverPtr->memorySize = pI830->FbMapSize;
 +    }
      pI830->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS;
  
-     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);
+     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);
  
  
      /* Limits are described in the BLT engine chapter under Graphics Data Size
diff --cc src/i830_memory.c
index 96a4d67,15d3a48..2328858
@@@ -108,18 -108,6 +108,13 @@@
  
  #define ALIGN(i,m)    (((i) + (m) - 1) & ~((m) - 1))
  
 +/* Our hardware status area is just a single page */
 +#define HWSTATUS_PAGE_SIZE GTT_PAGE_SIZE
 +
- enum tile_format {
-     TILING_NONE,
-     TILING_XMAJOR,
-     TILING_YMAJOR
- };
- 
 +static i830_memory *
 +i830_allocate_aperture(ScrnInfoPtr pScrn, const char *name,
 +		       long size, unsigned long alignment, int flags);
++
  static void i830_set_fence(ScrnInfoPtr pScrn, int nr, unsigned int offset,
  			   unsigned int pitch, unsigned int size,
  			   enum tile_format tile_format);
@@@ -749,22 -519,19 +744,24 @@@
  i830_allocate_memory(ScrnInfoPtr pScrn, const char *name,
  		     unsigned long size, unsigned long alignment, int flags)
  {
 +    I830Ptr pI830 = I830PTR(pScrn);
      i830_memory *mem;
  
 -    mem = i830_allocate_aperture(pScrn, name, size, alignment, flags);
 -    if (mem == NULL)
 -	return NULL;
 +    if (pI830->memory_manager && !(flags & NEED_PHYSICAL_ADDR)) {
 +	return i830_allocate_memory_bo(pScrn, name, size, alignment, flags);
 +    } else {
 +	mem = i830_allocate_aperture(pScrn, name, size, alignment, flags);
 +	if (mem == NULL)
 +	    return NULL;
  
 -    if (!i830_allocate_agp_memory(pScrn, mem, flags)) {
 -	i830_free_memory(pScrn, mem);
 -	return NULL;
 +	if (!i830_allocate_agp_memory(pScrn, mem, flags)) {
 +	    i830_free_memory(pScrn, mem);
 +	    return NULL;
 +	}
      }
  
+     mem->tiling = TILE_NONE;
+ 
      return mem;
  }
  
@@@ -789,15 -556,9 +786,15 @@@
      i830_memory *mem;
      int fence_divide, i;
  
-     if (tile_format == TILING_NONE)
+     if (tile_format == TILE_NONE)
  	return i830_allocate_memory(pScrn, name, size, alignment, flags);
  
 +    /* XXX: for now, refuse to tile with movable buffer object allocations,
 +     * until we can move the set_fence (and failure recovery) into bind time.
 +     */
 +    if (pI830->memory_manager != NULL && !(flags & NEED_LIFETIME_FIXED))
 +	return NULL;
 +
      /* Only allocate page-sized increments. */
      size = ALIGN(size, GTT_PAGE_SIZE);
  
@@@ -898,9 -657,11 +887,11 @@@
      }
  
      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
 -		   "%sMemory allocation layout:\n", prefix);
 +		   "%sFixed memory allocation layout:\n", prefix);
  
      for (mem = pI830->memory_list->next; mem->next != NULL; mem = mem->next) {
+ 	char phys_suffix[32] = "";
+ 	char *tile_suffix = "";
  
  	if (mem->offset >= pI830->stolen_size &&
  	    mem->prev->offset < pI830->stolen_size)
@@@ -927,50 -687,6 +917,31 @@@
      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
  		   "%s0x%08lx:            end of aperture\n",
  		   prefix, pI830->FbMapSize);
 +
 +#ifdef XF86DRI_MM
 +    if (pI830->memory_manager) {
 +	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
 +		       "%sBO memory allocation layout:\n", prefix);
 +	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
 +		       "%s0x%08lx:            start of memory manager\n",
 +		       prefix, pI830->memory_manager->offset);
 +	for (mem = pI830->bo_list; mem != NULL; mem = mem->next) {
 +	    if (mem->bound) {
 +		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,
 +			       "%sunpinned          : %s (%ld kB)\n", prefix,
 +			       mem->name, mem->size / 1024);
 +	    }
 +	}
 +	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
 +		       "%s0x%08lx:            end of memory manager\n",
 +		       prefix, pI830->memory_manager->end);
 +    }
 +#endif /* XF86DRI_MM */
- 
-     if (pI830->front_buffer != NULL) {
- 	i830_describe_tiling(pScrn, verbosity, prefix, pI830->front_buffer,
- 			     pI830->front_tiled);
-     }
- #ifdef XF86DRI
-     if (pI830->back_buffer != NULL) {
- 	i830_describe_tiling(pScrn, verbosity, prefix, pI830->back_buffer,
- 			     pI830->back_tiled);
-     }
-     if (pI830->third_buffer != NULL) {
- 	i830_describe_tiling(pScrn, verbosity, prefix, pI830->third_buffer,
- 			     pI830->third_tiled);
-     }
-     if (pI830->depth_buffer != NULL) {
- 	i830_describe_tiling(pScrn, verbosity, prefix, pI830->depth_buffer,
- 			     pI830->depth_tiled);
-     }
- #endif
  }
  
  static Bool
@@@ -1096,15 -804,9 +1067,16 @@@
      int align;
      long size, fb_height;
      char *name;
 +    int flags;
      i830_memory *front_buffer = NULL;
+     Bool tiling;
  
 +    /* The front buffer is currently marked as NEED_LIFETIME_FIXED because
 +     * DRIDoMappings is the only caller of the rm/add map functions,
 +     * and it's only called at startup.  This should be easily fixable.
 +     */
 +    flags = NEED_LIFETIME_FIXED | ALLOW_SHARING;
 +
      /* Clear everything first. */
      memset(FbMemBox, 0, sizeof(*FbMemBox));
  
@@@ -1180,10 -891,8 +1161,8 @@@
  	else
  	    align = KB(512);
  	front_buffer = i830_allocate_memory_tiled(pScrn, name, size,
--						  pitch, align,
- 						  flags,
- 						  TILING_XMAJOR);
- 	pI830->front_tiled = FENCE_XMAJOR;
 -						  0, TILE_XMAJOR);
++						  pitch, align, flags,
++						  TILE_XMAJOR);
      }
  
      /* If not, attempt it linear */
@@@ -1539,24 -1235,15 +1514,22 @@@
      {
  	size = ROUND_TO_PAGE(pitch * ALIGN(height, 16));
  	*buffer = i830_allocate_memory_tiled(pScrn, name, size, pitch,
 -					     GTT_PAGE_SIZE, ALIGN_BOTH_ENDS,
 +					     GTT_PAGE_SIZE,
 +					     ALIGN_BOTH_ENDS |
 +					     NEED_LIFETIME_FIXED |
 +					     ALLOW_SHARING,
- 					     TILING_XMAJOR);
- 	*tiled = FENCE_XMAJOR;
+ 					     TILE_XMAJOR);
      }
  
 -    /* Otherwise, just allocate it linear */
 +    /* Otherwise, just allocate it linear.  The offset must stay constant
 +     * currently because we don't ever update the DRI maps after screen init.
 +     */
      if (*buffer == NULL) {
  	size = ROUND_TO_PAGE(pitch * height);
  	*buffer = i830_allocate_memory(pScrn, name, size, GTT_PAGE_SIZE,
 -				       ALIGN_BOTH_ENDS);
 +				       ALIGN_BOTH_ENDS |
 +				       NEED_LIFETIME_FIXED |
 +				       ALLOW_SHARING);
- 	*tiled = FENCE_LINEAR;
      }
  
      if (*buffer == NULL) {
@@@ -1596,24 -1283,16 +1569,21 @@@
  
  	pI830->depth_buffer =
  	    i830_allocate_memory_tiled(pScrn, "depth buffer", size, pitch,
 -				       GTT_PAGE_SIZE, ALIGN_BOTH_ENDS,
 +				       GTT_PAGE_SIZE,
 +				       ALIGN_BOTH_ENDS |
 +				       NEED_LIFETIME_FIXED |
 +				       ALLOW_SHARING,
  				       tile_format);
- 	pI830->depth_tiled = (tile_format == TILING_YMAJOR) ? FENCE_YMAJOR :
- 	    FENCE_XMAJOR;
      }
  
 -    /* Otherwise, allocate it linear. */
 +    /* Otherwise, allocate it linear. The offset must stay constant
 +     * currently because we don't ever update the DRI maps after screen init.
 +     */
      if (pI830->depth_buffer == NULL) {
  	size = ROUND_TO_PAGE(pitch * height);
  	pI830->depth_buffer =
  	    i830_allocate_memory(pScrn, "depth buffer", size, GTT_PAGE_SIZE,
 -				 0);
 +				 ALLOW_SHARING | NEED_LIFETIME_FIXED);
- 	pI830->depth_tiled = FENCE_LINEAR;
      }
  
      if (pI830->depth_buffer == NULL) {
diff-tree 2231cdcd8f1ee81b3e59cc5e3a325c22ee0f40e4 (from a69db6f7fe1703b473e5c1d1e0088ccc203f4d5a)
Author: Dave Airlie <airlied at redhat.com>
Date:   Thu Aug 16 17:15:54 2007 +1000

    i915: add support for render to a8

diff --git a/src/i915_render.c b/src/i915_render.c
index 7f25d90..7546dfd 100644
--- a/src/i915_render.c
+++ b/src/i915_render.c
@@ -155,16 +155,9 @@ static Bool i915_get_dest_format(Picture
     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;
@@ -313,6 +306,7 @@ i915_prepare_composite(int op, PicturePt
     I830Ptr pI830 = I830PTR(pScrn);
     CARD32 dst_format, dst_offset, dst_pitch;
     CARD32 blendctl;
+    int out_reg = FS_OC;
 
     IntelEmitInvarientState(pScrn);
     *pI830->last_3d = LAST_3D_RENDER;
@@ -412,6 +406,9 @@ i915_prepare_composite(int op, PicturePt
 	ADVANCE_LP_RING();
     }
 
+    if (dst_format == COLR_BUF_8BIT)
+	out_reg = FS_U0;
+
     FS_BEGIN();
 
     /* Declare the registers necessary for our program.  I don't think the
@@ -432,7 +429,7 @@ i915_prepare_composite(int op, PicturePt
 
     if (!pMask) {
 	/* No mask, so move to output color */
-	i915_fs_mov(FS_OC, i915_fs_operand_reg(FS_R0));
+	i915_fs_mov(out_reg, i915_fs_operand_reg(FS_R0));
     } else {
 	/* Load the pMaskPicture texel */
 	i915_fs_texld(FS_R1, FS_S1, FS_T1);
@@ -453,17 +450,20 @@ i915_prepare_composite(int op, PicturePt
 	    PICT_FORMAT_RGB(pMaskPicture->format))
 	{
 	    if (i915_blend_op[op].src_alpha) {
-		i915_fs_mul(FS_OC, i915_fs_operand(FS_R0, W, W, W, W),
+		i915_fs_mul(out_reg, 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_mul(out_reg, 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_mul(out_reg, i915_fs_operand_reg(FS_R0),
 			i915_fs_operand(FS_R1, W, W, W, W));
 	}
     }
+    if (dst_format == COLR_BUF_8BIT)
+	i915_fs_mov(FS_OC, i915_fs_operand(out_reg, W, W, W, W));
+
     FS_END();
 
     return TRUE;
diff-tree a69db6f7fe1703b473e5c1d1e0088ccc203f4d5a (from 5126a71f82767b9e23cd590453718f3364789740)
Author: Dave Airlie <airlied at redhat.com>
Date:   Wed Aug 15 18:28:50 2007 +1000

    intel: don't setup texOffsetStart unless using EXA

diff --git a/src/i830_dri.c b/src/i830_dri.c
index a4fc97c..e2b42b4 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -602,6 +602,7 @@ I830DRIScreenInit(ScreenPtr pScreen)
 #endif
 #if DRIINFO_MAJOR_VERSION > 5 || \
     (DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 3)
+      if (pI830->useEXA)
 	 pDRIInfo->texOffsetStart = I830TexOffsetStart;
 #endif
 
diff-tree 5126a71f82767b9e23cd590453718f3364789740 (from d9f89a1af7e7ff4056727060cdf2e35c15a4dcdd)
Author: Zhenyu Wang <zhenyu.z.wang at intel.com>
Date:   Tue Aug 14 13:54:55 2007 +0800

    Fix seg fault introduced in tiling patch when TV detect
    
    When TV does load detect, fb hasn't been setup, so we should check
    that in i830_display_tiled(). Caught by Nanhai.

diff --git a/src/i830_display.c b/src/i830_display.c
index 7a229b2..706b9ba 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -511,7 +511,7 @@ i830_display_tiled(xf86CrtcPtr crtc)
     if (crtc->rotatedData)
 	return FALSE;
 
-    if (pI830->front_buffer->tiling != TILE_NONE)
+    if (pI830->front_buffer && pI830->front_buffer->tiling != TILE_NONE)
 	return TRUE;
 
     return FALSE;
diff-tree d9f89a1af7e7ff4056727060cdf2e35c15a4dcdd (from 5bc194d3d3c87bb0128d9ac10f090f031345eb37)
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Fri Aug 10 17:59:33 2007 -0700

    Save/restore tile-mode offset registers DSPATILEOFF and DSPBTILEOFF
    
    Now that the driver sets these registers, they must be saved and restored.

diff --git a/src/i830.h b/src/i830.h
index 7ae17b4..ca48b52 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -499,6 +499,7 @@ typedef struct _I830Rec {
    CARD32 saveDSPAPOS;
    CARD32 saveDSPABASE;
    CARD32 saveDSPASURF;
+   CARD32 saveDSPATILEOFF;
    CARD32 saveFPB0;
    CARD32 saveFPB1;
    CARD32 saveDPLL_B;
@@ -515,6 +516,7 @@ typedef struct _I830Rec {
    CARD32 saveDSPBPOS;
    CARD32 saveDSPBBASE;
    CARD32 saveDSPBSURF;
+   CARD32 saveDSPBTILEOFF;
    CARD32 saveVCLK_DIVISOR_VGA0;
    CARD32 saveVCLK_DIVISOR_VGA1;
    CARD32 saveVCLK_POST_DIV;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index acb8354..712b2dd 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1816,6 +1816,8 @@ SaveHWState(ScrnInfoPtr pScrn)
    if (IS_I965G(pI830)) {
       pI830->saveDSPASURF = INREG(DSPASURF);
       pI830->saveDSPBSURF = INREG(DSPBSURF);
+      pI830->saveDSPATILEOFF = INREG(DSPATILEOFF);
+      pI830->saveDSPBTILEOFF = INREG(DSPBTILEOFF);
    }
 
    pI830->saveVCLK_DIVISOR_VGA0 = INREG(VCLK_DIVISOR_VGA0);
@@ -1910,7 +1912,10 @@ RestoreHWState(ScrnInfoPtr pScrn)
    OUTREG(PIPEASRC, pI830->savePIPEASRC);
    OUTREG(DSPABASE, pI830->saveDSPABASE);
    if (IS_I965G(pI830))
+   {
       OUTREG(DSPASURF, pI830->saveDSPASURF);
+      OUTREG(DSPATILEOFF, pI830->saveDSPATILEOFF);
+   }
    OUTREG(PIPEACONF, pI830->savePIPEACONF);
    i830WaitForVblank(pScrn);
    OUTREG(DSPACNTR, pI830->saveDSPACNTR);
@@ -1947,7 +1952,10 @@ RestoreHWState(ScrnInfoPtr pScrn)
       OUTREG(PIPEBSRC, pI830->savePIPEBSRC);
       OUTREG(DSPBBASE, pI830->saveDSPBBASE);
       if (IS_I965G(pI830))
+      {
 	 OUTREG(DSPBSURF, pI830->saveDSPBSURF);
+	 OUTREG(DSPBTILEOFF, pI830->saveDSPBTILEOFF);
+      }
       OUTREG(PIPEBCONF, pI830->savePIPEBCONF);
       i830WaitForVblank(pScrn);
       OUTREG(DSPBCNTR, pI830->saveDSPBCNTR);
diff-tree 5bc194d3d3c87bb0128d9ac10f090f031345eb37 (from 64b943c79cf957a4c54482720195d7f27b7f0c0d)
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Fri Aug 10 17:54:32 2007 -0700

    Set DSPATILEOFF/DSPBTILEOFF to handle 965 tiled frame buffers.
    
    DSPATILEOFF and DSPBTILEOFF replace DSPASURF and DSPBSURF when the frame
    buffer is in tiled mode.

diff --git a/src/i830_display.c b/src/i830_display.c
index a77da1b..7a229b2 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -375,6 +375,7 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x,
     unsigned long Start, Offset;
     int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE);
     int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
+    int dsptileoff = (pipe == 0 ? DSPATILEOFF : DSPBTILEOFF);
 
     Offset = ((y * pScrn->displayWidth + x) * pI830->cpp);
     if (pI830->front_buffer == NULL) {
@@ -399,6 +400,7 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x,
 	POSTING_READ(dspbase);
         OUTREG(dspsurf, Start);
 	POSTING_READ(dspsurf);
+	OUTREG(dsptileoff, (y << 16) | x);
     } else {
 	OUTREG(dspbase, Start + Offset);
 	POSTING_READ(dspbase);
diff-tree 64b943c79cf957a4c54482720195d7f27b7f0c0d (from ba9a503ba2099025e393f3382bb453985ef23497)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Aug 10 15:48:05 2007 -0700

    Add #if 0-ed fence debugging code.  It's noisy, and of little use to most.

diff --git a/src/i830_debug.c b/src/i830_debug.c
index 055ca93..8b4b76f 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -334,6 +334,19 @@ DEBUGSTRING(i830_debug_sdvo)
 		     enable, pipe, stall, detected, sdvoextra, gang);
 }
 
+#if 0
+DEBUGSTRING(i810_debug_fence_new)
+{
+    char *enable = (val & FENCE_VALID) ? "enabled" : "disabled";
+    char format = (val & I965_FENCE_Y_MAJOR) ? 'Y' : 'X';
+    int pitch = ((val & 0xffc) >> 2) * 128;
+    unsigned int offset = val & 0xfffff000;
+
+    return XNFprintf("%s, %c tile walk, %d pitch, 0x%08x offset",
+		     enable, format, pitch, offset);
+}
+#endif
+
 #define DEFINEREG(reg) \
 	{ reg, #reg, NULL, 0 }
 #define DEFINEREG2(reg, func) \
@@ -465,6 +478,25 @@ static struct i830SnapshotRec {
     DEFINEREG(TV_H_LUMA_59),
     DEFINEREG(TV_H_CHROMA_0),
     DEFINEREG(TV_H_CHROMA_59),
+
+#if 0
+    DEFINEREG2(FENCE_NEW + 0, i810_debug_fence_new),
+    DEFINEREG2(FENCE_NEW + 8, i810_debug_fence_new),
+    DEFINEREG2(FENCE_NEW + 16, i810_debug_fence_new),
+    DEFINEREG2(FENCE_NEW + 24, i810_debug_fence_new),
+    DEFINEREG2(FENCE_NEW + 32, i810_debug_fence_new),
+    DEFINEREG2(FENCE_NEW + 40, i810_debug_fence_new),
+    DEFINEREG2(FENCE_NEW + 48, i810_debug_fence_new),
+    DEFINEREG2(FENCE_NEW + 56, i810_debug_fence_new),
+    DEFINEREG2(FENCE_NEW + 64, i810_debug_fence_new),
+    DEFINEREG2(FENCE_NEW + 72, i810_debug_fence_new),
+    DEFINEREG2(FENCE_NEW + 80, i810_debug_fence_new),
+    DEFINEREG2(FENCE_NEW + 88, i810_debug_fence_new),
+    DEFINEREG2(FENCE_NEW + 96, i810_debug_fence_new),
+    DEFINEREG2(FENCE_NEW + 104, i810_debug_fence_new),
+    DEFINEREG2(FENCE_NEW + 112, i810_debug_fence_new),
+    DEFINEREG2(FENCE_NEW + 120, i810_debug_fence_new),
+#endif
 };
 #undef DEFINEREG
 #define NUM_I830_SNAPSHOTREGS (sizeof(i830_snapshot) / sizeof(i830_snapshot[0]))
diff-tree ba9a503ba2099025e393f3382bb453985ef23497 (from b7751c7d1d6bcf310824295c3bab4ff36760c791)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Aug 10 15:06:58 2007 -0700

    Don't force tiling on if it is disabled in configuration but fbc is possible.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 6a03ff6..acb8354 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2275,12 +2275,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 	   pI830->fb_compression = FALSE;
    }
 
-   if (pI830->fb_compression && !pI830->tiling) {
-       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Framebuffer compression enabled, "
-		  "forcing tiling on.\n");
-       pI830->tiling = TRUE;
-   }
-
    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Framebuffer compression %sabled\n",
 	      pI830->fb_compression ? "en" : "dis");
    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Tiling %sabled\n", pI830->tiling ?
diff-tree b7751c7d1d6bcf310824295c3bab4ff36760c791 (from cb36635a053d4ac3971fea05060d31dbd3d382d2)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Aug 10 17:42:09 2007 -0700

    Fix stack-smashing in the last commit.

diff --git a/src/i830_memory.c b/src/i830_memory.c
index 6ba2cd1..15d3a48 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -660,7 +660,7 @@ i830_describe_allocations(ScrnInfoPtr pS
 		   "%sMemory allocation layout:\n", prefix);
 
     for (mem = pI830->memory_list->next; mem->next != NULL; mem = mem->next) {
-	char phys_suffix[30] = "";
+	char phys_suffix[32] = "";
 	char *tile_suffix = "";
 
 	if (mem->offset >= pI830->stolen_size &&
@@ -672,7 +672,8 @@ i830_describe_allocations(ScrnInfoPtr pS
 	}
 
 	if (mem->bus_addr != 0)
-	    sprintf(phys_suffix, ", 0x%16llx physical\n", mem->bus_addr);
+	    snprintf(phys_suffix, sizeof(phys_suffix),
+		    ", 0x%016llx physical\n", mem->bus_addr);
 	if (mem->tiling == TILE_XMAJOR)
 	    tile_suffix = " X tiled";
 	else if (mem->tiling == TILE_YMAJOR)
diff-tree cb36635a053d4ac3971fea05060d31dbd3d382d2 (from ed1b106fabf3a18489bdb3083326f27387a9cb72)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Aug 10 14:16:59 2007 -0700

    Attempt to fix several front buffer tiling failure cases.
    
    Front buffer tiling is now disabled with G965 and XAA.  Some of the acceleration
    that i830_xaa.c does can't be supported on tiled buffers.
    
    Adds a tiling field to struct i830_memory, and uses it instead of separate
    variables for each potential tiled buffer.

diff --git a/src/i830.h b/src/i830.h
index f72e1d6..7ae17b4 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -117,6 +117,12 @@ typedef CARD8(*I830ReadIndexedByteFunc)(
 typedef void (*I830WriteByteFunc)(I830Ptr pI830, IOADDRESS addr, CARD8 value);
 typedef CARD8(*I830ReadByteFunc)(I830Ptr pI830, IOADDRESS addr);
 
+enum tile_format {
+    TILE_NONE,
+    TILE_XMAJOR,
+    TILE_YMAJOR
+};
+
 /** Record of a linear allocation in the aperture. */
 typedef struct _i830_memory i830_memory;
 struct _i830_memory {
@@ -148,6 +154,8 @@ struct _i830_memory {
      */
     unsigned long agp_offset;
 
+    enum tile_format tiling;
+
     /** Description of the allocation, for logging */
     char *name;
 
@@ -316,8 +324,6 @@ typedef struct _I830Rec {
 
    i830_memory *logical_context;
 
-   unsigned int front_tiled;
-
 #ifdef XF86DRI
    i830_memory *back_buffer;
    i830_memory *third_buffer;
@@ -331,10 +337,6 @@ typedef struct _I830Rec {
    int mmModeFlags;
    int mmSize;
 
-   unsigned int back_tiled;
-   unsigned int third_tiled;
-   unsigned int depth_tiled;
-
    Bool want_vblank_interrupts;
 #ifdef DAMAGE
    DamagePtr pDamage;
diff --git a/src/i830_display.c b/src/i830_display.c
index d5f7586..a77da1b 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -505,14 +505,14 @@ i830_display_tiled(xf86CrtcPtr crtc)
     ScrnInfoPtr pScrn = crtc->scrn;
     I830Ptr pI830 = I830PTR(pScrn);
 
-    if (!pI830->tiling)
-	return FALSE;
-
     /* Rotated data is currently linear, allocated either via XAA or EXA */
     if (crtc->rotatedData)
 	return FALSE;
 
-    return TRUE;
+    if (pI830->front_buffer->tiling != TILE_NONE)
+	return TRUE;
+
+    return FALSE;
 }
 
 static Bool
diff --git a/src/i830_dri.c b/src/i830_dri.c
index ca1190c..a4fc97c 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1658,10 +1658,13 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, 
 
    I830DRIUnmapScreenRegions(pScrn, sarea);
 
-   sarea->front_tiled = pI830->front_tiled;
-   sarea->back_tiled = pI830->back_tiled;
-   sarea->third_tiled = pI830->third_tiled;
-   sarea->depth_tiled = pI830->depth_tiled;
+   sarea->front_tiled = (pI830->front_buffer->tiling != TILE_NONE);
+   sarea->back_tiled = (pI830->back_buffer->tiling != TILE_NONE);
+   if (pI830->third_buffer != NULL)
+       sarea->third_tiled = (pI830->third_buffer->tiling != TILE_NONE);
+   else
+       sarea->third_tiled = FALSE;
+   sarea->depth_tiled = (pI830->depth_buffer->tiling != TILE_NONE);
    sarea->rotated_tiled = FALSE;
 
    sarea->front_offset = pI830->front_buffer->offset;
diff --git a/src/i830_exa.c b/src/i830_exa.c
index 023a845..fdf94d7 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -97,19 +97,30 @@ const int I830PatternROP[16] =
     ROP_1
 };
 
-/* FIXME: use pixmap private instead */
+/**
+ * Returns whether a given pixmap is tiled or not.
+ *
+ * Currently, we only have one pixmap that might be tiled, which is the front
+ * buffer.  At the point where we are tiling some pixmaps managed by the
+ * general allocator, we should move this to using pixmap privates.
+ */
 Bool
-i830_pixmap_tiled(PixmapPtr p)
+i830_pixmap_tiled(PixmapPtr pPixmap)
 {
-    ScreenPtr pScreen = p->drawable.pScreen;
+    ScreenPtr pScreen = pPixmap->drawable.pScreen;
     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
+    unsigned long offset;
 
-    if (!pI830->tiling)
-	return FALSE;
-
-    if (p == pScreen->GetScreenPixmap(pScreen))
+    /* Don't use exaGetPixmapOffset becuase we might be called from XAA code. */
+    offset = (long)pPixmap->devPrivate.ptr -
+	(long)pI830->FbBase;
+    if (offset == pI830->front_buffer->offset &&
+	pI830->front_buffer->tiling != TILE_NONE)
+    {
 	return TRUE;
+    }
+
     return FALSE;
 }
 
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 93b054c..6ba2cd1 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -108,12 +108,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 #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);
@@ -536,6 +530,8 @@ i830_allocate_memory(ScrnInfoPtr pScrn, 
 	return NULL;
     }
 
+    mem->tiling = TILE_NONE;
+
     return mem;
 }
 
@@ -560,7 +556,7 @@ i830_allocate_memory_tiled(ScrnInfoPtr p
     i830_memory *mem;
     int fence_divide, i;
 
-    if (tile_format == TILING_NONE)
+    if (tile_format == TILE_NONE)
 	return i830_allocate_memory(pScrn, name, size, alignment, flags);
 
     /* Only allocate page-sized increments. */
@@ -637,19 +633,11 @@ i830_allocate_memory_tiled(ScrnInfoPtr p
     }
 
     mem->size = size;
+    mem->tiling = tile_format;
 
     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 " : "");
-}
-
 void
 i830_describe_allocations(ScrnInfoPtr pScrn, int verbosity, const char *prefix)
 {
@@ -672,6 +660,8 @@ i830_describe_allocations(ScrnInfoPtr pS
 		   "%sMemory allocation layout:\n", prefix);
 
     for (mem = pI830->memory_list->next; mem->next != NULL; mem = mem->next) {
+	char phys_suffix[30] = "";
+	char *tile_suffix = "";
 
 	if (mem->offset >= pI830->stolen_size &&
 	    mem->prev->offset < pI830->stolen_size)
@@ -681,42 +671,21 @@ i830_describe_allocations(ScrnInfoPtr pS
 			   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, 0x%16llx physical)\n",
-			   prefix,
-			   mem->offset, mem->end - 1, mem->name,
-			   mem->size / 1024, mem->bus_addr);
-	}
+	if (mem->bus_addr != 0)
+	    sprintf(phys_suffix, ", 0x%16llx physical\n", mem->bus_addr);
+	if (mem->tiling == TILE_XMAJOR)
+	    tile_suffix = " X tiled";
+	else if (mem->tiling == TILE_YMAJOR)
+	    tile_suffix = " Y tiled";
+
+	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		       "%s0x%08lx-0x%08lx: %s (%ld kB%s)%s\n", prefix,
+		       mem->offset, mem->end - 1, mem->name,
+		       mem->size / 1024, phys_suffix, tile_suffix);
     }
     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);
-    }
-#ifdef XF86DRI
-    if (pI830->back_buffer != NULL) {
-	i830_describe_tiling(pScrn, verbosity, prefix, pI830->back_buffer,
-			     pI830->back_tiled);
-    }
-    if (pI830->third_buffer != NULL) {
-	i830_describe_tiling(pScrn, verbosity, prefix, pI830->third_buffer,
-			     pI830->third_tiled);
-    }
-    if (pI830->depth_buffer != NULL) {
-	i830_describe_tiling(pScrn, verbosity, prefix, pI830->depth_buffer,
-			     pI830->depth_tiled);
-    }
-#endif
 }
 
 static Bool
@@ -835,6 +804,7 @@ i830_allocate_framebuffer(ScrnInfoPtr pS
     long size, fb_height;
     char *name;
     i830_memory *front_buffer = NULL;
+    Bool tiling;
 
     /* Clear everything first. */
     memset(FbMemBox, 0, sizeof(*FbMemBox));
@@ -903,8 +873,17 @@ i830_allocate_framebuffer(ScrnInfoPtr pS
 
     name = secondary ? "secondary front buffer" : "front buffer";
 
+    /* Front buffer tiling has to be disabled with G965 XAA because some of the
+     * acceleration operations (non-XY COLOR_BLT) can't be done to tiled
+     * buffers.
+     */
+    if (!pI830->useEXA && IS_I965G(pI830))
+	tiling = FALSE;
+    else
+	tiling = pI830->tiling;
+
     /* Attempt to allocate it tiled first if we have page flipping on. */
-    if (pI830->tiling && IsTileable(pScrn, pitch)) {
+    if (tiling && IsTileable(pScrn, pitch)) {
 	/* XXX: probably not the case on 965 */
 	if (IS_I9XX(pI830))
 	    align = MB(1);
@@ -912,14 +891,12 @@ i830_allocate_framebuffer(ScrnInfoPtr pS
 	    align = KB(512);
 	front_buffer = i830_allocate_memory_tiled(pScrn, name, size,
 						  pitch, align,
-						  0, TILING_XMAJOR);
-	pI830->front_tiled = FENCE_XMAJOR;
+						  0, TILE_XMAJOR);
     }
 
     /* 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) {
@@ -1240,7 +1217,7 @@ myLog2(unsigned int n)
 
 static Bool
 i830_allocate_backbuffer(ScrnInfoPtr pScrn, i830_memory **buffer,
-			 unsigned int *tiled, const char *name)
+			 const char *name)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     unsigned int pitch = pScrn->displayWidth * pI830->cpp;
@@ -1258,8 +1235,7 @@ i830_allocate_backbuffer(ScrnInfoPtr pSc
 	size = ROUND_TO_PAGE(pitch * ALIGN(height, 16));
 	*buffer = i830_allocate_memory_tiled(pScrn, name, size, pitch,
 					     GTT_PAGE_SIZE, ALIGN_BOTH_ENDS,
-					     TILING_XMAJOR);
-	*tiled = FENCE_XMAJOR;
+					     TILE_XMAJOR);
     }
 
     /* Otherwise, just allocate it linear */
@@ -1267,7 +1243,6 @@ i830_allocate_backbuffer(ScrnInfoPtr pSc
 	size = ROUND_TO_PAGE(pitch * height);
 	*buffer = i830_allocate_memory(pScrn, name, size, GTT_PAGE_SIZE,
 				       ALIGN_BOTH_ENDS);
-	*tiled = FENCE_LINEAR;
     }
 
     if (*buffer == NULL) {
@@ -1303,14 +1278,12 @@ i830_allocate_depthbuffer(ScrnInfoPtr pS
 	/* The 965 requires that the depth buffer be in Y Major format, while
 	 * the rest appear to fail when handed that format.
 	 */
-	tile_format = IS_I965G(pI830) ? TILING_YMAJOR: TILING_XMAJOR;
+	tile_format = IS_I965G(pI830) ? TILE_YMAJOR: TILE_XMAJOR;
 
 	pI830->depth_buffer =
 	    i830_allocate_memory_tiled(pScrn, "depth buffer", size, pitch,
 				       GTT_PAGE_SIZE, ALIGN_BOTH_ENDS,
 				       tile_format);
-	pI830->depth_tiled = (tile_format == TILING_YMAJOR) ? FENCE_YMAJOR :
-	    FENCE_XMAJOR;
     }
 
     /* Otherwise, allocate it linear. */
@@ -1319,7 +1292,6 @@ i830_allocate_depthbuffer(ScrnInfoPtr pS
 	pI830->depth_buffer =
 	    i830_allocate_memory(pScrn, "depth buffer", size, GTT_PAGE_SIZE,
 				 0);
-	pI830->depth_tiled = FENCE_LINEAR;
     }
 
     if (pI830->depth_buffer == NULL) {
@@ -1405,13 +1377,11 @@ i830_allocate_3d_memory(ScrnInfoPtr pScr
 	    return FALSE;
     }
 
-    if (!i830_allocate_backbuffer(pScrn, &pI830->back_buffer,
-				  &pI830->back_tiled, "back buffer"))
+    if (!i830_allocate_backbuffer(pScrn, &pI830->back_buffer, "back buffer"))
 	return FALSE;
 
     if (pI830->TripleBuffer && !i830_allocate_backbuffer(pScrn,
 							 &pI830->third_buffer,
-							 &pI830->third_tiled,
 							 "third buffer")) {
        xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		  "Failed to allocate third buffer, triple buffering "
@@ -1447,7 +1417,7 @@ i830_set_fence(ScrnInfoPtr pScrn, int nr
     DPRINTF(PFX, "i830_set_fence(): %d, 0x%08x, %d, %d kByte\n",
 	    nr, offset, pitch, size / 1024);
 
-    assert(tile_format != TILING_NONE);
+    assert(tile_format != TILE_NONE);
 
     if (IS_I965G(pI830)) {
 	if (nr < 0 || nr >= FENCE_NEW_NR) {
@@ -1457,18 +1427,18 @@ i830_set_fence(ScrnInfoPtr pScrn, int nr
 	}
 
 	switch (tile_format) {
-	case TILING_XMAJOR:
+	case TILE_XMAJOR:
             pI830->fence[nr] = (((pitch / 128) - 1) << 2) | offset | 1;
 	    pI830->fence[nr] |= I965_FENCE_X_MAJOR;
             break;
-	case TILING_YMAJOR:
+	case TILE_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:
+	case TILE_NONE:
             break;
 	}
 
@@ -1516,13 +1486,13 @@ i830_set_fence(ScrnInfoPtr pScrn, int nr
     val = offset | FENCE_VALID;
 
     switch (tile_format) {
-    case TILING_XMAJOR:
+    case TILE_XMAJOR:
 	val |= FENCE_X_MAJOR;
 	break;
-    case TILING_YMAJOR:
+    case TILE_YMAJOR:
 	val |= FENCE_Y_MAJOR;
 	break;
-    case TILING_NONE:
+    case TILE_NONE:
 	break;
     }
 
@@ -1590,7 +1560,7 @@ i830_set_fence(ScrnInfoPtr pScrn, int nr
     }
 
     if ((IS_I945G(pI830) || IS_I945GM(pI830) || IS_G33CLASS(pI830))
-	    && tile_format == TILING_YMAJOR)
+	    && tile_format == TILE_YMAJOR)
 	fence_pitch = pitch / 128;
     else if (IS_I9XX(pI830))
 	fence_pitch = pitch / 512;
diff --git a/src/i830_xaa.c b/src/i830_xaa.c
index aa06a80..fabac20 100644
--- a/src/i830_xaa.c
+++ b/src/i830_xaa.c
@@ -269,40 +269,39 @@ I830XAAInit(ScreenPtr pScreen)
     return TRUE;
 }
 
-#ifdef XF86DRI
 static unsigned int
-CheckTiling(ScrnInfoPtr pScrn)
+I830CheckTiling(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->back_buffer != NULL &&
-	  pI830->bufferOffset == pI830->back_buffer->offset &&
-	  pI830->back_tiled == FENCE_XMAJOR) {
-         tiled = 1;
-      }
-      if (pI830->third_buffer != NULL &&
-	  pI830->bufferOffset == pI830->third_buffer->offset &&
-	  pI830->third_tiled == FENCE_XMAJOR) {
-         tiled = 1;
-      }
-      /* not really supported as it's always YMajor tiled */
-      if (pI830->depth_buffer != NULL &&
-	  pI830->bufferOffset == pI830->depth_buffer->offset &&
-	  pI830->depth_tiled == FENCE_XMAJOR) {
-         tiled = 1;
-      }
+   if (pI830->bufferOffset == pI830->front_buffer->offset &&
+       pI830->front_buffer->tiling != TILE_NONE)
+   {
+       return TRUE;
+   }
+#ifdef XF86DRI
+   if (pI830->back_buffer != NULL &&
+       pI830->bufferOffset == pI830->back_buffer->offset &&
+       pI830->back_buffer->tiling != TILE_NONE)
+   {
+       return TRUE;
    }
+   if (pI830->depth_buffer != NULL &&
+       pI830->bufferOffset == pI830->depth_buffer->offset &&
+       pI830->depth_buffer->tiling != TILE_NONE)
+   {
+       return TRUE;
+   }
+   if (pI830->third_buffer != NULL &&
+       pI830->bufferOffset == pI830->third_buffer->offset &&
+       pI830->third_buffer->tiling != TILE_NONE)
+   {
+       return TRUE;
+   }
+#endif
 
-   return tiled;
+   return FALSE;
 }
-#else
-#define CheckTiling(pScrn) 0
-#endif
 
 void
 I830SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
@@ -314,16 +313,20 @@ I830SetupForSolidFill(ScrnInfoPtr pScrn,
 	ErrorF("I830SetupForFillRectSolid color: %x rop: %x mask: %x\n",
 	       color, rop, planemask);
 
+    if (IS_I965G(pI830) && I830CheckTiling(pScrn)) {
+	pI830->BR[13] = (pScrn->displayWidth * pI830->cpp) >> 4;
+    } else {
+	pI830->BR[13] = (pScrn->displayWidth * pI830->cpp);
+    }
+
 #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));
+    pI830->BR[13] |= (I830PatternROP[rop] << 16);
 #else
-    pI830->BR[13] = ((XAAGetPatternROP(rop) << 16) |
-		     (pScrn->displayWidth * pI830->cpp));
+    pI830->BR[13] |= ((XAAGetPatternROP(rop) << 16);
 #endif
 
     pI830->BR[16] = color;
@@ -381,7 +384,12 @@ I830SetupForScreenToScreenCopy(ScrnInfoP
 	ErrorF("I830SetupForScreenToScreenCopy %d %d %x %x %d\n",
 	       xdir, ydir, rop, planemask, transparency_color);
 
-    pI830->BR[13] = (pScrn->displayWidth * pI830->cpp);
+    if (IS_I965G(pI830) && I830CheckTiling(pScrn)) {
+	pI830->BR[13] = (pScrn->displayWidth * pI830->cpp) >> 4;
+    } else {
+	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
@@ -411,7 +419,7 @@ I830SubsequentScreenToScreenCopy(ScrnInf
 {
     I830Ptr pI830 = I830PTR(pScrn);
     int dst_x2, dst_y2;
-    unsigned int tiled = CheckTiling(pScrn);
+    unsigned int tiled = I830CheckTiling(pScrn);
 
     if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
 	ErrorF("I830SubsequentScreenToScreenCopy %d,%d - %d,%d %dx%d\n",
@@ -420,10 +428,6 @@ I830SubsequentScreenToScreenCopy(ScrnInf
     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);
 
@@ -463,7 +467,11 @@ I830SetupForMono8x8PatternFill(ScrnInfoP
     pI830->BR[18] = bg;
     pI830->BR[19] = fg;
 
-    pI830->BR[13] = (pScrn->displayWidth * pI830->cpp);	/* In bytes */
+    if (IS_I965G(pI830) && I830CheckTiling(pScrn)) {
+	pI830->BR[13] = (pScrn->displayWidth * pI830->cpp) >> 4;
+    } else {
+	pI830->BR[13] = (pScrn->displayWidth * pI830->cpp);
+    }
     pI830->BR[13] |= XAAGetPatternROP(rop) << 16;
     if (bg == -1)
 	pI830->BR[13] |= (1 << 28);
@@ -487,7 +495,7 @@ I830SubsequentMono8x8PatternFillRect(Scr
 {
     I830Ptr pI830 = I830PTR(pScrn);
     int x1, x2, y1, y2;
-    unsigned int tiled = CheckTiling(pScrn);
+    unsigned int tiled = I830CheckTiling(pScrn);
 
     x1 = x;
     x2 = x + w;
@@ -497,10 +505,6 @@ I830SubsequentMono8x8PatternFillRect(Scr
     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);
 
@@ -560,7 +564,11 @@ I830SetupForScanlineCPUToScreenColorExpa
 	       fg, bg, rop, planemask);
 
     /* Fill out register values */
-    pI830->BR[13] = (pScrn->displayWidth * pI830->cpp);
+    if (IS_I965G(pI830) && I830CheckTiling(pScrn)) {
+	pI830->BR[13] = (pScrn->displayWidth * pI830->cpp) >> 4;
+    } else {
+	pI830->BR[13] = (pScrn->displayWidth * pI830->cpp);
+    }
     pI830->BR[13] |= XAAGetCopyROP(rop) << 16;
     if (bg == -1)
 	pI830->BR[13] |= (1 << 29);
@@ -603,7 +611,7 @@ static void
 I830SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    unsigned int tiled = CheckTiling(pScrn);
+    unsigned int tiled = I830CheckTiling(pScrn);
 
     if (pI830->init == 0) {
 	pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] -
@@ -621,10 +629,6 @@ I830SubsequentColorExpandScanline(ScrnIn
 	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);
 
@@ -666,7 +670,11 @@ I830SetupForScanlineImageWrite(ScrnInfoP
 	ErrorF("I830SetupForScanlineImageWrite %x %x\n", rop, planemask);
 
     /* Fill out register values */
-    pI830->BR[13] = (pScrn->displayWidth * pI830->cpp);
+    if (IS_I965G(pI830) && I830CheckTiling(pScrn)) {
+	pI830->BR[13] = (pScrn->displayWidth * pI830->cpp) >> 4;
+    } else {
+	pI830->BR[13] = (pScrn->displayWidth * pI830->cpp);
+    }
     pI830->BR[13] |= XAAGetCopyROP(rop) << 16;
 
     switch (pScrn->bitsPerPixel) {
@@ -703,7 +711,7 @@ static void
 I830SubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    unsigned int tiled = CheckTiling(pScrn);
+    unsigned int tiled = I830CheckTiling(pScrn);
 
     if (pI830->init == 0) {
 	pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] -
diff --git a/src/i915_render.c b/src/i915_render.c
index 9c937f2..7f25d90 100644
--- a/src/i915_render.c
+++ b/src/i915_render.c
@@ -285,10 +285,9 @@ i915_texture_setup(PicturePtr pPict, Pix
 
     pI830->mapstate[unit * 3 + 0] = offset;
     pI830->mapstate[unit * 3 + 1] = format |
+	MS3_USE_FENCE_REGS |
 	((pPix->drawable.height - 1) << MS3_HEIGHT_SHIFT) |
 	((pPix->drawable.width - 1) << MS3_WIDTH_SHIFT);
-    if (pI830->tiling)
-	pI830->mapstate[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 <<
diff --git a/src/i915_video.c b/src/i915_video.c
index e116fe2..a6447b1 100644
--- a/src/i915_video.c
+++ b/src/i915_video.c
@@ -149,7 +149,7 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
       OUT_RING(_3DSTATE_MAP_STATE | 3);
       OUT_RING(0x00000001);	/* texture map #1 */
       OUT_RING(pPriv->YBuf0offset);
-      ms3 = MAPSURF_422;
+      ms3 = MAPSURF_422 | MS3_USE_FENCE_REGS;
       switch (id) {
       case FOURCC_YUY2:
 	 ms3 |= MT_422_YCRCB_NORMAL;
@@ -160,8 +160,6 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
       }
       ms3 |= (height - 1) << MS3_HEIGHT_SHIFT;
       ms3 |= (width - 1) << MS3_WIDTH_SHIFT;
-      if (pI830->tiling)
-	 ms3 |= MS3_USE_FENCE_REGS;
       OUT_RING(ms3);
       OUT_RING(((video_pitch / 4) - 1) << MS4_PITCH_SHIFT);
       ADVANCE_LP_RING();
@@ -248,29 +246,23 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
       OUT_RING(0x00000007);
 
       OUT_RING(pPriv->YBuf0offset);
-      ms3 = MAPSURF_8BIT | MT_8BIT_I8;
+      ms3 = MAPSURF_8BIT | MT_8BIT_I8 | MS3_USE_FENCE_REGS;
       ms3 |= (height - 1) << MS3_HEIGHT_SHIFT;
       ms3 |= (width - 1) << MS3_WIDTH_SHIFT;
-      if (pI830->tiling)
-	 ms3 |= MS3_USE_FENCE_REGS;
       OUT_RING(ms3);
       OUT_RING(((video_pitch * 2 / 4) - 1) << MS4_PITCH_SHIFT);
 
       OUT_RING(pPriv->UBuf0offset);
-      ms3 = MAPSURF_8BIT | MT_8BIT_I8;
+      ms3 = MAPSURF_8BIT | MT_8BIT_I8 | MS3_USE_FENCE_REGS;
       ms3 |= (height / 2 - 1) << MS3_HEIGHT_SHIFT;
       ms3 |= (width / 2 - 1) << MS3_WIDTH_SHIFT;
-      if (pI830->tiling)
-	 ms3 |= MS3_USE_FENCE_REGS;
       OUT_RING(ms3);
       OUT_RING(((video_pitch / 4) - 1) << MS4_PITCH_SHIFT);
 
       OUT_RING(pPriv->VBuf0offset);
-      ms3 = MAPSURF_8BIT | MT_8BIT_I8;
+      ms3 = MAPSURF_8BIT | MT_8BIT_I8 | MS3_USE_FENCE_REGS;
       ms3 |= (height / 2 - 1) << MS3_HEIGHT_SHIFT;
       ms3 |= (width / 2 - 1) << MS3_WIDTH_SHIFT;
-      if (pI830->tiling)
-	 ms3 |= MS3_USE_FENCE_REGS;
       OUT_RING(ms3);
       OUT_RING(((video_pitch / 4) - 1) << MS4_PITCH_SHIFT);
       ADVANCE_LP_RING();
diff-tree ed1b106fabf3a18489bdb3083326f27387a9cb72 (from f71b9358b4157a8cfdc694ddef8ca3f98926ca91)
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Fri Aug 10 14:31:16 2007 -0700

    Clean up tv mode name allocation and copy.
    
    TV mode names used to contain the signalling standard along with the pixel
    size. The signalling has been moved to the TV_FORMAT property, but the
    allocation and initialization of the mode name was left a bit messy as a
    result.

diff --git a/src/i830_tv.c b/src/i830_tv.c
index aba0e3b..e3aeaf9 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -1415,10 +1415,8 @@ i830_tv_get_modes(xf86OutputPtr output)
 	    continue;
 
 	mode_ptr = xnfcalloc(1, sizeof(DisplayModeRec));
-    	mode_ptr->name = xnfalloc(strlen(tv_mode->name) + 
-				  strlen(input->name) + 4);
-	sprintf(mode_ptr->name, "%s", input->name);
-
+    	mode_ptr->name = xnfalloc(strlen(input->name) + 1);
+	strcpy (mode_ptr->name, input->name);
 
 	mode_ptr->HDisplay = hactive_s;
 	mode_ptr->HSyncStart = hactive_s + 1;
diff-tree f71b9358b4157a8cfdc694ddef8ca3f98926ca91 (from e6746d0f286ef9d9a87f748d40e5421c268f2f7d)
Author: Jesse Barnes <jesse.barnes at intel.com>
Date:   Fri Aug 10 15:53:04 2007 -0400

    Cleanup tiling and FBC driver output.
    
    Remove an extra "FBC enabled" message from i830_memory.c (only report errors
    if they occur), and don't print the "forcing FBC on" message if tiling was
    already enabled, as it's redundant and confusing.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 693e12a..6a03ff6 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2275,7 +2275,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 	   pI830->fb_compression = FALSE;
    }
 
-   if (pI830->fb_compression) {
+   if (pI830->fb_compression && !pI830->tiling) {
        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Framebuffer compression enabled, "
 		  "forcing tiling on.\n");
        pI830->tiling = TRUE;
diff --git a/src/i830_memory.c b/src/i830_memory.c
index ccd26b3..93b054c 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -1073,10 +1073,7 @@ static void i830_setup_fb_compression(Sc
     }
 
 out:
-    if (pI830->fb_compression)
-	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Framebuffer compression "
-		   "enabled\n");
-    else
+    if (!pI830->fb_compression)
 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Allocation error, framebuffer"
 		   " compression disabled\n");
 	
diff-tree e6746d0f286ef9d9a87f748d40e5421c268f2f7d (from e0fcf645a228094620b8f7fdd580963611bdd6ef)
Author: Jesse Barnes <jesse.barnes at intel.com>
Date:   Fri Aug 10 15:48:15 2007 -0400

    Enable tiling by default on 965.

diff --git a/man/intel.man b/man/intel.man
index 5909fdd..2b19711 100644
--- a/man/intel.man
+++ b/man/intel.man
@@ -85,7 +85,7 @@ Default: enabled on supported configurat
 .BI "Option \*qTiling\*q \*q" boolean \*q
 This option controls whether memory buffers are allocated in tiled mode.  In
 many cases (especially for complex rendering), tiling can improve performance.
-Default: enabled on supported configurations.
+Default: enabled.
 .TP
 .BI "Option \*qDRI\*q \*q" boolean \*q
 Disable or enable DRI support.
diff --git a/src/i830.h b/src/i830.h
index 17dfb72..f72e1d6 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -721,17 +721,8 @@ i830_get_transformed_coordinates(int x, 
 
 void i830_enter_render(ScrnInfoPtr);
 
-static inline int i830_tiling_supported(I830Ptr pI830)
-{
-    if (IS_I965G(pI830))
-	return FALSE;
-    return TRUE;
-}
-
 static inline int i830_fb_compression_supported(I830Ptr pI830)
 {
-    if (!i830_tiling_supported(pI830))
-	return FALSE;
     if (!IS_MOBILE(pI830))
 	return FALSE;
     if (IS_I810(pI830) || IS_I815(pI830) || IS_I830(pI830))
diff --git a/src/i830_driver.c b/src/i830_driver.c
index f293bfd..693e12a 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2250,11 +2250,8 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       pI830->CacheLines = -1;
    }
 
-   /* Enable tiling by default where supported */
-   if (i830_tiling_supported(pI830))
-       pI830->tiling = TRUE;
-   else
-       pI830->tiling = FALSE;
+   /* Enable tiling by default */
+   pI830->tiling = TRUE;
 
    /* Allow user override if they set a value */
    if (xf86IsOptionSet(pI830->Options, OPTION_TILING)) {
diff-tree e0fcf645a228094620b8f7fdd580963611bdd6ef (from 7b143e5c8397da077c0e02455c21c5a99cf50942)
Author: Jesse Barnes <jesse.barnes at intel.com>
Date:   Fri Aug 10 15:43:06 2007 -0400

    Tiling fixes for 965
    
    This should be close to the last set of tiling fixes for 965 chipsets.
    Prior to this commit, the 965 composite hook didn't take tiling into
    account, nor did 965 textured video, which caused display corruption.
    However, there seems to be at least one last bug to squash--on occasion,
    a configuration with tiling enabled won't properly display text.  This
    is likely another tiling related problem with the composite hook.

diff --git a/src/i830.h b/src/i830.h
index c2321d4..17dfb72 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -739,6 +739,8 @@ static inline int i830_fb_compression_su
     return TRUE;
 }
 
+Bool i830_pixmap_tiled(PixmapPtr p);
+
 extern const int I830PatternROP[16];
 extern const int I830CopyROP[16];
 
diff --git a/src/i830_display.c b/src/i830_display.c
index 6fe7be7..d5f7586 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -498,6 +498,23 @@ i830_pipe_a_require_deactivate (ScrnInfo
     return;
 }
 
+/* FIXME: use pixmap private instead if possible */
+static Bool
+i830_display_tiled(xf86CrtcPtr crtc)
+{
+    ScrnInfoPtr pScrn = crtc->scrn;
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    if (!pI830->tiling)
+	return FALSE;
+
+    /* Rotated data is currently linear, allocated either via XAA or EXA */
+    if (crtc->rotatedData)
+	return FALSE;
+
+    return TRUE;
+}
+
 static Bool
 i830_use_fb_compression(xf86CrtcPtr crtc)
 {
@@ -510,6 +527,9 @@ i830_use_fb_compression(xf86CrtcPtr crtc
     if (!pI830->fb_compression)
 	return FALSE;
 
+    if (!i830_display_tiled(crtc))
+	return FALSE;
+
     /* Pre-965 only supports plane A */
     if (!IS_I965GM(pI830) && plane != FBC_CTL_PLANEA)
 	return FALSE;
@@ -1078,7 +1098,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
     else
 	dspcntr |= DISPPLANE_SEL_PIPE_B;
 
-    if (pI830->tiling)
+    if (IS_I965G(pI830) && i830_display_tiled(crtc))
 	dspcntr |= DISPLAY_PLANE_TILED;
 
     pipeconf = INREG(pipeconf_reg);
diff --git a/src/i830_exa.c b/src/i830_exa.c
index b0029d1..023a845 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -97,8 +97,9 @@ const int I830PatternROP[16] =
     ROP_1
 };
 
-static Bool
-exaPixmapTiled(PixmapPtr p)
+/* FIXME: use pixmap private instead */
+Bool
+i830_pixmap_tiled(PixmapPtr p)
 {
     ScreenPtr pScreen = p->drawable.pScreen;
     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
@@ -189,7 +190,7 @@ I830EXASolid(PixmapPtr pPixmap, int x1, 
 	if (pPixmap->drawable.bitsPerPixel == 32)
 	    cmd |= XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB;
 
-	if (IS_I965G(pI830) && exaPixmapTiled(pPixmap)) {
+	if (IS_I965G(pI830) && i830_pixmap_tiled(pPixmap)) {
 	    assert((pitch % 512) == 0);
 	    pitch >>= 2;
 	    cmd |= XY_COLOR_BLT_TILED;
@@ -274,13 +275,13 @@ I830EXACopy(PixmapPtr pDstPixmap, int sr
 	    cmd |= XY_SRC_COPY_BLT_WRITE_ALPHA | XY_SRC_COPY_BLT_WRITE_RGB;
 
 	if (IS_I965G(pI830)) {
-	    if (exaPixmapTiled(pDstPixmap)) {
+	    if (i830_pixmap_tiled(pDstPixmap)) {
 		assert((dst_pitch % 512) == 0);
 		dst_pitch >>= 2;
 		cmd |= XY_SRC_COPY_BLT_DST_TILED;
 	    }
 
-	    if (exaPixmapTiled(pI830->pSrcPixmap)) {
+	    if (i830_pixmap_tiled(pI830->pSrcPixmap)) {
 		assert((src_pitch % 512) == 0);
 		src_pitch >>= 2;
 		cmd |= XY_SRC_COPY_BLT_SRC_TILED;
diff --git a/src/i965_render.c b/src/i965_render.c
index ec64ddd..ad3b53e 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -392,9 +392,11 @@ i965_prepare_composite(int op, PicturePt
 {
     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;
+    CARD32 src_offset, src_pitch, src_tile_format = 0, src_tiled = 0;
+    CARD32 mask_offset = 0, mask_pitch = 0, mask_tile_format = 0,
+	mask_tiled = 0;
+    CARD32 dst_format, dst_offset, dst_pitch, dst_tile_format = 0,
+	dst_tiled = 0;
     Bool rotation_program = FALSE;
 
     IntelEmitInvarientState(pScrn);
@@ -402,11 +404,23 @@ i965_prepare_composite(int op, PicturePt
 
     src_offset = intel_get_pixmap_offset(pSrc);
     src_pitch = intel_get_pixmap_pitch(pSrc);
+    if (i830_pixmap_tiled(pSrc)) {
+	src_tiled = 1;
+	src_tile_format = 0; /* Tiled X */
+    }
     dst_offset = intel_get_pixmap_offset(pDst);
     dst_pitch = intel_get_pixmap_pitch(pDst);
+    if (i830_pixmap_tiled(pDst)) {
+	dst_tiled = 1;
+	dst_tile_format = 0; /* Tiled X */
+    }
     if (pMask) {
 	mask_offset = intel_get_pixmap_offset(pMask);
 	mask_pitch = intel_get_pixmap_pitch(pMask);
+	if (i830_pixmap_tiled(pMask)) {
+	    mask_tiled = 1;
+	    mask_tile_format = 0; /* Tiled X */
+	}
     }
     pI830->scale_units[0][0] = pSrc->drawable.width;
     pI830->scale_units[0][1] = pSrc->drawable.height;
@@ -634,6 +648,8 @@ i965_prepare_composite(int op, PicturePt
     dest_surf_state->ss2.mip_count = 0;
     dest_surf_state->ss2.render_target_rotation = 0;
     dest_surf_state->ss3.pitch = dst_pitch - 1;
+    dest_surf_state->ss3.tile_walk = dst_tile_format;
+    dest_surf_state->ss3.tiled_surface = dst_tiled;
 
     dest_surf_state = (void *)(state_base + dest_surf_offset);
     memcpy (dest_surf_state, &dest_surf_state_local, sizeof (dest_surf_state_local));
@@ -660,6 +676,8 @@ i965_prepare_composite(int op, PicturePt
     src_surf_state->ss2.mip_count = 0;
     src_surf_state->ss2.render_target_rotation = 0;
     src_surf_state->ss3.pitch = src_pitch - 1;
+    src_surf_state->ss3.tile_walk = src_tile_format;
+    src_surf_state->ss3.tiled_surface = src_tiled;
 
     src_surf_state = (void *)(state_base + src_surf_offset);
     memcpy (src_surf_state, &src_surf_state_local, sizeof (src_surf_state_local));
@@ -688,6 +706,8 @@ i965_prepare_composite(int op, PicturePt
    	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.tile_walk = mask_tile_format;
+	mask_surf_state->ss3.tiled_surface = mask_tiled;
 
 	mask_surf_state = (void *)(state_base + mask_surf_offset);
 	memcpy (mask_surf_state, &mask_surf_state_local, sizeof (mask_surf_state_local));
diff --git a/src/i965_video.c b/src/i965_video.c
index 3084233..6ed7f01 100644
--- a/src/i965_video.c
+++ b/src/i965_video.c
@@ -378,6 +378,8 @@ I965DisplayVideoTextured(ScrnInfoPtr pSc
     dest_surf_state->ss2.mip_count = 0;
     dest_surf_state->ss2.render_target_rotation = 0;
     dest_surf_state->ss3.pitch = pPixmap->devKind - 1;
+    dest_surf_state->ss3.tiled_surface = i830_pixmap_tiled(pPixmap);
+    dest_surf_state->ss3.tile_walk = 0; /* TileX */
 
     /* Set up the source surface state buffer */
     memset(src_surf_state, 0, sizeof(*src_surf_state));
@@ -408,6 +410,7 @@ I965DisplayVideoTextured(ScrnInfoPtr pSc
     src_surf_state->ss2.mip_count = 0;
     src_surf_state->ss2.render_target_rotation = 0;
     src_surf_state->ss3.pitch = video_pitch - 1;
+    /* FIXME: account for tiling if we ever do it */
 
     /* Set up a binding table for our two surfaces.  Only the PS will use it */
     /* XXX: are these offset from the right place? */
diff-tree 7b143e5c8397da077c0e02455c21c5a99cf50942 (from 14691b24da5aa29d8c41ac7b7c61828e3cd9eab7)
Author: Dave Airlie <airlied at redhat.com>
Date:   Thu Aug 9 12:14:44 2007 +1000

    i965: increase composite vertex buffer size and alignment to be safe

diff --git a/src/i965_render.c b/src/i965_render.c
index 018208a..ec64ddd 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -285,7 +285,7 @@ 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 = (6 * 4) * 4 ; /* 6 DWORDS per vertex - and mask*/
 
 static CARD32 src_blend, dst_blend;
 
@@ -496,7 +496,7 @@ i965_prepare_composite(int op, PicturePt
    	next_offset = mask_sampler_offset + sizeof(*mask_sampler_state);
     }
     /* Align VB to native size of elements, for safety */
-    vb_offset = ALIGN(next_offset, 8);
+    vb_offset = ALIGN(next_offset, 32);
     next_offset = vb_offset + vb_size;
 
     /* And then the general state: */
diff-tree 14691b24da5aa29d8c41ac7b7c61828e3cd9eab7 (from 5e18c6af9051da654d2a6a97553ef4fe777bb61e)
Author: Dave Airlie <airlied at linux.ie>
Date:   Thu Aug 9 09:41:32 2007 +1000

    i965: fix memcpy of the sf_kernel when a mask is needed

diff --git a/src/i965_render.c b/src/i965_render.c
index c528813..018208a 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -793,7 +793,8 @@ i965_prepare_composite(int op, PicturePt
      * back to SF which then hands pixels off to WM.
      */
     if (pMask)
-	memcpy(sf_kernel, sf_kernel_static_mask, sizeof (sf_kernel_static));
+	memcpy(sf_kernel, sf_kernel_static_mask,
+		sizeof (sf_kernel_static_mask));
     else if (rotation_program)
 	memcpy(sf_kernel, sf_kernel_static_rotation, 
 		sizeof (sf_kernel_static_rotation));
diff-tree 5e18c6af9051da654d2a6a97553ef4fe777bb61e (from b0ec670cdb0b6ca6fc0f4f165fa3ee5a20d7c985)
Author: Carl Worth <cworth at cworth.org>
Date:   Wed Aug 8 11:13:37 2007 -0700

    Allow 965 composite acceleration to A8 destinations.
    
    Note that this is a slowdown in text rendering due to the high overhead of our
    compositing setup, but appears to be correct according to rendercheck.

diff --git a/src/i965_render.c b/src/i965_render.c
index 744501a..c528813 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -161,16 +161,9 @@ static Bool i965_get_dest_format(Picture
     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;
+        *dst_format = BRW_SURFACEFORMAT_A8_UNORM;
         break;
-    */
     case PICT_a4r4g4b4:
     case PICT_x4r4g4b4:
 	*dst_format = BRW_SURFACEFORMAT_B4G4R4A4_UNORM;
diff-tree b0ec670cdb0b6ca6fc0f4f165fa3ee5a20d7c985 (from 92af2f4bbcb395cbde097776718449d99843ad67)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Aug 8 11:03:51 2007 -0700

    Bug #11593: Remove dead struct vch_bdb_20 which was angering the sun compiler.

diff --git a/src/i830_bios.h b/src/i830_bios.h
index cb7666e..9e8356a 100644
--- a/src/i830_bios.h
+++ b/src/i830_bios.h
@@ -130,9 +130,6 @@ struct aimdb_block {
     CARD16  aimdb_size;
 } __attribute__((packed));
 
-struct vch_bdb_20 {
-} __attribute__((packed));
-
 struct vch_panel_data {
     CARD16	fp_timing_offset;
     CARD8	fp_timing_size;
diff-tree 92af2f4bbcb395cbde097776718449d99843ad67 (from parents)
Merge: da82a47a558597f3653e2b33bc6adbab18574b57 e0be352f5017f0e645a4ff8a40961d9c2b98863a
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Aug 7 15:18:17 2007 -0700

    Merge branch 'origin'
    
    Conflicts:
    
    	src/i830_exa.c

diff-tree da82a47a558597f3653e2b33bc6adbab18574b57 (from 3510d5728fa972b36d022b4f9189d46ff98d7b16)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Aug 6 17:01:37 2007 -0700

    Fix EXA rendering with tiled front buffer on pre-965.
    
    The 915 and earlier appear to respect the fence registers, while only the 965
    requires the per-operation tiling setting and pitch shifting.  This will also
    fix issues with rendering on the 965 involving multiple cliprects, where the
    pitch would get divided repeatedly.
    
    This removes the offset < 4096 fallback, which essentially resulted in no
    acceleration to tiled buffers, hiding the issues.

diff --git a/src/i830.h b/src/i830.h
index 64a3690..c2321d4 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -405,10 +405,8 @@ typedef struct _I830Rec {
    CloseScreenProcPtr CloseScreen;
 
 #ifdef I830_USE_EXA
-   unsigned int copy_src_pitch;
-   unsigned int copy_src_off;
-   unsigned int copy_src_tiled;
    ExaDriverPtr	EXADriverPtr;
+   PixmapPtr pSrcPixmap;
 #endif
 
    I830WriteIndexedByteFunc writeControl;
diff --git a/src/i830_exa.c b/src/i830_exa.c
index 19f4e30..b0029d1 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -152,10 +152,8 @@ I830EXAPrepareSolid(PixmapPtr pPixmap, i
 	I830FALLBACK("pixmap offset not aligned");
     if (pitch % pI830->EXADriverPtr->pixmapPitchAlign != 0)
 	I830FALLBACK("pixmap pitch not aligned");
-    if (exaPixmapTiled(pPixmap) && offset > 4096)
-	I830FALLBACK("offset limited to 4k for tiled targets");
 
-    pI830->BR[13] = (pitch & 0xffff);
+    pI830->BR[13] = (I830PatternROP[alu] & 0xff) << 16 ;
     switch (pPixmap->drawable.bitsPerPixel) {
 	case 8:
 	    break;
@@ -168,7 +166,6 @@ I830EXAPrepareSolid(PixmapPtr pPixmap, i
 	    pI830->BR[13] |= ((1 << 24) | (1 << 25));
 	    break;
     }
-    pI830->BR[13] |= (I830PatternROP[alu] & 0xff) << 16 ;
     pI830->BR[16] = fg;
     return TRUE;
 }
@@ -178,10 +175,11 @@ I830EXASolid(PixmapPtr pPixmap, int x1, 
 {
     ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
-    unsigned long offset;
+    unsigned long offset, pitch;
     uint32_t cmd;
 
     offset = exaGetPixmapOffset(pPixmap);
+    pitch = exaGetPixmapPitch(pPixmap);
 
     {
 	BEGIN_LP_RING(6);
@@ -191,16 +189,15 @@ I830EXASolid(PixmapPtr pPixmap, int x1, 
 	if (pPixmap->drawable.bitsPerPixel == 32)
 	    cmd |= XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB;
 
-	if (exaPixmapTiled(pPixmap)) {
-	    /* Fixup pitch for destination if tiled */
-	    pI830->BR[13] = (ROUND_TO(pI830->BR[13] & 0xffff, 512) >> 2) |
-		(pI830->BR[13] & 0xffff0000);
+	if (IS_I965G(pI830) && exaPixmapTiled(pPixmap)) {
+	    assert((pitch % 512) == 0);
+	    pitch >>= 2;
 	    cmd |= XY_COLOR_BLT_TILED;
 	}
 
 	OUT_RING(cmd);
 
-	OUT_RING(pI830->BR[13]);
+	OUT_RING(pI830->BR[13] | pitch);
 	OUT_RING((y1 << 16) | (x1 & 0xffff));
 	OUT_RING((y2 << 16) | (x2 & 0xffff));
 	OUT_RING(offset);
@@ -233,17 +230,9 @@ I830EXAPrepareCopy(PixmapPtr pSrcPixmap,
     if (!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planemask))
 	I830FALLBACK("planemask is not solid");
 
-    pI830->copy_src_pitch = exaGetPixmapPitch(pSrcPixmap);
-    pI830->copy_src_off = exaGetPixmapOffset(pSrcPixmap);
-    pI830->copy_src_tiled = exaPixmapTiled(pSrcPixmap);
-
-    if (pI830->copy_src_tiled && pI830->copy_src_off > 4096)
-	I830FALLBACK("offset limited to 4k for tiled targets");
-    if (exaPixmapTiled(pDstPixmap) && exaGetPixmapOffset(pDstPixmap) > 4096)
-	I830FALLBACK("offset limited to 4k for tiled targets");
+    pI830->pSrcPixmap = pSrcPixmap;
 
-    pI830->BR[13] = exaGetPixmapPitch(pDstPixmap);
-    pI830->BR[13] |= I830CopyROP[alu] << 16;
+    pI830->BR[13] = I830CopyROP[alu] << 16;
 
     switch (pSrcPixmap->drawable.bitsPerPixel) {
     case 8:
@@ -266,12 +255,15 @@ I830EXACopy(PixmapPtr pDstPixmap, int sr
     I830Ptr pI830 = I830PTR(pScrn);
     uint32_t cmd;
     int dst_x2, dst_y2;
-    unsigned int dst_off;
+    unsigned int dst_off, dst_pitch, src_off, src_pitch;
 
     dst_x2 = dst_x1 + w;
     dst_y2 = dst_y1 + h;
 
     dst_off = exaGetPixmapOffset(pDstPixmap);
+    dst_pitch = exaGetPixmapPitch(pDstPixmap);
+    src_off = exaGetPixmapOffset(pI830->pSrcPixmap);
+    src_pitch = exaGetPixmapPitch(pI830->pSrcPixmap);
 
     {
 	BEGIN_LP_RING(8);
@@ -281,29 +273,29 @@ I830EXACopy(PixmapPtr pDstPixmap, int sr
 	if (pDstPixmap->drawable.bitsPerPixel == 32)
 	    cmd |= XY_SRC_COPY_BLT_WRITE_ALPHA | XY_SRC_COPY_BLT_WRITE_RGB;
 
-	if (exaPixmapTiled(pDstPixmap)) {
-	    /* Fixup pitch for destination if tiled */
-	    pI830->BR[13] = (ROUND_TO(pI830->BR[13] & 0xffff, 512) >> 2) |
-		(pI830->BR[13] & 0xffff0000);
-	    cmd |= XY_SRC_COPY_BLT_DST_TILED;
-	}
+	if (IS_I965G(pI830)) {
+	    if (exaPixmapTiled(pDstPixmap)) {
+		assert((dst_pitch % 512) == 0);
+		dst_pitch >>= 2;
+		cmd |= XY_SRC_COPY_BLT_DST_TILED;
+	    }
 
-	if (pI830->copy_src_tiled) {
-	    pI830->copy_src_pitch =
-		(ROUND_TO(pI830->copy_src_pitch & 0xffff, 512) >> 2) |
-		(pI830->copy_src_pitch & 0xffff0000);
-	    cmd |= XY_SRC_COPY_BLT_SRC_TILED;
+	    if (exaPixmapTiled(pI830->pSrcPixmap)) {
+		assert((src_pitch % 512) == 0);
+		src_pitch >>= 2;
+		cmd |= XY_SRC_COPY_BLT_SRC_TILED;
+	    }
 	}
 
 	OUT_RING(cmd);
 
-	OUT_RING(pI830->BR[13]);
+	OUT_RING(pI830->BR[13] | dst_pitch);
 	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(pI830->copy_src_off);
+	OUT_RING(src_pitch);
+	OUT_RING(src_off);
 
 	ADVANCE_LP_RING();
     }
diff --git a/src/i830_xaa.c b/src/i830_xaa.c
index ec8a879..aa06a80 100644
--- a/src/i830_xaa.c
+++ b/src/i830_xaa.c
@@ -126,7 +126,6 @@ I830XAAInit(ScreenPtr pScreen)
     if (!infoPtr)
 	return FALSE;
 
-    pI830->bufferOffset = 0;
     infoPtr->Flags = LINEAR_FRAMEBUFFER | OFFSCREEN_PIXMAPS | PIXMAP_CACHE;
 
     /* Use the same sync function as the I830.
@@ -235,6 +234,7 @@ I830XAAInit(ScreenPtr pScreen)
 	    infoPtr->RestoreAccelState = I830RestoreAccelState;
     }
 
+    /* Set up pI830->bufferOffset */
     I830SelectBuffer(pScrn, I830_SELECT_FRONT);
 
     if (!XAAInit(pScreen, infoPtr))
diff-tree e0be352f5017f0e645a4ff8a40961d9c2b98863a (from 7431abee5fb971d1f8bc7ac4bea137f6ece9418b)
Author: Jesse Barnes <jesse.barnes at intel.com>
Date:   Tue Aug 7 12:37:25 2007 -0700

    Fixup pitch in Prepare* functions, since actual hooks may
    be called many times for the same pixmap, and we don't want
    to keep dividing the pitch by 4.

diff --git a/src/i830_exa.c b/src/i830_exa.c
index ed57605..3486537 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -153,6 +153,8 @@ I830EXAPrepareSolid(PixmapPtr pPixmap, i
     if ( pitch % pI830->EXADriverPtr->pixmapPitchAlign != 0)
 	I830FALLBACK("pixmap pitch not aligned");
 
+    if (exaPixmapTiled(pPixmap))
+	pitch /= 4;
     pI830->BR[13] = (pitch & 0xffff);
     switch (pPixmap->drawable.bitsPerPixel) {
 	case 8:
@@ -189,12 +191,8 @@ I830EXASolid(PixmapPtr pPixmap, int x1, 
 	if (pPixmap->drawable.bitsPerPixel == 32)
 	    cmd |= XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB;
 
-	if (exaPixmapTiled(pPixmap)) {
-	    /* Fixup pitch for destination if tiled */
-	    pI830->BR[13] = ((pI830->BR[13] & 0xffff) >> 2) |
-		(pI830->BR[13] & 0xffff0000);
+	if (exaPixmapTiled(pPixmap))
 	    cmd |= XY_COLOR_BLT_TILED;
-	}
 
 	OUT_RING(cmd);
 
@@ -232,10 +230,16 @@ I830EXAPrepareCopy(PixmapPtr pSrcPixmap,
 	I830FALLBACK("planemask is not solid");
 
     pI830->copy_src_pitch = exaGetPixmapPitch(pSrcPixmap);
+    if (exaPixmapTiled(pSrcPixmap))
+	pI830->copy_src_pitch /= 4;
+
     pI830->copy_src_off = exaGetPixmapOffset(pSrcPixmap);
     pI830->copy_src_tiled = exaPixmapTiled(pSrcPixmap);
 
     pI830->BR[13] = exaGetPixmapPitch(pDstPixmap);
+    if (exaPixmapTiled(pDstPixmap))
+	pI830->BR[13] /= 4;
+
     pI830->BR[13] |= I830CopyROP[alu] << 16;
 
     switch (pSrcPixmap->drawable.bitsPerPixel) {
@@ -274,17 +278,11 @@ I830EXACopy(PixmapPtr pDstPixmap, int sr
 	if (pDstPixmap->drawable.bitsPerPixel == 32)
 	    cmd |= XY_SRC_COPY_BLT_WRITE_ALPHA | XY_SRC_COPY_BLT_WRITE_RGB;
 
-	if (exaPixmapTiled(pDstPixmap)) {
-	    /* Fixup pitch for destination if tiled */
-	    pI830->BR[13] = ((pI830->BR[13] & 0xffff) >> 2) |
-		(pI830->BR[13] & 0xffff0000);
+	if (exaPixmapTiled(pDstPixmap))
 	    cmd |= XY_SRC_COPY_BLT_DST_TILED;
-	}
 
-	if (pI830->copy_src_tiled) {
-	    pI830->copy_src_pitch >>= 2;
+	if (pI830->copy_src_tiled)
 	    cmd |= XY_SRC_COPY_BLT_SRC_TILED;
-	}
 
 	OUT_RING(cmd);
 
diff-tree 7431abee5fb971d1f8bc7ac4bea137f6ece9418b (from 9e1914270a0978ec4dfae757d3dd57ca7ffe17e5)
Author: Brice Goglin <bgoglin at debian.org>
Date:   Tue Aug 7 09:13:00 2007 +0200

    Define INTEL_VERSION_MAJOR/MINOR/PATCH using PACKAGE_VERSION_*

diff --git a/configure.ac b/configure.ac
index 9b76b65..8c2b5ec 100644
--- a/configure.ac
+++ b/configure.ac
@@ -26,16 +26,6 @@ AC_INIT([xf86-video-intel],
         [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
         xf86-video-intel)
 
-AC_DEFINE_UNQUOTED([INTEL_VERSION_MAJOR],
-		   [$(echo $PACKAGE_VERSION | sed -e 's/^\([[0-9]]*\)\.[[0-9]]*\.[[0-9]]*/\1/')],
-		   [Major version])
-AC_DEFINE_UNQUOTED([INTEL_VERSION_MINOR],
-		   [$(echo $PACKAGE_VERSION | sed -e 's/^[[0-9]]*\.\([[0-9]]*\)\.[[0-9]]*/\1/')],
-		   [Minor version])
-AC_DEFINE_UNQUOTED([INTEL_VERSION_PATCH],
-		   [$(echo $PACKAGE_VERSION | sed -e 's/^[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)/\1/')],
-		   [Patch version])
-
 AC_CONFIG_SRCDIR([Makefile.am])
 AM_CONFIG_HEADER([config.h])
 AC_CONFIG_AUX_DIR(.)
diff --git a/src/i810.h b/src/i810.h
index 614de52..ff9134e 100644
--- a/src/i810.h
+++ b/src/i810.h
@@ -66,6 +66,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define I810_DRIVER_NAME "intel"
 #define I810_LEGACY_DRIVER_NAME "i810"
 
+#define INTEL_VERSION_MAJOR PACKAGE_VERSION_MAJOR
+#define INTEL_VERSION_MINOR PACKAGE_VERSION_MINOR
+#define INTEL_VERSION_PATCH PACKAGE_VERSION_PATCHLEVEL
+
 /* HWMC Surfaces */
 #define I810_MAX_SURFACES 7
 #define I810_MAX_SUBPICTURES 2
diff-tree 9e1914270a0978ec4dfae757d3dd57ca7ffe17e5 (from 5ff05dffe229e35da7619762628fdd0f125585e8)
Author: Jesse Barnes <jesse.barnes at intel.com>
Date:   Mon Aug 6 17:55:00 2007 -0700

    Remove 4k offset checks from Copy & Solid hooks.
    Reading the docs too literally can cause you to hide bugs with false fixes...

diff --git a/src/i830_exa.c b/src/i830_exa.c
index 0e9cd5b..ed57605 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -152,8 +152,6 @@ I830EXAPrepareSolid(PixmapPtr pPixmap, i
 	I830FALLBACK("pixmap offset not aligned");
     if ( pitch % pI830->EXADriverPtr->pixmapPitchAlign != 0)
 	I830FALLBACK("pixmap pitch not aligned");
-    if ( exaPixmapTiled(pPixmap) && offset > 4096)
-	I830FALLBACK("offset limited to 4k for tiled targets");
 
     pI830->BR[13] = (pitch & 0xffff);
     switch (pPixmap->drawable.bitsPerPixel) {
@@ -193,7 +191,7 @@ I830EXASolid(PixmapPtr pPixmap, int x1, 
 
 	if (exaPixmapTiled(pPixmap)) {
 	    /* Fixup pitch for destination if tiled */
-	    pI830->BR[13] = (ROUND_TO(pI830->BR[13] & 0xffff, 512) >> 2) | 
+	    pI830->BR[13] = ((pI830->BR[13] & 0xffff) >> 2) |
 		(pI830->BR[13] & 0xffff0000);
 	    cmd |= XY_COLOR_BLT_TILED;
 	}
@@ -237,12 +235,6 @@ I830EXAPrepareCopy(PixmapPtr pSrcPixmap,
     pI830->copy_src_off = exaGetPixmapOffset(pSrcPixmap);
     pI830->copy_src_tiled = exaPixmapTiled(pSrcPixmap);
 
-    if (pI830->copy_src_tiled && pI830->copy_src_off > 4096)
-	I830FALLBACK("offset limited to 4k for tiled targets");
-    if (exaPixmapTiled(pDstPixmap) &&
-	exaGetPixmapOffset(pDstPixmap) > 4096)
-	I830FALLBACK("offset limited to 4k for tiled targets");
-
     pI830->BR[13] = exaGetPixmapPitch(pDstPixmap);
     pI830->BR[13] |= I830CopyROP[alu] << 16;
 
@@ -284,15 +276,13 @@ I830EXACopy(PixmapPtr pDstPixmap, int sr
 
 	if (exaPixmapTiled(pDstPixmap)) {
 	    /* Fixup pitch for destination if tiled */
-	    pI830->BR[13] = (ROUND_TO(pI830->BR[13] & 0xffff, 512) >> 2) | 
+	    pI830->BR[13] = ((pI830->BR[13] & 0xffff) >> 2) |
 		(pI830->BR[13] & 0xffff0000);
 	    cmd |= XY_SRC_COPY_BLT_DST_TILED;
 	}
 
 	if (pI830->copy_src_tiled) {
-	    pI830->copy_src_pitch =
-		(ROUND_TO(pI830->copy_src_pitch & 0xffff, 512) >> 2) | 
-		(pI830->copy_src_pitch & 0xffff0000);
+	    pI830->copy_src_pitch >>= 2;
 	    cmd |= XY_SRC_COPY_BLT_SRC_TILED;
 	}
 
diff-tree 3510d5728fa972b36d022b4f9189d46ff98d7b16 (from 5ff05dffe229e35da7619762628fdd0f125585e8)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Aug 6 16:44:39 2007 -0700

    Fix accumulated whitespace nits in i830_exa.c

diff --git a/src/i830_exa.c b/src/i830_exa.c
index 0e9cd5b..19f4e30 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -54,7 +54,7 @@ do {							\
 #define I830FALLBACK(s, arg...) 			\
 do { 							\
 	return FALSE;					\
-} while(0) 
+} while(0)
 #endif
 
 const int I830CopyROP[16] =
@@ -148,11 +148,11 @@ I830EXAPrepareSolid(PixmapPtr pPixmap, i
     offset = exaGetPixmapOffset(pPixmap);
     pitch = exaGetPixmapPitch(pPixmap);
 
-    if ( offset % pI830->EXADriverPtr->pixmapOffsetAlign != 0)
+    if (offset % pI830->EXADriverPtr->pixmapOffsetAlign != 0)
 	I830FALLBACK("pixmap offset not aligned");
-    if ( pitch % pI830->EXADriverPtr->pixmapPitchAlign != 0)
+    if (pitch % pI830->EXADriverPtr->pixmapPitchAlign != 0)
 	I830FALLBACK("pixmap pitch not aligned");
-    if ( exaPixmapTiled(pPixmap) && offset > 4096)
+    if (exaPixmapTiled(pPixmap) && offset > 4096)
 	I830FALLBACK("offset limited to 4k for tiled targets");
 
     pI830->BR[13] = (pitch & 0xffff);
@@ -181,8 +181,8 @@ I830EXASolid(PixmapPtr pPixmap, int x1, 
     unsigned long offset;
     uint32_t cmd;
 
-    offset = exaGetPixmapOffset(pPixmap);  
-    
+    offset = exaGetPixmapOffset(pPixmap);
+
     {
 	BEGIN_LP_RING(6);
 
@@ -193,7 +193,7 @@ I830EXASolid(PixmapPtr pPixmap, int x1, 
 
 	if (exaPixmapTiled(pPixmap)) {
 	    /* Fixup pitch for destination if tiled */
-	    pI830->BR[13] = (ROUND_TO(pI830->BR[13] & 0xffff, 512) >> 2) | 
+	    pI830->BR[13] = (ROUND_TO(pI830->BR[13] & 0xffff, 512) >> 2) |
 		(pI830->BR[13] & 0xffff0000);
 	    cmd |= XY_COLOR_BLT_TILED;
 	}
@@ -239,8 +239,7 @@ I830EXAPrepareCopy(PixmapPtr pSrcPixmap,
 
     if (pI830->copy_src_tiled && pI830->copy_src_off > 4096)
 	I830FALLBACK("offset limited to 4k for tiled targets");
-    if (exaPixmapTiled(pDstPixmap) &&
-	exaGetPixmapOffset(pDstPixmap) > 4096)
+    if (exaPixmapTiled(pDstPixmap) && exaGetPixmapOffset(pDstPixmap) > 4096)
 	I830FALLBACK("offset limited to 4k for tiled targets");
 
     pI830->BR[13] = exaGetPixmapPitch(pDstPixmap);
@@ -284,14 +283,14 @@ I830EXACopy(PixmapPtr pDstPixmap, int sr
 
 	if (exaPixmapTiled(pDstPixmap)) {
 	    /* Fixup pitch for destination if tiled */
-	    pI830->BR[13] = (ROUND_TO(pI830->BR[13] & 0xffff, 512) >> 2) | 
+	    pI830->BR[13] = (ROUND_TO(pI830->BR[13] & 0xffff, 512) >> 2) |
 		(pI830->BR[13] & 0xffff0000);
 	    cmd |= XY_SRC_COPY_BLT_DST_TILED;
 	}
 
 	if (pI830->copy_src_tiled) {
 	    pI830->copy_src_pitch =
-		(ROUND_TO(pI830->copy_src_pitch & 0xffff, 512) >> 2) | 
+		(ROUND_TO(pI830->copy_src_pitch & 0xffff, 512) >> 2) |
 		(pI830->copy_src_pitch & 0xffff0000);
 	    cmd |= XY_SRC_COPY_BLT_SRC_TILED;
 	}
@@ -460,11 +459,12 @@ I830EXAInit(ScreenPtr pScreen)
 	pI830->exa_offscreen->size;
     pI830->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS;
 
-    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);
+    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);
 
 
     /* Limits are described in the BLT engine chapter under Graphics Data Size
diff-tree 5ff05dffe229e35da7619762628fdd0f125585e8 (from ba90d944329dd8c79a757c38128964fbbe4ab898)
Author: Jesse Barnes <jesse.barnes at intel.com>
Date:   Mon Aug 6 16:01:10 2007 -0700

    More tiled rendering fixes: - check for tiling, not just offset in PrepareSolid - combine pI830->tiling and frontbuffer checks into new exaPixmapTiled function for readability

diff --git a/src/i830_exa.c b/src/i830_exa.c
index 88853a7..0e9cd5b 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -98,9 +98,14 @@ const int I830PatternROP[16] =
 };
 
 static Bool
-exaPixmapInFrontbuffer(PixmapPtr p)
+exaPixmapTiled(PixmapPtr p)
 {
     ScreenPtr pScreen = p->drawable.pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    if (!pI830->tiling)
+	return FALSE;
 
     if (p == pScreen->GetScreenPixmap(pScreen))
 	return TRUE;
@@ -147,7 +152,7 @@ I830EXAPrepareSolid(PixmapPtr pPixmap, i
 	I830FALLBACK("pixmap offset not aligned");
     if ( pitch % pI830->EXADriverPtr->pixmapPitchAlign != 0)
 	I830FALLBACK("pixmap pitch not aligned");
-    if ( pI830->tiling && offset > 4096)
+    if ( exaPixmapTiled(pPixmap) && offset > 4096)
 	I830FALLBACK("offset limited to 4k for tiled targets");
 
     pI830->BR[13] = (pitch & 0xffff);
@@ -186,7 +191,7 @@ I830EXASolid(PixmapPtr pPixmap, int x1, 
 	if (pPixmap->drawable.bitsPerPixel == 32)
 	    cmd |= XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB;
 
-	if (pI830->tiling && exaPixmapInFrontbuffer(pPixmap)) {
+	if (exaPixmapTiled(pPixmap)) {
 	    /* Fixup pitch for destination if tiled */
 	    pI830->BR[13] = (ROUND_TO(pI830->BR[13] & 0xffff, 512) >> 2) | 
 		(pI830->BR[13] & 0xffff0000);
@@ -230,12 +235,11 @@ I830EXAPrepareCopy(PixmapPtr pSrcPixmap,
 
     pI830->copy_src_pitch = exaGetPixmapPitch(pSrcPixmap);
     pI830->copy_src_off = exaGetPixmapOffset(pSrcPixmap);
-    pI830->copy_src_tiled = (pI830->tiling &&
-			     exaPixmapInFrontbuffer(pSrcPixmap));
+    pI830->copy_src_tiled = exaPixmapTiled(pSrcPixmap);
 
     if (pI830->copy_src_tiled && pI830->copy_src_off > 4096)
 	I830FALLBACK("offset limited to 4k for tiled targets");
-    if (pI830->tiling && exaPixmapInFrontbuffer(pDstPixmap) &&
+    if (exaPixmapTiled(pDstPixmap) &&
 	exaGetPixmapOffset(pDstPixmap) > 4096)
 	I830FALLBACK("offset limited to 4k for tiled targets");
 
@@ -278,7 +282,7 @@ I830EXACopy(PixmapPtr pDstPixmap, int sr
 	if (pDstPixmap->drawable.bitsPerPixel == 32)
 	    cmd |= XY_SRC_COPY_BLT_WRITE_ALPHA | XY_SRC_COPY_BLT_WRITE_RGB;
 
-	if (pI830->tiling && exaPixmapInFrontbuffer(pDstPixmap)) {
+	if (exaPixmapTiled(pDstPixmap)) {
 	    /* Fixup pitch for destination if tiled */
 	    pI830->BR[13] = (ROUND_TO(pI830->BR[13] & 0xffff, 512) >> 2) | 
 		(pI830->BR[13] & 0xffff0000);
diff-tree ba90d944329dd8c79a757c38128964fbbe4ab898 (from 322a163cfbda885adc6bb09c1f976d36617ea83b)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Aug 3 16:46:09 2007 -0700

    Add the file mode for bios_dumper output so it doesn't have 000 permissions.

diff --git a/src/bios_reader/bios_dumper.c b/src/bios_reader/bios_dumper.c
index c0dbdcf..6f163d5 100644
--- a/src/bios_reader/bios_dumper.c
+++ b/src/bios_reader/bios_dumper.c
@@ -29,6 +29,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <stdarg.h>
+#include <sys/stat.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <pciaccess.h>
@@ -80,7 +81,7 @@ int main(int argc, char **argv)
 	exit(1);
     }
 
-    fd = open(argv[1], O_RDWR | O_CREAT | O_TRUNC);
+    fd = open(argv[1], O_RDWR | O_CREAT | O_TRUNC, DEFFILEMODE);
     if (fd < 0) {
 	fprintf(stderr, "Couldn't open output: %s\n", strerror(errno));
 	exit(1);
diff-tree 322a163cfbda885adc6bb09c1f976d36617ea83b (from ffbab2ee5dc227b2a8a5ffd1717ae00e8e37f956)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Aug 3 10:46:39 2007 -0700

    Quirk away the nonexistent TV connector on the Panasonic CF-Y4.

diff --git a/src/i830_quirks.c b/src/i830_quirks.c
index e209fea..b75baef 100644
--- a/src/i830_quirks.c
+++ b/src/i830_quirks.c
@@ -57,6 +57,8 @@ static void quirk_mac_mini (I830Ptr pI83
 static i830_quirk i830_quirk_list[] = {
     /* Lenovo T61 has no TV output */
     { PCI_CHIP_I965_GM, 0x17aa, 0x20b5, quirk_ignore_tv },
+    /* Panasonic Toughbook CF-Y4 has no TV output */
+    { PCI_CHIP_I915_GM, 0x10f7, 0x8338, quirk_ignore_tv },
     /* Lenovo 3000 v200 */
     { PCI_CHIP_I965_GM, 0x17aa, 0x3c18, quirk_ignore_tv },
     /* Aopen mini pc */
diff-tree ffbab2ee5dc227b2a8a5ffd1717ae00e8e37f956 (from 019dbfda294aaafb28d8bea0fe2f5dadc2ea3e0b)
Author: Jesse Barnes <jesse.barnes at intel.com>
Date:   Fri Aug 3 21:27:52 2007 -0700

    Limit Solid & Copy offsets to 4k when rendering to tiled targets

diff --git a/src/i830_exa.c b/src/i830_exa.c
index 5da153e..88853a7 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -147,6 +147,8 @@ I830EXAPrepareSolid(PixmapPtr pPixmap, i
 	I830FALLBACK("pixmap offset not aligned");
     if ( pitch % pI830->EXADriverPtr->pixmapPitchAlign != 0)
 	I830FALLBACK("pixmap pitch not aligned");
+    if ( pI830->tiling && offset > 4096)
+	I830FALLBACK("offset limited to 4k for tiled targets");
 
     pI830->BR[13] = (pitch & 0xffff);
     switch (pPixmap->drawable.bitsPerPixel) {
@@ -231,6 +233,12 @@ I830EXAPrepareCopy(PixmapPtr pSrcPixmap,
     pI830->copy_src_tiled = (pI830->tiling &&
 			     exaPixmapInFrontbuffer(pSrcPixmap));
 
+    if (pI830->copy_src_tiled && pI830->copy_src_off > 4096)
+	I830FALLBACK("offset limited to 4k for tiled targets");
+    if (pI830->tiling && exaPixmapInFrontbuffer(pDstPixmap) &&
+	exaGetPixmapOffset(pDstPixmap) > 4096)
+	I830FALLBACK("offset limited to 4k for tiled targets");
+
     pI830->BR[13] = exaGetPixmapPitch(pDstPixmap);
     pI830->BR[13] |= I830CopyROP[alu] << 16;
 
diff-tree 019dbfda294aaafb28d8bea0fe2f5dadc2ea3e0b (from parents)
Merge: 3d3c0e8c55f639a501c0756948b518abd903d7d0 15f71edba37738f8ba279fa07452fda10cc65298
Author: Jesse Barnes <jesse.barnes at intel.com>
Date:   Fri Aug 3 20:45:14 2007 -0700

    Merge branch 'master' of ssh://git.freedesktop.org/git/xorg/driver/xf86-video-intel

diff-tree 3d3c0e8c55f639a501c0756948b518abd903d7d0 (from 0da4f2b0cd7203377ad10407928a367b8c6d310e)
Author: Jesse Barnes <jesse.barnes at intel.com>
Date:   Fri Aug 3 20:40:45 2007 -0700

    Tiled rendering & fbc fixes:
      - actually enable tiling in DSP(A|B)CNTR if needed
      - add logic to EXA routines for tiled case (still needs work)
      - enable/disable fbc on DPMS events (meant moving functions higher in file)
      - fix fence register pitch programming (use correct pitch instead of kludged value)

diff --git a/src/i810_reg.h b/src/i810_reg.h
index d1fed22..03e10d6 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -2029,6 +2029,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define DSPBCNTR		0x71180
 #define DISPLAY_PLANE_ENABLE 			(1<<31)
 #define DISPLAY_PLANE_DISABLE			0
+#define DISPLAY_PLANE_TILED			(1<<10)
 #define DISPPLANE_GAMMA_ENABLE			(1<<30)
 #define DISPPLANE_GAMMA_DISABLE			0
 #define DISPPLANE_PIXFORMAT_MASK		(0xf<<26)
@@ -2168,12 +2169,15 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define XY_COLOR_BLT_CMD		((2<<29)|(0x50<<22)|(0x4))
 #define XY_COLOR_BLT_WRITE_ALPHA	(1<<21)
 #define XY_COLOR_BLT_WRITE_RGB		(1<<20)
+#define XY_COLOR_BLT_TILED		(1<<11)
 
 #define XY_SETUP_CLIP_BLT_CMD		((2<<29)|(3<<22)|1)
 
 #define XY_SRC_COPY_BLT_CMD		((2<<29)|(0x53<<22)|6)
 #define XY_SRC_COPY_BLT_WRITE_ALPHA	(1<<21)
 #define XY_SRC_COPY_BLT_WRITE_RGB	(1<<20)
+#define XY_SRC_COPY_BLT_SRC_TILED	(1<<15)
+#define XY_SRC_COPY_BLT_DST_TILED	(1<<11)
 
 #define SRC_COPY_BLT_CMD		((2<<29)|(0x43<<22)|0x4)
 #define SRC_COPY_BLT_WRITE_ALPHA	(1<<21)
diff --git a/src/i830.h b/src/i830.h
index a8de0e6..64a3690 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -407,6 +407,7 @@ typedef struct _I830Rec {
 #ifdef I830_USE_EXA
    unsigned int copy_src_pitch;
    unsigned int copy_src_off;
+   unsigned int copy_src_tiled;
    ExaDriverPtr	EXADriverPtr;
 #endif
 
diff --git a/src/i830_display.c b/src/i830_display.c
index 26873fe..6fe7be7 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -498,6 +498,123 @@ i830_pipe_a_require_deactivate (ScrnInfo
     return;
 }
 
+static Bool
+i830_use_fb_compression(xf86CrtcPtr crtc)
+{
+    ScrnInfoPtr pScrn = crtc->scrn;
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
+    int pipe = intel_crtc->pipe;
+    int plane = (pipe == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB);
+
+    if (!pI830->fb_compression)
+	return FALSE;
+
+    /* Pre-965 only supports plane A */
+    if (!IS_I965GM(pI830) && plane != FBC_CTL_PLANEA)
+	return FALSE;
+
+    /* Need 15, 16, or 32 (w/alpha) pixel format */
+    if (!(pScrn->bitsPerPixel == 16 || /* covers 15 bit mode as well */
+	  pScrn->bitsPerPixel == 32)) /* mode_set dtrt if fbc is in use */
+	return FALSE;
+
+    /*
+     * No checks for pixel multiply, incl. horizontal, or interlaced modes
+     * since they're currently unused.
+     */
+    return TRUE;
+}
+
+/*
+ * Several restrictions:
+ *   - DSP[AB]CNTR - no line duplication && no pixel multiplier
+ *   - pixel format == 15 bit, 16 bit, or 32 bit xRGB_8888
+ *   - no alpha buffer discard
+ *   - no dual wide display
+ *   - progressive mode only (DSP[AB]CNTR)
+ *   - uncompressed fb is <= 2048 in width, 0 mod 8
+ *   - uncompressed fb is <= 1536 in height, 0 mod 2
+ *   - SR display watermarks must be equal between 16bpp and 32bpp?
+ *
+ * FIXME: verify above conditions are true
+ */
+static void
+i830_enable_fb_compression(xf86CrtcPtr crtc)
+{
+    ScrnInfoPtr pScrn = crtc->scrn;
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
+    uint32_t fbc_ctl = 0;
+    unsigned long compressed_stride;
+    int pipe = intel_crtc->pipe;
+    /* FIXME: plane & pipe might not always be equal */
+    int plane = (pipe == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB);
+    unsigned long uncompressed_stride = pScrn->displayWidth * pI830->cpp;
+    unsigned long interval = 1000;
+
+    if (INREG(FBC_CONTROL) & FBC_CTL_EN) {
+	char cur_pipe = (INREG(FBC_CONTROL2) & 1) ? 'b' : 'a';
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "fbc already enabled on "
+		   "pipe %c, not enabling on pipe %c\n", cur_pipe, pipe ? 'b' :
+		   'a');
+	return;
+    }
+
+    compressed_stride = pI830->compressed_front_buffer->size /
+	FBC_LL_SIZE;
+
+    if (uncompressed_stride < compressed_stride)
+	compressed_stride = uncompressed_stride;
+
+    /* FBC_CTL wants 64B units */
+    compressed_stride = (compressed_stride / 64) - 1;
+
+    /* Set it up... */
+    /* Wait for compressing bit to clear */
+    while (INREG(FBC_STATUS) & FBC_STAT_COMPRESSING)
+	; /* nothing */
+    i830WaitForVblank(pScrn);
+    OUTREG(FBC_CFB_BASE, pI830->compressed_front_buffer->bus_addr);
+    OUTREG(FBC_LL_BASE, pI830->compressed_ll_buffer->bus_addr + 6);
+    OUTREG(FBC_CONTROL2, FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_FULL |
+	   FBC_CTL_CPU_FENCE | plane);
+
+    /* Zero buffers */
+    memset(pI830->FbBase + pI830->compressed_front_buffer->offset, 0,
+	   pI830->compressed_front_buffer->size);
+    memset(pI830->FbBase + pI830->compressed_ll_buffer->offset, 0,
+	   pI830->compressed_ll_buffer->size);
+
+    /* enable it... */
+    fbc_ctl |= FBC_CTL_EN | FBC_CTL_PERIODIC;
+    fbc_ctl |= (compressed_stride & 0xff) << FBC_CTL_STRIDE_SHIFT;
+    fbc_ctl |= (interval & 0x2fff) << FBC_CTL_INTERVAL_SHIFT;
+    fbc_ctl |= FBC_CTL_UNCOMPRESSIBLE;
+    OUTREG(FBC_CONTROL, fbc_ctl);
+
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "fbc enabled on plane %c\n", pipe ?
+	       'b' : 'a');
+}
+
+static void
+i830_disable_fb_compression(xf86CrtcPtr crtc)
+{
+    ScrnInfoPtr pScrn = crtc->scrn;
+    I830Ptr pI830 = I830PTR(pScrn);
+    uint32_t fbc_ctl;
+    char pipe = (INREG(FBC_CONTROL2) & 1) ? 'b' : 'a';
+
+    /* Disable compression */
+    fbc_ctl = INREG(FBC_CONTROL);
+    fbc_ctl &= ~FBC_CTL_EN;
+    OUTREG(FBC_CONTROL, fbc_ctl);
+
+    /* Wait for compressing bit to clear */
+    while (INREG(FBC_STATUS) & FBC_STAT_COMPRESSING)
+	; /* nothing */
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "fbc disabled on pipe %c\n", pipe);
+}
 
 /**
  * Sets the power management mode of the pipe and plane.
@@ -561,8 +678,16 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mod
 
 	/* Give the overlay scaler a chance to enable if it's on this pipe */
 	i830_crtc_dpms_video(crtc, TRUE);
+
+	/* Reenable compression if needed */
+	if (i830_use_fb_compression(crtc))
+	    i830_enable_fb_compression(crtc);
 	break;
     case DPMSModeOff:
+	/* Shut off compression if in use */
+	if (i830_use_fb_compression(crtc))
+	    i830_disable_fb_compression(crtc);
+
 	/* Give the overlay scaler a chance to disable if it's on this pipe */
 	i830_crtc_dpms_video(crtc, FALSE);
 
@@ -656,112 +781,6 @@ i830_crtc_unlock (xf86CrtcPtr crtc)
 #endif
 }
 
-static Bool
-i830_use_fb_compression(xf86CrtcPtr crtc)
-{
-    ScrnInfoPtr pScrn = crtc->scrn;
-    I830Ptr pI830 = I830PTR(pScrn);
-    I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
-    int pipe = intel_crtc->pipe;
-    int plane = (pipe == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB);
-
-    if (!pI830->fb_compression)
-	return FALSE;
-
-    /* Pre-965 only supports plane A */
-    if (!IS_I965GM(pI830) && plane != FBC_CTL_PLANEA)
-	return FALSE;
-
-    /* Need 15, 16, or 32 (w/alpha) pixel format */
-    if (!(pScrn->bitsPerPixel == 16 || /* covers 15 bit mode as well */
-	  pScrn->bitsPerPixel == 32)) /* mode_set dtrt if fbc is in use */
-	return FALSE;
-
-    /*
-     * No checks for pixel multiply, incl. horizontal, or interlaced modes
-     * since they're currently unused.
-     */
-    return TRUE;
-}
-
-/*
- * Several restrictions:
- *   - DSP[AB]CNTR - no line duplication && no pixel multiplier
- *   - pixel format == 15 bit, 16 bit, or 32 bit xRGB_8888
- *   - no alpha buffer discard
- *   - no dual wide display
- *   - progressive mode only (DSP[AB]CNTR)
- *   - uncompressed fb is <= 2048 in width, 0 mod 8
- *   - uncompressed fb is <= 1536 in height, 0 mod 2
- *   - SR display watermarks must be equal between 16bpp and 32bpp?
- *
- * FIXME: verify above conditions are true
- */
-static void
-i830_enable_fb_compression(xf86CrtcPtr crtc)
-{
-    ScrnInfoPtr pScrn = crtc->scrn;
-    I830Ptr pI830 = I830PTR(pScrn);
-    I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
-    uint32_t fbc_ctl;
-    unsigned long compressed_stride;
-    int pipe = intel_crtc->pipe;
-    int plane = (pipe == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB);
-    unsigned long uncompressed_stride = pScrn->displayWidth * pI830->cpp;
-    unsigned long interval = 1000;
-
-    if (INREG(FBC_CONTROL) & FBC_CTL_EN) {
-	char cur_pipe = (INREG(FBC_CONTROL2) & 1) ? 'b' : 'a';
-	xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "fbc already enabled on "
-		   "pipe %c, not enabling on pipe %c\n", cur_pipe, pipe ? 'b' :
-		   'a');
-	return;
-    }
-
-    compressed_stride = pI830->compressed_front_buffer->size /
-	FBC_LL_SIZE;
-
-    if (uncompressed_stride < compressed_stride)
-	compressed_stride = uncompressed_stride;
-
-    /* FBC_CTL wants 64B units */
-    compressed_stride = (compressed_stride / 64) - 1;
-
-    /* Set it up... */
-    OUTREG(FBC_CFB_BASE, pI830->compressed_front_buffer->bus_addr);
-    OUTREG(FBC_LL_BASE, pI830->compressed_ll_buffer->bus_addr + FBC_LL_PAD);
-    OUTREG(FBC_CONTROL2, FBC_CTL_CPU_FENCE | plane);
-
-    /* enable it... */
-    fbc_ctl = INREG(FBC_CONTROL);
-    fbc_ctl |= FBC_CTL_EN | FBC_CTL_PERIODIC;
-    fbc_ctl |= (compressed_stride & 0xff) << FBC_CTL_STRIDE_SHIFT;
-    fbc_ctl |= (interval & 0x2fff) << FBC_CTL_INTERVAL_SHIFT;
-    OUTREG(FBC_CONTROL, fbc_ctl);
-
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "fbc enabled on pipe %c\n", pipe ?
-	       'b' : 'a');
-}
-
-static void
-i830_disable_fb_compression(xf86CrtcPtr crtc)
-{
-    ScrnInfoPtr pScrn = crtc->scrn;
-    I830Ptr pI830 = I830PTR(pScrn);
-    uint32_t fbc_ctl;
-    char pipe = (INREG(FBC_CONTROL2) & 1) ? 'b' : 'a';
-
-    /* Disable compression */
-    fbc_ctl = INREG(FBC_CONTROL);
-    fbc_ctl &= ~FBC_CTL_EN;
-    OUTREG(FBC_CONTROL, fbc_ctl);
-
-    /* Wait for compressing bit to clear */
-    while (INREG(FBC_STATUS) & FBC_STAT_COMPRESSING)
-	; /* nothing */
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "fbc disabled on pipe %c\n", pipe);
-}
-
 static void
 i830_crtc_prepare (xf86CrtcPtr crtc)
 {
@@ -1059,6 +1078,9 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
     else
 	dspcntr |= DISPPLANE_SEL_PIPE_B;
 
+    if (pI830->tiling)
+	dspcntr |= DISPLAY_PLANE_TILED;
+
     pipeconf = INREG(pipeconf_reg);
     if (pipe == 0 && !IS_I965G(pI830))
     {
diff --git a/src/i830_exa.c b/src/i830_exa.c
index fed4067..5da153e 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -97,6 +97,16 @@ const int I830PatternROP[16] =
     ROP_1
 };
 
+static Bool
+exaPixmapInFrontbuffer(PixmapPtr p)
+{
+    ScreenPtr pScreen = p->drawable.pScreen;
+
+    if (p == pScreen->GetScreenPixmap(pScreen))
+	return TRUE;
+    return FALSE;
+}
+
 /**
  * I830EXASync - wait for a command to finish
  * @pScreen: current screen
@@ -162,16 +172,26 @@ I830EXASolid(PixmapPtr pPixmap, int x1, 
     ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
     unsigned long offset;
+    uint32_t cmd;
 
     offset = exaGetPixmapOffset(pPixmap);  
     
     {
 	BEGIN_LP_RING(6);
+
+	cmd = XY_COLOR_BLT_CMD;
+
 	if (pPixmap->drawable.bitsPerPixel == 32)
-	    OUT_RING(XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA
-			| XY_COLOR_BLT_WRITE_RGB);
-	else
-	    OUT_RING(XY_COLOR_BLT_CMD);
+	    cmd |= XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB;
+
+	if (pI830->tiling && exaPixmapInFrontbuffer(pPixmap)) {
+	    /* Fixup pitch for destination if tiled */
+	    pI830->BR[13] = (ROUND_TO(pI830->BR[13] & 0xffff, 512) >> 2) | 
+		(pI830->BR[13] & 0xffff0000);
+	    cmd |= XY_COLOR_BLT_TILED;
+	}
+
+	OUT_RING(cmd);
 
 	OUT_RING(pI830->BR[13]);
 	OUT_RING((y1 << 16) | (x1 & 0xffff));
@@ -208,6 +228,8 @@ I830EXAPrepareCopy(PixmapPtr pSrcPixmap,
 
     pI830->copy_src_pitch = exaGetPixmapPitch(pSrcPixmap);
     pI830->copy_src_off = exaGetPixmapOffset(pSrcPixmap);
+    pI830->copy_src_tiled = (pI830->tiling &&
+			     exaPixmapInFrontbuffer(pSrcPixmap));
 
     pI830->BR[13] = exaGetPixmapPitch(pDstPixmap);
     pI830->BR[13] |= I830CopyROP[alu] << 16;
@@ -231,6 +253,7 @@ I830EXACopy(PixmapPtr pDstPixmap, int sr
 {
     ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
+    uint32_t cmd;
     int dst_x2, dst_y2;
     unsigned int dst_off;
 
@@ -242,11 +265,26 @@ I830EXACopy(PixmapPtr pDstPixmap, int sr
     {
 	BEGIN_LP_RING(8);
 
+	cmd = XY_SRC_COPY_BLT_CMD;
+
 	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
-	    OUT_RING(XY_SRC_COPY_BLT_CMD);
+	    cmd |= XY_SRC_COPY_BLT_WRITE_ALPHA | XY_SRC_COPY_BLT_WRITE_RGB;
+
+	if (pI830->tiling && exaPixmapInFrontbuffer(pDstPixmap)) {
+	    /* Fixup pitch for destination if tiled */
+	    pI830->BR[13] = (ROUND_TO(pI830->BR[13] & 0xffff, 512) >> 2) | 
+		(pI830->BR[13] & 0xffff0000);
+	    cmd |= XY_SRC_COPY_BLT_DST_TILED;
+	}
+
+	if (pI830->copy_src_tiled) {
+	    pI830->copy_src_pitch =
+		(ROUND_TO(pI830->copy_src_pitch & 0xffff, 512) >> 2) | 
+		(pI830->copy_src_pitch & 0xffff0000);
+	    cmd |= XY_SRC_COPY_BLT_SRC_TILED;
+	}
+
+	OUT_RING(cmd);
 
 	OUT_RING(pI830->BR[13]);
 	OUT_RING((dst_y1 << 16) | (dst_x1 & 0xffff));
diff --git a/src/i830_memory.c b/src/i830_memory.c
index b38a5df..ccd26b3 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -1453,11 +1453,6 @@ i830_set_fence(ScrnInfoPtr pScrn, int nr
     assert(tile_format != TILING_NONE);
 
     if (IS_I965G(pI830)) {
-        if (tile_format == TILING_XMAJOR)
-            pitch = 512;
-        else
-            pitch = 128;
- 
 	if (nr < 0 || nr >= FENCE_NEW_NR) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		       "i830_set_fence(): fence %d out of range\n",nr);
diff --git a/src/i830_reg.h b/src/i830_reg.h
index 8a2a98a..df22ed4 100644
--- a/src/i830_reg.h
+++ b/src/i830_reg.h
@@ -36,6 +36,7 @@
 #define   FBC_CTL_EN		(1<<31)
 #define   FBC_CTL_PERIODIC	(1<<30)
 #define   FBC_CTL_INTERVAL_SHIFT (16)
+#define   FBC_CTL_UNCOMPRESSIBLE (1<<14)
 #define   FBC_CTL_STRIDE_SHIFT	(5)
 #define   FBC_CTL_FENCENO	(1<<0)
 #define FBC_COMMAND		0x0320c
@@ -46,9 +47,15 @@
 #define   FBC_STAT_MODIFIED	(1<<29)
 #define   FBC_STAT_CURRENT_LINE	(1<<0)
 #define FBC_CONTROL2		0x03214
+#define   FBC_CTL_FENCE_DBL	(0<<4)
+#define   FBC_CTL_IDLE_IMM	(0<<2)
+#define   FBC_CTL_IDLE_FULL	(1<<2)
+#define   FBC_CTL_IDLE_LINE	(2<<2)
+#define   FBC_CTL_IDLE_DEBUG	(3<<2)
 #define   FBC_CTL_CPU_FENCE	(1<<1)
 #define   FBC_CTL_PLANEA	(0<<0)
 #define   FBC_CTL_PLANEB	(1<<0)
+#define FBC_FENCE_OFF		0x0321b
 
 #define FBC_LL_SIZE		(1536)
 #define FBC_LL_PAD		(32)
diff-tree 79d9a309b19e22561e000a47b732c67479c2e6d4 (from 857b4a7bcb69ca43b866b4283fe075abbafb1d22)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Aug 2 15:50:42 2007 -0700

    Mark DRI buffers as shareable, and pass their buffer handles through the SAREA.

diff --git a/src/i830.h b/src/i830.h
index 730d6bc..ccbae4f 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -756,6 +756,7 @@ extern const int I830CopyROP[16];
 #define ALIGN_BOTH_ENDS			0x00000002
 #define NEED_NON_STOLEN			0x00000004
 #define NEED_LIFETIME_FIXED		0x00000008
+#define ALLOW_SHARING			0x00000010
 
 /* Chipset registers for VIDEO BIOS memory RW access */
 #define _855_DRAM_RW_CONTROL 0x58
diff --git a/src/i830_common.h b/src/i830_common.h
index 9c8616c..1ca2642 100644
--- a/src/i830_common.h
+++ b/src/i830_common.h
@@ -138,6 +138,15 @@ typedef struct {
 	int third_offset;
 	int third_size;
 	unsigned int third_tiled;
+
+	/* buffer object handles for the static buffers.  May change
+	 * over the lifetime of the client, though it doesn't in our current
+	 * implementation.
+	 */
+	unsigned int front_bo_handle;
+	unsigned int back_bo_handle;
+	unsigned int third_bo_handle;
+	unsigned int depth_bo_handle;
 } drmI830Sarea;
 
 /* Flags for perf_boxes
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 0ffafca..f97edd7 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1664,6 +1664,7 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, 
       sarea->third_offset = 0;
       sarea->third_size = 0;
    }
+
    sarea->depth_offset = pI830->depth_buffer->offset;
    sarea->depth_size = pI830->depth_buffer->size;
    if (pI830->textures != NULL) {
@@ -1678,6 +1679,21 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, 
    sarea->virtualX = pScrn->virtualX;
    sarea->virtualY = pScrn->virtualY;
 
+   sarea->front_bo_handle = -1;
+   sarea->back_bo_handle = -1;
+   sarea->third_bo_handle = -1;
+   sarea->depth_bo_handle = -1;
+#ifdef XF86DRI_MM
+   if (pI830->front_buffer->bo.size)
+       sarea->front_bo_handle = pI830->front_buffer->bo.handle;
+   if (pI830->back_buffer->bo.size)
+       sarea->back_bo_handle = pI830->back_buffer->bo.handle;
+   if (pI830->third_buffer != NULL && pI830->third_buffer->bo.size)
+       sarea->third_bo_handle = pI830->third_buffer->bo.handle;
+   if (pI830->depth_buffer->bo.size)
+       sarea->depth_bo_handle = pI830->depth_buffer->bo.handle;
+#endif
+
    /* The rotation is now handled entirely by the X Server, so just leave the
     * DRI unaware.
     */
diff --git a/src/i830_dri.h b/src/i830_dri.h
index a2cf78e..b6a8366 100644
--- a/src/i830_dri.h
+++ b/src/i830_dri.h
@@ -9,7 +9,7 @@
 #define I830_MAX_DRAWABLES 256
 
 #define I830_MAJOR_VERSION 1
-#define I830_MINOR_VERSION 8
+#define I830_MINOR_VERSION 9
 #define I830_PATCHLEVEL 0
 
 #define I830_REG_SIZE 0x80000
diff --git a/src/i830_memory.c b/src/i830_memory.c
index e4d5d3d..96a4d67 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -692,6 +692,8 @@ i830_allocate_memory_bo(ScrnInfoPtr pScr
 
     mask = DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_MAPPABLE |
 	DRM_BO_FLAG_MEM_TT;
+    if (flags & ALLOW_SHARING)
+	mask |= DRM_BO_FLAG_SHAREABLE;
 
     ret = drmBOCreate(pI830->drmSubFD, 0, size, align / GTT_PAGE_SIZE, NULL,
 		      drm_bo_type_dc, mask, 0, &mem->bo);
@@ -1101,7 +1103,7 @@ i830_allocate_framebuffer(ScrnInfoPtr pS
      * DRIDoMappings is the only caller of the rm/add map functions,
      * and it's only called at startup.  This should be easily fixable.
      */
-    flags = NEED_LIFETIME_FIXED;
+    flags = NEED_LIFETIME_FIXED | ALLOW_SHARING;
 
     /* Clear everything first. */
     memset(FbMemBox, 0, sizeof(*FbMemBox));
@@ -1537,9 +1539,11 @@ i830_allocate_backbuffer(ScrnInfoPtr pSc
     {
 	size = ROUND_TO_PAGE(pitch * ALIGN(height, 16));
 	*buffer = i830_allocate_memory_tiled(pScrn, name, size, pitch,
-					     GTT_PAGE_SIZE, ALIGN_BOTH_ENDS,
-					     TILING_XMAJOR |
-					     NEED_LIFETIME_FIXED);
+					     GTT_PAGE_SIZE,
+					     ALIGN_BOTH_ENDS |
+					     NEED_LIFETIME_FIXED |
+					     ALLOW_SHARING,
+					     TILING_XMAJOR);
 	*tiled = FENCE_XMAJOR;
     }
 
@@ -1549,7 +1553,9 @@ i830_allocate_backbuffer(ScrnInfoPtr pSc
     if (*buffer == NULL) {
 	size = ROUND_TO_PAGE(pitch * height);
 	*buffer = i830_allocate_memory(pScrn, name, size, GTT_PAGE_SIZE,
-				       ALIGN_BOTH_ENDS | NEED_LIFETIME_FIXED);
+				       ALIGN_BOTH_ENDS |
+				       NEED_LIFETIME_FIXED |
+				       ALLOW_SHARING);
 	*tiled = FENCE_LINEAR;
     }
 
@@ -1591,7 +1597,9 @@ i830_allocate_depthbuffer(ScrnInfoPtr pS
 	pI830->depth_buffer =
 	    i830_allocate_memory_tiled(pScrn, "depth buffer", size, pitch,
 				       GTT_PAGE_SIZE,
-				       ALIGN_BOTH_ENDS | NEED_LIFETIME_FIXED,
+				       ALIGN_BOTH_ENDS |
+				       NEED_LIFETIME_FIXED |
+				       ALLOW_SHARING,
 				       tile_format);
 	pI830->depth_tiled = (tile_format == TILING_YMAJOR) ? FENCE_YMAJOR :
 	    FENCE_XMAJOR;
@@ -1604,7 +1612,7 @@ i830_allocate_depthbuffer(ScrnInfoPtr pS
 	size = ROUND_TO_PAGE(pitch * height);
 	pI830->depth_buffer =
 	    i830_allocate_memory(pScrn, "depth buffer", size, GTT_PAGE_SIZE,
-				 NEED_LIFETIME_FIXED);
+				 ALLOW_SHARING | NEED_LIFETIME_FIXED);
 	pI830->depth_tiled = FENCE_LINEAR;
     }
 
@@ -1646,6 +1654,7 @@ i830_allocate_texture_memory(ScrnInfoPtr
 	 */
 	pI830->textures = i830_allocate_memory(pScrn, "classic textures", size,
 					       GTT_PAGE_SIZE,
+					       ALLOW_SHARING |
 					       NEED_LIFETIME_FIXED);
 	if (pI830->textures == NULL) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
diff-tree 0da4f2b0cd7203377ad10407928a367b8c6d310e (from f403a50afbcef1e54f554481c72037338bd5357c)
Author: Jesse Barnes <jesse.barnes at intel.com>
Date:   Tue Jul 31 16:22:36 2007 -0700

    Legacy backlight changes:
      - add support for 965GM
      - make sure legacy enabled systems don't reduce the range of backlight values we can present to the user

diff --git a/src/i810_reg.h b/src/i810_reg.h
index 248df04..d1fed22 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -822,6 +822,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 # define PP_SEQUENCE_MASK			0x30000000
 
 #define PP_CONTROL	0x61204
+# define POWER_DOWN_ON_RESET			(1 << 1)
 # define POWER_TARGET_ON			(1 << 0)
 
 #define LVDSPP_ON       0x61208
@@ -1066,6 +1067,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 #define BLC_PWM_CTL		0x61254
 #define BACKLIGHT_MODULATION_FREQ_SHIFT		(17)
+#define BACKLIGHT_MODULATION_FREQ_SHIFT2	(16)
 /**
  * This is the most significant 15 bits of the number of backlight cycles in a
  * complete cycle of the modulated backlight control.
@@ -1073,7 +1075,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * The actual value is this field multiplied by two.
  */
 #define BACKLIGHT_MODULATION_FREQ_MASK		(0x7fff << 17)
+#define BACKLIGHT_MODULATION_FREQ_MASK2		(0xffff << 16)
 #define BLM_LEGACY_MODE				(1 << 16)
+
 /**
  * This is the number of cycles out of the backlight modulation cycle for which
  * the backlight is on.
@@ -1084,6 +1088,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define BACKLIGHT_DUTY_CYCLE_SHIFT		(0)
 #define BACKLIGHT_DUTY_CYCLE_MASK		(0xffff)
 
+/* On 965+ backlight control is in another register */
+#define BLC_PWM_CTL2			0x61250
+#define 	BLM_LEGACY_MODE2	(1 << 30)
+
 #define BLM_CTL			0x61260
 #define BLM_THRESHOLD_0		0x61270
 #define BLM_THRESHOLD_1		0x61274
diff --git a/src/i830.h b/src/i830.h
index bf072a1..a8de0e6 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -532,6 +532,7 @@ typedef struct _I830Rec {
    CARD32 savePaletteB[256];
    CARD32 saveSWF[17];
    CARD32 saveBLC_PWM_CTL;
+   CARD32 saveBLC_PWM_CTL2;
    CARD32 saveFBC_CFB_BASE;
    CARD32 saveFBC_LL_BASE;
    CARD32 saveFBC_CONTROL2;
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index 246008b..18e5c2b 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -46,6 +46,30 @@ struct i830_lvds_priv {
     int		    backlight_duty_cycle;
 };
 
+/**
+ * Use legacy backlight controls?
+ *
+ * \param pI830 device in question
+ *
+ * Returns TRUE if legacy backlight should be used, false otherwise.
+ */
+static int
+i830_lvds_backlight_legacy(I830Ptr pI830)
+{
+    CARD32 blc_pwm_ctl, blc_pwm_ctl2;
+
+    /* 965GM+ change the location of the legacy control bit */
+    if (IS_I965GM(pI830)) {
+	blc_pwm_ctl2 = INREG(BLC_PWM_CTL2);
+	if (blc_pwm_ctl2 & BLM_LEGACY_MODE2)
+	    return TRUE;
+    } else {
+	blc_pwm_ctl = INREG(BLC_PWM_CTL);
+	if (blc_pwm_ctl & BLM_LEGACY_MODE)
+	    return TRUE;
+    }
+    return FALSE;
+}
 
 /**
  * Sets the backlight level.
@@ -59,18 +83,12 @@ i830_lvds_set_backlight(xf86OutputPtr ou
     I830Ptr pI830 = I830PTR(pScrn);
     CARD32 blc_pwm_ctl;
 
+    if (i830_lvds_backlight_legacy(pI830))
+	pciWriteByte(pI830->PciTag, LEGACY_BACKLIGHT_BRIGHTNESS, 0xfe);
+
     blc_pwm_ctl = INREG(BLC_PWM_CTL);
-    if (blc_pwm_ctl & BLM_LEGACY_MODE)
-    {
-	pciWriteByte (pI830->PciTag, 
-		      LEGACY_BACKLIGHT_BRIGHTNESS,
-		      level & 0xff);
-    }
-    else
-    {
-	blc_pwm_ctl &= ~BACKLIGHT_DUTY_CYCLE_MASK;
-	OUTREG(BLC_PWM_CTL, blc_pwm_ctl | (level << BACKLIGHT_DUTY_CYCLE_SHIFT));
-    }
+    blc_pwm_ctl &= ~BACKLIGHT_DUTY_CYCLE_MASK;
+    OUTREG(BLC_PWM_CTL, blc_pwm_ctl | (level << BACKLIGHT_DUTY_CYCLE_SHIFT));
 }
 
 /**
@@ -82,12 +100,24 @@ i830_lvds_get_max_backlight(xf86OutputPt
     ScrnInfoPtr pScrn = output->scrn;
     I830Ptr	pI830 = I830PTR(pScrn);
     CARD32	pwm_ctl = INREG(BLC_PWM_CTL);
+    CARD32	val;
+
+    if (IS_I965GM(pI830)) {
+	val = ((pwm_ctl & BACKLIGHT_MODULATION_FREQ_MASK2) >>
+	       BACKLIGHT_MODULATION_FREQ_SHIFT2);
+    } else {
+	val = ((pwm_ctl & BACKLIGHT_MODULATION_FREQ_MASK) >>
+	       BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
+    }
     
-    if (pwm_ctl & BLM_LEGACY_MODE)
-	return 0xff;
-    else
-	return ((pwm_ctl & BACKLIGHT_MODULATION_FREQ_MASK) >>
-		BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
+    /*
+     * In legacy control mode, backlight value is calculated:
+     * if (LBB[7:0] != 0xff)
+     *     backlight = BLC_PWM_CTL[15:0] *  BPC[7:0]
+     * else
+     *     backlight = BLC_PWM_CTL[15:0]
+     */
+    return val;
 }
 
 /**
@@ -138,21 +168,15 @@ i830_lvds_save (xf86OutputPtr output)
     ScrnInfoPtr		    pScrn = output->scrn;
     I830Ptr		    pI830 = I830PTR(pScrn);
 
+    if (IS_I965GM(pI830))
+	pI830->saveBLC_PWM_CTL2 = INREG(BLC_PWM_CTL2);
     pI830->savePP_ON = INREG(LVDSPP_ON);
     pI830->savePP_OFF = INREG(LVDSPP_OFF);
     pI830->savePP_CONTROL = INREG(PP_CONTROL);
     pI830->savePP_CYCLE = INREG(PP_CYCLE);
     pI830->saveBLC_PWM_CTL = INREG(BLC_PWM_CTL);
-    if (pI830->saveBLC_PWM_CTL & BLM_LEGACY_MODE)
-    {
-	dev_priv->backlight_duty_cycle = pciReadByte (pI830->PciTag,
-						      LEGACY_BACKLIGHT_BRIGHTNESS);
-    }
-    else
-    {
-	dev_priv->backlight_duty_cycle = (pI830->saveBLC_PWM_CTL &
-					  BACKLIGHT_DUTY_CYCLE_MASK);
-    }
+    dev_priv->backlight_duty_cycle = (pI830->saveBLC_PWM_CTL &
+				      BACKLIGHT_DUTY_CYCLE_MASK);
 
     /*
      * If the light is off at server startup, just make it full brightness
@@ -167,6 +191,8 @@ i830_lvds_restore(xf86OutputPtr output)
     ScrnInfoPtr	pScrn = output->scrn;
     I830Ptr	pI830 = I830PTR(pScrn);
 
+    if (IS_I965GM(pI830))
+	OUTREG(BLC_PWM_CTL2, pI830->saveBLC_PWM_CTL2);
     OUTREG(BLC_PWM_CTL, pI830->saveBLC_PWM_CTL);
     OUTREG(LVDSPP_ON, pI830->savePP_ON);
     OUTREG(LVDSPP_OFF, pI830->savePP_OFF);
diff-tree 15f71edba37738f8ba279fa07452fda10cc65298 (from f403a50afbcef1e54f554481c72037338bd5357c)
Author: Zhenyu Wang <zhenyu.z.wang at intel.com>
Date:   Sat Jul 28 17:43:29 2007 +0800

    Update Lenovo TV quirk info

diff --git a/src/i830_quirks.c b/src/i830_quirks.c
index 8a4b07c..e209fea 100644
--- a/src/i830_quirks.c
+++ b/src/i830_quirks.c
@@ -57,6 +57,7 @@ static void quirk_mac_mini (I830Ptr pI83
 static i830_quirk i830_quirk_list[] = {
     /* Lenovo T61 has no TV output */
     { PCI_CHIP_I965_GM, 0x17aa, 0x20b5, quirk_ignore_tv },
+    /* Lenovo 3000 v200 */
     { PCI_CHIP_I965_GM, 0x17aa, 0x3c18, quirk_ignore_tv },
     /* Aopen mini pc */
     { PCI_CHIP_I945_GM, 0xa0a0, SUBSYS_ANY, quirk_ignore_lvds },
diff-tree 857b4a7bcb69ca43b866b4283fe075abbafb1d22 (from d7b5b595ad29ae0ac3adbd3a176be3fe7ffa6474)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Jul 27 18:03:12 2007 -0700

    Pin some buffer objects at creation time, which can't be moved yet.
    
    A number of other interfaces of ours don't allow buffer offsets to be updated
    after screeninit.  This attempts to catalog why for each one, so that they
    can be fixed one by one.
    
    This happens to restore the EXA offscreen allocator for now, as a fixed-offset
    object.

diff --git a/src/i830.h b/src/i830.h
index 14de7f0..730d6bc 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -160,6 +160,7 @@ struct _i830_memory {
 
 #ifdef XF86DRI_MM
     drmBO bo;
+    Bool lifetime_fixed_offset;
 #endif
 };
 
@@ -754,6 +755,7 @@ extern const int I830CopyROP[16];
 #define NEED_PHYSICAL_ADDR		0x00000001
 #define ALIGN_BOTH_ENDS			0x00000002
 #define NEED_NON_STOLEN			0x00000004
+#define NEED_LIFETIME_FIXED		0x00000008
 
 /* Chipset registers for VIDEO BIOS memory RW access */
 #define _855_DRAM_RW_CONTROL 0x58
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 676b4cb..c86840a 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -712,6 +712,10 @@ I830LoadPalette(ScrnInfoPtr pScrn, int n
    }
 }
 
+#if 0
+/* This code ended up unused, but will be at least a reference when we let the
+ * front buffer move.
+ */
 static void
 i830UpdateFrontOffset(ScrnInfoPtr pScrn)
 {
@@ -755,6 +759,7 @@ i830CreateScreenResources(ScreenPtr pScr
 
    return TRUE;
 }
+#endif
 
 int
 i830_output_clones (ScrnInfoPtr pScrn, int type_mask)
@@ -2724,8 +2729,10 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    pScreen->SaveScreen = xf86SaveScreen;
    pI830->CloseScreen = pScreen->CloseScreen;
    pScreen->CloseScreen = I830CloseScreen;
+#if 0
    pI830->CreateScreenResources = pScreen->CreateScreenResources;
    pScreen->CreateScreenResources = i830CreateScreenResources;
+#endif
 
    if (!xf86CrtcScreenInit (pScreen))
        return FALSE;
@@ -2872,7 +2879,9 @@ I830EnterVT(int scrnIndex, int flags)
 
    i830_describe_allocations(pScrn, 1, "");
 
+#if 0
    i830UpdateFrontOffset(pScrn);
+#endif
 
    if (i830_check_error_state(pScrn)) {
       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 80e3536..e4d5d3d 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -108,6 +108,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 #define ALIGN(i,m)    (((i) + (m) - 1) & ~((m) - 1))
 
+/* Our hardware status area is just a single page */
+#define HWSTATUS_PAGE_SIZE GTT_PAGE_SIZE
+
 enum tile_format {
     TILING_NONE,
     TILING_XMAJOR,
@@ -155,23 +158,29 @@ i830_bind_memory(ScrnInfoPtr pScrn, i830
 {
     I830Ptr pI830 = I830PTR(pScrn);
 
-    if (mem == NULL || mem->bound || !pI830->gtt_acquired)
+    if (mem == NULL || mem->bound)
 	return TRUE;
 
 #ifdef XF86DRI_MM
     if (mem->bo.size != 0) {
+	I830Ptr pI830 = I830PTR(pScrn);
 	int ret;
 
 	ret = drmBOSetPin(pI830->drmSubFD, &mem->bo, 1);
-	mem->offset = mem->bo.offset;
-	mem->end = mem->offset + mem->size;
-	if (ret)
-	    return FALSE;
-	else
+	if (ret == 0) {
+	    mem->bound = TRUE;
+	    mem->offset = mem->bo.offset;
+	    mem->end = mem->bo.offset + mem->size;
 	    return TRUE;
+	} else {
+	    return FALSE;
+	}
     }
 #endif
 
+    if (!pI830->gtt_acquired)
+	return TRUE;
+
     if (mem->key == -1 ||
 	xf86BindGARTMemory(pScrn->scrnIndex, mem->key, mem->agp_offset)) {
 	mem->bound = TRUE;
@@ -195,10 +204,15 @@ i830_unbind_memory(ScrnInfoPtr pScrn, i8
 	int ret;
 
 	ret = drmBOSetPin(pI830->drmSubFD, &mem->bo, 0);
-	if (ret)
-	    return FALSE;
-	else
+	if (ret == 0) {
+	    mem->bound = FALSE;
+	    /* Give buffer obviously wrong offset/end until it's re-pinned. */
+	    mem->offset = -1;
+	    mem->end = -1;
 	    return TRUE;
+	} else {
+	    return FALSE;
+	}
     }
 #endif
 
@@ -213,15 +227,16 @@ i830_unbind_memory(ScrnInfoPtr pScrn, i8
 void
 i830_free_memory(ScrnInfoPtr pScrn, i830_memory *mem)
 {
-#ifdef XF86DRI_MM
-    I830Ptr pI830 = I830PTR(pScrn);
-#endif
-
     if (mem == NULL)
 	return;
 
+    /* Free any AGP memory. */
+    i830_unbind_memory(pScrn, mem);
+
 #ifdef XF86DRI_MM
     if (mem->bo.size != 0) {
+	I830Ptr pI830 = I830PTR(pScrn);
+
 	drmBOUnReference(pI830->drmSubFD, &mem->bo);
 	if (pI830->bo_list == mem)
 	    pI830->bo_list = mem->next;
@@ -240,9 +255,6 @@ i830_free_memory(ScrnInfoPtr pScrn, i830
     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;
@@ -326,6 +338,9 @@ i830_allocator_init(ScrnInfoPtr pScrn, u
     I830Ptr pI830 = I830PTR(pScrn);
     i830_memory *start, *end;
     int ret;
+#ifdef XF86DRI_MM
+    int dri_major, dri_minor, dri_patch;
+#endif
 
     start = xcalloc(1, sizeof(*start));
     if (start == NULL)
@@ -363,16 +378,23 @@ i830_allocator_init(ScrnInfoPtr pScrn, u
     pI830->memory_list = start;
 
 #ifdef XF86DRI_MM
+    DRIQueryVersion(&dri_major, &dri_minor, &dri_patch);
+
     /* Now that we have our manager set up, initialize the kernel MM if
-     * possible, covering almost all of the aperture.
+     * possible, covering almost all of the aperture.  We need libdri interface
+     * 5.4 or newer so we can rely on the lock being held after DRIScreenInit,
+     * rather than after DRIFinishScreenInit.
      */
-    if (pI830->directRenderingEnabled && pI830->drmMinor >= 7) {
+    if (pI830->directRenderingEnabled && pI830->drmMinor >= 7 &&
+	(dri_major > 5 || (dri_major == 5 && dri_minor >= 4)))
+    {
 	int mmsize;
 
 	/* Take over all of the graphics aperture minus enough to for
 	 * physical-address allocations of cursor/overlay registers.
 	 */
 	mmsize = size;
+	/* Overlay is always set up as fixed, currently. */
 	if (!OVERLAY_NOPHYSICAL(pI830) && !IS_I965G(pI830)) {
 	    mmsize -= ROUND_TO(OVERLAY_SIZE, GTT_PAGE_SIZE);
 	    if (pI830->CursorNeedsPhysical) {
@@ -678,10 +700,19 @@ i830_allocate_memory_bo(ScrnInfoPtr pScr
 	xfree(mem);
 	return NULL;
     }
-
-    mem->offset = mem->bo.offset;
-    mem->end = mem->bo.start + size;
+    /* Give buffer obviously wrong offset/end until it's pinned. */
+    mem->offset = -1;
+    mem->end = -1;
     mem->size = size;
+    if (flags & NEED_LIFETIME_FIXED) {
+	if (!i830_bind_memory(pScrn, mem)) {
+	    drmBOUnReference(pI830->drmSubFD, &mem->bo);
+	    xfree(mem->name);
+	    xfree(mem);
+	    return NULL;
+	}
+	mem->lifetime_fixed_offset = TRUE;
+    }
 
     /* Insert new allocation into the list */
     mem->prev = NULL;
@@ -700,6 +731,17 @@ i830_allocate_memory_bo(ScrnInfoPtr pScr
  * VT.  When the kernel memory manager is available and compatible with flags
  * (that is, flags doesn't say that the allocation must include a physical
  * address), that will be used for the allocation.
+ *
+ * flags:
+ * - NEED_PHYSICAL_ADDR: Allocates the memory physically contiguous, and return
+ *   the bus address for that memory.
+ * - ALIGN_BOTH_ENDS: after choosing the alignment, align the end offset to
+ *   @alignment as well.
+ * - NEED_NON-STOLEN: don't allow any part of the memory allocation to lie
+ *   within stolen memory
+ * - NEED_LIFETIME_FIXED: don't allow the buffer object to move throughout
+ *   the entire Screen lifetime.  This means not using buffer objects, which
+ *   get their offsets chosen at each EnterVT time.
  */
 static i830_memory *
 i830_allocate_memory(ScrnInfoPtr pScrn, const char *name,
@@ -748,10 +790,10 @@ i830_allocate_memory_tiled(ScrnInfoPtr p
     if (tile_format == TILING_NONE)
 	return i830_allocate_memory(pScrn, name, size, alignment, flags);
 
-    /* XXX: for now, refuse to tile with buffer object allocations,
-     * until we can move the set_fence (and failure recovery) into EnterVT.
+    /* XXX: for now, refuse to tile with movable buffer object allocations,
+     * until we can move the set_fence (and failure recovery) into bind time.
      */
-    if (pI830->memory_manager != NULL)
+    if (pI830->memory_manager != NULL && !(flags & NEED_LIFETIME_FIXED))
 	return NULL;
 
     /* Only allocate page-sized increments. */
@@ -892,10 +934,16 @@ i830_describe_allocations(ScrnInfoPtr pS
 		       "%s0x%08lx:            start of memory manager\n",
 		       prefix, pI830->memory_manager->offset);
 	for (mem = pI830->bo_list; mem != NULL; mem = mem->next) {
-	    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);
+	    if (mem->bound) {
+		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,
+			       "%sunpinned          : %s (%ld kB)\n", prefix,
+			       mem->name, mem->size / 1024);
+	    }
 	}
 	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
 		       "%s0x%08lx:            end of memory manager\n",
@@ -931,9 +979,13 @@ i830_allocate_ringbuffer(ScrnInfoPtr pSc
     if (pI830->noAccel || pI830->LpRing->mem != NULL)
 	return TRUE;
 
+    /* We don't have any mechanism in the DRM yet to alert it that we've moved
+     * the ringbuffer since init time, so allocate it fixed for its lifetime.
+     */
     pI830->LpRing->mem = i830_allocate_memory(pScrn, "ring buffer",
 					      PRIMARY_RINGBUFFER_SIZE,
-					      GTT_PAGE_SIZE, 0);
+					      GTT_PAGE_SIZE,
+					      NEED_LIFETIME_FIXED);
     if (pI830->LpRing->mem == NULL) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		   "Failed to allocate Ring Buffer space\n");
@@ -953,7 +1005,7 @@ static Bool
 i830_allocate_overlay(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    int flags = NEED_PHYSICAL_ADDR;
+    int flags = NEED_PHYSICAL_ADDR | NEED_LIFETIME_FIXED;
 
     /* Only allocate if overlay is going to be enabled. */
     if (!pI830->XvEnabled)
@@ -963,6 +1015,10 @@ i830_allocate_overlay(ScrnInfoPtr pScrn)
 	flags = 0;
 
     if (!IS_I965G(pI830)) {
+	/* XXX: The lifetime fixed offset for overlay register is bogus, and we
+	 * should just tell i830_video.c about the new location at EnterVT
+	 * time.
+	 */
 	pI830->overlay_regs = i830_allocate_memory(pScrn, "overlay registers",
 						   OVERLAY_SIZE, GTT_PAGE_SIZE,
 						   flags);
@@ -1030,7 +1086,7 @@ IsTileable(ScrnInfoPtr pScrn, int pitch)
  */
 static i830_memory *
 i830_allocate_framebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox,
-			  Bool secondary, int flags)
+			  Bool secondary)
 {
     unsigned int pitch = pScrn->displayWidth * pI830->cpp;
     unsigned long minspace, avail;
@@ -1038,8 +1094,15 @@ i830_allocate_framebuffer(ScrnInfoPtr pS
     int align;
     long size, fb_height;
     char *name;
+    int flags;
     i830_memory *front_buffer = NULL;
 
+    /* The front buffer is currently marked as NEED_LIFETIME_FIXED because
+     * DRIDoMappings is the only caller of the rm/add map functions,
+     * and it's only called at startup.  This should be easily fixable.
+     */
+    flags = NEED_LIFETIME_FIXED;
+
     /* Clear everything first. */
     memset(FbMemBox, 0, sizeof(*FbMemBox));
 
@@ -1107,7 +1170,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. */
+    /* Attempt to allocate it tiled first if possible. */
     if (pI830->tiling && IsTileable(pScrn, pitch)) {
 	/* XXX: probably not the case on 965 */
 	if (IS_I9XX(pI830))
@@ -1116,7 +1179,8 @@ i830_allocate_framebuffer(ScrnInfoPtr pS
 	    align = KB(512);
 	front_buffer = i830_allocate_memory_tiled(pScrn, name, size,
 						  pitch, align,
-						  0, TILING_XMAJOR);
+						  flags,
+						  TILING_XMAJOR);
 	pI830->front_tiled = FENCE_XMAJOR;
     }
 
@@ -1149,7 +1213,7 @@ i830_allocate_cursor_buffers(ScrnInfoPtr
 
     /* Try to allocate one big blob for our cursor memory.  This works
      * around a limitation in the FreeBSD AGP driver that allows only one
-     * physical allocation larger than a page, and could allos us
+     * physical allocation larger than a page, and could allow us
      * to pack the cursors smaller.
      */
     size = xf86_config->num_crtc * (HWCURSOR_SIZE + HWCURSOR_SIZE_ARGB);
@@ -1356,23 +1420,18 @@ i830_allocate_2d_memory(ScrnInfoPtr pScr
 
 	pI830->front_buffer_2 =
 	    i830_allocate_framebuffer(pI830Ent->pScrn_2, pI8302,
-				      &pI830->FbMemBox2, TRUE, 0);
+				      &pI830->FbMemBox2, TRUE);
 	if (pI830->front_buffer_2 == NULL)
 	    return FALSE;
     }
     pI830->front_buffer =
-	i830_allocate_framebuffer(pScrn, pI830, &pI830->FbMemBox, FALSE, 0);
+	i830_allocate_framebuffer(pScrn, pI830, &pI830->FbMemBox, FALSE);
     if (pI830->front_buffer == NULL)
 	return FALSE;
 
 #ifdef I830_USE_EXA
     if (pI830->useEXA) {
-	/* With the kernel memory manager, the exa offscreen allocation would
-	 * change locations at EnterVT, which EXA is unprepared for.  The
-	 * performance of EXA offscreen memory management was low enough
-	 * that just not using it is reasonable.
-	 */
-	if (pI830->exa_offscreen == NULL && pI830->memory_manager == NULL) {
+	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.
 	     *
@@ -1384,8 +1443,13 @@ i830_allocate_2d_memory(ScrnInfoPtr pScr
 	    size += 1920 * 1088 * 2 * 2;
 	    size = ROUND_TO_PAGE(size);
 
-	    pI830->exa_offscreen = i830_allocate_memory(pScrn, "exa offscreen",
-							size, 1, 0);
+	    /* EXA has no way to tell it that the offscreen memory manager has
+	     * moved its base and all the contents with it, so we have to have
+	     * it locked in place for the whole driver instance.
+	     */
+	    pI830->exa_offscreen =
+		i830_allocate_memory(pScrn, "exa offscreen",
+				     size, 1, NEED_LIFETIME_FIXED);
 	    if (pI830->exa_offscreen == NULL) {
 		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 			   "Failed to allocate EXA offscreen memory.");
@@ -1396,14 +1460,18 @@ i830_allocate_2d_memory(ScrnInfoPtr pScr
 #endif /* I830_USE_EXA */
 
     if (!pI830->noAccel && !pI830->useEXA) {
+	/* The lifetime fixed offset of xaa scratch is probably not required,
+	 * but we do some setup using it at XAAInit() time.  And XAA may not
+	 * end up being supported with TTM anyway.
+	 */
 	pI830->xaa_scratch =
 	    i830_allocate_memory(pScrn, "xaa scratch", MAX_SCRATCH_BUFFER_SIZE,
-				 GTT_PAGE_SIZE, 0);
+				 GTT_PAGE_SIZE, NEED_LIFETIME_FIXED);
 	if (pI830->xaa_scratch == NULL) {
 	    pI830->xaa_scratch =
 		i830_allocate_memory(pScrn, "xaa scratch",
 				     MIN_SCRATCH_BUFFER_SIZE, GTT_PAGE_SIZE,
-				     0);
+				     NEED_LIFETIME_FIXED);
 	    if (pI830->xaa_scratch == NULL) {
 		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 			   "Failed to allocate scratch buffer space\n");
@@ -1418,12 +1486,12 @@ i830_allocate_2d_memory(ScrnInfoPtr pScr
 	    pI830->xaa_scratch_2 =
 		i830_allocate_memory(pScrn, "xaa scratch 2",
 				     MAX_SCRATCH_BUFFER_SIZE, GTT_PAGE_SIZE,
-				     0);
+				     NEED_LIFETIME_FIXED);
 	    if (pI830->xaa_scratch_2 == NULL) {
 		pI830->xaa_scratch_2 =
 		    i830_allocate_memory(pScrn, "xaa scratch 2",
 					 MIN_SCRATCH_BUFFER_SIZE,
-					 GTT_PAGE_SIZE, 0);
+					 GTT_PAGE_SIZE, NEED_LIFETIME_FIXED);
 		if (pI830->xaa_scratch_2 == NULL) {
 		    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 			       "Failed to allocate secondary scratch "
@@ -1470,15 +1538,18 @@ i830_allocate_backbuffer(ScrnInfoPtr pSc
 	size = ROUND_TO_PAGE(pitch * ALIGN(height, 16));
 	*buffer = i830_allocate_memory_tiled(pScrn, name, size, pitch,
 					     GTT_PAGE_SIZE, ALIGN_BOTH_ENDS,
-					     TILING_XMAJOR);
+					     TILING_XMAJOR |
+					     NEED_LIFETIME_FIXED);
 	*tiled = FENCE_XMAJOR;
     }
 
-    /* Otherwise, just allocate it linear */
+    /* Otherwise, just allocate it linear.  The offset must stay constant
+     * currently because we don't ever update the DRI maps after screen init.
+     */
     if (*buffer == NULL) {
 	size = ROUND_TO_PAGE(pitch * height);
 	*buffer = i830_allocate_memory(pScrn, name, size, GTT_PAGE_SIZE,
-				       ALIGN_BOTH_ENDS);
+				       ALIGN_BOTH_ENDS | NEED_LIFETIME_FIXED);
 	*tiled = FENCE_LINEAR;
     }
 
@@ -1519,18 +1590,21 @@ i830_allocate_depthbuffer(ScrnInfoPtr pS
 
 	pI830->depth_buffer =
 	    i830_allocate_memory_tiled(pScrn, "depth buffer", size, pitch,
-				       GTT_PAGE_SIZE, ALIGN_BOTH_ENDS,
+				       GTT_PAGE_SIZE,
+				       ALIGN_BOTH_ENDS | NEED_LIFETIME_FIXED,
 				       tile_format);
 	pI830->depth_tiled = (tile_format == TILING_YMAJOR) ? FENCE_YMAJOR :
 	    FENCE_XMAJOR;
     }
 
-    /* Otherwise, allocate it linear. */
+    /* Otherwise, allocate it linear. The offset must stay constant
+     * currently because we don't ever update the DRI maps after screen init.
+     */
     if (pI830->depth_buffer == NULL) {
 	size = ROUND_TO_PAGE(pitch * height);
 	pI830->depth_buffer =
 	    i830_allocate_memory(pScrn, "depth buffer", size, GTT_PAGE_SIZE,
-				 0);
+				 NEED_LIFETIME_FIXED);
 	pI830->depth_tiled = FENCE_LINEAR;
     }
 
@@ -1567,8 +1641,12 @@ i830_allocate_texture_memory(ScrnInfoPtr
 		       size / 1024);
 	    return FALSE;
 	}
+	/* The offset must stay constant currently because we don't ever update
+	 * the DRI maps after screen init.
+	 */
 	pI830->textures = i830_allocate_memory(pScrn, "classic textures", size,
-					       GTT_PAGE_SIZE, 0);
+					       GTT_PAGE_SIZE,
+					       NEED_LIFETIME_FIXED);
 	if (pI830->textures == NULL) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		       "Failed to allocate texture space.\n");
@@ -1582,11 +1660,14 @@ i830_allocate_texture_memory(ScrnInfoPtr
 static Bool
 i830_allocate_hwstatus(ScrnInfoPtr pScrn)
 {
-#define HWSTATUS_PAGE_SIZE (4*1024)
     I830Ptr pI830 = I830PTR(pScrn);
 
+    /* The current DRM will leak the HWS mapping if we update the address
+     * after init (at best), so allocate it fixed for its lifetime
+     * (i.e. not through buffer objects).
+     */
     pI830->hw_status = i830_allocate_memory(pScrn, "G33 hw status",
-	    HWSTATUS_PAGE_SIZE, GTT_PAGE_SIZE, 0);
+	    HWSTATUS_PAGE_SIZE, GTT_PAGE_SIZE, NEED_LIFETIME_FIXED);
     if (pI830->hw_status == NULL) {
 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		"Failed to allocate hw status page for G33.\n");
@@ -1866,10 +1947,12 @@ i830_bind_all_memory(ScrnInfoPtr pScrn)
 		FatalError("Couldn't bind memory for %s\n", mem->name);
 	    }
 	}
+#ifdef XF86DRI_MM
 	for (mem = pI830->bo_list; mem != NULL; mem = mem->next) {
-	    if (!i830_bind_memory(pScrn, mem))
+	    if (!mem->lifetime_fixed_offset && !i830_bind_memory(pScrn, mem))
 		FatalError("Couldn't bind memory for BO %s\n", mem->name);
 	}
+#endif
     }
 
     return TRUE;
@@ -1892,8 +1975,15 @@ i830_unbind_all_memory(ScrnInfoPtr pScrn
 	{
 	    i830_unbind_memory(pScrn, mem);
 	}
-	for (mem = pI830->bo_list; mem != NULL; mem = mem->next)
-	    i830_unbind_memory(pScrn, mem);
+#ifdef XF86DRI_MM
+	for (mem = pI830->bo_list; mem != NULL; mem = mem->next) {
+	    /* Don't unpin objects which require that their offsets never
+	     * change.
+	     */
+	    if (!mem->lifetime_fixed_offset)
+		i830_unbind_memory(pScrn, mem);
+	}
+#endif
 
 	pI830->gtt_acquired = FALSE;
 
diff-tree d7b5b595ad29ae0ac3adbd3a176be3fe7ffa6474 (from 2b1ec0f51479c1d7e5e62803c68feca29375519d)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Jul 27 12:48:08 2007 -0700

    Delay the first screen pixmap update to CreateScreenResources.
    
    The return value of GetScreenPixmap before CreateScreenResources is not, in
    fact, a pixmap.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 929a541..676b4cb 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -712,6 +712,50 @@ I830LoadPalette(ScrnInfoPtr pScrn, int n
    }
 }
 
+static void
+i830UpdateFrontOffset(ScrnInfoPtr pScrn)
+{
+   ScreenPtr pScreen = pScrn->pScreen;
+   I830Ptr pI830 = I830PTR(pScrn);
+
+   /* If we are still in ScreenInit, there is no screen pixmap to be updated
+    * yet.  We'll fix it up at CreateScreenResources.
+    */
+   if (pI830->starting)
+      return;
+
+   /* Update buffer locations, which may have changed as a result of
+    * i830_bind_all_memory().
+    */
+   pScrn->fbOffset = pI830->front_buffer->offset;
+   if (!pScreen->ModifyPixmapHeader(pScreen->GetScreenPixmap(pScreen),
+				    -1, -1, -1, -1, -1,
+				    (pointer)(pI830->FbBase +
+					      pScrn->fbOffset)))
+       FatalError("Couldn't adjust screen pixmap\n");
+}
+
+/**
+ * Adjust the screen pixmap for the current location of the front buffer.
+ * This is done at EnterVT when buffers are bound as long as the resources
+ * have already been created, but the first EnterVT happens before
+ * CreateScreenResources.
+ */
+static Bool
+i830CreateScreenResources(ScreenPtr pScreen)
+{
+   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+   I830Ptr pI830 = I830PTR(pScrn);
+
+   pScreen->CreateScreenResources = pI830->CreateScreenResources;
+   if (!(*pScreen->CreateScreenResources)(pScreen))
+      return FALSE;
+
+   i830UpdateFrontOffset(pScrn);
+
+   return TRUE;
+}
+
 int
 i830_output_clones (ScrnInfoPtr pScrn, int type_mask)
 {
@@ -2680,6 +2724,8 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    pScreen->SaveScreen = xf86SaveScreen;
    pI830->CloseScreen = pScreen->CloseScreen;
    pScreen->CloseScreen = I830CloseScreen;
+   pI830->CreateScreenResources = pScreen->CreateScreenResources;
+   pScreen->CreateScreenResources = i830CreateScreenResources;
 
    if (!xf86CrtcScreenInit (pScreen))
        return FALSE;
@@ -2803,7 +2849,6 @@ static Bool
 I830EnterVT(int scrnIndex, int flags)
 {
    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
-   ScreenPtr pScreen = pScrn->pScreen;
    I830Ptr  pI830 = I830PTR(pScrn);
    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
    int o;
@@ -2827,15 +2872,7 @@ I830EnterVT(int scrnIndex, int flags)
 
    i830_describe_allocations(pScrn, 1, "");
 
-   /* Update buffer locations, which may have changed as a result of
-    * i830_bind_all_memory().
-    */
-   pScrn->fbOffset = pI830->front_buffer->offset;
-   if (!pScreen->ModifyPixmapHeader(pScreen->GetScreenPixmap(pScreen),
-				    -1, -1, -1, -1, -1,
-				    (pointer)(pI830->FbBase +
-					      pScrn->fbOffset)))
-       FatalError("Couldn't adjust screen pixmap\n");
+   i830UpdateFrontOffset(pScrn);
 
    if (i830_check_error_state(pScrn)) {
       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
diff-tree 2b1ec0f51479c1d7e5e62803c68feca29375519d (from 1a585d03972394cb97dec2462937b0104bdf4de2)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Jul 27 10:00:35 2007 -0700

    Use the dontMapFramebuffer option available with DRIINFO 5.4.
    
    If not available, AIGLX init will fail.  While here, simplify DRIINFO tests
    since we refuse to init with a version queried less than the version we
    compiled against, anyway.

diff --git a/src/i830_dri.c b/src/i830_dri.c
index 0d511d2..0ffafca 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -124,11 +124,20 @@ static void I830DRIMoveBuffers(WindowPtr
 
 static void I830DRITransitionTo2d(ScreenPtr pScreen);
 static void I830DRITransitionTo3d(ScreenPtr pScreen);
-static void I830DRITransitionMultiToSingle3d(ScreenPtr pScreen);
-static void I830DRITransitionSingleToMulti3d(ScreenPtr pScreen);
 #if defined(DAMAGE) && (DRIINFO_MAJOR_VERSION > 5 ||		\
 			(DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1))
 #define DRI_SUPPORTS_CLIP_NOTIFY 1
+#else
+#define DRI_SUPPORTS_CLIP_NOTIFY 0
+static void I830DRITransitionMultiToSingle3d(ScreenPtr pScreen);
+static void I830DRITransitionSingleToMulti3d(ScreenPtr pScreen);
+#endif
+
+#if (DRIINFO_MAJOR_VERSION > 5 || \
+     (DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 4))
+#define DRI_DRIVER_FRAMEBUFFER_MAP 1
+#else
+#define DRI_DRIVER_FRAMEBUFFER_MAP 0
 #endif
 
 #ifdef DRI_SUPPORTS_CLIP_NOTIFY
@@ -491,7 +500,8 @@ I830CheckDRIAvailable(ScrnInfoPtr pScrn)
       int major, minor, patch;
 
       DRIQueryVersion(&major, &minor, &patch);
-      if (major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION) {
+      if (major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION ||
+	  major < 5) {
 	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		    "[dri] %s failed because of a version mismatch.\n"
 		    "[dri] libDRI version is %d.%d.%d but version %d.%d.x is needed.\n"
@@ -546,12 +556,6 @@ I830DRIScreenInit(ScreenPtr pScreen)
    pDRIInfo->ddxDriverMajorVersion = I830_MAJOR_VERSION;
    pDRIInfo->ddxDriverMinorVersion = I830_MINOR_VERSION;
    pDRIInfo->ddxDriverPatchVersion = I830_PATCHLEVEL;
-   /* Supply a dummy mapping info required by DRI setup.  See bug #5714 for
-    * progress on removing this requirement.
-    */
-   pDRIInfo->frameBufferPhysicalAddress = (char *) pI830->LinearAddr;
-   pDRIInfo->frameBufferSize = GTT_PAGE_SIZE;
-   pDRIInfo->frameBufferStride = 1;
    pDRIInfo->ddxDrawableTableEntry = I830_MAX_DRAWABLES;
 
    if (SAREA_MAX_DRAWABLES < I830_MAX_DRAWABLES)
@@ -587,40 +591,38 @@ I830DRIScreenInit(ScreenPtr pScreen)
    pDRIInfo->MoveBuffers = I830DRIMoveBuffers;
    pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
 
-   {
-#if DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1
-      int major, minor, patch;
-
-      DRIQueryVersion(&major, &minor, &patch);
-
-#if DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 3
-      if (minor >= 3)
-#endif
 #if DRIINFO_MAJOR_VERSION > 5 || \
     (DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 3)
-	 pDRIInfo->texOffsetStart = I830TexOffsetStart;
+      pDRIInfo->texOffsetStart = I830TexOffsetStart;
 #endif
 
-#if DRI_SUPPORTS_CLIP_NOTIFY && DRIINFO_MAJOR_VERSION == 5
-      if (minor >= 1)
-#endif
 #if DRI_SUPPORTS_CLIP_NOTIFY
-	 pDRIInfo->ClipNotify = I830DRIClipNotify;
+      pDRIInfo->ClipNotify = I830DRIClipNotify;
+#endif
+
+#if DRI_DRIVER_FRAMEBUFFER_MAP
+   /* DRI version is high enough that we can get the DRI code to not
+    * try to manage the framebuffer.
+    */
+   pDRIInfo->frameBufferPhysicalAddress = 0;
+   pDRIInfo->frameBufferSize = 0;
+   pDRIInfo->frameBufferStride = 0;
+   pDRIInfo->dontMapFrameBuffer = TRUE;
+#else
+   /* Supply a dummy mapping info required by DRI setup.
+    */
+   pDRIInfo->frameBufferPhysicalAddress = (char *) pI830->LinearAddr;
+   pDRIInfo->frameBufferSize = GTT_PAGE_SIZE;
+   pDRIInfo->frameBufferStride = 1;
 #endif
-#endif /* DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1 */
-   }
 
    pDRIInfo->TransitionTo2d = I830DRITransitionTo2d;
    pDRIInfo->TransitionTo3d = I830DRITransitionTo3d;
 
-#if DRIINFO_MAJOR_VERSION > 5 || \
-    (DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1)
-   if (!pDRIInfo->ClipNotify)
+#if !DRI_SUPPORTS_CLIP_NOTIFY
+   pDRIInfo->TransitionSingleToMulti3D = I830DRITransitionSingleToMulti3d;
+   pDRIInfo->TransitionMultiToSingle3D = I830DRITransitionMultiToSingle3d;
 #endif
-   {
-      pDRIInfo->TransitionSingleToMulti3D = I830DRITransitionSingleToMulti3d;
-      pDRIInfo->TransitionMultiToSingle3D = I830DRITransitionMultiToSingle3d;
-   }
 
    /* do driver-independent DRI screen initialization here */
    if (!DRIScreenInit(pScreen, pDRIInfo, &pI830->drmSubFD)) {
@@ -633,30 +635,14 @@ I830DRIScreenInit(ScreenPtr pScreen)
       return FALSE;
    }
 
-   /* Now, nuke dri.c's frontbuffer map setup. */
-#if 0
-   if (xf86LoaderCheckSymbol("DRIGetScreenPrivate")) {
-      DRIScreenPrivPtr pDRIPriv =
-	  (DRIScreenPrivPtr) DRIGetScreenPrivate(pScreen);
-
-      if (pDRIPriv && pDRIPriv->drmFD && pDRIPriv->hFrameBuffer) {
-         xf86DrvMsg(pScreen->myNum, X_ERROR,
-                    "[intel] removing original screen mapping\n");
-         drmRmMap(pDRIPriv->drmFD, pDRIPriv->hFrameBuffer);
-         pDRIPriv->hFrameBuffer = 0;
-         xf86DrvMsg(pScreen->myNum, X_ERROR,
-                    "[intel] done removing original screen mapping\n");
-      }
-   }
-#endif
-   {
+   /* Now, nuke dri.c's dummy frontbuffer map setup if we did that. */
+   if (pDRIInfo->frameBufferSize != 0) {
        int tmp;
        unsigned int fb_handle;
        void *ptmp;
 
        /* With the compat method, it will continue to report
-	* the wrong map out of GetDeviceInfo, but we don't have any consumers
-	* of the frontbuffer handle from there.
+	* the wrong map out of GetDeviceInfo, which will break AIGLX.
 	*/
        DRIGetDeviceInfo(pScreen, &fb_handle, &tmp, &tmp, &tmp, &tmp, &ptmp);
        drmRmMap(pI830->drmSubFD, fb_handle);
@@ -763,11 +749,12 @@ I830DRIMapScreenRegions(ScrnInfoPtr pScr
 {
    ScreenPtr pScreen = pScrn->pScreen;
    I830Ptr pI830 = I830PTR(pScrn);
+   drm_handle_t front_handle;
 
-#if 1 /* Remove this soon - see bug 5714 */
-   pI830->pDRIInfo->frameBufferSize = ROUND_TO_PAGE(pScrn->displayWidth *
-					     pScrn->virtualY * pI830->cpp);
-#endif
+   pI830->pDRIInfo->frameBufferPhysicalAddress = (char *) pI830->LinearAddr;
+   pI830->pDRIInfo->frameBufferStride = pScrn->displayWidth * pI830->cpp;
+   pI830->pDRIInfo->frameBufferSize =
+      ROUND_TO_PAGE(pI830->pDRIInfo->frameBufferStride * pScrn->virtualY);
 
    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 	      "[drm] Mapping front buffer\n");
@@ -776,12 +763,17 @@ I830DRIMapScreenRegions(ScrnInfoPtr pScr
 		 sarea->front_size,
 		 DRM_AGP,
 		 0,
-		 (drmAddress) &sarea->front_handle) < 0) {
+		 &front_handle) < 0) {
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		  "[drm] drmAddMap(front_handle) failed. Disabling DRI\n");
        DRICloseScreen(pScreen);
        return FALSE;
    }
+   sarea->front_handle = front_handle;
+#if DRI_DRIVER_FRAMEBUFFER_MAP
+   pI830->pDRIInfo->hFrameBuffer = front_handle;
+#endif
+
    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Front Buffer = 0x%08x\n",
 	      (int)sarea->front_handle);
 
@@ -1530,6 +1522,7 @@ I830DRISetPfMask(ScreenPtr pScreen, int 
       pSAREAPriv->pf_active = 0;
 }
 
+#if !DRI_SUPPORTS_CLIP_NOTIFY
 static void
 I830DRITransitionSingleToMulti3d(ScreenPtr pScreen)
 {
@@ -1550,6 +1543,7 @@ I830DRITransitionMultiToSingle3d(ScreenP
     */
    I830DRISetPfMask(pScreen, pI830->allowPageFlip ? 0x3 : 0);
 }
+#endif /* !DRI_SUPPORTS_CLIP_NOTIFY */
 
 static void
 I830DRITransitionTo3d(ScreenPtr pScreen)
diff-tree f403a50afbcef1e54f554481c72037338bd5357c (from 34c82ad7ce83394db47588693b578cf91991bf1c)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Fri Jul 27 09:24:24 2007 +0800

    Add another Lenovo TV output quirk
    
    From issue report http://lists.freedesktop.org/archives/xorg/2007-July/026644.html

diff --git a/src/i830_quirks.c b/src/i830_quirks.c
index 1bf4692..8a4b07c 100644
--- a/src/i830_quirks.c
+++ b/src/i830_quirks.c
@@ -57,6 +57,7 @@ static void quirk_mac_mini (I830Ptr pI83
 static i830_quirk i830_quirk_list[] = {
     /* Lenovo T61 has no TV output */
     { PCI_CHIP_I965_GM, 0x17aa, 0x20b5, quirk_ignore_tv },
+    { PCI_CHIP_I965_GM, 0x17aa, 0x3c18, quirk_ignore_tv },
     /* Aopen mini pc */
     { PCI_CHIP_I945_GM, 0xa0a0, SUBSYS_ANY, quirk_ignore_lvds },
     /* Mac mini has no lvds, but macbook pro does */
diff-tree 34c82ad7ce83394db47588693b578cf91991bf1c (from 0fd3ba0518b3cde9ca0e4e2fc1854c00d8a43d5c)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Fri Jul 27 09:14:13 2007 +0800

    Add quirk support
    
    This one trys to use a flag for possible quirks. It adds a quirk
    for my Lenovo T61 TV output, and ports some origin LVDS quirks to it.

diff --git a/src/Makefile.am b/src/Makefile.am
index 858ffd1..50e913e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -90,6 +90,7 @@ intel_drv_la_SOURCES = \
 	 i830_debug.h \
 	 i830_display.c \
 	 i830_display.h \
+         i830_quirks.c \
          i830_driver.c \
 	 i830_dvo.c \
          i830.h \
diff --git a/src/i830.h b/src/i830.h
index aa2b240..bf072a1 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -541,6 +541,7 @@ typedef struct _I830Rec {
 
    /** Enables logging of debug output related to mode switching. */
    Bool debug_modes;
+   unsigned int quirk_flag;
 } I830Rec;
 
 #define I830PTR(p) ((I830Ptr)((p)->driverPrivate))
@@ -750,4 +751,10 @@ extern const int I830CopyROP[16];
 #define _845_DRAM_RW_CONTROL 0x90
 #define DRAM_WRITE    0x33330000
 
+/* quirk flag definition */
+#define QUIRK_IGNORE_TV			0x00000001
+#define QUIRK_IGNORE_LVDS		0x00000002
+#define QUIRK_IGNORE_MACMINI_LVDS 	0x00000004
+extern void i830_fixup_devices(ScrnInfoPtr);
+
 #endif /* _I830_H_ */
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 9bb12c6..f293bfd 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1192,6 +1192,9 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    xf86DrvMsg(pScrn->scrnIndex, from, "IO registers at addr 0x%lX\n",
 	      (unsigned long)pI830->MMIOAddr);
 
+   /* check quirks */
+   i830_fixup_devices(pScrn);
+
    /* Allocate an xf86CrtcConfig */
    xf86CrtcConfigInit (pScrn, &i830_xf86crtc_config_funcs);
    xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index e2c6e3c..246008b 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -462,6 +462,9 @@ i830_lvds_init(ScrnInfoPtr pScrn)
     DisplayModePtr	    modes, scan, bios_mode;
     struct i830_lvds_priv   *dev_priv;
 
+    if (pI830->quirk_flag & QUIRK_IGNORE_LVDS)
+	return;
+
     output = xf86OutputCreate (pScrn, &i830_lvds_output_funcs, "LVDS");
     if (!output)
 	return;
@@ -575,29 +578,23 @@ i830_lvds_init(ScrnInfoPtr pScrn)
     /* 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 */
-	    goto disable_exit;
-
-	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->quirk_flag & QUIRK_IGNORE_MACMINI_LVDS) {
+	/* 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 (dev_priv->panel_fixed_mode != NULL &&
+	if (dev_priv->panel_fixed_mode != NULL &&
 		dev_priv->panel_fixed_mode->HDisplay == 800 &&
 		dev_priv->panel_fixed_mode->VDisplay == 600)
-	    {
-		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-			   "Suspected Mac Mini, ignoring the LVDS\n");
-		goto disable_exit;
-	    }
+	{
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		    "Suspected Mac Mini, ignoring the LVDS\n");
+	    goto disable_exit;
 	}
     }
 
diff --git a/src/i830_quirks.c b/src/i830_quirks.c
new file mode 100644
index 0000000..1bf4692
--- /dev/null
+++ b/src/i830_quirks.c
@@ -0,0 +1,80 @@
+/*
+ * 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:
+ *    Zhenyu Wang <zhenyu.z.wang at intel.com>
+ *
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "i830.h"
+
+#define SUBSYS_ANY (~0)
+
+typedef struct {
+    int chipType;
+    int subsysVendor;
+    int subsysCard;
+    void (*hook)(I830Ptr);
+} i830_quirk, *i830_quirk_ptr;
+
+static void quirk_ignore_tv (I830Ptr pI830)
+{
+    pI830->quirk_flag |= QUIRK_IGNORE_TV;
+}
+
+static void quirk_ignore_lvds (I830Ptr pI830)
+{
+    pI830->quirk_flag |= QUIRK_IGNORE_LVDS;
+}
+
+static void quirk_mac_mini (I830Ptr pI830)
+{
+    pI830->quirk_flag |= QUIRK_IGNORE_MACMINI_LVDS;
+}
+
+static i830_quirk i830_quirk_list[] = {
+    /* Lenovo T61 has no TV output */
+    { PCI_CHIP_I965_GM, 0x17aa, 0x20b5, quirk_ignore_tv },
+    /* Aopen mini pc */
+    { PCI_CHIP_I945_GM, 0xa0a0, SUBSYS_ANY, quirk_ignore_lvds },
+    /* Mac mini has no lvds, but macbook pro does */
+    { PCI_CHIP_I945_GM, 0x8086, 0x7270, quirk_mac_mini },
+    { 0, 0, 0, NULL },
+};
+
+void i830_fixup_devices(ScrnInfoPtr scrn)
+{
+    I830Ptr pI830 = I830PTR(scrn);
+    i830_quirk_ptr p = i830_quirk_list;
+
+    while (p && p->chipType != 0) {
+	if (pI830->PciInfo->chipType == p->chipType &&
+		pI830->PciInfo->subsysVendor == p->subsysVendor &&
+		(pI830->PciInfo->subsysCard == p->subsysCard ||
+		 p->subsysCard == SUBSYS_ANY))
+	    p->hook(pI830);
+	++p;
+    }
+}
diff --git a/src/i830_tv.c b/src/i830_tv.c
index 8337d86..aba0e3b 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -1625,6 +1625,9 @@ i830_tv_init(ScrnInfoPtr pScrn)
     struct i830_tv_priv	    *dev_priv;
     CARD32		    tv_dac_on, tv_dac_off, save_tv_dac;
 
+    if (pI830->quirk_flag & QUIRK_IGNORE_TV)
+	return;
+
     if ((INREG(TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED)
 	return;
 
diff-tree 1a585d03972394cb97dec2462937b0104bdf4de2 (from 18c707a8c13ac5fffdd30d55e6f5926a68b367df)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jul 26 10:46:35 2007 -0700

    Use new drmBOSetPin interface instead of NO_EVICT/NO_MOVE buffers.
    
    To do this, we have to deal with buffer offsets being set at EnterVT time
    instead of screen init time. We've wanted to move this direction for a long
    time, but there are repercussions.  The EXA offscreen memory manager has to
    be disabled, because it can't be moved.  That will be replaced by BO-backed
    pixmaps soon.  Also unresolved is whether our moving
    front/back/depth/texture buffers will break the classic-mode DRI driver.
    
    This code doesn't actually work yet.

diff --git a/src/i830.h b/src/i830.h
index 6e1f88a..14de7f0 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -286,7 +286,13 @@ typedef struct _I830Rec {
    /* These are set in PreInit and never changed. */
    long FbMapSize;
 
-   i830_memory *memory_list;	/**< Linked list of video memory allocations */
+   /**
+    * Linked list of video memory allocations.  The head and tail are
+    * dummy entries that bound the allocation area.
+    */
+   i830_memory *memory_list;
+   /** Linked list of buffer object memory allocations */
+   i830_memory *bo_list;
    long stolen_size;		/**< bytes of pre-bound stolen memory */
    int gtt_acquired;		/**< whether we currently own the AGP */
 
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 20c6c68..929a541 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2403,8 +2403,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 
    I830UnmapMMIO(pScrn);
 
-   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");
@@ -2632,6 +2630,14 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    } else
       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Initializing SW Cursor!\n");
 
+#ifdef XF86DRI
+   /* Must be called before EnterVT, so we can acquire the DRI lock when
+    * binding our memory.
+    */
+   if (pI830->directRenderingEnabled)
+      pI830->directRenderingEnabled = I830DRIFinishScreenInit(pScreen);
+#endif
+
    if (!I830EnterVT(scrnIndex, 0))
       return FALSE;
 
@@ -2654,11 +2660,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       I830InitVideo(pScreen);
 #endif
 
-#ifdef XF86DRI
-   if (pI830->directRenderingEnabled)
-      pI830->directRenderingEnabled = I830DRIFinishScreenInit(pScreen);
-#endif
-
    /* Setup 3D engine, needed for rotation too */
    IntelEmitInvarientState(pScrn);
 
@@ -2802,6 +2803,7 @@ static Bool
 I830EnterVT(int scrnIndex, int flags)
 {
    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+   ScreenPtr pScreen = pScrn->pScreen;
    I830Ptr  pI830 = I830PTR(pScrn);
    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
    int o;
@@ -2823,6 +2825,18 @@ I830EnterVT(int scrnIndex, int flags)
       if (!i830_bind_all_memory(pScrn))
          return FALSE;
 
+   i830_describe_allocations(pScrn, 1, "");
+
+   /* Update buffer locations, which may have changed as a result of
+    * i830_bind_all_memory().
+    */
+   pScrn->fbOffset = pI830->front_buffer->offset;
+   if (!pScreen->ModifyPixmapHeader(pScreen->GetScreenPixmap(pScreen),
+				    -1, -1, -1, -1, -1,
+				    (pointer)(pI830->FbBase +
+					      pScrn->fbOffset)))
+       FatalError("Couldn't adjust screen pixmap\n");
+
    if (i830_check_error_state(pScrn)) {
       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		 "Existing errors found in hardware state.\n");
diff --git a/src/i830_exa.c b/src/i830_exa.c
index fed4067..e801d50 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -405,9 +405,14 @@ I830EXAInit(ScreenPtr pScreen)
     pI830->EXADriverPtr->exa_major = 2;
     pI830->EXADriverPtr->exa_minor = 1;
     pI830->EXADriverPtr->memoryBase = pI830->FbBase;
-    pI830->EXADriverPtr->offScreenBase = pI830->exa_offscreen->offset;
-    pI830->EXADriverPtr->memorySize = pI830->exa_offscreen->offset +
+    if (pI830->exa_offscreen) {
+	pI830->EXADriverPtr->offScreenBase = pI830->exa_offscreen->offset;
+	pI830->EXADriverPtr->memorySize = pI830->exa_offscreen->offset +
 	pI830->exa_offscreen->size;
+    } else {
+	pI830->EXADriverPtr->offScreenBase = pI830->FbMapSize;
+	pI830->EXADriverPtr->memorySize = pI830->FbMapSize;
+    }
     pI830->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS;
 
     DPRINTF(PFX, "EXA Mem: memoryBase 0x%x, end 0x%x, offscreen base 0x%x, memorySize 0x%x\n",
diff --git a/src/i830_memory.c b/src/i830_memory.c
index d4e9bff..80e3536 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -155,10 +155,25 @@ i830_bind_memory(ScrnInfoPtr pScrn, i830
 {
     I830Ptr pI830 = I830PTR(pScrn);
 
-    if (mem == NULL || mem->key == -1 || mem->bound || !pI830->gtt_acquired)
+    if (mem == NULL || mem->bound || !pI830->gtt_acquired)
 	return TRUE;
 
-    if (xf86BindGARTMemory(pScrn->scrnIndex, mem->key, mem->agp_offset)) {
+#ifdef XF86DRI_MM
+    if (mem->bo.size != 0) {
+	int ret;
+
+	ret = drmBOSetPin(pI830->drmSubFD, &mem->bo, 1);
+	mem->offset = mem->bo.offset;
+	mem->end = mem->offset + mem->size;
+	if (ret)
+	    return FALSE;
+	else
+	    return TRUE;
+    }
+#endif
+
+    if (mem->key == -1 ||
+	xf86BindGARTMemory(pScrn->scrnIndex, mem->key, mem->agp_offset)) {
 	mem->bound = TRUE;
 	return TRUE;
     } else {
@@ -171,10 +186,23 @@ i830_bind_memory(ScrnInfoPtr pScrn, i830
 static Bool
 i830_unbind_memory(ScrnInfoPtr pScrn, i830_memory *mem)
 {
-    if (mem == NULL || mem->key == -1 || !mem->bound)
+    if (mem == NULL || !mem->bound)
 	return TRUE;
 
-    if (xf86UnbindGARTMemory(pScrn->scrnIndex, mem->key)) {
+#ifdef XF86DRI_MM
+    if (mem->bo.size != 0) {
+	I830Ptr pI830 = I830PTR(pScrn);
+	int ret;
+
+	ret = drmBOSetPin(pI830->drmSubFD, &mem->bo, 0);
+	if (ret)
+	    return FALSE;
+	else
+	    return TRUE;
+    }
+#endif
+
+    if (mem->key == -1 || xf86UnbindGARTMemory(pScrn->scrnIndex, mem->key)) {
 	mem->bound = FALSE;
 	return TRUE;
     } else {
@@ -195,6 +223,12 @@ i830_free_memory(ScrnInfoPtr pScrn, i830
 #ifdef XF86DRI_MM
     if (mem->bo.size != 0) {
 	drmBOUnReference(pI830->drmSubFD, &mem->bo);
+	if (pI830->bo_list == mem)
+	    pI830->bo_list = mem->next;
+	if (mem->next)
+	    mem->next->prev = NULL;
+	if (mem->prev)
+	    mem->prev->next = NULL;
 	xfree(mem->name);
 	xfree(mem);
 	return;
@@ -615,7 +649,7 @@ i830_allocate_memory_bo(ScrnInfoPtr pScr
 {
     I830Ptr pI830 = I830PTR(pScrn);
     i830_memory *mem;
-    unsigned long hint, mask;
+    unsigned long mask;
     int ret;
 
     assert((flags & NEED_PHYSICAL_ADDR) == 0);
@@ -635,14 +669,10 @@ i830_allocate_memory_bo(ScrnInfoPtr pScr
     }
 
     mask = DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_MAPPABLE |
-	DRM_BO_FLAG_NO_EVICT | DRM_BO_FLAG_NO_MOVE;
-    hint = DRM_BO_HINT_DONT_FENCE | DRM_BO_HINT_DONT_BLOCK |
-	DRM_BO_HINT_ALLOW_UNFENCED_MAP;
+	DRM_BO_FLAG_MEM_TT;
 
-    I830DRILock(pScrn);
     ret = drmBOCreate(pI830->drmSubFD, 0, size, align / GTT_PAGE_SIZE, NULL,
-		      drm_bo_type_dc, mask, hint, &mem->bo);
-    I830DRIUnlock(pScrn);
+		      drm_bo_type_dc, mask, 0, &mem->bo);
     if (ret) {
 	xfree(mem->name);
 	xfree(mem);
@@ -653,6 +683,13 @@ i830_allocate_memory_bo(ScrnInfoPtr pScr
     mem->end = mem->bo.start + size;
     mem->size = size;
 
+    /* Insert new allocation into the list */
+    mem->prev = NULL;
+    mem->next = pI830->bo_list;
+    if (pI830->bo_list != NULL)
+	pI830->bo_list->prev = mem;
+    pI830->bo_list = mem;
+
     return mem;
 }
 #endif /* XF86DRI_MM */
@@ -711,6 +748,12 @@ i830_allocate_memory_tiled(ScrnInfoPtr p
     if (tile_format == TILING_NONE)
 	return i830_allocate_memory(pScrn, name, size, alignment, flags);
 
+    /* XXX: for now, refuse to tile with buffer object allocations,
+     * until we can move the set_fence (and failure recovery) into EnterVT.
+     */
+    if (pI830->memory_manager != NULL)
+	return NULL;
+
     /* Only allocate page-sized increments. */
     size = ALIGN(size, GTT_PAGE_SIZE);
 
@@ -811,7 +854,7 @@ i830_describe_allocations(ScrnInfoPtr pS
     }
 
     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-		   "%sMemory allocation layout:\n", prefix);
+		   "%sFixed memory allocation layout:\n", prefix);
 
     for (mem = pI830->memory_list->next; mem->next != NULL; mem = mem->next) {
 
@@ -831,7 +874,7 @@ i830_describe_allocations(ScrnInfoPtr pS
 	} else {
 	    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
 			   "%s0x%08lx-0x%08lx: %s "
-			   "(%ld kB, 0x%16llx physical)\n",
+			   "(%ld kB, 0x%016llx physical)\n",
 			   prefix,
 			   mem->offset, mem->end - 1, mem->name,
 			   mem->size / 1024, mem->bus_addr);
@@ -841,6 +884,25 @@ i830_describe_allocations(ScrnInfoPtr pS
 		   "%s0x%08lx:            end of aperture\n",
 		   prefix, pI830->FbMapSize);
 
+#ifdef XF86DRI_MM
+    if (pI830->memory_manager) {
+	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		       "%sBO memory allocation layout:\n", prefix);
+	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		       "%s0x%08lx:            start of memory manager\n",
+		       prefix, pI830->memory_manager->offset);
+	for (mem = pI830->bo_list; mem != NULL; mem = mem->next) {
+	    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);
+	}
+	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		       "%s0x%08lx:            end of memory manager\n",
+		       prefix, pI830->memory_manager->end);
+    }
+#endif /* XF86DRI_MM */
+
     if (pI830->front_buffer != NULL) {
 	i830_describe_tiling(pScrn, verbosity, prefix, pI830->front_buffer,
 			     pI830->front_tiled);
@@ -1305,7 +1367,12 @@ i830_allocate_2d_memory(ScrnInfoPtr pScr
 
 #ifdef I830_USE_EXA
     if (pI830->useEXA) {
-	if (pI830->exa_offscreen == NULL) {
+	/* With the kernel memory manager, the exa offscreen allocation would
+	 * change locations at EnterVT, which EXA is unprepared for.  The
+	 * performance of EXA offscreen memory management was low enough
+	 * that just not using it is reasonable.
+	 */
+	if (pI830->exa_offscreen == NULL && pI830->memory_manager == NULL) {
 	    /* Default EXA to having 3 screens worth of offscreen memory space
 	     * (for pixmaps), plus a double-buffered, 1920x1088 video's worth.
 	     *
@@ -1799,6 +1866,10 @@ i830_bind_all_memory(ScrnInfoPtr pScrn)
 		FatalError("Couldn't bind memory for %s\n", mem->name);
 	    }
 	}
+	for (mem = pI830->bo_list; mem != NULL; mem = mem->next) {
+	    if (!i830_bind_memory(pScrn, mem))
+		FatalError("Couldn't bind memory for BO %s\n", mem->name);
+	}
     }
 
     return TRUE;
@@ -1821,6 +1892,8 @@ i830_unbind_all_memory(ScrnInfoPtr pScrn
 	{
 	    i830_unbind_memory(pScrn, mem);
 	}
+	for (mem = pI830->bo_list; mem != NULL; mem = mem->next)
+	    i830_unbind_memory(pScrn, mem);
 
 	pI830->gtt_acquired = FALSE;
 
diff-tree 0fd3ba0518b3cde9ca0e4e2fc1854c00d8a43d5c (from 45962eed51120ff77326c29d72cf8b6cd8a934b5)
Author: Brice Goglin <Brice.Goglin at ens-lyon.org>
Date:   Wed Jul 25 20:11:32 2007 +0200

    Fix typo in intel.man
    
    Reported by A. Costa" <agcosta at gis.net> in
    http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=432061

diff --git a/man/intel.man b/man/intel.man
index 33dc319..5909fdd 100644
--- a/man/intel.man
+++ b/man/intel.man
@@ -141,7 +141,7 @@ and that is used with the 3D driver in M
 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 
+activate 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.
diff-tree 18c707a8c13ac5fffdd30d55e6f5926a68b367df (from 45962eed51120ff77326c29d72cf8b6cd8a934b5)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Jul 25 10:11:16 2007 -0700

    When TTM is available, use it instead of manual AGP allocations when possible.
    
    This is a step towards being able to expose buffer objects through the screen
    private to DRI clients, instead of having them have to use the fake buffer
    object type.
    
    This fails in two ways.  First, the kernel memory manager is not currently
    suitable for doing the physical allocations we need, so we still use AGP for
    those.  Additionally, the DRI lock can't be initialized early enough for us, so
    these buffer object allocations fail.  This will be fixed by improving the
    DRM interface.

diff --git a/man/intel.man b/man/intel.man
index 33dc319..c682d55 100644
--- a/man/intel.man
+++ b/man/intel.man
@@ -128,9 +128,8 @@ Default: XVideo is enabled for configura
 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. 
+This option is only used for chipsets in the range i830-i945.
+Default for i830-i945 series: Enabled.
 Default for i810: The option is not used.
 Default for i965: The option is always true.
 .TP
diff --git a/src/i830.h b/src/i830.h
index aa2b240..6e1f88a 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -158,6 +158,9 @@ struct _i830_memory {
     i830_memory *prev;
     /** @} */
 
+#ifdef XF86DRI_MM
+    drmBO bo;
+#endif
 };
 
 typedef struct {
@@ -328,8 +331,7 @@ typedef struct _I830Rec {
 
    int TexGranularity;
    int drmMinor;
-   int mmModeFlags;
-   int mmSize;
+   Bool allocate_classic_textures;
 
    unsigned int back_tiled;
    unsigned int third_tiled;
@@ -635,6 +637,7 @@ extern void I830SubsequentSolidFillRect(
 
 Bool i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset,
 			 unsigned long size);
+void i830_allocator_fini(ScrnInfoPtr pScrn);
 void i830_describe_allocations(ScrnInfoPtr pScrn, int verbosity,
 			       const char *prefix);
 void i830_reset_allocations(ScrnInfoPtr pScrn);
@@ -744,6 +747,7 @@ extern const int I830CopyROP[16];
 /* Flags for memory allocation function */
 #define NEED_PHYSICAL_ADDR		0x00000001
 #define ALIGN_BOTH_ENDS			0x00000002
+#define NEED_NON_STOLEN			0x00000004
 
 /* Chipset registers for VIDEO BIOS memory RW access */
 #define _855_DRAM_RW_CONTROL 0x58
diff --git a/src/i830_accel.c b/src/i830_accel.c
index 5cbad44..4d9ea79 100644
--- a/src/i830_accel.c
+++ b/src/i830_accel.c
@@ -254,6 +254,12 @@ I830RefreshRing(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
 
+   /* If we're reaching RefreshRing as a result of grabbing the DRI lock
+    * before we've set up the ringbuffer, don't bother.
+    */
+   if (pI830->LpRing->mem == NULL)
+       return;
+
    pI830->LpRing->head = INREG(LP_RING + RING_HEAD) & I830_HEAD_MASK;
    pI830->LpRing->tail = INREG(LP_RING + RING_TAIL);
    pI830->LpRing->space = pI830->LpRing->head - (pI830->LpRing->tail + 8);
diff --git a/src/i830_dri.c b/src/i830_dri.c
index ca1190c..0d511d2 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -546,16 +546,12 @@ I830DRIScreenInit(ScreenPtr pScreen)
    pDRIInfo->ddxDriverMajorVersion = I830_MAJOR_VERSION;
    pDRIInfo->ddxDriverMinorVersion = I830_MINOR_VERSION;
    pDRIInfo->ddxDriverPatchVersion = I830_PATCHLEVEL;
-#if 1 /* Remove this soon - see bug 5714 */
-   pDRIInfo->frameBufferPhysicalAddress = (char *) pI830->LinearAddr +
-					  pI830->front_buffer->offset;
-   pDRIInfo->frameBufferSize = ROUND_TO_PAGE(pScrn->displayWidth *
-					     pScrn->virtualY * pI830->cpp);
-#else
-   /* For rotation we map a 0 length framebuffer as we remap ourselves later */
-   pDRIInfo->frameBufferSize = 0;
-#endif
-   pDRIInfo->frameBufferStride = pScrn->displayWidth * pI830->cpp;
+   /* Supply a dummy mapping info required by DRI setup.  See bug #5714 for
+    * progress on removing this requirement.
+    */
+   pDRIInfo->frameBufferPhysicalAddress = (char *) pI830->LinearAddr;
+   pDRIInfo->frameBufferSize = GTT_PAGE_SIZE;
+   pDRIInfo->frameBufferStride = 1;
    pDRIInfo->ddxDrawableTableEntry = I830_MAX_DRAWABLES;
 
    if (SAREA_MAX_DRAWABLES < I830_MAX_DRAWABLES)
@@ -637,11 +633,11 @@ I830DRIScreenInit(ScreenPtr pScreen)
       return FALSE;
    }
 
-#if 0 /* disabled now, see frameBufferSize above being set to 0 */
-   /* for this driver, get rid of the front buffer mapping now */
+   /* Now, nuke dri.c's frontbuffer map setup. */
+#if 0
    if (xf86LoaderCheckSymbol("DRIGetScreenPrivate")) {
-      DRIScreenPrivPtr pDRIPriv 
-         = (DRIScreenPrivPtr) DRIGetScreenPrivate(pScreen);
+      DRIScreenPrivPtr pDRIPriv =
+	  (DRIScreenPrivPtr) DRIGetScreenPrivate(pScreen);
 
       if (pDRIPriv && pDRIPriv->drmFD && pDRIPriv->hFrameBuffer) {
          xf86DrvMsg(pScreen->myNum, X_ERROR,
@@ -652,11 +648,25 @@ I830DRIScreenInit(ScreenPtr pScreen)
                     "[intel] done removing original screen mapping\n");
       }
    }
-   else {
-      xf86DrvMsg(pScreen->myNum, X_ERROR,
-                 "[intel] DRIGetScreenPrivate not found!!!!\n");
-   }      
 #endif
+   {
+       int tmp;
+       unsigned int fb_handle;
+       void *ptmp;
+
+       /* With the compat method, it will continue to report
+	* the wrong map out of GetDeviceInfo, but we don't have any consumers
+	* of the frontbuffer handle from there.
+	*/
+       DRIGetDeviceInfo(pScreen, &fb_handle, &tmp, &tmp, &tmp, &tmp, &ptmp);
+       drmRmMap(pI830->drmSubFD, fb_handle);
+
+       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		  "Removed DRI frontbuffer mapping in compatibility mode.\n");
+       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		  "DRIGetDeviceInfo will report incorrect frontbuffer "
+		  "handle.\n");
+   }
 
    /* Check the i915 DRM versioning */
    {
@@ -724,27 +734,6 @@ I830DRIScreenInit(ScreenPtr pScreen)
 	    return FALSE;
 	 }
 	 pI830->drmMinor = version->version_minor;
-	 if (version->version_minor < 7) {
-	    if (pI830->mmModeFlags & I830_KERNEL_MM) {
-	       xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-			  "Unable to use TTM-based memory manager with DRM version %d.%d\n",
-			  version->version_major, version->version_minor);
-	       pI830->mmModeFlags &= ~I830_KERNEL_MM;
-
-	       i830_free_memory(pScrn, pI830->memory_manager);
-	       pI830->memory_manager = NULL;
-
-	       if (!(pI830->mmModeFlags & I830_KERNEL_TEX)) {
-		  pI830->mmModeFlags |= I830_KERNEL_TEX;
-
-		  if (!i830_allocate_texture_memory(pScrn)) {
-		     I830DRICloseScreen(pScreen);
-		     drmFreeVersion(version);
-		     return FALSE;
-		  }
-	       }
-	    }
-	 }
 #ifdef DAMAGE
 	 if (pI830->allowPageFlip && pI830->drmMinor < 9) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
@@ -762,7 +751,7 @@ I830DRIScreenInit(ScreenPtr pScreen)
     */
 
    if ((pDRIInfo->clientDriverName == I830ClientDriverName) && 
-       (pI830->mmModeFlags & I830_KERNEL_TEX)) {
+       (pI830->allocate_classic_textures)) {
       pDRIInfo->clientDriverName = I830LegacyClientDriverName;
    }
 
@@ -780,26 +769,21 @@ I830DRIMapScreenRegions(ScrnInfoPtr pScr
 					     pScrn->virtualY * pI830->cpp);
 #endif
 
-   /* The I965G isn't ready for the front buffer mapping to be moved around,
-    * because of issues with rmmap, it seems.
-    */
-   if (!IS_I965G(pI830)) {
-      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		 "[drm] Mapping front buffer\n");
-      if (drmAddMap(pI830->drmSubFD,
-		    (drm_handle_t)(sarea->front_offset + pI830->LinearAddr),
-		    sarea->front_size,
-		    DRM_AGP,
-		    0,
-		    (drmAddress) &sarea->front_handle) < 0) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		    "[drm] drmAddMap(front_handle) failed. Disabling DRI\n");
-	 DRICloseScreen(pScreen);
-	 return FALSE;
-      }
-      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Front Buffer = 0x%08x\n",
-		 (int)sarea->front_handle);
+   xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+	      "[drm] Mapping front buffer\n");
+   if (drmAddMap(pI830->drmSubFD,
+		 (drm_handle_t)(sarea->front_offset + pI830->LinearAddr),
+		 sarea->front_size,
+		 DRM_AGP,
+		 0,
+		 (drmAddress) &sarea->front_handle) < 0) {
+       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		  "[drm] drmAddMap(front_handle) failed. Disabling DRI\n");
+       DRICloseScreen(pScreen);
+       return FALSE;
    }
+   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Front Buffer = 0x%08x\n",
+	      (int)sarea->front_handle);
 
    if (drmAddMap(pI830->drmSubFD,
                  (drm_handle_t)(sarea->back_offset + pI830->LinearAddr),
@@ -841,7 +825,7 @@ I830DRIMapScreenRegions(ScrnInfoPtr pScr
    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Depth Buffer = 0x%08x\n",
               (int)sarea->depth_handle);
 
-   if (pI830->mmModeFlags & I830_KERNEL_TEX) {
+   if (pI830->allocate_classic_textures) {
       if (drmAddMap(pI830->drmSubFD,
 		    (drm_handle_t)sarea->tex_offset + pI830->LinearAddr,
 		    sarea->tex_size, DRM_AGP, 0,
@@ -1710,7 +1694,7 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, 
 
    success = I830DRIMapScreenRegions(pScrn, sarea);
 
-   if (success && (pI830->mmModeFlags & I830_KERNEL_TEX))
+   if (success && pI830->allocate_classic_textures)
       I830InitTextureHeap(pScrn, sarea);
 
    return success;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 9bb12c6..20c6c68 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -290,7 +290,6 @@ typedef enum {
    OPTION_TILING,
 #ifdef XF86DRI_MM
    OPTION_INTELTEXPOOL,
-   OPTION_INTELMMSIZE,
 #endif
    OPTION_TRIPLEBUFFER,
 } I830Opts;
@@ -313,7 +312,6 @@ static OptionInfoRec I830Options[] = {
    {OPTION_TILING,	"Tiling",	OPTV_BOOLEAN,	{0},	TRUE},
 #ifdef XF86DRI_MM
    {OPTION_INTELTEXPOOL,"Legacy3D",     OPTV_BOOLEAN,	{0},	FALSE},
-   {OPTION_INTELMMSIZE, "AperTexSize",  OPTV_INTEGER,	{0},	FALSE},
 #endif
    {OPTION_TRIPLEBUFFER, "TripleBuffer", OPTV_BOOLEAN,	{0},	FALSE},
    {-1,			NULL,		OPTV_NONE,	{0},	FALSE}
@@ -1319,50 +1317,22 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 	 pI830->directRenderingDisabled = TRUE;
       }
 
-      pI830->mmModeFlags = 0;
-
       if (!pI830->directRenderingDisabled) {
-	 pI830->mmModeFlags = I830_KERNEL_TEX;
-#ifdef XF86DRI_MM
-	 Bool tmp = FALSE;
-
-	 if (!IS_I965G(pI830))
-	    pI830->mmModeFlags |= I830_KERNEL_MM;
-#endif
+	 pI830->allocate_classic_textures = TRUE;
 
 	 from = X_PROBED;
 
 #ifdef XF86DRI_MM
-	 if (xf86GetOptValBool(pI830->Options, 
-			       OPTION_INTELTEXPOOL, &tmp)) {
-	    from = X_CONFIG;
-	    if (tmp) {
-	       pI830->mmModeFlags |= I830_KERNEL_TEX;
-	       pI830->mmModeFlags &= ~I830_KERNEL_MM;
-	    } else {
-	       pI830->mmModeFlags &= ~I830_KERNEL_TEX;
-	       pI830->mmModeFlags |= I830_KERNEL_MM;
-	    }	       
-	 }
-#endif
-
-	 xf86DrvMsg(pScrn->scrnIndex, from,
-		    "Will %stry to allocate texture pool "
-		    "for old Mesa 3D driver.\n",
-		    (pI830->mmModeFlags & I830_KERNEL_TEX) ?
-		    "" : "not ");
+	 if (!IS_I965G(pI830)) {
+	    Bool tmp;
 
-#ifdef XF86DRI_MM
-	 pI830->mmSize = I830_MM_MAXSIZE;
-	 from = X_INFO;
-	 if (xf86GetOptValInteger(pI830->Options, OPTION_INTELMMSIZE,
-				  &(pI830->mmSize))) {
-	    from = X_CONFIG;
+	    if (xf86GetOptValBool(pI830->Options,
+				  OPTION_INTELTEXPOOL, &tmp)) {
+	       from = X_CONFIG;
+	       if (!tmp)
+		  pI830->allocate_classic_textures = FALSE;
+	    }
 	 }
-	 xf86DrvMsg(pScrn->scrnIndex, from, 
-		    "Will try to reserve %d kiB of AGP aperture space\n"
-		    "\tfor the DRM memory manager.\n",
-		    pI830->mmSize);
 #endif
       }
    } 
@@ -2128,12 +2098,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    int i;
    Bool allocation_done = FALSE;
    MessageType from;
-#ifdef XF86DRI
-   Bool driDisabled;
-#ifdef XF86DRI_MM
-   unsigned long savedMMSize;
-#endif
-#endif
 
    pScrn = xf86Screens[pScreen->myNum];
    pI830 = I830PTR(pScrn);
@@ -2227,6 +2191,23 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       pScrn->videoRam &= ~3;
    }
 
+#ifdef XF86DRI
+   /* Check for appropriate bpp and module support to initialize DRI. */
+   if (!I830CheckDRIAvailable(pScrn)) {
+      pI830->directRenderingDisabled = TRUE;
+   }
+
+   /* If DRI hasn't been explicitly disabled, try to initialize it.
+    * It will be used by the memory allocator.
+    */
+   if (!pI830->directRenderingDisabled)
+      pI830->directRenderingEnabled = I830DRIScreenInit(pScreen);
+   else
+      pI830->directRenderingEnabled = FALSE;
+#else
+   pI830->directRenderingEnabled = FALSE;
+#endif
+
    /* 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,
@@ -2321,12 +2302,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
     * for it, and if there's also enough to allow tiling to be enabled.
     */
 
-   if (!I830CheckDRIAvailable(pScrn)) {
-      pI830->directRenderingDisabled = TRUE;
-#ifdef XF86DRI_MM
-      pI830->mmSize = 0;
-#endif
-   }
 
 #ifdef I830_XV
     /*
@@ -2336,7 +2311,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
     pI830->XvEnabled = !pI830->XvDisabled;
 #endif
 
-   if (!pI830->directRenderingDisabled) {
+   if (pI830->directRenderingEnabled) {
       int savedDisplayWidth = pScrn->displayWidth;
       Bool tiled = FALSE;
 
@@ -2366,25 +2341,18 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 	 }
       }
 
-      /* Attempt several rounds of allocation to get 2d and 3d memory to fit:
+      /* Attempt two 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
+       * 0: untiled
+       * 1: tiled
        */
 
-#ifdef XF86DRI_MM
-      savedMMSize = pI830->mmSize;
-#define MM_TURNS 4
-#else
 #define MM_TURNS 2
-#endif
       for (i = 0; i < MM_TURNS; i++) {
-	 if (!tiled && i < 2)
+	 if (!tiled && i == 0)
 	    continue;
 
-	 if (i >= MM_TURNS/2) {
+	 if (i >= 1) {
 	    /* For further allocations, disable tiling */
 	    pI830->tiling = FALSE;
 	    pScrn->displayWidth = savedDisplayWidth;
@@ -2395,26 +2363,9 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 	    pI830->allowPageFlip = FALSE;
 	 }
 
-#ifdef XF86DRI_MM
-	 if (i & 1) {
-	    /* For this allocation, switch to a smaller DRI memory manager
-	     * size.
-	     */
-	    pI830->mmSize = I830_MM_MINPAGES * GTT_PAGE_SIZE / KB(1);
-	 } 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");
-#else
 	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		    "Attempting memory allocation with %s buffers:\n",
+		    "Attempting memory allocation with %s buffers.\n",
 		    (i & 1) ? "untiled" : "tiled");
-#endif
 
 	 if (i830_allocate_2d_memory(pScrn) &&
 	     i830_allocate_3d_memory(pScrn))
@@ -2436,10 +2387,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       if (i == MM_TURNS) {
 	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		    "Not enough video memory.  Disabling DRI.\n");
-#ifdef XF86DRI_MM
-	 pI830->mmSize = 0;
-#endif
-	 pI830->directRenderingDisabled = TRUE;
+	 pI830->directRenderingEnabled = FALSE;
       }
    }
 #endif
@@ -2461,7 +2409,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		 "Cannot support DRI with frame buffer width > 2048.\n");
       pI830->tiling = FALSE;
-      pI830->directRenderingDisabled = TRUE;
+      pI830->directRenderingEnabled = FALSE;
    }
 
    pScrn->displayWidth = pScrn->displayWidth;
@@ -2563,11 +2511,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 
 #ifdef XF86DRI
    /*
-    * pI830->directRenderingDisabled is set once in PreInit.  Reinitialise
-    * pI830->directRenderingEnabled based on it each generation.
-    */
-   pI830->directRenderingEnabled = !pI830->directRenderingDisabled;
-   /*
     * Setup DRI after visuals have been established, but before fbScreenInit
     * is called.   fbScreenInit will eventually call into the drivers
     * InitGLXVisuals call back.
@@ -2578,26 +2521,21 @@ 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);
       }
    }
 
-   driDisabled = !pI830->directRenderingEnabled;
-
    if (pI830->directRenderingEnabled)
-      pI830->directRenderingEnabled = I830DRIScreenInit(pScreen);
+      pI830->directRenderingEnabled = I830DRIDoMappings(pScreen);
 
-   if (!pI830->directRenderingEnabled) {
+   /* If we failed for any reason, free DRI memory. */
+   if (!pI830->directRenderingEnabled)
       i830_free_3d_memory(pScrn);
-   }
 
 #else
    pI830->directRenderingEnabled = FALSE;
 #endif
 
 #ifdef XF86DRI
-   if (pI830->directRenderingEnabled)
-      pI830->directRenderingEnabled = I830DRIDoMappings(pScreen);
 
    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Page Flipping %sabled\n",
 	      pI830->allowPageFlip ? "en" : "dis");
@@ -2717,9 +2655,8 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 #endif
 
 #ifdef XF86DRI
-   if (pI830->directRenderingEnabled) {
+   if (pI830->directRenderingEnabled)
       pI830->directRenderingEnabled = I830DRIFinishScreenInit(pScreen);
-   }
 #endif
 
    /* Setup 3D engine, needed for rotation too */
@@ -2730,7 +2667,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       pI830->directRenderingOpen = TRUE;
       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering: Enabled\n");
    } else {
-      if (driDisabled)
+      if (pI830->directRenderingDisabled)
 	 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering: Disabled\n");
       else
 	 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering: Failed\n");
@@ -2771,37 +2708,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    pI830->closing = FALSE;
    pI830->suspended = FALSE;
 
-#ifdef XF86DRI_MM
-   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"
-		    "\tDisabling DRI.\n");
-	 pI830->directRenderingOpen = FALSE;
-	 I830DRICloseScreen(pScreen);
-	 pI830->directRenderingEnabled = FALSE;
-      } else {
-	 unsigned long aperEnd = ROUND_DOWN_TO(pI830->memory_manager->offset +
-					       pI830->memory_manager->size,
-					       GTT_PAGE_SIZE) / GTT_PAGE_SIZE;
-	 unsigned long aperStart = ROUND_TO(pI830->memory_manager->offset,
-					    GTT_PAGE_SIZE) / GTT_PAGE_SIZE;
-
-	 if (drmMMInit(pI830->drmSubFD, aperStart, aperEnd - aperStart,
-		       DRM_BO_MEM_TT)) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 
-		       "Could not initialize the DRM memory manager.\n");
-	    
-	    pI830->directRenderingOpen = FALSE;
-	    I830DRICloseScreen(pScreen);
-	    pI830->directRenderingEnabled = FALSE;
-	 }
-      }
-   }
-#endif /* XF86DRI_MM */
-
    return TRUE;
 }
 
@@ -2862,7 +2768,7 @@ I830LeaveVT(int scrnIndex, int flags)
    if (pI830->directRenderingOpen) {
       DRILock(screenInfo.screens[pScrn->scrnIndex], 0);
 #ifdef XF86DRI_MM
-      if (pI830->mmModeFlags & I830_KERNEL_MM) {
+      if (pI830->memory_manager != NULL) {
 	 drmMMLock(pI830->drmSubFD, DRM_BO_MEM_TT);
       }
 #endif /* XF86DRI_MM */
@@ -2967,7 +2873,7 @@ I830EnterVT(int scrnIndex, int flags)
 	    sarea->texList[i].age = sarea->texAge;
 
 #ifdef XF86DRI_MM
-	 if (pI830->mmModeFlags & I830_KERNEL_MM) {
+	 if (pI830->memory_manager != NULL) {
 	    drmMMUnlock(pI830->drmSubFD, DRM_BO_MEM_TT);
 	 }
 #endif /* XF86DRI_MM */
@@ -3014,26 +2920,6 @@ I830CloseScreen(int scrnIndex, ScreenPtr
 #endif
 
    pI830->closing = TRUE;
-#ifdef XF86DRI
-   if (pI830->directRenderingOpen) {
-#ifdef DAMAGE
-      if (pI830->pDamage) {
-	 PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen);
-
-	 DamageUnregister(&pPix->drawable, pI830->pDamage);
-	 DamageDestroy(pI830->pDamage);
-	 pI830->pDamage = NULL;
-      }
-#endif
-#ifdef XF86DRI_MM
-      if (pI830->mmModeFlags & I830_KERNEL_MM) {
-	 drmMMTakedown(pI830->drmSubFD, DRM_BO_MEM_TT);	 
-      }
-#endif /* XF86DRI_MM */
-      pI830->directRenderingOpen = FALSE;
-      I830DRICloseScreen(pScreen);
-   }
-#endif
 
    if (pScrn->vtSema == TRUE) {
       I830LeaveVT(scrnIndex, 0);
@@ -3068,7 +2954,22 @@ I830CloseScreen(int scrnIndex, ScreenPtr
 #endif
    xf86_cursors_fini (pScreen);
 
-   i830_reset_allocations(pScrn);
+   i830_allocator_fini(pScrn);
+#ifdef XF86DRI
+   if (pI830->directRenderingOpen) {
+#ifdef DAMAGE
+      if (pI830->pDamage) {
+	 PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen);
+
+	 DamageUnregister(&pPix->drawable, pI830->pDamage);
+	 DamageDestroy(pI830->pDamage);
+	 pI830->pDamage = NULL;
+      }
+#endif
+      pI830->directRenderingOpen = FALSE;
+      I830DRICloseScreen(pScreen);
+   }
+#endif
 
    if (I830IsPrimary(pScrn)) {
       xf86GARTCloseScreen(scrnIndex);
diff --git a/src/i830_memory.c b/src/i830_memory.c
index b38a5df..d4e9bff 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -114,6 +114,9 @@ enum tile_format {
     TILING_YMAJOR
 };
 
+static i830_memory *
+i830_allocate_aperture(ScrnInfoPtr pScrn, const char *name,
+		       long size, unsigned long alignment, int flags);
 static void i830_set_fence(ScrnInfoPtr pScrn, int nr, unsigned int offset,
 			   unsigned int pitch, unsigned int size,
 			   enum tile_format tile_format);
@@ -182,10 +185,22 @@ i830_unbind_memory(ScrnInfoPtr pScrn, i8
 void
 i830_free_memory(ScrnInfoPtr pScrn, i830_memory *mem)
 {
+#ifdef XF86DRI_MM
+    I830Ptr pI830 = I830PTR(pScrn);
+#endif
+
     if (mem == NULL)
 	return;
 
-    /* Disconnect from the list of allocations */
+#ifdef XF86DRI_MM
+    if (mem->bo.size != 0) {
+	drmBOUnReference(pI830->drmSubFD, &mem->bo);
+	xfree(mem->name);
+	xfree(mem);
+	return;
+    }
+#endif
+	    /* Disconnect from the list of allocations */
     if (mem->prev != NULL)
 	mem->prev->next = mem->next;
     if (mem->next != NULL)
@@ -237,7 +252,6 @@ i830_reset_allocations(ScrnInfoPtr pScrn
     pI830->third_buffer = NULL;
     pI830->depth_buffer = NULL;
     pI830->textures = NULL;
-    pI830->memory_manager = NULL;
 #endif
     pI830->LpRing->mem = NULL;
 
@@ -260,21 +274,24 @@ i830_free_3d_memory(ScrnInfoPtr pScrn)
     pI830->depth_buffer = NULL;
     i830_free_memory(pScrn, pI830->textures);
     pI830->textures = NULL;
-    i830_free_memory(pScrn, pI830->memory_manager);
-    pI830->memory_manager = NULL;
 #endif
 }
 
 /**
  * Initialize's the driver's video memory allocator to allocate in the
  * given range.
+ *
+ * This sets up the kernel memory manager to manage as much of the memory
+ * as we think it can, while leaving enough to us to fulfill our non-TTM
+ * static allocations.  Some of these exist because of the need for physical
+ * addresses to reference.
  */
 Bool
-i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset,
-		    unsigned long size)
+i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset, unsigned long size)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     i830_memory *start, *end;
+    int ret;
 
     start = xcalloc(1, sizeof(*start));
     if (start == NULL)
@@ -311,9 +328,82 @@ i830_allocator_init(ScrnInfoPtr pScrn, u
 
     pI830->memory_list = start;
 
+#ifdef XF86DRI_MM
+    /* Now that we have our manager set up, initialize the kernel MM if
+     * possible, covering almost all of the aperture.
+     */
+    if (pI830->directRenderingEnabled && pI830->drmMinor >= 7) {
+	int mmsize;
+
+	/* Take over all of the graphics aperture minus enough to for
+	 * physical-address allocations of cursor/overlay registers.
+	 */
+	mmsize = size;
+	if (!OVERLAY_NOPHYSICAL(pI830) && !IS_I965G(pI830)) {
+	    mmsize -= ROUND_TO(OVERLAY_SIZE, GTT_PAGE_SIZE);
+	    if (pI830->CursorNeedsPhysical) {
+		mmsize -= 2 * (ROUND_TO(HWCURSOR_SIZE, GTT_PAGE_SIZE) +
+			     ROUND_TO(HWCURSOR_SIZE_ARGB, GTT_PAGE_SIZE));
+	    }
+	}
+	if (pI830->fb_compression)
+	    mmsize -= MB(6);
+	/* Can't do TTM on stolen memory */
+	mmsize -= pI830->stolen_size;
+
+	/* Create the aperture allocation */
+	pI830->memory_manager =
+	    i830_allocate_aperture(pScrn, "DRI memory manager",
+				   mmsize, GTT_PAGE_SIZE,
+				   ALIGN_BOTH_ENDS | NEED_NON_STOLEN);
+
+	if (pI830->memory_manager != NULL) {
+	    /* Tell the kernel to manage it */
+	    ret = drmMMInit(pI830->drmSubFD,
+			    pI830->memory_manager->offset / GTT_PAGE_SIZE,
+			    pI830->memory_manager->size / GTT_PAGE_SIZE,
+			    DRM_BO_MEM_TT);
+	    if (ret != 0) {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			   "Failed to initialize kernel memory manager\n");
+		i830_free_memory(pScrn, pI830->memory_manager);
+		pI830->memory_manager = NULL;
+	    }
+	} else {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Failed to allocate space for kernel memory manager\n");
+	    i830_free_memory(pScrn, pI830->memory_manager);
+	    pI830->memory_manager = NULL;
+	}
+    }
+#endif /* XF86DRI_MM */
+
     return TRUE;
 }
 
+void
+i830_allocator_fini(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    /* Free most of the allocations */
+    i830_reset_allocations(pScrn);
+
+#ifdef XF86DRI_MM
+    /* The memory manager is more special */
+    if (pI830->memory_manager) {
+	 drmMMTakedown(pI830->drmSubFD, DRM_BO_MEM_TT);
+	 i830_free_memory(pScrn, pI830->memory_manager);
+	 pI830->memory_manager = NULL;
+    }
+#endif /* XF86DRI_MM */
+
+    /* Free the start/end markers */
+    free(pI830->memory_list->next);
+    free(pI830->memory_list);
+    pI830->memory_list = NULL;
+}
+
 /**
  * Reads a GTT entry for the memory at the given offset and returns the
  * physical address.
@@ -447,6 +537,9 @@ i830_allocate_aperture(ScrnInfoPtr pScrn
 		mem->offset = ROUND_TO(pI830->stolen_size, alignment);
 	    }
 	}
+	if ((flags & NEED_NON_STOLEN) && mem->offset < pI830->stolen_size) {
+	    mem->offset = ROUND_TO(pI830->stolen_size, alignment);
+	}
 
 	mem->end = mem->offset + size;
 	if (flags & ALIGN_BOTH_ENDS)
@@ -515,25 +608,80 @@ i830_allocate_agp_memory(ScrnInfoPtr pSc
     return TRUE;
 }
 
+#ifdef XF86DRI_MM
+static i830_memory *
+i830_allocate_memory_bo(ScrnInfoPtr pScrn, const char *name,
+			unsigned long size, unsigned long align, int flags)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    i830_memory *mem;
+    unsigned long hint, mask;
+    int ret;
+
+    assert((flags & NEED_PHYSICAL_ADDR) == 0);
+
+    /* Only allocate page-sized increments. */
+    size = ALIGN(size, GTT_PAGE_SIZE);
+    align = ROUND_TO(align, GTT_PAGE_SIZE);
+
+    mem = xcalloc(1, sizeof(*mem));
+    if (mem == NULL)
+	return NULL;
+
+    mem->name = xstrdup(name);
+    if (name == NULL) {
+	xfree(mem);
+	return NULL;
+    }
+
+    mask = DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_MAPPABLE |
+	DRM_BO_FLAG_NO_EVICT | DRM_BO_FLAG_NO_MOVE;
+    hint = DRM_BO_HINT_DONT_FENCE | DRM_BO_HINT_DONT_BLOCK |
+	DRM_BO_HINT_ALLOW_UNFENCED_MAP;
+
+    I830DRILock(pScrn);
+    ret = drmBOCreate(pI830->drmSubFD, 0, size, align / GTT_PAGE_SIZE, NULL,
+		      drm_bo_type_dc, mask, hint, &mem->bo);
+    I830DRIUnlock(pScrn);
+    if (ret) {
+	xfree(mem->name);
+	xfree(mem);
+	return NULL;
+    }
+
+    mem->offset = mem->bo.offset;
+    mem->end = mem->bo.start + size;
+    mem->size = size;
+
+    return mem;
+}
+#endif /* XF86DRI_MM */
 
 /* Allocates video memory at the given size and alignment.
  *
  * The memory will be bound automatically when the driver is in control of the
- * VT.
+ * VT.  When the kernel memory manager is available and compatible with flags
+ * (that is, flags doesn't say that the allocation must include a physical
+ * address), that will be used for the allocation.
  */
 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;
 
-    mem = i830_allocate_aperture(pScrn, name, size, alignment, flags);
-    if (mem == NULL)
-	return NULL;
+    if (pI830->memory_manager && !(flags & NEED_PHYSICAL_ADDR)) {
+	return i830_allocate_memory_bo(pScrn, name, size, alignment, flags);
+    } else {
+	mem = i830_allocate_aperture(pScrn, name, size, alignment, flags);
+	if (mem == NULL)
+	    return NULL;
 
-    if (!i830_allocate_agp_memory(pScrn, mem, flags)) {
-	i830_free_memory(pScrn, mem);
-	return NULL;
+	if (!i830_allocate_agp_memory(pScrn, mem, flags)) {
+	    i830_free_memory(pScrn, mem);
+	    return NULL;
+	}
     }
 
     return mem;
@@ -588,7 +736,7 @@ i830_allocate_memory_tiled(ScrnInfoPtr p
 	aper_align = alignment;
 
     fence_divide = 1;
-    mem = i830_allocate_aperture(pScrn, name, aper_size, aper_align, flags);
+    mem = i830_allocate_memory(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
@@ -604,8 +752,8 @@ i830_allocate_memory_tiled(ScrnInfoPtr p
 		break;
 	    }
 
-	    mem = i830_allocate_aperture(pScrn, name, aper_size,
-					 aper_align / fence_divide, flags);
+	    mem = i830_allocate_memory(pScrn, name, aper_size,
+				       aper_align / fence_divide, flags);
 	}
     }
 
@@ -623,12 +771,6 @@ i830_allocate_memory_tiled(ScrnInfoPtr p
 	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++,
@@ -1341,17 +1483,7 @@ i830_allocate_texture_memory(ScrnInfoPtr
     unsigned long size;
     int i;
 
-    if (pI830->mmModeFlags & I830_KERNEL_MM) {
-	pI830->memory_manager =
-	    i830_allocate_aperture(pScrn, "DRI memory manager",
-				   pI830->mmSize * KB(1), GTT_PAGE_SIZE,
-				   ALIGN_BOTH_ENDS);
-	/* XXX: try memory manager size backoff here? */
-	if (pI830->memory_manager == NULL)
-	    return FALSE;
-    }
-
-    if (pI830->mmModeFlags & I830_KERNEL_TEX) {
+    if (pI830->allocate_classic_textures) {
 	/* XXX: auto-sizing */
 	size = MB(32);
 	i = myLog2(size / I830_NR_TEX_REGIONS);
@@ -1368,7 +1500,7 @@ i830_allocate_texture_memory(ScrnInfoPtr
 		       size / 1024);
 	    return FALSE;
 	}
-	pI830->textures = i830_allocate_memory(pScrn, "textures", size,
+	pI830->textures = i830_allocate_memory(pScrn, "classic textures", size,
 					       GTT_PAGE_SIZE, 0);
 	if (pI830->textures == NULL) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
diff-tree 45962eed51120ff77326c29d72cf8b6cd8a934b5 (from b1af2c0e01c54ef1d40fd0ca1ede29a1dd7ed97b)
Author: Zhenyu Wang <zhenyu.z.wang at intel.com>
Date:   Mon Jul 23 09:50:17 2007 +0800

    Fix a typo in i915 render
    
    Fence setting is in mapstate actually. This fixes rotation in
    tiled fb case, thanks Keith to report this.

diff --git a/src/i915_render.c b/src/i915_render.c
index 9d5bc0a..9c937f2 100644
--- a/src/i915_render.c
+++ b/src/i915_render.c
@@ -288,7 +288,7 @@ i915_texture_setup(PicturePtr pPict, Pix
 	((pPix->drawable.height - 1) << MS3_HEIGHT_SHIFT) |
 	((pPix->drawable.width - 1) << MS3_WIDTH_SHIFT);
     if (pI830->tiling)
-	pI830->samplerstate[unit * 3 + 1] |= MS3_USE_FENCE_REGS;
+	pI830->mapstate[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 <<
diff-tree b1af2c0e01c54ef1d40fd0ca1ede29a1dd7ed97b (from c7920a0e819308762fca3d6fc7ab194bd565b06a)
Author: Zhenyu Wang <zhenyu.z.wang at intel.com>
Date:   Fri Jul 20 15:18:48 2007 +0800

    Fix device id info for 945GME, 965GME
    
    which do have new host bridge ids

diff --git a/src/common.h b/src/common.h
index cc07e49..fa96a5d 100644
--- a/src/common.h
+++ b/src/common.h
@@ -331,10 +331,14 @@ extern int I810_DEBUG;
 
 #ifndef PCI_CHIP_I945_GM
 #define PCI_CHIP_I945_GM        0x27A2
-#define PCI_CHIP_I945_GME	0x27AE
 #define PCI_CHIP_I945_GM_BRIDGE 0x27A0
 #endif
 
+#ifndef PCI_CHIP_I945_GME
+#define PCI_CHIP_I945_GME	 0x27AE
+#define PCI_CHIP_I945_GME_BRIDGE 0x27AC
+#endif
+
 #ifndef PCI_CHIP_I965_G_1
 #define PCI_CHIP_I965_G_1		0x2982
 #define PCI_CHIP_I965_G_1_BRIDGE 	0x2980
@@ -357,10 +361,14 @@ extern int I810_DEBUG;
 
 #ifndef PCI_CHIP_I965_GM
 #define PCI_CHIP_I965_GM        0x2A02
-#define PCI_CHIP_I965_GME	0x2A12
 #define PCI_CHIP_I965_GM_BRIDGE 0x2A00
 #endif
 
+#ifndef PCI_CHIP_I965_GME
+#define PCI_CHIP_I965_GME       0x2A12
+#define PCI_CHIP_I965_GME_BRIDGE 0x2A10
+#endif
+
 #ifndef PCI_CHIP_G33_G
 #define PCI_CHIP_G33_G		0x29C2
 #define PCI_CHIP_G33_G_BRIDGE 	0x29C0
diff-tree c7920a0e819308762fca3d6fc7ab194bd565b06a (from 37652b68880f1881b90bd22218cfe86eca7e5974)
Author: Dave Airlie <airlied at linux.ie>
Date:   Thu Jul 19 15:09:54 2007 +1000

    strip out remainder of drmmm code in driver

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 3e90eea..9bb12c6 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2863,11 +2863,7 @@ I830LeaveVT(int scrnIndex, int flags)
       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);
-#else
 	 drmMMLock(pI830->drmSubFD, DRM_BO_MEM_TT);
-#endif
       }
 #endif /* XF86DRI_MM */
       I830DRISetVBlankInterrupt (pScrn, FALSE);
@@ -2972,11 +2968,7 @@ I830EnterVT(int scrnIndex, int flags)
 
 #ifdef XF86DRI_MM
 	 if (pI830->mmModeFlags & I830_KERNEL_MM) {
-#ifndef XSERVER_LIBDRM_MM
-	    I830DrmMMUnlock(pI830->drmSubFD, DRM_BO_MEM_TT);
-#else
 	    drmMMUnlock(pI830->drmSubFD, DRM_BO_MEM_TT);
-#endif
 	 }
 #endif /* XF86DRI_MM */
 
@@ -3035,11 +3027,7 @@ I830CloseScreen(int scrnIndex, ScreenPtr
 #endif
 #ifdef XF86DRI_MM
       if (pI830->mmModeFlags & I830_KERNEL_MM) {
-#ifndef XSERVER_LIBDRM_MM
-	 I830DrmMMTakedown(pI830->drmSubFD, DRM_BO_MEM_TT);
-#else
 	 drmMMTakedown(pI830->drmSubFD, DRM_BO_MEM_TT);	 
-#endif
       }
 #endif /* XF86DRI_MM */
       pI830->directRenderingOpen = FALSE;
diff-tree 37652b68880f1881b90bd22218cfe86eca7e5974 (from e40f6a4923d1323702406266e90eae3218a8a44e)
Author: Dave Airlie <airlied at linux.ie>
Date:   Tue Jul 17 14:03:21 2007 +1000

    intel: oops I commited pixman local workaround - undo it

diff --git a/configure.ac b/configure.ac
index ec2864d..9b76b65 100644
--- a/configure.ac
+++ b/configure.ac
@@ -85,7 +85,7 @@ XORG_DRIVER_CHECK_EXT(XF86DRI, xextproto
 XORG_DRIVER_CHECK_EXT(DPMSExtension, xextproto)
 
 # Checks for pkg-config packages
-PKG_CHECK_MODULES(XORG, [pixman xorg-server xproto xvmc fontsproto $REQUIRED_MODULES])
+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)
diff-tree e40f6a4923d1323702406266e90eae3218a8a44e (from 1e169be25b2e4ab34afd4b8ae8ae0041f6069125)
Author: Dave Airlie <airlied at linux.ie>
Date:   Tue Jul 17 09:20:07 2007 +1000

    intel: actually 2.3.1 should be good enough

diff --git a/configure.ac b/configure.ac
index 48c8cb2..ec2864d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -183,7 +183,7 @@ if test "$DRI" = yes; then
         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.3.2],[DRI_MM=yes], [DRI_MM=no])
+	PKG_CHECK_MODULES(DRI_MM, [libdrm >= 2.3.1],[DRI_MM=yes], [DRI_MM=no])
 	if test "x$DRI_MM" = xyes; then
 		AC_DEFINE(XF86DRI_MM,1,[Extended DRI memory management])
 	fi
diff-tree 1e169be25b2e4ab34afd4b8ae8ae0041f6069125 (from ff2be3995d33f9e4b7f63b380f166b6168c9b9c6)
Author: Dave Airlie <airlied at linux.ie>
Date:   Tue Jul 17 09:17:31 2007 +1000

    intel: don't try and use TTM memory manager with old libdrm interface
    
    I probably need to release a libdrm with this interface in it now..

diff --git a/configure.ac b/configure.ac
index ec30376..48c8cb2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -85,7 +85,7 @@ XORG_DRIVER_CHECK_EXT(XF86DRI, xextproto
 XORG_DRIVER_CHECK_EXT(DPMSExtension, xextproto)
 
 # Checks for pkg-config packages
-PKG_CHECK_MODULES(XORG, [xorg-server xproto xvmc fontsproto $REQUIRED_MODULES])
+PKG_CHECK_MODULES(XORG, [pixman 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)
@@ -183,7 +183,7 @@ if test "$DRI" = yes; then
         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])
+	PKG_CHECK_MODULES(DRI_MM, [libdrm >= 2.3.2],[DRI_MM=yes], [DRI_MM=no])
 	if test "x$DRI_MM" = xyes; then
 		AC_DEFINE(XF86DRI_MM,1,[Extended DRI memory management])
 	fi
diff --git a/src/i830.h b/src/i830.h
index b85ee26..aa2b240 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -750,10 +750,4 @@ extern const int I830CopyROP[16];
 #define _845_DRAM_RW_CONTROL 0x90
 #define DRAM_WRITE    0x33330000
 
-/* 
- * Xserver MM compatibility. Remove code guarded by this when the
- * XServer contains the libdrm mm code
- */
-#undef XSERVER_LIBDRM_MM
-
 #endif /* _I830_H_ */
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 51a17f0..3e90eea 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2116,83 +2116,6 @@ IntelEmitInvarientState(ScrnInfoPtr pScr
    }
 }
 
-#ifdef XF86DRI_MM
-#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 /* XF86DRI_MM */
-
 static Bool
 I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
 {
@@ -2866,13 +2789,8 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 	 unsigned long aperStart = ROUND_TO(pI830->memory_manager->offset,
 					    GTT_PAGE_SIZE) / GTT_PAGE_SIZE;
 
-#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");
 	    
diff-tree ff2be3995d33f9e4b7f63b380f166b6168c9b9c6 (from 00f4587025a3879626623135b0a153fcdb906719)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Fri Jul 13 12:47:18 2007 -0700

    Remove hard-coded CRT blanking frobbing for load detection.
    
    CRT blanking needn't be adjusted to perform load detection on 9xx chips, and
    the 8xx load detection path now adjusts blanking just during load detection.
    Adjusting the blanking interval turned out to cause many monitors to fail to
    sync.

diff --git a/src/i830_crt.c b/src/i830_crt.c
index 9e6180e..d7762a0 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -97,8 +97,6 @@ static Bool
 i830_crt_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
 		    DisplayModePtr adjusted_mode)
 {
-    /* disable blanking so we can detect monitors */
-    adjusted_mode->CrtcVBlankStart = adjusted_mode->CrtcVTotal - 3;
     return TRUE;
 }
 
@@ -360,8 +358,8 @@ i830_crt_detect(xf86OutputPtr output)
 	    return XF86OutputStatusDisconnected;
     }
 
-//    if (i830_crt_detect_ddc(output))
-//	return XF86OutputStatusConnected;
+    if (i830_crt_detect_ddc(output))
+	return XF86OutputStatusConnected;
 
     /* Use the load-detect method if we have no other way of telling. */
     crtc = i830GetLoadDetectPipe (output, NULL, &dpms_mode);
diff --git a/src/i830_display.c b/src/i830_display.c
index 16af496..26873fe 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -1509,6 +1509,8 @@ i830GetLoadDetectPipe(xf86OutputPtr outp
 	output->funcs->mode_set (output, &crtc->mode, &crtc->mode);
 	output->funcs->commit (output);
     }
+    /* let the output get through one full cycle before testing */
+    i830WaitForVblank (pScrn);
 
     return crtc;
 }
diff-tree 00f4587025a3879626623135b0a153fcdb906719 (from 6f18300aed1340348c6d395f326061b5315be643)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Fri Jul 13 10:58:06 2007 -0700

    Ensure pipe/output active before doing load detection.
    
    If the pipe or output have been set to DPMSOff, then load detection will not
    work correctly. Also, share the load detection configuration code between
    crt and tv outputs.

diff --git a/src/i830.h b/src/i830.h
index 409057c..b85ee26 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -220,6 +220,8 @@ typedef struct _I830CrtcPrivateRec {
 
     Bool    		    enabled;
     
+    int			    dpms_mode;
+    
     /* Lookup table values to be set when the CRTC is enabled */
     CARD8 lut_r[256], lut_g[256], lut_b[256];
 
diff --git a/src/i830_crt.c b/src/i830_crt.c
index 1900dfb..9e6180e 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -349,8 +349,9 @@ i830_crt_detect(xf86OutputPtr output)
 {
     ScrnInfoPtr		    pScrn = output->scrn;
     I830Ptr		    pI830 = I830PTR(pScrn);
-    xf86CrtcPtr	    crtc;
-
+    xf86CrtcPtr		    crtc;
+    int			    dpms_mode;
+    
     if (IS_I945G(pI830) || IS_I945GM(pI830) || IS_I965G(pI830) ||
 	    IS_G33CLASS(pI830)) {
 	if (i830_crt_detect_hotplug(output))
@@ -359,49 +360,18 @@ i830_crt_detect(xf86OutputPtr output)
 	    return XF86OutputStatusDisconnected;
     }
 
-    if (i830_crt_detect_ddc(output))
-	return XF86OutputStatusConnected;
+//    if (i830_crt_detect_ddc(output))
+//	return XF86OutputStatusConnected;
 
     /* Use the load-detect method if we have no other way of telling. */
-    crtc = i830GetLoadDetectPipe (output);
+    crtc = i830GetLoadDetectPipe (output, NULL, &dpms_mode);
     
     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 (!crtc->enabled)
-	{
-	    xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
-	    /*
-	     * Give us some border at the bottom for load detection on i8xx
-	     */
-	    mode.CrtcVBlankStart = mode.CrtcVSyncStart;
-	    if (mode.CrtcVBlankEnd - mode.CrtcVBlankStart < 3)
-		mode.CrtcVBlankStart = mode.CrtcVBlankEnd - 3;
-	    xf86CrtcSetMode (crtc, &mode, RR_Rotate_0, 0, 0);
-	}
-	else if (intel_output->load_detect_temp)
-	{
-	    /* Add this output to the crtc */
-	    output->funcs->mode_set (output, &crtc->mode, &crtc->mode);
-	    output->funcs->commit (output);
-	}
-	connected = i830_crt_detect_load (crtc, output);
 
-	i830ReleaseLoadDetectPipe (output);
+	connected = i830_crt_detect_load (crtc, output);
+	i830ReleaseLoadDetectPipe (output, dpms_mode);
 	if (connected)
 	    return XF86OutputStatusConnected;
 	else
diff --git a/src/i830_display.c b/src/i830_display.c
index ff25b29..16af496 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -605,6 +605,8 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mod
 	break;
     }
 
+    intel_crtc->dpms_mode = mode;
+
 #ifdef XF86DRI
     if (pI830->directRenderingEnabled) {
 	drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScrn->pScreen);
@@ -1424,58 +1426,116 @@ i830DescribeOutputConfiguration(ScrnInfo
  * \return crtc, or NULL if no pipes are available.
  */
     
+/* VESA 640x480x72Hz mode to set on the pipe */
+static DisplayModeRec   load_detect_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,
+
+    640, 640, 664, 704, 832, 832, 0,
+    480, 489, 489, 491, 520, 520,
+    FALSE, FALSE, 0, NULL, 0, 0.0, 0.0
+};
+
 xf86CrtcPtr
-i830GetLoadDetectPipe(xf86OutputPtr output)
+i830GetLoadDetectPipe(xf86OutputPtr output, DisplayModePtr mode, int *dpms_mode)
 {
     ScrnInfoPtr		    pScrn = output->scrn;
     xf86CrtcConfigPtr	    xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     I830OutputPrivatePtr    intel_output = output->driver_private;
+    I830CrtcPrivatePtr	    intel_crtc;
     xf86CrtcPtr		    supported_crtc =NULL;
-    xf86CrtcPtr		    detect_crtc = NULL;
+    xf86CrtcPtr		    crtc = NULL;
     int			    i;
 
     if (output->crtc) 
-	return output->crtc;
+    {
+	crtc = output->crtc;
+	/*
+	 * Make sure the crtc and output are running
+	 */
+	intel_crtc = crtc->driver_private;
+	*dpms_mode = intel_crtc->dpms_mode;
+	if (intel_crtc->dpms_mode != DPMSModeOn)
+	{
+	    crtc->funcs->dpms (crtc, DPMSModeOn);
+	    output->funcs->dpms (output, DPMSModeOn);
+	}
+	return crtc;
+    }
 
     for (i = 0; i < xf86_config->num_crtc; i++)
     {
-	xf86CrtcPtr crtc;
+	xf86CrtcPtr possible_crtc;
 	if (!(output->possible_crtcs & (1 << i)))
 	    continue;
-	crtc = xf86_config->crtc[i];
-	if (!crtc->enabled)
+	possible_crtc = xf86_config->crtc[i];
+	if (!possible_crtc->enabled)
 	{
-	    detect_crtc = crtc;
+	    crtc = possible_crtc;
 	    break;
 	}
 	if (!supported_crtc)
-	    supported_crtc = crtc;
+	    supported_crtc = possible_crtc;
+    }
+    if (!crtc)
+    {
+	crtc = supported_crtc;
+	if (!crtc)
+	    return NULL;
     }
-    if (!detect_crtc)
-	detect_crtc = supported_crtc;
-    if (!detect_crtc)
-	return NULL;
 
-    output->crtc = detect_crtc;
+    output->crtc = crtc;
     intel_output->load_detect_temp = TRUE;
+    
+    intel_crtc = crtc->driver_private;
+    *dpms_mode = intel_crtc->dpms_mode;
 
-    return detect_crtc;
+    if (!crtc->enabled)
+    {
+	if (!mode)
+	    mode = &load_detect_mode;
+	xf86CrtcSetMode (crtc, mode, RR_Rotate_0, 0, 0);
+    }
+    else
+    {
+	if (intel_crtc->dpms_mode != DPMSModeOn)
+	    crtc->funcs->dpms (crtc, DPMSModeOn);
+
+	/* Add this output to the crtc */
+	output->funcs->mode_set (output, &crtc->mode, &crtc->mode);
+	output->funcs->commit (output);
+    }
+
+    return crtc;
 }
 
 void
-i830ReleaseLoadDetectPipe(xf86OutputPtr output)
+i830ReleaseLoadDetectPipe(xf86OutputPtr output, int dpms_mode)
 {
     ScrnInfoPtr		    pScrn = output->scrn;
     I830OutputPrivatePtr    intel_output = output->driver_private;
+    xf86CrtcPtr		    crtc = output->crtc;
     
     if (intel_output->load_detect_temp) 
     {
-	xf86CrtcPtr crtc = output->crtc;
 	output->crtc = NULL;
 	intel_output->load_detect_temp = FALSE;
 	crtc->enabled = xf86CrtcInUse (crtc);
 	xf86DisableUnusedFunctions(pScrn);
     }
+    /*
+     * Switch crtc and output back off if necessary
+     */
+    if (crtc->enabled && dpms_mode != DPMSModeOn)
+    {
+	if (output->crtc == crtc)
+	    output->funcs->dpms (output, dpms_mode);
+	crtc->funcs->dpms (crtc, dpms_mode);
+    }
 }
 
 /* Returns the clock of the currently programmed mode of the given pipe. */
@@ -1623,6 +1683,7 @@ i830_crtc_init(ScrnInfoPtr pScrn, int pi
 
     intel_crtc = xnfcalloc (sizeof (I830CrtcPrivateRec), 1);
     intel_crtc->pipe = pipe;
+    intel_crtc->dpms_mode = DPMSModeOff;
 
     /* Initialize the LUTs for when we turn on the CRTC. */
     for (i = 0; i < 256; i++) {
diff --git a/src/i830_display.h b/src/i830_display.h
index 07dfe93..1eeb7f1 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -32,8 +32,8 @@ void i830PipeSetBase(xf86CrtcPtr crtc, i
 void i830WaitForVblank(ScrnInfoPtr pScrn);
 void i830DescribeOutputConfiguration(ScrnInfoPtr pScrn);
 
-xf86CrtcPtr i830GetLoadDetectPipe(xf86OutputPtr output);
-void i830ReleaseLoadDetectPipe(xf86OutputPtr output);
+xf86CrtcPtr i830GetLoadDetectPipe(xf86OutputPtr output, DisplayModePtr mode, int *dpms_mode);
+void i830ReleaseLoadDetectPipe(xf86OutputPtr output, int dpms_mode);
 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_tv.c b/src/i830_tv.c
index 1c818ba..8337d86 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -1353,24 +1353,15 @@ i830_tv_detect(xf86OutputPtr output)
     DisplayModeRec	    mode;
     I830OutputPrivatePtr    intel_output = output->driver_private;
     struct i830_tv_priv	    *dev_priv = intel_output->dev_priv;
+    int			    dpms_mode;
 
-    crtc = i830GetLoadDetectPipe (output);
+    mode = reported_modes[0];
+    xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
+    crtc = i830GetLoadDetectPipe (output, &mode, &dpms_mode);
     if (crtc)
     {
-	if (!crtc->enabled)
-        {
-            /* 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);
-        }
-	else if (intel_output->load_detect_temp)
-	{
-	    output->funcs->mode_set (output, &crtc->mode, &crtc->mode);
-	    output->funcs->commit (output);
-	}
         i830_tv_detect_type (crtc, output);
-        i830ReleaseLoadDetectPipe (output);
+        i830ReleaseLoadDetectPipe (output, dpms_mode);
     }
 
     switch (dev_priv->type) {
diff-tree 6f18300aed1340348c6d395f326061b5315be643 (from 04130ac6b705aa49161fb6dae83ad0bdd76e89d9)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Mon Jul 9 21:29:55 2007 -0700

    Eliminate bogus (and harmful) blanking adjustment for load detect.
    
    Instead of always adding blanking to mode lines, use the FORCE_BORDER option
    on i9xx hardware where it works, and dynamically add a bit of border if
    necessary on i8xx hardware to make load detection work. This may cause
    flashing when a usable crtc is not otherwise idle when load detection is
    requested.

diff --git a/src/i830_crt.c b/src/i830_crt.c
index 6d70f39..1900dfb 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -209,10 +209,8 @@ i830_crt_detect_load (xf86CrtcPtr	    cr
     CARD32		    dsl;
     CARD8		    st00;
     int			    bclrpat_reg, pipeconf_reg, pipe_dsl_reg;
-    int			    vtotal_reg;
-    int			    vblank_reg;
+    int			    vtotal_reg, vblank_reg, vsync_reg;
     int			    pipe = i830_crtc->pipe;
-    int			    count, detect;
     Bool		    present;
 
     if (pipe == 0) 
@@ -220,6 +218,7 @@ i830_crt_detect_load (xf86CrtcPtr	    cr
 	bclrpat_reg = BCLRPAT_A;
 	vtotal_reg = VTOTAL_A;
 	vblank_reg = VBLANK_A;
+	vsync_reg = VSYNC_A;
 	pipeconf_reg = PIPEACONF;
 	pipe_dsl_reg = PIPEA_DSL;
     }
@@ -228,6 +227,7 @@ i830_crt_detect_load (xf86CrtcPtr	    cr
 	bclrpat_reg = BCLRPAT_B;
 	vtotal_reg = VTOTAL_B;
 	vblank_reg = VBLANK_B;
+	vsync_reg = VSYNC_B;
 	pipeconf_reg = PIPEBCONF;
 	pipe_dsl_reg = PIPEB_DSL;
     }
@@ -242,45 +242,78 @@ i830_crt_detect_load (xf86CrtcPtr	    cr
     vblank_start = (vblank & 0xfff) + 1;
     vblank_end = ((vblank >> 16) & 0xfff) + 1;
     
-    /* sample in the vertical border, selecting the larger one */
-    if (vblank_start - vactive >= vtotal - vblank_end)
-	vsample = (vblank_start + vactive) >> 1;
-    else
-	vsample = (vtotal + vblank_end) >> 1;
-
     /* Set the border color to purple. */
     OUTREG(bclrpat_reg, 0x500050);
     
-    /*
-     * Wait for the border to be displayed
-     */
-    while (INREG(pipe_dsl_reg) >= vactive)
-	;
-    while ((dsl = INREG(pipe_dsl_reg)) <= vsample)
-	;
-    /*
-     * Watch ST00 for an entire scanline
-     */
-    detect = 0;
-    count = 0;
-    do {
-	count++;
-	/* Read the ST00 VGA status register */
-	st00 = pI830->readStandard(pI830, 0x3c2);
-	if (st00 & (1 << 4))
-	    detect++;
-    } while ((INREG(pipe_dsl_reg) == dsl));
+    if (IS_I9XX (pI830))
+    {
+	CARD32	pipeconf = INREG(pipeconf_reg);
+	OUTREG(pipeconf_reg, pipeconf | PIPECONF_FORCE_BORDER);
+	
+	st00 = pI830->readStandard (pI830, 0x3c2);
+	present = (st00 & (1 << 4)) != 0;
+	OUTREG(pipeconf_reg, pipeconf);
+    }
+    else
+    {
+	Bool	restore_vblank = FALSE;
+	int	count, detect;
+
+	/*
+	 * If there isn't any border, add some.
+	 * Yes, this will flicker
+	 */
+	if (vblank_start <= vactive && vblank_end >= vtotal)
+	{
+	    CARD32  vsync = INREG(vsync_reg);
+	    CARD32  vsync_start = (vsync & 0xffff) + 1;
+
+	    vblank_start = vsync_start;
+	    OUTREG(vblank_reg, (vblank_start - 1) | ((vblank_end - 1) << 16));
+	    restore_vblank = TRUE;
+	}
+	
+	/* sample in the vertical border, selecting the larger one */
+	if (vblank_start - vactive >= vtotal - vblank_end)
+	    vsample = (vblank_start + vactive) >> 1;
+	else
+	    vsample = (vtotal + vblank_end) >> 1;
+
+	/*
+	 * Wait for the border to be displayed
+	 */
+	while (INREG(pipe_dsl_reg) >= vactive)
+	    ;
+	while ((dsl = INREG(pipe_dsl_reg)) <= vsample)
+	    ;
+	/*
+	 * Watch ST00 for an entire scanline
+	 */
+	detect = 0;
+	count = 0;
+	do {
+	    count++;
+	    /* Read the ST00 VGA status register */
+	    st00 = pI830->readStandard(pI830, 0x3c2);
+	    if (st00 & (1 << 4))
+		detect++;
+	} while ((INREG(pipe_dsl_reg) == dsl));
+	
+	/* restore vblank if necessary */
+	if (restore_vblank)
+	    OUTREG(vblank_reg, vblank);
+	/*
+	 * If more than 3/4 of the scanline detected a monitor,
+	 * then it is assumed to be present. This works even on i830,
+	 * where there isn't any way to force the border color across
+	 * the screen
+	 */
+	present = detect * 4 > count * 3;
+    }
 
     /* Restore previous settings */
     OUTREG(bclrpat_reg, save_bclrpat);
 
-    /*
-     * If more than 3/4 of the scanline detected a monitor,
-     * then it is assumed to be present. This works even on i830,
-     * where there isn't any way to force the border color across
-     * the screen
-     */
-    present = detect * 4 > count * 3;
     return present;
 }
 
@@ -352,10 +385,17 @@ i830_crt_detect(xf86OutputPtr output)
 	if (!crtc->enabled)
 	{
 	    xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
+	    /*
+	     * Give us some border at the bottom for load detection on i8xx
+	     */
+	    mode.CrtcVBlankStart = mode.CrtcVSyncStart;
+	    if (mode.CrtcVBlankEnd - mode.CrtcVBlankStart < 3)
+		mode.CrtcVBlankStart = mode.CrtcVBlankEnd - 3;
 	    xf86CrtcSetMode (crtc, &mode, RR_Rotate_0, 0, 0);
 	}
 	else if (intel_output->load_detect_temp)
 	{
+	    /* Add this output to the crtc */
 	    output->funcs->mode_set (output, &crtc->mode, &crtc->mode);
 	    output->funcs->commit (output);
 	}
diff --git a/src/i830_display.c b/src/i830_display.c
index f3b5c50..ff25b29 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -1169,13 +1169,6 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
     OUTREG(vtot_reg, (adjusted_mode->CrtcVDisplay - 1) |
 	((adjusted_mode->CrtcVTotal - 1) << 16));
     
-    /*
-     * Give us some border at the bottom for load detection
-     */
-    adjusted_mode->CrtcVBlankStart = adjusted_mode->CrtcVSyncStart;
-    if (adjusted_mode->CrtcVBlankEnd - adjusted_mode->CrtcVBlankStart < 3)
-	adjusted_mode->CrtcVBlankStart = adjusted_mode->CrtcVBlankEnd - 3;
-    
     OUTREG(vblank_reg, (adjusted_mode->CrtcVBlankStart - 1) |
 	((adjusted_mode->CrtcVBlankEnd - 1) << 16));
     OUTREG(vsync_reg, (adjusted_mode->CrtcVSyncStart - 1) |
@@ -1437,25 +1430,36 @@ i830GetLoadDetectPipe(xf86OutputPtr outp
     ScrnInfoPtr		    pScrn = output->scrn;
     xf86CrtcConfigPtr	    xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     I830OutputPrivatePtr    intel_output = output->driver_private;
-    xf86CrtcPtr	    crtc;
+    xf86CrtcPtr		    supported_crtc =NULL;
+    xf86CrtcPtr		    detect_crtc = NULL;
     int			    i;
 
     if (output->crtc) 
 	return output->crtc;
 
     for (i = 0; i < xf86_config->num_crtc; i++)
-	if (output->possible_crtcs & (1 << i))
+    {
+	xf86CrtcPtr crtc;
+	if (!(output->possible_crtcs & (1 << i)))
+	    continue;
+	crtc = xf86_config->crtc[i];
+	if (!crtc->enabled)
+	{
+	    detect_crtc = crtc;
 	    break;
-
-    if (i == xf86_config->num_crtc)
+	}
+	if (!supported_crtc)
+	    supported_crtc = crtc;
+    }
+    if (!detect_crtc)
+	detect_crtc = supported_crtc;
+    if (!detect_crtc)
 	return NULL;
 
-    crtc = xf86_config->crtc[i];
-
-    output->crtc = crtc;
+    output->crtc = detect_crtc;
     intel_output->load_detect_temp = TRUE;
 
-    return crtc;
+    return detect_crtc;
 }
 
 void
diff-tree 04130ac6b705aa49161fb6dae83ad0bdd76e89d9 (from 88f8b688e2316ae4a1f7485f0010ce90de54783a)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Jul 11 11:42:56 2007 +0800

    Fix i915 rendering for tiled buffer
    
    Make it to check fence register for dest buffer.

diff --git a/src/i915_render.c b/src/i915_render.c
index 2148883..9d5bc0a 100644
--- a/src/i915_render.c
+++ b/src/i915_render.c
@@ -373,12 +373,9 @@ i915_prepare_composite(int op, PicturePt
 	CARD32 ss2;
 
 	BEGIN_LP_RING(16);
-	/* 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_ID_COLOR_BACK| BUF_3D_USE_FENCE|
+		BUF_3D_PITCH(dst_pitch));
 	OUT_RING(BUF_3D_ADDR(dst_offset));
 
 	OUT_RING(_3DSTATE_DST_BUF_VARS_CMD);
diff-tree 88f8b688e2316ae4a1f7485f0010ce90de54783a (from bf831117b4659cc4f2774098dee938505f780a9b)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Jul 9 12:56:13 2007 -0700

    Fix some physical address handling for >4GB addresses.
    
    The upper bits would have been inappropriately dropped on G33-class hardware,
    and on G965-class hardware in a 32-bit environment.  The only use of physical
    addresses on these should be for FBC, though, and FBC requires addresses
    below 4GB.  This is unresolved.

diff --git a/src/i830.h b/src/i830.h
index 8b6c5e6..409057c 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -134,7 +134,7 @@ struct _i830_memory {
      * Physical (or more properly, bus) address of the allocation.
      * Only set if requested during allocation.
      */
-    unsigned long bus_addr;
+    uint64_t bus_addr;
     /** AGP memory handle */
     int key;
     /**
@@ -235,7 +235,7 @@ typedef struct _I830CrtcPrivateRec {
     /* Physical or virtual addresses of the cursor for setting in the cursor
      * registers.
      */
-    unsigned long cursor_addr;
+    uint64_t cursor_addr;
     unsigned long cursor_argb_addr;
     Bool	cursor_is_argb;
 } I830CrtcPrivateRec, *I830CrtcPrivatePtr;
diff --git a/src/i830_memory.c b/src/i830_memory.c
index a589738..b38a5df 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -319,9 +319,9 @@ i830_allocator_init(ScrnInfoPtr pScrn, u
  * physical address.
  *
  * \return physical address if successful.
- * \return (unsigned long)-1 if unsuccessful.
+ * \return (uint64_t)-1 if unsuccessful.
  */
-static unsigned long
+static uint64_t
 i830_get_gtt_physical(ScrnInfoPtr pScrn, unsigned long offset)
 {
     I830Ptr pI830 = I830PTR(pScrn);
@@ -334,8 +334,11 @@ i830_get_gtt_physical(ScrnInfoPtr pScrn,
     gttentry = INGTT(offset / 1024);
 
     /* Mask out these reserved bits on this hardware. */
-    if (!IS_I965G(pI830))
+    if (!IS_I9XX(pI830) || IS_I915G(pI830) || IS_I915GM(pI830) ||
+	IS_I945G(pI830) || IS_I945GM(pI830))
+    {
 	gttentry &= ~PTE_ADDRESS_MASK_HIGH;
+    }
 
     /* If it's not a mapping type we know, then bail. */
     if ((gttentry & PTE_MAPPING_TYPE_MASK) != PTE_MAPPING_TYPE_UNCACHED &&
@@ -346,19 +349,10 @@ i830_get_gtt_physical(ScrnInfoPtr pScrn,
 		   (unsigned int)(gttentry & PTE_MAPPING_TYPE_MASK));
 	return -1;
     }
-    /* If we can't represent the address with an unsigned long, bail. */
-    if (sizeof(unsigned long) == 4 &&
-	(gttentry & PTE_ADDRESS_MASK_HIGH) != 0)
-    {
-	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		   "High memory PTE (0x%08x) on 32-bit system\n",
-		   (unsigned int)gttentry);
-	return -1;
-    }
     assert((gttentry & PTE_VALID) != 0);
 
     return (gttentry & PTE_ADDRESS_MASK) |
-	(gttentry & PTE_ADDRESS_MASK_HIGH << (32 - 4));
+	((uint64_t)(gttentry & PTE_ADDRESS_MASK_HIGH) << (32 - 4));
 }
 
 /**
@@ -366,14 +360,15 @@ i830_get_gtt_physical(ScrnInfoPtr pScrn,
  * physical address.
  *
  * \return physical address if successful.
- * \return (unsigned long)-1 if unsuccessful.
+ * \return (uint64_t)-1 if unsuccessful.
  */
-static unsigned long
+static uint64_t
 i830_get_stolen_physical(ScrnInfoPtr pScrn, unsigned long offset,
 			 unsigned long size)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    unsigned long physical, scan;
+    uint64_t physical;
+    unsigned long scan;
 
     /* Check that the requested region is within stolen memory. */
     if (offset + size >= pI830->stolen_size)
@@ -387,11 +382,12 @@ i830_get_stolen_physical(ScrnInfoPtr pSc
      * contiguously.
      */
     for (scan = offset + 4096; scan < offset + size; scan += 4096) {
-	unsigned long scan_physical = i830_get_gtt_physical(pScrn, scan);
+	uint64_t scan_physical = i830_get_gtt_physical(pScrn, scan);
 
 	if ((scan - offset) != (scan_physical - physical)) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		       "Non-contiguous GTT entries: (%ld,%ld) vs (%ld,%ld)\n",
+		       "Non-contiguous GTT entries: (%ld,0x16%llx) vs "
+		       "(%ld,0x%16llx)\n",
 		       scan, scan_physical, offset, physical);
 	    return -1;
 	}
@@ -444,7 +440,7 @@ i830_allocate_aperture(ScrnInfoPtr pScrn
 	    mem->bus_addr = i830_get_stolen_physical(pScrn, mem->offset,
 						     mem->size);
 
-	    if (mem->bus_addr == ((unsigned long)-1)) {
+	    if (mem->bus_addr == ((uint64_t)-1)) {
 		/* Move the start of the allocation to just past the end of
 		 * stolen memory.
 		 */
@@ -498,11 +494,15 @@ i830_allocate_agp_memory(ScrnInfoPtr pSc
 
     size = mem->size - (mem->agp_offset - mem->offset);
 
-    if (flags & NEED_PHYSICAL_ADDR)
+    if (flags & NEED_PHYSICAL_ADDR) {
+	unsigned long agp_bus_addr;
+
 	mem->key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 2,
-					  &mem->bus_addr);
-    else
+					  &agp_bus_addr);
+	mem->bus_addr = agp_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;
@@ -688,7 +688,8 @@ i830_describe_allocations(ScrnInfoPtr pS
 			   mem->size / 1024);
 	} else {
 	    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-			   "%s0x%08lx-0x%08lx: %s (%ld kB, 0x%08lx physical)\n",
+			   "%s0x%08lx-0x%08lx: %s "
+			   "(%ld kB, 0x%16llx physical)\n",
 			   prefix,
 			   mem->offset, mem->end - 1, mem->name,
 			   mem->size / 1024, mem->bus_addr);
@@ -956,9 +957,13 @@ i830_allocate_cursor_buffers(ScrnInfoPtr
 	unsigned long cursor_offset_base = pI830->cursor_mem->offset;
 	unsigned long cursor_addr_base, offset = 0;
 
-	if (pI830->CursorNeedsPhysical)
-	    cursor_addr_base = pI830->cursor_mem->bus_addr;
-	else
+	if (pI830->CursorNeedsPhysical) {
+	    /* On any hardware that requires physical addresses for cursors,
+	     * the PTEs don't support memory above 4GB, so we can safely
+	     * ignore the top 32 bits of cursor_mem->bus_addr.
+	     */
+	    cursor_addr_base = (unsigned long)pI830->cursor_mem->bus_addr;
+	} else
 	    cursor_addr_base = pI830->cursor_mem->offset;
 
 	/* Set up the offsets for our cursors in each CRTC. */
diff-tree bf831117b4659cc4f2774098dee938505f780a9b (from b426866fe1be2ad3861559beff69186379a6afad)
Author: Jesse Barnes <jbarnes at hobbes.virtuousgeek.org>
Date:   Sat Jul 7 10:15:32 2007 -0700

    FBC fixes:
      - allow FBC and Tiling to be forced off if configured to do so
      - only touch FBC registers if pI830->fb_compression is true

diff --git a/src/i830_display.c b/src/i830_display.c
index 853f4e4..f3b5c50 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -747,7 +747,7 @@ i830_disable_fb_compression(xf86CrtcPtr 
     ScrnInfoPtr pScrn = crtc->scrn;
     I830Ptr pI830 = I830PTR(pScrn);
     uint32_t fbc_ctl;
-    char pipe = (INREG(FBC_CONTROL2) & 1) ? 'b' : 'a';;
+    char pipe = (INREG(FBC_CONTROL2) & 1) ? 'b' : 'a';
 
     /* Disable compression */
     fbc_ctl = INREG(FBC_CONTROL);
@@ -764,7 +764,8 @@ static void
 i830_crtc_prepare (xf86CrtcPtr crtc)
 {
     /* Temporarily turn off FB compression during modeset */
-    i830_disable_fb_compression(crtc);
+    if (i830_use_fb_compression(crtc))
+        i830_disable_fb_compression(crtc);
     crtc->funcs->dpms (crtc, DPMSModeOff);
 }
 
diff --git a/src/i830_driver.c b/src/i830_driver.c
index dcbed22..51a17f0 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1753,10 +1753,12 @@ SaveHWState(ScrnInfoPtr pScrn)
    vgaRegPtr vgaReg = &hwp->SavedReg;
    int i;
 
-   pI830->saveFBC_CFB_BASE = INREG(FBC_CFB_BASE);
-   pI830->saveFBC_LL_BASE = INREG(FBC_LL_BASE);
-   pI830->saveFBC_CONTROL2 = INREG(FBC_CONTROL2);
-   pI830->saveFBC_CONTROL = INREG(FBC_CONTROL);
+   if (pI830->fb_compression) {
+       pI830->saveFBC_CFB_BASE = INREG(FBC_CFB_BASE);
+       pI830->saveFBC_LL_BASE = INREG(FBC_LL_BASE);
+       pI830->saveFBC_CONTROL2 = INREG(FBC_CONTROL2);
+       pI830->saveFBC_CONTROL = INREG(FBC_CONTROL);
+   }
 
    /* Save video mode information for native mode-setting. */
    pI830->saveDSPACNTR = INREG(DSPACNTR);
@@ -1982,10 +1984,12 @@ RestoreHWState(ScrnInfoPtr pScrn)
    OUTREG(SWF31, pI830->saveSWF[15]);
    OUTREG(SWF32, pI830->saveSWF[16]);
 
-   OUTREG(FBC_CFB_BASE, pI830->saveFBC_CFB_BASE);
-   OUTREG(FBC_LL_BASE, pI830->saveFBC_LL_BASE);
-   OUTREG(FBC_CONTROL2, pI830->saveFBC_CONTROL2);
-   OUTREG(FBC_CONTROL, pI830->saveFBC_CONTROL);
+   if (pI830->fb_compression) {
+       OUTREG(FBC_CFB_BASE, pI830->saveFBC_CFB_BASE);
+       OUTREG(FBC_LL_BASE, pI830->saveFBC_LL_BASE);
+       OUTREG(FBC_CONTROL2, pI830->saveFBC_CONTROL2);
+       OUTREG(FBC_CONTROL, pI830->saveFBC_CONTROL);
+   }
 
    vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS);
    vgaHWLock(hwp);
@@ -2320,14 +2324,19 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       pI830->CacheLines = -1;
    }
 
-   /* Enable tiling by default where supported or if the user forced it on */
+   /* Enable tiling by default where supported */
    if (i830_tiling_supported(pI830))
        pI830->tiling = TRUE;
    else
        pI830->tiling = FALSE;
 
-   if (xf86ReturnOptValBool(pI830->Options, OPTION_TILING, FALSE))
-       pI830->tiling = TRUE;
+   /* Allow user override if they set a value */
+   if (xf86IsOptionSet(pI830->Options, OPTION_TILING)) {
+       if (xf86ReturnOptValBool(pI830->Options, OPTION_TILING, FALSE))
+	   pI830->tiling = TRUE;
+       else
+	   pI830->tiling = FALSE;
+   }
 
    /* Enable FB compression if possible */
    if (i830_fb_compression_supported(pI830))
@@ -2335,8 +2344,13 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    else
        pI830->fb_compression = FALSE;
 
-   if (xf86ReturnOptValBool(pI830->Options, OPTION_FBC, FALSE))
-       pI830->fb_compression = TRUE;
+   /* Again, allow user override if set */
+   if (xf86IsOptionSet(pI830->Options, OPTION_FBC)) {
+       if (xf86ReturnOptValBool(pI830->Options, OPTION_FBC, FALSE))
+	   pI830->fb_compression = TRUE;
+       else
+	   pI830->fb_compression = FALSE;
+   }
 
    if (pI830->fb_compression) {
        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Framebuffer compression enabled, "
diff-tree b426866fe1be2ad3861559beff69186379a6afad (from 377c58373daa6bef5d37ead2b6f9a769a905b6fa)
Author: Jesse Barnes <jesse.barnes at intel.com>
Date:   Fri Jul 6 20:48:40 2007 -0700

    Fix manpage to reflect default behavior.

diff --git a/man/intel.man b/man/intel.man
index 8bd3f28..33dc319 100644
--- a/man/intel.man
+++ b/man/intel.man
@@ -80,12 +80,12 @@ This option controls whether the framebu
 If possible, the front buffer will be allocated in a tiled format and compressed
 periodically to save memory bandwidth and power.
 This option is only available on mobile chipsets.
-Default: disabled.
+Default: enabled on supported configurations.
 .TP
 .BI "Option \*qTiling\*q \*q" boolean \*q
 This option controls whether memory buffers are allocated in tiled mode.  In
 many cases (especially for complex rendering), tiling can improve performance.
-Default: enabled.
+Default: enabled on supported configurations.
 .TP
 .BI "Option \*qDRI\*q \*q" boolean \*q
 Disable or enable DRI support.
diff-tree 377c58373daa6bef5d37ead2b6f9a769a905b6fa (from 9c0388dc8d4c6495fae21af6da644b34e20173d1)
Author: Jesse Barnes <jesse.barnes at intel.com>
Date:   Fri Jul 6 20:39:19 2007 -0700

    Fix naming of FBC plane enable bits (mistakenly called them pipes earlier).

diff --git a/src/i830_display.c b/src/i830_display.c
index dc52c0b..853f4e4 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -661,13 +661,13 @@ i830_use_fb_compression(xf86CrtcPtr crtc
     I830Ptr pI830 = I830PTR(pScrn);
     I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
     int pipe = intel_crtc->pipe;
-    int plane = (pipe == 0 ? FBC_CTL_PIPEA : FBC_CTL_PIPEB);
+    int plane = (pipe == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB);
 
     if (!pI830->fb_compression)
 	return FALSE;
 
-    /* Pre-965 only supports plane A, which is synonymous with pipe A for now */
-    if (!IS_I965GM(pI830) && plane != FBC_CTL_PIPEA)
+    /* Pre-965 only supports plane A */
+    if (!IS_I965GM(pI830) && plane != FBC_CTL_PLANEA)
 	return FALSE;
 
     /* Need 15, 16, or 32 (w/alpha) pixel format */
@@ -704,7 +704,7 @@ i830_enable_fb_compression(xf86CrtcPtr c
     uint32_t fbc_ctl;
     unsigned long compressed_stride;
     int pipe = intel_crtc->pipe;
-    int plane = (pipe == 0 ? FBC_CTL_PIPEA : FBC_CTL_PIPEB);
+    int plane = (pipe == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB);
     unsigned long uncompressed_stride = pScrn->displayWidth * pI830->cpp;
     unsigned long interval = 1000;
 
diff --git a/src/i830_reg.h b/src/i830_reg.h
index d1670c3..8a2a98a 100644
--- a/src/i830_reg.h
+++ b/src/i830_reg.h
@@ -47,8 +47,8 @@
 #define   FBC_STAT_CURRENT_LINE	(1<<0)
 #define FBC_CONTROL2		0x03214
 #define   FBC_CTL_CPU_FENCE	(1<<1)
-#define   FBC_CTL_PIPEA		(0<<0)
-#define   FBC_CTL_PIPEB		(1<<0)
+#define   FBC_CTL_PLANEA	(0<<0)
+#define   FBC_CTL_PLANEB	(1<<0)
 
 #define FBC_LL_SIZE		(1536)
 #define FBC_LL_PAD		(32)
diff-tree 9c0388dc8d4c6495fae21af6da644b34e20173d1 (from cecbc71fdc9af832cef23427696f6f654f7d6104)
Author: Jesse Barnes <jesse.barnes at intel.com>
Date:   Fri Jul 6 20:38:41 2007 -0700

    Update man page with current behavior.

diff --git a/man/intel.man b/man/intel.man
index 3173bc7..8bd3f28 100644
--- a/man/intel.man
+++ b/man/intel.man
@@ -75,12 +75,17 @@ driver attempts to allocate space for at
 HD-sized XV video.  The default used for a specific configuration can be found
 by examining the __xservername__ log file.
 .TP
-.BI "Option \*qFrameBufferCompression\*q \*q" boolean \*q
+.BI "Option \*qFramebufferCompression\*q \*q" boolean \*q
 This option controls whether the framebuffer compression feature is enabled.
 If possible, the front buffer will be allocated in a tiled format and compressed
 periodically to save memory bandwidth and power.
-.TP
 This option is only available on mobile chipsets.
+Default: disabled.
+.TP
+.BI "Option \*qTiling\*q \*q" boolean \*q
+This option controls whether memory buffers are allocated in tiled mode.  In
+many cases (especially for complex rendering), tiling can improve performance.
+Default: enabled.
 .TP
 .BI "Option \*qDRI\*q \*q" boolean \*q
 Disable or enable DRI support.
diff-tree cecbc71fdc9af832cef23427696f6f654f7d6104 (from 4359df9419d2d02a2f9d9adc7f5a49ecf07ddd30)
Author: Jesse Barnes <jesse.barnes at intel.com>
Date:   Fri Jul 6 16:36:34 2007 -0700

    Fix debug output in fbc enable/disable routines.  Add logic to make sure fbc
    isn't enabled twice on two different pipes.

diff --git a/src/i830_display.c b/src/i830_display.c
index c79676d..dc52c0b 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -708,6 +708,14 @@ i830_enable_fb_compression(xf86CrtcPtr c
     unsigned long uncompressed_stride = pScrn->displayWidth * pI830->cpp;
     unsigned long interval = 1000;
 
+    if (INREG(FBC_CONTROL) & FBC_CTL_EN) {
+	char cur_pipe = (INREG(FBC_CONTROL2) & 1) ? 'b' : 'a';
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "fbc already enabled on "
+		   "pipe %c, not enabling on pipe %c\n", cur_pipe, pipe ? 'b' :
+		   'a');
+	return;
+    }
+
     compressed_stride = pI830->compressed_front_buffer->size /
 	FBC_LL_SIZE;
 
@@ -730,7 +738,7 @@ i830_enable_fb_compression(xf86CrtcPtr c
     OUTREG(FBC_CONTROL, fbc_ctl);
 
     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "fbc enabled on pipe %c\n", pipe ?
-	       "a" : "b");
+	       'b' : 'a');
 }
 
 static void
@@ -739,6 +747,7 @@ i830_disable_fb_compression(xf86CrtcPtr 
     ScrnInfoPtr pScrn = crtc->scrn;
     I830Ptr pI830 = I830PTR(pScrn);
     uint32_t fbc_ctl;
+    char pipe = (INREG(FBC_CONTROL2) & 1) ? 'b' : 'a';;
 
     /* Disable compression */
     fbc_ctl = INREG(FBC_CONTROL);
@@ -748,7 +757,7 @@ i830_disable_fb_compression(xf86CrtcPtr 
     /* Wait for compressing bit to clear */
     while (INREG(FBC_STATUS) & FBC_STAT_COMPRESSING)
 	; /* nothing */
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "fbc disabled\n");
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "fbc disabled on pipe %c\n", pipe);
 }
 
 static void
diff-tree 4359df9419d2d02a2f9d9adc7f5a49ecf07ddd30 (from ca593a5219549df94a6d234ebbcf9e7c44723c9b)
Author: Jesse Barnes <jesse.barnes at intel.com>
Date:   Fri Jul 6 16:17:45 2007 -0700

    Fix tiling and fb compression defaults for 965 (not yet fully supported).

diff --git a/src/i830.h b/src/i830.h
index 4748b81..8b6c5e6 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -727,6 +727,8 @@ static inline int i830_tiling_supported(
 
 static inline int i830_fb_compression_supported(I830Ptr pI830)
 {
+    if (!i830_tiling_supported(pI830))
+	return FALSE;
     if (!IS_MOBILE(pI830))
 	return FALSE;
     if (IS_I810(pI830) || IS_I815(pI830) || IS_I830(pI830))
diff --git a/src/i830_driver.c b/src/i830_driver.c
index a380971..dcbed22 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2334,9 +2334,9 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
        pI830->fb_compression = TRUE;
    else
        pI830->fb_compression = FALSE;
-   /* ... but disable if requested */
-   if (!xf86ReturnOptValBool(pI830->Options, OPTION_FBC, TRUE))
-       pI830->fb_compression = FALSE;
+
+   if (xf86ReturnOptValBool(pI830->Options, OPTION_FBC, FALSE))
+       pI830->fb_compression = TRUE;
 
    if (pI830->fb_compression) {
        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Framebuffer compression enabled, "
diff-tree ca593a5219549df94a6d234ebbcf9e7c44723c9b (from 8798ef11321ee6957919279076758d47ad956cf3)
Author: Jesse Barnes <jesse.barnes at intel.com>
Date:   Fri Jul 6 16:10:52 2007 -0700

    FBC and tiling changes
      - change framebuffer option name to "FramebufferCompression"
      - add new "Tiling" option (controls all tiling, not just front buffer)
      - add debug message to fb compression enable/disable routines
      - update man page with new options

diff --git a/src/i830.h b/src/i830.h
index 1358e3e..4748b81 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -343,7 +343,7 @@ typedef struct _I830Rec {
    Bool NeedRingBufferLow;
    Bool allowPageFlip;
    Bool TripleBuffer;
-   Bool disableTiling;
+   Bool tiling;
    Bool fb_compression;
 
    int backPitch;
@@ -718,6 +718,22 @@ i830_get_transformed_coordinates(int x, 
 
 void i830_enter_render(ScrnInfoPtr);
 
+static inline int i830_tiling_supported(I830Ptr pI830)
+{
+    if (IS_I965G(pI830))
+	return FALSE;
+    return TRUE;
+}
+
+static inline int i830_fb_compression_supported(I830Ptr pI830)
+{
+    if (!IS_MOBILE(pI830))
+	return FALSE;
+    if (IS_I810(pI830) || IS_I815(pI830) || IS_I830(pI830))
+	return FALSE;
+    return TRUE;
+}
+
 extern const int I830PatternROP[16];
 extern const int I830CopyROP[16];
 
diff --git a/src/i830_display.c b/src/i830_display.c
index 0befef9..c79676d 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -728,6 +728,9 @@ i830_enable_fb_compression(xf86CrtcPtr c
     fbc_ctl |= (compressed_stride & 0xff) << FBC_CTL_STRIDE_SHIFT;
     fbc_ctl |= (interval & 0x2fff) << FBC_CTL_INTERVAL_SHIFT;
     OUTREG(FBC_CONTROL, fbc_ctl);
+
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "fbc enabled on pipe %c\n", pipe ?
+	       "a" : "b");
 }
 
 static void
@@ -745,6 +748,7 @@ i830_disable_fb_compression(xf86CrtcPtr 
     /* Wait for compressing bit to clear */
     while (INREG(FBC_STATUS) & FBC_STAT_COMPRESSING)
 	; /* nothing */
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "fbc disabled\n");
 }
 
 static void
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 5f934fe..a380971 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -287,6 +287,7 @@ typedef enum {
    OPTION_CHECKDEVICES,
    OPTION_MODEDEBUG,
    OPTION_FBC,
+   OPTION_TILING,
 #ifdef XF86DRI_MM
    OPTION_INTELTEXPOOL,
    OPTION_INTELMMSIZE,
@@ -308,7 +309,8 @@ static OptionInfoRec I830Options[] = {
    {OPTION_VIDEO_KEY,	"VideoKey",	OPTV_INTEGER,	{0},	FALSE},
    {OPTION_CHECKDEVICES, "CheckDevices",OPTV_BOOLEAN,	{0},	FALSE},
    {OPTION_MODEDEBUG,	"ModeDebug",	OPTV_BOOLEAN,	{0},	FALSE},
-   {OPTION_FBC,		"FrameBufferCompression", OPTV_BOOLEAN, {0}, FALSE},
+   {OPTION_FBC,		"FramebufferCompression", OPTV_BOOLEAN, {0}, TRUE},
+   {OPTION_TILING,	"Tiling",	OPTV_BOOLEAN,	{0},	TRUE},
 #ifdef XF86DRI_MM
    {OPTION_INTELTEXPOOL,"Legacy3D",     OPTV_BOOLEAN,	{0},	FALSE},
    {OPTION_INTELMMSIZE, "AperTexSize",  OPTV_INTEGER,	{0},	FALSE},
@@ -2318,12 +2320,34 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       pI830->CacheLines = -1;
    }
 
-   if (xf86ReturnOptValBool(pI830->Options, OPTION_FBC, FALSE))
+   /* Enable tiling by default where supported or if the user forced it on */
+   if (i830_tiling_supported(pI830))
+       pI830->tiling = TRUE;
+   else
+       pI830->tiling = FALSE;
+
+   if (xf86ReturnOptValBool(pI830->Options, OPTION_TILING, FALSE))
+       pI830->tiling = TRUE;
+
+   /* Enable FB compression if possible */
+   if (i830_fb_compression_supported(pI830))
        pI830->fb_compression = TRUE;
    else
        pI830->fb_compression = FALSE;
+   /* ... but disable if requested */
+   if (!xf86ReturnOptValBool(pI830->Options, OPTION_FBC, TRUE))
+       pI830->fb_compression = FALSE;
 
-   pI830->disableTiling = FALSE;
+   if (pI830->fb_compression) {
+       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Framebuffer compression enabled, "
+		  "forcing tiling on.\n");
+       pI830->tiling = TRUE;
+   }
+
+   xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Framebuffer compression %sabled\n",
+	      pI830->fb_compression ? "en" : "dis");
+   xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Tiling %sabled\n", pI830->tiling ?
+	      "en" : "dis");
 
    if (I830IsPrimary(pScrn)) {
       /* Alloc our pointers for the primary head */
@@ -2413,7 +2437,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
        * 3: untiled, small
        */
 
-      pI830->disableTiling = FALSE;
 #ifdef XF86DRI_MM
       savedMMSize = pI830->mmSize;
 #define MM_TURNS 4
@@ -2426,7 +2449,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 
 	 if (i >= MM_TURNS/2) {
 	    /* For further allocations, disable tiling */
-	    pI830->disableTiling = TRUE;
+	    pI830->tiling = FALSE;
 	    pScrn->displayWidth = savedDisplayWidth;
 	    if (pI830->allowPageFlip)
 	       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
@@ -2481,9 +2504,8 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 #endif
 	 pI830->directRenderingDisabled = TRUE;
       }
-   } else
+   }
 #endif
-      pI830->disableTiling = TRUE; /* no DRI - so disableTiling */
 
    if (!allocation_done) {
       if (!i830_allocate_2d_memory(pScrn)) {
@@ -2501,7 +2523,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    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->tiling = FALSE;
       pI830->directRenderingDisabled = TRUE;
    }
 
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 7134600..a589738 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -903,9 +903,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 ((!pI830->disableTiling && pI830->allowPageFlip &&
-	 IsTileable(pScrn, pitch)) || pI830->fb_compression)
-    {
+    if (pI830->tiling && IsTileable(pScrn, pitch)) {
 	/* XXX: probably not the case on 965 */
 	if (IS_I9XX(pI830))
 	    align = MB(1);
@@ -1253,7 +1251,7 @@ i830_allocate_backbuffer(ScrnInfoPtr pSc
 	height = pScrn->virtualX;
 
     /* Try to allocate on the best tile-friendly boundaries. */
-    if (!pI830->disableTiling && IsTileable(pScrn, pitch))
+    if (pI830->tiling && IsTileable(pScrn, pitch))
     {
 	size = ROUND_TO_PAGE(pitch * ALIGN(height, 16));
 	*buffer = i830_allocate_memory_tiled(pScrn, name, size, pitch,
@@ -1294,7 +1292,7 @@ i830_allocate_depthbuffer(ScrnInfoPtr pS
 	height = pScrn->virtualX;
 
     /* First try allocating it tiled */
-    if (!pI830->disableTiling && IsTileable(pScrn, pitch))
+    if (pI830->tiling && IsTileable(pScrn, pitch))
     {
 	enum tile_format tile_format;
 
diff --git a/src/i915_render.c b/src/i915_render.c
index b2dacfe..2148883 100644
--- a/src/i915_render.c
+++ b/src/i915_render.c
@@ -287,7 +287,7 @@ i915_texture_setup(PicturePtr pPict, Pix
     pI830->mapstate[unit * 3 + 1] = format |
 	((pPix->drawable.height - 1) << MS3_HEIGHT_SHIFT) |
 	((pPix->drawable.width - 1) << MS3_WIDTH_SHIFT);
-    if (!pI830->disableTiling)
+    if (pI830->tiling)
 	pI830->samplerstate[unit * 3 + 1] |= MS3_USE_FENCE_REGS;
     pI830->mapstate[unit * 3 + 2] = ((pitch / 4) - 1) << MS4_PITCH_SHIFT;
 
diff --git a/src/i915_video.c b/src/i915_video.c
index f1bf4cc..e116fe2 100644
--- a/src/i915_video.c
+++ b/src/i915_video.c
@@ -160,7 +160,7 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
       }
       ms3 |= (height - 1) << MS3_HEIGHT_SHIFT;
       ms3 |= (width - 1) << MS3_WIDTH_SHIFT;
-      if (!pI830->disableTiling)
+      if (pI830->tiling)
 	 ms3 |= MS3_USE_FENCE_REGS;
       OUT_RING(ms3);
       OUT_RING(((video_pitch / 4) - 1) << MS4_PITCH_SHIFT);
@@ -251,7 +251,7 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
       ms3 = MAPSURF_8BIT | MT_8BIT_I8;
       ms3 |= (height - 1) << MS3_HEIGHT_SHIFT;
       ms3 |= (width - 1) << MS3_WIDTH_SHIFT;
-      if (!pI830->disableTiling)
+      if (pI830->tiling)
 	 ms3 |= MS3_USE_FENCE_REGS;
       OUT_RING(ms3);
       OUT_RING(((video_pitch * 2 / 4) - 1) << MS4_PITCH_SHIFT);
@@ -260,7 +260,7 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
       ms3 = MAPSURF_8BIT | MT_8BIT_I8;
       ms3 |= (height / 2 - 1) << MS3_HEIGHT_SHIFT;
       ms3 |= (width / 2 - 1) << MS3_WIDTH_SHIFT;
-      if (!pI830->disableTiling)
+      if (pI830->tiling)
 	 ms3 |= MS3_USE_FENCE_REGS;
       OUT_RING(ms3);
       OUT_RING(((video_pitch / 4) - 1) << MS4_PITCH_SHIFT);
@@ -269,7 +269,7 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
       ms3 = MAPSURF_8BIT | MT_8BIT_I8;
       ms3 |= (height / 2 - 1) << MS3_HEIGHT_SHIFT;
       ms3 |= (width / 2 - 1) << MS3_WIDTH_SHIFT;
-      if (!pI830->disableTiling)
+      if (pI830->tiling)
 	 ms3 |= MS3_USE_FENCE_REGS;
       OUT_RING(ms3);
       OUT_RING(((video_pitch / 4) - 1) << MS4_PITCH_SHIFT);
diff-tree 8798ef11321ee6957919279076758d47ad956cf3 (from parents)
Merge: 8919b2292147add41a1c1c6e5e673257cb6c6c6e 3c552af65d28fafec1d09484a8914b690b961349
Author: Jesse Barnes <jbarnes at nietzche.virtuousgeek.org>
Date:   Thu Jul 5 12:21:31 2007 -0700

    Merge branch 'master' into fbc

diff-tree 8919b2292147add41a1c1c6e5e673257cb6c6c6e (from 407b124af8f7bb42abe4eecc87476c4c3e555cd0)
Author: Jesse Barnes <jbarnes at nietzche.virtuousgeek.org>
Date:   Thu Jul 5 12:21:06 2007 -0700

    Re-add tiling kludge, but only for 965.

diff --git a/src/i830_memory.c b/src/i830_memory.c
index 904476a..7134600 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -1450,6 +1450,11 @@ i830_set_fence(ScrnInfoPtr pScrn, int nr
     assert(tile_format != TILING_NONE);
 
     if (IS_I965G(pI830)) {
+        if (tile_format == TILING_XMAJOR)
+            pitch = 512;
+        else
+            pitch = 128;
+ 
 	if (nr < 0 || nr >= FENCE_NEW_NR) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		       "i830_set_fence(): fence %d out of range\n",nr);
diff-tree 407b124af8f7bb42abe4eecc87476c4c3e555cd0 (from 7a87b9d2a2eb4d281dce67586756ff5653b2805a)
Author: Jesse Barnes <jbarnes at nietzche.virtuousgeek.org>
Date:   Thu Jul 5 11:31:34 2007 -0700

    Remove tiling kludge.  May need more fixes for 965.

diff --git a/src/i830_memory.c b/src/i830_memory.c
index f4271ef..904476a 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -1444,8 +1444,6 @@ i830_set_fence(ScrnInfoPtr pScrn, int nr
     CARD32 fence_mask = 0;
     unsigned int fence_pitch;
 
-    pitch = 512;
-
     DPRINTF(PFX, "i830_set_fence(): %d, 0x%08x, %d, %d kByte\n",
 	    nr, offset, pitch, size / 1024);
 
diff-tree 7a87b9d2a2eb4d281dce67586756ff5653b2805a (from fecf964534f5ba6d40480cb13adc89094946a51e)
Author: Jesse Barnes <jbarnes at nietzche.virtuousgeek.org>
Date:   Thu Jul 5 11:23:06 2007 -0700

    Revert discard alpha change, requires other fixes to work.

diff --git a/src/i830_display.c b/src/i830_display.c
index 6bfa7e6..db02402 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -1032,10 +1032,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
 	    dspcntr |= DISPPLANE_16BPP;
 	break;
     case 32:
-	if (pI830->fb_compression)
-	    dspcntr |= DISPPLANE_32BPP;
-	else
-	    dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
+	dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
 	break;
     default:
 	FatalError("unknown display bpp\n");
diff-tree fecf964534f5ba6d40480cb13adc89094946a51e (from 60ee7b6a91b2b8c447130c60cd8b19eb68119777)
Author: Jesse Barnes <jbarnes at nietzche.virtuousgeek.org>
Date:   Thu Jul 5 10:59:23 2007 -0700

    FBC fixes:
      - properly check several FBC enablement constraints
      - don't use alpha discard if FBC is in use

diff --git a/src/i830_display.c b/src/i830_display.c
index 1feb13b..6bfa7e6 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -654,6 +654,34 @@ i830_crtc_unlock (xf86CrtcPtr crtc)
 #endif
 }
 
+static Bool
+i830_use_fb_compression(xf86CrtcPtr crtc)
+{
+    ScrnInfoPtr pScrn = crtc->scrn;
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
+    int pipe = intel_crtc->pipe;
+    int plane = (pipe == 0 ? FBC_CTL_PIPEA : FBC_CTL_PIPEB);
+
+    if (!pI830->fb_compression)
+	return FALSE;
+
+    /* Pre-965 only supports plane A, which is synonymous with pipe A for now */
+    if (!IS_I965GM(pI830) && plane != FBC_CTL_PIPEA)
+	return FALSE;
+
+    /* Need 15, 16, or 32 (w/alpha) pixel format */
+    if (!(pScrn->bitsPerPixel == 16 || /* covers 15 bit mode as well */
+	  pScrn->bitsPerPixel == 32)) /* mode_set dtrt if fbc is in use */
+	return FALSE;
+
+    /*
+     * No checks for pixel multiply, incl. horizontal, or interlaced modes
+     * since they're currently unused.
+     */
+    return TRUE;
+}
+
 /*
  * Several restrictions:
  *   - DSP[AB]CNTR - no line duplication && no pixel multiplier
@@ -661,6 +689,9 @@ i830_crtc_unlock (xf86CrtcPtr crtc)
  *   - no alpha buffer discard
  *   - no dual wide display
  *   - progressive mode only (DSP[AB]CNTR)
+ *   - uncompressed fb is <= 2048 in width, 0 mod 8
+ *   - uncompressed fb is <= 1536 in height, 0 mod 2
+ *   - SR display watermarks must be equal between 16bpp and 32bpp?
  *
  * FIXME: verify above conditions are true
  */
@@ -719,20 +750,14 @@ i830_disable_fb_compression(xf86CrtcPtr 
 static void
 i830_crtc_prepare (xf86CrtcPtr crtc)
 {
-    ScrnInfoPtr pScrn = crtc->scrn;
-    I830Ptr pI830 = I830PTR(pScrn);
-    crtc->funcs->dpms (crtc, DPMSModeOff);
-
     /* Temporarily turn off FB compression during modeset */
-    if (pI830->fb_compression)
-	i830_disable_fb_compression(crtc);
+    i830_disable_fb_compression(crtc);
+    crtc->funcs->dpms (crtc, DPMSModeOff);
 }
 
 static void
 i830_crtc_commit (xf86CrtcPtr crtc)
 {
-    ScrnInfoPtr pScrn = crtc->scrn;
-    I830Ptr pI830 = I830PTR(pScrn);
     I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
     Bool		deactivate = FALSE;
 
@@ -748,7 +773,7 @@ i830_crtc_commit (xf86CrtcPtr crtc)
 	i830_pipe_a_require_deactivate (crtc->scrn);
 
     /* Reenable FB compression if possible */
-    if (pI830->fb_compression)
+    if (i830_use_fb_compression(crtc))
 	i830_enable_fb_compression(crtc);
 }
 
@@ -1007,7 +1032,10 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
 	    dspcntr |= DISPPLANE_16BPP;
 	break;
     case 32:
-	dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
+	if (pI830->fb_compression)
+	    dspcntr |= DISPPLANE_32BPP;
+	else
+	    dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
 	break;
     default:
 	FatalError("unknown display bpp\n");
diff-tree 60ee7b6a91b2b8c447130c60cd8b19eb68119777 (from f02036aedcd7866c567a6adc070eda3dad872105)
Author: Jesse Barnes <jbarnes at nietzche.virtuousgeek.org>
Date:   Tue Jul 3 14:20:34 2007 -0700

    Fixup line length buffer padding, add kludge for front buffer tile
    pitch.

diff --git a/src/i830_display.c b/src/i830_display.c
index 5b1d6ea..1feb13b 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -678,7 +678,7 @@ i830_enable_fb_compression(xf86CrtcPtr c
     unsigned long interval = 1000;
 
     compressed_stride = pI830->compressed_front_buffer->size /
-	FBC_COMPRESSED_LINES;
+	FBC_LL_SIZE;
 
     if (uncompressed_stride < compressed_stride)
 	compressed_stride = uncompressed_stride;
@@ -688,7 +688,7 @@ i830_enable_fb_compression(xf86CrtcPtr c
 
     /* Set it up... */
     OUTREG(FBC_CFB_BASE, pI830->compressed_front_buffer->bus_addr);
-    OUTREG(FBC_LL_BASE, pI830->compressed_ll_buffer->bus_addr);
+    OUTREG(FBC_LL_BASE, pI830->compressed_ll_buffer->bus_addr + FBC_LL_PAD);
     OUTREG(FBC_CONTROL2, FBC_CTL_CPU_FENCE | plane);
 
     /* enable it... */
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 8703f2d..f4271ef 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -1052,8 +1052,7 @@ static void i830_setup_fb_compression(Sc
      */
     pI830->compressed_front_buffer =
 	i830_allocate_memory(pScrn, "compressed frame buffer",
-			     MB(6), KB(4),
-			     NEED_PHYSICAL_ADDR);
+			     MB(6), KB(4), NEED_PHYSICAL_ADDR);
 
     if (!pI830->compressed_front_buffer) {
 	pI830->fb_compression = FALSE;
@@ -1062,7 +1061,8 @@ static void i830_setup_fb_compression(Sc
 
     pI830->compressed_ll_buffer =
 	i830_allocate_memory(pScrn, "compressed ll buffer",
-			     1568, KB(4), NEED_PHYSICAL_ADDR);
+			     FBC_LL_SIZE + FBC_LL_PAD, KB(4),
+			     NEED_PHYSICAL_ADDR);
     if (!pI830->compressed_ll_buffer) {
 	i830_free_memory(pScrn, pI830->compressed_front_buffer);
 	pI830->fb_compression = FALSE;
@@ -1444,6 +1444,8 @@ i830_set_fence(ScrnInfoPtr pScrn, int nr
     CARD32 fence_mask = 0;
     unsigned int fence_pitch;
 
+    pitch = 512;
+
     DPRINTF(PFX, "i830_set_fence(): %d, 0x%08x, %d, %d kByte\n",
 	    nr, offset, pitch, size / 1024);
 
diff --git a/src/i830_reg.h b/src/i830_reg.h
index b5fa1b9..d1670c3 100644
--- a/src/i830_reg.h
+++ b/src/i830_reg.h
@@ -50,7 +50,8 @@
 #define   FBC_CTL_PIPEA		(0<<0)
 #define   FBC_CTL_PIPEB		(1<<0)
 
-#define FBC_COMPRESSED_LINES	(1536+32)
+#define FBC_LL_SIZE		(1536)
+#define FBC_LL_PAD		(32)
 
 #define I830_SET_FIELD( var, mask, value ) (var &= ~(mask), var |= value)
 
diff-tree 3c552af65d28fafec1d09484a8914b690b961349 (from 2b9961eb9ce8734565ecdb01cb11610714d7f610)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Jul 2 18:33:47 2007 -0700

    Update documentation and bump driver version to 2.1.0.

diff --git a/README b/README
index bcb0205..c91c661 100644
--- a/README
+++ b/README
@@ -1,6 +1,6 @@
 Information for Intel graphics driver users
 Eric Anholt
-2007-04-02
+2007-07-02
 
 This document provides a brief summary of the Intel graphics support provided
 by the xf86-video-intel driver.  More information can also be found in the
@@ -15,9 +15,14 @@ Supported Hardware:
 	i845
 	i852
 	i855
-	i915
-	i945
-	i965
+	915G
+	915GM
+	945G
+	945GM/GME
+	946GZ
+	G965
+	GM/GME965
+	G33/Q33/Q35
 
 Features
 - Full support for 8, 15, 16, and 24 bit pixel depths.
@@ -70,6 +75,9 @@ Known Limitations
   release.
 - Gray output with integrated TV-out and PAL TVs.
 - EXA support unstable on i845.
+- Some GM965 systems, such as the Thinkpad T61, probe the TV as being connected
+  even when no output connector is available.  This results in the gnome-panel
+  issue noted below.
 
 Common issues not caused by the driver
 - Font sizes (DPI) are wrong.  Some displays incorrectly report their
@@ -80,7 +88,7 @@ Common issues not caused by the driver
 - gnome-panel is located in the middle of the screen.  gnome-panel places
   itself within head #0's boundaries, which doesn't work well with a second
   head covering the same area as head #0 but larger.
-- Older resolution-changing applicationss have poor results in
+- Older resolution-changing applications have poor results in
   multihead systems.  Previous extensions such as RandR 1.1 exposed only a
   single output to client programs, and those requests map poorly to multi-head
   systems.  Currently, those requests map to just one of the outputs in the
diff --git a/configure.ac b/configure.ac
index a39635e..ec30376 100644
--- a/configure.ac
+++ b/configure.ac
@@ -22,7 +22,7 @@
 
 AC_PREREQ(2.57)
 AC_INIT([xf86-video-intel],
-        2.0.0,
+        2.1.0,
         [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
         xf86-video-intel)
 
diff --git a/man/intel.man b/man/intel.man
index 8991619..75280a7 100644
--- a/man/intel.man
+++ b/man/intel.man
@@ -24,14 +24,15 @@ 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, 946GZ and 965GM chipsets.
+865G, 915G, 915GM, 945G, 945GM, 965G, 965Q, 946GZ, 965GM, 945GME,
+G33, Q33, and Q35 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
+The Intel 8xx and 9xx families of integrated graphics chipsets have 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
@@ -66,12 +67,9 @@ 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
+2D acceleration and video when XAA acceleration is enabled.  Decreasing this
+amount leaves more for 3D textures.  Increasing it can improve 2D performance
+at the expense of 3D performance.
 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
@@ -145,7 +143,7 @@ the full benefit without triple bufferin
 .B "Option \*qTripleBuffer\*q"
 ).
 Default for i810: The option is not used.
-Default for i830 and above: Disabled.
+Default for i830 and above: Disabled (This option is currently unstable).
 .TP
 .BI "Option \*qTripleBuffer\*q \*q" boolean \*q
 Enable support for triple buffering. This should improve 3D performance at the
@@ -202,5 +200,5 @@ support reworked for XFree86 4.3 by Davi
 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. 965GM support
-added by Wang Zhenyu.
+Zhenyu. TV out support added by Zou Nan Hai and Keith Packard. 965GM, G33,
+Q33, and Q35 support added by Wang Zhenyu.
diff-tree f02036aedcd7866c567a6adc070eda3dad872105 (from b384c608978dcd3d2ea6c0018179673cb4735f4c)
Author: Jesse Barnes <jbarnes at nietzche.virtuousgeek.org>
Date:   Mon Jul 2 15:42:02 2007 -0700

    Framebuffer compression changes:
      - move FBC register definitions to i830_reg.h
      - add fix from Arjan for 965 depth buffer tiling
      - add VT switch and clear-at-server-start code for FBC registers

diff --git a/src/i830.h b/src/i830.h
index 29982ec..1358e3e 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -530,6 +530,10 @@ typedef struct _I830Rec {
    CARD32 savePaletteB[256];
    CARD32 saveSWF[17];
    CARD32 saveBLC_PWM_CTL;
+   CARD32 saveFBC_CFB_BASE;
+   CARD32 saveFBC_LL_BASE;
+   CARD32 saveFBC_CONTROL2;
+   CARD32 saveFBC_CONTROL;
 
    enum last_3d *last_3d;
 
diff --git a/src/i830_display.c b/src/i830_display.c
index f3b24b2..5b1d6ea 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -38,6 +38,7 @@
 
 #include "xf86.h"
 #include "i830.h"
+#include "i830_reg.h"
 #include "i830_bios.h"
 #include "i830_display.h"
 #include "i830_debug.h"
@@ -653,28 +654,6 @@ i830_crtc_unlock (xf86CrtcPtr crtc)
 #endif
 }
 
-#define FBC_CFB_BASE		0x03200 /* 4k page aligned */
-#define FBC_LL_BASE		0x03204 /* 4k page aligned */
-#define FBC_CONTROL		0x03208
-#define   FBC_CTL_EN		(1<<31)
-#define   FBC_CTL_PERIODIC	(1<<30)
-#define   FBC_CTL_INTERVAL_SHIFT (16)
-#define   FBC_CTL_STRIDE_SHIFT	(5)
-#define   FBC_CTL_FENCENO	(1<<0)
-#define FBC_COMMAND		0x0320c
-#define   FBC_CMD_COMPRESS	(1<<0)
-#define FBC_STATUS		0x03210
-#define   FBC_STAT_COMPRESSING	(1<<31)
-#define   FBC_STAT_COMPRESSED	(1<<30)
-#define   FBC_STAT_MODIFIED	(1<<29)
-#define   FBC_STAT_CURRENT_LINE	(1<<0)
-#define FBC_CONTROL2		0x03214
-#define   FBC_CTL_CPU_FENCE	(1<<1)
-#define   FBC_CTL_PIPEA		(0<<0)
-#define   FBC_CTL_PIPEB		(1<<0)
-
-#define FBC_COMPRESSED_LINES	(1536+32)
-
 /*
  * Several restrictions:
  *   - DSP[AB]CNTR - no line duplication && no pixel multiplier
@@ -718,9 +697,6 @@ i830_enable_fb_compression(xf86CrtcPtr c
     fbc_ctl |= (compressed_stride & 0xff) << FBC_CTL_STRIDE_SHIFT;
     fbc_ctl |= (interval & 0x2fff) << FBC_CTL_INTERVAL_SHIFT;
     OUTREG(FBC_CONTROL, fbc_ctl);
-
-    /* and request immediate compression */
-    OUTREG(FBC_COMMAND, FBC_CMD_COMPRESS);
 }
 
 static void
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 42d0f87..5f934fe 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -192,6 +192,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "vbe.h"
 #include "shadow.h"
 #include "i830.h"
+#include "i830_reg.h"
 #include "i830_display.h"
 #include "i830_debug.h"
 #include "i830_bios.h"
@@ -1750,6 +1751,11 @@ SaveHWState(ScrnInfoPtr pScrn)
    vgaRegPtr vgaReg = &hwp->SavedReg;
    int i;
 
+   pI830->saveFBC_CFB_BASE = INREG(FBC_CFB_BASE);
+   pI830->saveFBC_LL_BASE = INREG(FBC_LL_BASE);
+   pI830->saveFBC_CONTROL2 = INREG(FBC_CONTROL2);
+   pI830->saveFBC_CONTROL = INREG(FBC_CONTROL);
+
    /* Save video mode information for native mode-setting. */
    pI830->saveDSPACNTR = INREG(DSPACNTR);
    pI830->savePIPEACONF = INREG(PIPEACONF);
@@ -1974,6 +1980,11 @@ RestoreHWState(ScrnInfoPtr pScrn)
    OUTREG(SWF31, pI830->saveSWF[15]);
    OUTREG(SWF32, pI830->saveSWF[16]);
 
+   OUTREG(FBC_CFB_BASE, pI830->saveFBC_CFB_BASE);
+   OUTREG(FBC_LL_BASE, pI830->saveFBC_LL_BASE);
+   OUTREG(FBC_CONTROL2, pI830->saveFBC_CONTROL2);
+   OUTREG(FBC_CONTROL, pI830->saveFBC_CONTROL);
+
    vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS);
    vgaHWLock(hwp);
 
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 5e553f1..8703f2d 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -104,6 +104,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 #include "i830.h"
 #include "i810_reg.h"
+#include "i830_reg.h"
 
 #define ALIGN(i,m)    (((i) + (m) - 1) & ~((m) - 1))
 
@@ -1032,6 +1033,12 @@ static void i830_setup_fb_compression(Sc
 	goto out;
     }
 
+    /* Clear out any stale state */
+    OUTREG(FBC_CFB_BASE, 0);
+    OUTREG(FBC_LL_BASE, 0);
+    OUTREG(FBC_CONTROL2, 0);
+    OUTREG(FBC_CONTROL, 0);
+
     /*
      * Compressed framebuffer limitations:
      *   - contiguous, physical, uncached memory
@@ -1302,7 +1309,8 @@ i830_allocate_depthbuffer(ScrnInfoPtr pS
 	    i830_allocate_memory_tiled(pScrn, "depth buffer", size, pitch,
 				       GTT_PAGE_SIZE, ALIGN_BOTH_ENDS,
 				       tile_format);
-	pI830->depth_tiled = FENCE_XMAJOR;
+	pI830->depth_tiled = (tile_format == TILING_YMAJOR) ? FENCE_YMAJOR :
+	    FENCE_XMAJOR;
     }
 
     /* Otherwise, allocate it linear. */
diff --git a/src/i830_reg.h b/src/i830_reg.h
index 7a8df9f..b5fa1b9 100644
--- a/src/i830_reg.h
+++ b/src/i830_reg.h
@@ -29,6 +29,29 @@
 #ifndef _I830_REG_H_
 #define _I830_REG_H_
 
+/* Framebuffer compression */
+#define FBC_CFB_BASE		0x03200 /* 4k page aligned */
+#define FBC_LL_BASE		0x03204 /* 4k page aligned */
+#define FBC_CONTROL		0x03208
+#define   FBC_CTL_EN		(1<<31)
+#define   FBC_CTL_PERIODIC	(1<<30)
+#define   FBC_CTL_INTERVAL_SHIFT (16)
+#define   FBC_CTL_STRIDE_SHIFT	(5)
+#define   FBC_CTL_FENCENO	(1<<0)
+#define FBC_COMMAND		0x0320c
+#define   FBC_CMD_COMPRESS	(1<<0)
+#define FBC_STATUS		0x03210
+#define   FBC_STAT_COMPRESSING	(1<<31)
+#define   FBC_STAT_COMPRESSED	(1<<30)
+#define   FBC_STAT_MODIFIED	(1<<29)
+#define   FBC_STAT_CURRENT_LINE	(1<<0)
+#define FBC_CONTROL2		0x03214
+#define   FBC_CTL_CPU_FENCE	(1<<1)
+#define   FBC_CTL_PIPEA		(0<<0)
+#define   FBC_CTL_PIPEB		(1<<0)
+
+#define FBC_COMPRESSED_LINES	(1536+32)
+
 #define I830_SET_FIELD( var, mask, value ) (var &= ~(mask), var |= value)
 
 #define CMD_3D (0x3<<29)
diff-tree 2b9961eb9ce8734565ecdb01cb11610714d7f610 (from 3d9ee8b2991ec0da8cc21b8455ff7f00fd0335b5)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Jul 2 15:16:33 2007 -0700

    Fix reversed LVDS dither enabling logic on GM965.

diff --git a/src/i830_display.c b/src/i830_display.c
index aba86ae..ebde525 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -1019,9 +1019,9 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
 	if (IS_I965G(pI830))
 	{
 	    if ((lvds & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP)
-		lvds |= LVDS_DITHER_ENABLE;
-	    else
 		lvds &= ~LVDS_DITHER_ENABLE;
+	    else
+		lvds |= LVDS_DITHER_ENABLE;
 	}
 
 	OUTREG(LVDS, lvds);
diff-tree 3d9ee8b2991ec0da8cc21b8455ff7f00fd0335b5 (from 1e2e301348b4168aeed38b3fdc6b0e43d5678a86)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Jul 2 14:38:28 2007 -0700

    Bug #11365: Disable the panel fitter unless it's needed for the chosen mode.
    
    The automatic panel scaling appears to choose bad sampling on some GM965
    hardware for 1:1 mapping modes, and there's no real sense in having it on
    if we just want 1:1.

diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index d469815..e2c6e3c 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -261,17 +261,23 @@ i830_lvds_mode_set(xf86OutputPtr output,
     I830CrtcPrivatePtr	    intel_crtc = output->crtc->driver_private;
     CARD32		    pfit_control;
 
-    /* The LVDS pin pair will already have been turned on in the
+    /* The LVDS pin pair will already have been turned on in
      * i830_crtc_mode_set since it has a large impact on the DPLL settings.
      */
 
-    /* Enable automatic panel scaling so that non-native modes fill the
-     * screen.  Should be enabled before the pipe is enabled, according to
+    /* Enable automatic panel scaling for non-native modes so that they fill
+     * the screen.  Should be enabled before the pipe is enabled, according to
      * register description and PRM.
      */
-    pfit_control = (PFIT_ENABLE |
-		    VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
-		    VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR);
+    if (mode->HDisplay != adjusted_mode->HDisplay ||
+	mode->VDisplay != adjusted_mode->VDisplay)
+    {
+	pfit_control = PFIT_ENABLE |
+	    VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
+	    VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR;
+    } else {
+	pfit_control = 0;
+    }
 
     if (!IS_I965G(pI830)) {
 	if (dev_priv->panel_wants_dither)
diff-tree b384c608978dcd3d2ea6c0018179673cb4735f4c (from 1e2e301348b4168aeed38b3fdc6b0e43d5678a86)
Author: Jesse Barnes <jbarnes at nietzche.virtuousgeek.org>
Date:   Mon Jul 2 09:32:28 2007 -0700

    Enable framebuffer compression (use Option "FrameBufferCompression"
    "true" in your xorg.conf).  Should save ~0.5W during typical 2D usage.

diff --git a/man/intel.man b/man/intel.man
index 8991619..3e443cd 100644
--- a/man/intel.man
+++ b/man/intel.man
@@ -77,6 +77,13 @@ driver attempts to allocate space for at
 HD-sized XV video.  The default used for a specific configuration can be found
 by examining the __xservername__ log file.
 .TP
+.BI "Option \*qFrameBufferCompression\*q \*q" boolean \*q
+This option controls whether the framebuffer compression feature is enabled.
+If possible, the front buffer will be allocated in a tiled format and compressed
+periodically to save memory bandwidth and power.
+.TP
+This option is only available on mobile chipsets.
+.TP
 .BI "Option \*qDRI\*q \*q" boolean \*q
 Disable or enable DRI support.
 Default: DRI is enabled for configurations where it is supported.
diff --git a/src/i830.h b/src/i830.h
index 9dda33a..29982ec 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -287,6 +287,8 @@ typedef struct _I830Rec {
 
    i830_memory *front_buffer;
    i830_memory *front_buffer_2;
+   i830_memory *compressed_front_buffer;
+   i830_memory *compressed_ll_buffer;
    /* One big buffer for all cursors for kernels that support this */
    i830_memory *cursor_mem;
    /* separate small buffers for kernels that support this */
@@ -342,6 +344,7 @@ typedef struct _I830Rec {
    Bool allowPageFlip;
    Bool TripleBuffer;
    Bool disableTiling;
+   Bool fb_compression;
 
    int backPitch;
 
diff --git a/src/i830_display.c b/src/i830_display.c
index aba86ae..f3b24b2 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -653,15 +653,110 @@ i830_crtc_unlock (xf86CrtcPtr crtc)
 #endif
 }
 
+#define FBC_CFB_BASE		0x03200 /* 4k page aligned */
+#define FBC_LL_BASE		0x03204 /* 4k page aligned */
+#define FBC_CONTROL		0x03208
+#define   FBC_CTL_EN		(1<<31)
+#define   FBC_CTL_PERIODIC	(1<<30)
+#define   FBC_CTL_INTERVAL_SHIFT (16)
+#define   FBC_CTL_STRIDE_SHIFT	(5)
+#define   FBC_CTL_FENCENO	(1<<0)
+#define FBC_COMMAND		0x0320c
+#define   FBC_CMD_COMPRESS	(1<<0)
+#define FBC_STATUS		0x03210
+#define   FBC_STAT_COMPRESSING	(1<<31)
+#define   FBC_STAT_COMPRESSED	(1<<30)
+#define   FBC_STAT_MODIFIED	(1<<29)
+#define   FBC_STAT_CURRENT_LINE	(1<<0)
+#define FBC_CONTROL2		0x03214
+#define   FBC_CTL_CPU_FENCE	(1<<1)
+#define   FBC_CTL_PIPEA		(0<<0)
+#define   FBC_CTL_PIPEB		(1<<0)
+
+#define FBC_COMPRESSED_LINES	(1536+32)
+
+/*
+ * Several restrictions:
+ *   - DSP[AB]CNTR - no line duplication && no pixel multiplier
+ *   - pixel format == 15 bit, 16 bit, or 32 bit xRGB_8888
+ *   - no alpha buffer discard
+ *   - no dual wide display
+ *   - progressive mode only (DSP[AB]CNTR)
+ *
+ * FIXME: verify above conditions are true
+ */
+static void
+i830_enable_fb_compression(xf86CrtcPtr crtc)
+{
+    ScrnInfoPtr pScrn = crtc->scrn;
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
+    uint32_t fbc_ctl;
+    unsigned long compressed_stride;
+    int pipe = intel_crtc->pipe;
+    int plane = (pipe == 0 ? FBC_CTL_PIPEA : FBC_CTL_PIPEB);
+    unsigned long uncompressed_stride = pScrn->displayWidth * pI830->cpp;
+    unsigned long interval = 1000;
+
+    compressed_stride = pI830->compressed_front_buffer->size /
+	FBC_COMPRESSED_LINES;
+
+    if (uncompressed_stride < compressed_stride)
+	compressed_stride = uncompressed_stride;
+
+    /* FBC_CTL wants 64B units */
+    compressed_stride = (compressed_stride / 64) - 1;
+
+    /* Set it up... */
+    OUTREG(FBC_CFB_BASE, pI830->compressed_front_buffer->bus_addr);
+    OUTREG(FBC_LL_BASE, pI830->compressed_ll_buffer->bus_addr);
+    OUTREG(FBC_CONTROL2, FBC_CTL_CPU_FENCE | plane);
+
+    /* enable it... */
+    fbc_ctl = INREG(FBC_CONTROL);
+    fbc_ctl |= FBC_CTL_EN | FBC_CTL_PERIODIC;
+    fbc_ctl |= (compressed_stride & 0xff) << FBC_CTL_STRIDE_SHIFT;
+    fbc_ctl |= (interval & 0x2fff) << FBC_CTL_INTERVAL_SHIFT;
+    OUTREG(FBC_CONTROL, fbc_ctl);
+
+    /* and request immediate compression */
+    OUTREG(FBC_COMMAND, FBC_CMD_COMPRESS);
+}
+
+static void
+i830_disable_fb_compression(xf86CrtcPtr crtc)
+{
+    ScrnInfoPtr pScrn = crtc->scrn;
+    I830Ptr pI830 = I830PTR(pScrn);
+    uint32_t fbc_ctl;
+
+    /* Disable compression */
+    fbc_ctl = INREG(FBC_CONTROL);
+    fbc_ctl &= ~FBC_CTL_EN;
+    OUTREG(FBC_CONTROL, fbc_ctl);
+
+    /* Wait for compressing bit to clear */
+    while (INREG(FBC_STATUS) & FBC_STAT_COMPRESSING)
+	; /* nothing */
+}
+
 static void
 i830_crtc_prepare (xf86CrtcPtr crtc)
 {
+    ScrnInfoPtr pScrn = crtc->scrn;
+    I830Ptr pI830 = I830PTR(pScrn);
     crtc->funcs->dpms (crtc, DPMSModeOff);
+
+    /* Temporarily turn off FB compression during modeset */
+    if (pI830->fb_compression)
+	i830_disable_fb_compression(crtc);
 }
 
 static void
 i830_crtc_commit (xf86CrtcPtr crtc)
 {
+    ScrnInfoPtr pScrn = crtc->scrn;
+    I830Ptr pI830 = I830PTR(pScrn);
     I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
     Bool		deactivate = FALSE;
 
@@ -675,6 +770,10 @@ i830_crtc_commit (xf86CrtcPtr crtc)
 	xf86_reload_cursors (crtc->scrn->pScreen);
     if (deactivate)
 	i830_pipe_a_require_deactivate (crtc->scrn);
+
+    /* Reenable FB compression if possible */
+    if (pI830->fb_compression)
+	i830_enable_fb_compression(crtc);
 }
 
 void
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 7f1fe2c..42d0f87 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -285,6 +285,7 @@ typedef enum {
    OPTION_COLOR_KEY,
    OPTION_CHECKDEVICES,
    OPTION_MODEDEBUG,
+   OPTION_FBC,
 #ifdef XF86DRI_MM
    OPTION_INTELTEXPOOL,
    OPTION_INTELMMSIZE,
@@ -306,6 +307,7 @@ static OptionInfoRec I830Options[] = {
    {OPTION_VIDEO_KEY,	"VideoKey",	OPTV_INTEGER,	{0},	FALSE},
    {OPTION_CHECKDEVICES, "CheckDevices",OPTV_BOOLEAN,	{0},	FALSE},
    {OPTION_MODEDEBUG,	"ModeDebug",	OPTV_BOOLEAN,	{0},	FALSE},
+   {OPTION_FBC,		"FrameBufferCompression", OPTV_BOOLEAN, {0}, FALSE},
 #ifdef XF86DRI_MM
    {OPTION_INTELTEXPOOL,"Legacy3D",     OPTV_BOOLEAN,	{0},	FALSE},
    {OPTION_INTELMMSIZE, "AperTexSize",  OPTV_INTEGER,	{0},	FALSE},
@@ -2305,6 +2307,11 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       pI830->CacheLines = -1;
    }
 
+   if (xf86ReturnOptValBool(pI830->Options, OPTION_FBC, FALSE))
+       pI830->fb_compression = TRUE;
+   else
+       pI830->fb_compression = FALSE;
+
    pI830->disableTiling = FALSE;
 
    if (I830IsPrimary(pScrn)) {
diff --git a/src/i830_memory.c b/src/i830_memory.c
index afdd93d..5e553f1 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -902,8 +902,8 @@ 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 (!pI830->disableTiling && pI830->allowPageFlip &&
-	IsTileable(pScrn, pitch))
+    if ((!pI830->disableTiling && pI830->allowPageFlip &&
+	 IsTileable(pScrn, pitch)) || pI830->fb_compression)
     {
 	/* XXX: probably not the case on 965 */
 	if (IS_I9XX(pI830))
@@ -1022,6 +1022,56 @@ i830_allocate_cursor_buffers(ScrnInfoPtr
     return TRUE;
 }
 
+static void i830_setup_fb_compression(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    /* Only mobile chips since 845 support this feature */
+    if (!IS_MOBILE(pI830)) {
+	pI830->fb_compression = FALSE;
+	goto out;
+    }
+
+    /*
+     * Compressed framebuffer limitations:
+     *   - contiguous, physical, uncached memory
+     *   - ideally as large as the front buffer(s), smaller sizes cache less
+     *   - uncompressed buffer must be tiled w/pitch 2k-16k
+     *   - uncompressed fb is <= 2048 in width, 0 mod 8
+     *   - uncompressed fb is <= 1536 in height, 0 mod 2
+     *   - compressed fb stride is <= uncompressed stride
+     *   - SR display watermarks must be equal between 16bpp and 32bpp?
+     *   - both compressed and line buffers must be in stolen memory
+     */
+    pI830->compressed_front_buffer =
+	i830_allocate_memory(pScrn, "compressed frame buffer",
+			     MB(6), KB(4),
+			     NEED_PHYSICAL_ADDR);
+
+    if (!pI830->compressed_front_buffer) {
+	pI830->fb_compression = FALSE;
+	goto out;
+    }
+
+    pI830->compressed_ll_buffer =
+	i830_allocate_memory(pScrn, "compressed ll buffer",
+			     1568, KB(4), NEED_PHYSICAL_ADDR);
+    if (!pI830->compressed_ll_buffer) {
+	i830_free_memory(pScrn, pI830->compressed_front_buffer);
+	pI830->fb_compression = FALSE;
+	goto out;
+    }
+
+out:
+    if (pI830->fb_compression)
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Framebuffer compression "
+		   "enabled\n");
+    else
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Allocation error, framebuffer"
+		   " compression disabled\n");
+	
+    return;
+}
 /*
  * Allocate memory for 2D operation.  This includes the (front) framebuffer,
  * ring buffer, scratch memory, HW cursor.
@@ -1046,6 +1096,9 @@ i830_allocate_2d_memory(ScrnInfoPtr pScr
     /* Allocate the ring buffer first, so it ends up in stolen mem. */
     i830_allocate_ringbuffer(pScrn);
 
+    if (pI830->fb_compression)
+	i830_setup_fb_compression(pScrn);
+
     /* Next, allocate other fixed-size allocations we have. */
     if (!pI830->SWCursor && !i830_allocate_cursor_buffers(pScrn)) {
 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
diff-tree 1e2e301348b4168aeed38b3fdc6b0e43d5678a86 (from 11862c2e1f23b77b56d7bd8b384579b5e3ae377b)
Author: Keith Packard <keithp at dulcimer.keithp.com>
Date:   Sat Jun 30 12:45:24 2007 -0700

    Fix load detection to use border region instead of blanking.
    
    Make sure there is some border area to use by changing how the pipe is
    configured, then pick a scanline in the middle of the border for load
    detection. This lets the load detect code use an active pipe instead of
    requiring an idle one.

diff --git a/src/i830_crt.c b/src/i830_crt.c
index d9f4ee6..6d70f39 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -201,15 +201,16 @@ i830_crt_detect_load (xf86CrtcPtr	    cr
     ScrnInfoPtr		    pScrn = output->scrn;
     I830Ptr		    pI830 = I830PTR(pScrn);
     I830CrtcPrivatePtr	    i830_crtc = I830CrtcPrivate(crtc);
-    I830OutputPrivatePtr    intel_output = output->driver_private;
     CARD32		    save_bclrpat;
     CARD32		    save_vtotal;
     CARD32		    vtotal, vactive;
     CARD32		    vsample;
+    CARD32		    vblank, vblank_start, vblank_end;
     CARD32		    dsl;
     CARD8		    st00;
     int			    bclrpat_reg, pipeconf_reg, pipe_dsl_reg;
     int			    vtotal_reg;
+    int			    vblank_reg;
     int			    pipe = i830_crtc->pipe;
     int			    count, detect;
     Bool		    present;
@@ -218,6 +219,7 @@ i830_crt_detect_load (xf86CrtcPtr	    cr
     {
 	bclrpat_reg = BCLRPAT_A;
 	vtotal_reg = VTOTAL_A;
+	vblank_reg = VBLANK_A;
 	pipeconf_reg = PIPEACONF;
 	pipe_dsl_reg = PIPEA_DSL;
     }
@@ -225,18 +227,26 @@ i830_crt_detect_load (xf86CrtcPtr	    cr
     {
 	bclrpat_reg = BCLRPAT_B;
 	vtotal_reg = VTOTAL_B;
+	vblank_reg = VBLANK_B;
 	pipeconf_reg = PIPEBCONF;
 	pipe_dsl_reg = PIPEB_DSL;
     }
 
     save_bclrpat = INREG(bclrpat_reg);
     save_vtotal = INREG(vtotal_reg);
+    vblank = INREG(vblank_reg);
+    
+    vtotal = ((save_vtotal >> 16) & 0xfff) + 1;
+    vactive = (save_vtotal & 0x7ff) + 1;
 
-    vtotal = (save_vtotal >> 16) & 0xfff;
-    vactive = save_vtotal & 0x7ff;
+    vblank_start = (vblank & 0xfff) + 1;
+    vblank_end = ((vblank >> 16) & 0xfff) + 1;
     
-    /* sample the middle of the blanking interval */
-    vsample = ((vtotal - 3) + (vactive)) >> 1;
+    /* sample in the vertical border, selecting the larger one */
+    if (vblank_start - vactive >= vtotal - vblank_end)
+	vsample = (vblank_start + vactive) >> 1;
+    else
+	vsample = (vtotal + vblank_end) >> 1;
 
     /* Set the border color to purple. */
     OUTREG(bclrpat_reg, 0x500050);
@@ -271,8 +281,6 @@ i830_crt_detect_load (xf86CrtcPtr	    cr
      * the screen
      */
     present = detect * 4 > count * 3;
-    xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "present: %s (%d of %d) at %ld desired %ld temp %d\n",
-		present ? "TRUE" : "FALSE", detect, count, dsl, vsample, intel_output->load_detect_temp);
     return present;
 }
 
@@ -341,11 +349,16 @@ i830_crt_detect(xf86OutputPtr output)
 	Bool			connected;
 	I830OutputPrivatePtr	intel_output = output->driver_private;
 	
-	if (intel_output->load_detect_temp)
+	if (!crtc->enabled)
 	{
 	    xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
 	    xf86CrtcSetMode (crtc, &mode, RR_Rotate_0, 0, 0);
 	}
+	else if (intel_output->load_detect_temp)
+	{
+	    output->funcs->mode_set (output, &crtc->mode, &crtc->mode);
+	    output->funcs->commit (output);
+	}
 	connected = i830_crt_detect_load (crtc, output);
 
 	i830ReleaseLoadDetectPipe (output);
@@ -384,6 +397,7 @@ i830_crt_init(ScrnInfoPtr pScrn)
 {
     xf86OutputPtr	    output;
     I830OutputPrivatePtr    i830_output;
+    I830Ptr		    pI830 = I830PTR(pScrn);
 
     output = xf86OutputCreate (pScrn, &i830_crt_output_funcs, "VGA");
     if (!output)
@@ -395,7 +409,11 @@ i830_crt_init(ScrnInfoPtr pScrn)
 	return;
     }
     i830_output->type = I830_OUTPUT_ANALOG;
-    i830_output->pipe_mask = ((1 << 0) | (1 << 1));
+    /* i830 (almador) cannot place the analog adaptor on pipe B */
+    if (IS_I830(pI830))
+	i830_output->pipe_mask = (1 << 0);
+    else
+	i830_output->pipe_mask = ((1 << 0) | (1 << 1));
     i830_output->clone_mask = ((1 << I830_OUTPUT_ANALOG) |
 			       (1 << I830_OUTPUT_DVO_TMDS));
     
diff --git a/src/i830_display.c b/src/i830_display.c
index 16ef2cc..aba86ae 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -1054,6 +1054,14 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
 	((adjusted_mode->CrtcHSyncEnd - 1) << 16));
     OUTREG(vtot_reg, (adjusted_mode->CrtcVDisplay - 1) |
 	((adjusted_mode->CrtcVTotal - 1) << 16));
+    
+    /*
+     * Give us some border at the bottom for load detection
+     */
+    adjusted_mode->CrtcVBlankStart = adjusted_mode->CrtcVSyncStart;
+    if (adjusted_mode->CrtcVBlankEnd - adjusted_mode->CrtcVBlankStart < 3)
+	adjusted_mode->CrtcVBlankStart = adjusted_mode->CrtcVBlankEnd - 3;
+    
     OUTREG(vblank_reg, (adjusted_mode->CrtcVBlankStart - 1) |
 	((adjusted_mode->CrtcVBlankEnd - 1) << 16));
     OUTREG(vsync_reg, (adjusted_mode->CrtcVSyncStart - 1) |
@@ -1322,7 +1330,7 @@ i830GetLoadDetectPipe(xf86OutputPtr outp
 	return output->crtc;
 
     for (i = 0; i < xf86_config->num_crtc; i++)
-	if (!xf86CrtcInUse (xf86_config->crtc[i]))
+	if (output->possible_crtcs & (1 << i))
 	    break;
 
     if (i == xf86_config->num_crtc)
@@ -1344,9 +1352,10 @@ i830ReleaseLoadDetectPipe(xf86OutputPtr 
     
     if (intel_output->load_detect_temp) 
     {
-	output->crtc->enabled = FALSE;
+	xf86CrtcPtr crtc = output->crtc;
 	output->crtc = NULL;
 	intel_output->load_detect_temp = FALSE;
+	crtc->enabled = xf86CrtcInUse (crtc);
 	xf86DisableUnusedFunctions(pScrn);
     }
 }
diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index 2521ee3..cb461d7 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -462,13 +462,13 @@ i830_dvo_init(ScrnInfoPtr pScrn)
 					  "TMDS");
 		break;
 	    case I830_OUTPUT_DVO_LVDS:
-		intel_output->pipe_mask = (1 << 1);
+		intel_output->pipe_mask = ((1 << 0) | (1 << 1));
 		intel_output->clone_mask = (1 << I830_OUTPUT_DVO_LVDS);
 		output = xf86OutputCreate(pScrn, &i830_dvo_output_funcs,
 					  "LVDS");
 		break;
 	    case I830_OUTPUT_DVO_TVOUT:
-		intel_output->pipe_mask = (1 << 1);
+		intel_output->pipe_mask = ((1 << 0) | (1 << 1));
 		intel_output->clone_mask = (1 << I830_OUTPUT_DVO_TVOUT);
 		output = xf86OutputCreate(pScrn, &i830_dvo_output_funcs,
 					  "TV");
diff --git a/src/i830_tv.c b/src/i830_tv.c
index b95986f..1c818ba 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -1357,13 +1357,18 @@ i830_tv_detect(xf86OutputPtr output)
     crtc = i830GetLoadDetectPipe (output);
     if (crtc)
     {
-        if (intel_output->load_detect_temp)
+	if (!crtc->enabled)
         {
             /* 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);
         }
+	else if (intel_output->load_detect_temp)
+	{
+	    output->funcs->mode_set (output, &crtc->mode, &crtc->mode);
+	    output->funcs->commit (output);
+	}
         i830_tv_detect_type (crtc, output);
         i830ReleaseLoadDetectPipe (output);
     }
diff-tree 11862c2e1f23b77b56d7bd8b384579b5e3ae377b (from 6503eb45023d0db9a94cb9d1e14a26af07a6628d)
Author: Alan Coopersmith <alan.coopersmith at sun.com>
Date:   Thu Jun 28 23:31:28 2007 -0700

    Add *~ to .gitignore to skip emacs & patch backup files

diff --git a/.gitignore b/.gitignore
index 8109409..410a074 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,7 @@ Makefile.in
 *.la
 *.lo
 *.o
+*~
 aclocal.m4
 autom4te.cache
 compile
diff-tree 6503eb45023d0db9a94cb9d1e14a26af07a6628d (from 5257e36f502676fd6a44bbb8e747d9138ed3bc5c)
Author: Alan Coopersmith <alan.coopersmith at sun.com>
Date:   Thu Jun 28 23:30:35 2007 -0700

    Add AM_PROG_CC_C_O to configure.ac
    
    Clears automake-1.10 warning: src/bios_reader/Makefile.am:8: compiling
     `bios_dumper.c' with per-target flags requires `AM_PROG_CC_C_O' in
     `configure.ac'

diff --git a/configure.ac b/configure.ac
index 51203fe..a39635e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -48,6 +48,7 @@ AM_MAINTAINER_MODE
 AC_DISABLE_STATIC
 AC_PROG_LIBTOOL
 AC_PROG_CC
+AM_PROG_CC_C_O
 
 AC_CHECK_PROG(gen4asm, [intel-gen4asm], yes, no)
 AM_CONDITIONAL(HAVE_GEN4ASM, test x$gen4asm = xyes)
diff-tree 5257e36f502676fd6a44bbb8e747d9138ed3bc5c (from 16bfcb8042519f24b4494fd621814f39949ceeb6)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Jun 28 15:29:52 2007 -0700

    Handle dual-channel LVDS on i855.
    
    Just as with i9xx LVDS, the i855 LVDS can operate in dual-channel mode with
    a modified P2 divisor value (7 instead of 14). Just using the existing 9xx
    code for 855 appears to work fine.

diff --git a/src/i830_display.c b/src/i830_display.c
index f6e99be..16ef2cc 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -92,7 +92,7 @@ typedef struct {
 #define I8XX_P2_SLOW		      4
 #define I8XX_P2_FAST		      2
 #define I8XX_P2_LVDS_SLOW	      14
-#define I8XX_P2_LVDS_FAST	      14 /* No fast option */
+#define I8XX_P2_LVDS_FAST	      7
 #define I8XX_P2_SLOW_LIMIT	 165000
 
 #define I9XX_DOT_MIN		  20000
@@ -311,8 +311,7 @@ i830FindBestPLL(xf86CrtcPtr crtc, int ta
     const intel_limit_t   *limit = intel_limit (crtc);
     int err = target;
 
-    if (IS_I9XX(pI830) && i830PipeHasType(crtc, I830_OUTPUT_LVDS) &&
-	(INREG(LVDS) & LVDS_PORT_EN) != 0)
+    if (i830PipeHasType(crtc, I830_OUTPUT_LVDS))
     {
 	/* For LVDS, if the panel is on, just rely on its current settings for
 	 * dual-channel.  We haven't figured out how to reliably set up
@@ -1006,7 +1005,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
 	/* Set the B0-B3 data pairs corresponding to whether we're going to
 	 * set the DPLLs for dual-channel mode or not.
 	 */
-	if (clock.p2 == 7)
+	if (clock.p2 == I9XX_P2_LVDS_FAST)
 	    lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
 	else
 	    lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
diff-tree 16bfcb8042519f24b4494fd621814f39949ceeb6 (from 9675ccb30818bf831ac4c634751ab4bfe35f7bfe)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Jun 28 15:27:56 2007 -0700

    Decode PLL registers in LVDS mode a bit better in debug code.
    
    LVDS mode changes how the PLL works in fairly dramatic ways; the debug code
    wasn't properly accounting for those differences resulting in fairly bogus
    debug output.

diff --git a/src/i830_debug.c b/src/i830_debug.c
index bda263c..055ca93 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -571,39 +571,91 @@ void i830DumpRegs (ScrnInfoPtr pScrn)
     {
 	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_WARNING, "p2 out of range\n");
-	    break;
+	if (IS_I9XX(pI830)) 
+	{
+	    CARD32  lvds = INREG(LVDS);
+	    if ((lvds & LVDS_PORT_EN) &&
+		(lvds & LVDS_PIPEB_SELECT) == (pipe << 30))
+	    {
+		if ((lvds & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP)
+		    p2 = 7;
+		else
+		    p2 = 14;
+	    }
+	    else
+	    {
+		switch ((dpll >> 24) & 0x3) {
+		case 0:
+		    p2 = 10;
+		    break;
+		case 1:
+		    p2 = 5;
+		    break;
+		default:
+		    p2 = 1;
+		    xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "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_WARNING, "p1 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_WARNING, "p1 out of range\n");
-	    break;
+	else
+	{
+	    CARD32  lvds = INREG(LVDS);
+	    if (IS_I85X (pI830) && 
+		(lvds & LVDS_PORT_EN) &&
+		(lvds & LVDS_PIPEB_SELECT) == (pipe << 30))
+	    {
+		if ((lvds & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP)
+		    p2 = 7;
+		else
+		    p2 = 14;
+		switch ((dpll >> 16) & 0x3f) {
+		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;
+		default:
+		    p1 = 1;
+		    xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "LVDS P1 0x%x invalid encoding\n",
+				(dpll >> 16) & 0x3f);
+		    break;
+		}
+	    }
+	    else
+	    {
+		if (dpll & (1 << 23))
+		    p2 = 4;
+		else
+		    p2 = 2;
+		if (dpll & PLL_P1_DIVIDE_BY_TWO)
+		    p1 = 2;
+		else
+		    p1 = ((dpll >> 16) & 0x3f) + 2;
+	    }
 	}
 	switch ((dpll >> 13) & 0x3) {
 	case 0:
diff-tree 9675ccb30818bf831ac4c634751ab4bfe35f7bfe (from 7a2300c88ae59f5b7c3ce89d33147e3f0ca23c18)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Jun 27 09:23:33 2007 +0800

    EXA: fallback mask transform on i965
    
    It needs to fix shader programs which hasn't been done yet.

diff --git a/src/i965_render.c b/src/i965_render.c
index 2ab1a6b..744501a 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -429,6 +429,8 @@ i965_prepare_composite(int op, PicturePt
 	    rotation_program = TRUE;
     } else {
 	pI830->transform[1] = pMaskPicture->transform;
+	if (pI830->transform[1])
+	    I830FALLBACK("i965 mask transform not implemented!\n");
 	pI830->scale_units[1][0] = pMask->drawable.width;
 	pI830->scale_units[1][1] = pMask->drawable.height;
     }
diff-tree 7a2300c88ae59f5b7c3ce89d33147e3f0ca23c18 (from fff4a3b58fa18ee2ad91f998d190e90b77c051ab)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Jun 27 09:19:22 2007 +0800

    EXA: don't have to check offscreen size
    
    DDX will check it for EXA_OFFSCREEN_PIXMAPS flag

diff --git a/src/i830_exa.c b/src/i830_exa.c
index 22618dc..fed4067 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -400,7 +400,7 @@ I830EXAInit(ScreenPtr pScreen)
 	return FALSE;
     }
     memset(pI830->EXADriverPtr, 0, sizeof(*pI830->EXADriverPtr));
-    
+
     pI830->bufferOffset = 0;
     pI830->EXADriverPtr->exa_major = 2;
     pI830->EXADriverPtr->exa_minor = 1;
@@ -408,21 +408,14 @@ I830EXAInit(ScreenPtr pScreen)
     pI830->EXADriverPtr->offScreenBase = pI830->exa_offscreen->offset;
     pI830->EXADriverPtr->memorySize = pI830->exa_offscreen->offset +
 	pI830->exa_offscreen->size;
-	   
+    pI830->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS;
+
     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;
-    else {
-	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Not enough video RAM for "
-		   "offscreen memory manager. Xv disabled\n");
-	/* disable Xv here... */
-    }
 
     /* Limits are described in the BLT engine chapter under Graphics Data Size
      * Limitations, and the descriptions of SURFACE_STATE, 3DSTATE_BUFFER_INFO,
diff-tree fff4a3b58fa18ee2ad91f998d190e90b77c051ab (from 0a8a4afd3c59011d6b1f5b39aedfb9bce0e55c48)
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Jun 25 23:15:58 2007 -0700

    Use local structures for vs_state, sf_state, and wm_state

diff --git a/src/i965_render.c b/src/i965_render.c
index d79edd1..2ab1a6b 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -268,9 +268,9 @@ static struct brw_sampler_state *src_sam
 static struct brw_sampler_state *mask_sampler_state, mask_sampler_state_local;
 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_vs_unit_state *vs_state, vs_state_local;
+static struct brw_sf_unit_state *sf_state, sf_state_local;
+static struct brw_wm_unit_state *wm_state, wm_state_local;
 static struct brw_cc_unit_state *cc_state, cc_state_local;
 static struct brw_cc_viewport *cc_viewport;
 
@@ -530,9 +530,6 @@ i965_prepare_composite(int op, PicturePt
     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);
     sf_kernel = (void *)(state_base + sf_kernel_offset);
     ps_kernel = (void *)(state_base + ps_kernel_offset);
     sip_kernel = (void *)(state_base + sip_kernel_offset);
@@ -786,12 +783,16 @@ i965_prepare_composite(int op, PicturePt
     }
 
     /* Set up the vertex shader to be disabled (passthrough) */
+    vs_state = &vs_state_local;
     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;
 
+    vs_state = (void *)(state_base + vs_offset);
+    memcpy (vs_state, &vs_state_local, sizeof (vs_state_local));
+
     /* 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.
@@ -804,6 +805,7 @@ i965_prepare_composite(int op, PicturePt
     else
 	memcpy(sf_kernel, sf_kernel_static, sizeof (sf_kernel_static));
 
+    sf_state = &sf_state_local;
     memset(sf_state, 0, sizeof(*sf_state));
     sf_state->thread0.kernel_start_pointer =
 	(state_base_offset + sf_kernel_offset) >> 6;
@@ -835,6 +837,9 @@ i965_prepare_composite(int op, PicturePt
     sf_state->sf6.dest_org_vbias = 0x8;
     sf_state->sf6.dest_org_hbias = 0x8;
 
+    sf_state = (void *)(state_base + sf_offset);
+    memcpy (sf_state, &sf_state_local, sizeof (sf_state_local));
+
    /* Set up the PS kernel (dispatched by WM) */
     if (pMask) {
 	if (pMaskPicture->componentAlpha && 
@@ -856,6 +861,7 @@ i965_prepare_composite(int op, PicturePt
 	       sizeof (ps_kernel_static_nomask));
     }
 
+    wm_state = &wm_state_local;
     memset(wm_state, 0, sizeof (*wm_state));
     wm_state->thread0.kernel_start_pointer =
 	(state_base_offset + ps_kernel_offset) >> 6;
@@ -893,6 +899,9 @@ i965_prepare_composite(int op, PicturePt
     wm_state->wm5.enable_8_pix = 0;
     wm_state->wm5.early_depth_test = 1;
 
+    wm_state = (void *)(state_base + wm_offset);
+    memcpy (wm_state, &wm_state_local, sizeof (wm_state_local));
+
     /* Begin the long sequence of commands needed to set up the 3D
      * rendering pipe
      */
diff-tree 0a8a4afd3c59011d6b1f5b39aedfb9bce0e55c48 (from 499166a60fcbf16021bd9ec233790ba55803aa44)
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Jun 25 23:12:23 2007 -0700

    Use local structure for src_sampler_state and mask_sampler_state

diff --git a/src/i965_render.c b/src/i965_render.c
index 0882271..d79edd1 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -264,8 +264,8 @@ static int urb_cs_start, urb_cs_size;
 static struct brw_surface_state *dest_surf_state, dest_surf_state_local;
 static struct brw_surface_state *src_surf_state, src_surf_state_local;
 static struct brw_surface_state *mask_surf_state, mask_surf_state_local;
-static struct brw_sampler_state *src_sampler_state;
-static struct brw_sampler_state *mask_sampler_state;
+static struct brw_sampler_state *src_sampler_state, src_sampler_state_local;
+static struct brw_sampler_state *mask_sampler_state, mask_sampler_state_local;
 static struct brw_sampler_default_color *default_color_state;
 
 static struct brw_vs_unit_state *vs_state;
@@ -539,10 +539,6 @@ i965_prepare_composite(int op, PicturePt
 
     cc_viewport = (void *)(state_base + cc_viewport_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);
@@ -712,6 +708,7 @@ i965_prepare_composite(int op, PicturePt
    	binding_table[2] = state_base_offset + mask_surf_offset;
 
     /* PS kernel use this sampler */
+    src_sampler_state = &src_sampler_state_local;
     memset(src_sampler_state, 0, sizeof(*src_sampler_state));
     src_sampler_state->ss0.lod_preclamp = 1; /* GL mode */
     switch(pSrcPicture->filter) {
@@ -748,7 +745,11 @@ i965_prepare_composite(int op, PicturePt
     }
     src_sampler_state->ss3.chroma_key_enable = 0; /* disable chromakey */
 
+    src_sampler_state = (void *)(state_base + src_sampler_offset);
+    memcpy (src_sampler_state, &src_sampler_state_local, sizeof (src_sampler_state_local));
+
     if (pMask) {
+	mask_sampler_state = &mask_sampler_state_local;
    	memset(mask_sampler_state, 0, sizeof(*mask_sampler_state));
    	mask_sampler_state->ss0.lod_preclamp = 1; /* GL mode */
    	switch(pMaskPicture->filter) {
@@ -779,6 +780,9 @@ i965_prepare_composite(int op, PicturePt
    	    mask_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_WRAP;
     	}
    	mask_sampler_state->ss3.chroma_key_enable = 0; /* disable chromakey */
+
+	mask_sampler_state = (void *)(state_base + mask_sampler_offset);
+	memcpy (mask_sampler_state, &mask_sampler_state_local, sizeof (mask_sampler_state_local));
     }
 
     /* Set up the vertex shader to be disabled (passthrough) */
diff-tree 499166a60fcbf16021bd9ec233790ba55803aa44 (from a418ef7316808b239884a90c3fe890220bcc0242)
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Jun 25 23:09:17 2007 -0700

    Use local structure for mask_surf_state

diff --git a/src/i965_render.c b/src/i965_render.c
index eb74cd5..0882271 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -263,7 +263,7 @@ static int urb_cs_start, urb_cs_size;
 
 static struct brw_surface_state *dest_surf_state, dest_surf_state_local;
 static struct brw_surface_state *src_surf_state, src_surf_state_local;
-static struct brw_surface_state *mask_surf_state;
+static struct brw_surface_state *mask_surf_state, mask_surf_state_local;
 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;
@@ -539,9 +539,6 @@ i965_prepare_composite(int op, PicturePt
 
     cc_viewport = (void *)(state_base + cc_viewport_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);
@@ -681,6 +678,7 @@ i965_prepare_composite(int op, PicturePt
 
     /* setup mask surface */
     if (pMask) {
+	mask_surf_state = &mask_surf_state_local;
    	memset(mask_surf_state, 0, sizeof(*mask_surf_state));
 	mask_surf_state->ss0.surface_type = BRW_SURFACE_2D;
    	mask_surf_state->ss0.surface_format =
@@ -702,6 +700,9 @@ i965_prepare_composite(int op, PicturePt
    	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 = (void *)(state_base + mask_surf_offset);
+	memcpy (mask_surf_state, &mask_surf_state_local, sizeof (mask_surf_state_local));
     }
 
     /* Set up a binding table for our surfaces.  Only the PS will use it */
diff-tree a418ef7316808b239884a90c3fe890220bcc0242 (from 0e3c0b17826b7b5a21ee2c1d789b084fc167f1ed)
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Jun 25 23:07:19 2007 -0700

    Use local structure for src_surf_state

diff --git a/src/i965_render.c b/src/i965_render.c
index 09a4362..eb74cd5 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -262,7 +262,7 @@ static int urb_sf_start, urb_sf_size;
 static int urb_cs_start, urb_cs_size;
 
 static struct brw_surface_state *dest_surf_state, dest_surf_state_local;
-static struct brw_surface_state *src_surf_state;
+static struct brw_surface_state *src_surf_state, src_surf_state_local;
 static struct brw_surface_state *mask_surf_state;
 static struct brw_sampler_state *src_sampler_state;
 static struct brw_sampler_state *mask_sampler_state;
@@ -539,7 +539,6 @@ i965_prepare_composite(int op, PicturePt
 
     cc_viewport = (void *)(state_base + cc_viewport_offset);
 
-    src_surf_state = (void *)(state_base + src_surf_offset);
     if (pMask)
 	mask_surf_state = (void *)(state_base + mask_surf_offset);
 
@@ -655,6 +654,7 @@ i965_prepare_composite(int op, PicturePt
     memcpy (dest_surf_state, &dest_surf_state_local, sizeof (dest_surf_state_local));
 
     /* Set up the source surface state buffer */
+    src_surf_state = &src_surf_state_local;
     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);
@@ -676,6 +676,9 @@ i965_prepare_composite(int op, PicturePt
     src_surf_state->ss2.render_target_rotation = 0;
     src_surf_state->ss3.pitch = src_pitch - 1;
 
+    src_surf_state = (void *)(state_base + src_surf_offset);
+    memcpy (src_surf_state, &src_surf_state_local, sizeof (src_surf_state_local));
+
     /* setup mask surface */
     if (pMask) {
    	memset(mask_surf_state, 0, sizeof(*mask_surf_state));
diff-tree 0e3c0b17826b7b5a21ee2c1d789b084fc167f1ed (from 41a2c0f15446d59678461648f476fa71d40d44e0)
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Jun 25 23:05:50 2007 -0700

    Use local structure for dest_surf_state

diff --git a/src/i965_render.c b/src/i965_render.c
index 71953e7..09a4362 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -261,7 +261,7 @@ 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 *dest_surf_state, dest_surf_state_local;
 static struct brw_surface_state *src_surf_state;
 static struct brw_surface_state *mask_surf_state;
 static struct brw_sampler_state *src_sampler_state;
@@ -539,7 +539,6 @@ i965_prepare_composite(int op, PicturePt
 
     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);
@@ -628,6 +627,7 @@ i965_prepare_composite(int op, PicturePt
     memcpy (sip_kernel, sip_kernel_static, sizeof (sip_kernel_static));
 
     /* Set up the state buffer for the destination surface */
+    dest_surf_state = &dest_surf_state_local;
     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;
@@ -651,6 +651,9 @@ i965_prepare_composite(int op, PicturePt
     dest_surf_state->ss2.render_target_rotation = 0;
     dest_surf_state->ss3.pitch = dst_pitch - 1;
 
+    dest_surf_state = (void *)(state_base + dest_surf_offset);
+    memcpy (dest_surf_state, &dest_surf_state_local, sizeof (dest_surf_state_local));
+
     /* 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;
diff-tree 41a2c0f15446d59678461648f476fa71d40d44e0 (from 59f2150caca7eb374a2db43a472ba85f50d23274)
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Jun 25 23:03:47 2007 -0700

    Use local structure for cc_state

diff --git a/src/i965_render.c b/src/i965_render.c
index 347bca0..71953e7 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -271,7 +271,7 @@ static struct brw_sampler_default_color 
 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_unit_state *cc_state, cc_state_local;
 static struct brw_cc_viewport *cc_viewport;
 
 static struct brw_instruction *sf_kernel;
@@ -533,7 +533,6 @@ i965_prepare_composite(int op, PicturePt
     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);
@@ -594,6 +593,7 @@ i965_prepare_composite(int op, PicturePt
     cc_viewport->max_depth = 1.e35;
 
     /* Color calculator state */
+    cc_state = &cc_state_local;
     memset(cc_state, 0, sizeof(*cc_state));
     cc_state->cc0.stencil_enable = 0;   /* disable stencil */
     cc_state->cc2.depth_test = 0;       /* disable depth test */
@@ -621,6 +621,9 @@ i965_prepare_composite(int op, PicturePt
     cc_state->cc6.clamp_pre_alpha_blend = 1;
     cc_state->cc6.clamp_range = 0;  /* clamp range [0,1] */
 
+    cc_state = (void *)(state_base + cc_offset);
+    memcpy (cc_state, &cc_state_local, sizeof (cc_state_local));
+
     /* Upload system kernel */
     memcpy (sip_kernel, sip_kernel_static, sizeof (sip_kernel_static));
 
diff-tree 59f2150caca7eb374a2db43a472ba85f50d23274 (from 66aa0e61e1e8d2216a9c0555be5be004ed0a3192)
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Jun 25 11:28:57 2007 -0700

    Remove redundant i830WaitSync from i965_prepare_composite
    
    There were two calls to i830WaitSync, and between them no state was
    being changed---just offsets were being computed.

diff --git a/src/i965_render.c b/src/i965_render.c
index e69a939..347bca0 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -437,9 +437,6 @@ i965_prepare_composite(int op, PicturePt
 
     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);
diff-tree 66aa0e61e1e8d2216a9c0555be5be004ed0a3192 (from f8d7cbc6e1322acad3351591336cefcfba7d9aaf)
Author: Dave Mueller <dave.mueller at gmx.ch>
Date:   Fri Jun 22 16:45:27 2007 -0700

    Bug #11171: Add support for the Ti TFP410 DVO TMDS transmitter.

diff --git a/configure.ac b/configure.ac
index 66992fc..51203fe 100644
--- a/configure.ac
+++ b/configure.ac
@@ -230,5 +230,6 @@ AC_OUTPUT([
 	src/ivch/Makefile
 	src/reg_dumper/Makefile
 	src/sil164/Makefile
+	src/tfp410/Makefile
 	man/Makefile
 ])
diff --git a/src/Makefile.am b/src/Makefile.am
index 2b5799c..858ffd1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -22,7 +22,7 @@ if HAVE_PCIACCESS
 REGDUMPER = reg_dumper
 endif
 
-SUBDIRS = xvmc bios_reader ch7017 ch7xxx ivch sil164 $(REGDUMPER)
+SUBDIRS = xvmc bios_reader ch7017 ch7xxx ivch sil164 tfp410 $(REGDUMPER)
 
 # this is obnoxious:
 # -module lets us name the module exactly how we want
diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index 5666d26..2521ee3 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -36,11 +36,16 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #include "sil164/sil164.h"
 #include "ch7xxx/ch7xxx.h"
+#include "tfp410/tfp410.h"
 
 static const char *SIL164Symbols[] = {
     "Sil164VidOutput",
     NULL
 };
+static const char *TFP410Symbols[] = {
+    "Tfp410VidOutput",
+    NULL
+};
 static const char *CH7xxxSymbols[] = {
     "CH7xxxVidOutput",
     NULL
@@ -84,6 +89,14 @@ struct _I830DVODriver i830_dvo_drivers[]
 	.address = 0x04, /* Might also be 0x44, 0x84, 0xc4 */
 	.symbols = ivch_symbols
     },
+    {
+	.type = I830_OUTPUT_DVO_TMDS,
+	.modulename = "tfp410",
+	.fntablename = "TFP410VidOutput",
+	.dvo_reg = DVOC,
+	.address = (TFP410_ADDR_1<<1),
+	.symbols = TFP410Symbols
+    },
     /*
     { I830_OUTPUT_DVO_LVDS, "ch7017", "ch7017_methods",
       0xea, ch7017_symbols, NULL, NULL, NULL }
diff --git a/src/tfp410/Makefile.am b/src/tfp410/Makefile.am
new file mode 100644
index 0000000..89a27d0
--- /dev/null
+++ b/src/tfp410/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 = @WARN_CFLAGS@ @XMODES_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@
+
+tfp410_la_LTLIBRARIES = tfp410.la
+tfp410_la_LDFLAGS = -module -avoid-version
+tfp410_ladir = @moduledir@/drivers
+
+tfp410_la_SOURCES = \
+	tfp410.c \
+	tfp410_module.c \
+	tfp410.h \
+	tfp410_reg.h
diff --git a/src/tfp410/tfp410.c b/src/tfp410/tfp410.c
new file mode 100644
index 0000000..fecb64c
--- /dev/null
+++ b/src/tfp410/tfp410.c
@@ -0,0 +1,265 @@
+/* -*- c-basic-offset: 4 -*- */
+/*
+ * Copyright © 2007 Dave Mueller
+ *
+ * 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:
+ *    Dave Mueller <dave.mueller at gmx.ch>
+ *
+ */
+
+#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 "xf86Crtc.h"
+#define DPMS_SERVER
+#include <X11/extensions/dpms.h>
+
+#include "../i2c_vid.h"
+#include "tfp410.h"
+#include "tfp410_reg.h"
+
+static Bool
+tfp410ReadByte(TFP410Ptr tfp, int addr, CARD8 *ch)
+{
+    if (!xf86I2CReadByte(&(tfp->d), addr, ch)) {
+	xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_ERROR,
+		   "Unable to read from %s Slave %d.\n",
+		   tfp->d.pI2CBus->BusName, tfp->d.SlaveAddr);
+	return FALSE;
+    }
+    return TRUE;
+}
+
+static Bool
+tfp410WriteByte(TFP410Ptr tfp, int addr, CARD8 ch)
+{
+    if (!xf86I2CWriteByte(&(tfp->d), addr, ch)) {
+	xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_ERROR,
+		   "Unable to write to %s Slave %d.\n",
+		   tfp->d.pI2CBus->BusName, tfp->d.SlaveAddr);
+	return FALSE;
+    }
+    return TRUE;
+}
+
+static int
+tfp410GetID(TFP410Ptr tfp, int addr)
+{
+    unsigned char ch1, ch2;
+
+    if (tfp410ReadByte(tfp, addr+0, &ch1) &&
+        tfp410ReadByte(tfp, addr+1, &ch2)) {
+
+	return ((ch2<<8) & 0xFF00) | (ch1 & 0x00FF);
+    }
+    return -1;
+}
+
+/* Ti TFP410 driver for chip on i2c bus */
+static void *
+tfp410_init(I2CBusPtr b, I2CSlaveAddr addr)
+{
+    /* this will detect the tfp410 chip on the specified i2c bus */
+    TFP410Ptr tfp;
+    int id;
+
+    xf86DrvMsg(b->scrnIndex, X_INFO, "detecting tfp410\n");
+
+    tfp = xcalloc(1, sizeof(TFP410Rec));
+    if (tfp == NULL)
+	return NULL;
+
+    tfp->d.DevName = "TFP410 TMDS Controller";
+    tfp->d.SlaveAddr = addr;
+    tfp->d.pI2CBus = b;
+    tfp->d.StartTimeout = b->StartTimeout;
+    tfp->d.BitTimeout = b->BitTimeout;
+    tfp->d.AcknTimeout = b->AcknTimeout;
+    tfp->d.ByteTimeout = b->ByteTimeout;
+    tfp->d.DriverPrivate.ptr = tfp;
+
+    if ((id = tfp410GetID(tfp, TFP410_VID_LO)) != TFP410_VID) {
+	xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_ERROR,
+		   "tfp410 not detected got VID %X: from %s Slave %d.\n",
+		   id, tfp->d.pI2CBus->BusName, tfp->d.SlaveAddr);
+	goto out;
+    }
+
+    if ((id = tfp410GetID(tfp, TFP410_DID_LO)) != TFP410_DID) {
+	xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_ERROR,
+		   "tfp410 not detected got DID %X: from %s Slave %d.\n",
+		   id, tfp->d.pI2CBus->BusName, tfp->d.SlaveAddr);
+	goto out;
+    }
+
+    if (!xf86I2CDevInit(&(tfp->d))) {
+	goto out;
+    }
+
+    return tfp;
+
+out:
+    xfree(tfp);
+    return NULL;
+}
+
+static xf86OutputStatus
+tfp410_detect(I2CDevPtr d)
+{
+    TFP410Ptr tfp = TFPPTR(d);
+    xf86OutputStatus ret = XF86OutputStatusDisconnected;
+    unsigned char ctl2;
+
+    if (tfp410ReadByte(tfp, TFP410_CTL_2, &ctl2)) {
+	if (ctl2 & TFP410_CTL_2_HTPLG)
+	    ret = XF86OutputStatusConnected;
+	else
+	    ret = XF86OutputStatusDisconnected;
+    }
+
+    return ret;
+}
+
+static ModeStatus
+tfp410_mode_valid(I2CDevPtr d, DisplayModePtr mode)
+{
+    return MODE_OK;
+}
+
+static void
+tfp410_mode_set(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode)
+{
+    /* 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.
+     */
+    /* don't do much */
+    return;
+}
+
+/* set the tfp410 power state */
+static void
+tfp410_dpms(I2CDevPtr d, int mode)
+{
+    TFP410Ptr tfp = TFPPTR(d);
+    unsigned char ctl1;
+
+    if (!tfp410ReadByte(tfp, TFP410_CTL_1, &ctl1))
+	return;
+
+    if (mode == DPMSModeOn)
+	ctl1 |= TFP410_CTL_1_PD;
+    else
+	ctl1 &= ~TFP410_CTL_1_PD;
+
+    tfp410WriteByte(tfp, TFP410_CTL_1, ctl1);
+}
+
+static void
+tfp410_dump_regs(I2CDevPtr d)
+{
+    TFP410Ptr tfp = TFPPTR(d);
+    CARD8 val, val2;
+
+    tfp410ReadByte(tfp, TFP410_REV, &val);
+    xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO,
+	       "TFP410_REV: 0x%02X\n", val);
+    tfp410ReadByte(tfp, TFP410_CTL_1, &val);
+    xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO,
+	       "TFP410_CTL1: 0x%02X\n", val);
+    tfp410ReadByte(tfp, TFP410_CTL_2, &val);
+    xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO,
+	       "TFP410_CTL2: 0x%02X\n", val);
+    tfp410ReadByte(tfp, TFP410_CTL_3, &val);
+    xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO,
+	       "TFP410_CTL3: 0x%02X\n", val);
+    tfp410ReadByte(tfp, TFP410_USERCFG, &val);
+    xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO,
+	       "TFP410_USERCFG: 0x%02X\n", val);
+    tfp410ReadByte(tfp, TFP410_DE_DLY, &val);
+    xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO,
+	       "TFP410_DE_DLY: 0x%02X\n", val);
+    tfp410ReadByte(tfp, TFP410_DE_CTL, &val);
+    xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO,
+	       "TFP410_DE_CTL: 0x%02X\n", val);
+    tfp410ReadByte(tfp, TFP410_DE_TOP, &val);
+    xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO,
+	       "TFP410_DE_TOP: 0x%02X\n", val);
+    tfp410ReadByte(tfp, TFP410_DE_CNT_LO, &val);
+    tfp410ReadByte(tfp, TFP410_DE_CNT_HI, &val2);
+    xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO,
+	       "TFP410_DE_CNT: 0x%02X%02X\n", val2, val);
+    tfp410ReadByte(tfp, TFP410_DE_LIN_LO, &val);
+    tfp410ReadByte(tfp, TFP410_DE_LIN_HI, &val2);
+    xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO,
+	       "TFP410_DE_LIN: 0x%02X%02X\n", val2, val);
+    tfp410ReadByte(tfp, TFP410_H_RES_LO, &val);
+    tfp410ReadByte(tfp, TFP410_H_RES_HI, &val2);
+    xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO,
+	       "TFP410_H_RES: 0x%02X%02X\n", val2, val);
+    tfp410ReadByte(tfp, TFP410_V_RES_LO, &val);
+    tfp410ReadByte(tfp, TFP410_V_RES_HI, &val2);
+    xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO,
+	       "TFP410_V_RES: 0x%02X%02X\n", val2, val);
+}
+
+static void
+tfp410_save(I2CDevPtr d)
+{
+    TFP410Ptr tfp = TFPPTR(d);
+
+    if (!tfp410ReadByte(tfp, TFP410_CTL_1, &tfp->SavedReg.ctl1))
+	return;
+
+    if (!tfp410ReadByte(tfp, TFP410_CTL_2, &tfp->SavedReg.ctl2))
+	return;
+}
+
+static void
+tfp410_restore(I2CDevPtr d)
+{
+    TFP410Ptr tfp = TFPPTR(d);
+
+    /* Restore it powered down initially */
+    tfp410WriteByte(tfp, TFP410_CTL_1, tfp->SavedReg.ctl1 & ~0x1);
+
+    tfp410WriteByte(tfp, TFP410_CTL_2, tfp->SavedReg.ctl2);
+    tfp410WriteByte(tfp, TFP410_CTL_1, tfp->SavedReg.ctl1);
+}
+
+I830I2CVidOutputRec TFP410VidOutput = {
+    .init = tfp410_init,
+    .detect = tfp410_detect,
+    .mode_valid = tfp410_mode_valid,
+    .mode_set = tfp410_mode_set,
+    .dpms = tfp410_dpms,
+    .dump_regs = tfp410_dump_regs,
+    .save = tfp410_save,
+    .restore = tfp410_restore,
+};
diff --git a/src/tfp410/tfp410.h b/src/tfp410/tfp410.h
new file mode 100644
index 0000000..fb3f452
--- /dev/null
+++ b/src/tfp410/tfp410.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright © 2007 Dave Mueller
+ *
+ * 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:
+ *    Dave Mueller <dave.mueller at gmx.ch>
+ *
+ */
+
+#ifndef TFP410_H
+#define TFP410_H
+
+#define TFP410_ADDR_1 0x38
+
+#endif
diff --git a/src/tfp410/tfp410_module.c b/src/tfp410/tfp410_module.c
new file mode 100644
index 0000000..c05b21a
--- /dev/null
+++ b/src/tfp410/tfp410_module.c
@@ -0,0 +1,38 @@
+/* -*- c-basic-offset: 4 -*- */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86Module.h"
+
+static MODULESETUPPROTO(tfp410Setup);
+
+static XF86ModuleVersionInfo tfp410VersRec = {
+    "tfp410",
+    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 tfp410ModuleData = {
+    &tfp410VersRec,
+    tfp410Setup,
+    NULL
+};
+
+static pointer
+tfp410Setup(pointer module, pointer opts, int *errmaj, int *errmin)
+{
+    return (pointer)1;
+}
diff --git a/src/tfp410/tfp410_reg.h b/src/tfp410/tfp410_reg.h
new file mode 100644
index 0000000..45afa9b
--- /dev/null
+++ b/src/tfp410/tfp410_reg.h
@@ -0,0 +1,104 @@
+/* -*- c-basic-offset: 4 -*- */
+/*
+ * Copyright © 2007 Dave Mueller
+ *
+ * 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:
+ *    Dave Mueller <dave.mueller at gmx.ch>
+ *
+ */
+
+#ifndef TFP410_REG_H
+#define TFP410_REG_H
+
+/* register definitions according to the TFP410 data sheet */
+#define TFP410_VID 0x014C
+#define TFP410_DID 0x0410
+
+#define TFP410_VID_LO 0x00
+#define TFP410_VID_HI 0x01
+#define TFP410_DID_LO 0x02
+#define TFP410_DID_HI 0x03
+#define TFP410_REV    0x04
+
+#define TFP410_CTL_1 0x08
+#define TFP410_CTL_1_TDIS (1<<6)
+#define TFP410_CTL_1_VEN (1<<5)
+#define TFP410_CTL_1_HEN (1<<4)
+#define TFP410_CTL_1_DSEL (1<<3)
+#define TFP410_CTL_1_BSEL (1<<2)
+#define TFP410_CTL_1_EDGE (1<<1)
+#define TFP410_CTL_1_PD   (1<<0)
+
+#define TFP410_CTL_2 0x09
+#define TFP410_CTL_2_VLOW (1<<7)
+#define TFP410_CTL_2_MSEL_MASK (0x7<<4)
+#define TFP410_CTL_2_MSEL (1<<4)
+#define TFP410_CTL_2_TSEL (1<<3)
+#define TFP410_CTL_2_RSEN (1<<2)
+#define TFP410_CTL_2_HTPLG (1<<1)
+#define TFP410_CTL_2_MDI (1<<0)
+
+#define TFP410_CTL_3 0x0A
+#define TFP410_CTL_3_DK_MASK (0x7<<5)
+#define TFP410_CTL_3_DK (1<<5)
+#define TFP410_CTL_3_DKEN (1<<4)
+#define TFP410_CTL_3_CTL_MASK (0x7<<1)
+#define TFP410_CTL_3_CTL (1<<1)
+
+#define TFP410_USERCFG 0x0B
+
+#define TFP410_DE_DLY 0x32
+
+#define TFP410_DE_CTL 0x33
+#define TFP410_DE_CTL_DEGEN (1<<6)
+#define TFP410_DE_CTL_VSPOL (1<<5)
+#define TFP410_DE_CTL_HSPOL (1<<4)
+#define TFP410_DE_CTL_DEDLY8 (1<<0)
+
+#define TFP410_DE_TOP 0x34
+
+#define TFP410_DE_CNT_LO 0x36
+#define TFP410_DE_CNT_HI 0x37
+
+#define TFP410_DE_LIN_LO 0x38
+#define TFP410_DE_LIN_HI 0x39
+
+#define TFP410_H_RES_LO 0x3A
+#define TFP410_H_RES_HI 0x3B
+
+#define TFP410_V_RES_LO 0x3C
+#define TFP410_V_RES_HI 0x3D
+
+typedef struct _TFP410SaveRec {
+    CARD8 ctl1;
+    CARD8 ctl2;
+} TFP410SaveRec;
+
+typedef struct {
+    I2CDevRec d;
+    TFP410SaveRec SavedReg;
+    TFP410SaveRec ModeReg;
+} TFP410Rec, *TFP410Ptr;
+
+#define TFPPTR(d) ((TFP410Ptr)(d->DriverPrivate.ptr))
+
+#endif
diff-tree f8d7cbc6e1322acad3351591336cefcfba7d9aaf (from ec236c76b93aea5f2ee1e8b8509cde4625974fcb)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Jun 22 16:29:21 2007 -0700

    Move the ivch's fixed panel mode support to i830_dvo.c for other LVDS drivers.
    
    This also results in removal of the setup hook, which was being called
    unconditionally and breaking non-ivch dvo drivers.

diff --git a/src/i2c_vid.h b/src/i2c_vid.h
index 1a21fca..6c4e95d 100644
--- a/src/i2c_vid.h
+++ b/src/i2c_vid.h
@@ -30,12 +30,6 @@ typedef struct _I830I2CVidOutputRec {
      * Returns NULL if the device does not exist.
      */
     void *(*init)(I2CBusPtr b, I2CSlaveAddr addr);
-    
-    /**
-     * Setup the device for use, after the relevant output has been created
-     */
-    Bool
-    (*setup) (I2CDevPtr d, xf86OutputPtr output);
 
     /**
      * Called to allow the output a chance to create properties after the
diff --git a/src/i830.h b/src/i830.h
index 8947524..9dda33a 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -209,6 +209,8 @@ struct _I830DVODriver {
    I830I2CVidOutputRec *vid_rec;
    void *dev_priv;
    pointer modhandle;
+   DisplayModePtr panel_fixed_mode;
+   Bool panel_wants_dither;
 };
 
 extern const char *i830_output_type_names[];
diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index dfd39ff..5666d26 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -60,20 +60,30 @@ static const char *ch7017_symbols[] = {
 /* driver list */
 struct _I830DVODriver i830_dvo_drivers[] =
 {
-    {I830_OUTPUT_DVO_TMDS, "sil164", "SIL164VidOutput", DVOC,
-     (SIL164_ADDR_1<<1), SIL164Symbols, NULL , NULL, NULL},
-    {I830_OUTPUT_DVO_TMDS | I830_OUTPUT_DVO_TVOUT, "ch7xxx", "CH7xxxVidOutput", DVOC,
-     (CH7xxx_ADDR_1<<1), CH7xxxSymbols, NULL , NULL, NULL},
-    {I830_OUTPUT_DVO_LVDS, "ivch", "ivch_methods", DVOA,
-     0x04, ivch_symbols, NULL, NULL, NULL},
-    /*
-    {I830_OUTPUT_DVO_LVDS, "ivch", "ivch_methods",
-     0x44, ivch_symbols, NULL, NULL, NULL},
-    {I830_OUTPUT_DVO_LVDS, "ivch", "ivch_methods",
-     0x84, ivch_symbols, NULL, NULL, NULL},
-    {I830_OUTPUT_DVO_LVDS, "ivch", "ivch_methods",
-     0xc4, ivch_symbols, NULL, NULL, NULL},
-    */
+    {
+	.type = I830_OUTPUT_DVO_TMDS,
+	.modulename = "sil164",
+	.fntablename = "SIL164VidOutput",
+	.dvo_reg = DVOC,
+	.address = (SIL164_ADDR_1<<1),
+	.symbols = SIL164Symbols
+    },
+    {
+	.type = I830_OUTPUT_DVO_TMDS,
+	.modulename = "ch7xxx",
+	.fntablename = "CH7xxxVidOutput",
+	.dvo_reg = DVOC,
+	.address = (CH7xxx_ADDR_1<<1),
+	.symbols = CH7xxxSymbols
+    },
+    {
+	.type = I830_OUTPUT_DVO_LVDS,
+	.modulename = "ivch",
+	.fntablename = "ivch_methods",
+	.dvo_reg = DVOA,
+	.address = 0x04, /* Might also be 0x44, 0x84, 0xc4 */
+	.symbols = ivch_symbols
+    },
     /*
     { I830_OUTPUT_DVO_LVDS, "ch7017", "ch7017_methods",
       0xea, ch7017_symbols, NULL, NULL, NULL }
@@ -140,6 +150,7 @@ static int
 i830_dvo_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
 {
     I830OutputPrivatePtr    intel_output = output->driver_private;
+    struct _I830DVODriver   *drv = intel_output->i2c_drv;
     void		    *dev_priv = intel_output->i2c_drv->dev_priv;
 
     if (pMode->Flags & V_DBLSCAN)
@@ -147,6 +158,13 @@ i830_dvo_mode_valid(xf86OutputPtr output
 
     /* XXX: Validate clock range */
 
+    if (drv->panel_fixed_mode) {
+	if (pMode->HDisplay > drv->panel_fixed_mode->HDisplay)
+	    return MODE_PANEL;
+	if (pMode->VDisplay > drv->panel_fixed_mode->VDisplay)
+	    return MODE_PANEL;
+    }
+
     return intel_output->i2c_drv->vid_rec->mode_valid(dev_priv, pMode);
 }
 
@@ -155,6 +173,25 @@ i830_dvo_mode_fixup(xf86OutputPtr output
 		    DisplayModePtr adjusted_mode)
 {
     I830OutputPrivatePtr    intel_output = output->driver_private;
+    struct _I830DVODriver   *drv = intel_output->i2c_drv;
+
+    /* 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 (drv->panel_fixed_mode != NULL) {
+	adjusted_mode->HDisplay = drv->panel_fixed_mode->HDisplay;
+	adjusted_mode->HSyncStart = drv->panel_fixed_mode->HSyncStart;
+	adjusted_mode->HSyncEnd = drv->panel_fixed_mode->HSyncEnd;
+	adjusted_mode->HTotal = drv->panel_fixed_mode->HTotal;
+	adjusted_mode->VDisplay = drv->panel_fixed_mode->VDisplay;
+	adjusted_mode->VSyncStart = drv->panel_fixed_mode->VSyncStart;
+	adjusted_mode->VSyncEnd = drv->panel_fixed_mode->VSyncEnd;
+	adjusted_mode->VTotal = drv->panel_fixed_mode->VTotal;
+	adjusted_mode->Clock = drv->panel_fixed_mode->Clock;
+	xf86SetModeCrtc(adjusted_mode, INTERLACE_HALVE_V);
+    }
 
     if (intel_output->i2c_drv->vid_rec->mode_fixup)
 	return intel_output->i2c_drv->vid_rec->mode_fixup (intel_output->i2c_drv->dev_priv,
@@ -235,6 +272,7 @@ static DisplayModePtr
 i830_dvo_get_modes(xf86OutputPtr output)
 {
     I830OutputPrivatePtr    intel_output = output->driver_private;
+    struct _I830DVODriver   *drv = intel_output->i2c_drv;
     DisplayModePtr	    modes;
 
     /* We should probably have an i2c driver get_modes function for those
@@ -253,6 +291,9 @@ i830_dvo_get_modes(xf86OutputPtr output)
 	    return modes;
     }
 
+    if (drv->panel_fixed_mode != NULL)
+	return xf86DuplicateMode(drv->panel_fixed_mode);
+
     return NULL;
 }
 
@@ -436,7 +477,19 @@ i830_dvo_init(ScrnInfoPtr pScrn)
 	    drv->dev_priv = ret_ptr;
 	    intel_output->i2c_drv = drv;
 	    intel_output->pI2CBus = pI2CBus;
-	    drv->vid_rec->setup (drv->dev_priv, output);
+
+	    if (intel_output->type == I830_OUTPUT_DVO_LVDS) {
+		/* For our LVDS chipsets, we should hopefully be able to
+		 * dig the fixed panel mode out of the BIOS data.  However,
+		 * it's in a different format from the BIOS data on chipsets
+		 * with integrated LVDS (stored in AIM headers, liekly),
+		 * so for now, just get the current mode being output through
+		 * DVO.
+		 */
+		drv->panel_fixed_mode = i830_dvo_get_current_mode(output);
+		drv->panel_wants_dither = TRUE;
+	    }
+
 	    return;
 	}
 	xf86UnloadSubModule(drv->modhandle);
diff --git a/src/ivch/ivch.c b/src/ivch/ivch.c
index eac878e..bd11dd4 100644
--- a/src/ivch/ivch.c
+++ b/src/ivch/ivch.c
@@ -49,9 +49,6 @@ struct ivch_priv {
 
     xf86OutputPtr   output;
 
-    DisplayModePtr  panel_fixed_mode;
-    Bool	    panel_wants_dither;
-
     CARD16    	    width;
     CARD16    	    height;
 
@@ -189,6 +186,9 @@ ivch_init(I2CBusPtr b, I2CSlaveAddr addr
 	goto out;
     }
 
+    ivch_read(priv, VR20, &priv->width);
+    ivch_read(priv, VR21, &priv->height);
+
     return priv;
 
 out:
@@ -196,60 +196,18 @@ out:
     return NULL;
 }
 
-/** Gets the panel mode */
-static Bool
-ivch_setup (I2CDevPtr d, xf86OutputPtr output)
-{
-    struct ivch_priv	*priv = d->DriverPrivate.ptr;
-
-    priv->output = output;
-    ivch_read (priv, VR20, &priv->width);
-    ivch_read (priv, VR21, &priv->height);
-    
-    priv->panel_fixed_mode = i830_bios_get_panel_mode (output->scrn, &priv->panel_wants_dither);
-    if (!priv->panel_fixed_mode)
-    {
-	priv->panel_fixed_mode = i830_dvo_get_current_mode (output);
-	priv->panel_wants_dither = TRUE;
-    }
-
-    return TRUE;
-}
-
 static xf86OutputStatus
 ivch_detect(I2CDevPtr d)
 {
     return XF86OutputStatusConnected;
 }
 
-static DisplayModePtr
-ivch_get_modes (I2CDevPtr d)
-{
-    struct ivch_priv	*priv = d->DriverPrivate.ptr;
-
-    if (priv->panel_fixed_mode)
-	return xf86DuplicateMode (priv->panel_fixed_mode);
-
-    return NULL;
-}
-
 static ModeStatus
 ivch_mode_valid(I2CDevPtr d, DisplayModePtr mode)
 {
-    struct ivch_priv	*priv = d->DriverPrivate.ptr;
-    DisplayModePtr	panel_fixed_mode = priv->panel_fixed_mode;
-    
     if (mode->Clock > 112000)
 	return MODE_CLOCK_HIGH;
 
-    if (panel_fixed_mode)
-    {
-	if (mode->HDisplay > panel_fixed_mode->HDisplay)
-	    return MODE_PANEL;
-	if (mode->VDisplay > panel_fixed_mode->VDisplay)
-	    return MODE_PANEL;
-    }
-    
     return MODE_OK;
 }
 
@@ -291,33 +249,6 @@ ivch_dpms(I2CDevPtr d, int mode)
     usleep (16 * 1000);
 }
 
-static Bool
-ivch_mode_fixup(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode)
-{
-    struct ivch_priv	*priv = d->DriverPrivate.ptr;
-    DisplayModePtr	panel_fixed_mode = priv->panel_fixed_mode;
-    
-    /* 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 (panel_fixed_mode != NULL) {
-	adjusted_mode->HDisplay = panel_fixed_mode->HDisplay;
-	adjusted_mode->HSyncStart = panel_fixed_mode->HSyncStart;
-	adjusted_mode->HSyncEnd = panel_fixed_mode->HSyncEnd;
-	adjusted_mode->HTotal = panel_fixed_mode->HTotal;
-	adjusted_mode->VDisplay = panel_fixed_mode->VDisplay;
-	adjusted_mode->VSyncStart = panel_fixed_mode->VSyncStart;
-	adjusted_mode->VSyncEnd = panel_fixed_mode->VSyncEnd;
-	adjusted_mode->VTotal = panel_fixed_mode->VTotal;
-	adjusted_mode->Clock = panel_fixed_mode->Clock;
-	xf86SetModeCrtc(adjusted_mode, INTERLACE_HALVE_V);
-    }
-
-    return TRUE;
-}
-    
 static void
 ivch_mode_set(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode)
 {
@@ -420,14 +351,11 @@ ivch_restore(I2CDevPtr d)
 
 I830I2CVidOutputRec ivch_methods = {
     .init = ivch_init,
-    .setup = ivch_setup,
     .dpms = ivch_dpms,
     .save = ivch_save,
     .restore = ivch_restore,
     .mode_valid = ivch_mode_valid,
-    .mode_fixup = ivch_mode_fixup,
     .mode_set = ivch_mode_set,
     .detect = ivch_detect,
-    .get_modes = ivch_get_modes,
     .dump_regs = ivch_dump_regs,
 };
diff-tree ec236c76b93aea5f2ee1e8b8509cde4625974fcb (from d957c6b8e1dde8e11c1db3431e0ff58c5d984880)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Fri Jun 22 16:32:46 2007 +0100

    I830 needs to have plane/pipe/pll started in mode_set.
    
    The patch for the i855 to stop enabling plane/pipe/pll in mode_set broke the
    i830. Revert that just for the i830, leaving it enabled for the i855.

diff --git a/src/i830_display.c b/src/i830_display.c
index 1f0f5b8..f6e99be 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -963,7 +963,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
      * will be run after the mode is set. On 9xx, it helps.
      * On 855, it can lock up the chip (and the entire machine)
      */
-    if (IS_I9XX (pI830))
+    if (!IS_I85X (pI830))
     {
 	dspcntr |= DISPLAY_PLANE_ENABLE;
 	pipeconf |= PIPEACONF_ENABLE;
diff-tree d957c6b8e1dde8e11c1db3431e0ff58c5d984880 (from a67c2965385001bcb8987265f698ff0f5809cd11)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Fri Jun 22 01:32:02 2007 +0100

    Increase vblank wait timeout from 20ms to 30ms. 49.6Hz < 20ms.
    
    The x40 LVDS mode has a 49.6Hz vertical refresh. Waiting for only 20ms can
    sometimes cause the driver to start programming the hardware before the
    vblank has occurred, which will lock up the i855 chipset. Extend this to
    30ms (the maximum timeout used by the BIOS) to ensure this doesn't happen.
    
    Detecting actual vblank occurance using the various status registers should
    also be possible but isn't yet working.

diff --git a/src/i830_display.c b/src/i830_display.c
index 2df1fcc..1f0f5b8 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -362,7 +362,7 @@ void
 i830WaitForVblank(ScrnInfoPtr pScreen)
 {
     /* Wait for 20ms, i.e. one cycle at 50hz. */
-    usleep(20000);
+    usleep(30000);
 }
 
 void
diff-tree a67c2965385001bcb8987265f698ff0f5809cd11 (from d6e46f67ab3af1ad3bfa72acb0efd9fe79dbf1dc)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Jun 21 23:59:38 2007 +0100

    Follow BIOS configuration for Legacy Backlight Brightness.
    
    The backlight control in the LVDS controller can either operate in 'normal'
    mode or 'legacy' mode. In legacy mode, it uses the PCI config space register
    0xf4 which can range from 0 to 0xff. In normal mode, it reads the range and
    current value from the BLC_PWM_CTL register.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index 6001297..248df04 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -1056,6 +1056,14 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define RENCLK_GATE_D2		0x6208
 #define RAMCLK_GATE_D		0x6210		/* CRL only */
 
+/*
+ * This is a PCI config space register to manipulate backlight brightness
+ * It is used when the BLM_LEGACY_MODE is turned on. When enabled, the first
+ * byte of this config register sets brightness within the range from
+ * 0 to 0xff
+ */
+#define LEGACY_BACKLIGHT_BRIGHTNESS 0xf4
+
 #define BLC_PWM_CTL		0x61254
 #define BACKLIGHT_MODULATION_FREQ_SHIFT		(17)
 /**
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index ee278aa..d469815 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -59,8 +59,18 @@ i830_lvds_set_backlight(xf86OutputPtr ou
     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));
+    blc_pwm_ctl = INREG(BLC_PWM_CTL);
+    if (blc_pwm_ctl & BLM_LEGACY_MODE)
+    {
+	pciWriteByte (pI830->PciTag, 
+		      LEGACY_BACKLIGHT_BRIGHTNESS,
+		      level & 0xff);
+    }
+    else
+    {
+	blc_pwm_ctl &= ~BACKLIGHT_DUTY_CYCLE_MASK;
+	OUTREG(BLC_PWM_CTL, blc_pwm_ctl | (level << BACKLIGHT_DUTY_CYCLE_SHIFT));
+    }
 }
 
 /**
@@ -71,9 +81,13 @@ i830_lvds_get_max_backlight(xf86OutputPt
 {
     ScrnInfoPtr pScrn = output->scrn;
     I830Ptr	pI830 = I830PTR(pScrn);
+    CARD32	pwm_ctl = INREG(BLC_PWM_CTL);
     
-    return ((INREG(BLC_PWM_CTL) & BACKLIGHT_MODULATION_FREQ_MASK) >>
-	BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
+    if (pwm_ctl & BLM_LEGACY_MODE)
+	return 0xff;
+    else
+	return ((pwm_ctl & BACKLIGHT_MODULATION_FREQ_MASK) >>
+		BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
 }
 
 /**
@@ -129,8 +143,16 @@ i830_lvds_save (xf86OutputPtr output)
     pI830->savePP_CONTROL = INREG(PP_CONTROL);
     pI830->savePP_CYCLE = INREG(PP_CYCLE);
     pI830->saveBLC_PWM_CTL = INREG(BLC_PWM_CTL);
-    dev_priv->backlight_duty_cycle = (pI830->saveBLC_PWM_CTL &
-				      BACKLIGHT_DUTY_CYCLE_MASK);
+    if (pI830->saveBLC_PWM_CTL & BLM_LEGACY_MODE)
+    {
+	dev_priv->backlight_duty_cycle = pciReadByte (pI830->PciTag,
+						      LEGACY_BACKLIGHT_BRIGHTNESS);
+    }
+    else
+    {
+	dev_priv->backlight_duty_cycle = (pI830->saveBLC_PWM_CTL &
+					  BACKLIGHT_DUTY_CYCLE_MASK);
+    }
 
     /*
      * If the light is off at server startup, just make it full brightness
diff-tree d6e46f67ab3af1ad3bfa72acb0efd9fe79dbf1dc (from 9d104634cf03bea82d1467f01e577cb8d2e4b554)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Jun 21 20:16:36 2007 +0100

    Eliminate some uninitialized variable warnings

diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index d81e5dd..dfd39ff 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -179,6 +179,7 @@ i830_dvo_mode_set(xf86OutputPtr output, 
 
     switch (dvo_reg) {
     case DVOA:
+    default:
 	dvo_srcdim_reg = DVOA_SRCDIM;
 	break;
     case DVOB:
diff --git a/src/i830_video.c b/src/i830_video.c
index 43e25bb..b4f9e74 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -1702,6 +1702,10 @@ i830_covering_crtc (ScrnInfoPtr pScrn,
 
     best_crtc = NULL;
     best_coverage = 0;
+    crtc_box_ret->x1 = 0;
+    crtc_box_ret->x2 = 0;
+    crtc_box_ret->y1 = 0;
+    crtc_box_ret->y2 = 0;
     for (c = 0; c < xf86_config->num_crtc; c++)
     {
 	crtc = xf86_config->crtc[c];
diff-tree 9d104634cf03bea82d1467f01e577cb8d2e4b554 (from 3bbf313ba541526a893915f8b6c64b1eccf325e0)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Jun 21 01:15:39 2007 +0100

    Add 3DSTATE_CLEAR_PARAMETERS bits

diff --git a/src/i915_reg.h b/src/i915_reg.h
index 6b40d70..682a157 100644
--- a/src/i915_reg.h
+++ b/src/i915_reg.h
@@ -109,6 +109,13 @@
 /* 3DSTATE_CHROMA_KEY */
 
 /* 3DSTATE_CLEAR_PARAMETERS, p150 */
+#define _3DSTATE_CLEAR_PARAMETERS   (CMD_3D | (0x1d<<24) | (0x9c<<16) | 5)
+/* Dword 1 */
+#define CLEARPARAM_CLEAR_RECT	    (1 << 16)
+#define CLEARPARAM_ZONE_INIT	    (0 << 16)
+#define CLEARPARAM_WRITE_COLOR	    (1 << 2)
+#define CLEARPARAM_WRITE_DEPTH	    (1 << 1)
+#define CLEARPARAM_WRITE_STENCIL    (1 << 0)
 
 /* 3DSTATE_CONSTANT_BLEND_COLOR, p153 */
 #define _3DSTATE_CONST_BLEND_COLOR_CMD	(CMD_3D | (0x1d<<24) | (0x88<<16))
diff-tree 3bbf313ba541526a893915f8b6c64b1eccf325e0 (from acef342c870f3b5b781e48c8bf44739aa5ee8ffa)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Tue Jun 19 09:33:50 2007 +0800

    Fix left G33 issues
    
    Be sure to check G33 chip type in:
    - sdvo output
    - Y-major tile
    - crt detect
    - and xaa composite
    Sorry for that I should have fixed them very earlier...

diff --git a/src/i830_crt.c b/src/i830_crt.c
index bbb4a83..d9f4ee6 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -310,7 +310,8 @@ i830_crt_detect(xf86OutputPtr output)
     I830Ptr		    pI830 = I830PTR(pScrn);
     xf86CrtcPtr	    crtc;
 
-    if (IS_I945G(pI830) || IS_I945GM(pI830) || IS_I965G(pI830)) {
+    if (IS_I945G(pI830) || IS_I945GM(pI830) || IS_I965G(pI830) ||
+	    IS_G33CLASS(pI830)) {
 	if (i830_crt_detect_hotplug(output))
 	    return XF86OutputStatusConnected;
 	else
diff --git a/src/i830_debug.c b/src/i830_debug.c
index 9354958..bda263c 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -224,7 +224,7 @@ DEBUGSTRING(i830_debug_dpll)
 	break;
     }
 
-    if (IS_I945G(pI830) || IS_I945GM(pI830)) {
+    if (IS_I945G(pI830) || IS_I945GM(pI830) || IS_G33CLASS(pI830)) {
 	sprintf(sdvoextra, ", SDVO mult %d",
 		(int)((val & SDVO_MULTIPLIER_MASK) >>
 		SDVO_MULTIPLIER_SHIFT_HIRES) + 1);
diff --git a/src/i830_display.c b/src/i830_display.c
index 6965337..2df1fcc 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -706,7 +706,7 @@ i830_get_core_clock_speed(ScrnInfoPtr pS
     /* Core clock values taken from the published datasheets.
      * The 830 may go up to 166 Mhz, which we should check.
      */
-    if (IS_I945G(pI830))
+    if (IS_I945G(pI830) || IS_G33CLASS(pI830))
 	return 400000;
     else if (IS_I915G(pI830))
 	return 333000;
@@ -869,7 +869,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
 	if (is_sdvo)
 	{
 	    dpll |= DPLL_DVO_HIGH_SPEED;
-	    if (IS_I945G(pI830) || IS_I945GM(pI830))
+	    if (IS_I945G(pI830) || IS_I945GM(pI830) || IS_G33CLASS(pI830))
 	    {
 		int sdvo_pixel_multiply = adjusted_mode->Clock / mode->Clock;
 		dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 17d4c4e..afdd93d 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -790,7 +790,7 @@ IsTileable(ScrnInfoPtr pScrn, int pitch)
     switch (pitch) {
     case 128:
     case 256:
-	if (IS_I945G(pI830) || IS_I945GM(pI830))
+	if (IS_I945G(pI830) || IS_I945GM(pI830) || IS_G33CLASS(pI830))
 	    return TRUE;
 	else
 	    return FALSE;
@@ -1528,7 +1528,8 @@ i830_set_fence(ScrnInfoPtr pScrn, int nr
    	}
     }
 
-    if ((IS_I945G(pI830) || IS_I945GM(pI830)) && tile_format == TILING_YMAJOR)
+    if ((IS_I945G(pI830) || IS_I945GM(pI830) || IS_G33CLASS(pI830))
+	    && tile_format == TILING_YMAJOR)
 	fence_pitch = pitch / 128;
     else if (IS_I9XX(pI830))
 	fence_pitch = pitch / 512;
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 3916dba..2767715 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -747,7 +747,7 @@ i830_sdvo_mode_set(xf86OutputPtr output,
     sdvo_pixel_multiply = i830_sdvo_get_pixel_multiplier(mode);
     if (IS_I965G(pI830)) {
 	/* done in crtc_mode_set as the dpll_md reg must be written early */
-    } else if (IS_I945G(pI830) || IS_I945GM(pI830)) {
+    } else if (IS_I945G(pI830) || IS_I945GM(pI830) || IS_G33CLASS(pI830)) {
 	/* done in crtc_mode_set as it lives inside the dpll register */
     } else {
 	sdvox |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT;
diff --git a/src/i830_xaa.c b/src/i830_xaa.c
index 790299c..ec8a879 100644
--- a/src/i830_xaa.c
+++ b/src/i830_xaa.c
@@ -249,7 +249,7 @@ I830XAAInit(ScreenPtr pScreen)
 	    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))
+		   IS_I945G(pI830) || IS_I945GM(pI830) || IS_G33CLASS(pI830))
 	{
 	    pI830->xaa_check_composite = i915_check_composite;
 	    pI830->xaa_prepare_composite = i915_prepare_composite;
diff-tree acef342c870f3b5b781e48c8bf44739aa5ee8ffa (from fbbb41bc5e03478cb46ee8f64ef68b23ff3fc14b)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Jun 18 11:57:48 2007 -0700

    Bug #11295: Disable textured video on i915 with framebuffer width too large.

diff --git a/src/i830_video.c b/src/i830_video.c
index 1ee43dd..43e25bb 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -569,7 +569,9 @@ I830InitVideo(ScreenPtr pScreen)
     /* Set up textured video if we can do it at this depth and we are on
      * supported hardware.
      */
-    if (pScrn->bitsPerPixel >= 16 && (IS_I9XX(pI830) || IS_I965G(pI830))) {
+    if (pScrn->bitsPerPixel >= 16 && (IS_I9XX(pI830) || IS_I965G(pI830)) &&
+	!(!IS_I965G(pI830) && pScrn->displayWidth > 2048))
+    {
 	texturedAdaptor = I830SetupImageVideoTextured(pScreen);
 	if (texturedAdaptor != NULL) {
 	    adaptors[num_adaptors++] = texturedAdaptor;
diff-tree fbbb41bc5e03478cb46ee8f64ef68b23ff3fc14b (from d5ca000ece145a35fd6df0dcf3fb3460bd2d64e3)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Sun Jun 17 14:59:24 2007 +0100

    Let DPMS functions enable plane/pipe/output on 8xx hardware.
    
    On 855, letting crtc_mode_set enable the plane and pipe will occasionally
    hang the chip. Instead, wait for crtc_enable to light things up. For 9xx,
    leave things alone.

diff --git a/src/i830_display.c b/src/i830_display.c
index adc7479..6965337 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -958,11 +958,17 @@ 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
+    /*
+     * This "shouldn't" be needed as the dpms on code
+     * will be run after the mode is set. On 9xx, it helps.
+     * On 855, it can lock up the chip (and the entire machine)
+     */
+    if (IS_I9XX (pI830))
+    {
+	dspcntr |= DISPLAY_PLANE_ENABLE;
+	pipeconf |= PIPEACONF_ENABLE;
+	dpll |= DPLL_VCO_ENABLE;
+    }
     
     /* Disable the panel fitter if it was on our pipe */
     if (i830_panel_fitter_pipe (pI830) == pipe)
diff-tree d5ca000ece145a35fd6df0dcf3fb3460bd2d64e3 (from 6b2ae93506d6795f87d6993bebfcb4e6632508ee)
Author: Rémi Cardona <remi at gentoo.org>
Date:   Sat Jun 16 13:17:54 2007 +0100

    Include stdint.h to get uint64_t

diff --git a/src/i830_common.h b/src/i830_common.h
index 5c2d919..9c8616c 100644
--- a/src/i830_common.h
+++ b/src/i830_common.h
@@ -31,6 +31,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef _I830_COMMON_H_
 #define _I830_COMMON_H_
 
+#include <stdint.h>
 
 #define I830_NR_TEX_REGIONS 255	/* maximum due to use of chars for next/prev */
 #define I830_LOG_MIN_TEX_REGION_SIZE 14
diff-tree 6b2ae93506d6795f87d6993bebfcb4e6632508ee (from 671ba03befebfdd7256855858987aabc28b2e8cd)
Author: Dave Airlie <airlied at linux.ie>
Date:   Fri Jun 15 23:30:04 2007 +1000

    sdvo: add support for RGB outputs on SDVO
    
    This lights up my monitor VGA-1 - it doesn't look the best though

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 24c9c99..3916dba 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -1280,6 +1280,18 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
         output->subpixel_order = SubPixelHorizontalRGB;
 	name_prefix="TMDS";
     }
+    else if (dev_priv->caps.output_flags & SDVO_OUTPUT_RGB0)
+    {
+	dev_priv->active_outputs = SDVO_OUTPUT_RGB0;
+        output->subpixel_order = SubPixelHorizontalRGB;
+	name_prefix="VGA";
+    }
+    else if (dev_priv->caps.output_flags & SDVO_OUTPUT_RGB1)
+    {
+	dev_priv->active_outputs = SDVO_OUTPUT_RGB1;
+        output->subpixel_order = SubPixelHorizontalRGB;
+	name_prefix="VGA";
+    }
     else
     {
 	unsigned char	bytes[2];
@@ -1318,6 +1330,6 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
 	       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 & SDVO_OUTPUT_TMDS0 ? 'Y' : 'N',
-	       dev_priv->caps.output_flags & SDVO_OUTPUT_TMDS1 ? 'Y' : 'N');
+	       dev_priv->caps.output_flags & (SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_TMDS0) ? 'Y' : 'N',
+	       dev_priv->caps.output_flags & (SDVO_OUTPUT_RGB1 | SDVO_OUTPUT_TMDS1) ? 'Y' : 'N');
 }
diff-tree 671ba03befebfdd7256855858987aabc28b2e8cd (from 6c29e0bae5f1e7cee02b678418394abb971594eb)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Jun 13 16:30:26 2007 -0700

    Fix and enable the 915-class planar textured video path.

diff --git a/src/i830_video.c b/src/i830_video.c
index c1ddc98..1ee43dd 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -2347,9 +2347,8 @@ I830PutImage(ScrnInfoPtr pScrn,
     case FOURCC_I420:
 	srcPitch = (width + 3) & ~3;
 	srcPitch2 = ((width >> 1) + 3) & ~3;
-	if (pPriv->textured) {
+	if (pPriv->textured && IS_I965G(pI830))
 	    destId = FOURCC_YUY2;
-	}
 	break;
     case FOURCC_UYVY:
     case FOURCC_YUY2:
@@ -2450,7 +2449,7 @@ I830PutImage(ScrnInfoPtr pScrn,
     case FOURCC_I420:
 	top &= ~1;
 	nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top;
-	if (pPriv->textured) {
+	if (pPriv->textured && IS_I965G(pI830)) {
 	    I830CopyPlanarToPackedData(pScrn, pPriv, buf, srcPitch, srcPitch2,
 				       dstPitch, height, top, left, nlines,
 				       npixels, id);
diff --git a/src/i915_video.c b/src/i915_video.c
index d02f770..f1bf4cc 100644
--- a/src/i915_video.c
+++ b/src/i915_video.c
@@ -48,7 +48,7 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
 			 PixmapPtr pPixmap)
 {
    I830Ptr pI830 = I830PTR(pScrn);
-   CARD32 format, ms3, s2, s5;
+   CARD32 format, ms3, s5;
    BoxPtr pbox;
    int nbox, dxo, dyo, pix_xoff, pix_yoff;
    Bool planar;
@@ -68,11 +68,8 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
       planar = TRUE;
       break;
    default:
-#if 0
       ErrorF("Unknown format 0x%x\n", id);
-#endif
-      planar = FALSE;
-      break;
+      return;
    }
 
    IntelEmitInvarientState(pScrn);
@@ -96,18 +93,14 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
 
    OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) |
 	    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);
-   else
-      s2 |= S2_TEXCOORD_FMT(1, TEXCOORDFMT_NOT_PRESENT);
-   s2 |= 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(s2);
+   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_XY);
    s5 = 0x0;
@@ -148,7 +141,9 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
 	       (FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) |
 	       (FILTER_LINEAR << SS2_MIN_FILTER_SHIFT));
       OUT_RING((TEXCOORDMODE_CLAMP_EDGE << SS3_TCX_ADDR_MODE_SHIFT) |
-	       (TEXCOORDMODE_CLAMP_EDGE << SS3_TCY_ADDR_MODE_SHIFT));
+	       (TEXCOORDMODE_CLAMP_EDGE << SS3_TCY_ADDR_MODE_SHIFT) |
+	       (0 << SS3_TEXTUREMAP_INDEX_SHIFT) |
+	       SS3_NORMALIZED_COORDS);
       OUT_RING(0x00000000);
 
       OUT_RING(_3DSTATE_MAP_STATE | 3);
@@ -168,7 +163,7 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
       if (!pI830->disableTiling)
 	 ms3 |= MS3_USE_FENCE_REGS;
       OUT_RING(ms3);
-      OUT_RING(((video_pitch / 4) - 1) << 21);
+      OUT_RING(((video_pitch / 4) - 1) << MS4_PITCH_SHIFT);
       ADVANCE_LP_RING();
 
       FS_BEGIN();
@@ -179,8 +174,7 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
    } else {
       FS_LOCALS(16);
 
-      BEGIN_LP_RING(1 + 18 + 11 + 11);
-      OUT_RING(MI_NOOP);
+      BEGIN_LP_RING(18 + 11 + 11);
       /* For the planar formats, we set up three samplers -- one for each plane,
        * in a Y8 format.  Because I couldn't get the special PLANAR_TO_PACKED
        * shader setup to work, I did the manual pixel shader:
@@ -226,23 +220,29 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
       OUT_RING(_3DSTATE_SAMPLER_STATE | 9);
       OUT_RING(0x00000007);
       /* sampler 0 */
-      OUT_RING(0x00000000);
       OUT_RING((FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) |
 	       (FILTER_LINEAR << SS2_MIN_FILTER_SHIFT));
       OUT_RING((TEXCOORDMODE_CLAMP_EDGE << SS3_TCX_ADDR_MODE_SHIFT) |
-	       (TEXCOORDMODE_CLAMP_EDGE << SS3_TCY_ADDR_MODE_SHIFT));
-      /* sampler 1 */
+	       (TEXCOORDMODE_CLAMP_EDGE << SS3_TCY_ADDR_MODE_SHIFT) |
+	       (0 << SS3_TEXTUREMAP_INDEX_SHIFT) |
+	       SS3_NORMALIZED_COORDS);
       OUT_RING(0x00000000);
+      /* sampler 1 */
       OUT_RING((FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) |
 	       (FILTER_LINEAR << SS2_MIN_FILTER_SHIFT));
       OUT_RING((TEXCOORDMODE_CLAMP_EDGE << SS3_TCX_ADDR_MODE_SHIFT) |
-	       (TEXCOORDMODE_CLAMP_EDGE << SS3_TCY_ADDR_MODE_SHIFT));
-      /* sampler 2 */
+	       (TEXCOORDMODE_CLAMP_EDGE << SS3_TCY_ADDR_MODE_SHIFT) |
+	       (1 << SS3_TEXTUREMAP_INDEX_SHIFT) |
+	       SS3_NORMALIZED_COORDS);
       OUT_RING(0x00000000);
+      /* sampler 2 */
       OUT_RING((FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) |
 	       (FILTER_LINEAR << SS2_MIN_FILTER_SHIFT));
       OUT_RING((TEXCOORDMODE_CLAMP_EDGE << SS3_TCX_ADDR_MODE_SHIFT) |
-	       (TEXCOORDMODE_CLAMP_EDGE << SS3_TCY_ADDR_MODE_SHIFT));
+	       (TEXCOORDMODE_CLAMP_EDGE << SS3_TCY_ADDR_MODE_SHIFT) |
+	       (2 << SS3_TEXTUREMAP_INDEX_SHIFT) |
+	       SS3_NORMALIZED_COORDS);
+      OUT_RING(0x00000000);
 
       OUT_RING(_3DSTATE_MAP_STATE | 9);
       OUT_RING(0x00000007);
@@ -251,36 +251,39 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
       ms3 = MAPSURF_8BIT | MT_8BIT_I8;
       ms3 |= (height - 1) << MS3_HEIGHT_SHIFT;
       ms3 |= (width - 1) << MS3_WIDTH_SHIFT;
+      if (!pI830->disableTiling)
+	 ms3 |= MS3_USE_FENCE_REGS;
       OUT_RING(ms3);
-      OUT_RING(((video_pitch * 2 / 4) - 1) << 21);
+      OUT_RING(((video_pitch * 2 / 4) - 1) << MS4_PITCH_SHIFT);
 
       OUT_RING(pPriv->UBuf0offset);
       ms3 = MAPSURF_8BIT | MT_8BIT_I8;
       ms3 |= (height / 2 - 1) << MS3_HEIGHT_SHIFT;
       ms3 |= (width / 2 - 1) << MS3_WIDTH_SHIFT;
+      if (!pI830->disableTiling)
+	 ms3 |= MS3_USE_FENCE_REGS;
       OUT_RING(ms3);
-      OUT_RING(((video_pitch / 4) - 1) << 21);
+      OUT_RING(((video_pitch / 4) - 1) << MS4_PITCH_SHIFT);
 
       OUT_RING(pPriv->VBuf0offset);
       ms3 = MAPSURF_8BIT | MT_8BIT_I8;
       ms3 |= (height / 2 - 1) << MS3_HEIGHT_SHIFT;
       ms3 |= (width / 2 - 1) << MS3_WIDTH_SHIFT;
+      if (!pI830->disableTiling)
+	 ms3 |= MS3_USE_FENCE_REGS;
       OUT_RING(ms3);
-      OUT_RING(((video_pitch / 4) - 1) << 21);
+      OUT_RING(((video_pitch / 4) - 1) << MS4_PITCH_SHIFT);
       ADVANCE_LP_RING();
 
       FS_BEGIN();
       /* Declare samplers */
-      i915_fs_dcl(FS_S0);
-      i915_fs_dcl(FS_S1);
-      i915_fs_dcl(FS_S2);
-      i915_fs_dcl(FS_T0);
-      i915_fs_dcl(FS_T1);
+      i915_fs_dcl(FS_S0); /* Y */
+      i915_fs_dcl(FS_S1); /* U */
+      i915_fs_dcl(FS_S2); /* V */
+      i915_fs_dcl(FS_T0); /* normalized coords */
 
-      /* Load samplers to temporaries.  Y (sampler 0) gets the un-halved coords-
-       * from t1.
-       */
-      i915_fs_texld(FS_R1, FS_S0, FS_T1);
+      /* Load samplers to temporaries. */
+      i915_fs_texld(FS_R1, FS_S0, FS_T0);
       i915_fs_texld(FS_R2, FS_S1, FS_T0);
       i915_fs_texld(FS_R3, FS_S2, FS_T0);
 
@@ -293,16 +296,17 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
       i915_fs_add(FS_R0, i915_fs_operand_reg(FS_R0),
                  i915_fs_operand_reg(FS_C0));
       /* dot-product the YUV data in R0 by the vectors of coefficients for
-       * calculating R, G, and B, storing the results in the R, G, or B channels
-       * of the output color.
+       * calculating R, G, and B, storing the results in the R, G, or B
+       * channels of the output color.  The OC results are implicitly clamped
+       * at the end of the program.
        */
-      i915_fs_dp3_masked(FS_OC, MASK_X | MASK_SATURATE,
+      i915_fs_dp3_masked(FS_OC, MASK_X,
                         i915_fs_operand_reg(FS_R0),
                         i915_fs_operand_reg(FS_C1));
-      i915_fs_dp3_masked(FS_OC, MASK_Y | MASK_SATURATE,
+      i915_fs_dp3_masked(FS_OC, MASK_Y,
                         i915_fs_operand_reg(FS_R0),
                         i915_fs_operand_reg(FS_C2));
-      i915_fs_dp3_masked(FS_OC, MASK_Z | MASK_SATURATE,
+      i915_fs_dp3_masked(FS_OC, MASK_Z,
                         i915_fs_operand_reg(FS_R0),
                         i915_fs_operand_reg(FS_C3));
       /* Set alpha of the output to 1.0, by wiring W to 1 and not actually using
@@ -342,19 +346,13 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
       int box_x2 = pbox->x2;
       int box_y2 = pbox->y2;
       float src_scale_x, src_scale_y;
-      int vert_data_count;
 
       pbox++;
 
-      src_scale_x = (float)src_w / (float)drw_w;
-      src_scale_y  = (float)src_h / (float)drw_h;
-
-      if (!planar)
-	 vert_data_count = 12;
-      else
-	 vert_data_count = 18;
+      src_scale_x = ((float)src_w / width) / drw_w;
+      src_scale_y  = ((float)src_h / height) / drw_h;
 
-      BEGIN_LP_RING(vert_data_count + 8);
+      BEGIN_LP_RING(8 + 12);
       OUT_RING(MI_NOOP);
       OUT_RING(MI_NOOP);
       OUT_RING(MI_NOOP);
@@ -366,47 +364,25 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
       /* vertex data - rect list consists of bottom right, bottom left, and top
        * left vertices.
        */
-      OUT_RING(PRIM3D_INLINE | PRIM3D_RECTLIST |
-	       (vert_data_count - 1));
+      OUT_RING(PRIM3D_INLINE | PRIM3D_RECTLIST | (12 - 1));
 
       /* bottom right */
       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);
-      } else {
-	 OUT_RING_F((box_x2 - dxo) * src_scale_x / 2.0);
-	 OUT_RING_F((box_y2 - dyo) * src_scale_y / 2.0);
-	 OUT_RING_F((box_x2 - dxo) * src_scale_x);
-	 OUT_RING_F((box_y2 - dyo) * src_scale_y);
-      }
+      OUT_RING_F((box_x2 - dxo) * src_scale_x);
+      OUT_RING_F((box_y2 - dyo) * src_scale_y);
 
       /* bottom left */
       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);
-      } else {
-	 OUT_RING_F((box_x1 - dxo) * src_scale_x / 2.0);
-	 OUT_RING_F((box_y2 - dyo) * src_scale_y / 2.0);
-	 OUT_RING_F((box_x1 - dxo) * src_scale_x);
-	 OUT_RING_F((box_y2 - dyo) * src_scale_y);
-      }
+      OUT_RING_F((box_x1 - dxo) * src_scale_x);
+      OUT_RING_F((box_y2 - dyo) * src_scale_y);
 
       /* top left */
       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);
-      } else {
-	 OUT_RING_F((box_x1 - dxo) * src_scale_x / 2.0);
-	 OUT_RING_F((box_y1 - dyo) * src_scale_y / 2.0);
-	 OUT_RING_F((box_x1 - dxo) * src_scale_x);
-	 OUT_RING_F((box_y1 - dyo) * src_scale_y);
-      }
+      OUT_RING_F((box_x1 - dxo) * src_scale_x);
+      OUT_RING_F((box_y1 - dyo) * src_scale_y);
 
       ADVANCE_LP_RING();
    }
diff-tree 6c29e0bae5f1e7cee02b678418394abb971594eb (from 420e41e7921d3cc07c784fd17936ec8a675f3b20)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Jun 13 13:40:39 2007 -0700

    Improve the drm_i915_flip_t check.

diff --git a/configure.ac b/configure.ac
index da9fd3f..66992fc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -191,11 +191,14 @@ if test "$DRI" = yes; then
 	fi
 
 	save_CFLAGS="$CFLAGS"
-	CFLAGS="$DRI_CFLAGS"
+	CFLAGS="$XORG_CFLAGS $DRI_CFLAGS"
 	AC_CHECK_TYPE(drm_i915_flip_t,
 		      [AC_DEFINE(HAVE_I915_FLIP, 1,
 			         [Have drm_i915_flip_t and related definitions])],
-		      [], [#include <i915_drm.h>])
+		      [], [
+#include <inttypes.h>
+#include <i915_drm.h>
+])
 	CFLAGS="$save_CFLAGS"
 fi
 
diff-tree 420e41e7921d3cc07c784fd17936ec8a675f3b20 (from 51612e5ac3ddfb2bb172c58f2dfff9631093b69c)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Jun 13 13:34:26 2007 -0700

    Revert "Replace failure-prone configure test for fresh libdrm with a simple ifndef."
    
    This reverts commit c2b130354aecffbeb2a2d23c7371461feaf5766a.
    
    Sadly, a non-working DRM_IOCTL_I915_FLIP already existed.

diff --git a/configure.ac b/configure.ac
index 53d23ed..da9fd3f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -189,6 +189,14 @@ if test "$DRI" = yes; then
 	if test "$have_damage_h" = yes; then
 		AC_DEFINE(DAMAGE,1,[Use Damage extension])
 	fi
+
+	save_CFLAGS="$CFLAGS"
+	CFLAGS="$DRI_CFLAGS"
+	AC_CHECK_TYPE(drm_i915_flip_t,
+		      [AC_DEFINE(HAVE_I915_FLIP, 1,
+			         [Have drm_i915_flip_t and related definitions])],
+		      [], [#include <i915_drm.h>])
+	CFLAGS="$save_CFLAGS"
 fi
 
 AM_CONDITIONAL(VIDEO_DEBUG, test x$VIDEO_DEBUG = xyes)
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 6ec56cf..ca1190c 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -83,8 +83,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #include "i915_drm.h"
 
-/* This block can be removed when libdrm >= 2.3.1 is required. */
-#ifndef DRM_IOCTL_I915_FLIP
+/* This block and the corresponding configure test can be removed when
+ * libdrm >= 2.3.1 is required.
+ */
+#ifndef HAVE_I915_FLIP
 
 #define DRM_VBLANK_FLIP 0x8000000
 
diff-tree 51612e5ac3ddfb2bb172c58f2dfff9631093b69c (from ceb6dd72443c094212b0281c42cbe92e9a29f682)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Jun 12 16:09:54 2007 -0700

    On hang, dump up to the head pointer, not just up to the tail.

diff --git a/src/i830_debug.c b/src/i830_debug.c
index 19eb17a..9354958 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -666,7 +666,8 @@ i830_dump_ring(ScrnInfoPtr pScrn)
     virt = pI830->LpRing->virtual_start;
     ErrorF ("Ring at virtual 0x%x head 0x%x tail 0x%x count %d\n",
 	    (unsigned int) virt, head, tail, (((tail + mask + 1) - head) & mask) >> 2);
-    for (ring = (head - 128) & mask; ring != tail; ring = (ring + 4) & mask)
+    for (ring = (head - 128) & mask; ring != ((head + 4) & mask);
+	 ring = (ring + 4) & mask)
     {
 	ErrorF ("\t%08x: %08x\n", ring, *(volatile unsigned int *) (virt + ring));
     }
diff-tree ceb6dd72443c094212b0281c42cbe92e9a29f682 (from c2b130354aecffbeb2a2d23c7371461feaf5766a)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Jun 4 16:37:53 2007 -0700

    Fix context switching between DRI and X.
    
    Now, all 3D pipeline consumers in the driver just call
    IntelEmitInvariantState(), which handles basic state setup, the caching of that
    state setup, and notifying DRI clients.  This also removes a mistaken idle
    wait in the Render code which was papering over the brokenness in the context
    switching.

diff --git a/src/i830.h b/src/i830.h
index e4d5070..8947524 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -307,7 +307,6 @@ typedef struct _I830Rec {
    Rotation rotation;
    void (*PointerMoved)(int, int, int);
    CreateScreenResourcesProcPtr    CreateScreenResources;
-   int *used3D;
 
    i830_memory *logical_context;
 
@@ -527,7 +526,7 @@ typedef struct _I830Rec {
    CARD32 saveSWF[17];
    CARD32 saveBLC_PWM_CTL;
 
-   enum last_3d last_3d;
+   enum last_3d *last_3d;
 
    /** Enables logging of debug output related to mode switching. */
    Bool debug_modes;
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 4746be0..6ec56cf 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1196,7 +1196,7 @@ I830DRISwapContext(ScreenPtr pScreen, DR
       if (I810_DEBUG & DEBUG_VERBOSE_DRI)
 	 ErrorF("i830DRISwapContext (in)\n");
 
-      pI830->last_3d = LAST_3D_OTHER;
+      *pI830->last_3d = LAST_3D_OTHER;
 
       if (!pScrn->vtSema)
      	 return;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 3133d77..7f1fe2c 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2045,22 +2045,25 @@ I830InitFBManager(
    return ret;
 }
 
-/* Initialize the first context */
+/**
+ * Intialiazes the hardware for the 3D pipeline use in the 2D driver.
+ *
+ * Some state caching is performed to avoid redundant state emits.  This
+ * function is also responsible for marking the state as clobbered for DRI
+ * clients.
+ */
 void
 IntelEmitInvarientState(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
    CARD32 ctx_addr;
-#ifdef XF86DRI
-   drmI830Sarea *sarea;
-#endif
 
-   if (pI830->noAccel || !I830IsPrimary(pScrn))
+   if (pI830->noAccel)
       return;
 
 #ifdef XF86DRI
    if (pI830->directRenderingEnabled) {
-      sarea = DRIGetSAREAPrivate(pScrn->pScreen);
+      drmI830Sarea *sarea = DRIGetSAREAPrivate(pScrn->pScreen);
 
       /* Mark that the X Server was the last holder of the context */
       if (sarea)
@@ -2068,6 +2071,12 @@ IntelEmitInvarientState(ScrnInfoPtr pScr
    }
 #endif
 
+   /* If we've emitted our state since the last clobber by another client,
+    * skip it.
+    */
+   if (*pI830->last_3d != LAST_3D_OTHER)
+      return;
+
    ctx_addr = pI830->logical_context->offset;
    assert((pI830->logical_context->offset & 2047) == 0);
    {
@@ -2304,13 +2313,14 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
          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) {
+      if (!pI830->last_3d)
+         pI830->last_3d = xalloc(sizeof(enum last_3d));
+      if (!pI830->LpRing || !pI830->overlayOn || !pI830->last_3d) {
          xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		 "Could not allocate primary data structures.\n");
          return FALSE;
       }
+      *pI830->last_3d = LAST_3D_OTHER;
       *pI830->overlayOn = FALSE;
       if (pI830->entityPrivate)
          pI830->entityPrivate->XvInUse = -1;
@@ -2320,7 +2330,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       pI830->LpRing = pI8301->LpRing;
       pI830->overlay_regs = pI8301->overlay_regs;
       pI830->overlayOn = pI8301->overlayOn;
-      pI830->used3D = pI8301->used3D;
+      pI830->last_3d = pI8301->last_3d;
    }
 
    /* Need MMIO mapped to do GTT lookups during memory allocation. */
@@ -3012,15 +3022,11 @@ I830EnterVT(int scrnIndex, int flags)
     */
    i830SetHotkeyControl(pScrn, HOTKEY_DRIVER_NOTIFY);
 
-   /* Needed for rotation */
-   IntelEmitInvarientState(pScrn);
-
    if (pI830->checkDevices)
       pI830->devicesTimer = TimerSet(NULL, 0, 1000, I830CheckDevicesTimer, pScrn);
 
-   /* Force invarient 3D state to be emitted */
-   *pI830->used3D = 1<<31;
-   pI830->last_3d = LAST_3D_OTHER;
+   /* Mark 3D state as being clobbered */
+   *pI830->last_3d = LAST_3D_OTHER;
 
    return TRUE;
 }
@@ -3111,8 +3117,8 @@ I830CloseScreen(int scrnIndex, ScreenPtr
       pI830->LpRing = NULL;
       xfree(pI830->overlayOn);
       pI830->overlayOn = NULL;
-      xfree(pI830->used3D);
-      pI830->used3D = NULL;
+      xfree(pI830->last_3d);
+      pI830->last_3d = NULL;
    }
 
    pScrn->PointerMoved = pI830->PointerMoved;
diff --git a/src/i830_exa.c b/src/i830_exa.c
index bb60c0a..22618dc 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -270,22 +270,6 @@ I830EXADoneCopy(PixmapPtr pDstPixmap)
 #endif
 }
 
-void
-i830_enter_render(ScrnInfoPtr pScrn)
-{
-    I830Ptr pI830 = I830PTR(pScrn);
-#ifdef XF86DRI
-    if (pI830->directRenderingEnabled) {
-        drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
-	pSAREAPriv->ctxOwner = DRIGetContext(pScrn->pScreen);
-    }
-#endif
-    if (pI830->last_3d != LAST_3D_RENDER) {
-	i830WaitSync(pScrn);
-	pI830->last_3d = LAST_3D_RENDER;
-    }
-}
-
 #define xFixedToFloat(val) \
 	((float)xFixedToInt(val) + ((float)xFixedFrac(val) / 65536.0))
 
diff --git a/src/i830_render.c b/src/i830_render.c
index 957953e..90b884f 100644
--- a/src/i830_render.c
+++ b/src/i830_render.c
@@ -400,7 +400,8 @@ i830_prepare_composite(int op, PicturePt
     I830Ptr pI830 = I830PTR(pScrn);
     CARD32 dst_format, dst_offset, dst_pitch;
 
-    i830_enter_render(pScrn);
+    IntelEmitInvarientState(pScrn);
+    *pI830->last_3d = LAST_3D_RENDER;
 
     i830_get_dest_format(pDstPicture, &dst_format);
     dst_offset = intel_get_pixmap_offset(pDst);
diff --git a/src/i915_render.c b/src/i915_render.c
index d5a8579..b2dacfe 100644
--- a/src/i915_render.c
+++ b/src/i915_render.c
@@ -315,7 +315,8 @@ i915_prepare_composite(int op, PicturePt
     CARD32 dst_format, dst_offset, dst_pitch;
     CARD32 blendctl;
 
-    i830_enter_render(pScrn);
+    IntelEmitInvarientState(pScrn);
+    *pI830->last_3d = LAST_3D_RENDER;
 
     i915_get_dest_format(pDstPicture, &dst_format);
     dst_offset = intel_get_pixmap_offset(pDst);
diff --git a/src/i915_video.c b/src/i915_video.c
index e4e0f1a..d02f770 100644
--- a/src/i915_video.c
+++ b/src/i915_video.c
@@ -75,13 +75,8 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
       break;
    }
 
-   /* 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;
-
-   pI830->last_3d = LAST_3D_VIDEO;
+   IntelEmitInvarientState(pScrn);
+   *pI830->last_3d = LAST_3D_VIDEO;
 
    BEGIN_LP_RING(20);
 
diff --git a/src/i965_render.c b/src/i965_render.c
index 956baf3..e69a939 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -404,7 +404,8 @@ i965_prepare_composite(int op, PicturePt
     CARD32 dst_format, dst_offset, dst_pitch;
     Bool rotation_program = FALSE;
 
-    i830_enter_render(pScrn);
+    IntelEmitInvarientState(pScrn);
+    *pI830->last_3d = LAST_3D_RENDER;
 
     src_offset = intel_get_pixmap_offset(pSrc);
     src_pitch = intel_get_pixmap_pitch(pSrc);
diff --git a/src/i965_video.c b/src/i965_video.c
index 17d2006..3084233 100644
--- a/src/i965_video.c
+++ b/src/i965_video.c
@@ -200,20 +200,8 @@ I965DisplayVideoTextured(ScrnInfoPtr pSc
 
     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 */
+    IntelEmitInvarientState(pScrn);
+    *pI830->last_3d = LAST_3D_VIDEO;
 
     next_offset = 0;
 
diff-tree c2b130354aecffbeb2a2d23c7371461feaf5766a (from 0e1deb607f94e4aa3ec4b9df8ff7a07a1c95e31d)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Jun 12 08:49:21 2007 -0700

    Replace failure-prone configure test for fresh libdrm with a simple ifndef.

diff --git a/configure.ac b/configure.ac
index da9fd3f..53d23ed 100644
--- a/configure.ac
+++ b/configure.ac
@@ -189,14 +189,6 @@ if test "$DRI" = yes; then
 	if test "$have_damage_h" = yes; then
 		AC_DEFINE(DAMAGE,1,[Use Damage extension])
 	fi
-
-	save_CFLAGS="$CFLAGS"
-	CFLAGS="$DRI_CFLAGS"
-	AC_CHECK_TYPE(drm_i915_flip_t,
-		      [AC_DEFINE(HAVE_I915_FLIP, 1,
-			         [Have drm_i915_flip_t and related definitions])],
-		      [], [#include <i915_drm.h>])
-	CFLAGS="$save_CFLAGS"
 fi
 
 AM_CONDITIONAL(VIDEO_DEBUG, test x$VIDEO_DEBUG = xyes)
diff --git a/src/i830_dri.c b/src/i830_dri.c
index a17770b..4746be0 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -83,10 +83,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #include "i915_drm.h"
 
-/* This block and the corresponding configure test can be removed when
- * libdrm >= 2.3.1 is required.
- */
-#ifndef HAVE_I915_FLIP
+/* This block can be removed when libdrm >= 2.3.1 is required. */
+#ifndef DRM_IOCTL_I915_FLIP
 
 #define DRM_VBLANK_FLIP 0x8000000
 
diff-tree 0e1deb607f94e4aa3ec4b9df8ff7a07a1c95e31d (from 8d7a0ccd4f674659eb781def2cfdc3a6e5a219ce)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Jun 11 17:33:33 2007 -0700

    Fix a typo in _3DSTATE_DEPTH_SUBRECT_DISABLE definition.
    
    This is already fixed in the definition in the 3d driver.

diff --git a/src/i915_reg.h b/src/i915_reg.h
index 6751de6..6b40d70 100644
--- a/src/i915_reg.h
+++ b/src/i915_reg.h
@@ -133,9 +133,9 @@
 #define _3DSTATE_DEPTH_OFFSET_SCALE       (CMD_3D | (0x1d<<24) | (0x97<<16))
 /* scale in dword 1 */
 
-
+/* The depth subrectangle is not supported, but must be disabled. */
 /* 3DSTATE_DEPTH_SUBRECT_DISABLE, p160 */
-#define _3DSTATE_DEPTH_SUBRECT_DISABLE    (CMD_3D | (0x1c<<24) | (0x11<19) | 0x2)
+#define _3DSTATE_DEPTH_SUBRECT_DISABLE	(CMD_3D | (0x1c<<24) | (0x11<<19) | (1 << 1) | (0 << 0))
 
 /* p161 */
 #define _3DSTATE_DST_BUF_VARS_CMD	(CMD_3D | (0x1d<<24) | (0x85<<16))
diff-tree 8d7a0ccd4f674659eb781def2cfdc3a6e5a219ce (from 15caa64a497dcc0eacb0f91166d9b70206a8db35)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Jun 11 17:33:07 2007 -0700

    Clean up some nits in i915_video.c setup.
    
    - The screen dimensions were used for the clipping despite drawing being done
      to any pixmap, not necessarily the screen.
    - One piece of state setup was not documented anywhere, and isn't used in other
      3d hardware paths that also work.
    - A 3DSTATE_MODES_1 command (830-class only) was issued even though it no
      longer exists.

diff --git a/src/i915_video.c b/src/i915_video.c
index e837097..e4e0f1a 100644
--- a/src/i915_video.c
+++ b/src/i915_video.c
@@ -83,7 +83,7 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
 
    pI830->last_3d = LAST_3D_VIDEO;
 
-   BEGIN_LP_RING(24);
+   BEGIN_LP_RING(20);
 
    /* flush map & render cache */
    OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
@@ -94,16 +94,11 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
    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 */
+   OUT_RING((pPixmap->drawable.width - 1) |
+	    (pPixmap->drawable.height - 1) << 16); /* ymax, xmax */
    OUT_RING(0x00000000);	/* yorigin, xorigin */
    OUT_RING(MI_NOOP);
 
-   OUT_RING(0x7c000003);	/* unknown command */
-   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);
    s2 = S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D);
diff-tree 15caa64a497dcc0eacb0f91166d9b70206a8db35 (from 404fd47573f855b0442d49a383542fc093825ad0)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Fri Jun 8 18:44:28 2007 -0700

    Add description for how to use the frame and pixel counter registers.
    
    The 24-bit frame and pixel counters were not described in detail and
    will be useful for DRM.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index 8df664e..6001297 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -1967,9 +1967,30 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define DSPFW1			0x70034
 #define DSPFW2			0x70038
 #define DSPFW3			0x7003c
+/*
+ * The two pipe frame counter registers are not synchronized, so
+ * reading a stable value is somewhat tricky. The following code 
+ * should work:
+ *
+ *  do {
+ *    high1 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >> PIPE_FRAME_HIGH_SHIFT;
+ *    low1 =  ((INREG(PIPEAFRAMEPIXEL) & PIPE_FRAME_LOW_MASK) >> PIPE_FRAME_LOW_SHIFT);
+ *    high2 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >> PIPE_FRAME_HIGH_SHIFT);
+ *  } while (high1 != high2);
+ *  frame = (high1 << 8) | low1;
+ */
 #define PIPEAFRAMEHIGH		0x70040
+#define PIPE_FRAME_HIGH_MASK	0x0000ffff
+#define PIPE_FRAME_HIGH_SHIFT	0
 #define PIPEAFRAMEPIXEL		0x70044
-
+#define PIPE_FRAME_LOW_MASK	0xff000000
+#define PIPE_FRAME_LOW_SHIFT	24
+/*
+ * Pixel within the current frame is counted in the PIPEAFRAMEPIXEL register
+ * and is 24 bits wide.
+ */
+#define PIPE_PIXEL_MASK		0x00ffffff
+#define PIPE_PIXEL_SHIFT	0
 
 #define PIPEB_DSL		0x71000
 
diff-tree 404fd47573f855b0442d49a383542fc093825ad0 (from f4c05973d391bdb0a9b0eadb155548310baa98fd)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Jun 6 11:01:48 2007 +0800

    Enable overlay on G33 class chipsets
    
    Which have to use gfx vm offset fot setup overlay regs.

diff --git a/src/common.h b/src/common.h
index 2369a75..cc07e49 100644
--- a/src/common.h
+++ b/src/common.h
@@ -399,6 +399,8 @@ extern int I810_DEBUG;
 #define IS_I9XX(pI810) (IS_I915G(pI810) || IS_I915GM(pI810) || IS_I945G(pI810) || IS_I945GM(pI810) || IS_I965G(pI810) || IS_G33CLASS(pI810))
 
 #define IS_MOBILE(pI810) (IS_I830(pI810) || IS_I85X(pI810) || IS_I915GM(pI810) || IS_I945GM(pI810) || IS_I965GM(pI810))
+/* mark chipsets for using gfx VM offset for overlay */
+#define OVERLAY_NOPHYSICAL(pI810) (IS_G33CLASS(pI810))
 
 #define GTT_PAGE_SIZE			KB(4)
 #define ROUND_TO(x, y)			(((x) + (y) - 1) / (y) * (y))
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 747cfcc..17d4c4e 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -747,15 +747,19 @@ static Bool
 i830_allocate_overlay(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
+    int flags = NEED_PHYSICAL_ADDR;
 
     /* Only allocate if overlay is going to be enabled. */
     if (!pI830->XvEnabled)
 	return TRUE;
 
+    if (OVERLAY_NOPHYSICAL(pI830))
+	flags = 0;
+
     if (!IS_I965G(pI830)) {
 	pI830->overlay_regs = i830_allocate_memory(pScrn, "overlay registers",
 						   OVERLAY_SIZE, GTT_PAGE_SIZE,
-						   NEED_PHYSICAL_ADDR);
+						   flags);
 	if (pI830->overlay_regs == NULL) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		       "Failed to allocate Overlay register space.\n");
diff --git a/src/i830_video.c b/src/i830_video.c
index e5efcaa..c1ddc98 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -428,7 +428,10 @@ i830_overlay_on(ScrnInfoPtr pScrn)
     OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE);
     OUT_RING(MI_NOOP);
     OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_ON);
-    OUT_RING(pI830->overlay_regs->bus_addr | OFC_UPDATE);
+    if (OVERLAY_NOPHYSICAL(pI830))
+	OUT_RING(pI830->overlay_regs->offset | OFC_UPDATE);
+    else
+	OUT_RING(pI830->overlay_regs->bus_addr | OFC_UPDATE);
     /* Wait for the overlay to light up before attempting to use it */
     OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
     OUT_RING(MI_NOOP);
@@ -458,7 +461,10 @@ i830_overlay_continue(ScrnInfoPtr pScrn,
     if (!*pI830->overlayOn)
 	return;
 
-    flip_addr = pI830->overlay_regs->bus_addr;
+    if (OVERLAY_NOPHYSICAL(pI830))
+	flip_addr = pI830->overlay_regs->offset;
+    else
+	flip_addr = pI830->overlay_regs->bus_addr;
     if (update_filter)
 	flip_addr |= OFC_UPDATE;
     OVERLAY_DEBUG ("overlay_continue cmd 0x%08lx -> 0x%08lx sta 0x%08lx\n",
@@ -507,7 +513,10 @@ i830_overlay_off(ScrnInfoPtr pScrn)
 	OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE);
 	OUT_RING(MI_NOOP);
 	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_CONTINUE);
-	OUT_RING(pI830->overlay_regs->bus_addr);
+	if (OVERLAY_NOPHYSICAL(pI830))
+	    OUT_RING(pI830->overlay_regs->offset);
+	else
+	    OUT_RING(pI830->overlay_regs->bus_addr);
 	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
 	OUT_RING(MI_NOOP);
 	ADVANCE_LP_RING();
@@ -572,7 +581,7 @@ I830InitVideo(ScreenPtr pScreen)
     }
 
     /* Set up overlay video if we can do it at this depth. */
-    if (!IS_I965G(pI830) && !IS_G33CLASS(pI830) && pScrn->bitsPerPixel != 8 &&
+    if (!IS_I965G(pI830) && pScrn->bitsPerPixel != 8 &&
 	pI830->overlay_regs != NULL)
     {
 	overlayAdaptor = I830SetupImageVideoOverlay(pScreen);
diff-tree f4c05973d391bdb0a9b0eadb155548310baa98fd (from 36fcaeb2ef94db5399071540bba106dec3db81d5)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Tue Jun 5 11:07:41 2007 -0700

    Add support for the G33, Q33, and Q35 chipsets.
    
    These chipsets require that the hardware status page be referenced by an offset
    in the GTT rather than a physical memory address, so the X Server allocates it
    rather than the DRM.

diff --git a/src/common.h b/src/common.h
index c879333..2369a75 100644
--- a/src/common.h
+++ b/src/common.h
@@ -361,6 +361,21 @@ extern int I810_DEBUG;
 #define PCI_CHIP_I965_GM_BRIDGE 0x2A00
 #endif
 
+#ifndef PCI_CHIP_G33_G
+#define PCI_CHIP_G33_G		0x29C2
+#define PCI_CHIP_G33_G_BRIDGE 	0x29C0
+#endif
+
+#ifndef PCI_CHIP_Q35_G
+#define PCI_CHIP_Q35_G		0x29B2
+#define PCI_CHIP_Q35_G_BRIDGE 	0x29B0
+#endif
+
+#ifndef PCI_CHIP_Q33_G
+#define PCI_CHIP_Q33_G		0x29D2
+#define PCI_CHIP_Q33_G_BRIDGE 	0x29D0
+#endif
+
 #define IS_I810(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I810 ||	\
 			pI810->PciInfo->chipType == PCI_CHIP_I810_DC100 || \
 			pI810->PciInfo->chipType == PCI_CHIP_I810_E)
@@ -378,7 +393,10 @@ extern int I810_DEBUG;
 #define IS_I945GM(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I945_GM || pI810->PciInfo->chipType == PCI_CHIP_I945_GME)
 #define IS_I965GM(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I965_GM || pI810->PciInfo->chipType == PCI_CHIP_I965_GME)
 #define IS_I965G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I965_G || pI810->PciInfo->chipType == PCI_CHIP_I965_G_1 || pI810->PciInfo->chipType == PCI_CHIP_I965_Q || pI810->PciInfo->chipType == PCI_CHIP_I946_GZ || pI810->PciInfo->chipType == PCI_CHIP_I965_GM || pI810->PciInfo->chipType == PCI_CHIP_I965_GME)
-#define IS_I9XX(pI810) (IS_I915G(pI810) || IS_I915GM(pI810) || IS_I945G(pI810) || IS_I945GM(pI810) || IS_I965G(pI810))
+#define IS_G33CLASS(pI810) (pI810->PciInfo->chipType == PCI_CHIP_G33_G ||\
+ 			    pI810->PciInfo->chipType == PCI_CHIP_Q35_G ||\
+ 			    pI810->PciInfo->chipType == PCI_CHIP_Q33_G)
+#define IS_I9XX(pI810) (IS_I915G(pI810) || IS_I915GM(pI810) || IS_I945G(pI810) || IS_I945GM(pI810) || IS_I965G(pI810) || IS_G33CLASS(pI810))
 
 #define IS_MOBILE(pI810) (IS_I830(pI810) || IS_I85X(pI810) || IS_I915GM(pI810) || IS_I945GM(pI810) || IS_I965GM(pI810))
 
diff --git a/src/i810_driver.c b/src/i810_driver.c
index 5b04a47..972b6d5 100644
--- a/src/i810_driver.c
+++ b/src/i810_driver.c
@@ -147,6 +147,9 @@ static SymTabRec I810Chipsets[] = {
    {PCI_CHIP_I946_GZ,		"946GZ"},
    {PCI_CHIP_I965_GM,		"965GM"},
    {PCI_CHIP_I965_GME,		"965GME/GLE"},
+   {PCI_CHIP_G33_G,		"G33"},
+   {PCI_CHIP_Q35_G,		"Q35"},
+   {PCI_CHIP_Q33_G,		"Q33"},
    {-1,				NULL}
 };
 
@@ -173,6 +176,9 @@ static PciChipsets I810PciChipsets[] = {
    {PCI_CHIP_I946_GZ,		PCI_CHIP_I946_GZ,	RES_SHARED_VGA},
    {PCI_CHIP_I965_GM,		PCI_CHIP_I965_GM,	RES_SHARED_VGA},
    {PCI_CHIP_I965_GME,		PCI_CHIP_I965_GME,	RES_SHARED_VGA},
+   {PCI_CHIP_G33_G,		PCI_CHIP_G33_G,		RES_SHARED_VGA},
+   {PCI_CHIP_Q35_G,		PCI_CHIP_Q35_G,		RES_SHARED_VGA},
+   {PCI_CHIP_Q33_G,		PCI_CHIP_Q33_G,		RES_SHARED_VGA},
    {-1,				-1, RES_UNDEFINED }
 };
 
@@ -620,6 +626,9 @@ I810Probe(DriverPtr drv, int flags)
 	    case PCI_CHIP_I946_GZ:
 	    case PCI_CHIP_I965_GM:
 	    case PCI_CHIP_I965_GME:
+ 	    case PCI_CHIP_G33_G:
+ 	    case PCI_CHIP_Q35_G:
+ 	    case PCI_CHIP_Q33_G:
     	       xf86SetEntitySharable(usedChips[i]);
 
     	       /* Allocate an entity private if necessary */		
diff --git a/src/i810_reg.h b/src/i810_reg.h
index 234d124..8df664e 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -525,6 +525,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define PGETBL_SIZE_512KB   (0 << 1)
 #define PGETBL_SIZE_256KB   (1 << 1)
 #define PGETBL_SIZE_128KB   (2 << 1)
+#define G33_PGETBL_SIZE_MASK		(3 << 8)
+#define G33_PGETBL_SIZE_1M		(1 << 8)
+#define G33_PGETBL_SIZE_2M		(2 << 8)
 
 #define I830_PTE_BASE			0x10000
 #define PTE_ADDRESS_MASK		0xfffff000
@@ -2076,12 +2079,12 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define I830_GMCH_MEM_64M	0x1
 #define I830_GMCH_MEM_128M	0
 
-#define I830_GMCH_GMS_MASK			0x70
-#define I830_GMCH_GMS_DISABLED		0x00
+#define I830_GMCH_GMS_MASK			0xF0
+#define I830_GMCH_GMS_DISABLED			0x00
 #define I830_GMCH_GMS_LOCAL			0x10
-#define I830_GMCH_GMS_STOLEN_512	0x20
-#define I830_GMCH_GMS_STOLEN_1024	0x30
-#define I830_GMCH_GMS_STOLEN_8192	0x40
+#define I830_GMCH_GMS_STOLEN_512		0x20
+#define I830_GMCH_GMS_STOLEN_1024		0x30
+#define I830_GMCH_GMS_STOLEN_8192		0x40
 
 #define I830_RDRAM_CHANNEL_TYPE		0x03010
 #define I830_RDRAM_ND(x)			(((x) & 0x20) >> 5)
@@ -2096,6 +2099,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define I855_GMCH_GMS_STOLEN_32M		(0x5 << 4)
 #define I915G_GMCH_GMS_STOLEN_48M		(0x6 << 4)
 #define I915G_GMCH_GMS_STOLEN_64M		(0x7 << 4)
+#define G33_GMCH_GMS_STOLEN_128M		(0x8 << 4)
+#define G33_GMCH_GMS_STOLEN_256M		(0x9 << 4)
 
 #define I85X_CAPID			0x44
 #define I85X_VARIANT_MASK			0x7
diff --git a/src/i830.h b/src/i830.h
index 76cc6e8..e4d5070 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -319,6 +319,7 @@ typedef struct _I830Rec {
    i830_memory *depth_buffer;
    i830_memory *textures;		/**< Compatibility texture memory */
    i830_memory *memory_manager;		/**< DRI memory manager aperture */
+   i830_memory *hw_status;		/* for G33 hw status page alloc */
 
    int TexGranularity;
    int drmMinor;
diff --git a/src/i830_common.h b/src/i830_common.h
index f853ccd..5c2d919 100644
--- a/src/i830_common.h
+++ b/src/i830_common.h
@@ -54,6 +54,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define DRM_I830_DESTROY_HEAP             0x0c
 #define DRM_I830_SET_VBLANK_PIPE	  0x0d
 #define DRM_I830_GET_VBLANK_PIPE	  0x0e
+#define DRM_I830_HWS_PAGE_ADDR		  0x11
 
 
 typedef struct {
@@ -224,4 +225,8 @@ typedef struct {
 	int pipe;
 } drmI830VBlankPipe;
 
+typedef struct {
+	uint64_t addr;
+} drmI830HWS;
+
 #endif /* _I830_DRM_H_ */
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 663ef14..a17770b 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -232,6 +232,22 @@ I830SetParam(ScrnInfoPtr pScrn, int para
    return TRUE;
 }
 
+static Bool
+I830SetHWS(ScrnInfoPtr pScrn, int addr)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    drmI830HWS hws;
+
+    hws.addr = addr;
+
+    if (drmCommandWrite(pI830->drmSubFD, DRM_I830_HWS_PAGE_ADDR,
+		&hws, sizeof(drmI830HWS))) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		"G33 status page initialization Failed\n");
+	return FALSE;
+    }
+    return TRUE;
+}
 
 static Bool
 I830InitVisualConfigs(ScreenPtr pScreen)
@@ -933,6 +949,12 @@ I830DRIDoMappings(ScreenPtr pScreen)
       return FALSE;
    }
 
+   if (IS_G33CLASS(pI830)) {
+       if (!I830SetHWS(pScrn, pI830->hw_status->offset)) {
+	   DRICloseScreen(pScreen);
+	   return FALSE;
+       }
+   }
    /* init to zero to be safe */
    sarea->front_handle = 0;
    sarea->back_handle = 0;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 1290d6d..3133d77 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -236,6 +236,9 @@ static SymTabRec I830Chipsets[] = {
    {PCI_CHIP_I946_GZ,		"946GZ"},
    {PCI_CHIP_I965_GM,		"965GM"},
    {PCI_CHIP_I965_GME,		"965GME/GLE"},
+   {PCI_CHIP_G33_G,		"G33"},
+   {PCI_CHIP_Q35_G,		"Q35"},
+   {PCI_CHIP_Q33_G,		"Q33"},
    {-1,				NULL}
 };
 
@@ -256,6 +259,9 @@ static PciChipsets I830PciChipsets[] = {
    {PCI_CHIP_I946_GZ,		PCI_CHIP_I946_GZ,	RES_SHARED_VGA},
    {PCI_CHIP_I965_GM,		PCI_CHIP_I965_GM,	RES_SHARED_VGA},
    {PCI_CHIP_I965_GME,		PCI_CHIP_I965_GME,	RES_SHARED_VGA},
+   {PCI_CHIP_G33_G,		PCI_CHIP_G33_G,		RES_SHARED_VGA},
+   {PCI_CHIP_Q35_G,		PCI_CHIP_Q35_G,		RES_SHARED_VGA},
+   {PCI_CHIP_Q33_G,		PCI_CHIP_Q33_G,		RES_SHARED_VGA},
    {-1,				-1,			RES_UNDEFINED}
 };
 
@@ -436,6 +442,19 @@ I830DetectMemory(ScrnInfoPtr pScrn)
       default:
 	 FatalError("Unknown GTT size value: %08x\n", (int)INREG(PGETBL_CTL));
       }
+   } else if (IS_G33CLASS(pI830)) {
+      /* G33's GTT size is detect in GMCH_CTRL */
+      switch (gmch_ctrl & G33_PGETBL_SIZE_MASK) {
+      case G33_PGETBL_SIZE_1M:
+	 gtt_size = 1024;
+	 break;
+      case G33_PGETBL_SIZE_2M:
+	 gtt_size = 2048;
+	 break;
+      default:
+	 FatalError("Unknown GTT size value: %08x\n",
+		    (int)(gmch_ctrl & G33_PGETBL_SIZE_MASK));
+      }
    } else {
       /* Older chipsets only had GTT appropriately sized for the aperture. */
       gtt_size = pI830->FbMapSize / (1024*1024);
@@ -473,6 +492,14 @@ I830DetectMemory(ScrnInfoPtr pScrn)
 	 if (IS_I9XX(pI830))
 	    memsize = MB(64) - KB(range);
 	 break;
+      case G33_GMCH_GMS_STOLEN_128M:
+	 if (IS_G33CLASS(pI830))
+	     memsize = MB(128) - KB(range);
+	 break;
+      case G33_GMCH_GMS_STOLEN_256M:
+	 if (IS_G33CLASS(pI830))
+	     memsize = MB(256) - KB(range);
+	 break;
       }
    } else {
       switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
@@ -1076,6 +1103,15 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    case PCI_CHIP_I965_GME:
       chipname = "965GME/GLE";
       break;
+   case PCI_CHIP_G33_G:
+      chipname = "G33";
+      break;
+   case PCI_CHIP_Q35_G:
+      chipname = "Q35";
+      break;
+   case PCI_CHIP_Q33_G:
+      chipname = "Q33";
+      break;
    default:
       chipname = "unknown chipset";
       break;
@@ -1430,7 +1466,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    else
       pI830->CursorNeedsPhysical = FALSE;
 
-   if (IS_I965G(pI830))
+   if (IS_I965G(pI830) || IS_G33CLASS(pI830))
       pI830->CursorNeedsPhysical = FALSE;
 
    /*
diff --git a/src/i830_exa.c b/src/i830_exa.c
index 88d1b97..bb60c0a 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -509,7 +509,7 @@ I830EXAInit(ScreenPtr pScreen)
     	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))
+	       IS_I945G(pI830) || IS_I945GM(pI830) || IS_G33CLASS(pI830))
     {
 	pI830->EXADriverPtr->CheckComposite = i915_check_composite;
    	pI830->EXADriverPtr->PrepareComposite = i915_prepare_composite;
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 3ae10cf..747cfcc 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -1312,6 +1312,22 @@ i830_allocate_texture_memory(ScrnInfoPtr
     return TRUE;
 }
 
+static Bool
+i830_allocate_hwstatus(ScrnInfoPtr pScrn)
+{
+#define HWSTATUS_PAGE_SIZE (4*1024)
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    pI830->hw_status = i830_allocate_memory(pScrn, "G33 hw status",
+	    HWSTATUS_PAGE_SIZE, GTT_PAGE_SIZE, 0);
+    if (pI830->hw_status == NULL) {
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		"Failed to allocate hw status page for G33.\n");
+	return FALSE;
+    }
+    return TRUE;
+}
+
 Bool
 i830_allocate_3d_memory(ScrnInfoPtr pScrn)
 {
@@ -1319,6 +1335,11 @@ i830_allocate_3d_memory(ScrnInfoPtr pScr
 
     DPRINTF(PFX, "i830_allocate_3d_memory\n");
 
+    if (IS_G33CLASS(pI830)) {
+	if (!i830_allocate_hwstatus(pScrn))
+	    return FALSE;
+    }
+
     if (!i830_allocate_backbuffer(pScrn, &pI830->back_buffer,
 				  &pI830->back_tiled, "back buffer"))
 	return FALSE;
diff --git a/src/i830_video.c b/src/i830_video.c
index b8726a8..e5efcaa 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -572,7 +572,7 @@ 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) && !IS_G33CLASS(pI830) && pScrn->bitsPerPixel != 8 &&
 	pI830->overlay_regs != NULL)
     {
 	overlayAdaptor = I830SetupImageVideoOverlay(pScreen);
diff-tree 36fcaeb2ef94db5399071540bba106dec3db81d5 (from 8a19e7d57bc23dd163b45e0ab7deca4f074c934d)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Jun 4 15:58:31 2007 -0700

    Fix misplaced merge of 1280x768 panel fixup.

diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index ecc91aa..ee278aa 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -496,7 +496,16 @@ i830_lvds_init(ScrnInfoPtr pScrn)
 	    dev_priv->panel_fixed_mode = i830_crtc_mode_get(pScrn, crtc);
 	    if (dev_priv->panel_fixed_mode != NULL)
 		dev_priv->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.
+     */
+    bios_mode = i830_bios_get_panel_mode(pScrn, &dev_priv->panel_wants_dither);
+    if (bios_mode != NULL) {
+	if (dev_priv->panel_fixed_mode != NULL) {
 	    /* Fixup for a 1280x768 panel with the horizontal trimmed
 	     * down to 1024 for text mode.
 	     */
@@ -512,16 +521,7 @@ i830_lvds_init(ScrnInfoPtr pScrn)
 		dev_priv->panel_fixed_mode->HSyncEnd = 1440;
 		dev_priv->panel_fixed_mode->HTotal = 1688;
 	    }
-	}
-    }
 
-    /* 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.
-     */
-    bios_mode = i830_bios_get_panel_mode(pScrn, &dev_priv->panel_wants_dither);
-    if (bios_mode != NULL) {
-	if (dev_priv->panel_fixed_mode != NULL) {
 	    if (pI830->debug_modes &&
 		!xf86ModesEqual(dev_priv->panel_fixed_mode, bios_mode))
 	    {
diff-tree 8a19e7d57bc23dd163b45e0ab7deca4f074c934d (from e986f6cb62f8644c5fa835bd7dfb7b014c2677c5)
Author: Keith Packard <keithp at dulcimer.keithp.com>
Date:   Tue Jun 5 00:09:57 2007 -0700

    Always ensure the pipe A is lit when activating overlay on pipe B.
    
    Ok, so moving video from pipe A to pipe B still requires that pipe A be
    active during the transition. Instead of trying to be fancy, just ensure
    that pipe A is running on each transition to pipe B.

diff --git a/src/i830_video.c b/src/i830_video.c
index 382b1eb..b8726a8 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -416,18 +416,12 @@ i830_overlay_on(ScrnInfoPtr pScrn)
 	return;
 
     /*
-     * On I830, if pipe A is off the first time the overlay
-     * is enabled, it will fail to turn and blank the entire 
-     * screen. Light up pipe A in this case to provide a clock
-     * for the overlay hardware
+     * On I830, if pipe A is off when the overlayis enabled, it will fail to
+     * turn on and blank the entire screen or lock up the ring. Light up pipe
+     * A in this case to provide a clock for the overlay hardware
      */
-    if (pPriv->current_crtc && 
-	i830_crtc_pipe (pPriv->current_crtc) != 0 &&
-	!pPriv->started_video)
-    {
-	pPriv->started_video = TRUE;
+    if (pPriv->current_crtc && i830_crtc_pipe (pPriv->current_crtc) != 0)
 	deactivate = i830_pipe_a_require_activate (pScrn);
-    }
 
     overlay->OCMD &= ~OVERLAY_ENABLE;
     BEGIN_LP_RING(6);
diff --git a/src/i830_video.h b/src/i830_video.h
index 88a7bd9..7e2d149 100644
--- a/src/i830_video.h
+++ b/src/i830_video.h
@@ -77,7 +77,6 @@ typedef struct {
    int oneLineMode;
    int scaleRatio;
    Bool textured;
-   Bool started_video;
 } I830PortPrivRec, *I830PortPrivPtr;
 
 #define GET_PORT_PRIVATE(pScrn) \
diff-tree e986f6cb62f8644c5fa835bd7dfb7b014c2677c5 (from 0984c1fc0963f1ebab31f5b8fce5ad4c387fbd2c)
Author: Keith Packard <keithp at dulcimer.keithp.com>
Date:   Mon Jun 4 23:52:23 2007 -0700

    Automatically switch overlay when crtcs are reconfigured.
    
    As crtcs are disabled and enabled, make sure the automatic crtc selection
    mechanism drives overlay configuration at each request to display an image.

diff --git a/src/i830_video.c b/src/i830_video.c
index 155bcc1..382b1eb 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -345,27 +345,55 @@ CompareOverlay(I830Ptr pI830, CARD32 * o
 }
 #endif
 
-static int
-I830CrtcPipe (xf86CrtcPtr crtc)
-{
-    if (crtc == NULL)
-	return 0;
-    return ((I830CrtcPrivatePtr) crtc->driver_private)->pipe;
-}
+static void
+I830SetOneLineModeRatio(ScrnInfoPtr pScrn);
 
-static xf86CrtcPtr
-I830CrtcForPipe (ScrnInfoPtr pScrn, int pipe)
+static void
+i830_overlay_switch_to_crtc (ScrnInfoPtr pScrn, xf86CrtcPtr crtc)
 {
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-    int			c;
+    I830Ptr		pI830 = I830PTR(pScrn);
+    I830PortPrivPtr	pPriv = GET_PORT_PRIVATE(pScrn);
+    I830CrtcPrivatePtr  intel_crtc = crtc->driver_private;
+    int			pipeconf_reg = intel_crtc->pipe == 0 ? PIPEACONF : PIPEBCONF;
 
-    for (c = 0; c < xf86_config->num_crtc; c++)
+    if (INREG(pipeconf_reg) & PIPEACONF_DOUBLE_WIDE)
+	pPriv->overlayOK = FALSE;
+    else
+	pPriv->overlayOK = TRUE;
+    
+    if (!pPriv->overlayOK)
+	return;
+
+    /* Check we have an LFP connected */
+    if (i830PipeHasType(crtc, I830_OUTPUT_LVDS)) 
     {
-	xf86CrtcPtr crtc = xf86_config->crtc[c];
-	if (I830CrtcPipe (crtc) == pipe)
-	    return crtc;
+
+	int	vtotal_reg = intel_crtc->pipe ? VTOTAL_A : VTOTAL_B;
+	CARD32	size = intel_crtc->pipe ? INREG(PIPEBSRC) : INREG(PIPEASRC);
+	CARD32	active;
+	CARD32	hsize, vsize;
+
+	hsize = (size >> 16) & 0x7FF;
+	vsize = size & 0x7FF;
+	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));
+
+	    pPriv->scaleRatio = (int)(((float)active * 65536) / (float)vsize);
+	}
     }
-    return NULL;
 }
 
 /*
@@ -383,7 +411,6 @@ i830_overlay_on(ScrnInfoPtr pScrn)
     I830OverlayRegPtr	overlay = I830OVERLAYREG(pI830);
     I830PortPrivPtr	pPriv = pI830->adaptor->pPortPrivates[0].ptr;
     Bool		deactivate = FALSE;
-    xf86CrtcPtr		crtc0 = NULL;
     
     if (*pI830->overlayOn)
 	return;
@@ -633,7 +660,7 @@ I830ResetVideo(ScrnInfoPtr pScrn)
      * Select which pipe the overlay is enabled on.
      */
     overlay->OCONFIG &= ~OVERLAY_PIPE_MASK;
-    if (I830CrtcPipe (pPriv->current_crtc) == 0)
+    if (i830_crtc_pipe (pPriv->current_crtc) == 0)
 	overlay->OCONFIG |= OVERLAY_PIPE_A;
     else 
 	overlay->OCONFIG |= OVERLAY_PIPE_B;
@@ -1717,9 +1744,6 @@ i830_display_video(ScrnInfoPtr pScrn, xf
     OVERLAY_DEBUG("I830DisplayVideo: %dx%d (pitch %d)\n", width, height,
 		  dstPitch);
 
-    if (!pPriv->overlayOK)
-	return;
-
 #if VIDEO_DEBUG
     CompareOverlay(pI830, (CARD32 *) overlay, 0x100);
 #endif
@@ -1737,9 +1761,14 @@ i830_display_video(ScrnInfoPtr pScrn, xf
     if (crtc != pPriv->current_crtc)
     {
         pPriv->current_crtc = crtc;
-        I830ResetVideo (pScrn);
+	i830_overlay_switch_to_crtc (pScrn, crtc);
+	if (pPriv->overlayOK)
+	    I830ResetVideo (pScrn);
     }
 
+    if (!pPriv->overlayOK)
+	return;
+
     switch (crtc->rotation & 0xf) {
     case RR_Rotate_0:
 	dstBox->x1 -= crtc->x;
@@ -2271,7 +2300,7 @@ I830PutImage(ScrnInfoPtr pScrn,
 
     if (pI830->entityPrivate) {
 	if (pI830->entityPrivate->XvInUse != -1 &&
-	    pI830->entityPrivate->XvInUse != I830CrtcPipe (pPriv->current_crtc)) {
+	    pI830->entityPrivate->XvInUse != i830_crtc_pipe (pPriv->current_crtc)) {
 #ifdef PANORAMIX
 	    if (!noPanoramiXExtension) {
 		return Success; /* faked for trying to share it */
@@ -2282,7 +2311,7 @@ I830PutImage(ScrnInfoPtr pScrn,
 	    }
 	}
 
-	pI830->entityPrivate->XvInUse = I830CrtcPipe (pPriv->current_crtc);;
+	pI830->entityPrivate->XvInUse = i830_crtc_pipe (pPriv->current_crtc);;
     }
 
     /* overlay limits */
@@ -2766,7 +2795,7 @@ I830DisplaySurface(XF86SurfacePtr surfac
 
     if (pI830->entityPrivate) {
 	if (pI830->entityPrivate->XvInUse != -1 &&
-	    pI830->entityPrivate->XvInUse != I830CrtcPipe (pI830Priv->current_crtc)) {
+	    pI830->entityPrivate->XvInUse != i830_crtc_pipe (pI830Priv->current_crtc)) {
 #ifdef PANORAMIX
 	    if (!noPanoramiXExtension) {
 		return Success; /* faked for trying to share it */
@@ -2777,7 +2806,7 @@ I830DisplaySurface(XF86SurfacePtr surfac
 	    }
 	}
 
-	pI830->entityPrivate->XvInUse = I830CrtcPipe (pI830Priv->current_crtc);
+	pI830->entityPrivate->XvInUse = i830_crtc_pipe (pI830Priv->current_crtc);
     }
 
     x1 = src_x;
@@ -2861,7 +2890,6 @@ i830_crtc_dpms_video(xf86CrtcPtr crtc, B
     ScrnInfoPtr pScrn = crtc->scrn;
     I830Ptr pI830 = I830PTR(pScrn);
     I830PortPrivPtr pPriv;
-    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
 
     if (pI830->adaptor == NULL)
 	return;
@@ -2872,53 +2900,12 @@ i830_crtc_dpms_video(xf86CrtcPtr crtc, B
 
     pPriv = GET_PORT_PRIVATE(pScrn);
 
-    /* Check if it's the crtc the overlay is on */
     if (crtc != pPriv->current_crtc)
 	return;
 
+    /* Check if it's the crtc the overlay is on */
     if (on) {
-	int size, hsize, vsize, active;
-	int pipeconf_reg = intel_crtc->pipe == 0 ? PIPEACONF : PIPEBCONF;
-	char pipename = intel_crtc->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(crtc, I830_OUTPUT_LVDS)) {
-	    int vtotal_reg = intel_crtc->pipe ? VTOTAL_A : VTOTAL_B;
-	    size = intel_crtc->pipe ? INREG(PIPEBSRC) : INREG(PIPEASRC);
-	    hsize = (size >> 16) & 0x7FF;
-	    vsize = size & 0x7FF;
-	    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));
-
-		pPriv->scaleRatio = (int)(((float)active * 65536) / (float)vsize);
-	    }
-	}
+	i830_overlay_switch_to_crtc (pScrn, crtc);
     } 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
diff-tree 0984c1fc0963f1ebab31f5b8fce5ad4c387fbd2c (from 88ee25ebad78e54d243d728b775a69365359b5fb)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Thu May 31 10:17:26 2007 +0800

    Add pci ids for 945GME

diff --git a/src/common.h b/src/common.h
index 6aa0412..c879333 100644
--- a/src/common.h
+++ b/src/common.h
@@ -331,6 +331,7 @@ extern int I810_DEBUG;
 
 #ifndef PCI_CHIP_I945_GM
 #define PCI_CHIP_I945_GM        0x27A2
+#define PCI_CHIP_I945_GME	0x27AE
 #define PCI_CHIP_I945_GM_BRIDGE 0x27A0
 #endif
 
@@ -374,7 +375,7 @@ extern int I810_DEBUG;
 #define IS_I915G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I915_G || pI810->PciInfo->chipType == PCI_CHIP_E7221_G)
 #define IS_I915GM(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I915_GM)
 #define IS_I945G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I945_G)
-#define IS_I945GM(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I945_GM)
+#define IS_I945GM(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I945_GM || pI810->PciInfo->chipType == PCI_CHIP_I945_GME)
 #define IS_I965GM(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I965_GM || pI810->PciInfo->chipType == PCI_CHIP_I965_GME)
 #define IS_I965G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I965_G || pI810->PciInfo->chipType == PCI_CHIP_I965_G_1 || pI810->PciInfo->chipType == PCI_CHIP_I965_Q || pI810->PciInfo->chipType == PCI_CHIP_I946_GZ || pI810->PciInfo->chipType == PCI_CHIP_I965_GM || pI810->PciInfo->chipType == PCI_CHIP_I965_GME)
 #define IS_I9XX(pI810) (IS_I915G(pI810) || IS_I915GM(pI810) || IS_I945G(pI810) || IS_I945GM(pI810) || IS_I965G(pI810))
diff --git a/src/i810_driver.c b/src/i810_driver.c
index 6b6dd25..5b04a47 100644
--- a/src/i810_driver.c
+++ b/src/i810_driver.c
@@ -140,6 +140,7 @@ static SymTabRec I810Chipsets[] = {
    {PCI_CHIP_I915_GM,		"915GM"},
    {PCI_CHIP_I945_G,		"945G"},
    {PCI_CHIP_I945_GM,		"945GM"},
+   {PCI_CHIP_I945_GME,		"945GME"},
    {PCI_CHIP_I965_G,		"965G"},
    {PCI_CHIP_I965_G_1,		"965G"},
    {PCI_CHIP_I965_Q,		"965Q"},
@@ -165,6 +166,7 @@ static PciChipsets I810PciChipsets[] = {
    {PCI_CHIP_I915_GM,		PCI_CHIP_I915_GM,	RES_SHARED_VGA},
    {PCI_CHIP_I945_G,		PCI_CHIP_I945_G,	RES_SHARED_VGA},
    {PCI_CHIP_I945_GM,		PCI_CHIP_I945_GM,	RES_SHARED_VGA},
+   {PCI_CHIP_I945_GME,		PCI_CHIP_I945_GME,	RES_SHARED_VGA},
    {PCI_CHIP_I965_G,		PCI_CHIP_I965_G,	RES_SHARED_VGA},
    {PCI_CHIP_I965_G_1,		PCI_CHIP_I965_G_1,	RES_SHARED_VGA},
    {PCI_CHIP_I965_Q,		PCI_CHIP_I965_Q,	RES_SHARED_VGA},
@@ -611,6 +613,7 @@ I810Probe(DriverPtr drv, int flags)
 	    case PCI_CHIP_I915_GM:
 	    case PCI_CHIP_I945_G:
 	    case PCI_CHIP_I945_GM:
+	    case PCI_CHIP_I945_GME:
 	    case PCI_CHIP_I965_G:
 	    case PCI_CHIP_I965_G_1:
 	    case PCI_CHIP_I965_Q:
diff --git a/src/i830_driver.c b/src/i830_driver.c
index f5c9d32..1290d6d 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -229,6 +229,7 @@ static SymTabRec I830Chipsets[] = {
    {PCI_CHIP_I915_GM,		"915GM"},
    {PCI_CHIP_I945_G,		"945G"},
    {PCI_CHIP_I945_GM,		"945GM"},
+   {PCI_CHIP_I945_GME,		"945GME"},
    {PCI_CHIP_I965_G,		"965G"},
    {PCI_CHIP_I965_G_1,		"965G"},
    {PCI_CHIP_I965_Q,		"965Q"},
@@ -248,6 +249,7 @@ static PciChipsets I830PciChipsets[] = {
    {PCI_CHIP_I915_GM,		PCI_CHIP_I915_GM,	RES_SHARED_VGA},
    {PCI_CHIP_I945_G,		PCI_CHIP_I945_G,	RES_SHARED_VGA},
    {PCI_CHIP_I945_GM,		PCI_CHIP_I945_GM,	RES_SHARED_VGA},
+   {PCI_CHIP_I945_GME,		PCI_CHIP_I945_GME,	RES_SHARED_VGA},
    {PCI_CHIP_I965_G,		PCI_CHIP_I965_G,	RES_SHARED_VGA},
    {PCI_CHIP_I965_G_1,		PCI_CHIP_I965_G_1,	RES_SHARED_VGA},
    {PCI_CHIP_I965_Q,		PCI_CHIP_I965_Q,	RES_SHARED_VGA},
@@ -1055,6 +1057,9 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    case PCI_CHIP_I945_GM:
       chipname = "945GM";
       break;
+   case PCI_CHIP_I945_GME:
+      chipname = "945GME";
+      break;
    case PCI_CHIP_I965_G:
    case PCI_CHIP_I965_G_1:
       chipname = "965G";
diff-tree 88ee25ebad78e54d243d728b775a69365359b5fb (from 92e4deb50e049cc83cbde4995ba0b901feceb15a)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Thu May 31 10:13:30 2007 +0800

    Add pci ids for 965GME/GLE chip

diff --git a/src/common.h b/src/common.h
index f45fc8e..6aa0412 100644
--- a/src/common.h
+++ b/src/common.h
@@ -356,6 +356,7 @@ extern int I810_DEBUG;
 
 #ifndef PCI_CHIP_I965_GM
 #define PCI_CHIP_I965_GM        0x2A02
+#define PCI_CHIP_I965_GME	0x2A12
 #define PCI_CHIP_I965_GM_BRIDGE 0x2A00
 #endif
 
@@ -374,8 +375,8 @@ extern int I810_DEBUG;
 #define IS_I915GM(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I915_GM)
 #define IS_I945G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I945_G)
 #define IS_I945GM(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I945_GM)
-#define IS_I965GM(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I965_GM)
-#define IS_I965G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I965_G || pI810->PciInfo->chipType == PCI_CHIP_I965_G_1 || pI810->PciInfo->chipType == PCI_CHIP_I965_Q || pI810->PciInfo->chipType == PCI_CHIP_I946_GZ || pI810->PciInfo->chipType == PCI_CHIP_I965_GM)
+#define IS_I965GM(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I965_GM || pI810->PciInfo->chipType == PCI_CHIP_I965_GME)
+#define IS_I965G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I965_G || pI810->PciInfo->chipType == PCI_CHIP_I965_G_1 || pI810->PciInfo->chipType == PCI_CHIP_I965_Q || pI810->PciInfo->chipType == PCI_CHIP_I946_GZ || pI810->PciInfo->chipType == PCI_CHIP_I965_GM || pI810->PciInfo->chipType == PCI_CHIP_I965_GME)
 #define IS_I9XX(pI810) (IS_I915G(pI810) || IS_I915GM(pI810) || IS_I945G(pI810) || IS_I945GM(pI810) || IS_I965G(pI810))
 
 #define IS_MOBILE(pI810) (IS_I830(pI810) || IS_I85X(pI810) || IS_I915GM(pI810) || IS_I945GM(pI810) || IS_I965GM(pI810))
diff --git a/src/i810_driver.c b/src/i810_driver.c
index baca21c..6b6dd25 100644
--- a/src/i810_driver.c
+++ b/src/i810_driver.c
@@ -145,6 +145,7 @@ static SymTabRec I810Chipsets[] = {
    {PCI_CHIP_I965_Q,		"965Q"},
    {PCI_CHIP_I946_GZ,		"946GZ"},
    {PCI_CHIP_I965_GM,		"965GM"},
+   {PCI_CHIP_I965_GME,		"965GME/GLE"},
    {-1,				NULL}
 };
 
@@ -169,6 +170,7 @@ static PciChipsets I810PciChipsets[] = {
    {PCI_CHIP_I965_Q,		PCI_CHIP_I965_Q,	RES_SHARED_VGA},
    {PCI_CHIP_I946_GZ,		PCI_CHIP_I946_GZ,	RES_SHARED_VGA},
    {PCI_CHIP_I965_GM,		PCI_CHIP_I965_GM,	RES_SHARED_VGA},
+   {PCI_CHIP_I965_GME,		PCI_CHIP_I965_GME,	RES_SHARED_VGA},
    {-1,				-1, RES_UNDEFINED }
 };
 
@@ -614,6 +616,7 @@ I810Probe(DriverPtr drv, int flags)
 	    case PCI_CHIP_I965_Q:
 	    case PCI_CHIP_I946_GZ:
 	    case PCI_CHIP_I965_GM:
+	    case PCI_CHIP_I965_GME:
     	       xf86SetEntitySharable(usedChips[i]);
 
     	       /* Allocate an entity private if necessary */		
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 8e74903..f5c9d32 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -234,6 +234,7 @@ static SymTabRec I830Chipsets[] = {
    {PCI_CHIP_I965_Q,		"965Q"},
    {PCI_CHIP_I946_GZ,		"946GZ"},
    {PCI_CHIP_I965_GM,		"965GM"},
+   {PCI_CHIP_I965_GME,		"965GME/GLE"},
    {-1,				NULL}
 };
 
@@ -252,6 +253,7 @@ static PciChipsets I830PciChipsets[] = {
    {PCI_CHIP_I965_Q,		PCI_CHIP_I965_Q,	RES_SHARED_VGA},
    {PCI_CHIP_I946_GZ,		PCI_CHIP_I946_GZ,	RES_SHARED_VGA},
    {PCI_CHIP_I965_GM,		PCI_CHIP_I965_GM,	RES_SHARED_VGA},
+   {PCI_CHIP_I965_GME,		PCI_CHIP_I965_GME,	RES_SHARED_VGA},
    {-1,				-1,			RES_UNDEFINED}
 };
 
@@ -1066,6 +1068,9 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    case PCI_CHIP_I965_GM:
       chipname = "965GM";
       break;
+   case PCI_CHIP_I965_GME:
+      chipname = "965GME/GLE";
+      break;
    default:
       chipname = "unknown chipset";
       break;
diff-tree 92e4deb50e049cc83cbde4995ba0b901feceb15a (from 888a4a5f469bf955e3ee3e184b628808ae8a4498)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Wed May 30 11:49:07 2007 -0600

    Extend XV_PIPE range to include new -1 value

diff --git a/src/i830_video.c b/src/i830_video.c
index 4517975..155bcc1 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -229,7 +229,7 @@ static XF86VideoFormatRec Formats[NUM_FO
 
 #define CLONE_ATTRIBUTES 1
 static XF86AttributeRec CloneAttributes[CLONE_ATTRIBUTES] = {
-    {XvSettable | XvGettable, 0, 1, "XV_PIPE"}
+    {XvSettable | XvGettable, -1, 1, "XV_PIPE"}
 };
 
 #define NUM_ATTRIBUTES 5
diff-tree 888a4a5f469bf955e3ee3e184b628808ae8a4498 (from 516fb73ffee0aea7cf892e6703d37f8ecf52b812)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed May 30 14:42:35 2007 +0800

    Fix i965 render's draw clip rectangle
    
    Use scrn's virtual size is not correct in rotation rendering.
    This fixes initial rotation problem on i965.

diff --git a/src/i965_render.c b/src/i965_render.c
index 848774e..956baf3 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -945,8 +945,8 @@ i965_prepare_composite(int op, PicturePt
 	 */
    	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(DRAW_YMAX(pDst->drawable.height - 1) |
+		 DRAW_XMAX(pDst->drawable.width - 1)); /* ymax, xmax */
    	OUT_RING(0x00000000);	/* yorigin, xorigin */
 
 	/* skip the depth buffer */
diff-tree 516fb73ffee0aea7cf892e6703d37f8ecf52b812 (from 72462568da589054828b72ace83232a71636ee73)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue May 29 10:22:25 2007 -0700

    Remove README statement that 830M panels are unsupported.

diff --git a/README b/README
index f209baa..bcb0205 100644
--- a/README
+++ b/README
@@ -57,11 +57,6 @@ options.
 
 
 Known Limitations
-- Bug #8534: i830 laptop panels not supported.  The driver
-  will fail to recognize them, and only function through VGA output.  Two
-  partial DVO chip drivers (ivch and ch7017) are included which contain some of
-  the code necessary for i830 laptop panel support, but some I2C debugging will
-  be necessary to get those drivers to attach.
 - No support for "zaphod mode" dualhead.  This is the mode in which two
   Device sections are placed in the config file, and doesn't support DRI or
   many other features.  Instead, only "MergedFB-style" dualhead is supported.
diff-tree 72462568da589054828b72ace83232a71636ee73 (from 906b974bfeeed18d79c244ad3db4f5d30e13e4c8)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue May 29 10:21:12 2007 -0700

    Expand manpage description of outputs supported.

diff --git a/man/intel.man b/man/intel.man
index daf9030..8991619 100644
--- a/man/intel.man
+++ b/man/intel.man
@@ -168,11 +168,28 @@ Enable printing of additional debugging 
 the server log.
 
 .PP
-The 830M and newer driver supports RandR 1.2, exposing the VGA, LVDS
-(laptop panel), TMDS (DVI on SDVO/DVO cards), and TV (on 915GM/945GM)
-outputs.  Per-output configuration is done through the
-.B Monitor
-section of __xconfigfile__(__filemansuffix__).
+The 830M and newer driver supports the following outputs through RandR 1.2:
+.PP
+.TP
+.BI "VGA"
+Analog VGA output
+.TP
+.BI "LVDS"
+Laptop panel
+.TP
+.BI "TV"
+Integrated TV output
+.TP
+.BI "TMDS-1"
+First DVI SDVO output
+.TP
+.BI "TMDS-2"
+Second DVI SDVO output
+.PP
+SDVO and DVO TV outputs are not supported by the driver at this time.
+.PP
+See __xconfigfile__(__filemansuffix__) for information on associating Monitor
+sections with these outputs for configuration.
 
 .SH "SEE ALSO"
 __xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), xorgconfig(__appmansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__)
diff-tree 906b974bfeeed18d79c244ad3db4f5d30e13e4c8 (from 4b2781291844b61b397e257a0fdb43e964e5f603)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue May 29 09:49:08 2007 -0700

    Add a fixup to LVDS panel mode detection for 1280x768 panel from text mode.
    
    Apparently some BIOSes will program a small mode with large blanking instead of
    using the pannel fitter.

diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index 566c868..ecc91aa 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -496,6 +496,22 @@ i830_lvds_init(ScrnInfoPtr pScrn)
 	    dev_priv->panel_fixed_mode = i830_crtc_mode_get(pScrn, crtc);
 	    if (dev_priv->panel_fixed_mode != NULL)
 		dev_priv->panel_fixed_mode->type |= M_T_PREFERRED;
+
+	    /* Fixup for a 1280x768 panel with the horizontal trimmed
+	     * down to 1024 for text mode.
+	     */
+	    if (!xf86ModesEqual(dev_priv->panel_fixed_mode, bios_mode) &&
+		dev_priv->panel_fixed_mode->HDisplay == 1024 &&
+		dev_priv->panel_fixed_mode->HSyncStart == 1200 &&
+		dev_priv->panel_fixed_mode->HSyncEnd == 1312 &&
+		dev_priv->panel_fixed_mode->HTotal == 1688 &&
+		dev_priv->panel_fixed_mode->VDisplay == 768)
+	    {
+		dev_priv->panel_fixed_mode->HDisplay = 1280;
+		dev_priv->panel_fixed_mode->HSyncStart = 1328;
+		dev_priv->panel_fixed_mode->HSyncEnd = 1440;
+		dev_priv->panel_fixed_mode->HTotal = 1688;
+	    }
 	}
     }
 
diff-tree 4b2781291844b61b397e257a0fdb43e964e5f603 (from 2a365eab0178c28782fba97bdd22365f30ce8963)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Sat May 26 10:09:11 2007 -0700

    Mark IVCH as connected when detected

diff --git a/src/ivch/ivch.c b/src/ivch/ivch.c
index e0755c0..eac878e 100644
--- a/src/ivch/ivch.c
+++ b/src/ivch/ivch.c
@@ -219,7 +219,7 @@ ivch_setup (I2CDevPtr d, xf86OutputPtr o
 static xf86OutputStatus
 ivch_detect(I2CDevPtr d)
 {
-    return XF86OutputStatusUnknown;
+    return XF86OutputStatusConnected;
 }
 
 static DisplayModePtr
diff-tree 2a365eab0178c28782fba97bdd22365f30ce8963 (from ff8c8cb869a3c780dbd826f7c94f06e4f3fda6af)
Author: Keith Packard <keithp at dulcimer.keithp.com>
Date:   Sun May 27 12:35:55 2007 -0700

    On i830, Pipe B cannot be lit the first time unless Pipe A is running.
    
    I don't understand it, but just like the video overlay, if Pipe A is not
    running, Pipe B will not turn the first time it is activated. This
    patch restructures the code used for the video overlay to share it
    with the crtc commit function.

diff --git a/src/i830.h b/src/i830.h
index 35f8192..76cc6e8 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -216,6 +216,8 @@ extern const char *i830_output_type_name
 typedef struct _I830CrtcPrivateRec {
     int			    pipe;
 
+    Bool    		    enabled;
+    
     /* Lookup table values to be set when the CRTC is enabled */
     CARD8 lut_r[256], lut_g[256], lut_b[256];
 
@@ -579,6 +581,15 @@ extern void I830InitVideo(ScreenPtr pScr
 extern void i830_crtc_dpms_video(xf86CrtcPtr crtc, Bool on);
 #endif
 
+int
+i830_crtc_pipe (xf86CrtcPtr crtc);
+
+Bool
+i830_pipe_a_require_activate (ScrnInfoPtr scrn);
+
+void
+i830_pipe_a_require_deactivate (ScrnInfoPtr scrn);
+
 #ifdef XF86DRI
 extern Bool I830Allocate3DMemory(ScrnInfoPtr pScrn, const int flags);
 extern void I830SetupMemoryTiling(ScrnInfoPtr pScrn);
diff --git a/src/i830_display.c b/src/i830_display.c
index 023a1aa..adc7479 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -429,6 +429,76 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x,
 #endif
 }
 
+/*
+ * Both crtc activation and video overlay enablement on pipe B
+ * will fail on i830 if pipe A is not running. This function
+ * makes sure pipe A is active for these cases
+ */
+
+int
+i830_crtc_pipe (xf86CrtcPtr crtc)
+{
+    if (crtc == NULL)
+	return 0;
+    return ((I830CrtcPrivatePtr) crtc->driver_private)->pipe;
+}
+
+static xf86CrtcPtr
+i830_crtc_for_pipe (ScrnInfoPtr scrn, int pipe)
+{
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+    int			c;
+
+    for (c = 0; c < xf86_config->num_crtc; c++)
+    {
+	xf86CrtcPtr crtc = xf86_config->crtc[c];
+	if (i830_crtc_pipe (crtc) == pipe)
+	    return crtc;
+    }
+    return NULL;
+}
+
+Bool
+i830_pipe_a_require_activate (ScrnInfoPtr scrn)
+{
+    xf86CrtcPtr	crtc = i830_crtc_for_pipe (scrn, 0);
+    /* 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 (!crtc)
+	return FALSE;
+    if (crtc->enabled)
+	return FALSE;
+    xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
+    crtc->funcs->mode_set (crtc, &mode, &mode, 0, 0);
+    crtc->funcs->dpms (crtc, DPMSModeOn);
+    return TRUE;
+}
+
+void
+i830_pipe_a_require_deactivate (ScrnInfoPtr scrn)
+{
+    xf86CrtcPtr	crtc = i830_crtc_for_pipe (scrn, 0);
+
+    if (!crtc)
+	return;
+    if (crtc->enabled)
+	return;
+    crtc->funcs->dpms (crtc, DPMSModeOff);
+    return;
+}
+
+
 /**
  * Sets the power management mode of the pipe and plane.
  *
@@ -593,9 +663,19 @@ i830_crtc_prepare (xf86CrtcPtr crtc)
 static void
 i830_crtc_commit (xf86CrtcPtr crtc)
 {
+    I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
+    Bool		deactivate = FALSE;
+
+    if (!intel_crtc->enabled && intel_crtc->pipe != 0)
+	deactivate = i830_pipe_a_require_activate (crtc->scrn);
+    
+    intel_crtc->enabled = TRUE;
+    
     crtc->funcs->dpms (crtc, DPMSModeOn);
     if (crtc->scrn->pScreen != NULL)
 	xf86_reload_cursors (crtc->scrn->pScreen);
+    if (deactivate)
+	i830_pipe_a_require_deactivate (crtc->scrn);
 }
 
 void
diff --git a/src/i830_video.c b/src/i830_video.c
index d57519b..4517975 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -382,6 +382,7 @@ i830_overlay_on(ScrnInfoPtr pScrn)
     I830Ptr		pI830 = I830PTR(pScrn);
     I830OverlayRegPtr	overlay = I830OVERLAYREG(pI830);
     I830PortPrivPtr	pPriv = pI830->adaptor->pPortPrivates[0].ptr;
+    Bool		deactivate = FALSE;
     xf86CrtcPtr		crtc0 = NULL;
     
     if (*pI830->overlayOn)
@@ -393,30 +394,12 @@ i830_overlay_on(ScrnInfoPtr pScrn)
      * screen. Light up pipe A in this case to provide a clock
      * for the overlay hardware
      */
-    if (!pPriv->started_video)
+    if (pPriv->current_crtc && 
+	i830_crtc_pipe (pPriv->current_crtc) != 0 &&
+	!pPriv->started_video)
     {
 	pPriv->started_video = TRUE;
-	crtc0 = I830CrtcForPipe (pScrn, 0);
-	if (!crtc0->enabled)
-	{
-	    /* 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
-	    };
-	    xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
-	    crtc0->funcs->mode_set (crtc0, &mode, &mode, 0, 0);
-	    crtc0->funcs->dpms (crtc0, DPMSModeOn);
-	}
-	else
-	    crtc0 = NULL;
+	deactivate = i830_pipe_a_require_activate (pScrn);
     }
 
     overlay->OCMD &= ~OVERLAY_ENABLE;
@@ -435,8 +418,8 @@ i830_overlay_on(ScrnInfoPtr pScrn)
      * If we turned pipe A on up above, turn it
      * back off
      */
-    if (crtc0)
-	crtc0->funcs->dpms (crtc0, DPMSModeOff);
+    if (deactivate)
+	i830_pipe_a_require_deactivate (pScrn);
 
     OVERLAY_DEBUG("overlay_on\n");
     *pI830->overlayOn = TRUE;
diff-tree ff8c8cb869a3c780dbd826f7c94f06e4f3fda6af (from 33f635d79fe891079558fd909d564f3cf424c482)
Author: Keith Packard <keithp at dulcimer.keithp.com>
Date:   Fri May 25 20:29:59 2007 -0700

    Compute and clip to crtc before call to xf86XVClipVideoHelper.
    
    By clipping to the crtc ahead of time, xf86XVClipVideoHelper will
    correctly clip to the bounds of the crtc, eliminating the need for any
    custom crtc clipping.
    
    Also, replace the broken xf86XVFillKeyHelper with a private version that
    doesn't end up stuck with the wrong clip list when the root window changes
    size.

diff --git a/src/i830_video.c b/src/i830_video.c
index c2d3b4b..d57519b 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -1636,38 +1636,35 @@ UpdateCoeff(int taps, double fCutoff, Bo
     }
 }
 
-/*
- * Return the number of pixels from 'box' covered by 'crtc'.
- * That is, the area of the intersection of 'box' and 'crtc'
- */
-static int
-I830CrtcBoxCoverage (xf86CrtcPtr crtc, BoxPtr box)
+static void
+i830_box_intersect (BoxPtr dest, BoxPtr a, BoxPtr b)
 {
-    BoxRec   dest;
-    BoxRec   pipe;
+    dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1;
+    dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2;
+    dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1;
+    dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2;
+    if (dest->x1 >= dest->x2 || dest->y1 >= dest->y2)
+	dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0;
+}
 
+static void
+i830_crtc_box (xf86CrtcPtr crtc, BoxPtr crtc_box)
+{
     if (crtc->enabled)
     {
-	pipe.x1 = crtc->x;
-	pipe.x2 = crtc->x + xf86ModeWidth (&crtc->mode, crtc->rotation);
-	pipe.y1 = crtc->y;
-	pipe.y2 = crtc->y + xf86ModeHeight (&crtc->mode, crtc->rotation);
+	crtc_box->x1 = crtc->x;
+	crtc_box->x2 = crtc->x + xf86ModeWidth (&crtc->mode, crtc->rotation);
+	crtc_box->y1 = crtc->y;
+	crtc_box->y2 = crtc->y + xf86ModeHeight (&crtc->mode, crtc->rotation);
     }
     else
-    {
-	pipe.x1 = pipe.x2 = 0;
-	pipe.y1 = pipe.y2 = 0;
-    }
-    dest.x1 = pipe.x1 > box->x1 ? pipe.x1 : box->x1;
-    dest.x2 = pipe.x2 < box->x2 ? pipe.x2 : box->x2;
-    dest.y1 = pipe.y1 > box->y1 ? pipe.y1 : box->y1;
-    dest.y2 = pipe.y2 < box->y2 ? pipe.y2 : box->y2;
-    if (dest.x1 >= dest.x2 || dest.y1 >= dest.y2)
-    {
-	dest.x1 = dest.x2 = 0;
-	dest.y1 = dest.y2 = 0;
-    }
-    return (int) (dest.x2 - dest.x1) * (int) (dest.y2 - dest.y1);
+	crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0;
+}
+
+static int
+i830_box_area (BoxPtr box)
+{
+    return (int) (box->x2 - box->x1) * (int) (box->y2 - box->y1);
 }
 
 /*
@@ -1677,21 +1674,28 @@ I830CrtcBoxCoverage (xf86CrtcPtr crtc, B
  */
 
 static xf86CrtcPtr
-I830CoveringCrtc (ScrnInfoPtr pScrn, BoxPtr pBox, xf86CrtcPtr desired)
+i830_covering_crtc (ScrnInfoPtr pScrn,
+		    BoxPtr	box,
+		    xf86CrtcPtr desired,
+		    BoxPtr	crtc_box_ret)
 {
     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     xf86CrtcPtr		crtc, best_crtc;
     int			coverage, best_coverage;
     int			c;
+    BoxRec		crtc_box, cover_box;
 
     best_crtc = NULL;
     best_coverage = 0;
     for (c = 0; c < xf86_config->num_crtc; c++)
     {
 	crtc = xf86_config->crtc[c];
-	coverage = I830CrtcBoxCoverage (crtc, pBox);
+	i830_crtc_box (crtc, &crtc_box);
+	i830_box_intersect (&cover_box, &crtc_box, box);
+	coverage = i830_box_area (&cover_box);
 	if (coverage > best_coverage)
 	{
+	    *crtc_box_ret = crtc_box;
 	    if (crtc == desired)
 		return crtc;
 	    best_crtc = crtc;
@@ -1713,19 +1717,19 @@ i830_swidth (I830Ptr pI830, unsigned int
 }
 
 static void
-I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height,
-		 int dstPitch, int x1, int y1, int x2, int y2, BoxPtr dstBox,
-		 short src_w, short src_h, short drw_w, short drw_h)
+i830_display_video(ScrnInfoPtr pScrn, xf86CrtcPtr crtc,
+		   int id, short width, short height,
+		   int dstPitch, int x1, int y1, int x2, int y2, BoxPtr dstBox,
+		   short src_w, short src_h, short drw_w, short drw_h)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
-    I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr;
+    I830Ptr		pI830 = I830PTR(pScrn);
+    I830PortPrivPtr	pPriv = pI830->adaptor->pPortPrivates[0].ptr;
     I830OverlayRegPtr	overlay = I830OVERLAYREG(pI830);
-    unsigned int swidth, swidthy, swidthuv;
-    unsigned int mask, shift, offsety, offsetu;
-    xf86CrtcPtr crtc;
-    int		tmp;
-    CARD32	OCMD;
-    Bool	scaleChanged = FALSE;
+    unsigned int	swidth, swidthy, swidthuv;
+    unsigned int	mask, shift, offsety, offsetu;
+    int			tmp;
+    CARD32		OCMD;
+    Bool		scaleChanged = FALSE;
 
     OVERLAY_DEBUG("I830DisplayVideo: %dx%d (pitch %d)\n", width, height,
 		  dstPitch);
@@ -1736,23 +1740,23 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
 #if VIDEO_DEBUG
     CompareOverlay(pI830, (CARD32 *) overlay, 0x100);
 #endif
-
-    crtc = I830CoveringCrtc (pScrn, dstBox, pPriv->desired_crtc);
-    if (crtc != pPriv->current_crtc)
-    {
-        pPriv->current_crtc = crtc;
-        I830ResetVideo (pScrn);
-    }
-
+    
     /*
      * If the video isn't visible on any CRTC, turn it off
      */
     if (!crtc)
     {
+	pPriv->current_crtc = NULL;
 	i830_overlay_off (pScrn);
 	return;
     }
     
+    if (crtc != pPriv->current_crtc)
+    {
+        pPriv->current_crtc = crtc;
+        I830ResetVideo (pScrn);
+    }
+
     switch (crtc->rotation & 0xf) {
     case RR_Rotate_0:
 	dstBox->x1 -= crtc->x;
@@ -1792,44 +1796,6 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
 	break;
     }
 
-    /* Fix up the dstBox if outside the visible screen */
-    {
-	int offset_x = (dstBox->x1 < 0) ? -dstBox->x1 : 0;
-	int offset_y = (dstBox->y1 < 0) ? -dstBox->y1 : 0;
-	int offset, offset2;
-
-	/* align */
-	offset_x = (offset_x + 3) & ~3;
-	offset_y = (offset_y + 3) & ~3;
-
-	if (crtc->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
-	    height -= offset_x;
-	    width -= offset_y;
-	} else {
-	    height -= offset_y;
-	    width -= offset_x;
-	}
-
-	if (id == FOURCC_I420 || id == FOURCC_YV12) {
-	    offset = ((offset_x/2) + (dstPitch * offset_y)) * 2;
-	    offset2 = ((offset_x/2) + ((dstPitch/2) * offset_y));
-	} else {
-	    offset = ((offset_x*2) + (dstPitch * offset_y));
-	    offset2 = ((offset_x*2) + ((dstPitch/2) * offset_y));
-	}
-
-	/* buffer locations */
-	pPriv->YBuf0offset += offset;
-	pPriv->UBuf0offset += offset2;
-	pPriv->VBuf0offset += offset2;
-
-	if(pPriv->doubleBuffer) {
-	    pPriv->YBuf1offset += offset;
-	    pPriv->UBuf1offset += offset2;
-	    pPriv->VBuf1offset += offset2;
-	}
-    }
-
     if (crtc->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
 	tmp = width;
 	width = height;
@@ -1851,32 +1817,6 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
 	drw_h = ((drw_h * pPriv->scaleRatio) >> 16) + 1;
     }
 
-    {
-	/* Keep the engine happy and clip to the real vertical size just
-	 * in case an LFP is in use and it's not at it's native resolution.
-	 */
-	int vactive = I830CrtcPipe (pPriv->current_crtc) ? (INREG(VTOTAL_B) & 0x7FF) : (INREG(VTOTAL_A) & 0x7FF);
-	int hactive = pPriv->current_crtc->mode.HDisplay;
-
-	vactive += 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 (dstBox->y1 > vactive) dstBox->y1 = vactive;
-	if (dstBox->y2 > vactive) dstBox->y2 = vactive;
-	if (dstBox->x1 > hactive) dstBox->x1 = hactive;
-	if (dstBox->x2 > hactive) dstBox->x2 = hactive;
-
-	/* nothing do to */
-	if (dstBox->x2 - dstBox->x1 <= 2 || dstBox->y2 - dstBox->y1 < N_VERT_Y_TAPS)
-	{
-	    OVERLAY_DEBUG("NOTHING TO DO\n");
-	    return;
-	}
-    }
-
     if (IS_I9XX(pI830)) {
 	shift = 6;
 	mask = 0x3f;
@@ -2220,6 +2160,84 @@ I830FreeMemory(ScrnInfoPtr pScrn, struct
     linear->offset = 0;
 }
 
+static Bool
+i830_clip_video_helper (ScrnInfoPtr pScrn,
+			xf86CrtcPtr *crtc_ret,
+			BoxPtr	    dst,
+			INT32	    *xa,
+			INT32	    *xb,
+			INT32	    *ya,
+			INT32	    *yb,
+			RegionPtr   reg,
+			INT32	    width,
+			INT32	    height)
+{
+    Bool	ret;
+    RegionRec	crtc_region_local;
+    RegionPtr	crtc_region = reg;
+    
+    /*
+     * For overlay video, compute the relevant CRTC and
+     * clip video to that
+     */
+    if (crtc_ret)
+    {
+	I830Ptr		pI830 = I830PTR(pScrn);
+	I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr;
+	BoxRec		crtc_box;
+	xf86CrtcPtr	crtc = i830_covering_crtc (pScrn, dst,
+						   pPriv->desired_crtc,
+						   &crtc_box);
+	
+	if (crtc)
+	{
+	    REGION_INIT (pScreen, &crtc_region_local, &crtc_box, 1);
+	    crtc_region = &crtc_region_local;
+	    REGION_INTERSECT (pScreen, crtc_region, crtc_region, reg);
+	}
+	*crtc_ret = crtc;
+    }
+    ret = xf86XVClipVideoHelper (dst, xa, xb, ya, yb, 
+				 crtc_region, width, height);
+    if (crtc_region != reg)
+	REGION_UNINIT (pScreen, &crtc_region_local);
+    return ret;
+}
+
+static void
+i830_fill_colorkey (ScreenPtr pScreen, CARD32 key, RegionPtr clipboxes)
+{
+   DrawablePtr root = &WindowTable[pScreen->myNum]->drawable;
+   XID	       pval[2];
+   BoxPtr      pbox = REGION_RECTS(clipboxes);
+   int	       i, nbox = REGION_NUM_RECTS(clipboxes);
+   xRectangle  *rects;
+   GCPtr       gc;
+
+   if(!xf86Screens[pScreen->myNum]->vtSema) return;
+
+   gc = GetScratchGC(root->depth, pScreen);
+   pval[0] = key;
+   pval[1] = IncludeInferiors;
+   (void) ChangeGC(gc, GCForeground|GCSubwindowMode, pval);
+   ValidateGC(root, gc);
+
+   rects = xalloc (nbox * sizeof(xRectangle));
+
+   for(i = 0; i < nbox; i++, pbox++) 
+   {
+      rects[i].x = pbox->x1;
+      rects[i].y = pbox->y1;
+      rects[i].width = pbox->x2 - pbox->x1;
+      rects[i].height = pbox->y2 - pbox->y1;
+   }
+   
+   (*gc->ops->PolyFillRect)(root, gc, nbox, rects);
+   
+   xfree (rects);
+   FreeScratchGC (gc);
+}
+
 /*
  * The source rectangle of the video is defined by (src_x, src_y, src_w, src_h).
  * The dest rectangle of the video is defined by (drw_x, drw_y, drw_w, drw_h).
@@ -2255,6 +2273,7 @@ I830PutImage(ScrnInfoPtr pScrn,
     BoxRec dstBox;
     int pitchAlignMask;
     int extraLinear;
+    xf86CrtcPtr	crtc;
 
     if (pPriv->textured)
 	overlay = NULL;
@@ -2301,8 +2320,10 @@ I830PutImage(ScrnInfoPtr pScrn,
     dstBox.y1 = drw_y;
     dstBox.y2 = drw_y + drw_h;
 
-    if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes,
-			       width, height))
+    if (!i830_clip_video_helper(pScrn, 
+				pPriv->textured ? NULL : &crtc,
+				&dstBox, &x1, &x2, &y1, &y2, clipBoxes,
+				width, height))
 	return Success;
 
     destId = id;
@@ -2455,14 +2476,15 @@ I830PutImage(ScrnInfoPtr pScrn,
     }
 
     if (!pPriv->textured) {
+	i830_display_video(pScrn, crtc, destId, width, height, dstPitch,
+			   x1, y1, x2, y2, &dstBox, src_w, src_h,
+			   drw_w, drw_h);
+	
 	/* update cliplist */
 	if (!RegionsEqual(&pPriv->clip, clipBoxes)) {
 	    REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
-	    xf86XVFillKeyHelper(pScreen, pPriv->colorKey, clipBoxes);
+	    i830_fill_colorkey (pScreen, pPriv->colorKey, clipBoxes);
 	}
-
-	I830DisplayVideo(pScrn, destId, width, height, dstPitch,
-			 x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
     } else if (IS_I965G(pI830)) {
 	I965DisplayVideoTextured(pScrn, pPriv, destId, clipBoxes, width, height,
 				 dstPitch, x1, y1, x2, y2,
@@ -2754,8 +2776,8 @@ I830DisplaySurface(XF86SurfacePtr surfac
     I830Ptr pI830 = I830PTR(pScrn);
     I830PortPrivPtr pI830Priv = GET_PORT_PRIVATE(pScrn);
     INT32 x1, y1, x2, y2;
-    INT32 loops = 0;
     BoxRec dstBox;
+    xf86CrtcPtr crtc;
 
     OVERLAY_DEBUG("I830DisplaySurface\n");
 
@@ -2785,43 +2807,24 @@ I830DisplaySurface(XF86SurfacePtr surfac
     dstBox.y1 = drw_y;
     dstBox.y2 = drw_y + drw_h;
 
-    if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes,
-			       surface->width, surface->height))
+    if (!i830_clip_video_helper (pScrn, &crtc, &dstBox,
+				 &x1, &x2, &y1, &y2, clipBoxes,
+				 surface->width, surface->height))
 	return Success;
 
     /* fixup pointers */
     pI830Priv->YBuf0offset = surface->offsets[0];
     pI830Priv->YBuf1offset = pI830Priv->YBuf0offset;
 
-    /* Make sure this buffer isn't in use */
-    loops = 0;
-    if (*pI830->overlayOn && pI830Priv->doubleBuffer) 
-    {
-	while (loops < 1000000) {
-#if USE_USLEEP_FOR_VIDEO
-	    usleep(10);
-#endif
-	    if (((INREG(DOVSTA) & OC_BUF) >> 20) == pI830Priv->currentBuf) {
-		break;
-	    }
-	    loops++;
-	}
-	if (loops >= 1000000) {
-	    ErrorF("loops (1) maxed out for buffer %d\n", pI830Priv->currentBuf);
-#if 0
-	    pI830Priv->currentBuf = !pI830Priv->currentBuf;
-#endif
-	}
-
-	/* buffer swap */
-	pI830Priv->currentBuf = !pI830Priv->currentBuf;
-    }
+    /* Pick the idle buffer */
+    if (!pI830Priv->textured && *pI830->overlayOn && pI830Priv->doubleBuffer) 
+	pI830Priv->currentBuf = !((INREG(DOVSTA) & OC_BUF) >> 20);
 
-    I830DisplayVideo(pScrn, surface->id, surface->width, surface->height,
+    i830_display_video(pScrn, crtc, surface->id, surface->width, surface->height,
 		     surface->pitches[0], x1, y1, x2, y2, &dstBox,
 		     src_w, src_h, drw_w, drw_h);
 
-    xf86XVFillKeyHelper(pScreen, pI830Priv->colorKey, clipBoxes);
+    i830_fill_colorkey (pScreen, pI830Priv->colorKey, clipBoxes);
 
     pPriv->isOn = TRUE;
     /* we've prempted the XvImage stream so set its free timer */
diff-tree 33f635d79fe891079558fd909d564f3cf424c482 (from ff0ac8ea63dd6e55573652c5826c482881da0d62)
Author: Keith Packard <keithp at dulcimer.keithp.com>
Date:   Fri May 25 17:32:06 2007 -0700

    Ensure Pipe A is active when enabling overlay the first time.
    
    The overlay on the i830 appears to be clocked by Pipe A when being enabled.
    If pipe A is not running, it will freeze the overlay and blank the screen.
    Setting a random mode on the Pipe and turning it on fixes this problem
    nicely.

diff --git a/src/i830_video.c b/src/i830_video.c
index e2d132e..c2d3b4b 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -321,6 +321,9 @@ typedef struct {
     CARD16 RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES];
 } I830OverlayRegRec, *I830OverlayRegPtr;
 
+#define I830OVERLAYREG(pI830) ((I830OverlayRegPtr)\
+			       ((pI830)->FbBase + \
+				(pI830)->overlay_regs->offset))
 #if VIDEO_DEBUG
 static void
 CompareOverlay(I830Ptr pI830, CARD32 * overlay, int size)
@@ -342,6 +345,29 @@ CompareOverlay(I830Ptr pI830, CARD32 * o
 }
 #endif
 
+static int
+I830CrtcPipe (xf86CrtcPtr crtc)
+{
+    if (crtc == NULL)
+	return 0;
+    return ((I830CrtcPrivatePtr) crtc->driver_private)->pipe;
+}
+
+static xf86CrtcPtr
+I830CrtcForPipe (ScrnInfoPtr pScrn, int pipe)
+{
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int			c;
+
+    for (c = 0; c < xf86_config->num_crtc; c++)
+    {
+	xf86CrtcPtr crtc = xf86_config->crtc[c];
+	if (I830CrtcPipe (crtc) == pipe)
+	    return crtc;
+    }
+    return NULL;
+}
+
 /*
  * This is more or less the correct way to initalise, update, and shut down
  * the overlay.
@@ -353,40 +379,91 @@ CompareOverlay(I830Ptr pI830, CARD32 * o
 static void
 i830_overlay_on(ScrnInfoPtr pScrn)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
-    I830OverlayRegPtr	overlay = (I830OverlayRegPtr) (pI830->FbBase +
-						       pI830->overlay_regs->offset);
-
+    I830Ptr		pI830 = I830PTR(pScrn);
+    I830OverlayRegPtr	overlay = I830OVERLAYREG(pI830);
+    I830PortPrivPtr	pPriv = pI830->adaptor->pPortPrivates[0].ptr;
+    xf86CrtcPtr		crtc0 = NULL;
+    
     if (*pI830->overlayOn)
 	return;
 
+    /*
+     * On I830, if pipe A is off the first time the overlay
+     * is enabled, it will fail to turn and blank the entire 
+     * screen. Light up pipe A in this case to provide a clock
+     * for the overlay hardware
+     */
+    if (!pPriv->started_video)
+    {
+	pPriv->started_video = TRUE;
+	crtc0 = I830CrtcForPipe (pScrn, 0);
+	if (!crtc0->enabled)
+	{
+	    /* 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
+	    };
+	    xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
+	    crtc0->funcs->mode_set (crtc0, &mode, &mode, 0, 0);
+	    crtc0->funcs->dpms (crtc0, DPMSModeOn);
+	}
+	else
+	    crtc0 = NULL;
+    }
+
     overlay->OCMD &= ~OVERLAY_ENABLE;
-    BEGIN_LP_RING(4);
+    BEGIN_LP_RING(6);
     OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE);
     OUT_RING(MI_NOOP);
     OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_ON);
     OUT_RING(pI830->overlay_regs->bus_addr | OFC_UPDATE);
+    /* Wait for the overlay to light up before attempting to use it */
+    OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
+    OUT_RING(MI_NOOP);
     ADVANCE_LP_RING();
+    i830WaitSync(pScrn);
+    
+    /*
+     * If we turned pipe A on up above, turn it
+     * back off
+     */
+    if (crtc0)
+	crtc0->funcs->dpms (crtc0, DPMSModeOff);
+
     OVERLAY_DEBUG("overlay_on\n");
     *pI830->overlayOn = TRUE;
+
+    overlay->OCMD |= OVERLAY_ENABLE;
 }
 
 static void
-i830_overlay_continue(ScrnInfoPtr pScrn)
+i830_overlay_continue(ScrnInfoPtr pScrn, Bool update_filter)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
-    I830OverlayRegPtr	overlay = (I830OverlayRegPtr) (pI830->FbBase +
-						       pI830->overlay_regs->offset);
+    I830Ptr		pI830 = I830PTR(pScrn);
+    CARD32		flip_addr;
+    I830OverlayRegPtr	overlay = I830OVERLAYREG(pI830);
 
     if (!*pI830->overlayOn)
 	return;
 
-    overlay->OCMD |= OVERLAY_ENABLE;
+    flip_addr = pI830->overlay_regs->bus_addr;
+    if (update_filter)
+	flip_addr |= OFC_UPDATE;
+    OVERLAY_DEBUG ("overlay_continue cmd 0x%08lx -> 0x%08lx sta 0x%08lx\n",
+		   overlay->OCMD, INREG(OCMD_REGISTER), INREG(DOVSTA));
     BEGIN_LP_RING(4);
     OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE);
     OUT_RING(MI_NOOP);
     OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_CONTINUE);
-    OUT_RING(pI830->overlay_regs->bus_addr | OFC_UPDATE);
+    OUT_RING(flip_addr);
     ADVANCE_LP_RING();
     OVERLAY_DEBUG("overlay_continue\n");
 }
@@ -395,22 +472,43 @@ static void
 i830_overlay_off(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    I830OverlayRegPtr	overlay = (I830OverlayRegPtr) (pI830->FbBase +
-						       pI830->overlay_regs->offset);
+    I830OverlayRegPtr	overlay = I830OVERLAYREG(pI830);
 
     if (!*pI830->overlayOn)
 	return;
 
-    overlay->OCMD &= ~OVERLAY_ENABLE;
-    BEGIN_LP_RING(6);
-    OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE);
-    OUT_RING(MI_NOOP);
-    OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_CONTINUE);
-    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();
-    i830WaitSync(pScrn);
+    /*
+     * Wait for overlay to go idle. This has to be
+     * separated from the turning off state by a WaitSync
+     * to ensure the overlay will not read OCMD early and
+     * disable the overlay before the commands here are
+     * executed
+     */
+    {
+	BEGIN_LP_RING(2);
+	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
+	OUT_RING(MI_NOOP);
+	ADVANCE_LP_RING();
+	i830WaitSync(pScrn);
+    }
+    
+    /*
+     * Turn overlay off
+     */
+    {
+	overlay->OCMD &= ~OVERLAY_ENABLE;
+	OVERLAY_DEBUG ("overlay_off cmd 0x%08lx -> 0x%08lx sta 0x%08lx\n",
+		       overlay->OCMD, INREG(OCMD_REGISTER), INREG(DOVSTA));
+	BEGIN_LP_RING(6);
+	OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE);
+	OUT_RING(MI_NOOP);
+	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_CONTINUE);
+	OUT_RING(pI830->overlay_regs->bus_addr);
+	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
+	OUT_RING(MI_NOOP);
+	ADVANCE_LP_RING();
+	i830WaitSync(pScrn);
+    }
     *pI830->overlayOn = FALSE;
     OVERLAY_DEBUG("overlay_off\n");
 }
@@ -490,21 +588,12 @@ I830InitVideo(ScreenPtr pScreen)
     xfree(adaptors);
 }
 
-static int
-I830CrtcPipe (xf86CrtcPtr crtc)
-{
-    if (crtc == NULL)
-	return 0;
-    return ((I830CrtcPrivatePtr) crtc->driver_private)->pipe;
-}
-
 static void
 I830ResetVideo(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr;
-    I830OverlayRegPtr overlay =
-    (I830OverlayRegPtr) (pI830->FbBase + pI830->overlay_regs->offset);
+    I830OverlayRegPtr	overlay = I830OVERLAYREG(pI830);
 
     OVERLAY_DEBUG("I830ResetVideo: base: %p, offset: 0x%lx, obase: %p\n",
 		  pI830->FbBase, pI830->overlay_regs->offset, overlay);
@@ -938,7 +1027,7 @@ I830SetPortAttribute(ScrnInfoPtr pScrn,
 	return Success;
     }
 
-    overlay = (I830OverlayRegPtr) (pI830->FbBase + pI830->overlay_regs->offset);
+    overlay = I830OVERLAYREG(pI830);
 
     if (attribute == xvBrightness) {
 	if ((value < -128) || (value > 127))
@@ -946,20 +1035,20 @@ I830SetPortAttribute(ScrnInfoPtr pScrn,
 	pPriv->brightness = value;
 	overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff);
 	OVERLAY_DEBUG("BRIGHTNESS\n");
-	i830_overlay_continue (pScrn);
+	i830_overlay_continue (pScrn, FALSE);
     } else if (attribute == xvContrast) {
 	if ((value < 0) || (value > 255))
 	    return BadValue;
 	pPriv->contrast = value;
 	overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff);
 	OVERLAY_DEBUG("CONTRAST\n");
-	i830_overlay_continue (pScrn);
+	i830_overlay_continue (pScrn, FALSE);
     } else if (attribute == xvSaturation) {
 	if ((value < 0) || (value > 1023))
 	    return BadValue;
 	pPriv->saturation = value;
 	overlay->OCLRC1 = pPriv->saturation;
-	i830_overlay_continue (pScrn);
+	i830_overlay_continue (pScrn, FALSE);
     } else if (attribute == xvPipe) {
 	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
 	if ((value < -1) || (value > xf86_config->num_crtc))
@@ -997,7 +1086,7 @@ I830SetPortAttribute(ScrnInfoPtr pScrn,
 	    break;
 	}
 	OVERLAY_DEBUG("COLORKEY\n");
-	i830_overlay_continue (pScrn);
+	i830_overlay_continue (pScrn, FALSE);
 	REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
     } else if(attribute == xvDoubleBuffer) {
 	if ((value < 0) || (value > 1))
@@ -1612,6 +1701,17 @@ I830CoveringCrtc (ScrnInfoPtr pScrn, Box
     return best_crtc;
 }
 
+static int
+i830_swidth (I830Ptr pI830, unsigned int offset,
+	     unsigned int width, unsigned int mask, int shift)
+{
+    int	swidth = ((offset + width + mask) >> shift) - (offset >> shift);
+    if (IS_I9XX(pI830))
+	swidth <<= 1;
+    swidth -= 1;
+    return swidth << 2;
+}
+
 static void
 I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height,
 		 int dstPitch, int x1, int y1, int x2, int y2, BoxPtr dstBox,
@@ -1619,12 +1719,13 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
 {
     I830Ptr pI830 = I830PTR(pScrn);
     I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr;
-    I830OverlayRegPtr overlay =
-    (I830OverlayRegPtr) (pI830->FbBase + pI830->overlay_regs->offset);
-    unsigned int swidth;
+    I830OverlayRegPtr	overlay = I830OVERLAYREG(pI830);
+    unsigned int swidth, swidthy, swidthuv;
     unsigned int mask, shift, offsety, offsetu;
     xf86CrtcPtr crtc;
-    int tmp;
+    int		tmp;
+    CARD32	OCMD;
+    Bool	scaleChanged = FALSE;
 
     OVERLAY_DEBUG("I830DisplayVideo: %dx%d (pitch %d)\n", width, height,
 		  dstPitch);
@@ -1652,9 +1753,6 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
 	return;
     }
     
-    /* Ensure overlay is turned on with OVERLAY_ENABLE at 0 */
-    i830_overlay_on (pScrn);
-
     switch (crtc->rotation & 0xf) {
     case RR_Rotate_0:
 	dstBox->x1 -= crtc->x;
@@ -1798,48 +1896,16 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
     switch (id) {
     case FOURCC_YV12:
     case FOURCC_I420:
-	swidth = width;
-
-	overlay->SWIDTH = swidth;
-	swidth /= 2;
-	overlay->SWIDTH |= (swidth & 0x7ff) << 16;
-
-	swidth = ((offsety + width + mask) >> shift) -
-	(offsety >> shift);
-
-	if (IS_I9XX(pI830))
-	    swidth <<= 1;
-
-	swidth -= 1;
-
-	OVERLAY_DEBUG("Y width is %d, swidth is %d\n", width, swidth);
-
-	overlay->SWIDTHSW = swidth << 2;
-
-	swidth = ((offsetu + (width / 2) + mask) >> shift) -
-	(offsetu >> shift);
-
-	if (IS_I9XX(pI830))
-	    swidth <<= 1;
-
-	swidth -= 1;
-
-	OVERLAY_DEBUG("UV width is %d, swidthsw is %d\n", width / 2, swidth);
-
-	overlay->SWIDTHSW |= swidth << 18;
-
-	OVERLAY_DEBUG("HEIGHT is %d\n",height);
-
+	overlay->SWIDTH = width | ((width/2 & 0x7ff) << 16);
+	swidthy  = i830_swidth (pI830, offsety, width, mask, shift);
+	swidthuv = i830_swidth (pI830, offsetu, width/2, mask, shift);
+	overlay->SWIDTHSW = (swidthy) | (swidthuv << 16);
 	overlay->SHEIGHT = height | ((height / 2) << 16);
 	break;
     case FOURCC_UYVY:
     case FOURCC_YUY2:
     default:
-	swidth = width;
-	overlay->SWIDTH = swidth;
-
-	OVERLAY_DEBUG("Y width is %d\n", swidth);
-
+	overlay->SWIDTH = width;
 	swidth = ((offsety + (width << 1) + mask) >> shift) -
 	(offsety >> shift);
 
@@ -1848,18 +1914,18 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
 
 	swidth -= 1;
 
-	OVERLAY_DEBUG("swidthsw is %d\n", swidth);
-
-	overlay->SWIDTHSW = swidth << 2;
-
-	OVERLAY_DEBUG("HEIGHT is %d\n",height);
+	swidth <<= 2;
+	
+	OVERLAY_DEBUG("swidthsw is old %d new %d\n",
+		      swidth,
+		      i830_swidth (pI830, offsety, width << 1,
+				   mask, shift));
 
+	overlay->SWIDTHSW = swidth;
 	overlay->SHEIGHT = height;
 	break;
     }
 
-    overlay->OCMD = OVERLAY_ENABLE;
-
     overlay->DWINPOS = (dstBox->y1 << 16) | dstBox->x1;
 
     overlay->DWINSZ = (((dstBox->y2 - dstBox->y1) << 16) |
@@ -1869,59 +1935,14 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
 		  dstBox->x1, dstBox->y1, dstBox->x2, dstBox->y2);
 
     /* buffer locations */
-    if (IS_I965G(pI830))
-    {
-	overlay->OBUF_0Y = 0;
-	overlay->OBUF_0U = 0;
-	overlay->OBUF_0V = 0;
-	overlay->OSTART_0Y = pPriv->YBuf0offset;
-	overlay->OSTART_0U = pPriv->UBuf0offset;
-	overlay->OSTART_0V = pPriv->VBuf0offset;
-	if(pPriv->doubleBuffer) {
-	    overlay->OBUF_1Y = 0;
-	    overlay->OBUF_1U = 0;
-	    overlay->OBUF_1V = 0;
-	    overlay->OSTART_1Y = pPriv->YBuf1offset;
-	    overlay->OSTART_1U = pPriv->UBuf1offset;
-	    overlay->OSTART_1V = pPriv->VBuf1offset;
-	}
-    } else {
-	overlay->OBUF_0Y = pPriv->YBuf0offset;
-	overlay->OBUF_0U = pPriv->UBuf0offset;
-	overlay->OBUF_0V = pPriv->VBuf0offset;
-	if(pPriv->doubleBuffer) {
-	    overlay->OBUF_1Y = pPriv->YBuf1offset;
-	    overlay->OBUF_1U = pPriv->UBuf1offset;
-	    overlay->OBUF_1V = pPriv->VBuf1offset;
-	}
-    }
-
-    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
-    {
-	int i;
-
-	ErrorF("First 32 bytes of Y data:\n");
-	for (i = 0; i < 32; i++)
-	    ErrorF(" %02x",
-		   ((unsigned char *)pI830->FbBase + pPriv->YBuf0offset)[i]);
-	ErrorF("\n");
-	ErrorF("First 16 bytes of U data:\n");
-	for (i = 0; i < 16; i++)
-	    ErrorF(" %02x",
-		   ((unsigned char *)pI830->FbBase + pPriv->UBuf0offset)[i]);
-	ErrorF("\n");
-	ErrorF("First 16 bytes of V data:\n");
-	for (i = 0; i < 16; i++)
-	    ErrorF(" %02x",
-		   ((unsigned char *)pI830->FbBase + pPriv->VBuf0offset)[i]);
-	ErrorF("\n");
+    overlay->OBUF_0Y = pPriv->YBuf0offset;
+    overlay->OBUF_0U = pPriv->UBuf0offset;
+    overlay->OBUF_0V = pPriv->VBuf0offset;
+    if(pPriv->doubleBuffer) {
+	overlay->OBUF_1Y = pPriv->YBuf1offset;
+	overlay->OBUF_1U = pPriv->UBuf1offset;
+	overlay->OBUF_1V = pPriv->VBuf1offset;
     }
-#endif
 
     OVERLAY_DEBUG("pos: 0x%lx, size: 0x%lx\n",
 		  overlay->DWINPOS, overlay->DWINSZ);
@@ -1933,7 +1954,6 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
      */
 
     {
-	Bool scaleChanged = FALSE;
 	int xscaleInt, xscaleFract, yscaleInt, yscaleFract;
 	int xscaleIntUV, xscaleFractUV;
 	int yscaleIntUV, yscaleFractUV;
@@ -2033,22 +2053,24 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
 	    for (i = 0; i < N_PHASES; i++) {
 		for (j = 0; j < N_HORIZ_Y_TAPS; j++) {
 		    pos = i * N_HORIZ_Y_TAPS + j;
-		    overlay->Y_HCOEFS[pos] = xcoeffY[pos].sign << 15 |
-		    xcoeffY[pos].exponent << 12 |
-		    xcoeffY[pos].mantissa;
+		    overlay->Y_HCOEFS[pos] = (xcoeffY[pos].sign << 15 |
+					      xcoeffY[pos].exponent << 12 |
+					      xcoeffY[pos].mantissa);
 		}
 	    }
 	    for (i = 0; i < N_PHASES; i++) {
 		for (j = 0; j < N_HORIZ_UV_TAPS; j++) {
 		    pos = i * N_HORIZ_UV_TAPS + j;
-		    overlay->UV_HCOEFS[pos] = xcoeffUV[pos].sign << 15 |
-		    xcoeffUV[pos].exponent << 12 |
-		    xcoeffUV[pos].mantissa;
+		    overlay->UV_HCOEFS[pos] = (xcoeffUV[pos].sign << 15 |
+					       xcoeffUV[pos].exponent << 12 |
+					       xcoeffUV[pos].mantissa);
 		}
 	    }
 	}
     }
 
+    OCMD = OVERLAY_ENABLE;
+    
     switch (id) {
     case FOURCC_YV12:
     case FOURCC_I420:
@@ -2060,32 +2082,36 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
 	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;
-	overlay->OCMD |= YUV_420;
+	OCMD &= ~SOURCE_FORMAT;
+	OCMD &= ~OV_BYTE_ORDER;
+	OCMD |= YUV_420;
 	break;
     case FOURCC_UYVY:
     case FOURCC_YUY2:
     default:
 	OVERLAY_DEBUG("YUV422\n");
 	overlay->OSTRIDE = dstPitch;
-	overlay->OCMD &= ~SOURCE_FORMAT;
-	overlay->OCMD |= YUV_422;
-	overlay->OCMD &= ~OV_BYTE_ORDER;
+	OCMD &= ~SOURCE_FORMAT;
+	OCMD |= YUV_422;
+	OCMD &= ~OV_BYTE_ORDER;
 	if (id == FOURCC_UYVY)
-	    overlay->OCMD |= Y_SWAP;
+	    OCMD |= Y_SWAP;
 	break;
     }
 
-    overlay->OCMD &= ~(BUFFER_SELECT | FIELD_SELECT);
+    OCMD &= ~(BUFFER_SELECT | FIELD_SELECT);
     if (pPriv->currentBuf == 0)
-	overlay->OCMD |= BUFFER0;
+	OCMD |= BUFFER0;
     else
-	overlay->OCMD |= BUFFER1;
+	OCMD |= BUFFER1;
 
-    OVERLAY_DEBUG("OCMD is 0x%lx\n", overlay->OCMD);
+    overlay->OCMD = OCMD;
+    OVERLAY_DEBUG("OCMD is 0x%lx\n", OCMD);
 
-    i830_overlay_continue (pScrn);
+    /* make sure the overlay is on */
+    i830_overlay_on (pScrn);
+    /* and show this frame */
+    i830_overlay_continue (pScrn, scaleChanged);
 }
 
 #ifdef I830_USE_EXA
@@ -2233,8 +2259,7 @@ I830PutImage(ScrnInfoPtr pScrn,
     if (pPriv->textured)
 	overlay = NULL;
     else
-	overlay = (I830OverlayRegPtr) (pI830->FbBase + 
-				       pI830->overlay_regs->offset);
+	overlay = I830OVERLAYREG(pI830);
 
 #if 0
     ErrorF("I830PutImage: src: (%d,%d)(%d,%d), dst: (%d,%d)(%d,%d)\n"
diff --git a/src/i830_video.h b/src/i830_video.h
index 7e2d149..88a7bd9 100644
--- a/src/i830_video.h
+++ b/src/i830_video.h
@@ -77,6 +77,7 @@ typedef struct {
    int oneLineMode;
    int scaleRatio;
    Bool textured;
+   Bool started_video;
 } I830PortPrivRec, *I830PortPrivPtr;
 
 #define GET_PORT_PRIVATE(pScrn) \
diff-tree ff0ac8ea63dd6e55573652c5826c482881da0d62 (from 109e5d597b76f7414601cb39c07b133ebf1b0e61)
Author: Keith Packard <keithp at dulcimer.keithp.com>
Date:   Fri May 25 17:26:15 2007 -0700

    Xv does not require directRendering

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 2cbddb0..8e74903 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2293,18 +2293,18 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 #endif
    }
 
+#ifdef I830_XV
+    /*
+     * Set this so that the overlay allocation is factored in when
+     * appropriate.
+     */
+    pI830->XvEnabled = !pI830->XvDisabled;
+#endif
+
    if (!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) &
diff-tree 109e5d597b76f7414601cb39c07b133ebf1b0e61 (from dfb1ec9a07f74125cb1724d41ed4342c4714e12b)
Author: Keith Packard <keithp at dulcimer.keithp.com>
Date:   Thu May 24 11:40:50 2007 -0700

    Clean up CRTC selection. Remove more overlay blocking.
    
    Create separate CRTC selection function, use ints instead of floats for
    coverage measurement. Remove pipe stalls waiting for overlay update.

diff --git a/src/i830_video.c b/src/i830_video.c
index e8ba7a8..e2d132e 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -361,13 +361,11 @@ i830_overlay_on(ScrnInfoPtr pScrn)
 	return;
 
     overlay->OCMD &= ~OVERLAY_ENABLE;
-    BEGIN_LP_RING(6);
+    BEGIN_LP_RING(4);
     OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE);
     OUT_RING(MI_NOOP);
     OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_ON);
     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();
     OVERLAY_DEBUG("overlay_on\n");
     *pI830->overlayOn = TRUE;
@@ -384,13 +382,11 @@ i830_overlay_continue(ScrnInfoPtr pScrn)
 	return;
 
     overlay->OCMD |= OVERLAY_ENABLE;
-    BEGIN_LP_RING(6);
+    BEGIN_LP_RING(4);
     OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE);
     OUT_RING(MI_NOOP);
     OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_CONTINUE);
     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();
     OVERLAY_DEBUG("overlay_continue\n");
 }
@@ -1551,8 +1547,12 @@ UpdateCoeff(int taps, double fCutoff, Bo
     }
 }
 
-static float
-I830CrtcVideoCoverage (xf86CrtcPtr crtc, BoxPtr video)
+/*
+ * Return the number of pixels from 'box' covered by 'crtc'.
+ * That is, the area of the intersection of 'box' and 'crtc'
+ */
+static int
+I830CrtcBoxCoverage (xf86CrtcPtr crtc, BoxPtr box)
 {
     BoxRec   dest;
     BoxRec   pipe;
@@ -1569,19 +1569,47 @@ I830CrtcVideoCoverage (xf86CrtcPtr crtc,
 	pipe.x1 = pipe.x2 = 0;
 	pipe.y1 = pipe.y2 = 0;
     }
-    dest.x1 = pipe.x1 > video->x1 ? pipe.x1 : video->x1;
-    dest.x2 = pipe.x2 < video->x2 ? pipe.x2 : video->x2;
-    dest.y1 = pipe.y1 > video->y1 ? pipe.y1 : video->y1;
-    dest.y2 = pipe.y2 < video->y2 ? pipe.y2 : video->y2;
+    dest.x1 = pipe.x1 > box->x1 ? pipe.x1 : box->x1;
+    dest.x2 = pipe.x2 < box->x2 ? pipe.x2 : box->x2;
+    dest.y1 = pipe.y1 > box->y1 ? pipe.y1 : box->y1;
+    dest.y2 = pipe.y2 < box->y2 ? pipe.y2 : box->y2;
     if (dest.x1 >= dest.x2 || dest.y1 >= dest.y2)
     {
 	dest.x1 = dest.x2 = 0;
 	dest.y1 = dest.y2 = 0;
     }
-    if (video->x1 >= video->x2 || video->y1 >= video->y2)
-	return 0.0;
-    return (((float) (dest.x2 - dest.x1) * (float) (dest.y2 - dest.y1)) /
-	    ((float) (video->x2 - video->x1) * (float) (video->y2 - video->y1)));
+    return (int) (dest.x2 - dest.x1) * (int) (dest.y2 - dest.y1);
+}
+
+/*
+ * Return the crtc covering 'box'. If two crtcs cover a portion of
+ * 'box', then prefer 'desired'. If 'desired' is NULL, then prefer the crtc
+ * with greater coverage
+ */
+
+static xf86CrtcPtr
+I830CoveringCrtc (ScrnInfoPtr pScrn, BoxPtr pBox, xf86CrtcPtr desired)
+{
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    xf86CrtcPtr		crtc, best_crtc;
+    int			coverage, best_coverage;
+    int			c;
+
+    best_crtc = NULL;
+    best_coverage = 0;
+    for (c = 0; c < xf86_config->num_crtc; c++)
+    {
+	crtc = xf86_config->crtc[c];
+	coverage = I830CrtcBoxCoverage (crtc, pBox);
+	if (coverage > best_coverage)
+	{
+	    if (crtc == desired)
+		return crtc;
+	    best_crtc = crtc;
+	    best_coverage = coverage;
+	}
+    }
+    return best_crtc;
 }
 
 static void
@@ -1608,35 +1636,11 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
     CompareOverlay(pI830, (CARD32 *) overlay, 0x100);
 #endif
 
+    crtc = I830CoveringCrtc (pScrn, dstBox, pPriv->desired_crtc);
+    if (crtc != pPriv->current_crtc)
     {
-	int		    coverage;
-	int		    c;
-	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-
-	crtc = NULL;
-	for (c = 0; c < xf86_config->num_crtc; c++)
-	{
-	    xf86CrtcPtr	this_crtc = xf86_config->crtc[c];
-	    coverage = I830CrtcVideoCoverage (this_crtc, dstBox);
-	    if (coverage)
-	    {
-		if (this_crtc == pPriv->desired_crtc)
-		{
-		    crtc = this_crtc;
-		    best_coverage = 1.0;
-		}
-		else if (coverage > best_coverage)
-		{
-		    crtc = this_crtc;
-		    best_coverage = coverage;
-		}
-	    }
-	}
-	if (crtc != pPriv->current_crtc)
-	{
-	    pPriv->current_crtc = crtc;
-	    I830ResetVideo (pScrn);
-	}
+        pPriv->current_crtc = crtc;
+        I830ResetVideo (pScrn);
     }
 
     /*
@@ -2221,7 +2225,7 @@ I830PutImage(ScrnInfoPtr pScrn,
     PixmapPtr pPixmap;
     INT32 x1, x2, y1, y2;
     int srcPitch, srcPitch2 = 0, dstPitch, destId;
-    int top, left, npixels, nlines, size, loops;
+    int top, left, npixels, nlines, size;
     BoxRec dstBox;
     int pitchAlignMask;
     int extraLinear;
diff-tree dfb1ec9a07f74125cb1724d41ed4342c4714e12b (from d172344599585e11388e59659dc9aaa86d7a31c1)
Author: Keith Packard <keithp at dulcimer.keithp.com>
Date:   Thu May 24 11:23:44 2007 -0700

    Eliminate blocking for video overlay.
    
    No need to block for the overlay; just use the idle buffer.  This will
    always work because the buffer switch occurs at vblank time, so there is
    always plenty of time to get the next buffer contents in place before it
    starts getting scanned to the screen.

diff --git a/src/i830_video.c b/src/i830_video.c
index 9cbd220..e8ba7a8 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -134,7 +134,7 @@ static Atom xvGamma0, xvGamma1, xvGamma2
 #define IMAGE_MAX_HEIGHT_LEGACY	1088
 
 /* overlay debugging printf function */
-#if 1
+#if 0
 #define OVERLAY_DEBUG ErrorF
 #else
 #define OVERLAY_DEBUG if (0) ErrorF
@@ -950,23 +950,20 @@ I830SetPortAttribute(ScrnInfoPtr pScrn,
 	pPriv->brightness = value;
 	overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff);
 	OVERLAY_DEBUG("BRIGHTNESS\n");
-	if (*pI830->overlayOn)
-	    i830_overlay_continue (pScrn);
+	i830_overlay_continue (pScrn);
     } else if (attribute == xvContrast) {
 	if ((value < 0) || (value > 255))
 	    return BadValue;
 	pPriv->contrast = value;
 	overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff);
 	OVERLAY_DEBUG("CONTRAST\n");
-	if (*pI830->overlayOn)
-	    i830_overlay_continue (pScrn);
+	i830_overlay_continue (pScrn);
     } else if (attribute == xvSaturation) {
 	if ((value < 0) || (value > 1023))
 	    return BadValue;
 	pPriv->saturation = value;
 	overlay->OCLRC1 = pPriv->saturation;
-	if (*pI830->overlayOn)
-	    i830_overlay_continue (pScrn);
+	i830_overlay_continue (pScrn);
     } else if (attribute == xvPipe) {
 	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
 	if ((value < -1) || (value > xf86_config->num_crtc))
@@ -1004,8 +1001,7 @@ I830SetPortAttribute(ScrnInfoPtr pScrn,
 	    break;
 	}
 	OVERLAY_DEBUG("COLORKEY\n");
-	if (*pI830->overlayOn)
-	    i830_overlay_continue (pScrn);
+	i830_overlay_continue (pScrn);
 	REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
     } else if(attribute == xvDoubleBuffer) {
 	if ((value < 0) || (value > 1))
@@ -1613,9 +1609,8 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
 #endif
 
     {
-	float best_coverage = 0.0;
-	float coverage;
-	int c;
+	int		    coverage;
+	int		    c;
 	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
 
 	crtc = NULL;
@@ -1644,6 +1639,18 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
 	}
     }
 
+    /*
+     * If the video isn't visible on any CRTC, turn it off
+     */
+    if (!crtc)
+    {
+	i830_overlay_off (pScrn);
+	return;
+    }
+    
+    /* Ensure overlay is turned on with OVERLAY_ENABLE at 0 */
+    i830_overlay_on (pScrn);
+
     switch (crtc->rotation & 0xf) {
     case RR_Rotate_0:
 	dstBox->x1 -= crtc->x;
@@ -1683,15 +1690,6 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
 	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)
-	I830ResetVideo(pScrn);
-
-    /* Ensure overlay is turned on with OVERLAY_ENABLE at 0 */
-    i830_overlay_on (pScrn);
-
     /* Fix up the dstBox if outside the visible screen */
     {
 	int offset_x = (dstBox->x1 < 0) ? -dstBox->x1 : 0;
@@ -1770,22 +1768,8 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
 	if (dstBox->x2 > hactive) dstBox->x2 = hactive;
 
 	/* nothing do to */
-	if ((!dstBox->x1 && !dstBox->x2) || (!dstBox->y1 && !dstBox->y2)) {
-	    OVERLAY_DEBUG("NOTHING TO DO\n");
-	    return;
-	}
-	if ((dstBox->x1 == (hactive) && 
-	     dstBox->x2 == (hactive)) || 
-	    (dstBox->y1 == vactive && 
-	     dstBox->y2 == vactive)) {
-	    OVERLAY_DEBUG("NOTHING TO DO\n");
-	    return;
-	}
-	if ((dstBox->y2 - dstBox->y1) <= N_VERT_Y_TAPS) {
-	    OVERLAY_DEBUG("NOTHING TO DO\n");
-	    return;
-	}
-	if ((dstBox->x2 - dstBox->x1) <= 2) {
+	if (dstBox->x2 - dstBox->x1 <= 2 || dstBox->y2 - dstBox->y1 < N_VERT_Y_TAPS)
+	{
 	    OVERLAY_DEBUG("NOTHING TO DO\n");
 	    return;
 	}
@@ -1874,8 +1858,8 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
 
     overlay->DWINPOS = (dstBox->y1 << 16) | dstBox->x1;
 
-    overlay->DWINSZ = ((dstBox->y2 - dstBox->y1) << 16) |
-    (dstBox->x2 - dstBox->x1);
+    overlay->DWINSZ = (((dstBox->y2 - dstBox->y1) << 16) |
+		       (dstBox->x2 - dstBox->x1));
 
     OVERLAY_DEBUG("dstBox: x1: %d, y1: %d, x2: %d, y2: %d\n",
 		  dstBox->x1, dstBox->y1, dstBox->x2, dstBox->y2);
@@ -2387,47 +2371,15 @@ I830PutImage(ScrnInfoPtr pScrn,
 	}
     }
 
-    /* Make sure this buffer isn't in use */
-    loops = 0;
-    if (!pPriv->textured && *pI830->overlayOn && pPriv->doubleBuffer &&
-	(overlay->OCMD & OVERLAY_ENABLE))
-    {
-	while (loops < 1000000) {
-#if USE_USLEEP_FOR_VIDEO
-	    usleep(10);
-#endif
-	    if (((INREG(DOVSTA) & OC_BUF) >> 20) == pPriv->currentBuf) {
-		break;
-	    }
-	    loops++;
-	}
-	if (loops >= 1000000) {
-	    ErrorF("loops (1) maxed out for buffer %d\n", pPriv->currentBuf);
-#if 0
-	    pPriv->currentBuf = !pPriv->currentBuf;
-#endif
-	}
-
-	/* buffer swap */
-	if (pPriv->currentBuf == 0)
-	    pPriv->currentBuf = 1;
-	else
-	    pPriv->currentBuf = 0;
-    }
+    /* Pick the idle buffer */
+    if (!pPriv->textured && *pI830->overlayOn && pPriv->doubleBuffer)
+	pPriv->currentBuf = !((INREG(DOVSTA) & OC_BUF) >> 20);
 
     /* copy data */
     top = y1 >> 16;
     left = (x1 >> 16) & ~1;
     npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left;
 
-    if (pPriv->textured) {
-	/* For textured video, we don't double buffer, and instead just wait for
-	 * acceleration to finish before writing the new video data into
-	 * framebuffer.
-	 */
-	i830WaitSync(pScrn);
-    }
-
     switch (id) {
     case FOURCC_YV12:
     case FOURCC_I420:
diff-tree d172344599585e11388e59659dc9aaa86d7a31c1 (from 02935ced3fba598a01d908ae49ccc30cbcc765a8)
Author: Keith Packard <keithp at dulcimer.keithp.com>
Date:   Wed May 23 20:00:16 2007 -0700

    Reformat i830_video.c to four-space indents.
    
    Yes, I can't stand it anymore. it's a huge patch, but
    git-diff -w shows no changes.

diff --git a/src/i830_video.c b/src/i830_video.c
index 2462d5d..9cbd220 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -1,42 +1,29 @@
 /***************************************************************************
- 
-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.
+ Copyright 2000 Intel Corporation.  All Rights Reserved. 
 
-**************************************************************************/
-/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_video.c,v 1.11tsi Exp $ */
+ 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.
 
-/*
- * 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_video.c,v 1.11tsi Exp $ */
 
 /*
  * i830_video.c: i830/i845 Xv driver. 
@@ -219,139 +206,139 @@ void exaMoveInPixmap (PixmapPtr pPixmap)
 #define MAX_CUTOFF_FREQ		3.0
 
 #define RGB16ToColorKey(c) \
-	(((c & 0xF800) << 8) | ((c & 0x07E0) << 5) | ((c & 0x001F) << 3))
+(((c & 0xF800) << 8) | ((c & 0x07E0) << 5) | ((c & 0x001F) << 3))
 
 #define RGB15ToColorKey(c) \
-        (((c & 0x7c00) << 9) | ((c & 0x03E0) << 6) | ((c & 0x001F) << 3))
+(((c & 0x7c00) << 9) | ((c & 0x03E0) << 6) | ((c & 0x001F) << 3))
 
 /* client libraries expect an encoding */
 static XF86VideoEncodingRec DummyEncoding[1] = {
-   {
-      0,
-      "XV_IMAGE",
-      IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT,
-      {1, 1}
-   }
+    {
+	0,
+	"XV_IMAGE",
+	IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT,
+	{1, 1}
+    }
 };
 
 #define NUM_FORMATS 3
 
 static XF86VideoFormatRec Formats[NUM_FORMATS] = {
-   {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
+    {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
 };
 
 #define CLONE_ATTRIBUTES 1
 static XF86AttributeRec CloneAttributes[CLONE_ATTRIBUTES] = {
-   {XvSettable | XvGettable, 0, 1, "XV_PIPE"}
+    {XvSettable | XvGettable, 0, 1, "XV_PIPE"}
 };
 
 #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"}
+    {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"}
 };
 
 #define NUM_TEXTURED_ATTRIBUTES 2
 static XF86AttributeRec TexturedAttributes[NUM_ATTRIBUTES] = {
-   {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"},
-   {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"},
+    {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"},
+    {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"},
 };
 
 #define GAMMA_ATTRIBUTES 6
 static XF86AttributeRec GammaAttributes[GAMMA_ATTRIBUTES] = {
-   {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA0"},
-   {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA1"},
-   {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA2"},
-   {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA3"},
-   {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA4"},
-   {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA5"}
+    {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA0"},
+    {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA1"},
+    {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA2"},
+    {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA3"},
+    {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA4"},
+    {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA5"}
 };
 
 #define NUM_IMAGES 4
 
 static XF86ImageRec Images[NUM_IMAGES] = {
-   XVIMAGE_YUY2,
-   XVIMAGE_YV12,
-   XVIMAGE_I420,
-   XVIMAGE_UYVY
+    XVIMAGE_YUY2,
+    XVIMAGE_YV12,
+    XVIMAGE_I420,
+    XVIMAGE_UYVY
 };
 
 typedef struct {
-   CARD32 OBUF_0Y;
-   CARD32 OBUF_1Y;
-   CARD32 OBUF_0U;
-   CARD32 OBUF_0V;
-   CARD32 OBUF_1U;
-   CARD32 OBUF_1V;
-   CARD32 OSTRIDE;
-   CARD32 YRGB_VPH;
-   CARD32 UV_VPH;
-   CARD32 HORZ_PH;
-   CARD32 INIT_PHS;
-   CARD32 DWINPOS;
-   CARD32 DWINSZ;
-   CARD32 SWIDTH;
-   CARD32 SWIDTHSW;
-   CARD32 SHEIGHT;
-   CARD32 YRGBSCALE;
-   CARD32 UVSCALE;
-   CARD32 OCLRC0;
-   CARD32 OCLRC1;
-   CARD32 DCLRKV;
-   CARD32 DCLRKM;
-   CARD32 SCLRKVH;
-   CARD32 SCLRKVL;
-   CARD32 SCLRKEN;
-   CARD32 OCONFIG;
-   CARD32 OCMD;
-   CARD32 RESERVED1;			/* 0x6C */
-   CARD32 OSTART_0Y; 		/* for i965 */
-   CARD32 OSTART_1Y;		/* for i965 */
-   CARD32 OSTART_0U;
-   CARD32 OSTART_0V;
-   CARD32 OSTART_1U;
-   CARD32 OSTART_1V;
-   CARD32 OTILEOFF_0Y;
-   CARD32 OTILEOFF_1Y;
-   CARD32 OTILEOFF_0U;
-   CARD32 OTILEOFF_0V;
-   CARD32 OTILEOFF_1U;
-   CARD32 OTILEOFF_1V;
-   CARD32 FASTHSCALE;			/* 0xA0 */
-   CARD32 UVSCALEV;			/* 0xA4 */
-
-   CARD32 RESERVEDC[(0x200 - 0xA8) / 4];		   /* 0xA8 - 0x1FC */
-   CARD16 Y_VCOEFS[N_VERT_Y_TAPS * N_PHASES];		   /* 0x200 */
-   CARD16 RESERVEDD[0x100 / 2 - N_VERT_Y_TAPS * N_PHASES];
-   CARD16 Y_HCOEFS[N_HORIZ_Y_TAPS * N_PHASES];		   /* 0x300 */
-   CARD16 RESERVEDE[0x200 / 2 - N_HORIZ_Y_TAPS * N_PHASES];
-   CARD16 UV_VCOEFS[N_VERT_UV_TAPS * N_PHASES];		   /* 0x500 */
-   CARD16 RESERVEDF[0x100 / 2 - N_VERT_UV_TAPS * N_PHASES];
-   CARD16 UV_HCOEFS[N_HORIZ_UV_TAPS * N_PHASES];	   /* 0x600 */
-   CARD16 RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES];
+    CARD32 OBUF_0Y;
+    CARD32 OBUF_1Y;
+    CARD32 OBUF_0U;
+    CARD32 OBUF_0V;
+    CARD32 OBUF_1U;
+    CARD32 OBUF_1V;
+    CARD32 OSTRIDE;
+    CARD32 YRGB_VPH;
+    CARD32 UV_VPH;
+    CARD32 HORZ_PH;
+    CARD32 INIT_PHS;
+    CARD32 DWINPOS;
+    CARD32 DWINSZ;
+    CARD32 SWIDTH;
+    CARD32 SWIDTHSW;
+    CARD32 SHEIGHT;
+    CARD32 YRGBSCALE;
+    CARD32 UVSCALE;
+    CARD32 OCLRC0;
+    CARD32 OCLRC1;
+    CARD32 DCLRKV;
+    CARD32 DCLRKM;
+    CARD32 SCLRKVH;
+    CARD32 SCLRKVL;
+    CARD32 SCLRKEN;
+    CARD32 OCONFIG;
+    CARD32 OCMD;
+    CARD32 RESERVED1;			/* 0x6C */
+    CARD32 OSTART_0Y; 		/* for i965 */
+    CARD32 OSTART_1Y;		/* for i965 */
+    CARD32 OSTART_0U;
+    CARD32 OSTART_0V;
+    CARD32 OSTART_1U;
+    CARD32 OSTART_1V;
+    CARD32 OTILEOFF_0Y;
+    CARD32 OTILEOFF_1Y;
+    CARD32 OTILEOFF_0U;
+    CARD32 OTILEOFF_0V;
+    CARD32 OTILEOFF_1U;
+    CARD32 OTILEOFF_1V;
+    CARD32 FASTHSCALE;			/* 0xA0 */
+    CARD32 UVSCALEV;			/* 0xA4 */
+
+    CARD32 RESERVEDC[(0x200 - 0xA8) / 4];		   /* 0xA8 - 0x1FC */
+    CARD16 Y_VCOEFS[N_VERT_Y_TAPS * N_PHASES];		   /* 0x200 */
+    CARD16 RESERVEDD[0x100 / 2 - N_VERT_Y_TAPS * N_PHASES];
+    CARD16 Y_HCOEFS[N_HORIZ_Y_TAPS * N_PHASES];		   /* 0x300 */
+    CARD16 RESERVEDE[0x200 / 2 - N_HORIZ_Y_TAPS * N_PHASES];
+    CARD16 UV_VCOEFS[N_VERT_UV_TAPS * N_PHASES];		   /* 0x500 */
+    CARD16 RESERVEDF[0x100 / 2 - N_VERT_UV_TAPS * N_PHASES];
+    CARD16 UV_HCOEFS[N_HORIZ_UV_TAPS * N_PHASES];	   /* 0x600 */
+    CARD16 RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES];
 } I830OverlayRegRec, *I830OverlayRegPtr;
 
 #if VIDEO_DEBUG
 static void
 CompareOverlay(I830Ptr pI830, CARD32 * overlay, int size)
 {
-   int i;
-   CARD32 val;
-   int bad = 0;
-
-   for (i = 0; i < size; i += 4) {
-      val = INREG(0x30100 + i);
-      if (val != overlay[i / 4]) {
-	 OVERLAY_DEBUG("0x%05x value doesn't match (0x%lx != 0x%lx)\n",
-		0x30100 + i, val, overlay[i / 4]);
-	 bad++;
-      }
-   }
-   if (!bad)
-      OVERLAY_DEBUG("CompareOverlay: no differences\n");
+    int i;
+    CARD32 val;
+    int bad = 0;
+
+    for (i = 0; i < size; i += 4) {
+	val = INREG(0x30100 + i);
+	if (val != overlay[i / 4]) {
+	    OVERLAY_DEBUG("0x%05x value doesn't match (0x%lx != 0x%lx)\n",
+			  0x30100 + i, val, overlay[i / 4]);
+	    bad++;
+	}
+    }
+    if (!bad)
+	OVERLAY_DEBUG("CompareOverlay: no differences\n");
 }
 #endif
 
@@ -369,7 +356,7 @@ i830_overlay_on(ScrnInfoPtr pScrn)
     I830Ptr pI830 = I830PTR(pScrn);
     I830OverlayRegPtr	overlay = (I830OverlayRegPtr) (pI830->FbBase +
 						       pI830->overlay_regs->offset);
-    
+
     if (*pI830->overlayOn)
 	return;
 
@@ -414,10 +401,10 @@ i830_overlay_off(ScrnInfoPtr pScrn)
     I830Ptr pI830 = I830PTR(pScrn);
     I830OverlayRegPtr	overlay = (I830OverlayRegPtr) (pI830->FbBase +
 						       pI830->overlay_regs->offset);
-    
+
     if (!*pI830->overlayOn)
 	return;
-    
+
     overlay->OCMD &= ~OVERLAY_ENABLE;
     BEGIN_LP_RING(6);
     OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE);
@@ -435,165 +422,165 @@ i830_overlay_off(ScrnInfoPtr pScrn)
 void
 I830InitVideo(ScreenPtr pScreen)
 {
-   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-   I830Ptr pI830 = I830PTR(pScrn);
-   XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
-   XF86VideoAdaptorPtr overlayAdaptor = NULL, texturedAdaptor = NULL;
-   int num_adaptors;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+    XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
+    XF86VideoAdaptorPtr overlayAdaptor = NULL, texturedAdaptor = NULL;
+    int num_adaptors;
 
 #if 0
-   {
-      I830OverlayRegRec tmp;
+    {
+	I830OverlayRegRec tmp;
+
+	ErrorF("sizeof I830OverlayRegRec is 0x%x\n", sizeof(I830OverlayRegRec));
+	ErrorF("Reserved C, D, E, F, G are %x, %x, %x, %x, %x\n",
+	       (unsigned long)&(tmp.RESERVEDC[0]) - (unsigned long)&tmp,
+	       (unsigned long)&(tmp.RESERVEDD[0]) - (unsigned long)&tmp,
+	       (unsigned long)&(tmp.RESERVEDE[0]) - (unsigned long)&tmp,
+	       (unsigned long)&(tmp.RESERVEDF[0]) - (unsigned long)&tmp,
+	       (unsigned long)&(tmp.RESERVEDG[0]) - (unsigned long)&tmp);
+    }
+#endif
+
+    num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
+    /* Give our adaptor list enough space for the overlay and/or texture video
+     * adaptors.
+     */
+    newAdaptors = xalloc((num_adaptors + 2) * sizeof(XF86VideoAdaptorPtr *));
+    if (newAdaptors == NULL)
+	return;
+
+    memcpy(newAdaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr));
+    adaptors = newAdaptors;
 
-      ErrorF("sizeof I830OverlayRegRec is 0x%x\n", sizeof(I830OverlayRegRec));
-      ErrorF("Reserved C, D, E, F, G are %x, %x, %x, %x, %x\n",
-	     (unsigned long)&(tmp.RESERVEDC[0]) - (unsigned long)&tmp,
-	     (unsigned long)&(tmp.RESERVEDD[0]) - (unsigned long)&tmp,
-	     (unsigned long)&(tmp.RESERVEDE[0]) - (unsigned long)&tmp,
-	     (unsigned long)&(tmp.RESERVEDF[0]) - (unsigned long)&tmp,
-	     (unsigned long)&(tmp.RESERVEDG[0]) - (unsigned long)&tmp);
-   }
-#endif
-
-   num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
-   /* Give our adaptor list enough space for the overlay and/or texture video
-    * adaptors.
-    */
-   newAdaptors = xalloc((num_adaptors + 2) * sizeof(XF86VideoAdaptorPtr *));
-   if (newAdaptors == NULL)
-      return;
-
-   memcpy(newAdaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr));
-   adaptors = newAdaptors;
-
-   /* Add the adaptors supported by our hardware.  First, set up the atoms
-    * that will be used by both output adaptors.
-    */
-   xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
-   xvContrast = MAKE_ATOM("XV_CONTRAST");
-
-   /* Set up textured video if we can do it at this depth and we are on
-    * supported hardware.
-    */
-   if (pScrn->bitsPerPixel >= 16 && (IS_I9XX(pI830) || IS_I965G(pI830))) {
-      texturedAdaptor = I830SetupImageVideoTextured(pScreen);
-      if (texturedAdaptor != NULL) {
-	 adaptors[num_adaptors++] = texturedAdaptor;
-	 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up textured video\n");
-      } else {
-	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		    "Failed to set up textured video\n");
-      }
-   }
-
-   /* Set up overlay video if we can do it at this depth. */
-   if (!IS_I965G(pI830) && pScrn->bitsPerPixel != 8 &&
-       pI830->overlay_regs != NULL)
-   {
-      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);
-   }
+    /* Add the adaptors supported by our hardware.  First, set up the atoms
+     * that will be used by both output adaptors.
+     */
+    xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
+    xvContrast = MAKE_ATOM("XV_CONTRAST");
+
+    /* Set up textured video if we can do it at this depth and we are on
+     * supported hardware.
+     */
+    if (pScrn->bitsPerPixel >= 16 && (IS_I9XX(pI830) || IS_I965G(pI830))) {
+	texturedAdaptor = I830SetupImageVideoTextured(pScreen);
+	if (texturedAdaptor != NULL) {
+	    adaptors[num_adaptors++] = texturedAdaptor;
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up textured video\n");
+	} else {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Failed to set up textured video\n");
+	}
+    }
+
+    /* Set up overlay video if we can do it at this depth. */
+    if (!IS_I965G(pI830) && pScrn->bitsPerPixel != 8 &&
+	pI830->overlay_regs != NULL)
+    {
+	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);
+    if (num_adaptors)
+	xf86XVScreenInit(pScreen, adaptors, num_adaptors);
 
-   xfree(adaptors);
+    xfree(adaptors);
 }
 
 static int
 I830CrtcPipe (xf86CrtcPtr crtc)
 {
-   if (crtc == NULL)
-      return 0;
-   return ((I830CrtcPrivatePtr) crtc->driver_private)->pipe;
+    if (crtc == NULL)
+	return 0;
+    return ((I830CrtcPrivatePtr) crtc->driver_private)->pipe;
 }
 
 static void
 I830ResetVideo(ScrnInfoPtr pScrn)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
-   I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr;
-   I830OverlayRegPtr overlay =
-	 (I830OverlayRegPtr) (pI830->FbBase + pI830->overlay_regs->offset);
-
-   OVERLAY_DEBUG("I830ResetVideo: base: %p, offset: 0x%lx, obase: %p\n",
-	   pI830->FbBase, pI830->overlay_regs->offset, overlay);
-   /*
-    * Default to maximum image size in YV12
-    */
-
-   memset(overlay, 0, sizeof(*overlay));
-   overlay->YRGB_VPH = 0;
-   overlay->UV_VPH = 0;
-   overlay->HORZ_PH = 0;
-   overlay->INIT_PHS = 0;
-   overlay->DWINPOS = 0;
-   overlay->DWINSZ = 0;
-   overlay->SWIDTH = 0;
-   overlay->SWIDTHSW = 0;
-   overlay->SHEIGHT = 0;
-   overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff);
-   overlay->OCLRC1 = pPriv->saturation;
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr;
+    I830OverlayRegPtr overlay =
+    (I830OverlayRegPtr) (pI830->FbBase + pI830->overlay_regs->offset);
+
+    OVERLAY_DEBUG("I830ResetVideo: base: %p, offset: 0x%lx, obase: %p\n",
+		  pI830->FbBase, pI830->overlay_regs->offset, overlay);
+    /*
+     * Default to maximum image size in YV12
+     */
+
+    memset(overlay, 0, sizeof(*overlay));
+    overlay->YRGB_VPH = 0;
+    overlay->UV_VPH = 0;
+    overlay->HORZ_PH = 0;
+    overlay->INIT_PHS = 0;
+    overlay->DWINPOS = 0;
+    overlay->DWINSZ = 0;
+    overlay->SWIDTH = 0;
+    overlay->SWIDTHSW = 0;
+    overlay->SHEIGHT = 0;
+    overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff);
+    overlay->OCLRC1 = pPriv->saturation;
 #if 0
-   overlay->AWINPOS = 0;
-   overlay->AWINSZ = 0;
+    overlay->AWINPOS = 0;
+    overlay->AWINSZ = 0;
 #endif
-   overlay->FASTHSCALE = 0;
+    overlay->FASTHSCALE = 0;
 
-   /*
-    * Enable destination color keying
-    */
-   switch (pScrn->depth) {
-   case 8:
-      overlay->DCLRKV = 0;
-      overlay->DCLRKM = 0xffffff | DEST_KEY_ENABLE;
-      break;
-   case 15:
-      overlay->DCLRKV = RGB15ToColorKey(pPriv->colorKey);
-      overlay->DCLRKM = 0x070707 | DEST_KEY_ENABLE;
-      break;
-   case 16:
-      overlay->DCLRKV = RGB16ToColorKey(pPriv->colorKey);
-      overlay->DCLRKM = 0x070307 | DEST_KEY_ENABLE;
-      break;
-   default:
-      overlay->DCLRKV = pPriv->colorKey;
-      overlay->DCLRKM = DEST_KEY_ENABLE;
-      break;
-   }
-
-   overlay->SCLRKVH = 0;
-   overlay->SCLRKVL = 0;
-   overlay->SCLRKEN = 0;		/* source color key disable */
-   overlay->OCONFIG = CC_OUT_8BIT;
-
-   /*
-    * Select which pipe the overlay is enabled on.
-    */
-   overlay->OCONFIG &= ~OVERLAY_PIPE_MASK;
-   if (I830CrtcPipe (pPriv->current_crtc) == 0)
-      overlay->OCONFIG |= OVERLAY_PIPE_A;
-   else 
-      overlay->OCONFIG |= OVERLAY_PIPE_B;
+    /*
+     * Enable destination color keying
+     */
+    switch (pScrn->depth) {
+    case 8:
+	overlay->DCLRKV = 0;
+	overlay->DCLRKM = 0xffffff | DEST_KEY_ENABLE;
+	break;
+    case 15:
+	overlay->DCLRKV = RGB15ToColorKey(pPriv->colorKey);
+	overlay->DCLRKM = 0x070707 | DEST_KEY_ENABLE;
+	break;
+    case 16:
+	overlay->DCLRKV = RGB16ToColorKey(pPriv->colorKey);
+	overlay->DCLRKM = 0x070307 | DEST_KEY_ENABLE;
+	break;
+    default:
+	overlay->DCLRKV = pPriv->colorKey;
+	overlay->DCLRKM = DEST_KEY_ENABLE;
+	break;
+    }
+
+    overlay->SCLRKVH = 0;
+    overlay->SCLRKVL = 0;
+    overlay->SCLRKEN = 0;		/* source color key disable */
+    overlay->OCONFIG = CC_OUT_8BIT;
+
+    /*
+     * Select which pipe the overlay is enabled on.
+     */
+    overlay->OCONFIG &= ~OVERLAY_PIPE_MASK;
+    if (I830CrtcPipe (pPriv->current_crtc) == 0)
+	overlay->OCONFIG |= OVERLAY_PIPE_A;
+    else 
+	overlay->OCONFIG |= OVERLAY_PIPE_B;
 
 #if 0
-   /* 
-    * XXX DUMP REGISTER CODE !!!
-    * This allows us to dump the complete i845 registers and compare
-    * with warm boot situations before we upload our first copy.
-    */
-   {
-      int i;
-      for (i = 0x30000; i < 0x31000; i += 4)
-	 ErrorF("0x%x 0x%lx\n", i, INREG(i));
-   }
+    /* 
+     * XXX DUMP REGISTER CODE !!!
+     * This allows us to dump the complete i845 registers and compare
+     * with warm boot situations before we upload our first copy.
+     */
+    {
+	int i;
+	for (i = 0x30000; i < 0x31000; i += 4)
+	    ErrorF("0x%x 0x%lx\n", i, INREG(i));
+    }
 #endif
 }
 
@@ -606,336 +593,336 @@ I830ResetVideo(ScrnInfoPtr pScrn)
 static void
 I830SetOneLineModeRatio(ScrnInfoPtr pScrn)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
-   I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr;
-   CARD32 panelFitControl = INREG(PFIT_CONTROLS);
-   int vertScale;
-
-   pPriv->scaleRatio = 0x10000;
-
-   if (panelFitControl & PFIT_ON_MASK) {
-      if (panelFitControl & PFIT_AUTOVSCALE_MASK) {
-         vertScale = INREG(PFIT_AUTOSCALE_RATIO) >> 16;
-      } else {
-         vertScale = INREG(PFIT_PROGRAMMED_SCALE_RATIO) >> 16;
-      }
-
-      if (vertScale != 0)
-         pPriv->scaleRatio = ((double) 0x10000 / (double)vertScale) * 0x10000;
- 
-      pPriv->oneLineMode = TRUE;
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr;
+    CARD32 panelFitControl = INREG(PFIT_CONTROLS);
+    int vertScale;
 
-      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabling Xvideo one-line mode\n");
-   }
+    pPriv->scaleRatio = 0x10000;
 
-   if (pPriv->scaleRatio == 0x10000)
-      pPriv->oneLineMode = FALSE;
+    if (panelFitControl & PFIT_ON_MASK) {
+	if (panelFitControl & PFIT_AUTOVSCALE_MASK) {
+	    vertScale = INREG(PFIT_AUTOSCALE_RATIO) >> 16;
+	} else {
+	    vertScale = INREG(PFIT_PROGRAMMED_SCALE_RATIO) >> 16;
+	}
+
+	if (vertScale != 0)
+	    pPriv->scaleRatio = ((double) 0x10000 / (double)vertScale) * 0x10000;
+
+	pPriv->oneLineMode = TRUE;
+
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabling Xvideo one-line mode\n");
+    }
+
+    if (pPriv->scaleRatio == 0x10000)
+	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;
+    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      ));
+    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;
-   CARD32   gamma0 = pPriv->gamma0;
-   CARD32   gamma1 = pPriv->gamma1;
-   CARD32   gamma2 = pPriv->gamma2;
-   CARD32   gamma3 = pPriv->gamma3;
-   CARD32   gamma4 = pPriv->gamma4;
-   CARD32   gamma5 = pPriv->gamma5;
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr;
+    CARD32   gamma0 = pPriv->gamma0;
+    CARD32   gamma1 = pPriv->gamma1;
+    CARD32   gamma2 = pPriv->gamma2;
+    CARD32   gamma3 = pPriv->gamma3;
+    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);
+    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);
+    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);
+    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);
-   OUTREG(OGAMC3, gamma3);
-   OUTREG(OGAMC2, gamma2);
-   OUTREG(OGAMC1, gamma1);
-   OUTREG(OGAMC0, gamma0);
+    OUTREG(OGAMC5, gamma5);
+    OUTREG(OGAMC4, gamma4);
+    OUTREG(OGAMC3, gamma3);
+    OUTREG(OGAMC2, gamma2);
+    OUTREG(OGAMC1, gamma1);
+    OUTREG(OGAMC0, gamma0);
 }
 
 static XF86VideoAdaptorPtr
 I830SetupImageVideoOverlay(ScreenPtr pScreen)
 {
-   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-   I830Ptr pI830 = I830PTR(pScrn);
-   XF86VideoAdaptorPtr adapt;
-   I830PortPrivPtr pPriv;
-   XF86AttributePtr att;
-
-   OVERLAY_DEBUG("I830SetupImageVideoOverlay\n");
-
-   if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
-			 sizeof(I830PortPrivRec) + sizeof(DevUnion))))
-      return NULL;
-
-   adapt->type = XvWindowMask | XvInputMask | XvImageMask;
-   adapt->flags = VIDEO_OVERLAID_IMAGES /*| VIDEO_CLIP_TO_VIEWPORT*/;
-   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;
-   adapt->pPortPrivates = (DevUnion *) (&adapt[1]);
-
-   pPriv = (I830PortPrivPtr) (&adapt->pPortPrivates[1]);
-
-   adapt->pPortPrivates[0].ptr = (pointer) (pPriv);
-   adapt->nAttributes = NUM_ATTRIBUTES;
-   adapt->nAttributes += CLONE_ATTRIBUTES;
-   if (IS_I9XX(pI830))
-      adapt->nAttributes += GAMMA_ATTRIBUTES; /* has gamma */
-   adapt->pAttributes = xnfalloc(sizeof(XF86AttributeRec) * adapt->nAttributes);
-   /* Now copy the attributes */
-   att = adapt->pAttributes;
-   memcpy((char *)att, (char*)Attributes, sizeof(XF86AttributeRec)* NUM_ATTRIBUTES);
-   att+=NUM_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;
-   }
-   adapt->nImages = NUM_IMAGES;
-   adapt->pImages = Images;
-   adapt->PutVideo = NULL;
-   adapt->PutStill = NULL;
-   adapt->GetVideo = NULL;
-   adapt->GetStill = NULL;
-   adapt->StopVideo = I830StopVideo;
-   adapt->SetPortAttribute = I830SetPortAttribute;
-   adapt->GetPortAttribute = I830GetPortAttribute;
-   adapt->QueryBestSize = I830QueryBestSize;
-   adapt->PutImage = I830PutImage;
-   adapt->QueryImageAttributes = I830QueryImageAttributesOverlay;
-
-   pPriv->textured = FALSE;
-   pPriv->colorKey = pI830->colorKey & ((1 << pScrn->depth) - 1);
-   pPriv->videoStatus = 0;
-   pPriv->brightness = 0;
-   pPriv->contrast = 64;
-   pPriv->saturation = 128;
-   pPriv->current_crtc = NULL;
-   pPriv->desired_crtc = NULL;
-   memset(&pPriv->linear, 0, sizeof(pPriv->linear));
-   pPriv->currentBuf = 0;
-   pPriv->gamma5 = 0xc0c0c0;
-   pPriv->gamma4 = 0x808080;
-   pPriv->gamma3 = 0x404040;
-   pPriv->gamma2 = 0x202020;
-   pPriv->gamma1 = 0x101010;
-   pPriv->gamma0 = 0x080808;
-   pPriv->doubleBuffer = 1;
-
-   /* gotta uninit this someplace */
-   REGION_NULL(pScreen, &pPriv->clip);
-
-   pI830->adaptor = adapt;
-
-   /* With LFP's we need to detect whether we're in One Line Mode, which
-    * essentially means a resolution greater than 1024x768, and fix up
-    * the scaler accordingly. */
-   pPriv->scaleRatio = 0x10000;
-   pPriv->oneLineMode = FALSE;
-
-   /*
-    * Initialise pPriv->overlayOK.  Set it to TRUE here so that a warning will
-    * be generated if i830_crtc_dpms_video() sets it to FALSE during mode
-    * setup.
-    */
-   pPriv->overlayOK = TRUE;
-
-   pI830->BlockHandler = pScreen->BlockHandler;
-   pScreen->BlockHandler = I830BlockHandler;
-
-   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 */
-   xvPipe = MAKE_ATOM("XV_PIPE");
-   
-   if (IS_I9XX(pI830)) {
-     xvGamma0 = MAKE_ATOM("XV_GAMMA0");
-     xvGamma1 = MAKE_ATOM("XV_GAMMA1");
-     xvGamma2 = MAKE_ATOM("XV_GAMMA2");
-     xvGamma3 = MAKE_ATOM("XV_GAMMA3");
-     xvGamma4 = MAKE_ATOM("XV_GAMMA4");
-     xvGamma5 = MAKE_ATOM("XV_GAMMA5");
-   }
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+    XF86VideoAdaptorPtr adapt;
+    I830PortPrivPtr pPriv;
+    XF86AttributePtr att;
+
+    OVERLAY_DEBUG("I830SetupImageVideoOverlay\n");
+
+    if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
+			  sizeof(I830PortPrivRec) + sizeof(DevUnion))))
+	return NULL;
+
+    adapt->type = XvWindowMask | XvInputMask | XvImageMask;
+    adapt->flags = VIDEO_OVERLAID_IMAGES /*| VIDEO_CLIP_TO_VIEWPORT*/;
+    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;
+    adapt->pPortPrivates = (DevUnion *) (&adapt[1]);
+
+    pPriv = (I830PortPrivPtr) (&adapt->pPortPrivates[1]);
+
+    adapt->pPortPrivates[0].ptr = (pointer) (pPriv);
+    adapt->nAttributes = NUM_ATTRIBUTES;
+    adapt->nAttributes += CLONE_ATTRIBUTES;
+    if (IS_I9XX(pI830))
+	adapt->nAttributes += GAMMA_ATTRIBUTES; /* has gamma */
+    adapt->pAttributes = xnfalloc(sizeof(XF86AttributeRec) * adapt->nAttributes);
+    /* Now copy the attributes */
+    att = adapt->pAttributes;
+    memcpy((char *)att, (char*)Attributes, sizeof(XF86AttributeRec)* NUM_ATTRIBUTES);
+    att+=NUM_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;
+    }
+    adapt->nImages = NUM_IMAGES;
+    adapt->pImages = Images;
+    adapt->PutVideo = NULL;
+    adapt->PutStill = NULL;
+    adapt->GetVideo = NULL;
+    adapt->GetStill = NULL;
+    adapt->StopVideo = I830StopVideo;
+    adapt->SetPortAttribute = I830SetPortAttribute;
+    adapt->GetPortAttribute = I830GetPortAttribute;
+    adapt->QueryBestSize = I830QueryBestSize;
+    adapt->PutImage = I830PutImage;
+    adapt->QueryImageAttributes = I830QueryImageAttributesOverlay;
+
+    pPriv->textured = FALSE;
+    pPriv->colorKey = pI830->colorKey & ((1 << pScrn->depth) - 1);
+    pPriv->videoStatus = 0;
+    pPriv->brightness = 0;
+    pPriv->contrast = 64;
+    pPriv->saturation = 128;
+    pPriv->current_crtc = NULL;
+    pPriv->desired_crtc = NULL;
+    memset(&pPriv->linear, 0, sizeof(pPriv->linear));
+    pPriv->currentBuf = 0;
+    pPriv->gamma5 = 0xc0c0c0;
+    pPriv->gamma4 = 0x808080;
+    pPriv->gamma3 = 0x404040;
+    pPriv->gamma2 = 0x202020;
+    pPriv->gamma1 = 0x101010;
+    pPriv->gamma0 = 0x080808;
+    pPriv->doubleBuffer = 1;
+
+    /* gotta uninit this someplace */
+    REGION_NULL(pScreen, &pPriv->clip);
+
+    pI830->adaptor = adapt;
+
+    /* With LFP's we need to detect whether we're in One Line Mode, which
+     * essentially means a resolution greater than 1024x768, and fix up
+     * the scaler accordingly. */
+    pPriv->scaleRatio = 0x10000;
+    pPriv->oneLineMode = FALSE;
+
+    /*
+     * Initialise pPriv->overlayOK.  Set it to TRUE here so that a warning will
+     * be generated if i830_crtc_dpms_video() sets it to FALSE during mode
+     * setup.
+     */
+    pPriv->overlayOK = TRUE;
+
+    pI830->BlockHandler = pScreen->BlockHandler;
+    pScreen->BlockHandler = I830BlockHandler;
+
+    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 */
+    xvPipe = MAKE_ATOM("XV_PIPE");
+
+    if (IS_I9XX(pI830)) {
+	xvGamma0 = MAKE_ATOM("XV_GAMMA0");
+	xvGamma1 = MAKE_ATOM("XV_GAMMA1");
+	xvGamma2 = MAKE_ATOM("XV_GAMMA2");
+	xvGamma3 = MAKE_ATOM("XV_GAMMA3");
+	xvGamma4 = MAKE_ATOM("XV_GAMMA4");
+	xvGamma5 = MAKE_ATOM("XV_GAMMA5");
+    }
 
-   I830ResetVideo(pScrn);
+    I830ResetVideo(pScrn);
 
-   I830UpdateGamma(pScrn);
+    I830UpdateGamma(pScrn);
 
-   return adapt;
+    return adapt;
 }
 
 static XF86VideoAdaptorPtr
 I830SetupImageVideoTextured(ScreenPtr pScreen)
 {
-   XF86VideoAdaptorPtr adapt;
-   XF86AttributePtr attrs;
-   I830PortPrivPtr portPrivs;
-   DevUnion *devUnions;
-   int nports = 16, i;
-   int nAttributes;
-
-   OVERLAY_DEBUG("I830SetupImageVideoOverlay\n");
-
-   nAttributes = NUM_TEXTURED_ATTRIBUTES;
-
-   adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec));
-   portPrivs = xcalloc(nports, sizeof(I830PortPrivRec));
-   devUnions = xcalloc(nports, sizeof(DevUnion));
-   attrs = xcalloc(nAttributes, sizeof(XF86AttributeRec));
-   if (adapt == NULL || portPrivs == NULL || devUnions == NULL ||
-       attrs == NULL)
-   {
-      xfree(adapt);
-      xfree(portPrivs);
-      xfree(devUnions);
-      xfree(attrs);
-      return NULL;
-   }
-
-   adapt->type = XvWindowMask | XvInputMask | XvImageMask;
-   adapt->flags = 0;
-   adapt->name = "Intel(R) Textured Video";
-   adapt->nEncodings = 1;
-   adapt->pEncodings = DummyEncoding;
-   adapt->nFormats = NUM_FORMATS;
-   adapt->pFormats = Formats;
-   adapt->nPorts = nports;
-   adapt->pPortPrivates = devUnions;
-   adapt->nAttributes = nAttributes;
-   adapt->pAttributes = attrs;
-   memcpy(attrs, TexturedAttributes, nAttributes * sizeof(XF86AttributeRec));
-   adapt->nImages = NUM_IMAGES;
-   adapt->pImages = Images;
-   adapt->PutVideo = NULL;
-   adapt->PutStill = NULL;
-   adapt->GetVideo = NULL;
-   adapt->GetStill = NULL;
-   adapt->StopVideo = I830StopVideo;
-   adapt->SetPortAttribute = I830SetPortAttribute;
-   adapt->GetPortAttribute = I830GetPortAttribute;
-   adapt->QueryBestSize = I830QueryBestSize;
-   adapt->PutImage = I830PutImage;
-   adapt->QueryImageAttributes = I830QueryImageAttributesTextured;
-
-   for (i = 0; i < nports; i++) {
-      I830PortPrivPtr pPriv = &portPrivs[i];
-
-      pPriv->textured = TRUE;
-      pPriv->videoStatus = 0;
-      memset(&pPriv->linear, 0, sizeof(pPriv->linear));
-      pPriv->currentBuf = 0;
-      pPriv->doubleBuffer = 0;
+    XF86VideoAdaptorPtr adapt;
+    XF86AttributePtr attrs;
+    I830PortPrivPtr portPrivs;
+    DevUnion *devUnions;
+    int nports = 16, i;
+    int nAttributes;
+
+    OVERLAY_DEBUG("I830SetupImageVideoOverlay\n");
+
+    nAttributes = NUM_TEXTURED_ATTRIBUTES;
+
+    adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec));
+    portPrivs = xcalloc(nports, sizeof(I830PortPrivRec));
+    devUnions = xcalloc(nports, sizeof(DevUnion));
+    attrs = xcalloc(nAttributes, sizeof(XF86AttributeRec));
+    if (adapt == NULL || portPrivs == NULL || devUnions == NULL ||
+	attrs == NULL)
+    {
+	xfree(adapt);
+	xfree(portPrivs);
+	xfree(devUnions);
+	xfree(attrs);
+	return NULL;
+    }
+
+    adapt->type = XvWindowMask | XvInputMask | XvImageMask;
+    adapt->flags = 0;
+    adapt->name = "Intel(R) Textured Video";
+    adapt->nEncodings = 1;
+    adapt->pEncodings = DummyEncoding;
+    adapt->nFormats = NUM_FORMATS;
+    adapt->pFormats = Formats;
+    adapt->nPorts = nports;
+    adapt->pPortPrivates = devUnions;
+    adapt->nAttributes = nAttributes;
+    adapt->pAttributes = attrs;
+    memcpy(attrs, TexturedAttributes, nAttributes * sizeof(XF86AttributeRec));
+    adapt->nImages = NUM_IMAGES;
+    adapt->pImages = Images;
+    adapt->PutVideo = NULL;
+    adapt->PutStill = NULL;
+    adapt->GetVideo = NULL;
+    adapt->GetStill = NULL;
+    adapt->StopVideo = I830StopVideo;
+    adapt->SetPortAttribute = I830SetPortAttribute;
+    adapt->GetPortAttribute = I830GetPortAttribute;
+    adapt->QueryBestSize = I830QueryBestSize;
+    adapt->PutImage = I830PutImage;
+    adapt->QueryImageAttributes = I830QueryImageAttributesTextured;
+
+    for (i = 0; i < nports; i++) {
+	I830PortPrivPtr pPriv = &portPrivs[i];
+
+	pPriv->textured = TRUE;
+	pPriv->videoStatus = 0;
+	memset(&pPriv->linear, 0, sizeof(pPriv->linear));
+	pPriv->currentBuf = 0;
+	pPriv->doubleBuffer = 0;
 
-      /* gotta uninit this someplace, XXX: shouldn't be necessary for textured */
-      REGION_NULL(pScreen, &pPriv->clip);
+	/* gotta uninit this someplace, XXX: shouldn't be necessary for textured */
+	REGION_NULL(pScreen, &pPriv->clip);
 
-      adapt->pPortPrivates[i].ptr = (pointer) (pPriv);
-   }
+	adapt->pPortPrivates[i].ptr = (pointer) (pPriv);
+    }
 
-   return adapt;
+    return adapt;
 }
 
 static Bool
 RegionsEqual(RegionPtr A, RegionPtr B)
 {
-   int *dataA, *dataB;
-   int num;
+    int *dataA, *dataB;
+    int num;
 
-   num = REGION_NUM_RECTS(A);
-   if (num != REGION_NUM_RECTS(B))
-      return FALSE;
-
-   if ((A->extents.x1 != B->extents.x1) ||
-       (A->extents.x2 != B->extents.x2) ||
-       (A->extents.y1 != B->extents.y1) || (A->extents.y2 != B->extents.y2))
-      return FALSE;
-
-   dataA = (int *)REGION_RECTS(A);
-   dataB = (int *)REGION_RECTS(B);
-
-   while (num--) {
-      if ((dataA[0] != dataB[0]) || (dataA[1] != dataB[1]))
-	 return FALSE;
-      dataA += 2;
-      dataB += 2;
-   }
+    num = REGION_NUM_RECTS(A);
+    if (num != REGION_NUM_RECTS(B))
+	return FALSE;
+
+    if ((A->extents.x1 != B->extents.x1) ||
+	(A->extents.x2 != B->extents.x2) ||
+	(A->extents.y1 != B->extents.y1) || (A->extents.y2 != B->extents.y2))
+	return FALSE;
+
+    dataA = (int *)REGION_RECTS(A);
+    dataB = (int *)REGION_RECTS(B);
+
+    while (num--) {
+	if ((dataA[0] != dataB[0]) || (dataA[1] != dataB[1]))
+	    return FALSE;
+	dataA += 2;
+	dataB += 2;
+    }
 
-   return TRUE;
+    return TRUE;
 }
 
 static void
 I830StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
 {
-   I830PortPrivPtr pPriv = (I830PortPrivPtr) data;
-   I830Ptr pI830 = I830PTR(pScrn);
+    I830PortPrivPtr pPriv = (I830PortPrivPtr) data;
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    if (pPriv->textured)
+	return;
 
-   if (pPriv->textured)
-      return;
+    OVERLAY_DEBUG("I830StopVideo\n");
 
-   OVERLAY_DEBUG("I830StopVideo\n");
+    REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
 
-   REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
-
-   if (shutdown) {
-      if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
-	 i830_overlay_off(pScrn);
-         if (pI830->entityPrivate)
-            pI830->entityPrivate->XvInUse = -1;
-      }
-      I830FreeMemory(pScrn, &pPriv->linear);
-      pPriv->videoStatus = 0;
-   } else {
-      if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
-	 pPriv->videoStatus |= OFF_TIMER;
-	 pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
-      }
-   }
+    if (shutdown) {
+	if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
+	    i830_overlay_off(pScrn);
+	    if (pI830->entityPrivate)
+		pI830->entityPrivate->XvInUse = -1;
+	}
+	I830FreeMemory(pScrn, &pPriv->linear);
+	pPriv->videoStatus = 0;
+    } else {
+	if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
+	    pPriv->videoStatus |= OFF_TIMER;
+	    pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
+	}
+    }
 
 }
 
@@ -943,148 +930,148 @@ static int
 I830SetPortAttribute(ScrnInfoPtr pScrn,
 		     Atom attribute, INT32 value, pointer data)
 {
-   I830PortPrivPtr pPriv = (I830PortPrivPtr) data;
-   I830Ptr pI830 = I830PTR(pScrn);
-   I830OverlayRegPtr overlay;
-
-   if (pPriv->textured) {
-      /* XXX: Currently the brightness/saturation attributes aren't hooked up.
-       * However, apps expect them to be there, and the spec seems to let us
-       * sneak out of actually implementing them for now.
-       */
-      return Success;
-   }
-
-   overlay = (I830OverlayRegPtr) (pI830->FbBase + pI830->overlay_regs->offset);
-
-   if (attribute == xvBrightness) {
-      if ((value < -128) || (value > 127))
-	 return BadValue;
-      pPriv->brightness = value;
-      overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff);
-      OVERLAY_DEBUG("BRIGHTNESS\n");
-      if (*pI830->overlayOn)
-	 i830_overlay_continue (pScrn);
-   } else if (attribute == xvContrast) {
-      if ((value < 0) || (value > 255))
-	 return BadValue;
-      pPriv->contrast = value;
-      overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff);
-      OVERLAY_DEBUG("CONTRAST\n");
-      if (*pI830->overlayOn)
-	 i830_overlay_continue (pScrn);
-   } else if (attribute == xvSaturation) {
-      if ((value < 0) || (value > 1023))
-	 return BadValue;
-      pPriv->saturation = value;
-      overlay->OCLRC1 = pPriv->saturation;
-      if (*pI830->overlayOn)
-	 i830_overlay_continue (pScrn);
-   } else if (attribute == xvPipe) {
-      xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-      if ((value < -1) || (value > xf86_config->num_crtc))
-         return BadValue;
-      if (value < 0)
-	 pPriv->desired_crtc = NULL;
-      else
-	 pPriv->desired_crtc = xf86_config->crtc[value];
-      /*
-       * Leave this to be updated at the next frame
-       */
-   } else if (attribute == xvGamma0 && (IS_I9XX(pI830))) {
-      pPriv->gamma0 = value; 
-   } else if (attribute == xvGamma1 && (IS_I9XX(pI830))) {
-      pPriv->gamma1 = value;
-   } else if (attribute == xvGamma2 && (IS_I9XX(pI830))) {
-      pPriv->gamma2 = value;
-   } else if (attribute == xvGamma3 && (IS_I9XX(pI830))) {
-      pPriv->gamma3 = value;
-   } else if (attribute == xvGamma4 && (IS_I9XX(pI830))) {
-      pPriv->gamma4 = value;
-   } else if (attribute == xvGamma5 && (IS_I9XX(pI830))) {
-      pPriv->gamma5 = value;
-   } else if (attribute == xvColorKey) {
-      pPriv->colorKey = value;
-      switch (pScrn->depth) {
-      case 16:
-	 overlay->DCLRKV = RGB16ToColorKey(pPriv->colorKey);
-	 break;
-      case 15:
-	 overlay->DCLRKV = RGB15ToColorKey(pPriv->colorKey);
-	 break;
-      default:
-	 overlay->DCLRKV = pPriv->colorKey;
-	 break;
-      }
-      OVERLAY_DEBUG("COLORKEY\n");
-      if (*pI830->overlayOn)
-	 i830_overlay_continue (pScrn);
-      REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
-   } else if(attribute == xvDoubleBuffer) {
-      if ((value < 0) || (value > 1))
-         return BadValue;
-      /* Do not allow buffer change while playing video */
-      if(!*pI830->overlayOn)
-     	 pPriv->doubleBuffer = value;
-   } else
-      return BadMatch;
-
-   /* Ensure that the overlay is off, ready for updating */
-   if ((attribute == xvGamma0 ||
-        attribute == xvGamma1 ||
-        attribute == xvGamma2 ||
-        attribute == xvGamma3 ||
-        attribute == xvGamma4 ||
-        attribute == xvGamma5) && (IS_I9XX(pI830))) {
-        OVERLAY_DEBUG("GAMMA\n");
+    I830PortPrivPtr pPriv = (I830PortPrivPtr) data;
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830OverlayRegPtr overlay;
+
+    if (pPriv->textured) {
+	/* XXX: Currently the brightness/saturation attributes aren't hooked up.
+	 * However, apps expect them to be there, and the spec seems to let us
+	 * sneak out of actually implementing them for now.
+	 */
+	return Success;
+    }
+
+    overlay = (I830OverlayRegPtr) (pI830->FbBase + pI830->overlay_regs->offset);
+
+    if (attribute == xvBrightness) {
+	if ((value < -128) || (value > 127))
+	    return BadValue;
+	pPriv->brightness = value;
+	overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff);
+	OVERLAY_DEBUG("BRIGHTNESS\n");
+	if (*pI830->overlayOn)
+	    i830_overlay_continue (pScrn);
+    } else if (attribute == xvContrast) {
+	if ((value < 0) || (value > 255))
+	    return BadValue;
+	pPriv->contrast = value;
+	overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff);
+	OVERLAY_DEBUG("CONTRAST\n");
+	if (*pI830->overlayOn)
+	    i830_overlay_continue (pScrn);
+    } else if (attribute == xvSaturation) {
+	if ((value < 0) || (value > 1023))
+	    return BadValue;
+	pPriv->saturation = value;
+	overlay->OCLRC1 = pPriv->saturation;
+	if (*pI830->overlayOn)
+	    i830_overlay_continue (pScrn);
+    } else if (attribute == xvPipe) {
+	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+	if ((value < -1) || (value > xf86_config->num_crtc))
+	    return BadValue;
+	if (value < 0)
+	    pPriv->desired_crtc = NULL;
+	else
+	    pPriv->desired_crtc = xf86_config->crtc[value];
+	/*
+	 * Leave this to be updated at the next frame
+	 */
+    } else if (attribute == xvGamma0 && (IS_I9XX(pI830))) {
+	pPriv->gamma0 = value; 
+    } else if (attribute == xvGamma1 && (IS_I9XX(pI830))) {
+	pPriv->gamma1 = value;
+    } else if (attribute == xvGamma2 && (IS_I9XX(pI830))) {
+	pPriv->gamma2 = value;
+    } else if (attribute == xvGamma3 && (IS_I9XX(pI830))) {
+	pPriv->gamma3 = value;
+    } else if (attribute == xvGamma4 && (IS_I9XX(pI830))) {
+	pPriv->gamma4 = value;
+    } else if (attribute == xvGamma5 && (IS_I9XX(pI830))) {
+	pPriv->gamma5 = value;
+    } else if (attribute == xvColorKey) {
+	pPriv->colorKey = value;
+	switch (pScrn->depth) {
+	case 16:
+	    overlay->DCLRKV = RGB16ToColorKey(pPriv->colorKey);
+	    break;
+	case 15:
+	    overlay->DCLRKV = RGB15ToColorKey(pPriv->colorKey);
+	    break;
+	default:
+	    overlay->DCLRKV = pPriv->colorKey;
+	    break;
+	}
+	OVERLAY_DEBUG("COLORKEY\n");
+	if (*pI830->overlayOn)
+	    i830_overlay_continue (pScrn);
+	REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
+    } else if(attribute == xvDoubleBuffer) {
+	if ((value < 0) || (value > 1))
+	    return BadValue;
+	/* Do not allow buffer change while playing video */
+	if(!*pI830->overlayOn)
+	    pPriv->doubleBuffer = value;
+    } else
+	return BadMatch;
+
+    /* Ensure that the overlay is off, ready for updating */
+    if ((attribute == xvGamma0 ||
+	 attribute == xvGamma1 ||
+	 attribute == xvGamma2 ||
+	 attribute == xvGamma3 ||
+	 attribute == xvGamma4 ||
+	 attribute == xvGamma5) && (IS_I9XX(pI830))) {
+	OVERLAY_DEBUG("GAMMA\n");
 	I830UpdateGamma(pScrn);
-   }
+    }
 
-   return Success;
+    return Success;
 }
 
 static int
 I830GetPortAttribute(ScrnInfoPtr pScrn,
 		     Atom attribute, INT32 * value, pointer data)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
-   I830PortPrivPtr pPriv = (I830PortPrivPtr) data;
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830PortPrivPtr pPriv = (I830PortPrivPtr) data;
 
-   if (attribute == xvBrightness) {
-      *value = pPriv->brightness;
-   } else if (attribute == xvContrast) {
-      *value = pPriv->contrast;
-   } else if (attribute == xvSaturation) {
-      *value = pPriv->saturation;
-   } else if (attribute == xvPipe) {
-      int		c;
-      xf86CrtcConfigPtr	xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-      for (c = 0; c < xf86_config->num_crtc; c++)
-	 if (xf86_config->crtc[c] == pPriv->desired_crtc)
-	    break;
-      if (c == xf86_config->num_crtc)
-	 c = -1;
-      *value = c;
-   } else if (attribute == xvGamma0 && (IS_I9XX(pI830))) {
-      *value = pPriv->gamma0;
-   } else if (attribute == xvGamma1 && (IS_I9XX(pI830))) {
-      *value = pPriv->gamma1;
-   } else if (attribute == xvGamma2 && (IS_I9XX(pI830))) {
-      *value = pPriv->gamma2;
-   } else if (attribute == xvGamma3 && (IS_I9XX(pI830))) {
-      *value = pPriv->gamma3;
-   } else if (attribute == xvGamma4 && (IS_I9XX(pI830))) {
-      *value = pPriv->gamma4;
-   } else if (attribute == xvGamma5 && (IS_I9XX(pI830))) {
-      *value = pPriv->gamma5;
-   } else if (attribute == xvColorKey) {
-      *value = pPriv->colorKey;
-   } else if (attribute == xvDoubleBuffer) {
-      *value = pPriv->doubleBuffer;
-   } else 
-      return BadMatch;
+    if (attribute == xvBrightness) {
+	*value = pPriv->brightness;
+    } else if (attribute == xvContrast) {
+	*value = pPriv->contrast;
+    } else if (attribute == xvSaturation) {
+	*value = pPriv->saturation;
+    } else if (attribute == xvPipe) {
+	int		c;
+	xf86CrtcConfigPtr	xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+	for (c = 0; c < xf86_config->num_crtc; c++)
+	    if (xf86_config->crtc[c] == pPriv->desired_crtc)
+		break;
+	if (c == xf86_config->num_crtc)
+	    c = -1;
+	*value = c;
+    } else if (attribute == xvGamma0 && (IS_I9XX(pI830))) {
+	*value = pPriv->gamma0;
+    } else if (attribute == xvGamma1 && (IS_I9XX(pI830))) {
+	*value = pPriv->gamma1;
+    } else if (attribute == xvGamma2 && (IS_I9XX(pI830))) {
+	*value = pPriv->gamma2;
+    } else if (attribute == xvGamma3 && (IS_I9XX(pI830))) {
+	*value = pPriv->gamma3;
+    } else if (attribute == xvGamma4 && (IS_I9XX(pI830))) {
+	*value = pPriv->gamma4;
+    } else if (attribute == xvGamma5 && (IS_I9XX(pI830))) {
+	*value = pPriv->gamma5;
+    } else if (attribute == xvColorKey) {
+	*value = pPriv->colorKey;
+    } else if (attribute == xvDoubleBuffer) {
+	*value = pPriv->doubleBuffer;
+    } else 
+	return BadMatch;
 
-   return Success;
+    return Success;
 }
 
 static void
@@ -1094,13 +1081,13 @@ I830QueryBestSize(ScrnInfoPtr pScrn,
 		  short drw_w, short drw_h,
 		  unsigned int *p_w, unsigned int *p_h, pointer data)
 {
-   if (vid_w > (drw_w << 1))
-      drw_w = vid_w >> 1;
-   if (vid_h > (drw_h << 1))
-      drw_h = vid_h >> 1;
+    if (vid_w > (drw_w << 1))
+	drw_w = vid_w >> 1;
+    if (vid_h > (drw_h << 1))
+	drw_h = vid_h >> 1;
 
-   *p_w = drw_w;
-   *p_h = drw_h;
+    *p_w = drw_w;
+    *p_h = drw_h;
 }
 
 static void
@@ -1109,95 +1096,95 @@ I830CopyPackedData(ScrnInfoPtr pScrn, I8
 		   int srcPitch,
 		   int dstPitch, int top, int left, int h, int w)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
-   unsigned char *src, *dst;
-   int i,j;
-   unsigned char *s;
+    I830Ptr pI830 = I830PTR(pScrn);
+    unsigned char *src, *dst;
+    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);
-#endif
-
-   src = buf + (top * srcPitch) + (left << 1);
-
-   if (pPriv->currentBuf == 0)
-      dst = pI830->FbBase + pPriv->YBuf0offset;
-   else
-      dst = pI830->FbBase + pPriv->YBuf1offset;
-
-   switch (pI830->rotation) {
-      case RR_Rotate_0:
-         w <<= 1;
-         for (i = 0; i < h; i++) {
-            memcpy(dst, src, w);
-            src += srcPitch;
-            dst += dstPitch;
-         }
-	 break;
-      case RR_Rotate_90:
-         h <<= 1;
-         for (i = 0; i < h; i+=2) {
-            s = src;
-            for (j = 0; j < w; j++) {
+    ErrorF("I830CopyPackedData: (%d,%d) (%d,%d)\n"
+	   "srcPitch: %d, dstPitch: %d\n", top, left, h, w,
+	   srcPitch, dstPitch);
+#endif
+
+    src = buf + (top * srcPitch) + (left << 1);
+
+    if (pPriv->currentBuf == 0)
+	dst = pI830->FbBase + pPriv->YBuf0offset;
+    else
+	dst = pI830->FbBase + pPriv->YBuf1offset;
+
+    switch (pI830->rotation) {
+    case RR_Rotate_0:
+	w <<= 1;
+	for (i = 0; i < h; i++) {
+	    memcpy(dst, src, w);
+	    src += srcPitch;
+	    dst += dstPitch;
+	}
+	break;
+    case RR_Rotate_90:
+	h <<= 1;
+	for (i = 0; i < h; i+=2) {
+	    s = src;
+	    for (j = 0; j < w; j++) {
 		/* Copy Y */
-               dst[(i + 0) + ((w - j - 1) * dstPitch)] = *s++; 
+		dst[(i + 0) + ((w - j - 1) * dstPitch)] = *s++; 
 		(void)*s++;
-            }
-            src += srcPitch;
-         }
-         h >>= 1;
-   	 src = buf + (top * srcPitch) + (left << 1);
-         for (i = 0; i < h; i+=2) {
-            for (j = 0; j < w; j+=2) {
+	    }
+	    src += srcPitch;
+	}
+	h >>= 1;
+	src = buf + (top * srcPitch) + (left << 1);
+	for (i = 0; i < h; i+=2) {
+	    for (j = 0; j < w; j+=2) {
 		/* Copy U */
 		dst[((i*2) + 1) + ((w - j - 1) * dstPitch)] = src[(j*2) + 1 + (i * srcPitch)];
 		dst[((i*2) + 1) + ((w - j - 2) * dstPitch)] = src[(j*2) + 1 + ((i+1) * srcPitch)];
 		/* Copy V */
 		dst[((i*2) + 3) + ((w - j - 1) * dstPitch)] = src[(j*2) + 3 + (i * srcPitch)];
 		dst[((i*2) + 3) + ((w - j - 2) * dstPitch)] = src[(j*2) + 3 + ((i+1) * srcPitch)];
-            }
-         }
-         break;
-      case RR_Rotate_180:
-         w <<= 1;
-         for (i = 0; i < h; i++) {
-            s = src;
-            for (j = 0; j < w; j+=4) {
-               dst[(w - j - 4) + ((h - i - 1) * dstPitch)] = *s++;
-               dst[(w - j - 3) + ((h - i - 1) * dstPitch)] = *s++;
-               dst[(w - j - 2) + ((h - i - 1) * dstPitch)] = *s++;
-               dst[(w - j - 1) + ((h - i - 1) * dstPitch)] = *s++;
-            }
-            src += srcPitch;
-         }
-         break;
-      case RR_Rotate_270:
-         h <<= 1;
-         for (i = 0; i < h; i+=2) {
-            s = src;
-            for (j = 0; j < w; j++) {
+	    }
+	}
+	break;
+    case RR_Rotate_180:
+	w <<= 1;
+	for (i = 0; i < h; i++) {
+	    s = src;
+	    for (j = 0; j < w; j+=4) {
+		dst[(w - j - 4) + ((h - i - 1) * dstPitch)] = *s++;
+		dst[(w - j - 3) + ((h - i - 1) * dstPitch)] = *s++;
+		dst[(w - j - 2) + ((h - i - 1) * dstPitch)] = *s++;
+		dst[(w - j - 1) + ((h - i - 1) * dstPitch)] = *s++;
+	    }
+	    src += srcPitch;
+	}
+	break;
+    case RR_Rotate_270:
+	h <<= 1;
+	for (i = 0; i < h; i+=2) {
+	    s = src;
+	    for (j = 0; j < w; j++) {
 		/* Copy Y */
-               dst[(h - i - 2) + (j * dstPitch)] = *s++;
+		dst[(h - i - 2) + (j * dstPitch)] = *s++;
 		(void)*s++;
-            }
-            src += srcPitch;
-         }
-         h >>= 1;
-   	 src = buf + (top * srcPitch) + (left << 1);
-         for (i = 0; i < h; i+=2) {
-            for (j = 0; j < w; j+=2) {
+	    }
+	    src += srcPitch;
+	}
+	h >>= 1;
+	src = buf + (top * srcPitch) + (left << 1);
+	for (i = 0; i < h; i+=2) {
+	    for (j = 0; j < w; j+=2) {
 		/* Copy U */
 		dst[(((h - i)*2) - 3) + (j * dstPitch)] = src[(j*2) + 1 + (i * srcPitch)];
 		dst[(((h - i)*2) - 3) + ((j - 1) * dstPitch)] = src[(j*2) + 1 + ((i+1) * srcPitch)];
 		/* Copy V */
 		dst[(((h - i)*2) - 1) + (j * dstPitch)] = src[(j*2) + 3 + (i * srcPitch)];
 		dst[(((h - i)*2) - 1) + ((j - 1) * dstPitch)] = src[(j*2) + 3 + ((i+1) * srcPitch)];
-            }
-         }
-         break;
-   }
+	    }
+	}
+	break;
+    }
 }
 
 /* Copies planar data in *buf to UYVY-packed data in the screen atYBufXOffset.
@@ -1208,55 +1195,55 @@ I830CopyPlanarToPackedData(ScrnInfoPtr p
 			   int srcPitch2, int dstPitch, int srcH,
 			   int top, int left, int h, int w, int id)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
-   CARD8 *dst1, *srcy, *srcu, *srcv;
-   int y;
-
-   if (pPriv->currentBuf == 0)
-      dst1 = pI830->FbBase + pPriv->YBuf0offset;
-   else
-      dst1 = pI830->FbBase + pPriv->YBuf1offset;
-
-   srcy = buf + (top * srcPitch) + left;
-   if (id == FOURCC_YV12) {
-      srcu = buf + (srcH * srcPitch) + ((top / 2) * srcPitch2) + (left / 2);
-      srcv = buf + (srcH * srcPitch) + ((srcH / 2) * srcPitch2) +
-	    ((top / 2) * srcPitch2) + (left / 2);
-   } else {
-      srcv = buf + (srcH * srcPitch) + ((top / 2) * srcPitch2) + (left / 2);
-      srcu = buf + (srcH * srcPitch) + ((srcH / 2) * srcPitch2) +
-	    ((top / 2) * srcPitch2) + (left / 2);
-   }
-
-   for (y = 0; y < h; y++) {
-      CARD32 *dst = (CARD32 *)dst1;
-      CARD8 *sy = srcy;
-      CARD8 *su = srcu;
-      CARD8 *sv = srcv;
-      int i;
-
-      i = w / 2;
-      while(i > 4) {
-	 dst[0] = sy[0] | (sy[1] << 16) | (sv[0] << 8) | (su[0] << 24);
-	 dst[1] = sy[2] | (sy[3] << 16) | (sv[1] << 8) | (su[1] << 24);
-	 dst[2] = sy[4] | (sy[5] << 16) | (sv[2] << 8) | (su[2] << 24);
-	 dst[3] = sy[6] | (sy[7] << 16) | (sv[3] << 8) | (su[3] << 24);
-	 dst += 4; su += 4; sv += 4; sy += 8;
-	 i -= 4;
-      }
-      while(i--) {
-	 dst[0] = sy[0] | (sy[1] << 16) | (sv[0] << 8) | (su[0] << 24);
-	 dst++; su++; sv++;
-	 sy += 2;
-      }
-
-      dst1 += dstPitch;
-      srcy += srcPitch;
-      if (y & 1) {
-	 srcu += srcPitch2;
-	 srcv += srcPitch2;
-      }	
-   }
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD8 *dst1, *srcy, *srcu, *srcv;
+    int y;
+
+    if (pPriv->currentBuf == 0)
+	dst1 = pI830->FbBase + pPriv->YBuf0offset;
+    else
+	dst1 = pI830->FbBase + pPriv->YBuf1offset;
+
+    srcy = buf + (top * srcPitch) + left;
+    if (id == FOURCC_YV12) {
+	srcu = buf + (srcH * srcPitch) + ((top / 2) * srcPitch2) + (left / 2);
+	srcv = buf + (srcH * srcPitch) + ((srcH / 2) * srcPitch2) +
+	((top / 2) * srcPitch2) + (left / 2);
+    } else {
+	srcv = buf + (srcH * srcPitch) + ((top / 2) * srcPitch2) + (left / 2);
+	srcu = buf + (srcH * srcPitch) + ((srcH / 2) * srcPitch2) +
+	((top / 2) * srcPitch2) + (left / 2);
+    }
+
+    for (y = 0; y < h; y++) {
+	CARD32 *dst = (CARD32 *)dst1;
+	CARD8 *sy = srcy;
+	CARD8 *su = srcu;
+	CARD8 *sv = srcv;
+	int i;
+
+	i = w / 2;
+	while(i > 4) {
+	    dst[0] = sy[0] | (sy[1] << 16) | (sv[0] << 8) | (su[0] << 24);
+	    dst[1] = sy[2] | (sy[3] << 16) | (sv[1] << 8) | (su[1] << 24);
+	    dst[2] = sy[4] | (sy[5] << 16) | (sv[2] << 8) | (su[2] << 24);
+	    dst[3] = sy[6] | (sy[7] << 16) | (sv[3] << 8) | (su[3] << 24);
+	    dst += 4; su += 4; sv += 4; sy += 8;
+	    i -= 4;
+	}
+	while(i--) {
+	    dst[0] = sy[0] | (sy[1] << 16) | (sv[0] << 8) | (su[0] << 24);
+	    dst++; su++; sv++;
+	    sy += 2;
+	}
+
+	dst1 += dstPitch;
+	srcy += srcPitch;
+	if (y & 1) {
+	    srcu += srcPitch2;
+	    srcv += srcPitch2;
+	}	
+    }
 }
 
 static void
@@ -1265,340 +1252,340 @@ I830CopyPlanarData(ScrnInfoPtr pScrn, I8
 		   int srcPitch2, int dstPitch, int srcH, int top, int left,
 		   int h, int w, int id)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
-   int i, j = 0;
-   unsigned char *src1, *src2, *src3, *dst1, *dst2, *dst3;
-   unsigned char *s;
-   int dstPitch2 = dstPitch << 1;
+    I830Ptr pI830 = I830PTR(pScrn);
+    int i, j = 0;
+    unsigned char *src1, *src2, *src3, *dst1, *dst2, *dst3;
+    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);
+    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);
 #endif
 
-   /* Copy Y data */
-   src1 = buf + (top * srcPitch) + left;
+    /* 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);
+    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
-      dst1 = pI830->FbBase + pPriv->YBuf1offset;
-
-   switch (pI830->rotation) {
-      case RR_Rotate_0:
-         for (i = 0; i < h; i++) {
-            memcpy(dst1, src1, w);
-            src1 += srcPitch;
-            dst1 += dstPitch2;
-         }
-	 break;
-      case RR_Rotate_90:
-         for (i = 0; i < h; i++) {
-            s = src1;
-            for (j = 0; j < w; j++) {
-               dst1[(i) + ((w - j - 1) * dstPitch2)] = *s++;
-            }
-            src1 += srcPitch;
-         }
-         break;
-      case RR_Rotate_180:
-         for (i = 0; i < h; i++) {
-            s = src1;
-            for (j = 0; j < w; j++) {
-               dst1[(w - j - 1) + ((h - i - 1) * dstPitch2)] = *s++;
-            }
-            src1 += srcPitch;
-         }
-         break;
-      case RR_Rotate_270:
-         for (i = 0; i < h; i++) {
-            s = src1;
-            for (j = 0; j < w; j++) {
-               dst1[(h - i - 1) + (j * dstPitch2)] = *s++;
-            }
-            src1 += srcPitch;
-         }
-         break;
-   }
+    if (pPriv->currentBuf == 0)
+	dst1 = pI830->FbBase + pPriv->YBuf0offset;
+    else
+	dst1 = pI830->FbBase + pPriv->YBuf1offset;
+
+    switch (pI830->rotation) {
+    case RR_Rotate_0:
+	for (i = 0; i < h; i++) {
+	    memcpy(dst1, src1, w);
+	    src1 += srcPitch;
+	    dst1 += dstPitch2;
+	}
+	break;
+    case RR_Rotate_90:
+	for (i = 0; i < h; i++) {
+	    s = src1;
+	    for (j = 0; j < w; j++) {
+		dst1[(i) + ((w - j - 1) * dstPitch2)] = *s++;
+	    }
+	    src1 += srcPitch;
+	}
+	break;
+    case RR_Rotate_180:
+	for (i = 0; i < h; i++) {
+	    s = src1;
+	    for (j = 0; j < w; j++) {
+		dst1[(w - j - 1) + ((h - i - 1) * dstPitch2)] = *s++;
+	    }
+	    src1 += srcPitch;
+	}
+	break;
+    case RR_Rotate_270:
+	for (i = 0; i < h; i++) {
+	    s = src1;
+	    for (j = 0; j < w; j++) {
+		dst1[(h - i - 1) + (j * dstPitch2)] = *s++;
+	    }
+	    src1 += srcPitch;
+	}
+	break;
+    }
 
-   /* Copy V data for YV12, or U data for I420 */
-   src2 = buf + (srcH * srcPitch) + ((top * srcPitch) >> 2) + (left >> 1);
+    /* 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);
+    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;
-      else
-	 dst2 = pI830->FbBase + pPriv->VBuf0offset;
-   } else {
-      if (id == FOURCC_I420)
-	 dst2 = pI830->FbBase + pPriv->UBuf1offset;
-      else
-	 dst2 = pI830->FbBase + pPriv->VBuf1offset;
-   }
-
-   switch (pI830->rotation) {
-      case RR_Rotate_0:
-         for (i = 0; i < h / 2; i++) {
-            memcpy(dst2, src2, w / 2);
-            src2 += srcPitch2;
-            dst2 += dstPitch;
-         }
-         break;
-      case RR_Rotate_90:
-         for (i = 0; i < (h/2); i++) {
-            s = src2;
-            for (j = 0; j < (w/2); j++) {
-               dst2[(i) + (((w/2) - j - 1) * (dstPitch))] = *s++;
-            }
-            src2 += srcPitch2;
-         }
-         break;
-      case RR_Rotate_180:
-         for (i = 0; i < (h/2); i++) {
-            s = src2;
-            for (j = 0; j < (w/2); j++) {
-               dst2[((w/2) - j - 1) + (((h/2) - i - 1) * dstPitch)] = *s++;
-            }
-            src2 += srcPitch2;
-         }
-         break;
-      case RR_Rotate_270:
-         for (i = 0; i < (h/2); i++) {
-            s = src2;
-            for (j = 0; j < (w/2); j++) {
-               dst2[((h/2) - i - 1) + (j * dstPitch)] = *s++;
-            }
-            src2 += srcPitch2;
-         }
-         break;
-   }
-
-   /* Copy U data for YV12, or V data for I420 */
-   src3 = buf + (srcH * srcPitch) + ((srcH >> 1) * srcPitch2) +
-	 ((top * srcPitch) >> 2) + (left >> 1);
+    if (pPriv->currentBuf == 0) {
+	if (id == FOURCC_I420)
+	    dst2 = pI830->FbBase + pPriv->UBuf0offset;
+	else
+	    dst2 = pI830->FbBase + pPriv->VBuf0offset;
+    } else {
+	if (id == FOURCC_I420)
+	    dst2 = pI830->FbBase + pPriv->UBuf1offset;
+	else
+	    dst2 = pI830->FbBase + pPriv->VBuf1offset;
+    }
+
+    switch (pI830->rotation) {
+    case RR_Rotate_0:
+	for (i = 0; i < h / 2; i++) {
+	    memcpy(dst2, src2, w / 2);
+	    src2 += srcPitch2;
+	    dst2 += dstPitch;
+	}
+	break;
+    case RR_Rotate_90:
+	for (i = 0; i < (h/2); i++) {
+	    s = src2;
+	    for (j = 0; j < (w/2); j++) {
+		dst2[(i) + (((w/2) - j - 1) * (dstPitch))] = *s++;
+	    }
+	    src2 += srcPitch2;
+	}
+	break;
+    case RR_Rotate_180:
+	for (i = 0; i < (h/2); i++) {
+	    s = src2;
+	    for (j = 0; j < (w/2); j++) {
+		dst2[((w/2) - j - 1) + (((h/2) - i - 1) * dstPitch)] = *s++;
+	    }
+	    src2 += srcPitch2;
+	}
+	break;
+    case RR_Rotate_270:
+	for (i = 0; i < (h/2); i++) {
+	    s = src2;
+	    for (j = 0; j < (w/2); j++) {
+		dst2[((h/2) - i - 1) + (j * dstPitch)] = *s++;
+	    }
+	    src2 += srcPitch2;
+	}
+	break;
+    }
+
+    /* 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);
+    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;
-      else
-	 dst3 = pI830->FbBase + pPriv->UBuf0offset;
-   } else {
-      if (id == FOURCC_I420)
-	 dst3 = pI830->FbBase + pPriv->VBuf1offset;
-      else
-	 dst3 = pI830->FbBase + pPriv->UBuf1offset;
-   }
-
-   switch (pI830->rotation) {
-      case RR_Rotate_0:
-         for (i = 0; i < h / 2; i++) {
-            memcpy(dst3, src3, w / 2);
-            src3 += srcPitch2;
-            dst3 += dstPitch;
-         }
-         break;
-      case RR_Rotate_90:
-         for (i = 0; i < (h/2); i++) {
-            s = src3;
-            for (j = 0; j < (w/2); j++) {
-               dst3[(i) + (((w/2) - j - 1) * (dstPitch))] = *s++;
-            }
-            src3 += srcPitch2;
-         }
-         break;
-      case RR_Rotate_180:
-         for (i = 0; i < (h/2); i++) {
-            s = src3;
-            for (j = 0; j < (w/2); j++) {
-               dst3[((w/2) - j - 1) + (((h/2) - i - 1) * dstPitch)] = *s++;
-            }
-            src3 += srcPitch2;
-         }
-         break;
-      case RR_Rotate_270:
-         for (i = 0; i < (h/2); i++) {
-            s = src3;
-            for (j = 0; j < (w/2); j++) {
-               dst3[((h/2) - i - 1) + (j * dstPitch)] = *s++;
-            }
-            src3 += srcPitch2;
-         }
-         break;
-   }
+    if (pPriv->currentBuf == 0) {
+	if (id == FOURCC_I420)
+	    dst3 = pI830->FbBase + pPriv->VBuf0offset;
+	else
+	    dst3 = pI830->FbBase + pPriv->UBuf0offset;
+    } else {
+	if (id == FOURCC_I420)
+	    dst3 = pI830->FbBase + pPriv->VBuf1offset;
+	else
+	    dst3 = pI830->FbBase + pPriv->UBuf1offset;
+    }
+
+    switch (pI830->rotation) {
+    case RR_Rotate_0:
+	for (i = 0; i < h / 2; i++) {
+	    memcpy(dst3, src3, w / 2);
+	    src3 += srcPitch2;
+	    dst3 += dstPitch;
+	}
+	break;
+    case RR_Rotate_90:
+	for (i = 0; i < (h/2); i++) {
+	    s = src3;
+	    for (j = 0; j < (w/2); j++) {
+		dst3[(i) + (((w/2) - j - 1) * (dstPitch))] = *s++;
+	    }
+	    src3 += srcPitch2;
+	}
+	break;
+    case RR_Rotate_180:
+	for (i = 0; i < (h/2); i++) {
+	    s = src3;
+	    for (j = 0; j < (w/2); j++) {
+		dst3[((w/2) - j - 1) + (((h/2) - i - 1) * dstPitch)] = *s++;
+	    }
+	    src3 += srcPitch2;
+	}
+	break;
+    case RR_Rotate_270:
+	for (i = 0; i < (h/2); i++) {
+	    s = src3;
+	    for (j = 0; j < (w/2); j++) {
+		dst3[((h/2) - i - 1) + (j * dstPitch)] = *s++;
+	    }
+	    src3 += srcPitch2;
+	}
+	break;
+    }
 }
 
 typedef struct {
-   CARD8 sign;
-   CARD16 mantissa;
-   CARD8 exponent;
+    CARD8 sign;
+    CARD16 mantissa;
+    CARD8 exponent;
 } coeffRec, *coeffPtr;
 
 static Bool
 SetCoeffRegs(double *coeff, int mantSize, coeffPtr pCoeff, int pos)
 {
-   int maxVal, icoeff, res;
-   int sign;
-   double c;
-
-   sign = 0;
-   maxVal = 1 << mantSize;
-   c = *coeff;
-   if (c < 0.0) {
-      sign = 1;
-      c = -c;
-   }
-
-   res = 12 - mantSize;
-   if ((icoeff = (int)(c * 4 * maxVal + 0.5)) < maxVal) {
-      pCoeff[pos].exponent = 3;
-      pCoeff[pos].mantissa = icoeff << res;
-      *coeff = (double)icoeff / (double)(4 * maxVal);
-   } else if ((icoeff = (int)(c * 2 * maxVal + 0.5)) < maxVal) {
-      pCoeff[pos].exponent = 2;
-      pCoeff[pos].mantissa = icoeff << res;
-      *coeff = (double)icoeff / (double)(2 * maxVal);
-   } else if ((icoeff = (int)(c * maxVal + 0.5)) < maxVal) {
-      pCoeff[pos].exponent = 1;
-      pCoeff[pos].mantissa = icoeff << res;
-      *coeff = (double)icoeff / (double)(maxVal);
-   } else if ((icoeff = (int)(c * maxVal * 0.5 + 0.5)) < maxVal) {
-      pCoeff[pos].exponent = 0;
-      pCoeff[pos].mantissa = icoeff << res;
-      *coeff = (double)icoeff / (double)(maxVal / 2);
-   } else {
-      /* Coeff out of range */
-      return FALSE;
-   }
-
-   pCoeff[pos].sign = sign;
-   if (sign)
-      *coeff = -(*coeff);
-   return TRUE;
+    int maxVal, icoeff, res;
+    int sign;
+    double c;
+
+    sign = 0;
+    maxVal = 1 << mantSize;
+    c = *coeff;
+    if (c < 0.0) {
+	sign = 1;
+	c = -c;
+    }
+
+    res = 12 - mantSize;
+    if ((icoeff = (int)(c * 4 * maxVal + 0.5)) < maxVal) {
+	pCoeff[pos].exponent = 3;
+	pCoeff[pos].mantissa = icoeff << res;
+	*coeff = (double)icoeff / (double)(4 * maxVal);
+    } else if ((icoeff = (int)(c * 2 * maxVal + 0.5)) < maxVal) {
+	pCoeff[pos].exponent = 2;
+	pCoeff[pos].mantissa = icoeff << res;
+	*coeff = (double)icoeff / (double)(2 * maxVal);
+    } else if ((icoeff = (int)(c * maxVal + 0.5)) < maxVal) {
+	pCoeff[pos].exponent = 1;
+	pCoeff[pos].mantissa = icoeff << res;
+	*coeff = (double)icoeff / (double)(maxVal);
+    } else if ((icoeff = (int)(c * maxVal * 0.5 + 0.5)) < maxVal) {
+	pCoeff[pos].exponent = 0;
+	pCoeff[pos].mantissa = icoeff << res;
+	*coeff = (double)icoeff / (double)(maxVal / 2);
+    } else {
+	/* Coeff out of range */
+	return FALSE;
+    }
+
+    pCoeff[pos].sign = sign;
+    if (sign)
+	*coeff = -(*coeff);
+    return TRUE;
 }
 
 static void
 UpdateCoeff(int taps, double fCutoff, Bool isHoriz, Bool isY, coeffPtr pCoeff)
 {
-   int i, j, j1, num, pos, mantSize;
-   double pi = 3.1415926535, val, sinc, window, sum;
-   double rawCoeff[MAX_TAPS * 32], coeffs[N_PHASES][MAX_TAPS];
-   double diff;
-   int tapAdjust[MAX_TAPS], tap2Fix;
-   Bool isVertAndUV;
-
-   if (isHoriz)
-      mantSize = 7;
-   else
-      mantSize = 6;
-
-   isVertAndUV = !isHoriz && !isY;
-   num = taps * 16;
-   for (i = 0; i < num  * 2; i++) {
-      val = (1.0 / fCutoff) * taps * pi * (i - num) / (2 * num);
-      if (val == 0.0)
-	 sinc = 1.0;
-      else
-	 sinc = sin(val) / val;
-
-      /* Hamming window */
-      window = (0.5 - 0.5 * cos(i * pi / num));
-      rawCoeff[i] = sinc * window;
-   }
-
-   for (i = 0; i < N_PHASES; i++) {
-      /* Normalise the coefficients. */
-      sum = 0.0;
-      for (j = 0; j < taps; j++) {
-	 pos = i + j * 32;
-	 sum += rawCoeff[pos];
-      }
-      for (j = 0; j < taps; j++) {
-	 pos = i + j * 32;
-	 coeffs[i][j] = rawCoeff[pos] / sum;
-      }
-
-      /* Set the register values. */
-      for (j = 0; j < taps; j++) {
-	 pos = j + i * taps;
-	 if ((j == (taps - 1) / 2) && !isVertAndUV)
-	    SetCoeffRegs(&coeffs[i][j], mantSize + 2, pCoeff, pos);
-	 else
-	    SetCoeffRegs(&coeffs[i][j], mantSize, pCoeff, pos);
-      }
-
-      tapAdjust[0] = (taps - 1) / 2;
-      for (j = 1, j1 = 1; j <= tapAdjust[0]; j++, j1++) {
-	 tapAdjust[j1] = tapAdjust[0] - j;
-	 tapAdjust[++j1] = tapAdjust[0] + j;
-      }
-
-      /* Adjust the coefficients. */
-      sum = 0.0;
-      for (j = 0; j < taps; j++)
-	 sum += coeffs[i][j];
-      if (sum != 1.0) {
-	 for (j1 = 0; j1 < taps; j1++) {
-	    tap2Fix = tapAdjust[j1];
-	    diff = 1.0 - sum;
-	    coeffs[i][tap2Fix] += diff;
-	    pos = tap2Fix + i * taps;
-	    if ((tap2Fix == (taps - 1) / 2) && !isVertAndUV)
-	       SetCoeffRegs(&coeffs[i][tap2Fix], mantSize + 2, pCoeff, pos);
+    int i, j, j1, num, pos, mantSize;
+    double pi = 3.1415926535, val, sinc, window, sum;
+    double rawCoeff[MAX_TAPS * 32], coeffs[N_PHASES][MAX_TAPS];
+    double diff;
+    int tapAdjust[MAX_TAPS], tap2Fix;
+    Bool isVertAndUV;
+
+    if (isHoriz)
+	mantSize = 7;
+    else
+	mantSize = 6;
+
+    isVertAndUV = !isHoriz && !isY;
+    num = taps * 16;
+    for (i = 0; i < num  * 2; i++) {
+	val = (1.0 / fCutoff) * taps * pi * (i - num) / (2 * num);
+	if (val == 0.0)
+	    sinc = 1.0;
+	else
+	    sinc = sin(val) / val;
+
+	/* Hamming window */
+	window = (0.5 - 0.5 * cos(i * pi / num));
+	rawCoeff[i] = sinc * window;
+    }
+
+    for (i = 0; i < N_PHASES; i++) {
+	/* Normalise the coefficients. */
+	sum = 0.0;
+	for (j = 0; j < taps; j++) {
+	    pos = i + j * 32;
+	    sum += rawCoeff[pos];
+	}
+	for (j = 0; j < taps; j++) {
+	    pos = i + j * 32;
+	    coeffs[i][j] = rawCoeff[pos] / sum;
+	}
+
+	/* Set the register values. */
+	for (j = 0; j < taps; j++) {
+	    pos = j + i * taps;
+	    if ((j == (taps - 1) / 2) && !isVertAndUV)
+		SetCoeffRegs(&coeffs[i][j], mantSize + 2, pCoeff, pos);
 	    else
-	       SetCoeffRegs(&coeffs[i][tap2Fix], mantSize, pCoeff, pos);
+		SetCoeffRegs(&coeffs[i][j], mantSize, pCoeff, pos);
+	}
 
-	    sum = 0.0;
-	    for (j = 0; j < taps; j++)
-	       sum += coeffs[i][j];
-	    if (sum == 1.0)
-	       break;
-	 }
-      }
-   }
+	tapAdjust[0] = (taps - 1) / 2;
+	for (j = 1, j1 = 1; j <= tapAdjust[0]; j++, j1++) {
+	    tapAdjust[j1] = tapAdjust[0] - j;
+	    tapAdjust[++j1] = tapAdjust[0] + j;
+	}
+
+	/* Adjust the coefficients. */
+	sum = 0.0;
+	for (j = 0; j < taps; j++)
+	    sum += coeffs[i][j];
+	if (sum != 1.0) {
+	    for (j1 = 0; j1 < taps; j1++) {
+		tap2Fix = tapAdjust[j1];
+		diff = 1.0 - sum;
+		coeffs[i][tap2Fix] += diff;
+		pos = tap2Fix + i * taps;
+		if ((tap2Fix == (taps - 1) / 2) && !isVertAndUV)
+		    SetCoeffRegs(&coeffs[i][tap2Fix], mantSize + 2, pCoeff, pos);
+		else
+		    SetCoeffRegs(&coeffs[i][tap2Fix], mantSize, pCoeff, pos);
+
+		sum = 0.0;
+		for (j = 0; j < taps; j++)
+		    sum += coeffs[i][j];
+		if (sum == 1.0)
+		    break;
+	    }
+	}
+    }
 }
 
 static float
 I830CrtcVideoCoverage (xf86CrtcPtr crtc, BoxPtr video)
 {
-   BoxRec   dest;
-   BoxRec   pipe;
+    BoxRec   dest;
+    BoxRec   pipe;
 
-   if (crtc->enabled)
-   {
-      pipe.x1 = crtc->x;
-      pipe.x2 = crtc->x + xf86ModeWidth (&crtc->mode, crtc->rotation);
-      pipe.y1 = crtc->y;
-      pipe.y2 = crtc->y + xf86ModeHeight (&crtc->mode, crtc->rotation);
-   }
-   else
-   {
-      pipe.x1 = pipe.x2 = 0;
-      pipe.y1 = pipe.y2 = 0;
-   }
-   dest.x1 = pipe.x1 > video->x1 ? pipe.x1 : video->x1;
-   dest.x2 = pipe.x2 < video->x2 ? pipe.x2 : video->x2;
-   dest.y1 = pipe.y1 > video->y1 ? pipe.y1 : video->y1;
-   dest.y2 = pipe.y2 < video->y2 ? pipe.y2 : video->y2;
-   if (dest.x1 >= dest.x2 || dest.y1 >= dest.y2)
-   {
-      dest.x1 = dest.x2 = 0;
-      dest.y1 = dest.y2 = 0;
-   }
-   if (video->x1 >= video->x2 || video->y1 >= video->y2)
-      return 0.0;
-   return (((float) (dest.x2 - dest.x1) * (float) (dest.y2 - dest.y1)) /
-	   ((float) (video->x2 - video->x1) * (float) (video->y2 - video->y1)));
+    if (crtc->enabled)
+    {
+	pipe.x1 = crtc->x;
+	pipe.x2 = crtc->x + xf86ModeWidth (&crtc->mode, crtc->rotation);
+	pipe.y1 = crtc->y;
+	pipe.y2 = crtc->y + xf86ModeHeight (&crtc->mode, crtc->rotation);
+    }
+    else
+    {
+	pipe.x1 = pipe.x2 = 0;
+	pipe.y1 = pipe.y2 = 0;
+    }
+    dest.x1 = pipe.x1 > video->x1 ? pipe.x1 : video->x1;
+    dest.x2 = pipe.x2 < video->x2 ? pipe.x2 : video->x2;
+    dest.y1 = pipe.y1 > video->y1 ? pipe.y1 : video->y1;
+    dest.y2 = pipe.y2 < video->y2 ? pipe.y2 : video->y2;
+    if (dest.x1 >= dest.x2 || dest.y1 >= dest.y2)
+    {
+	dest.x1 = dest.x2 = 0;
+	dest.y1 = dest.y2 = 0;
+    }
+    if (video->x1 >= video->x2 || video->y1 >= video->y2)
+	return 0.0;
+    return (((float) (dest.x2 - dest.x1) * (float) (dest.y2 - dest.y1)) /
+	    ((float) (video->x2 - video->x1) * (float) (video->y2 - video->y1)));
 }
 
 static void
@@ -1606,521 +1593,521 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
 		 int dstPitch, int x1, int y1, int x2, int y2, BoxPtr dstBox,
 		 short src_w, short src_h, short drw_w, short drw_h)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
-   I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr;
-   I830OverlayRegPtr overlay =
-	 (I830OverlayRegPtr) (pI830->FbBase + pI830->overlay_regs->offset);
-   unsigned int swidth;
-   unsigned int mask, shift, offsety, offsetu;
-   xf86CrtcPtr crtc;
-   int tmp;
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr;
+    I830OverlayRegPtr overlay =
+    (I830OverlayRegPtr) (pI830->FbBase + pI830->overlay_regs->offset);
+    unsigned int swidth;
+    unsigned int mask, shift, offsety, offsetu;
+    xf86CrtcPtr crtc;
+    int tmp;
 
-   OVERLAY_DEBUG("I830DisplayVideo: %dx%d (pitch %d)\n", width, height,
-		 dstPitch);
+    OVERLAY_DEBUG("I830DisplayVideo: %dx%d (pitch %d)\n", width, height,
+		  dstPitch);
 
-   if (!pPriv->overlayOK)
-      return;
+    if (!pPriv->overlayOK)
+	return;
 
 #if VIDEO_DEBUG
-   CompareOverlay(pI830, (CARD32 *) overlay, 0x100);
+    CompareOverlay(pI830, (CARD32 *) overlay, 0x100);
 #endif
 
-   {
-      float best_coverage = 0.0;
-      float coverage;
-      int c;
-      xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-      
-      crtc = NULL;
-      for (c = 0; c < xf86_config->num_crtc; c++)
-      {
-	 xf86CrtcPtr	this_crtc = xf86_config->crtc[c];
-	 coverage = I830CrtcVideoCoverage (this_crtc, dstBox);
-	 if (coverage)
-	 {
-	    if (this_crtc == pPriv->desired_crtc)
-	    {
-	       crtc = this_crtc;
-	       best_coverage = 1.0;
-	    }
-	    else if (coverage > best_coverage)
+    {
+	float best_coverage = 0.0;
+	float coverage;
+	int c;
+	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+
+	crtc = NULL;
+	for (c = 0; c < xf86_config->num_crtc; c++)
+	{
+	    xf86CrtcPtr	this_crtc = xf86_config->crtc[c];
+	    coverage = I830CrtcVideoCoverage (this_crtc, dstBox);
+	    if (coverage)
 	    {
-	       crtc = this_crtc;
-	       best_coverage = coverage;
+		if (this_crtc == pPriv->desired_crtc)
+		{
+		    crtc = this_crtc;
+		    best_coverage = 1.0;
+		}
+		else if (coverage > best_coverage)
+		{
+		    crtc = this_crtc;
+		    best_coverage = coverage;
+		}
 	    }
-	 }
-      }
-      if (crtc != pPriv->current_crtc)
-      {
-	 pPriv->current_crtc = crtc;
-	 I830ResetVideo (pScrn);
-      }
-   }
-
-   switch (crtc->rotation & 0xf) {
-	case RR_Rotate_0:
-		dstBox->x1 -= crtc->x;
-		dstBox->x2 -= crtc->x;
-		dstBox->y1 -= crtc->y;
-		dstBox->y2 -= crtc->y;
-		break;
-	case RR_Rotate_90:
-		tmp = dstBox->x1;
-		dstBox->x1 = dstBox->y1 - crtc->x;
-		dstBox->y1 = pScrn->virtualY - tmp - crtc->y;
-		tmp = dstBox->x2;
-		dstBox->x2 = dstBox->y2 - crtc->x;
-		dstBox->y2 = pScrn->virtualY - tmp - crtc->y;
-		tmp = dstBox->y1;
-		dstBox->y1 = dstBox->y2;
-		dstBox->y2 = tmp;
-		break;
-	case RR_Rotate_180:
-		tmp = dstBox->x1;
-		dstBox->x1 = pScrn->virtualX - dstBox->x2 - crtc->x;
-		dstBox->x2 = pScrn->virtualX - tmp - crtc->x;
-		tmp = dstBox->y1;
-		dstBox->y1 = pScrn->virtualY - dstBox->y2 - crtc->y;
-		dstBox->y2 = pScrn->virtualY - tmp - crtc->y;
-		break;
-	case RR_Rotate_270:
-		tmp = dstBox->x1;
-		dstBox->x1 = pScrn->virtualX - dstBox->y1 - crtc->x;
-		dstBox->y1 = tmp - crtc->y;
-		tmp = dstBox->x2;
-		dstBox->x2 = pScrn->virtualX - dstBox->y2 - crtc->x;
-		dstBox->y2 = tmp - crtc->y;
-		tmp = dstBox->x1;
-		dstBox->x1 = dstBox->x2;
-		dstBox->x2 = tmp;
-		break;
-   }
+	}
+	if (crtc != pPriv->current_crtc)
+	{
+	    pPriv->current_crtc = crtc;
+	    I830ResetVideo (pScrn);
+	}
+    }
+
+    switch (crtc->rotation & 0xf) {
+    case RR_Rotate_0:
+	dstBox->x1 -= crtc->x;
+	dstBox->x2 -= crtc->x;
+	dstBox->y1 -= crtc->y;
+	dstBox->y2 -= crtc->y;
+	break;
+    case RR_Rotate_90:
+	tmp = dstBox->x1;
+	dstBox->x1 = dstBox->y1 - crtc->x;
+	dstBox->y1 = pScrn->virtualY - tmp - crtc->y;
+	tmp = dstBox->x2;
+	dstBox->x2 = dstBox->y2 - crtc->x;
+	dstBox->y2 = pScrn->virtualY - tmp - crtc->y;
+	tmp = dstBox->y1;
+	dstBox->y1 = dstBox->y2;
+	dstBox->y2 = tmp;
+	break;
+    case RR_Rotate_180:
+	tmp = dstBox->x1;
+	dstBox->x1 = pScrn->virtualX - dstBox->x2 - crtc->x;
+	dstBox->x2 = pScrn->virtualX - tmp - crtc->x;
+	tmp = dstBox->y1;
+	dstBox->y1 = pScrn->virtualY - dstBox->y2 - crtc->y;
+	dstBox->y2 = pScrn->virtualY - tmp - crtc->y;
+	break;
+    case RR_Rotate_270:
+	tmp = dstBox->x1;
+	dstBox->x1 = pScrn->virtualX - dstBox->y1 - crtc->x;
+	dstBox->y1 = tmp - crtc->y;
+	tmp = dstBox->x2;
+	dstBox->x2 = pScrn->virtualX - dstBox->y2 - crtc->x;
+	dstBox->y2 = tmp - crtc->y;
+	tmp = dstBox->x1;
+	dstBox->x1 = dstBox->x2;
+	dstBox->x2 = tmp;
+	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)
+	I830ResetVideo(pScrn);
+
+    /* Ensure overlay is turned on with OVERLAY_ENABLE at 0 */
+    i830_overlay_on (pScrn);
+
+    /* Fix up the dstBox if outside the visible screen */
+    {
+	int offset_x = (dstBox->x1 < 0) ? -dstBox->x1 : 0;
+	int offset_y = (dstBox->y1 < 0) ? -dstBox->y1 : 0;
+	int offset, offset2;
+
+	/* align */
+	offset_x = (offset_x + 3) & ~3;
+	offset_y = (offset_y + 3) & ~3;
+
+	if (crtc->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
+	    height -= offset_x;
+	    width -= offset_y;
+	} else {
+	    height -= offset_y;
+	    width -= offset_x;
+	}
+
+	if (id == FOURCC_I420 || id == FOURCC_YV12) {
+	    offset = ((offset_x/2) + (dstPitch * offset_y)) * 2;
+	    offset2 = ((offset_x/2) + ((dstPitch/2) * offset_y));
+	} else {
+	    offset = ((offset_x*2) + (dstPitch * offset_y));
+	    offset2 = ((offset_x*2) + ((dstPitch/2) * offset_y));
+	}
+
+	/* buffer locations */
+	pPriv->YBuf0offset += offset;
+	pPriv->UBuf0offset += offset2;
+	pPriv->VBuf0offset += offset2;
+
+	if(pPriv->doubleBuffer) {
+	    pPriv->YBuf1offset += offset;
+	    pPriv->UBuf1offset += offset2;
+	    pPriv->VBuf1offset += offset2;
+	}
+    }
+
+    if (crtc->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
+	tmp = width;
+	width = height;
+	height = tmp;
+	tmp = drw_w;
+	drw_w = drw_h;
+	drw_h = tmp;
+	tmp = src_w;
+	src_w = src_h;
+	src_h = tmp;
+    }
+
+    if (pPriv->oneLineMode) {
+	/* change the coordinates with panel fitting active */
+	dstBox->y1 = (((dstBox->y1 - 1) * pPriv->scaleRatio) >> 16) + 1;
+	dstBox->y2 = ((dstBox->y2 * pPriv->scaleRatio) >> 16) + 1;
+
+	/* Now, alter the height, so we scale to the correct size */
+	drw_h = ((drw_h * pPriv->scaleRatio) >> 16) + 1;
+    }
+
+    {
+	/* Keep the engine happy and clip to the real vertical size just
+	 * in case an LFP is in use and it's not at it's native resolution.
+	 */
+	int vactive = I830CrtcPipe (pPriv->current_crtc) ? (INREG(VTOTAL_B) & 0x7FF) : (INREG(VTOTAL_A) & 0x7FF);
+	int hactive = pPriv->current_crtc->mode.HDisplay;
+
+	vactive += 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 (dstBox->y1 > vactive) dstBox->y1 = vactive;
+	if (dstBox->y2 > vactive) dstBox->y2 = vactive;
+	if (dstBox->x1 > hactive) dstBox->x1 = hactive;
+	if (dstBox->x2 > hactive) dstBox->x2 = hactive;
+
+	/* nothing do to */
+	if ((!dstBox->x1 && !dstBox->x2) || (!dstBox->y1 && !dstBox->y2)) {
+	    OVERLAY_DEBUG("NOTHING TO DO\n");
+	    return;
+	}
+	if ((dstBox->x1 == (hactive) && 
+	     dstBox->x2 == (hactive)) || 
+	    (dstBox->y1 == vactive && 
+	     dstBox->y2 == vactive)) {
+	    OVERLAY_DEBUG("NOTHING TO DO\n");
+	    return;
+	}
+	if ((dstBox->y2 - dstBox->y1) <= N_VERT_Y_TAPS) {
+	    OVERLAY_DEBUG("NOTHING TO DO\n");
+	    return;
+	}
+	if ((dstBox->x2 - dstBox->x1) <= 2) {
+	    OVERLAY_DEBUG("NOTHING TO DO\n");
+	    return;
+	}
+    }
 
-   /* 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)
-      I830ResetVideo(pScrn);
-
-   /* Ensure overlay is turned on with OVERLAY_ENABLE at 0 */
-   i830_overlay_on (pScrn);
-
-   /* Fix up the dstBox if outside the visible screen */
-   {
-      int offset_x = (dstBox->x1 < 0) ? -dstBox->x1 : 0;
-      int offset_y = (dstBox->y1 < 0) ? -dstBox->y1 : 0;
-      int offset, offset2;
-
-      /* align */
-      offset_x = (offset_x + 3) & ~3;
-      offset_y = (offset_y + 3) & ~3;
-
-      if (crtc->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
-         height -= offset_x;
-         width -= offset_y;
-      } else {
-         height -= offset_y;
-         width -= offset_x;
-      }
-
-      if (id == FOURCC_I420 || id == FOURCC_YV12) {
-         offset = ((offset_x/2) + (dstPitch * offset_y)) * 2;
-         offset2 = ((offset_x/2) + ((dstPitch/2) * offset_y));
-      } else {
-         offset = ((offset_x*2) + (dstPitch * offset_y));
-         offset2 = ((offset_x*2) + ((dstPitch/2) * offset_y));
-      }
-
-      /* buffer locations */
-      pPriv->YBuf0offset += offset;
-      pPriv->UBuf0offset += offset2;
-      pPriv->VBuf0offset += offset2;
-
-      if(pPriv->doubleBuffer) {
-         pPriv->YBuf1offset += offset;
-         pPriv->UBuf1offset += offset2;
-         pPriv->VBuf1offset += offset2;
-      }
-   }
-
-   if (crtc->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
-      tmp = width;
-      width = height;
-      height = tmp;
-      tmp = drw_w;
-      drw_w = drw_h;
-      drw_h = tmp;
-      tmp = src_w;
-      src_w = src_h;
-      src_h = tmp;
-   }
-
-   if (pPriv->oneLineMode) {
-      /* change the coordinates with panel fitting active */
-      dstBox->y1 = (((dstBox->y1 - 1) * pPriv->scaleRatio) >> 16) + 1;
-      dstBox->y2 = ((dstBox->y2 * pPriv->scaleRatio) >> 16) + 1;
- 
-      /* Now, alter the height, so we scale to the correct size */
-      drw_h = ((drw_h * pPriv->scaleRatio) >> 16) + 1;
-   }
-
-   {
-      /* Keep the engine happy and clip to the real vertical size just
-       * in case an LFP is in use and it's not at it's native resolution.
-       */
-      int vactive = I830CrtcPipe (pPriv->current_crtc) ? (INREG(VTOTAL_B) & 0x7FF) : (INREG(VTOTAL_A) & 0x7FF);
-      int hactive = pPriv->current_crtc->mode.HDisplay;
-
-      vactive += 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 (dstBox->y1 > vactive) dstBox->y1 = vactive;
-      if (dstBox->y2 > vactive) dstBox->y2 = vactive;
-      if (dstBox->x1 > hactive) dstBox->x1 = hactive;
-      if (dstBox->x2 > hactive) dstBox->x2 = hactive;
-
-      /* nothing do to */
-      if ((!dstBox->x1 && !dstBox->x2) || (!dstBox->y1 && !dstBox->y2)) {
-         OVERLAY_DEBUG("NOTHING TO DO\n");
-         return;
-      }
-      if ((dstBox->x1 == (hactive) && 
-           dstBox->x2 == (hactive)) || 
-          (dstBox->y1 == vactive && 
-           dstBox->y2 == vactive)) {
-         OVERLAY_DEBUG("NOTHING TO DO\n");
-         return;
-      }
-      if ((dstBox->y2 - dstBox->y1) <= N_VERT_Y_TAPS) {
-         OVERLAY_DEBUG("NOTHING TO DO\n");
-         return;
-      }
-      if ((dstBox->x2 - dstBox->x1) <= 2) {
-         OVERLAY_DEBUG("NOTHING TO DO\n");
-         return;
-      }
-   }
-
-   if (IS_I9XX(pI830)) {
-      shift = 6;
-      mask = 0x3f;
-   } else {
-      shift = 5;
-      mask = 0x1f;
-   }
-
-   if (pPriv->currentBuf == 0) {
-      offsety = pPriv->YBuf0offset;
-      offsetu = pPriv->UBuf0offset;
-   } else {
-      offsety = pPriv->YBuf1offset;
-      offsetu = pPriv->UBuf1offset;
-   }
-
-   switch (id) {
-   case FOURCC_YV12:
-   case FOURCC_I420:
-      swidth = width;
-
-      overlay->SWIDTH = swidth;
-      swidth /= 2;
-      overlay->SWIDTH |= (swidth & 0x7ff) << 16;
-
-      swidth = ((offsety + width + mask) >> shift) -
-	    (offsety >> shift);
-
-      if (IS_I9XX(pI830))
-         swidth <<= 1;
-
-      swidth -= 1;
-
-      OVERLAY_DEBUG("Y width is %d, swidth is %d\n", width, swidth);
-
-      overlay->SWIDTHSW = swidth << 2;
-
-      swidth = ((offsetu + (width / 2) + mask) >> shift) -
-	    (offsetu >> shift);
-
-      if (IS_I9XX(pI830))
-         swidth <<= 1;
-
-      swidth -= 1;
-
-      OVERLAY_DEBUG("UV width is %d, swidthsw is %d\n", width / 2, swidth);
-
-      overlay->SWIDTHSW |= swidth << 18;
-
-      OVERLAY_DEBUG("HEIGHT is %d\n",height);
-
-      overlay->SHEIGHT = height | ((height / 2) << 16);
-      break;
-   case FOURCC_UYVY:
-   case FOURCC_YUY2:
-   default:
-      swidth = width;
-      overlay->SWIDTH = swidth;
-
-      OVERLAY_DEBUG("Y width is %d\n", swidth);
-
-      swidth = ((offsety + (width << 1) + mask) >> shift) -
-	    (offsety >> shift);
-
-      if (IS_I9XX(pI830))
-         swidth <<= 1;
-
-      swidth -= 1;
-
-      OVERLAY_DEBUG("swidthsw is %d\n", swidth);
-
-      overlay->SWIDTHSW = swidth << 2;
-
-      OVERLAY_DEBUG("HEIGHT is %d\n",height);
-
-      overlay->SHEIGHT = height;
-      break;
-   }
-
-   overlay->OCMD = OVERLAY_ENABLE;
-
-   overlay->DWINPOS = (dstBox->y1 << 16) | dstBox->x1;
-
-   overlay->DWINSZ = ((dstBox->y2 - dstBox->y1) << 16) |
-	 (dstBox->x2 - dstBox->x1);
-
-   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))
-   {
-      overlay->OBUF_0Y = 0;
-      overlay->OBUF_0U = 0;
-      overlay->OBUF_0V = 0;
-      overlay->OSTART_0Y = pPriv->YBuf0offset;
-      overlay->OSTART_0U = pPriv->UBuf0offset;
-      overlay->OSTART_0V = pPriv->VBuf0offset;
-      if(pPriv->doubleBuffer) {
-         overlay->OBUF_1Y = 0;
-         overlay->OBUF_1U = 0;
-         overlay->OBUF_1V = 0;
-         overlay->OSTART_1Y = pPriv->YBuf1offset;
-         overlay->OSTART_1U = pPriv->UBuf1offset;
-         overlay->OSTART_1V = pPriv->VBuf1offset;
-      }
-   } else {
-      overlay->OBUF_0Y = pPriv->YBuf0offset;
-      overlay->OBUF_0U = pPriv->UBuf0offset;
-      overlay->OBUF_0V = pPriv->VBuf0offset;
-      if(pPriv->doubleBuffer) {
-         overlay->OBUF_1Y = pPriv->YBuf1offset;
-         overlay->OBUF_1U = pPriv->UBuf1offset;
-         overlay->OBUF_1V = pPriv->VBuf1offset;
-      }
-   }
-
-   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 (IS_I9XX(pI830)) {
+	shift = 6;
+	mask = 0x3f;
+    } else {
+	shift = 5;
+	mask = 0x1f;
+    }
+
+    if (pPriv->currentBuf == 0) {
+	offsety = pPriv->YBuf0offset;
+	offsetu = pPriv->UBuf0offset;
+    } else {
+	offsety = pPriv->YBuf1offset;
+	offsetu = pPriv->UBuf1offset;
+    }
+
+    switch (id) {
+    case FOURCC_YV12:
+    case FOURCC_I420:
+	swidth = width;
+
+	overlay->SWIDTH = swidth;
+	swidth /= 2;
+	overlay->SWIDTH |= (swidth & 0x7ff) << 16;
+
+	swidth = ((offsety + width + mask) >> shift) -
+	(offsety >> shift);
+
+	if (IS_I9XX(pI830))
+	    swidth <<= 1;
+
+	swidth -= 1;
+
+	OVERLAY_DEBUG("Y width is %d, swidth is %d\n", width, swidth);
+
+	overlay->SWIDTHSW = swidth << 2;
+
+	swidth = ((offsetu + (width / 2) + mask) >> shift) -
+	(offsetu >> shift);
+
+	if (IS_I9XX(pI830))
+	    swidth <<= 1;
+
+	swidth -= 1;
+
+	OVERLAY_DEBUG("UV width is %d, swidthsw is %d\n", width / 2, swidth);
+
+	overlay->SWIDTHSW |= swidth << 18;
+
+	OVERLAY_DEBUG("HEIGHT is %d\n",height);
+
+	overlay->SHEIGHT = height | ((height / 2) << 16);
+	break;
+    case FOURCC_UYVY:
+    case FOURCC_YUY2:
+    default:
+	swidth = width;
+	overlay->SWIDTH = swidth;
+
+	OVERLAY_DEBUG("Y width is %d\n", swidth);
+
+	swidth = ((offsety + (width << 1) + mask) >> shift) -
+	(offsety >> shift);
+
+	if (IS_I9XX(pI830))
+	    swidth <<= 1;
+
+	swidth -= 1;
+
+	OVERLAY_DEBUG("swidthsw is %d\n", swidth);
+
+	overlay->SWIDTHSW = swidth << 2;
+
+	OVERLAY_DEBUG("HEIGHT is %d\n",height);
+
+	overlay->SHEIGHT = height;
+	break;
+    }
+
+    overlay->OCMD = OVERLAY_ENABLE;
+
+    overlay->DWINPOS = (dstBox->y1 << 16) | dstBox->x1;
+
+    overlay->DWINSZ = ((dstBox->y2 - dstBox->y1) << 16) |
+    (dstBox->x2 - dstBox->x1);
+
+    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))
+    {
+	overlay->OBUF_0Y = 0;
+	overlay->OBUF_0U = 0;
+	overlay->OBUF_0V = 0;
+	overlay->OSTART_0Y = pPriv->YBuf0offset;
+	overlay->OSTART_0U = pPriv->UBuf0offset;
+	overlay->OSTART_0V = pPriv->VBuf0offset;
+	if(pPriv->doubleBuffer) {
+	    overlay->OBUF_1Y = 0;
+	    overlay->OBUF_1U = 0;
+	    overlay->OBUF_1V = 0;
+	    overlay->OSTART_1Y = pPriv->YBuf1offset;
+	    overlay->OSTART_1U = pPriv->UBuf1offset;
+	    overlay->OSTART_1V = pPriv->VBuf1offset;
+	}
+    } else {
+	overlay->OBUF_0Y = pPriv->YBuf0offset;
+	overlay->OBUF_0U = pPriv->UBuf0offset;
+	overlay->OBUF_0V = pPriv->VBuf0offset;
+	if(pPriv->doubleBuffer) {
+	    overlay->OBUF_1Y = pPriv->YBuf1offset;
+	    overlay->OBUF_1U = pPriv->UBuf1offset;
+	    overlay->OBUF_1V = pPriv->VBuf1offset;
+	}
+    }
+
+    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
-   {
-      int i;
+    {
+	int i;
+
+	ErrorF("First 32 bytes of Y data:\n");
+	for (i = 0; i < 32; i++)
+	    ErrorF(" %02x",
+		   ((unsigned char *)pI830->FbBase + pPriv->YBuf0offset)[i]);
+	ErrorF("\n");
+	ErrorF("First 16 bytes of U data:\n");
+	for (i = 0; i < 16; i++)
+	    ErrorF(" %02x",
+		   ((unsigned char *)pI830->FbBase + pPriv->UBuf0offset)[i]);
+	ErrorF("\n");
+	ErrorF("First 16 bytes of V data:\n");
+	for (i = 0; i < 16; i++)
+	    ErrorF(" %02x",
+		   ((unsigned char *)pI830->FbBase + pPriv->VBuf0offset)[i]);
+	ErrorF("\n");
+    }
+#endif
+
+    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
+     * coefficients.
+     */
+
+    {
+	Bool scaleChanged = FALSE;
+	int xscaleInt, xscaleFract, yscaleInt, yscaleFract;
+	int xscaleIntUV, xscaleFractUV;
+	int yscaleIntUV, yscaleFractUV;
+	/* UV is half the size of Y -- YUV420 */
+	int uvratio = 2;
+	CARD32 newval;
+	coeffRec xcoeffY[N_HORIZ_Y_TAPS * N_PHASES];
+	coeffRec xcoeffUV[N_HORIZ_UV_TAPS * N_PHASES];
+	int i, j, pos;
+
+	/*
+	 * Y down-scale factor as a multiple of 4096.
+	 */
+	xscaleFract = ((src_w - 1) << 12) / drw_w;
+	yscaleFract = ((src_h - 1) << 12) / drw_h;
+
+	/* Calculate the UV scaling factor. */
+	xscaleFractUV = xscaleFract / uvratio;
+	yscaleFractUV = yscaleFract / uvratio;
+
+	/*
+	 * To keep the relative Y and UV ratios exact, round the Y scales
+	 * to a multiple of the Y/UV ratio.
+	 */
+	xscaleFract = xscaleFractUV * uvratio;
+	yscaleFract = yscaleFractUV * uvratio;
+
+	/* Integer (un-multiplied) values. */
+	xscaleInt = xscaleFract >> 12;
+	yscaleInt = yscaleFract >> 12;
+
+	xscaleIntUV = xscaleFractUV >> 12;
+	yscaleIntUV = yscaleFractUV >> 12;
+
+	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) {
+	    OVERLAY_DEBUG("xscale: bad scale\n");
+	    return;
+	}
+
+	/* shouldn't get here */
+	if (xscaleIntUV > 7) {
+	    OVERLAY_DEBUG("xscaleUV: bad scale\n");
+	    return;
+	}
+
+	newval = (xscaleInt << 16) |
+	((xscaleFract & 0xFFF) << 3) | ((yscaleFract & 0xFFF) << 20);
+	if (newval != overlay->YRGBSCALE) {
+	    scaleChanged = TRUE;
+	    overlay->YRGBSCALE = newval;
+	}
+
+	newval = (xscaleIntUV << 16) | ((xscaleFractUV & 0xFFF) << 3) |
+	((yscaleFractUV & 0xFFF) << 20);
+	if (newval != overlay->UVSCALE) {
+	    scaleChanged = TRUE;
+	    overlay->UVSCALE = newval;
+	}
+
+	newval = yscaleInt << 16 | yscaleIntUV;
+	if (newval != overlay->UVSCALEV) {
+	    scaleChanged = TRUE;
+	    overlay->UVSCALEV = newval;
+	}
+
+	/* Recalculate coefficients if the scaling changed. */
+
+	/*
+	 * Only Horizontal coefficients so far.
+	 */
+	if (scaleChanged) {
+	    double fCutoffY;
+	    double fCutoffUV;
+
+	    fCutoffY = xscaleFract / 4096.0;
+	    fCutoffUV = xscaleFractUV / 4096.0;
+
+	    /* Limit to between 1.0 and 3.0. */
+	    if (fCutoffY < MIN_CUTOFF_FREQ)
+		fCutoffY = MIN_CUTOFF_FREQ;
+	    if (fCutoffY > MAX_CUTOFF_FREQ)
+		fCutoffY = MAX_CUTOFF_FREQ;
+	    if (fCutoffUV < MIN_CUTOFF_FREQ)
+		fCutoffUV = MIN_CUTOFF_FREQ;
+	    if (fCutoffUV > MAX_CUTOFF_FREQ)
+		fCutoffUV = MAX_CUTOFF_FREQ;
+
+	    UpdateCoeff(N_HORIZ_Y_TAPS, fCutoffY, TRUE, TRUE, xcoeffY);
+	    UpdateCoeff(N_HORIZ_UV_TAPS, fCutoffUV, TRUE, FALSE, xcoeffUV);
+
+	    for (i = 0; i < N_PHASES; i++) {
+		for (j = 0; j < N_HORIZ_Y_TAPS; j++) {
+		    pos = i * N_HORIZ_Y_TAPS + j;
+		    overlay->Y_HCOEFS[pos] = xcoeffY[pos].sign << 15 |
+		    xcoeffY[pos].exponent << 12 |
+		    xcoeffY[pos].mantissa;
+		}
+	    }
+	    for (i = 0; i < N_PHASES; i++) {
+		for (j = 0; j < N_HORIZ_UV_TAPS; j++) {
+		    pos = i * N_HORIZ_UV_TAPS + j;
+		    overlay->UV_HCOEFS[pos] = xcoeffUV[pos].sign << 15 |
+		    xcoeffUV[pos].exponent << 12 |
+		    xcoeffUV[pos].mantissa;
+		}
+	    }
+	}
+    }
 
-      ErrorF("First 32 bytes of Y data:\n");
-      for (i = 0; i < 32; i++)
-	 ErrorF(" %02x",
-		((unsigned char *)pI830->FbBase + pPriv->YBuf0offset)[i]);
-      ErrorF("\n");
-      ErrorF("First 16 bytes of U data:\n");
-      for (i = 0; i < 16; i++)
-	 ErrorF(" %02x",
-		((unsigned char *)pI830->FbBase + pPriv->UBuf0offset)[i]);
-      ErrorF("\n");
-      ErrorF("First 16 bytes of V data:\n");
-      for (i = 0; i < 16; i++)
-	 ErrorF(" %02x",
-		((unsigned char *)pI830->FbBase + pPriv->VBuf0offset)[i]);
-      ErrorF("\n");
-   }
-#endif
-
-   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
-    * coefficients.
-    */
-
-   {
-      Bool scaleChanged = FALSE;
-      int xscaleInt, xscaleFract, yscaleInt, yscaleFract;
-      int xscaleIntUV, xscaleFractUV;
-      int yscaleIntUV, yscaleFractUV;
-      /* UV is half the size of Y -- YUV420 */
-      int uvratio = 2;
-      CARD32 newval;
-      coeffRec xcoeffY[N_HORIZ_Y_TAPS * N_PHASES];
-      coeffRec xcoeffUV[N_HORIZ_UV_TAPS * N_PHASES];
-      int i, j, pos;
-
-      /*
-       * Y down-scale factor as a multiple of 4096.
-       */
-      xscaleFract = ((src_w - 1) << 12) / drw_w;
-      yscaleFract = ((src_h - 1) << 12) / drw_h;
-
-      /* Calculate the UV scaling factor. */
-      xscaleFractUV = xscaleFract / uvratio;
-      yscaleFractUV = yscaleFract / uvratio;
-
-      /*
-       * To keep the relative Y and UV ratios exact, round the Y scales
-       * to a multiple of the Y/UV ratio.
-       */
-      xscaleFract = xscaleFractUV * uvratio;
-      yscaleFract = yscaleFractUV * uvratio;
-
-      /* Integer (un-multiplied) values. */
-      xscaleInt = xscaleFract >> 12;
-      yscaleInt = yscaleFract >> 12;
-
-      xscaleIntUV = xscaleFractUV >> 12;
-      yscaleIntUV = yscaleFractUV >> 12;
-
-      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) {
-         OVERLAY_DEBUG("xscale: bad scale\n");
-	 return;
-      }
-
-      /* shouldn't get here */
-      if (xscaleIntUV > 7) {
-         OVERLAY_DEBUG("xscaleUV: bad scale\n");
-         return;
-      }
-
-      newval = (xscaleInt << 16) |
-	    ((xscaleFract & 0xFFF) << 3) | ((yscaleFract & 0xFFF) << 20);
-      if (newval != overlay->YRGBSCALE) {
-	 scaleChanged = TRUE;
-	 overlay->YRGBSCALE = newval;
-      }
-
-      newval = (xscaleIntUV << 16) | ((xscaleFractUV & 0xFFF) << 3) |
-	    ((yscaleFractUV & 0xFFF) << 20);
-      if (newval != overlay->UVSCALE) {
-	 scaleChanged = TRUE;
-	 overlay->UVSCALE = newval;
-      }
-
-      newval = yscaleInt << 16 | yscaleIntUV;
-      if (newval != overlay->UVSCALEV) {
-	 scaleChanged = TRUE;
-	 overlay->UVSCALEV = newval;
-      }
-
-      /* Recalculate coefficients if the scaling changed. */
-
-      /*
-       * Only Horizontal coefficients so far.
-       */
-      if (scaleChanged) {
-	 double fCutoffY;
-	 double fCutoffUV;
-
-	 fCutoffY = xscaleFract / 4096.0;
-	 fCutoffUV = xscaleFractUV / 4096.0;
-
-	 /* Limit to between 1.0 and 3.0. */
-	 if (fCutoffY < MIN_CUTOFF_FREQ)
-	    fCutoffY = MIN_CUTOFF_FREQ;
-	 if (fCutoffY > MAX_CUTOFF_FREQ)
-	    fCutoffY = MAX_CUTOFF_FREQ;
-	 if (fCutoffUV < MIN_CUTOFF_FREQ)
-	    fCutoffUV = MIN_CUTOFF_FREQ;
-	 if (fCutoffUV > MAX_CUTOFF_FREQ)
-	    fCutoffUV = MAX_CUTOFF_FREQ;
-
-	 UpdateCoeff(N_HORIZ_Y_TAPS, fCutoffY, TRUE, TRUE, xcoeffY);
-	 UpdateCoeff(N_HORIZ_UV_TAPS, fCutoffUV, TRUE, FALSE, xcoeffUV);
-
-	 for (i = 0; i < N_PHASES; i++) {
-	    for (j = 0; j < N_HORIZ_Y_TAPS; j++) {
-	       pos = i * N_HORIZ_Y_TAPS + j;
-	       overlay->Y_HCOEFS[pos] = xcoeffY[pos].sign << 15 |
-					xcoeffY[pos].exponent << 12 |
-					xcoeffY[pos].mantissa;
-	    }
-	 }
-	 for (i = 0; i < N_PHASES; i++) {
-	    for (j = 0; j < N_HORIZ_UV_TAPS; j++) {
-	       pos = i * N_HORIZ_UV_TAPS + j;
-	       overlay->UV_HCOEFS[pos] = xcoeffUV[pos].sign << 15 |
-					 xcoeffUV[pos].exponent << 12 |
-					 xcoeffUV[pos].mantissa;
-	    }
-	 }
-      }
-   }
-
-   switch (id) {
-   case FOURCC_YV12:
-   case FOURCC_I420:
-      OVERLAY_DEBUG("YUV420\n");
+    switch (id) {
+    case FOURCC_YV12:
+    case FOURCC_I420:
+	OVERLAY_DEBUG("YUV420\n");
 #if 0
-      /* set UV vertical phase to -0.25 */
-      overlay->UV_VPH = 0x30003000;
+	/* set UV vertical phase to -0.25 */
+	overlay->UV_VPH = 0x30003000;
 #endif
-      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;
-      overlay->OCMD |= YUV_420;
-      break;
-   case FOURCC_UYVY:
-   case FOURCC_YUY2:
-   default:
-      OVERLAY_DEBUG("YUV422\n");
-      overlay->OSTRIDE = dstPitch;
-      overlay->OCMD &= ~SOURCE_FORMAT;
-      overlay->OCMD |= YUV_422;
-      overlay->OCMD &= ~OV_BYTE_ORDER;
-      if (id == FOURCC_UYVY)
-	 overlay->OCMD |= Y_SWAP;
-      break;
-   }
-
-   overlay->OCMD &= ~(BUFFER_SELECT | FIELD_SELECT);
-   if (pPriv->currentBuf == 0)
-      overlay->OCMD |= BUFFER0;
-   else
-      overlay->OCMD |= BUFFER1;
+	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;
+	overlay->OCMD |= YUV_420;
+	break;
+    case FOURCC_UYVY:
+    case FOURCC_YUY2:
+    default:
+	OVERLAY_DEBUG("YUV422\n");
+	overlay->OSTRIDE = dstPitch;
+	overlay->OCMD &= ~SOURCE_FORMAT;
+	overlay->OCMD |= YUV_422;
+	overlay->OCMD &= ~OV_BYTE_ORDER;
+	if (id == FOURCC_UYVY)
+	    overlay->OCMD |= Y_SWAP;
+	break;
+    }
+
+    overlay->OCMD &= ~(BUFFER_SELECT | FIELD_SELECT);
+    if (pPriv->currentBuf == 0)
+	overlay->OCMD |= BUFFER0;
+    else
+	overlay->OCMD |= BUFFER1;
 
-   OVERLAY_DEBUG("OCMD is 0x%lx\n", overlay->OCMD);
+    OVERLAY_DEBUG("OCMD is 0x%lx\n", overlay->OCMD);
 
-   i830_overlay_continue (pScrn);
+    i830_overlay_continue (pScrn);
 }
 
 #ifdef I830_USE_EXA
 static void
 I830VideoSave(ScreenPtr pScreen, ExaOffscreenArea *area)
 {
-   struct linear_alloc *linear = area->privData;
+    struct linear_alloc *linear = area->privData;
 
-   linear->exa = NULL;
-   linear->offset = 0;
+    linear->exa = NULL;
+    linear->offset = 0;
 }
 #endif /* I830_USE_EXA */
 
@@ -2137,86 +2124,86 @@ static void
 I830AllocateMemory(ScrnInfoPtr pScrn, struct linear_alloc *linear, int size,
 		   int align)
 {
-   ScreenPtr pScreen = pScrn->pScreen;
-   I830Ptr pI830 = I830PTR(pScrn);
+    ScreenPtr pScreen = pScrn->pScreen;
+    I830Ptr pI830 = I830PTR(pScrn);
 
 #ifdef I830_USE_EXA
-   if (pI830->useEXA) {
-      if (linear->exa != NULL) {
-	 if (linear->exa->size >= size)
+    if (pI830->useEXA) {
+	if (linear->exa != NULL) {
+	    if (linear->exa->size >= size)
+		return;
+
+	    exaOffscreenFree(pScreen, linear->exa);
+	    linear->offset = 0;
+	}
+
+	linear->exa = exaOffscreenAlloc(pScreen, size, align, TRUE,
+					I830VideoSave, linear);
+	if (linear->exa == NULL)
 	    return;
-
-	 exaOffscreenFree(pScreen, linear->exa);
-	 linear->offset = 0;
-      }
-
-      linear->exa = exaOffscreenAlloc(pScreen, size, align, TRUE,
-				      I830VideoSave, linear);
-      if (linear->exa == NULL)
-	 return;
-      linear->offset = linear->exa->offset;
-   }
+	linear->offset = linear->exa->offset;
+    }
 #endif /* I830_USE_EXA */
 #ifdef I830_USE_XAA
-   if (!pI830->useEXA) {
-      /* Converts an offset from XAA's linear allocator to an offset from the
-       * start of fb.
-       */
+    if (!pI830->useEXA) {
+	/* Converts an offset from XAA's linear allocator to an offset from the
+	 * start of fb.
+	 */
 #define XAA_OFFSET_TO_OFFSET(x) \
 	(pI830->front_buffer->offset + (x * pI830->cpp))
 
-      /* 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;
-
-      if (linear->xaa != NULL) {
-	 if (linear->xaa->size >= size) {
-	    linear->offset = XAA_OFFSET_TO_OFFSET(linear->xaa->offset);
-	    return;
-	 }
+	/* 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;
+
+	if (linear->xaa != NULL) {
+	    if (linear->xaa->size >= size) {
+		linear->offset = XAA_OFFSET_TO_OFFSET(linear->xaa->offset);
+		return;
+	    }
 
-	 if (xf86ResizeOffscreenLinear(linear->xaa, size)) {
-	    linear->offset = XAA_OFFSET_TO_OFFSET(linear->xaa->offset);
-	    return;
-	 }
+	    if (xf86ResizeOffscreenLinear(linear->xaa, size)) {
+		linear->offset = XAA_OFFSET_TO_OFFSET(linear->xaa->offset);
+		return;
+	    }
 
-	 xf86FreeOffscreenLinear(linear->xaa);
-      }
+	    xf86FreeOffscreenLinear(linear->xaa);
+	}
 
-      linear->xaa = i830_xf86AllocateOffscreenLinear(pScreen, size, align,
-						     NULL, NULL, NULL);
-      if (linear->xaa == NULL)
-	 return;
+	linear->xaa = i830_xf86AllocateOffscreenLinear(pScreen, size, align,
+						       NULL, NULL, NULL);
+	if (linear->xaa == NULL)
+	    return;
 
-      linear->offset = XAA_OFFSET_TO_OFFSET(linear->xaa->offset);
-   }
+	linear->offset = XAA_OFFSET_TO_OFFSET(linear->xaa->offset);
+    }
 #endif /* I830_USE_XAA */
 }
 
 static void
 I830FreeMemory(ScrnInfoPtr pScrn, struct linear_alloc *linear)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
+    I830Ptr pI830 = I830PTR(pScrn);
 
 #ifdef I830_USE_EXA
-   if (pI830->useEXA) {
-      if (linear->exa != NULL) {
-	 exaOffscreenFree(pScrn->pScreen, linear->exa);
-	 linear->exa = NULL;
-      }
-   }
+    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;
-      }
-   }
+    if (!pI830->useEXA) {
+	if (linear->xaa != NULL) {
+	    xf86FreeOffscreenLinear(linear->xaa);
+	    linear->xaa = NULL;
+	}
+    }
 #endif /* I830_USE_XAA */
-   linear->offset = 0;
+    linear->offset = 0;
 }
 
 /*
@@ -2243,274 +2230,274 @@ I830PutImage(ScrnInfoPtr pScrn,
 	     Bool sync, RegionPtr clipBoxes, pointer data,
 	     DrawablePtr pDraw)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
-   I830PortPrivPtr pPriv = (I830PortPrivPtr) data;
-   ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
-   I830OverlayRegPtr overlay;
-   PixmapPtr pPixmap;
-   INT32 x1, x2, y1, y2;
-   int srcPitch, srcPitch2 = 0, dstPitch, destId;
-   int top, left, npixels, nlines, size, loops;
-   BoxRec dstBox;
-   int pitchAlignMask;
-   int extraLinear;
-
-   if (pPriv->textured)
-       overlay = NULL;
-   else
-       overlay = (I830OverlayRegPtr) (pI830->FbBase + 
-	       pI830->overlay_regs->offset);
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830PortPrivPtr pPriv = (I830PortPrivPtr) data;
+    ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
+    I830OverlayRegPtr overlay;
+    PixmapPtr pPixmap;
+    INT32 x1, x2, y1, y2;
+    int srcPitch, srcPitch2 = 0, dstPitch, destId;
+    int top, left, npixels, nlines, size, loops;
+    BoxRec dstBox;
+    int pitchAlignMask;
+    int extraLinear;
+
+    if (pPriv->textured)
+	overlay = NULL;
+    else
+	overlay = (I830OverlayRegPtr) (pI830->FbBase + 
+				       pI830->overlay_regs->offset);
 
 #if 0
-   ErrorF("I830PutImage: src: (%d,%d)(%d,%d), dst: (%d,%d)(%d,%d)\n"
+    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 &&
-	     pI830->entityPrivate->XvInUse != I830CrtcPipe (pPriv->current_crtc)) {
+    if (pI830->entityPrivate) {
+	if (pI830->entityPrivate->XvInUse != -1 &&
+	    pI830->entityPrivate->XvInUse != I830CrtcPipe (pPriv->current_crtc)) {
 #ifdef PANORAMIX
-		if (!noPanoramiXExtension) {
-			return Success; /* faked for trying to share it */
-		} else
+	    if (!noPanoramiXExtension) {
+		return Success; /* faked for trying to share it */
+	    } else
 #endif
-		{
-			return BadAlloc;
-		}
-	 }
+	    {
+		return BadAlloc;
+	    }
+	}
 
-      pI830->entityPrivate->XvInUse = I830CrtcPipe (pPriv->current_crtc);;
-   }
+	pI830->entityPrivate->XvInUse = I830CrtcPipe (pPriv->current_crtc);;
+    }
 
-   /* overlay limits */
-   if(src_w > (drw_w * 7))
-      drw_w = src_w * 7;
-
-   if(src_h > (drw_h * 7))
-      drw_h = src_h * 7;
-
-   /* Clip */
-   x1 = src_x;
-   x2 = src_x + src_w;
-   y1 = src_y;
-   y2 = src_y + src_h;
-
-   dstBox.x1 = drw_x;
-   dstBox.x2 = drw_x + drw_w;
-   dstBox.y1 = drw_y;
-   dstBox.y2 = drw_y + drw_h;
-
-   if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes,
-			      width, height))
-      return Success;
-
-   destId = id;
-   switch (id) {
-   case FOURCC_YV12:
-   case FOURCC_I420:
-      srcPitch = (width + 3) & ~3;
-      srcPitch2 = ((width >> 1) + 3) & ~3;
-      if (pPriv->textured) {
-	 destId = FOURCC_YUY2;
-      }
-      break;
-   case FOURCC_UYVY:
-   case FOURCC_YUY2:
-   default:
-      srcPitch = width << 1;
-      break;
-   }
-
-   /* Only needs to be DWORD-aligned for textured on i915, but overlay has
-    * stricter requirements.
-    */
-   if (pPriv->textured) {
-      pitchAlignMask = 3;
-   } else {
-      if (IS_I965G(pI830))
-	 pitchAlignMask = 255;
-      else
-	 pitchAlignMask = 63;
-   }
-
-   /* Determine the desired destination pitch (representing the chroma's pitch,
-    * in the planar case.
-    */
-   switch (destId) {
-   case FOURCC_YV12:
-   case FOURCC_I420:
-      if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
-         dstPitch = ((height / 2) + pitchAlignMask) & ~pitchAlignMask;
-         size = dstPitch * width * 3;
-      } else {
-         dstPitch = ((width / 2) + pitchAlignMask) & ~pitchAlignMask;
-         size = dstPitch * height * 3;
-      }
-      break;
-   case FOURCC_UYVY:
-   case FOURCC_YUY2:
-   default:
-      if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
-         dstPitch = ((height << 1) + pitchAlignMask) & ~pitchAlignMask;
-         size = dstPitch * width;
-      } else {
-         dstPitch = ((width << 1) + pitchAlignMask) & ~pitchAlignMask;
-         size = dstPitch * height;
-      }
-      break;
-   }
+    /* overlay limits */
+    if(src_w > (drw_w * 7))
+	drw_w = src_w * 7;
+
+    if(src_h > (drw_h * 7))
+	drw_h = src_h * 7;
+
+    /* Clip */
+    x1 = src_x;
+    x2 = src_x + src_w;
+    y1 = src_y;
+    y2 = src_y + src_h;
+
+    dstBox.x1 = drw_x;
+    dstBox.x2 = drw_x + drw_w;
+    dstBox.y1 = drw_y;
+    dstBox.y2 = drw_y + drw_h;
+
+    if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes,
+			       width, height))
+	return Success;
+
+    destId = id;
+    switch (id) {
+    case FOURCC_YV12:
+    case FOURCC_I420:
+	srcPitch = (width + 3) & ~3;
+	srcPitch2 = ((width >> 1) + 3) & ~3;
+	if (pPriv->textured) {
+	    destId = FOURCC_YUY2;
+	}
+	break;
+    case FOURCC_UYVY:
+    case FOURCC_YUY2:
+    default:
+	srcPitch = width << 1;
+	break;
+    }
+
+    /* Only needs to be DWORD-aligned for textured on i915, but overlay has
+     * stricter requirements.
+     */
+    if (pPriv->textured) {
+	pitchAlignMask = 3;
+    } else {
+	if (IS_I965G(pI830))
+	    pitchAlignMask = 255;
+	else
+	    pitchAlignMask = 63;
+    }
+
+    /* Determine the desired destination pitch (representing the chroma's pitch,
+     * in the planar case.
+     */
+    switch (destId) {
+    case FOURCC_YV12:
+    case FOURCC_I420:
+	if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
+	    dstPitch = ((height / 2) + pitchAlignMask) & ~pitchAlignMask;
+	    size = dstPitch * width * 3;
+	} else {
+	    dstPitch = ((width / 2) + pitchAlignMask) & ~pitchAlignMask;
+	    size = dstPitch * height * 3;
+	}
+	break;
+    case FOURCC_UYVY:
+    case FOURCC_YUY2:
+    default:
+	if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
+	    dstPitch = ((height << 1) + pitchAlignMask) & ~pitchAlignMask;
+	    size = dstPitch * width;
+	} else {
+	    dstPitch = ((width << 1) + pitchAlignMask) & ~pitchAlignMask;
+	    size = dstPitch * height;
+	}
+	break;
+    }
 #if 0
-   ErrorF("srcPitch: %d, dstPitch: %d, size: %d\n", srcPitch, dstPitch, size);
+    ErrorF("srcPitch: %d, dstPitch: %d, size: %d\n", srcPitch, dstPitch, size);
 #endif
 
-   if (IS_I965G(pI830))
-      extraLinear = BRW_LINEAR_EXTRA;
-   else
-      extraLinear = 0;
-
-   /* size is multiplied by 2 because we have two buffers that are flipping */
-   I830AllocateMemory(pScrn, &pPriv->linear,
-		      extraLinear + (pPriv->doubleBuffer ? size * 2 : size),
-		      16);
-
-   if (pPriv->linear.offset == 0)
-      return BadAlloc;
-
-   pPriv->extra_offset = pPriv->linear.offset +
-      (pPriv->doubleBuffer ? size * 2 : size);
-
-   /* fixup pointers */
-   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);
-      if(pPriv->doubleBuffer) {
-         pPriv->YBuf1offset = pPriv->YBuf0offset + size;
-         pPriv->UBuf1offset = pPriv->YBuf1offset + (dstPitch * 2 * width);
-         pPriv->VBuf1offset = pPriv->UBuf1offset + (dstPitch * width / 2);
-      }
-   } else {
-      pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * height);
-      pPriv->VBuf0offset = pPriv->UBuf0offset + (dstPitch * height / 2);
-      if(pPriv->doubleBuffer) {
-         pPriv->YBuf1offset = pPriv->YBuf0offset + size;
-         pPriv->UBuf1offset = pPriv->YBuf1offset + (dstPitch * 2 * height);
-         pPriv->VBuf1offset = pPriv->UBuf1offset + (dstPitch * height / 2);
-      }
-   }
-
-   /* Make sure this buffer isn't in use */
-   loops = 0;
-   if (!pPriv->textured && *pI830->overlayOn && pPriv->doubleBuffer &&
-       (overlay->OCMD & OVERLAY_ENABLE))
-   {
-      while (loops < 1000000) {
+    if (IS_I965G(pI830))
+	extraLinear = BRW_LINEAR_EXTRA;
+    else
+	extraLinear = 0;
+
+    /* size is multiplied by 2 because we have two buffers that are flipping */
+    I830AllocateMemory(pScrn, &pPriv->linear,
+		       extraLinear + (pPriv->doubleBuffer ? size * 2 : size),
+		       16);
+
+    if (pPriv->linear.offset == 0)
+	return BadAlloc;
+
+    pPriv->extra_offset = pPriv->linear.offset +
+    (pPriv->doubleBuffer ? size * 2 : size);
+
+    /* fixup pointers */
+    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);
+	if(pPriv->doubleBuffer) {
+	    pPriv->YBuf1offset = pPriv->YBuf0offset + size;
+	    pPriv->UBuf1offset = pPriv->YBuf1offset + (dstPitch * 2 * width);
+	    pPriv->VBuf1offset = pPriv->UBuf1offset + (dstPitch * width / 2);
+	}
+    } else {
+	pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * height);
+	pPriv->VBuf0offset = pPriv->UBuf0offset + (dstPitch * height / 2);
+	if(pPriv->doubleBuffer) {
+	    pPriv->YBuf1offset = pPriv->YBuf0offset + size;
+	    pPriv->UBuf1offset = pPriv->YBuf1offset + (dstPitch * 2 * height);
+	    pPriv->VBuf1offset = pPriv->UBuf1offset + (dstPitch * height / 2);
+	}
+    }
+
+    /* Make sure this buffer isn't in use */
+    loops = 0;
+    if (!pPriv->textured && *pI830->overlayOn && pPriv->doubleBuffer &&
+	(overlay->OCMD & OVERLAY_ENABLE))
+    {
+	while (loops < 1000000) {
 #if USE_USLEEP_FOR_VIDEO
-         usleep(10);
+	    usleep(10);
 #endif
-         if (((INREG(DOVSTA) & OC_BUF) >> 20) == pPriv->currentBuf) {
-	    break;
-         }
-         loops++;
-      }
-      if (loops >= 1000000) {
-         ErrorF("loops (1) maxed out for buffer %d\n", pPriv->currentBuf);
+	    if (((INREG(DOVSTA) & OC_BUF) >> 20) == pPriv->currentBuf) {
+		break;
+	    }
+	    loops++;
+	}
+	if (loops >= 1000000) {
+	    ErrorF("loops (1) maxed out for buffer %d\n", pPriv->currentBuf);
 #if 0
-         pPriv->currentBuf = !pPriv->currentBuf;
+	    pPriv->currentBuf = !pPriv->currentBuf;
 #endif
-      }
+	}
 
-      /* buffer swap */
-      if (pPriv->currentBuf == 0)
-         pPriv->currentBuf = 1;
-      else
-         pPriv->currentBuf = 0;
-   }
-
-   /* copy data */
-   top = y1 >> 16;
-   left = (x1 >> 16) & ~1;
-   npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left;
-
-   if (pPriv->textured) {
-      /* For textured video, we don't double buffer, and instead just wait for
-       * acceleration to finish before writing the new video data into
-       * framebuffer.
-       */
-      i830WaitSync(pScrn);
-   }
-
-   switch (id) {
-   case FOURCC_YV12:
-   case FOURCC_I420:
-      top &= ~1;
-      nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top;
-      if (pPriv->textured) {
-	 I830CopyPlanarToPackedData(pScrn, pPriv, buf, srcPitch, srcPitch2,
-				    dstPitch, height, top, left, nlines,
-				    npixels, id);
-      } else {
-	 I830CopyPlanarData(pScrn, pPriv, buf, srcPitch, srcPitch2, dstPitch,
-			    height, top, left, nlines, npixels, id);
-      }
-      break;
-   case FOURCC_UYVY:
-   case FOURCC_YUY2:
-   default:
-      nlines = ((y2 + 0xffff) >> 16) - top;
-      I830CopyPackedData(pScrn, pPriv, buf, srcPitch, dstPitch, top, left,
-			 nlines, npixels);
-      break;
-   }
-
-   if (pDraw->type == DRAWABLE_WINDOW) {
-      pPixmap = (*pScreen->GetWindowPixmap)((WindowPtr)pDraw);
-   } else {
-      pPixmap = (PixmapPtr)pDraw;
-   }
+	/* buffer swap */
+	if (pPriv->currentBuf == 0)
+	    pPriv->currentBuf = 1;
+	else
+	    pPriv->currentBuf = 0;
+    }
+
+    /* copy data */
+    top = y1 >> 16;
+    left = (x1 >> 16) & ~1;
+    npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left;
+
+    if (pPriv->textured) {
+	/* For textured video, we don't double buffer, and instead just wait for
+	 * acceleration to finish before writing the new video data into
+	 * framebuffer.
+	 */
+	i830WaitSync(pScrn);
+    }
+
+    switch (id) {
+    case FOURCC_YV12:
+    case FOURCC_I420:
+	top &= ~1;
+	nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top;
+	if (pPriv->textured) {
+	    I830CopyPlanarToPackedData(pScrn, pPriv, buf, srcPitch, srcPitch2,
+				       dstPitch, height, top, left, nlines,
+				       npixels, id);
+	} else {
+	    I830CopyPlanarData(pScrn, pPriv, buf, srcPitch, srcPitch2, dstPitch,
+			       height, top, left, nlines, npixels, id);
+	}
+	break;
+    case FOURCC_UYVY:
+    case FOURCC_YUY2:
+    default:
+	nlines = ((y2 + 0xffff) >> 16) - top;
+	I830CopyPackedData(pScrn, pPriv, buf, srcPitch, dstPitch, top, left,
+			   nlines, npixels);
+	break;
+    }
+
+    if (pDraw->type == DRAWABLE_WINDOW) {
+	pPixmap = (*pScreen->GetWindowPixmap)((WindowPtr)pDraw);
+    } else {
+	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)) {
-      /* 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)) {
- 	REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
-	 xf86XVFillKeyHelper(pScreen, pPriv->colorKey, clipBoxes);
-      }
-
-      I830DisplayVideo(pScrn, destId, width, height, dstPitch,
-		       x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
-   } 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, pPixmap);
-   } else {
-      I915DisplayVideoTextured(pScrn, pPriv, destId, clipBoxes, width, height,
-			       dstPitch, x1, y1, x2, y2,
-			       src_w, src_h, drw_w, drw_h, pPixmap);
-   }
-   if (pPriv->textured) {
-      DamageDamageRegion(pDraw, clipBoxes);
-   }
+    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)) {
+	/* 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)) {
+	    REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
+	    xf86XVFillKeyHelper(pScreen, pPriv->colorKey, clipBoxes);
+	}
+
+	I830DisplayVideo(pScrn, destId, width, height, dstPitch,
+			 x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
+    } 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, pPixmap);
+    } else {
+	I915DisplayVideoTextured(pScrn, pPriv, destId, clipBoxes, width, height,
+				 dstPitch, x1, y1, x2, y2,
+				 src_w, src_h, drw_w, drw_h, pPixmap);
+    }
+    if (pPriv->textured) {
+	DamageDamageRegion(pDraw, clipBoxes);
+    }
 
-   pPriv->videoStatus = CLIENT_VIDEO_ON;
+    pPriv->videoStatus = CLIENT_VIDEO_ON;
 
-   return Success;
+    return Success;
 }
 
 static int
@@ -2519,75 +2506,75 @@ I830QueryImageAttributes(ScrnInfoPtr pSc
 			 unsigned short *w, unsigned short *h,
 			 int *pitches, int *offsets, Bool textured)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
-   int size, tmp;
+    I830Ptr pI830 = I830PTR(pScrn);
+    int size, tmp;
 
 #if 0
-   ErrorF("I830QueryImageAttributes: w is %d, h is %d\n", *w, *h);
+    ErrorF("I830QueryImageAttributes: w is %d, h is %d\n", *w, *h);
 #endif
 
-   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)
-      offsets[0] = 0;
-
-   switch (id) {
-      /* IA44 is for XvMC only */
-   case FOURCC_IA44:
-   case FOURCC_AI44:
-      if (pitches)
-	 pitches[0] = *w;
-      size = *w * *h;
-      break;
-   case FOURCC_YV12:
-   case FOURCC_I420:
-      *h = (*h + 1) & ~1;
-      size = (*w + 3) & ~3;
-      if (pitches)
-	 pitches[0] = size;
-      size *= *h;
-      if (offsets)
-	 offsets[1] = size;
-      tmp = ((*w >> 1) + 3) & ~3;
-      if (pitches)
-	 pitches[1] = pitches[2] = tmp;
-      tmp *= (*h >> 1);
-      size += tmp;
-      if (offsets)
-	 offsets[2] = size;
-      size += tmp;
+    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)
+	offsets[0] = 0;
+
+    switch (id) {
+	/* IA44 is for XvMC only */
+    case FOURCC_IA44:
+    case FOURCC_AI44:
+	if (pitches)
+	    pitches[0] = *w;
+	size = *w * *h;
+	break;
+    case FOURCC_YV12:
+    case FOURCC_I420:
+	*h = (*h + 1) & ~1;
+	size = (*w + 3) & ~3;
+	if (pitches)
+	    pitches[0] = size;
+	size *= *h;
+	if (offsets)
+	    offsets[1] = size;
+	tmp = ((*w >> 1) + 3) & ~3;
+	if (pitches)
+	    pitches[1] = pitches[2] = tmp;
+	tmp *= (*h >> 1);
+	size += tmp;
+	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]);
-      if (offsets)
-	 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:
-   default:
-      size = *w << 1;
-      if (pitches)
-	 pitches[0] = size;
-      size *= *h;
-      break;
-   }
+	if (pitches)
+	    ErrorF("pitch 0 is %d, pitch 1 is %d, pitch 2 is %d\n", pitches[0],
+		   pitches[1], pitches[2]);
+	if (offsets)
+	    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:
+    default:
+	size = *w << 1;
+	if (pitches)
+	    pitches[0] = size;
+	size *= *h;
+	break;
+    }
 
-   return size;
+    return size;
 }
 
 static int
@@ -2596,7 +2583,7 @@ I830QueryImageAttributesOverlay(ScrnInfo
 				unsigned short *w, unsigned short *h,
 				int *pitches, int *offsets)
 {
-   return I830QueryImageAttributes(pScrn, id, w, h, pitches, offsets, FALSE);
+    return I830QueryImageAttributes(pScrn, id, w, h, pitches, offsets, FALSE);
 }
 
 static int
@@ -2605,50 +2592,50 @@ I830QueryImageAttributesTextured(ScrnInf
 				 unsigned short *w, unsigned short *h,
 				 int *pitches, int *offsets)
 {
-   return I830QueryImageAttributes(pScrn, id, w, h, pitches, offsets, TRUE);
+    return I830QueryImageAttributes(pScrn, id, w, h, pitches, offsets, TRUE);
 }
 
 static void
 I830BlockHandler(int i,
 		 pointer blockData, pointer pTimeout, pointer pReadmask)
 {
-   ScreenPtr pScreen = screenInfo.screens[i];
-   ScrnInfoPtr pScrn = xf86Screens[i];
-   I830Ptr pI830 = I830PTR(pScrn);
-   I830PortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
+    ScreenPtr pScreen = screenInfo.screens[i];
+    ScrnInfoPtr pScrn = xf86Screens[i];
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830PortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
 
-   pScreen->BlockHandler = pI830->BlockHandler;
+    pScreen->BlockHandler = pI830->BlockHandler;
 
-   (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
+    (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
 
-   pScreen->BlockHandler = I830BlockHandler;
+    pScreen->BlockHandler = I830BlockHandler;
 
-   if (pPriv->videoStatus & TIMER_MASK) {
+    if (pPriv->videoStatus & TIMER_MASK) {
 #if 1
-      Time now = currentTime.milliseconds;
+	Time now = currentTime.milliseconds;
 #else
-      UpdateCurrentTime();
+	UpdateCurrentTime();
 #endif
-      if (pPriv->videoStatus & OFF_TIMER) {
-	 if (pPriv->offTime < now) {
-	    /* Turn off the overlay */
-	    OVERLAY_DEBUG("BLOCKHANDLER\n");
-
-	    i830_overlay_off (pScrn);
-
-	    pPriv->videoStatus = FREE_TIMER;
-	    pPriv->freeTime = now + FREE_DELAY;
-       
-            if (pI830->entityPrivate)
-               pI830->entityPrivate->XvInUse = -1;
-	 }
-      } else {				/* FREE_TIMER */
-	 if (pPriv->freeTime < now) {
-	    I830FreeMemory(pScrn, &pPriv->linear);
-	    pPriv->videoStatus = 0;
-	 }
-      }
-   }
+	if (pPriv->videoStatus & OFF_TIMER) {
+	    if (pPriv->offTime < now) {
+		/* Turn off the overlay */
+		OVERLAY_DEBUG("BLOCKHANDLER\n");
+
+		i830_overlay_off (pScrn);
+
+		pPriv->videoStatus = FREE_TIMER;
+		pPriv->freeTime = now + FREE_DELAY;
+
+		if (pI830->entityPrivate)
+		    pI830->entityPrivate->XvInUse = -1;
+	    }
+	} else {				/* FREE_TIMER */
+	    if (pPriv->freeTime < now) {
+		I830FreeMemory(pScrn, &pPriv->linear);
+		pPriv->videoStatus = 0;
+	    }
+	}
+    }
 }
 
 /***************************************************************************
@@ -2656,8 +2643,8 @@ I830BlockHandler(int i,
  ***************************************************************************/
 
 typedef struct {
-   struct linear_alloc linear;
-   Bool isOn;
+    struct linear_alloc linear;
+    Bool isOn;
 } OffscreenPrivRec, *OffscreenPrivPtr;
 
 static int
@@ -2666,111 +2653,111 @@ I830AllocateSurface(ScrnInfoPtr pScrn,
 		    unsigned short w,
 		    unsigned short h, XF86SurfacePtr surface)
 {
-   int pitch, fbpitch, size;
-   OffscreenPrivPtr pPriv;
-   I830Ptr pI830 = I830PTR(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;
-   }
-
-   /* What to do when rotated ?? */
-   if (pI830->rotation != RR_Rotate_0)
-      return BadAlloc;
-
-   if (!(surface->pitches = xalloc(sizeof(int))))
-      return BadAlloc;
-   if (!(surface->offsets = xalloc(sizeof(int)))) {
-      xfree(surface->pitches);
-      return BadAlloc;
-   }
-   if (!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) {
-      xfree(surface->pitches);
-      xfree(surface->offsets);
-      return BadAlloc;
-   }
-
-   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] = pPriv->linear.offset;
-   surface->devPrivate.ptr = (pointer) pPriv;
+    int pitch, fbpitch, size;
+    OffscreenPrivPtr pPriv;
+    I830Ptr pI830 = I830PTR(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;
+    }
+
+    /* What to do when rotated ?? */
+    if (pI830->rotation != RR_Rotate_0)
+	return BadAlloc;
+
+    if (!(surface->pitches = xalloc(sizeof(int))))
+	return BadAlloc;
+    if (!(surface->offsets = xalloc(sizeof(int)))) {
+	xfree(surface->pitches);
+	return BadAlloc;
+    }
+    if (!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) {
+	xfree(surface->pitches);
+	xfree(surface->offsets);
+	return BadAlloc;
+    }
+
+    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] = pPriv->linear.offset;
+    surface->devPrivate.ptr = (pointer) pPriv;
 
-   memset(pI830->FbBase + surface->offsets[0], 0, size);
+    memset(pI830->FbBase + surface->offsets[0], 0, size);
 
-   return Success;
+    return Success;
 }
 
 static int
 I830StopSurface(XF86SurfacePtr surface)
 {
-   OffscreenPrivPtr pPriv = (OffscreenPrivPtr) surface->devPrivate.ptr;
-   ScrnInfoPtr pScrn = surface->pScrn;
+    OffscreenPrivPtr pPriv = (OffscreenPrivPtr) surface->devPrivate.ptr;
+    ScrnInfoPtr pScrn = surface->pScrn;
 
-   if (pPriv->isOn) {
-      I830Ptr pI830 = I830PTR(pScrn);
+    if (pPriv->isOn) {
+	I830Ptr pI830 = I830PTR(pScrn);
 
-      OVERLAY_DEBUG("StopSurface\n");
+	OVERLAY_DEBUG("StopSurface\n");
 
-      i830_overlay_off (pScrn);
+	i830_overlay_off (pScrn);
 
-      if (pI830->entityPrivate)
-         pI830->entityPrivate->XvInUse = -1;
+	if (pI830->entityPrivate)
+	    pI830->entityPrivate->XvInUse = -1;
 
-      pPriv->isOn = FALSE;
-   }
+	pPriv->isOn = FALSE;
+    }
 
-   return Success;
+    return Success;
 }
 
 static int
 I830FreeSurface(XF86SurfacePtr surface)
 {
-   OffscreenPrivPtr pPriv = (OffscreenPrivPtr) surface->devPrivate.ptr;
+    OffscreenPrivPtr pPriv = (OffscreenPrivPtr) surface->devPrivate.ptr;
 
-   I830StopSurface(surface);
-   I830FreeMemory(surface->pScrn, &pPriv->linear);
-   xfree(surface->pitches);
-   xfree(surface->offsets);
-   xfree(surface->devPrivate.ptr);
+    I830StopSurface(surface);
+    I830FreeMemory(surface->pScrn, &pPriv->linear);
+    xfree(surface->pitches);
+    xfree(surface->offsets);
+    xfree(surface->devPrivate.ptr);
 
-   return Success;
+    return Success;
 }
 
 static int
 I830GetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 * value)
 {
-   return I830GetPortAttribute(pScrn, attribute, value, NULL);
+    return I830GetPortAttribute(pScrn, attribute, value, NULL);
 }
 
 static int
 I830SetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value)
 {
-   return I830SetPortAttribute(pScrn, attribute, value, NULL);
+    return I830SetPortAttribute(pScrn, attribute, value, NULL);
 }
 
 static int
@@ -2780,198 +2767,198 @@ I830DisplaySurface(XF86SurfacePtr surfac
 		   short src_w, short src_h,
 		   short drw_w, short drw_h, RegionPtr clipBoxes)
 {
-   OffscreenPrivPtr pPriv = (OffscreenPrivPtr) surface->devPrivate.ptr;
-   ScrnInfoPtr pScrn = surface->pScrn;
-   ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
-   I830Ptr pI830 = I830PTR(pScrn);
-   I830PortPrivPtr pI830Priv = GET_PORT_PRIVATE(pScrn);
-   INT32 x1, y1, x2, y2;
-   INT32 loops = 0;
-   BoxRec dstBox;
-
-   OVERLAY_DEBUG("I830DisplaySurface\n");
-
-   if (pI830->entityPrivate) {
-	 if (pI830->entityPrivate->XvInUse != -1 &&
-	     pI830->entityPrivate->XvInUse != I830CrtcPipe (pI830Priv->current_crtc)) {
+    OffscreenPrivPtr pPriv = (OffscreenPrivPtr) surface->devPrivate.ptr;
+    ScrnInfoPtr pScrn = surface->pScrn;
+    ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830PortPrivPtr pI830Priv = GET_PORT_PRIVATE(pScrn);
+    INT32 x1, y1, x2, y2;
+    INT32 loops = 0;
+    BoxRec dstBox;
+
+    OVERLAY_DEBUG("I830DisplaySurface\n");
+
+    if (pI830->entityPrivate) {
+	if (pI830->entityPrivate->XvInUse != -1 &&
+	    pI830->entityPrivate->XvInUse != I830CrtcPipe (pI830Priv->current_crtc)) {
 #ifdef PANORAMIX
-		if (!noPanoramiXExtension) {
-			return Success; /* faked for trying to share it */
-		} else
+	    if (!noPanoramiXExtension) {
+		return Success; /* faked for trying to share it */
+	    } else
 #endif
-		{
-			return BadAlloc;
-		}
-	 }
+	    {
+		return BadAlloc;
+	    }
+	}
 
-      pI830->entityPrivate->XvInUse = I830CrtcPipe (pI830Priv->current_crtc);
-   }
+	pI830->entityPrivate->XvInUse = I830CrtcPipe (pI830Priv->current_crtc);
+    }
 
-   x1 = src_x;
-   x2 = src_x + src_w;
-   y1 = src_y;
-   y2 = src_y + src_h;
-
-   dstBox.x1 = drw_x;
-   dstBox.x2 = drw_x + drw_w;
-   dstBox.y1 = drw_y;
-   dstBox.y2 = drw_y + drw_h;
-
-   if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes,
-			      surface->width, surface->height))
-      return Success;
-
-   /* fixup pointers */
-   pI830Priv->YBuf0offset = surface->offsets[0];
-   pI830Priv->YBuf1offset = pI830Priv->YBuf0offset;
-
-   /* Make sure this buffer isn't in use */
-   loops = 0;
-   if (*pI830->overlayOn && pI830Priv->doubleBuffer) 
-   {
-      while (loops < 1000000) {
+    x1 = src_x;
+    x2 = src_x + src_w;
+    y1 = src_y;
+    y2 = src_y + src_h;
+
+    dstBox.x1 = drw_x;
+    dstBox.x2 = drw_x + drw_w;
+    dstBox.y1 = drw_y;
+    dstBox.y2 = drw_y + drw_h;
+
+    if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes,
+			       surface->width, surface->height))
+	return Success;
+
+    /* fixup pointers */
+    pI830Priv->YBuf0offset = surface->offsets[0];
+    pI830Priv->YBuf1offset = pI830Priv->YBuf0offset;
+
+    /* Make sure this buffer isn't in use */
+    loops = 0;
+    if (*pI830->overlayOn && pI830Priv->doubleBuffer) 
+    {
+	while (loops < 1000000) {
 #if USE_USLEEP_FOR_VIDEO
-         usleep(10);
+	    usleep(10);
 #endif
-         if (((INREG(DOVSTA) & OC_BUF) >> 20) == pI830Priv->currentBuf) {
-	    break;
-         }
-         loops++;
-      }
-      if (loops >= 1000000) {
-         ErrorF("loops (1) maxed out for buffer %d\n", pI830Priv->currentBuf);
+	    if (((INREG(DOVSTA) & OC_BUF) >> 20) == pI830Priv->currentBuf) {
+		break;
+	    }
+	    loops++;
+	}
+	if (loops >= 1000000) {
+	    ErrorF("loops (1) maxed out for buffer %d\n", pI830Priv->currentBuf);
 #if 0
-         pI830Priv->currentBuf = !pI830Priv->currentBuf;
+	    pI830Priv->currentBuf = !pI830Priv->currentBuf;
 #endif
-      }
+	}
 
-      /* buffer swap */
-      pI830Priv->currentBuf = !pI830Priv->currentBuf;
-   }
-
-   I830DisplayVideo(pScrn, surface->id, surface->width, surface->height,
-		    surface->pitches[0], x1, y1, x2, y2, &dstBox,
-		    src_w, src_h, drw_w, drw_h);
-
-   xf86XVFillKeyHelper(pScreen, pI830Priv->colorKey, clipBoxes);
-
-   pPriv->isOn = TRUE;
-   /* we've prempted the XvImage stream so set its free timer */
-   if (pI830Priv->videoStatus & CLIENT_VIDEO_ON) {
-      REGION_EMPTY(pScrn->pScreen, &pI830Priv->clip);
-      UpdateCurrentTime();
-      pI830Priv->videoStatus = FREE_TIMER;
-      pI830Priv->freeTime = currentTime.milliseconds + FREE_DELAY;
-      pScrn->pScreen->BlockHandler = I830BlockHandler;
-   }
+	/* buffer swap */
+	pI830Priv->currentBuf = !pI830Priv->currentBuf;
+    }
+
+    I830DisplayVideo(pScrn, surface->id, surface->width, surface->height,
+		     surface->pitches[0], x1, y1, x2, y2, &dstBox,
+		     src_w, src_h, drw_w, drw_h);
+
+    xf86XVFillKeyHelper(pScreen, pI830Priv->colorKey, clipBoxes);
+
+    pPriv->isOn = TRUE;
+    /* we've prempted the XvImage stream so set its free timer */
+    if (pI830Priv->videoStatus & CLIENT_VIDEO_ON) {
+	REGION_EMPTY(pScrn->pScreen, &pI830Priv->clip);
+	UpdateCurrentTime();
+	pI830Priv->videoStatus = FREE_TIMER;
+	pI830Priv->freeTime = currentTime.milliseconds + FREE_DELAY;
+	pScrn->pScreen->BlockHandler = I830BlockHandler;
+    }
 
-   return Success;
+    return Success;
 }
 
 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)))) {
-      return;
-   }
-
-   offscreenImages[0].image = &Images[0];
-   offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES /*| VIDEO_CLIP_TO_VIEWPORT*/;
-   offscreenImages[0].alloc_surface = I830AllocateSurface;
-   offscreenImages[0].free_surface = I830FreeSurface;
-   offscreenImages[0].display = I830DisplaySurface;
-   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].num_attributes = 1;
-   offscreenImages[0].attributes = Attributes;
+    XF86OffscreenImagePtr offscreenImages;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    /* need to free this someplace */
+    if (!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec)))) {
+	return;
+    }
+
+    offscreenImages[0].image = &Images[0];
+    offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES /*| VIDEO_CLIP_TO_VIEWPORT*/;
+    offscreenImages[0].alloc_surface = I830AllocateSurface;
+    offscreenImages[0].free_surface = I830FreeSurface;
+    offscreenImages[0].display = I830DisplaySurface;
+    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].num_attributes = 1;
+    offscreenImages[0].attributes = Attributes;
 
-   xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1);
+    xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1);
 }
 
 void
 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 == NULL)
-      return;
-
-   /* No overlay scaler on the 965. */
-   if (IS_I965G(pI830))
-      return;
-
-   pPriv = GET_PORT_PRIVATE(pScrn);
-
-   /* Check if it's the crtc the overlay is on */
-   if (crtc != pPriv->current_crtc)
-      return;
-
-   if (on) {
-      int size, hsize, vsize, active;
-      int pipeconf_reg = intel_crtc->pipe == 0 ? PIPEACONF : PIPEBCONF;
-      char pipename = intel_crtc->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(crtc, I830_OUTPUT_LVDS)) {
-	 int vtotal_reg = intel_crtc->pipe ? VTOTAL_A : VTOTAL_B;
-	 size = intel_crtc->pipe ? INREG(PIPEBSRC) : INREG(PIPEASRC);
-	 hsize = (size >> 16) & 0x7FF;
-	 vsize = size & 0x7FF;
-	 active = INREG(vtotal_reg) & 0x7FF;
+    ScrnInfoPtr pScrn = crtc->scrn;
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830PortPrivPtr pPriv;
+    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+
+    if (pI830->adaptor == NULL)
+	return;
 
-	 if (vsize < active && hsize > 1024)
-	    I830SetOneLineModeRatio(pScrn);
+    /* No overlay scaler on the 965. */
+    if (IS_I965G(pI830))
+	return;
 
-	 if (pPriv->scaleRatio & 0xFFFE0000) {
-	    /* Possible bogus ratio, using in-accurate fallback */
+    pPriv = GET_PORT_PRIVATE(pScrn);
+
+    /* Check if it's the crtc the overlay is on */
+    if (crtc != pPriv->current_crtc)
+	return;
+
+    if (on) {
+	int size, hsize, vsize, active;
+	int pipeconf_reg = intel_crtc->pipe == 0 ? PIPEACONF : PIPEBCONF;
+	char pipename = intel_crtc->pipe == 0 ? 'A' : 'B';
+
+	pPriv->overlayOK = TRUE;
+
+	if (INREG(pipeconf_reg) & PIPEACONF_DOUBLE_WIDE) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		       "Bogus panel fit register, Xvideo positioning may not "
-		       "be accurate.\n");
+		       "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,
-		       "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);
-	 }
-      }
-   } 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;
-   }
+		       "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(crtc, I830_OUTPUT_LVDS)) {
+	    int vtotal_reg = intel_crtc->pipe ? VTOTAL_A : VTOTAL_B;
+	    size = intel_crtc->pipe ? INREG(PIPEBSRC) : INREG(PIPEASRC);
+	    hsize = (size >> 16) & 0x7FF;
+	    vsize = size & 0x7FF;
+	    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));
+
+		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 02935ced3fba598a01d908ae49ccc30cbcc765a8 (from 08753f9b79f3f09879a18b552d90d88dbf52d4be)
Author: Keith Packard <keithp at dulcimer.keithp.com>
Date:   Wed May 23 19:24:25 2007 -0700

    Clean up overlay management.
    
    Create separate on/continue/off functions for overlay.
    Manage overlayOn boolean within those functions.
    Eliminate redundant management code in other routines.

diff --git a/src/i830_video.c b/src/i830_video.c
index 852c00f..2462d5d 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -357,80 +357,81 @@ CompareOverlay(I830Ptr pI830, CARD32 * o
 
 /*
  * 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
- * overlay in OCMD and calling OVERLAY_UPDATE.
+ * the overlay.
  *
  * XXX Need to make sure that the overlay engine is cleanly shutdown in
  * all modes of server exit.
  */
 
 static void
-i830_overlay_update(ScrnInfoPtr pScrn)
+i830_overlay_on(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
+    I830OverlayRegPtr	overlay = (I830OverlayRegPtr) (pI830->FbBase +
+						       pI830->overlay_regs->offset);
+    
+    if (*pI830->overlayOn)
+	return;
 
-    BEGIN_LP_RING(8);
+    overlay->OCMD &= ~OVERLAY_ENABLE;
+    BEGIN_LP_RING(6);
     OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE);
     OUT_RING(MI_NOOP);
-    if (!*pI830->overlayOn) {
-	OUT_RING(MI_NOOP);
-	OUT_RING(MI_NOOP);
-	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_ON);
-	OVERLAY_DEBUG("Overlay goes from off to on\n");
-	*pI830->overlayOn = TRUE;
-    } else {
-	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
-	OUT_RING(MI_NOOP);
-	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_CONTINUE);
-    }
-    if (IS_I965G(pI830))
-	OUT_RING(pI830->overlay_regs->offset | OFC_UPDATE);
-    else
-	OUT_RING(pI830->overlay_regs->bus_addr | OFC_UPDATE);
+    OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_ON);
+    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();
-    OVERLAY_DEBUG("OVERLAY_UPDATE\n");
+    OVERLAY_DEBUG("overlay_on\n");
+    *pI830->overlayOn = TRUE;
 }
 
-#define OVERLAY_UPDATE	i830_overlay_update(pScrn)
+static void
+i830_overlay_continue(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830OverlayRegPtr	overlay = (I830OverlayRegPtr) (pI830->FbBase +
+						       pI830->overlay_regs->offset);
+
+    if (!*pI830->overlayOn)
+	return;
+
+    overlay->OCMD |= OVERLAY_ENABLE;
+    BEGIN_LP_RING(6);
+    OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE);
+    OUT_RING(MI_NOOP);
+    OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_CONTINUE);
+    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();
+    OVERLAY_DEBUG("overlay_continue\n");
+}
 
 static void
 i830_overlay_off(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    if (*pI830->overlayOn) {
-	int spin = 1000000;
-	I830OverlayRegPtr overlay =					
-	  (I830OverlayRegPtr) (pI830->FbBase + pI830->overlay_regs->offset);
-	overlay->OCMD &= ~OVERLAY_ENABLE;
-	BEGIN_LP_RING(6);
-	OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE);
-	OUT_RING(MI_NOOP);
-	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_CONTINUE);
-	if (IS_I965G(pI830))
-	    OUT_RING(pI830->overlay_regs->offset | OFC_UPDATE);
-	else
-	    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();
-	i830WaitSync(pScrn);
-	*pI830->overlayOn = FALSE;
-	OUTREG(OCMD_REGISTER, INREG(OCMD_REGISTER) & ~OVERLAY_ENABLE);
-	OVERLAY_DEBUG("Overlay goes from on to off\n");
-	while (spin != 0 && (INREG(OCMD_REGISTER) & OVERLAY_ENABLE)){
-	    OVERLAY_DEBUG("SPIN %d\n",spin);
-	    spin--;
-	}
-	if (spin == 0)
-	    OVERLAY_DEBUG("OVERLAY FAILED TO GO OFF\n");
-	OVERLAY_DEBUG("OVERLAY_OFF\n");
-    }
+    I830OverlayRegPtr	overlay = (I830OverlayRegPtr) (pI830->FbBase +
+						       pI830->overlay_regs->offset);
+    
+    if (!*pI830->overlayOn)
+	return;
+    
+    overlay->OCMD &= ~OVERLAY_ENABLE;
+    BEGIN_LP_RING(6);
+    OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE);
+    OUT_RING(MI_NOOP);
+    OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_CONTINUE);
+    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();
+    i830WaitSync(pScrn);
+    *pI830->overlayOn = FALSE;
+    OVERLAY_DEBUG("overlay_off\n");
 }
 
-#define OVERLAY_OFF i830_overlay_off(pScrn)
-
 void
 I830InitVideo(ScreenPtr pScreen)
 {
@@ -582,8 +583,6 @@ I830ResetVideo(ScrnInfoPtr pScrn)
    else 
       overlay->OCONFIG |= OVERLAY_PIPE_B;
 
-   overlay->OCMD = YUV_420;
-
 #if 0
    /* 
     * XXX DUMP REGISTER CODE !!!
@@ -925,11 +924,7 @@ I830StopVideo(ScrnInfoPtr pScrn, pointer
 
    if (shutdown) {
       if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
-
-	 I830ResetVideo(pScrn);
-	 OVERLAY_UPDATE;
-	 OVERLAY_OFF;
-
+	 i830_overlay_off(pScrn);
          if (pI830->entityPrivate)
             pI830->entityPrivate->XvInUse = -1;
       }
@@ -967,10 +962,9 @@ I830SetPortAttribute(ScrnInfoPtr pScrn,
 	 return BadValue;
       pPriv->brightness = value;
       overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff);
-      if (*pI830->overlayOn)
-         OVERLAY_UPDATE;
       OVERLAY_DEBUG("BRIGHTNESS\n");
-      OVERLAY_UPDATE;
+      if (*pI830->overlayOn)
+	 i830_overlay_continue (pScrn);
    } else if (attribute == xvContrast) {
       if ((value < 0) || (value > 255))
 	 return BadValue;
@@ -978,14 +972,14 @@ I830SetPortAttribute(ScrnInfoPtr pScrn,
       overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff);
       OVERLAY_DEBUG("CONTRAST\n");
       if (*pI830->overlayOn)
-         OVERLAY_UPDATE;
+	 i830_overlay_continue (pScrn);
    } 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 (*pI830->overlayOn)
+	 i830_overlay_continue (pScrn);
    } else if (attribute == xvPipe) {
       xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
       if ((value < -1) || (value > xf86_config->num_crtc))
@@ -994,6 +988,9 @@ I830SetPortAttribute(ScrnInfoPtr pScrn,
 	 pPriv->desired_crtc = NULL;
       else
 	 pPriv->desired_crtc = xf86_config->crtc[value];
+      /*
+       * Leave this to be updated at the next frame
+       */
    } else if (attribute == xvGamma0 && (IS_I9XX(pI830))) {
       pPriv->gamma0 = value; 
    } else if (attribute == xvGamma1 && (IS_I9XX(pI830))) {
@@ -1021,7 +1018,7 @@ I830SetPortAttribute(ScrnInfoPtr pScrn,
       }
       OVERLAY_DEBUG("COLORKEY\n");
       if (*pI830->overlayOn)
-         OVERLAY_UPDATE;
+	 i830_overlay_continue (pScrn);
       REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
    } else if(attribute == xvDoubleBuffer) {
       if ((value < 0) || (value > 1))
@@ -1706,11 +1703,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
       I830ResetVideo(pScrn);
 
    /* Ensure overlay is turned on with OVERLAY_ENABLE at 0 */
-   if (!*pI830->overlayOn) {
-      OVERLAY_DEBUG("TURNING ON OVERLAY BEFORE UPDATE\n");
-      I830ResetVideo(pScrn);
-      OVERLAY_UPDATE;
-   }
+   i830_overlay_on (pScrn);
 
    /* Fix up the dstBox if outside the visible screen */
    {
@@ -2117,7 +2110,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
 
    OVERLAY_DEBUG("OCMD is 0x%lx\n", overlay->OCMD);
 
-   OVERLAY_UPDATE;
+   i830_overlay_continue (pScrn);
 }
 
 #ifdef I830_USE_EXA
@@ -2641,9 +2634,7 @@ I830BlockHandler(int i,
 	    /* Turn off the overlay */
 	    OVERLAY_DEBUG("BLOCKHANDLER\n");
 
-	    I830ResetVideo(pScrn);
-            OVERLAY_UPDATE;
-            OVERLAY_OFF;
+	    i830_overlay_off (pScrn);
 
 	    pPriv->videoStatus = FREE_TIMER;
 	    pPriv->freeTime = now + FREE_DELAY;
@@ -2745,9 +2736,7 @@ I830StopSurface(XF86SurfacePtr surface)
 
       OVERLAY_DEBUG("StopSurface\n");
 
-      I830ResetVideo(pScrn);
-      OVERLAY_UPDATE;
-      OVERLAY_OFF;
+      i830_overlay_off (pScrn);
 
       if (pI830->entityPrivate)
          pI830->entityPrivate->XvInUse = -1;
@@ -2763,9 +2752,7 @@ I830FreeSurface(XF86SurfacePtr surface)
 {
    OffscreenPrivPtr pPriv = (OffscreenPrivPtr) surface->devPrivate.ptr;
 
-   if (pPriv->isOn) {
-      I830StopSurface(surface);
-   }
+   I830StopSurface(surface);
    I830FreeMemory(surface->pScrn, &pPriv->linear);
    xfree(surface->pitches);
    xfree(surface->offsets);
@@ -2798,8 +2785,6 @@ I830DisplaySurface(XF86SurfacePtr surfac
    ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
    I830Ptr pI830 = I830PTR(pScrn);
    I830PortPrivPtr pI830Priv = GET_PORT_PRIVATE(pScrn);
-   I830OverlayRegPtr overlay =
-	 (I830OverlayRegPtr) (pI830->FbBase + pI830->overlay_regs->offset);
    INT32 x1, y1, x2, y2;
    INT32 loops = 0;
    BoxRec dstBox;
@@ -2842,7 +2827,8 @@ I830DisplaySurface(XF86SurfacePtr surfac
 
    /* Make sure this buffer isn't in use */
    loops = 0;
-   if (*pI830->overlayOn && pI830Priv->doubleBuffer && (overlay->OCMD & OVERLAY_ENABLE)) {
+   if (*pI830->overlayOn && pI830Priv->doubleBuffer) 
+   {
       while (loops < 1000000) {
 #if USE_USLEEP_FOR_VIDEO
          usleep(10);
@@ -2860,10 +2846,7 @@ I830DisplaySurface(XF86SurfacePtr surfac
       }
 
       /* buffer swap */
-      if (pI830Priv->currentBuf == 0)
-         pI830Priv->currentBuf = 1;
-      else
-         pI830Priv->currentBuf = 0;
+      pI830Priv->currentBuf = !pI830Priv->currentBuf;
    }
 
    I830DisplayVideo(pScrn, surface->id, surface->width, surface->height,
diff-tree 08753f9b79f3f09879a18b552d90d88dbf52d4be (from aa187186dc4f2d770a642060fe54f547ea8952b3)
Author: Keith Packard <keithp at dulcimer.keithp.com>
Date:   Wed May 23 18:59:10 2007 -0700

    Use FLIP_CONTINUE with ~OVERLAY_ENABLE to turn overlay off.
    
    This makes the overlay work on i830 with the modesetting driver. I don't
    know why the pre-modesetting driver worked without this, but it did.
    A more 'correct' fix would be welcome, but this does seem to do the trick.

diff --git a/src/i830_video.c b/src/i830_video.c
index 145d25a..852c00f 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -401,10 +401,13 @@ i830_overlay_off(ScrnInfoPtr pScrn)
     I830Ptr pI830 = I830PTR(pScrn);
     if (*pI830->overlayOn) {
 	int spin = 1000000;
+	I830OverlayRegPtr overlay =					
+	  (I830OverlayRegPtr) (pI830->FbBase + pI830->overlay_regs->offset);
+	overlay->OCMD &= ~OVERLAY_ENABLE;
 	BEGIN_LP_RING(6);
 	OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE);
 	OUT_RING(MI_NOOP);
-	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_OFF);
+	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_CONTINUE);
 	if (IS_I965G(pI830))
 	    OUT_RING(pI830->overlay_regs->offset | OFC_UPDATE);
 	else
diff-tree aa187186dc4f2d770a642060fe54f547ea8952b3 (from f5017a06a271bba0ace3c5415b78e78bc0c96f22)
Author: Keith Packard <keithp at dulcimer.keithp.com>
Date:   Mon May 21 10:49:08 2007 -0700

    Automatically select crtc based on coverage.
    
    By default, select crtc based on which one covers more of the video output.
    pipe property can be used to override selection when both have partial
    coverage.

diff --git a/src/i830_video.c b/src/i830_video.c
index 02ddff5..145d25a 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -147,7 +147,7 @@ static Atom xvGamma0, xvGamma1, xvGamma2
 #define IMAGE_MAX_HEIGHT_LEGACY	1088
 
 /* overlay debugging printf function */
-#if 0
+#if 1
 #define OVERLAY_DEBUG ErrorF
 #else
 #define OVERLAY_DEBUG if (0) ErrorF
@@ -159,68 +159,6 @@ 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
- * overlay in OCMD and calling OVERLAY_UPDATE.
- *
- * XXX Need to make sure that the overlay engine is cleanly shutdown in
- * all modes of server exit.
- */
-
-#define OVERLAY_UPDATE						\
-   do { 								\
-      BEGIN_LP_RING(8);							\
-      OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE);                       	\
-      OUT_RING(MI_NOOP);    						\
-      if (!*pI830->overlayOn) {						\
-	 OUT_RING(MI_NOOP);						\
-	 OUT_RING(MI_NOOP);						\
-	 OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_ON);		\
-	 OVERLAY_DEBUG("Overlay goes from off to on\n");		\
-	 *pI830->overlayOn = TRUE;					\
-      } else {								\
-	 OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);	\
-	 OUT_RING(MI_NOOP);						\
-	 OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_CONTINUE);		\
-      }									\
-      if (IS_I965G(pI830)) 						\
-         OUT_RING(pI830->overlay_regs->offset | OFC_UPDATE); 		\
-      else								\
-	 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();						\
-      OVERLAY_DEBUG("OVERLAY_UPDATE\n");				\
-   } while(0)
-
-#define OVERLAY_OFF							\
-   do { 								\
-      if (*pI830->overlayOn) {						\
-	 int spin = 1000000;						\
-	 BEGIN_LP_RING(6);						\
-         OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE);                   	\
-         OUT_RING(MI_NOOP);    						\
-	 OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_OFF);		\
-         if (IS_I965G(pI830)) 						\
-            OUT_RING(pI830->overlay_regs->offset | OFC_UPDATE);		\
-         else								\
-	    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();						\
-	 *pI830->overlayOn = FALSE;					\
-	 OVERLAY_DEBUG("Overlay goes from on to off\n");		\
-         while (spin != 0 && (INREG(OCMD_REGISTER) & OVERLAY_ENABLE)){	\
-		OVERLAY_DEBUG("SPIN %d\n",spin);			\
-		spin--;							\
- 	 }								\
-	 if (spin == 0)							\
-		OVERLAY_DEBUG("OVERLAY FAILED TO GO OFF\n");		\
-	 OVERLAY_DEBUG("OVERLAY_OFF\n");				\
-      }									\
-   } while(0)
-
-/*
  * OCMD - Overlay Command Register
  */
 #define OCMD_REGISTER		0x30168
@@ -417,6 +355,79 @@ CompareOverlay(I830Ptr pI830, CARD32 * o
 }
 #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
+ * overlay in OCMD and calling OVERLAY_UPDATE.
+ *
+ * XXX Need to make sure that the overlay engine is cleanly shutdown in
+ * all modes of server exit.
+ */
+
+static void
+i830_overlay_update(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    BEGIN_LP_RING(8);
+    OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE);
+    OUT_RING(MI_NOOP);
+    if (!*pI830->overlayOn) {
+	OUT_RING(MI_NOOP);
+	OUT_RING(MI_NOOP);
+	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_ON);
+	OVERLAY_DEBUG("Overlay goes from off to on\n");
+	*pI830->overlayOn = TRUE;
+    } else {
+	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
+	OUT_RING(MI_NOOP);
+	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_CONTINUE);
+    }
+    if (IS_I965G(pI830))
+	OUT_RING(pI830->overlay_regs->offset | OFC_UPDATE);
+    else
+	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();
+    OVERLAY_DEBUG("OVERLAY_UPDATE\n");
+}
+
+#define OVERLAY_UPDATE	i830_overlay_update(pScrn)
+
+static void
+i830_overlay_off(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    if (*pI830->overlayOn) {
+	int spin = 1000000;
+	BEGIN_LP_RING(6);
+	OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE);
+	OUT_RING(MI_NOOP);
+	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_OFF);
+	if (IS_I965G(pI830))
+	    OUT_RING(pI830->overlay_regs->offset | OFC_UPDATE);
+	else
+	    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();
+	i830WaitSync(pScrn);
+	*pI830->overlayOn = FALSE;
+	OUTREG(OCMD_REGISTER, INREG(OCMD_REGISTER) & ~OVERLAY_ENABLE);
+	OVERLAY_DEBUG("Overlay goes from on to off\n");
+	while (spin != 0 && (INREG(OCMD_REGISTER) & OVERLAY_ENABLE)){
+	    OVERLAY_DEBUG("SPIN %d\n",spin);
+	    spin--;
+	}
+	if (spin == 0)
+	    OVERLAY_DEBUG("OVERLAY FAILED TO GO OFF\n");
+	OVERLAY_DEBUG("OVERLAY_OFF\n");
+    }
+}
+
+#define OVERLAY_OFF i830_overlay_off(pScrn)
+
 void
 I830InitVideo(ScreenPtr pScreen)
 {
@@ -1557,6 +1568,39 @@ UpdateCoeff(int taps, double fCutoff, Bo
    }
 }
 
+static float
+I830CrtcVideoCoverage (xf86CrtcPtr crtc, BoxPtr video)
+{
+   BoxRec   dest;
+   BoxRec   pipe;
+
+   if (crtc->enabled)
+   {
+      pipe.x1 = crtc->x;
+      pipe.x2 = crtc->x + xf86ModeWidth (&crtc->mode, crtc->rotation);
+      pipe.y1 = crtc->y;
+      pipe.y2 = crtc->y + xf86ModeHeight (&crtc->mode, crtc->rotation);
+   }
+   else
+   {
+      pipe.x1 = pipe.x2 = 0;
+      pipe.y1 = pipe.y2 = 0;
+   }
+   dest.x1 = pipe.x1 > video->x1 ? pipe.x1 : video->x1;
+   dest.x2 = pipe.x2 < video->x2 ? pipe.x2 : video->x2;
+   dest.y1 = pipe.y1 > video->y1 ? pipe.y1 : video->y1;
+   dest.y2 = pipe.y2 < video->y2 ? pipe.y2 : video->y2;
+   if (dest.x1 >= dest.x2 || dest.y1 >= dest.y2)
+   {
+      dest.x1 = dest.x2 = 0;
+      dest.y1 = dest.y2 = 0;
+   }
+   if (video->x1 >= video->x2 || video->y1 >= video->y2)
+      return 0.0;
+   return (((float) (dest.x2 - dest.x1) * (float) (dest.y2 - dest.y1)) /
+	   ((float) (video->x2 - video->x1) * (float) (video->y2 - video->y1)));
+}
+
 static void
 I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height,
 		 int dstPitch, int x1, int y1, int x2, int y2, BoxPtr dstBox,
@@ -1568,6 +1612,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
 	 (I830OverlayRegPtr) (pI830->FbBase + pI830->overlay_regs->offset);
    unsigned int swidth;
    unsigned int mask, shift, offsety, offsetu;
+   xf86CrtcPtr crtc;
    int tmp;
 
    OVERLAY_DEBUG("I830DisplayVideo: %dx%d (pitch %d)\n", width, height,
@@ -1580,39 +1625,71 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
    CompareOverlay(pI830, (CARD32 *) overlay, 0x100);
 #endif
 
-   switch (pI830->rotation) {
+   {
+      float best_coverage = 0.0;
+      float coverage;
+      int c;
+      xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+      
+      crtc = NULL;
+      for (c = 0; c < xf86_config->num_crtc; c++)
+      {
+	 xf86CrtcPtr	this_crtc = xf86_config->crtc[c];
+	 coverage = I830CrtcVideoCoverage (this_crtc, dstBox);
+	 if (coverage)
+	 {
+	    if (this_crtc == pPriv->desired_crtc)
+	    {
+	       crtc = this_crtc;
+	       best_coverage = 1.0;
+	    }
+	    else if (coverage > best_coverage)
+	    {
+	       crtc = this_crtc;
+	       best_coverage = coverage;
+	    }
+	 }
+      }
+      if (crtc != pPriv->current_crtc)
+      {
+	 pPriv->current_crtc = crtc;
+	 I830ResetVideo (pScrn);
+      }
+   }
+
+   switch (crtc->rotation & 0xf) {
 	case RR_Rotate_0:
-		dstBox->x1 -= pScrn->frameX0;
-		dstBox->x2 -= pScrn->frameX0;
-		dstBox->y1 -= pScrn->frameY0;
-		dstBox->y2 -= pScrn->frameY0;
+		dstBox->x1 -= crtc->x;
+		dstBox->x2 -= crtc->x;
+		dstBox->y1 -= crtc->y;
+		dstBox->y2 -= crtc->y;
 		break;
 	case RR_Rotate_90:
 		tmp = dstBox->x1;
-		dstBox->x1 = dstBox->y1 - pScrn->frameX0;
-		dstBox->y1 = pScrn->virtualY - tmp - pScrn->frameY0;
+		dstBox->x1 = dstBox->y1 - crtc->x;
+		dstBox->y1 = pScrn->virtualY - tmp - crtc->y;
 		tmp = dstBox->x2;
-		dstBox->x2 = dstBox->y2 - pScrn->frameX0;
-		dstBox->y2 = pScrn->virtualY - tmp - pScrn->frameY0;
+		dstBox->x2 = dstBox->y2 - crtc->x;
+		dstBox->y2 = pScrn->virtualY - tmp - crtc->y;
 		tmp = dstBox->y1;
 		dstBox->y1 = dstBox->y2;
 		dstBox->y2 = tmp;
 		break;
 	case RR_Rotate_180:
 		tmp = dstBox->x1;
-		dstBox->x1 = pScrn->virtualX - dstBox->x2 - pScrn->frameX0;
-		dstBox->x2 = pScrn->virtualX - tmp - pScrn->frameX0;
+		dstBox->x1 = pScrn->virtualX - dstBox->x2 - crtc->x;
+		dstBox->x2 = pScrn->virtualX - tmp - crtc->x;
 		tmp = dstBox->y1;
-		dstBox->y1 = pScrn->virtualY - dstBox->y2 - pScrn->frameY0;
-		dstBox->y2 = pScrn->virtualY - tmp - pScrn->frameY0;
+		dstBox->y1 = pScrn->virtualY - dstBox->y2 - crtc->y;
+		dstBox->y2 = pScrn->virtualY - tmp - crtc->y;
 		break;
 	case RR_Rotate_270:
 		tmp = dstBox->x1;
-		dstBox->x1 = pScrn->virtualX - dstBox->y1 - pScrn->frameX0;
-		dstBox->y1 = tmp - pScrn->frameY0;
+		dstBox->x1 = pScrn->virtualX - dstBox->y1 - crtc->x;
+		dstBox->y1 = tmp - crtc->y;
 		tmp = dstBox->x2;
-		dstBox->x2 = pScrn->virtualX - dstBox->y2 - pScrn->frameX0;
-		dstBox->y2 = tmp - pScrn->frameY0;
+		dstBox->x2 = pScrn->virtualX - dstBox->y2 - crtc->x;
+		dstBox->y2 = tmp - crtc->y;
 		tmp = dstBox->x1;
 		dstBox->x1 = dstBox->x2;
 		dstBox->x2 = tmp;
@@ -1642,7 +1719,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
       offset_x = (offset_x + 3) & ~3;
       offset_y = (offset_y + 3) & ~3;
 
-      if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
+      if (crtc->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
          height -= offset_x;
          width -= offset_y;
       } else {
@@ -1670,7 +1747,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
       }
    }
 
-   if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
+   if (crtc->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
       tmp = width;
       width = height;
       height = tmp;
@@ -1696,6 +1773,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
        * in case an LFP is in use and it's not at it's native resolution.
        */
       int vactive = I830CrtcPipe (pPriv->current_crtc) ? (INREG(VTOTAL_B) & 0x7FF) : (INREG(VTOTAL_A) & 0x7FF);
+      int hactive = pPriv->current_crtc->mode.HDisplay;
 
       vactive += 1;
 
@@ -1705,16 +1783,16 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
       if (dstBox->x2 < 0) dstBox->x2 = 0;
       if (dstBox->y1 > vactive) dstBox->y1 = vactive;
       if (dstBox->y2 > vactive) dstBox->y2 = vactive;
-      if (dstBox->x1 > pScrn->currentMode->HDisplay) dstBox->x1 = pScrn->currentMode->HDisplay - 1;
-      if (dstBox->x2 > pScrn->currentMode->HDisplay) dstBox->x2 = pScrn->currentMode->HDisplay - 1;
+      if (dstBox->x1 > hactive) dstBox->x1 = hactive;
+      if (dstBox->x2 > hactive) dstBox->x2 = hactive;
 
       /* nothing do to */
       if ((!dstBox->x1 && !dstBox->x2) || (!dstBox->y1 && !dstBox->y2)) {
          OVERLAY_DEBUG("NOTHING TO DO\n");
          return;
       }
-      if ((dstBox->x1 == (pScrn->currentMode->HDisplay - 1) && 
-           dstBox->x2 == (pScrn->currentMode->HDisplay - 1)) || 
+      if ((dstBox->x1 == (hactive) && 
+           dstBox->x2 == (hactive)) || 
           (dstBox->y1 == vactive && 
            dstBox->y2 == vactive)) {
          OVERLAY_DEBUG("NOTHING TO DO\n");
diff-tree f5017a06a271bba0ace3c5415b78e78bc0c96f22 (from 2df87256df755e972eb884bc742832038a020b2c)
Author: Keith Packard <keithp at dulcimer.keithp.com>
Date:   Sun May 20 17:25:33 2007 -0700

    Use CRTCs instead of pipe indices for video pipe selection.
    
    Replace pipe indices with crtc indices and store references to the xf86Crtc
    objects in the video private structure.

diff --git a/src/i830_video.c b/src/i830_video.c
index d2f9724..02ddff5 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -492,6 +492,14 @@ I830InitVideo(ScreenPtr pScreen)
    xfree(adaptors);
 }
 
+static int
+I830CrtcPipe (xf86CrtcPtr crtc)
+{
+   if (crtc == NULL)
+      return 0;
+   return ((I830CrtcPrivatePtr) crtc->driver_private)->pipe;
+}
+
 static void
 I830ResetVideo(ScrnInfoPtr pScrn)
 {
@@ -555,7 +563,7 @@ I830ResetVideo(ScrnInfoPtr pScrn)
     * Select which pipe the overlay is enabled on.
     */
    overlay->OCONFIG &= ~OVERLAY_PIPE_MASK;
-   if (pPriv->pipe == 0)
+   if (I830CrtcPipe (pPriv->current_crtc) == 0)
       overlay->OCONFIG |= OVERLAY_PIPE_A;
    else 
       overlay->OCONFIG |= OVERLAY_PIPE_B;
@@ -731,7 +739,8 @@ I830SetupImageVideoOverlay(ScreenPtr pSc
    pPriv->brightness = 0;
    pPriv->contrast = 64;
    pPriv->saturation = 128;
-   pPriv->pipe = 0;  /* XXX must choose pipe wisely */
+   pPriv->current_crtc = NULL;
+   pPriv->desired_crtc = NULL;
    memset(&pPriv->linear, 0, sizeof(pPriv->linear));
    pPriv->currentBuf = 0;
    pPriv->gamma5 = 0xc0c0c0;
@@ -964,20 +973,13 @@ I830SetPortAttribute(ScrnInfoPtr pScrn,
       overlay->OCMD &= ~OVERLAY_ENABLE;
       OVERLAY_UPDATE;
    } else if (attribute == xvPipe) {
-      if ((value < 0) || (value > 1))
+      xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+      if ((value < -1) || (value > xf86_config->num_crtc))
          return BadValue;
-      pPriv->pipe = value;
-      /*
-       * Select which pipe the overlay is enabled on.
-       */
-      overlay->OCONFIG &= ~OVERLAY_PIPE_MASK;
-      if (pPriv->pipe == 0)
-         overlay->OCONFIG |= OVERLAY_PIPE_A;
-      else 
-         overlay->OCONFIG |= OVERLAY_PIPE_B;
-      OVERLAY_DEBUG("PIPE CHANGE\n");
-      if (*pI830->overlayOn)
-         OVERLAY_UPDATE;
+      if (value < 0)
+	 pPriv->desired_crtc = NULL;
+      else
+	 pPriv->desired_crtc = xf86_config->crtc[value];
    } else if (attribute == xvGamma0 && (IS_I9XX(pI830))) {
       pPriv->gamma0 = value; 
    } else if (attribute == xvGamma1 && (IS_I9XX(pI830))) {
@@ -1044,7 +1046,14 @@ I830GetPortAttribute(ScrnInfoPtr pScrn,
    } else if (attribute == xvSaturation) {
       *value = pPriv->saturation;
    } else if (attribute == xvPipe) {
-      *value = pPriv->pipe;
+      int		c;
+      xf86CrtcConfigPtr	xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+      for (c = 0; c < xf86_config->num_crtc; c++)
+	 if (xf86_config->crtc[c] == pPriv->desired_crtc)
+	    break;
+      if (c == xf86_config->num_crtc)
+	 c = -1;
+      *value = c;
    } else if (attribute == xvGamma0 && (IS_I9XX(pI830))) {
       *value = pPriv->gamma0;
    } else if (attribute == xvGamma1 && (IS_I9XX(pI830))) {
@@ -1686,7 +1695,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
       /* Keep the engine happy and clip to the real vertical size just
        * in case an LFP is in use and it's not at it's native resolution.
        */
-      int vactive = pPriv->pipe ? (INREG(VTOTAL_B) & 0x7FF) : (INREG(VTOTAL_A) & 0x7FF);
+      int vactive = I830CrtcPipe (pPriv->current_crtc) ? (INREG(VTOTAL_B) & 0x7FF) : (INREG(VTOTAL_A) & 0x7FF);
 
       vactive += 1;
 
@@ -2186,7 +2195,7 @@ I830PutImage(ScrnInfoPtr pScrn,
 
    if (pI830->entityPrivate) {
 	 if (pI830->entityPrivate->XvInUse != -1 &&
-	     pI830->entityPrivate->XvInUse != pPriv->pipe) {
+	     pI830->entityPrivate->XvInUse != I830CrtcPipe (pPriv->current_crtc)) {
 #ifdef PANORAMIX
 		if (!noPanoramiXExtension) {
 			return Success; /* faked for trying to share it */
@@ -2197,7 +2206,7 @@ I830PutImage(ScrnInfoPtr pScrn,
 		}
 	 }
 
-      pI830->entityPrivate->XvInUse = pPriv->pipe;
+      pI830->entityPrivate->XvInUse = I830CrtcPipe (pPriv->current_crtc);;
    }
 
    /* overlay limits */
@@ -2718,7 +2727,7 @@ I830DisplaySurface(XF86SurfacePtr surfac
 
    if (pI830->entityPrivate) {
 	 if (pI830->entityPrivate->XvInUse != -1 &&
-	     pI830->entityPrivate->XvInUse != pI830Priv->pipe) {
+	     pI830->entityPrivate->XvInUse != I830CrtcPipe (pI830Priv->current_crtc)) {
 #ifdef PANORAMIX
 		if (!noPanoramiXExtension) {
 			return Success; /* faked for trying to share it */
@@ -2729,7 +2738,7 @@ I830DisplaySurface(XF86SurfacePtr surfac
 		}
 	 }
 
-      pI830->entityPrivate->XvInUse = pI830Priv->pipe;
+      pI830->entityPrivate->XvInUse = I830CrtcPipe (pI830Priv->current_crtc);
    }
 
    x1 = src_x;
@@ -2832,7 +2841,6 @@ 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;
@@ -2846,14 +2854,14 @@ i830_crtc_dpms_video(xf86CrtcPtr crtc, B
 
    pPriv = GET_PORT_PRIVATE(pScrn);
 
-   /* Check if it's the pipe the overlay is on */
-   if (intel_crtc->pipe != pPriv->pipe)
+   /* Check if it's the crtc the overlay is on */
+   if (crtc != pPriv->current_crtc)
       return;
 
    if (on) {
       int size, hsize, vsize, active;
-      int pipeconf_reg = pPriv->pipe == 0 ? PIPEACONF : PIPEBCONF;
-      char pipename = pPriv->pipe == 0 ? 'A' : 'B';
+      int pipeconf_reg = intel_crtc->pipe == 0 ? PIPEACONF : PIPEBCONF;
+      char pipename = intel_crtc->pipe == 0 ? 'A' : 'B';
 
       pPriv->overlayOK = TRUE;
 
@@ -2870,10 +2878,9 @@ 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);
+      if (i830PipeHasType(crtc, I830_OUTPUT_LVDS)) {
+	 int vtotal_reg = intel_crtc->pipe ? VTOTAL_A : VTOTAL_B;
+	 size = intel_crtc->pipe ? INREG(PIPEBSRC) : INREG(PIPEASRC);
 	 hsize = (size >> 16) & 0x7FF;
 	 vsize = size & 0x7FF;
 	 active = INREG(vtotal_reg) & 0x7FF;
diff --git a/src/i830_video.h b/src/i830_video.h
index 854d0b8..7e2d149 100644
--- a/src/i830_video.h
+++ b/src/i830_video.h
@@ -53,7 +53,8 @@ typedef struct {
    int brightness;
    int contrast;
    int saturation;
-   int pipe;
+   xf86CrtcPtr current_crtc;
+   xf86CrtcPtr desired_crtc;
    int doubleBuffer;
 
    RegionRec clip;
diff-tree 2df87256df755e972eb884bc742832038a020b2c (from 9971fac87622c93503540196e1756fded3d4869e)
Author: Keith Packard <keithp at dulcimer.keithp.com>
Date:   Sun May 20 17:23:26 2007 -0700

    Dump pending ring on crash.
    
    When the hardware locks up, dump the pending commands in the ring for
    analysis.

diff --git a/src/i830_debug.c b/src/i830_debug.c
index 73b5d1c..19eb17a 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -649,6 +649,30 @@ void i830DumpRegs (ScrnInfoPtr pScrn)
 }
 
 #ifndef REG_DUMPER
+
+#define NUM_RING_DUMP	64
+
+static void
+i830_dump_ring(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    unsigned int head, tail, ring, mask;
+    volatile unsigned char *virt;
+    
+    head = (INREG (LP_RING + RING_HEAD)) & I830_HEAD_MASK;
+    tail = INREG (LP_RING + RING_TAIL) & I830_TAIL_MASK;
+    mask = pI830->LpRing->tail_mask;
+    
+    virt = pI830->LpRing->virtual_start;
+    ErrorF ("Ring at virtual 0x%x head 0x%x tail 0x%x count %d\n",
+	    (unsigned int) virt, head, tail, (((tail + mask + 1) - head) & mask) >> 2);
+    for (ring = (head - 128) & mask; ring != tail; ring = (ring + 4) & mask)
+    {
+	ErrorF ("\t%08x: %08x\n", ring, *(volatile unsigned int *) (virt + ring));
+    }
+    ErrorF ("Ring end\n");
+}
+
 /* Famous last words
  */
 void
@@ -678,6 +702,7 @@ i830_dump_error_state(ScrnInfoPtr pScrn)
 
     ErrorF("hwstam: %x ier: %x imr: %x iir: %x\n",
 	   INREG16(HWSTAM), INREG16(IER), INREG16(IMR), INREG16(IIR));
+    i830_dump_ring (pScrn);
 }
 
 void
diff-tree 9971fac87622c93503540196e1756fded3d4869e (from 5390a2e2611950d3f48cc735df4a0c37bc5377a5)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Tue May 22 10:46:39 2007 +0200

    i830: Provide new DRI texOffsetStart hook when available with EXA.

diff --git a/src/i830.h b/src/i830.h
index 8dcc4b5..35f8192 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -77,6 +77,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "exa.h"
 Bool I830EXAInit(ScreenPtr pScreen);
 #define EXA_LINEAR_EXTRA	(64*1024)
+unsigned long long I830TexOffsetStart(PixmapPtr pPix);
 #endif
 
 #ifdef I830_USE_XAA
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 9498661..663ef14 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -576,17 +576,26 @@ I830DRIScreenInit(ScreenPtr pScreen)
    pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
 
    {
-#if DRI_SUPPORTS_CLIP_NOTIFY && DRIINFO_MAJOR_VERSION == 5 && \
-    DRIINFO_MINOR_VERSION >= 1
+#if DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1
       int major, minor, patch;
 
       DRIQueryVersion(&major, &minor, &patch);
 
+#if DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 3
+      if (minor >= 3)
+#endif
+#if DRIINFO_MAJOR_VERSION > 5 || \
+    (DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 3)
+	 pDRIInfo->texOffsetStart = I830TexOffsetStart;
+#endif
+
+#if DRI_SUPPORTS_CLIP_NOTIFY && DRIINFO_MAJOR_VERSION == 5
       if (minor >= 1)
 #endif
 #if DRI_SUPPORTS_CLIP_NOTIFY
 	 pDRIInfo->ClipNotify = I830DRIClipNotify;
 #endif
+#endif /* DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1 */
    }
 
    pDRIInfo->TransitionTo2d = I830DRITransitionTo2d;
diff --git a/src/i830_exa.c b/src/i830_exa.c
index ff21fbb..88d1b97 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -541,3 +541,19 @@ I830EXAInit(ScreenPtr pScreen)
 
     return TRUE;
 }
+
+#ifdef XF86DRI
+
+#ifndef ExaOffscreenMarkUsed
+extern void ExaOffscreenMarkUsed(PixmapPtr);
+#endif
+
+unsigned long long
+I830TexOffsetStart(PixmapPtr pPix)
+{
+    exaMoveInPixmap(pPix);
+    ExaOffscreenMarkUsed(pPix);
+
+    return exaGetPixmapOffset(pPix);
+}
+#endif
diff-tree 5390a2e2611950d3f48cc735df4a0c37bc5377a5 (from 4120a20626998272424225261f2cf7960b7ec0ca)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Fri May 18 17:51:36 2007 +0200

    Update vblank pipes when a pipe gets disabled.

diff --git a/src/i830_display.c b/src/i830_display.c
index 9caab85..023a1aa 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -540,6 +540,8 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mod
 	drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScrn->pScreen);
 	Bool enabled = crtc->enabled && mode != DPMSModeOff;
 
+	I830DRISetVBlankInterrupt (pScrn, TRUE);
+
 	if (!sPriv)
 	    return;
 
diff-tree 4120a20626998272424225261f2cf7960b7ec0ca (from 8db28aeaa6e908017b40bd9180f144a2972f6278)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Fri May 18 10:10:34 2007 +0800

    EXA: add render enter helper function
    
    That notify mesa rendering is smashing the state, and check last 3d
    operation to do sync after we're swapped in or others.

diff --git a/src/i830.h b/src/i830.h
index ab52da0..8dcc4b5 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -695,6 +695,8 @@ void
 i830_get_transformed_coordinates(int x, int y, PictTransformPtr transform,
 				 float *x_out, float *y_out);
 
+void i830_enter_render(ScrnInfoPtr);
+
 extern const int I830PatternROP[16];
 extern const int I830CopyROP[16];
 
diff --git a/src/i830_exa.c b/src/i830_exa.c
index 1741732..ff21fbb 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -270,6 +270,22 @@ I830EXADoneCopy(PixmapPtr pDstPixmap)
 #endif
 }
 
+void
+i830_enter_render(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+#ifdef XF86DRI
+    if (pI830->directRenderingEnabled) {
+        drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
+	pSAREAPriv->ctxOwner = DRIGetContext(pScrn->pScreen);
+    }
+#endif
+    if (pI830->last_3d != LAST_3D_RENDER) {
+	i830WaitSync(pScrn);
+	pI830->last_3d = LAST_3D_RENDER;
+    }
+}
+
 #define xFixedToFloat(val) \
 	((float)xFixedToInt(val) + ((float)xFixedFrac(val) / 65536.0))
 
diff --git a/src/i830_render.c b/src/i830_render.c
index 077afa1..957953e 100644
--- a/src/i830_render.c
+++ b/src/i830_render.c
@@ -400,12 +400,12 @@ i830_prepare_composite(int op, PicturePt
     I830Ptr pI830 = I830PTR(pScrn);
     CARD32 dst_format, dst_offset, dst_pitch;
 
+    i830_enter_render(pScrn);
+
     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 (!i830_texture_setup(pSrcPicture, pSrc, 0))
 	I830FALLBACK("fail to setup src texture\n");
     if (pMask != NULL) {
@@ -632,9 +632,5 @@ i830_composite(PixmapPtr pDst, int srcX,
 void
 i830_done_composite(PixmapPtr pDst)
 {
-#if ALWAYS_SYNC
-    ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
-
-    I830Sync(pScrn);
-#endif
+    /* NO-OP */
 }
diff --git a/src/i915_render.c b/src/i915_render.c
index 5b2ed89..d5a8579 100644
--- a/src/i915_render.c
+++ b/src/i915_render.c
@@ -315,11 +315,7 @@ i915_prepare_composite(int op, PicturePt
     CARD32 dst_format, dst_offset, dst_pitch;
     CARD32 blendctl;
 
-#ifdef I830DEBUG
-    ErrorF("Enter i915 prepareComposite\n");
-#endif
-
-    pI830->last_3d = LAST_3D_RENDER;
+    i830_enter_render(pScrn);
 
     i915_get_dest_format(pDstPicture, &dst_format);
     dst_offset = intel_get_pixmap_offset(pDst);
diff --git a/src/i965_render.c b/src/i965_render.c
index bfbb77e..848774e 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -404,15 +404,7 @@ i965_prepare_composite(int op, PicturePt
     CARD32 dst_format, dst_offset, dst_pitch;
     Bool rotation_program = FALSE;
 
-#ifdef XF86DRI
-    if (pI830->directRenderingEnabled) {
-        drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
-
-        pSAREAPriv->ctxOwner = DRIGetContext(pScrn->pScreen);
-    }
-#endif
-
-    pI830->last_3d = LAST_3D_RENDER;
+    i830_enter_render(pScrn);
 
     src_offset = intel_get_pixmap_offset(pSrc);
     src_pitch = intel_get_pixmap_pitch(pSrc);
diff-tree 8db28aeaa6e908017b40bd9180f144a2972f6278 (from 16e50a91dd8b3676e8ce06052c549ab27e6843b7)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Fri May 18 09:54:34 2007 +0800

    Fix ring debug code
    
    Use proper unsigned type for timer variables, and try to dump 965G state.

diff --git a/src/i830_accel.c b/src/i830_accel.c
index 045b3b6..5cbad44 100644
--- a/src/i830_accel.c
+++ b/src/i830_accel.c
@@ -96,10 +96,10 @@ I830WaitLpRing(ScrnInfoPtr pScrn, int n,
    I830Ptr pI830 = I830PTR(pScrn);
    I830RingBuffer *ring = pI830->LpRing;
    int iters = 0;
-   int start = 0;
-   int now = 0;
+   unsigned int start = 0;
+   unsigned int now = 0;
    int last_head = 0;
-   int first = 0;
+   unsigned int first = 0;
 
    /* If your system hasn't moved the head pointer in 2 seconds, I'm going to
     * call it crashed.
@@ -128,9 +128,12 @@ I830WaitLpRing(ScrnInfoPtr pScrn, int n,
 	 start = now;
 	 last_head = ring->head;
       } else if (now - start > timeout_millis) {
-	 ErrorF("Error in I830WaitLpRing(), now is %d, start is %d\n", now,
-		start);
-	 i830_dump_error_state(pScrn);
+	 ErrorF("Error in I830WaitLpRing(), timeout for %d seconds\n",
+		timeout_millis/1000);
+	 if (IS_I965G(pI830))
+	     i965_dump_error_state(pScrn);
+	 else
+	     i830_dump_error_state(pScrn);
 	 ErrorF("space: %d wanted %d\n", ring->space, n);
 #ifdef XF86DRI
 	 if (pI830->directRenderingEnabled) {
@@ -153,7 +156,7 @@ I830WaitLpRing(ScrnInfoPtr pScrn, int n,
    if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) {
       now = GetTimeInMillis();
       if (now - first) {
-	 ErrorF("Elapsed %d ms\n", now - first);
+	 ErrorF("Elapsed %u ms\n", now - first);
 	 ErrorF("space: %d wanted %d\n", ring->space, n);
       }
    }
diff-tree 16e50a91dd8b3676e8ce06052c549ab27e6843b7 (from 12a9fcfe1b25cee850380d8ce11ef11cde9aaacb)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Fri May 18 09:53:36 2007 +0800

    EXA: remove a flush cmd in i915 render code

diff --git a/src/i915_render.c b/src/i915_render.c
index 4d42242..5b2ed89 100644
--- a/src/i915_render.c
+++ b/src/i915_render.c
@@ -375,7 +375,7 @@ i915_prepare_composite(int op, PicturePt
     {
 	CARD32 ss2;
 
-	BEGIN_LP_RING(18);
+	BEGIN_LP_RING(16);
 	/* color buffer
 	 * XXX: Need to add USE_FENCE if we ever tile the X Server's pixmaps or
 	 * visible screen.
@@ -408,10 +408,6 @@ i915_prepare_composite(int op, PicturePt
 	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);
diff-tree 12a9fcfe1b25cee850380d8ce11ef11cde9aaacb (from parents)
Merge: b930bb9d6da8c24dbe0949afb7bb2aa4bcb24687 e89d5f275442915cc7777e75d3fcf7e7ed0f2084
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu May 17 15:11:29 2007 -0700

    Merge branch 'master' of git+ssh://git.freedesktop.org/git/xorg/driver/xf86-video-intel

diff-tree e89d5f275442915cc7777e75d3fcf7e7ed0f2084 (from a441954630c6cdabbf463bfc3404160f97a04b4f)
Author: Keith Packard <keithp at dulcimer.keithp.com>
Date:   Thu May 17 15:00:12 2007 -0700

    Make each output control clones/crtcs. Split DVO into LVDS, TMDS, TV.
    
    Move clone/crtc config into each output where it's easier to understand (no
    need for a switch statement in I830PrepareOutputs. Also, split DVO into
    three sub-types (TMDS, LVDS, TVOUT) as those have different cloning
    abilities.

diff --git a/src/i830.h b/src/i830.h
index 0fe5d41..ab52da0 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -191,15 +191,12 @@ typedef struct {
    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
+#define I830_OUTPUT_DVO_TMDS 2
+#define I830_OUTPUT_DVO_LVDS 3
+#define I830_OUTPUT_DVO_TVOUT 4
+#define I830_OUTPUT_SDVO 5
+#define I830_OUTPUT_LVDS 6
+#define I830_OUTPUT_TVOUT 7
 
 struct _I830DVODriver {
    int type;
@@ -246,6 +243,8 @@ typedef struct _I830OutputPrivateRec {
    I2CBusPtr		    pDDCBus;
    struct _I830DVODriver    *i2c_drv;
    Bool			    load_detect_temp;
+   int                      pipe_mask;
+   int			    clone_mask;
    /** Output-private structure.  Should replace i2c_drv */
    void			    *dev_priv;
 } I830OutputPrivateRec, *I830OutputPrivatePtr;
diff --git a/src/i830_crt.c b/src/i830_crt.c
index 879ae9f..bbb4a83 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -394,6 +394,9 @@ i830_crt_init(ScrnInfoPtr pScrn)
 	return;
     }
     i830_output->type = I830_OUTPUT_ANALOG;
+    i830_output->pipe_mask = ((1 << 0) | (1 << 1));
+    i830_output->clone_mask = ((1 << I830_OUTPUT_ANALOG) |
+			       (1 << I830_OUTPUT_DVO_TMDS));
     
     output->driver_private = i830_output;
     output->interlaceAllowed = FALSE;
diff --git a/src/i830_display.c b/src/i830_display.c
index 4b205ba..9caab85 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -752,7 +752,9 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
 	case I830_OUTPUT_SDVO:
 	    is_sdvo = TRUE;
 	    break;
-	case I830_OUTPUT_DVO:
+	case I830_OUTPUT_DVO_TMDS:
+	case I830_OUTPUT_DVO_LVDS:
+	case I830_OUTPUT_DVO_TVOUT:
 	    is_dvo = TRUE;
 	    break;
 	case I830_OUTPUT_TVOUT:
diff --git a/src/i830_driver.c b/src/i830_driver.c
index b4d9d08..2cbddb0 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -728,44 +728,20 @@ I830SetupOutputs(ScrnInfoPtr pScrn)
    {
       xf86OutputPtr	   output = config->output[o];
       I830OutputPrivatePtr intel_output = output->driver_private;
-      int		   crtc_mask = 0, clone_mask = 0;
+      int		   crtc_mask;
+      int		   c;
       
-      /*
-       * 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));
-	 /*
-	  * 915 cannot do double-wide on pipe B
-	  * 830 cannot put CRT on pipe B
-	  */
-	 if (!IS_I915G(pI830) && !IS_I915GM (pI830) && !IS_I830(pI830))
-	    crtc_mask |= ((1 << 1));
-	 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;
+      crtc_mask = 0;
+      for (c = 0; c < config->num_crtc; c++)
+      {
+	 xf86CrtcPtr	      crtc = config->crtc[c];
+	 I830CrtcPrivatePtr   intel_crtc = crtc->driver_private;
+
+	 if (intel_output->pipe_mask & (1 << intel_crtc->pipe))
+	    crtc_mask |= (1 << c);
       }
       output->possible_crtcs = crtc_mask;
-      output->possible_clones = i830_output_clones (pScrn, clone_mask);
+      output->possible_clones = i830_output_clones (pScrn, intel_output->clone_mask);
    }
 }
 
diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index b69105e..d81e5dd 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -60,22 +60,22 @@ static const char *ch7017_symbols[] = {
 /* driver list */
 struct _I830DVODriver i830_dvo_drivers[] =
 {
-    {I830_DVO_CHIP_TMDS, "sil164", "SIL164VidOutput", DVOC,
+    {I830_OUTPUT_DVO_TMDS, "sil164", "SIL164VidOutput", DVOC,
      (SIL164_ADDR_1<<1), SIL164Symbols, NULL , NULL, NULL},
-    {I830_DVO_CHIP_TMDS | I830_DVO_CHIP_TVOUT, "ch7xxx", "CH7xxxVidOutput", DVOC,
+    {I830_OUTPUT_DVO_TMDS | I830_OUTPUT_DVO_TVOUT, "ch7xxx", "CH7xxxVidOutput", DVOC,
      (CH7xxx_ADDR_1<<1), CH7xxxSymbols, NULL , NULL, NULL},
-    {I830_DVO_CHIP_LVDS, "ivch", "ivch_methods", DVOA,
+    {I830_OUTPUT_DVO_LVDS, "ivch", "ivch_methods", DVOA,
      0x04, ivch_symbols, NULL, NULL, NULL},
     /*
-    {I830_DVO_CHIP_LVDS, "ivch", "ivch_methods",
+    {I830_OUTPUT_DVO_LVDS, "ivch", "ivch_methods",
      0x44, ivch_symbols, NULL, NULL, NULL},
-    {I830_DVO_CHIP_LVDS, "ivch", "ivch_methods",
+    {I830_OUTPUT_DVO_LVDS, "ivch", "ivch_methods",
      0x84, ivch_symbols, NULL, NULL, NULL},
-    {I830_DVO_CHIP_LVDS, "ivch", "ivch_methods",
+    {I830_OUTPUT_DVO_LVDS, "ivch", "ivch_methods",
      0xc4, ivch_symbols, NULL, NULL, NULL},
     */
     /*
-    { I830_DVO_CHIP_LVDS, "ch7017", "ch7017_methods",
+    { I830_OUTPUT_DVO_LVDS, "ch7017", "ch7017_methods",
       0xea, ch7017_symbols, NULL, NULL, NULL }
     */
 };
@@ -351,7 +351,6 @@ i830_dvo_init(ScrnInfoPtr pScrn)
     intel_output = xnfcalloc (sizeof (I830OutputPrivateRec), 1);
     if (!intel_output)
 	return;
-    intel_output->type = I830_OUTPUT_DVO;
 
     /* Set up the DDC bus */
     ret = I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOD, "DVODDC_D");
@@ -374,7 +373,7 @@ i830_dvo_init(ScrnInfoPtr pScrn)
 	ret_ptr = NULL;
 	drv->vid_rec = LoaderSymbol(drv->fntablename);
 
-	if (drv->type & I830_DVO_CHIP_LVDS)
+	if (drv->type == I830_OUTPUT_DVO_LVDS)
 	    gpio = GPIOB;
 	else
 	    gpio = GPIOE;
@@ -396,14 +395,29 @@ i830_dvo_init(ScrnInfoPtr pScrn)
 	    ret_ptr = drv->vid_rec->init(pI2CBus, drv->address);
 
 	if (ret_ptr != NULL) {
-	    xf86OutputPtr output;
+	    xf86OutputPtr output = NULL;
 
-	    if (drv->type & I830_DVO_CHIP_LVDS) {
+	    intel_output->type = drv->type;
+	    switch (drv->type) {
+	    case I830_OUTPUT_DVO_TMDS:
+		intel_output->pipe_mask = ((1 << 0) | (1 << 1));
+		intel_output->clone_mask = ((1 << I830_OUTPUT_ANALOG) |
+					    (1 << I830_OUTPUT_DVO_TMDS));
+		output = xf86OutputCreate(pScrn, &i830_dvo_output_funcs,
+					  "TMDS");
+		break;
+	    case I830_OUTPUT_DVO_LVDS:
+		intel_output->pipe_mask = (1 << 1);
+		intel_output->clone_mask = (1 << I830_OUTPUT_DVO_LVDS);
 		output = xf86OutputCreate(pScrn, &i830_dvo_output_funcs,
 					  "LVDS");
-	    } else {
+		break;
+	    case I830_OUTPUT_DVO_TVOUT:
+		intel_output->pipe_mask = (1 << 1);
+		intel_output->clone_mask = (1 << I830_OUTPUT_DVO_TVOUT);
 		output = xf86OutputCreate(pScrn, &i830_dvo_output_funcs,
-					  "TMDS");
+					  "TV");
+		break;
 	    }
 	    if (output == NULL) {
 		xf86DestroyI2CBusRec(pI2CBus, TRUE, TRUE);
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index e909812..566c868 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -445,6 +445,9 @@ i830_lvds_init(ScrnInfoPtr pScrn)
 	return;
     }
     intel_output->type = I830_OUTPUT_LVDS;
+    intel_output->pipe_mask = (1 << 1);
+    intel_output->clone_mask = (1 << I830_OUTPUT_LVDS);
+    
     output->driver_private = intel_output;
     output->subpixel_order = SubPixelHorizontalRGB;
     output->interlaceAllowed = FALSE;
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 43b55a0..24c9c99 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -1179,6 +1179,8 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
     
     dev_priv = (struct i830_sdvo_priv *) (intel_output + 1);
     intel_output->type = I830_OUTPUT_SDVO;
+    intel_output->pipe_mask = ((1 << 0) | (1 << 1));
+    intel_output->clone_mask = (1 << 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.
diff --git a/src/i830_tv.c b/src/i830_tv.c
index 336214f..b95986f 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -1669,6 +1669,8 @@ i830_tv_init(ScrnInfoPtr pScrn)
     }
     dev_priv = (struct i830_tv_priv *) (intel_output + 1);
     intel_output->type = I830_OUTPUT_TVOUT;
+    intel_output->pipe_mask = ((1 << 0) | (1 << 1));
+    intel_output->clone_mask = (1 << I830_OUTPUT_TVOUT);
     intel_output->dev_priv = dev_priv;
     dev_priv->type = TV_TYPE_UNKNOWN;
 
diff-tree a441954630c6cdabbf463bfc3404160f97a04b4f (from c0daa0a982e7074af4b50653b4a45b0a6352b43d)
Author: Keith Packard <keithp at dulcimer.keithp.com>
Date:   Thu May 17 14:11:49 2007 -0700

    Enable panel fitter on ivch DVO.
    
    Using BIOS source code as a guide, set up the panel fitter on the ivch. This
    involves setting the pipe to the panel fixed mode, the DVO to the source
    size and assigning vertical and horizontal scaling factors in the ivch
    itself.

diff --git a/src/ivch/ivch.c b/src/ivch/ivch.c
index a76e339..e0755c0 100644
--- a/src/ivch/ivch.c
+++ b/src/ivch/ivch.c
@@ -157,8 +157,6 @@ 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;
@@ -191,10 +189,6 @@ ivch_init(I2CBusPtr b, I2CSlaveAddr addr
 	goto out;
     }
 
-    ivch_read (priv, VR01, &temp); xf86DrvMsg (priv->d.pI2CBus->scrnIndex, X_INFO,
-					       "ivch VR01 0x%x\n", temp);
-    ivch_read (priv, VR40, &temp); xf86DrvMsg (priv->d.pI2CBus->scrnIndex, X_INFO,
-					       "ivch VR40 0x%x\n", temp);
     return priv;
 
 out:
@@ -250,7 +244,9 @@ ivch_mode_valid(I2CDevPtr d, DisplayMode
 
     if (panel_fixed_mode)
     {
-	if (!xf86ModesEqual (mode, panel_fixed_mode))
+	if (mode->HDisplay > panel_fixed_mode->HDisplay)
+	    return MODE_PANEL;
+	if (mode->VDisplay > panel_fixed_mode->VDisplay)
 	    return MODE_PANEL;
     }
     
@@ -280,8 +276,6 @@ ivch_dpms(I2CDevPtr d, int mode)
     else
 	vr01 &= ~(VR01_LCD_ENABLE | VR01_DVO_ENABLE);
 
-    vr01 &= ~VR01_PANEL_FIT_ENABLE;
-
     ivch_write(priv, VR01, vr01);
 
     /* Wait for the panel to make its state transition */
@@ -300,6 +294,27 @@ ivch_dpms(I2CDevPtr d, int mode)
 static Bool
 ivch_mode_fixup(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode)
 {
+    struct ivch_priv	*priv = d->DriverPrivate.ptr;
+    DisplayModePtr	panel_fixed_mode = priv->panel_fixed_mode;
+    
+    /* 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 (panel_fixed_mode != NULL) {
+	adjusted_mode->HDisplay = panel_fixed_mode->HDisplay;
+	adjusted_mode->HSyncStart = panel_fixed_mode->HSyncStart;
+	adjusted_mode->HSyncEnd = panel_fixed_mode->HSyncEnd;
+	adjusted_mode->HTotal = panel_fixed_mode->HTotal;
+	adjusted_mode->VDisplay = panel_fixed_mode->VDisplay;
+	adjusted_mode->VSyncStart = panel_fixed_mode->VSyncStart;
+	adjusted_mode->VSyncEnd = panel_fixed_mode->VSyncEnd;
+	adjusted_mode->VTotal = panel_fixed_mode->VTotal;
+	adjusted_mode->Clock = panel_fixed_mode->Clock;
+	xf86SetModeCrtc(adjusted_mode, INTERLACE_HALVE_V);
+    }
+
     return TRUE;
 }
     
@@ -310,22 +325,32 @@ ivch_mode_set(I2CDevPtr d, DisplayModePt
     CARD16		vr40 = 0;
     CARD16		vr01;
 
-    ivch_read (priv, VR01, &vr01);
-    /* Disable panel fitting for now, until we can test. */
-    if (adjusted_mode->HDisplay != priv->width || adjusted_mode->VDisplay != priv->height)
+    vr01 = 0;
+    vr40 = (VR40_STALL_ENABLE |
+	    VR40_VERTICAL_INTERP_ENABLE |
+	    VR40_HORIZONTAL_INTERP_ENABLE);
+    
+    if (mode->HDisplay != adjusted_mode->HDisplay || 
+	mode->VDisplay != adjusted_mode->VDisplay)
     {
+	CARD16	x_ratio, y_ratio;
+	
 	vr01 |= VR01_PANEL_FIT_ENABLE;
-	vr40 |= VR40_AUTO_RATIO_ENABLE;
+	vr40 |= VR40_CLOCK_GATING_ENABLE;
+	x_ratio = (((mode->HDisplay - 1) << 16) / (adjusted_mode->HDisplay - 1)) >> 2;
+	y_ratio = (((mode->VDisplay - 1) << 16) / (adjusted_mode->VDisplay - 1)) >> 2;
+	ivch_write (priv, VR42, x_ratio);
+	ivch_write (priv, VR41, y_ratio);
     }
     else
     {
 	vr01 &= ~VR01_PANEL_FIT_ENABLE;
-	vr40 &= ~VR40_AUTO_RATIO_ENABLE;
+	vr40 &= ~VR40_CLOCK_GATING_ENABLE;
     }
+    vr40 &= ~VR40_AUTO_RATIO_ENABLE;
 
     ivch_write(priv, VR01, vr01);
     ivch_write(priv, VR40, vr40);
-    ivch_dpms(d, DPMSModeOn);
 
     ivch_dump_regs(d);
 }
diff --git a/src/ivch/ivch_reg.h b/src/ivch/ivch_reg.h
index fe5507a..bcd8c56 100644
--- a/src/ivch/ivch_reg.h
+++ b/src/ivch/ivch_reg.h
@@ -46,6 +46,9 @@
  * @{
  */
 #define VR01		0x01
+/**
+ * Enable the panel fitter
+ */
 # define VR01_PANEL_FIT_ENABLE		(1 << 3)
 /**
  * Enables the LCD display.
@@ -185,26 +188,33 @@
  */
 #define VR40		0x40
 # define VR40_STALL_ENABLE		(1 << 13)
-# define VR40_VERTICAL_INTERP_ENABLE	(1 << 11)
+# define VR40_VERTICAL_INTERP_ENABLE	(1 << 12)
+# define VR40_ENHANCED_PANEL_FITTING	(1 << 11)
 # define VR40_HORIZONTAL_INTERP_ENABLE	(1 << 10)
 # define VR40_AUTO_RATIO_ENABLE		(1 << 9)
-# define VR40_PANEL_FIT_ENABLE		(1 << 8)
+# define VR40_CLOCK_GATING_ENABLE	(1 << 8)
 /** @} */
 
 /** @defgroup VR41 Panel Fitting Vertical Ratio
  * @{
+ *
+ * (((image_height - 1) << 16) / ((panel_height - 1))) >> 2
  */
 /** @} */
+#define VR41		0x41
 
 /** @defgroup VR42 Panel Fitting Horizontal Ratio
  * @{
+ * (((image_width - 1) << 16) / ((panel_width - 1))) >> 2
  */
 /** @} */
+#define VR42		0x42
 
 /** @defgroup VR43 Horizontal Image Size
  * @{
  */
 /** @} */
+#define VR43		0x43
 
 /** @defgroup VR44 Panel Fitting Coefficient 0
  * @{
diff-tree c0daa0a982e7074af4b50653b4a45b0a6352b43d (from b28817a87a1608e849e4a9a736dda43533a84b0c)
Author: Keith Packard <keithp at dulcimer.keithp.com>
Date:   Wed May 16 14:02:00 2007 -0700

    Change DVO module interface to pass more state across. Fix IVCH display.
    
    The DVO module interface reflected most of the xf86Output API to the
    underlying functions; finish that work given the changes that have since
    occurred in the xf86Output API.
    
    Move the LVDS-specific code into the IVCH module and make that work on the
    Thinkpad X30 (an i830-based laptop). Panel scaling does not work yet.

diff --git a/src/ch7017/ch7017.c b/src/ch7017/ch7017.c
index 7070c7d..8e3a6ef 100644
--- a/src/ch7017/ch7017.c
+++ b/src/ch7017/ch7017.c
@@ -144,7 +144,7 @@ ch7017_mode_valid(I2CDevPtr d, DisplayMo
 }
 
 static void
-ch7017_mode_set(I2CDevPtr d, DisplayModePtr mode)
+ch7017_mode_set(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode)
 {
     struct ch7017_priv *priv = d->DriverPrivate.ptr;
     CARD8 lvds_pll_feedback_div, lvds_pll_vco_control;
diff --git a/src/ch7xxx/ch7xxx.c b/src/ch7xxx/ch7xxx.c
index 0a96555..09a9627 100644
--- a/src/ch7xxx/ch7xxx.c
+++ b/src/ch7xxx/ch7xxx.c
@@ -206,7 +206,7 @@ ch7xxx_mode_valid(I2CDevPtr d, DisplayMo
 }
 
 static void
-ch7xxx_mode_set(I2CDevPtr d, DisplayModePtr mode)
+ch7xxx_mode_set(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode)
 {
     struct ch7xxx_priv *dev_priv = d->DriverPrivate.ptr;
     CARD8 tvco, tpcp, tpd, tlpf, idf;
diff --git a/src/i2c_vid.h b/src/i2c_vid.h
index 3be394d..1a21fca 100644
--- a/src/i2c_vid.h
+++ b/src/i2c_vid.h
@@ -1,16 +1,142 @@
-/* this needs to go in the server */
+/*
+ * Copyright © 2006 Eric Anholt
+ *
+ * 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 I2C_VID_H
 #define I2C_VID_H
+#include <randrstr.h>
 
 typedef struct _I830I2CVidOutputRec {
+    /**
+     * Initialize the device at startup time.
+     * Returns NULL if the device does not exist.
+     */
     void *(*init)(I2CBusPtr b, I2CSlaveAddr addr);
-    xf86OutputStatus (*detect)(I2CDevPtr d);
-    ModeStatus (*mode_valid)(I2CDevPtr d, DisplayModePtr mode);
-    void (*mode_set)(I2CDevPtr d, DisplayModePtr mode);
+    
+    /**
+     * Setup the device for use, after the relevant output has been created
+     */
+    Bool
+    (*setup) (I2CDevPtr d, xf86OutputPtr output);
+
+    /**
+     * Called to allow the output a chance to create properties after the
+     * RandR objects have been created.
+     */
+    void
+    (*create_resources)(I2CDevPtr d);
+
+    /**
+     * 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)(I2CDevPtr d, int mode);
-    void (*dump_regs)(I2CDevPtr d);
+    
+    /**
+     * Saves the output's state for restoration on VT switch.
+     */
     void (*save)(I2CDevPtr d);
+
+    /**
+     * Restore's the output's state at VT switch.
+     */
     void (*restore)(I2CDevPtr d);
+
+    /**
+     * 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)(I2CDevPtr d, DisplayModePtr mode);
+
+    /**
+     * 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)(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode);
+
+    /**
+     * Callback for preparing mode changes on an output
+     */
+    void (*prepare)(I2CDevPtr d);
+
+    /**
+     * Callback for committing mode changes on an output
+     */
+    void (*commit)(I2CDevPtr d);
+    
+    /**
+     * 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)(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode);
+    
+    /**
+     * Probe for a connected output, and return detect_status.
+     */
+    xf86OutputStatus (*detect)(I2CDevPtr d);
+
+    /**
+     * 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)(I2CDevPtr d);
+    
+#ifdef RANDR_12_INTERFACE
+    /**
+     * Callback when an output's property has changed.
+     */
+    Bool
+    (*set_property)(I2CDevPtr d, Atom property, RRPropertyValuePtr value);
+#endif
+
+    /**
+     * Clean up driver-specific bits of the output
+     */
+    void (*destroy) (I2CDevPtr d);
+
+    /**
+     * Debugging hook to dump device registers to log file
+     */
+    void (*dump_regs)(I2CDevPtr d);
 } I830I2CVidOutputRec, *I830I2CVidOutputPtr;
 
+/* XXX change this name to avoid driver-specific prefix */
+DisplayModePtr
+i830_dvo_get_current_mode (xf86OutputPtr output);
+
 #endif
diff --git a/src/i830.h b/src/i830.h
index c91be79..0fe5d41 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -205,6 +205,7 @@ struct _I830DVODriver {
    int type;
    char *modulename;
    char *fntablename;
+   unsigned int dvo_reg;
    int address;
    const char **symbols;
    I830I2CVidOutputRec *vid_rec;
@@ -466,13 +467,6 @@ typedef struct _I830Rec {
 
    int ddc2;
 
-   /* The BIOS's fixed timings for the LVDS */
-   DisplayModePtr panel_fixed_mode;
-
-   int backlight_duty_cycle;  /* restore backlight to this value */
-   
-   Bool panel_wants_dither;
-
    CARD32 saveDSPACNTR;
    CARD32 saveDSPBCNTR;
    CARD32 savePIPEACONF;
@@ -637,9 +631,6 @@ 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_dvo.c b/src/i830_dvo.c
index 129651c..b69105e 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -60,11 +60,11 @@ static const char *ch7017_symbols[] = {
 /* driver list */
 struct _I830DVODriver i830_dvo_drivers[] =
 {
-    {I830_DVO_CHIP_TMDS, "sil164", "SIL164VidOutput",
+    {I830_DVO_CHIP_TMDS, "sil164", "SIL164VidOutput", DVOC,
      (SIL164_ADDR_1<<1), SIL164Symbols, NULL , NULL, NULL},
-    {I830_DVO_CHIP_TMDS | I830_DVO_CHIP_TVOUT, "ch7xxx", "CH7xxxVidOutput",
+    {I830_DVO_CHIP_TMDS | I830_DVO_CHIP_TVOUT, "ch7xxx", "CH7xxxVidOutput", DVOC,
      (CH7xxx_ADDR_1<<1), CH7xxxSymbols, NULL , NULL, NULL},
-    {I830_DVO_CHIP_LVDS, "ivch", "ivch_methods",
+    {I830_DVO_CHIP_LVDS, "ivch", "ivch_methods", DVOA,
      0x04, ivch_symbols, NULL, NULL, NULL},
     /*
     {I830_DVO_CHIP_LVDS, "ivch", "ivch_methods",
@@ -88,20 +88,18 @@ 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;
-    unsigned int	    dvo_reg;
-
-    if (intel_output->i2c_drv->type & I830_DVO_CHIP_LVDS)
-	dvo_reg = DVOA;
-    else
-	dvo_reg = DVOC;
+    struct _I830DVODriver   *drv = intel_output->i2c_drv;
+    void *		    dev_priv = drv->dev_priv;
+    unsigned int	    dvo_reg = drv->dvo_reg;
 
     if (mode == DPMSModeOn) {
 	OUTREG(dvo_reg, INREG(dvo_reg) | DVO_ENABLE);
+	POSTING_READ(dvo_reg);
 	(*intel_output->i2c_drv->vid_rec->dpms)(dev_priv, mode);
     } else {
 	(*intel_output->i2c_drv->vid_rec->dpms)(dev_priv, mode);
 	OUTREG(dvo_reg, INREG(dvo_reg) & ~DVO_ENABLE);
+	POSTING_READ(dvo_reg);
     }
 }
 
@@ -131,18 +129,18 @@ i830_dvo_restore(xf86OutputPtr output)
     I830OutputPrivatePtr    intel_output = output->driver_private;
     void *		    dev_priv = intel_output->i2c_drv->dev_priv;
 
+    (*intel_output->i2c_drv->vid_rec->restore)(dev_priv);
+
     OUTREG(DVOA, pI830->saveDVOA);
     OUTREG(DVOB, pI830->saveDVOB);
     OUTREG(DVOC, pI830->saveDVOC);
-
-    (*intel_output->i2c_drv->vid_rec->restore)(dev_priv);
 }
 
 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;
+    void		    *dev_priv = intel_output->i2c_drv->dev_priv;
 
     if (pMode->Flags & V_DBLSCAN)
 	return MODE_NO_DBLESCAN;
@@ -156,8 +154,11 @@ static Bool
 i830_dvo_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
 		    DisplayModePtr adjusted_mode)
 {
-    /* XXX: Hook this up to a DVO driver function */
+    I830OutputPrivatePtr    intel_output = output->driver_private;
 
+    if (intel_output->i2c_drv->vid_rec->mode_fixup)
+	return intel_output->i2c_drv->vid_rec->mode_fixup (intel_output->i2c_drv->dev_priv,
+							   mode, adjusted_mode);
     return TRUE;
 }
 
@@ -170,21 +171,26 @@ i830_dvo_mode_set(xf86OutputPtr output, 
     xf86CrtcPtr	    crtc = output->crtc;
     I830CrtcPrivatePtr	    intel_crtc = crtc->driver_private;
     I830OutputPrivatePtr    intel_output = output->driver_private;
+    struct _I830DVODriver   *drv = intel_output->i2c_drv;
     int			    pipe = intel_crtc->pipe;
     CARD32		    dvo;
-    unsigned int	    dvo_reg, dvo_srcdim_reg;
+    unsigned int	    dvo_reg = drv->dvo_reg, dvo_srcdim_reg;
     int			    dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
 
-    if (intel_output->i2c_drv->type & I830_DVO_CHIP_LVDS) {
-	dvo_reg = DVOA;
+    switch (dvo_reg) {
+    case DVOA:
 	dvo_srcdim_reg = DVOA_SRCDIM;
-    } else {
-	dvo_reg = DVOC;
+	break;
+    case DVOB:
+	dvo_srcdim_reg = DVOB_SRCDIM;
+	break;
+    case DVOC:
 	dvo_srcdim_reg = DVOC_SRCDIM;
+	break;
     }
 
     intel_output->i2c_drv->vid_rec->mode_set(intel_output->i2c_drv->dev_priv,
-					     mode);
+					     mode, adjusted_mode);
 
     /* Save the data order, since I don't know what it should be set to. */
     dvo = INREG(dvo_reg) & (DVO_PRESERVE_MASK | DVO_DATA_ORDER_GBRG);
@@ -227,8 +233,6 @@ i830_dvo_detect(xf86OutputPtr output)
 static DisplayModePtr
 i830_dvo_get_modes(xf86OutputPtr output)
 {
-    ScrnInfoPtr		    pScrn = output->scrn;
-    I830Ptr		    pI830 = I830PTR(pScrn);
     I830OutputPrivatePtr    intel_output = output->driver_private;
     DisplayModePtr	    modes;
 
@@ -241,11 +245,11 @@ i830_dvo_get_modes(xf86OutputPtr output)
     if (modes != NULL)
 	return modes;
 
-    if (intel_output->i2c_drv->type & I830_DVO_CHIP_LVDS &&
-	pI830->panel_fixed_mode != NULL)
+    if (intel_output->i2c_drv->vid_rec->get_modes)
     {
-	xf86PrintModeline(pScrn->scrnIndex, pI830->panel_fixed_mode);
-	return xf86DuplicateMode(pI830->panel_fixed_mode);
+	modes = intel_output->i2c_drv->vid_rec->get_modes (intel_output->i2c_drv->dev_priv);
+	if (modes != NULL)
+	    return modes;
     }
 
     return NULL;
@@ -258,11 +262,12 @@ i830_dvo_destroy (xf86OutputPtr output)
 
     if (intel_output)
     {
+	if (intel_output->i2c_drv->vid_rec->destroy)
+	    intel_output->i2c_drv->vid_rec->destroy (intel_output->i2c_drv->dev_priv);
 	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);
     }
 }
@@ -287,35 +292,49 @@ static const xf86OutputFuncsRec i830_dvo
  * Other chips with DVO LVDS will need to extend this to deal with the LVDS
  * chip being on DVOB/C and having multiple pipes.
  */
-static void
-i830_dvo_get_panel_timings(xf86OutputPtr output)
+DisplayModePtr
+i830_dvo_get_current_mode (xf86OutputPtr output)
 {
     ScrnInfoPtr		    pScrn = output->scrn;
+    I830OutputPrivatePtr    intel_output = output->driver_private;
     I830Ptr		    pI830 = I830PTR(pScrn);
-    CARD32 dvoa = INREG(DVOA);
-
-    if (!IS_I830(pI830))
-	return;
+    struct _I830DVODriver   *drv = intel_output->i2c_drv;
+    unsigned int	    dvo_reg = drv->dvo_reg;
+    CARD32		    dvo = INREG(dvo_reg);
+    DisplayModePtr    	    mode = NULL;
 
-    assert(pI830->fixed_panel_mode == NULL);
-
-    /* If the DVOA port is active, that'll be the LVDS, so we can pull out
+    /* If the DVO port is active, that'll be the LVDS, so we can pull out
      * its timings to get how the BIOS set up the panel.
      */
-    if (dvoa & DVO_ENABLE) {
-	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-	int pipe = (dvoa & DVO_PIPE_B_SELECT) ? 1 : 0;
-	xf86CrtcPtr crtc = xf86_config->crtc[pipe];
-
-	pI830->panel_fixed_mode = i830_crtc_mode_get(pScrn, crtc);
-	if (pI830->panel_fixed_mode != NULL)
-	    pI830->panel_fixed_mode->type |= M_T_PREFERRED;
-
-	if (dvoa & DVO_HSYNC_ACTIVE_HIGH)
-	    pI830->panel_fixed_mode->Flags |= V_PHSYNC;
-	if (dvoa & DVO_VSYNC_ACTIVE_HIGH)
-	    pI830->panel_fixed_mode->Flags |= V_PVSYNC;
+    if (dvo & DVO_ENABLE) 
+    {
+	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+	int		    pipe = (dvo & DVO_PIPE_B_SELECT) ? 1 : 0;
+	int		    c;
+
+	for (c = 0; c < xf86_config->num_crtc; c++)
+	{
+	    xf86CrtcPtr		crtc = xf86_config->crtc[c];
+	    I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
+
+	    if (intel_crtc->pipe == pipe)
+	    {
+		mode = i830_crtc_mode_get(pScrn, crtc);
+
+		if (mode)
+		{
+		    mode->type |= M_T_PREFERRED;
+
+		    if (dvo & DVO_HSYNC_ACTIVE_HIGH)
+			mode->Flags |= V_PHSYNC;
+		    if (dvo & DVO_VSYNC_ACTIVE_HIGH)
+			mode->Flags |= V_PVSYNC;
+		}
+		break;
+	    }
+	}
     }
+    return mode;
 }
 
 void
@@ -394,9 +413,6 @@ i830_dvo_init(ScrnInfoPtr pScrn)
 		return;
 	    }
 
-	    if (drv->type & I830_DVO_CHIP_LVDS)
-		i830_dvo_get_panel_timings(output);
-
 	    output->driver_private = intel_output;
 	    output->subpixel_order = SubPixelHorizontalRGB;
 	    output->interlaceAllowed = FALSE;
@@ -405,6 +421,7 @@ i830_dvo_init(ScrnInfoPtr pScrn)
 	    drv->dev_priv = ret_ptr;
 	    intel_output->i2c_drv = drv;
 	    intel_output->pI2CBus = pI2CBus;
+	    drv->vid_rec->setup (drv->dev_priv, output);
 	    return;
 	}
 	xf86UnloadSubModule(drv->modhandle);
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index d16eccb..e909812 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -35,14 +35,27 @@
 #include "i830_display.h"
 #include "X11/Xatom.h"
 
+struct i830_lvds_priv {
+    /* The BIOS's fixed timings for the LVDS */
+    DisplayModePtr panel_fixed_mode;
+    
+    /* The panel needs dithering enabled */
+    Bool	    panel_wants_dither;
+
+    /* restore backlight to this value */
+    int		    backlight_duty_cycle;
+};
+
+
 /**
  * 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)
+i830_lvds_set_backlight(xf86OutputPtr output, int level)
 {
+    ScrnInfoPtr pScrn = output->scrn;
     I830Ptr pI830 = I830PTR(pScrn);
     CARD32 blc_pwm_ctl;
 
@@ -54,9 +67,10 @@ i830_lvds_set_backlight(ScrnInfoPtr pScr
  * Returns the maximum level of the backlight duty cycle field.
  */
 static CARD32
-i830_lvds_get_max_backlight(ScrnInfoPtr pScrn)
+i830_lvds_get_max_backlight(xf86OutputPtr output)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
+    ScrnInfoPtr pScrn = output->scrn;
+    I830Ptr	pI830 = I830PTR(pScrn);
     
     return ((INREG(BLC_PWM_CTL) & BACKLIGHT_MODULATION_FREQ_MASK) >>
 	BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
@@ -66,10 +80,13 @@ i830_lvds_get_max_backlight(ScrnInfoPtr 
  * Sets the power state for the panel.
  */
 static void
-i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on)
+i830SetLVDSPanelPower(xf86OutputPtr output, Bool on)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
-    CARD32 pp_status;
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    struct i830_lvds_priv   *dev_priv = intel_output->dev_priv;
+    ScrnInfoPtr		    pScrn = output->scrn;
+    I830Ptr		    pI830 = I830PTR(pScrn);
+    CARD32		    pp_status;
 
     if (on) {
 	OUTREG(PP_CONTROL, INREG(PP_CONTROL) | POWER_TARGET_ON);
@@ -77,9 +94,9 @@ i830SetLVDSPanelPower(ScrnInfoPtr pScrn,
 	    pp_status = INREG(PP_STATUS);
 	} while ((pp_status & PP_ON) == 0);
 
-	i830_lvds_set_backlight(pScrn, pI830->backlight_duty_cycle);
+	i830_lvds_set_backlight(output, dev_priv->backlight_duty_cycle);
     } else {
-	i830_lvds_set_backlight(pScrn, 0);
+	i830_lvds_set_backlight(output, 0);
 
 	OUTREG(PP_CONTROL, INREG(PP_CONTROL) & ~POWER_TARGET_ON);
 	do {
@@ -91,12 +108,10 @@ i830SetLVDSPanelPower(ScrnInfoPtr pScrn,
 static void
 i830_lvds_dpms (xf86OutputPtr output, int mode)
 {
-    ScrnInfoPtr	pScrn = output->scrn;
-
     if (mode == DPMSModeOn)
-	i830SetLVDSPanelPower(pScrn, TRUE);
+	i830SetLVDSPanelPower(output, TRUE);
     else
-	i830SetLVDSPanelPower(pScrn, FALSE);
+	i830SetLVDSPanelPower(output, FALSE);
 
     /* XXX: We never power down the LVDS pairs. */
 }
@@ -104,22 +119,24 @@ i830_lvds_dpms (xf86OutputPtr output, in
 static void
 i830_lvds_save (xf86OutputPtr output)
 {
-    ScrnInfoPtr	pScrn = output->scrn;
-    I830Ptr	pI830 = I830PTR(pScrn);
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    struct i830_lvds_priv   *dev_priv = intel_output->dev_priv;
+    ScrnInfoPtr		    pScrn = output->scrn;
+    I830Ptr		    pI830 = I830PTR(pScrn);
 
     pI830->savePP_ON = INREG(LVDSPP_ON);
     pI830->savePP_OFF = INREG(LVDSPP_OFF);
     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);
+    dev_priv->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 = i830_lvds_get_max_backlight(pScrn);
+    if (dev_priv->backlight_duty_cycle == 0)
+	dev_priv->backlight_duty_cycle = i830_lvds_get_max_backlight(output);
 }
 
 static void
@@ -134,17 +151,17 @@ i830_lvds_restore(xf86OutputPtr output)
     OUTREG(PP_CYCLE, pI830->savePP_CYCLE);
     OUTREG(PP_CONTROL, pI830->savePP_CONTROL);
     if (pI830->savePP_CONTROL & POWER_TARGET_ON)
-	i830SetLVDSPanelPower(pScrn, TRUE);
+	i830SetLVDSPanelPower(output, TRUE);
     else
-	i830SetLVDSPanelPower(pScrn, FALSE);
+	i830SetLVDSPanelPower(output, FALSE);
 }
 
 static int
 i830_lvds_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
 {
-    ScrnInfoPtr pScrn = output->scrn;
-    I830Ptr pI830 = I830PTR(pScrn);
-    DisplayModePtr  pFixedMode = pI830->panel_fixed_mode;
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    struct i830_lvds_priv   *dev_priv = intel_output->dev_priv;
+    DisplayModePtr	    pFixedMode = dev_priv->panel_fixed_mode;
 
     if (pFixedMode)
     {
@@ -161,10 +178,11 @@ static Bool
 i830_lvds_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
 		     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;
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    struct i830_lvds_priv   *dev_priv = intel_output->dev_priv;
+    ScrnInfoPtr		    pScrn = output->scrn;
+    xf86CrtcConfigPtr	    xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    I830CrtcPrivatePtr	    intel_crtc = output->crtc->driver_private;
     int i;
 
     for (i = 0; i < xf86_config->num_output; i++) {
@@ -189,16 +207,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_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;
+    if (dev_priv->panel_fixed_mode != NULL) {
+	adjusted_mode->HDisplay = dev_priv->panel_fixed_mode->HDisplay;
+	adjusted_mode->HSyncStart = dev_priv->panel_fixed_mode->HSyncStart;
+	adjusted_mode->HSyncEnd = dev_priv->panel_fixed_mode->HSyncEnd;
+	adjusted_mode->HTotal = dev_priv->panel_fixed_mode->HTotal;
+	adjusted_mode->VDisplay = dev_priv->panel_fixed_mode->VDisplay;
+	adjusted_mode->VSyncStart = dev_priv->panel_fixed_mode->VSyncStart;
+	adjusted_mode->VSyncEnd = dev_priv->panel_fixed_mode->VSyncEnd;
+	adjusted_mode->VTotal = dev_priv->panel_fixed_mode->VTotal;
+	adjusted_mode->Clock = dev_priv->panel_fixed_mode->Clock;
 	xf86SetModeCrtc(adjusted_mode, INTERLACE_HALVE_V);
     }
 
@@ -214,10 +232,12 @@ static void
 i830_lvds_mode_set(xf86OutputPtr output, DisplayModePtr mode,
 		   DisplayModePtr adjusted_mode)
 {
-    ScrnInfoPtr pScrn = output->scrn;
-    I830Ptr pI830 = I830PTR(pScrn);
-    I830CrtcPrivatePtr intel_crtc = output->crtc->driver_private;
-    CARD32 pfit_control;
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    struct i830_lvds_priv   *dev_priv = intel_output->dev_priv;
+    ScrnInfoPtr		    pScrn = output->scrn;
+    I830Ptr		    pI830 = I830PTR(pScrn);
+    I830CrtcPrivatePtr	    intel_crtc = output->crtc->driver_private;
+    CARD32		    pfit_control;
 
     /* The LVDS pin pair will already have been turned on in the
      * i830_crtc_mode_set since it has a large impact on the DPLL settings.
@@ -232,7 +252,7 @@ i830_lvds_mode_set(xf86OutputPtr output,
 		    VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR);
 
     if (!IS_I965G(pI830)) {
-	if (pI830->panel_wants_dither)
+	if (dev_priv->panel_wants_dither)
 	    pfit_control |= PANEL_8TO6_DITHER_ENABLE;
     } else {
 	pfit_control |= intel_crtc->pipe << PFIT_PIPE_SHIFT;
@@ -260,8 +280,7 @@ static DisplayModePtr
 i830_lvds_get_modes(xf86OutputPtr output)
 {
     I830OutputPrivatePtr    intel_output = output->driver_private;
-    ScrnInfoPtr		    pScrn = output->scrn;
-    I830Ptr		    pI830 = I830PTR(pScrn);
+    struct i830_lvds_priv   *dev_priv = intel_output->dev_priv;
     xf86MonPtr		    edid_mon;
     DisplayModePtr	    modes;
 
@@ -290,8 +309,8 @@ i830_lvds_get_modes(xf86OutputPtr output
 	}
     }
 
-    if (pI830->panel_fixed_mode != NULL)
-	return xf86DuplicateMode(pI830->panel_fixed_mode);
+    if (dev_priv->panel_fixed_mode != NULL)
+	return xf86DuplicateMode(dev_priv->panel_fixed_mode);
 
     return NULL;
 }
@@ -302,7 +321,12 @@ i830_lvds_destroy (xf86OutputPtr output)
     I830OutputPrivatePtr    intel_output = output->driver_private;
 
     if (intel_output)
+    {
+	struct i830_lvds_priv	*dev_priv = intel_output->dev_priv;
+	
+        xf86DeleteMode (&dev_priv->panel_fixed_mode, dev_priv->panel_fixed_mode);
 	xfree (intel_output);
+    }
 }
 
 #ifdef RANDR_12_INTERFACE
@@ -314,10 +338,11 @@ 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;
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    struct i830_lvds_priv   *dev_priv = intel_output->dev_priv;
+    ScrnInfoPtr		    pScrn = output->scrn;
+    INT32		    range[2];
+    int			    data, err;
 
     /* Set up the backlight property, which takes effect immediately
      * and accepts values only within the range.
@@ -329,7 +354,7 @@ i830_lvds_create_resources(xf86OutputPtr
 	TRUE);
 
     range[0] = 0;
-    range[1] = i830_lvds_get_max_backlight(pScrn);
+    range[1] = i830_lvds_get_max_backlight(output);
     err = RRConfigureOutputProperty(output->randr_output, backlight_atom,
 				    FALSE, TRUE, FALSE, 2, range);
     if (err != 0) {
@@ -337,7 +362,7 @@ i830_lvds_create_resources(xf86OutputPtr
 		   "RRConfigureOutputProperty error, %d\n", err);
     }
     /* Set the current value of the backlight property */
-    data = pI830->backlight_duty_cycle;
+    data = dev_priv->backlight_duty_cycle;
     err = RRChangeOutputProperty(output->randr_output, backlight_atom,
 				 XA_INTEGER, 32, PropModeReplace, 1, &data,
 				 FALSE, TRUE);
@@ -354,8 +379,8 @@ static Bool
 i830_lvds_set_property(xf86OutputPtr output, Atom property,
 		       RRPropertyValuePtr value)
 {
-    ScrnInfoPtr pScrn = output->scrn;
-    I830Ptr pI830 = I830PTR(pScrn);
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    struct i830_lvds_priv   *dev_priv = intel_output->dev_priv;
     
     if (property == backlight_atom) {
 	INT32 val;
@@ -367,13 +392,13 @@ i830_lvds_set_property(xf86OutputPtr out
 	}
 
 	val = *(INT32 *)value->data;
-	if (val < 0 || val > i830_lvds_get_max_backlight(pScrn))
+	if (val < 0 || val > i830_lvds_get_max_backlight(output))
 	    return FALSE;
 
-	if (val != pI830->backlight_duty_cycle)
+	if (val != dev_priv->backlight_duty_cycle)
 	{
-	    i830_lvds_set_backlight(pScrn, val);
-	    pI830->backlight_duty_cycle = val;
+	    i830_lvds_set_backlight(output, val);
+	    dev_priv->backlight_duty_cycle = val;
 	}
 	return TRUE;
     }
@@ -407,11 +432,13 @@ i830_lvds_init(ScrnInfoPtr pScrn)
     xf86OutputPtr	    output;
     I830OutputPrivatePtr    intel_output;
     DisplayModePtr	    modes, scan, bios_mode;
+    struct i830_lvds_priv   *dev_priv;
 
     output = xf86OutputCreate (pScrn, &i830_lvds_output_funcs, "LVDS");
     if (!output)
 	return;
-    intel_output = xnfcalloc (sizeof (I830OutputPrivateRec), 1);
+    intel_output = xnfcalloc (sizeof (I830OutputPrivateRec) + 
+			      sizeof (struct i830_lvds_priv), 1);
     if (!intel_output)
     {
 	xf86OutputDestroy (output);
@@ -423,6 +450,9 @@ i830_lvds_init(ScrnInfoPtr pScrn)
     output->interlaceAllowed = FALSE;
     output->doubleScanAllowed = FALSE;
 
+    dev_priv = (struct i830_lvds_priv *) (intel_output + 1);
+    intel_output->dev_priv = dev_priv;
+
     /* Set up the LVDS DDC channel.  Most panels won't support it, but it can
      * be useful if available.
      */
@@ -444,7 +474,7 @@ i830_lvds_init(ScrnInfoPtr pScrn)
 	    scan->prev = scan->next;
 	if (scan->next != NULL)
 	    scan->next = scan->prev;
-	pI830->panel_fixed_mode = scan;
+	dev_priv->panel_fixed_mode = scan;
     }
     /* Delete the mode list */
     while (modes != NULL)
@@ -453,16 +483,16 @@ i830_lvds_init(ScrnInfoPtr pScrn)
     /* 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) {
+    if (dev_priv->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;
+	    dev_priv->panel_fixed_mode = i830_crtc_mode_get(pScrn, crtc);
+	    if (dev_priv->panel_fixed_mode != NULL)
+		dev_priv->panel_fixed_mode->type |= M_T_PREFERRED;
 	}
     }
 
@@ -470,11 +500,11 @@ i830_lvds_init(ScrnInfoPtr pScrn)
      * the BIOS being unavailable or broken, but lack the configuration options
      * for now.
      */
-    bios_mode = i830_bios_get_panel_mode(pScrn);
+    bios_mode = i830_bios_get_panel_mode(pScrn, &dev_priv->panel_wants_dither);
     if (bios_mode != NULL) {
-	if (pI830->panel_fixed_mode != NULL) {
+	if (dev_priv->panel_fixed_mode != NULL) {
 	    if (pI830->debug_modes &&
-		!xf86ModesEqual(pI830->panel_fixed_mode, bios_mode))
+		!xf86ModesEqual(dev_priv->panel_fixed_mode, bios_mode))
 	    {
 		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 			   "BIOS panel mode data doesn't match probed data, "
@@ -482,12 +512,12 @@ i830_lvds_init(ScrnInfoPtr pScrn)
 		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);
+		xf86PrintModeline(pScrn->scrnIndex, dev_priv->panel_fixed_mode);
 		xfree(bios_mode->name);
 		xfree(bios_mode);
 	    }
 	}  else {
-	    pI830->panel_fixed_mode = bios_mode;
+	    dev_priv->panel_fixed_mode = bios_mode;
 	}
     } else {
 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
@@ -513,9 +543,9 @@ i830_lvds_init(ScrnInfoPtr pScrn)
 	     * display.
 	     */
 
-	    if (pI830->panel_fixed_mode != NULL &&
-		pI830->panel_fixed_mode->HDisplay == 800 &&
-		pI830->panel_fixed_mode->VDisplay == 600)
+	    if (dev_priv->panel_fixed_mode != NULL &&
+		dev_priv->panel_fixed_mode->HDisplay == 800 &&
+		dev_priv->panel_fixed_mode->VDisplay == 600)
 	    {
 		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 			   "Suspected Mac Mini, ignoring the LVDS\n");
diff --git a/src/ivch/ivch.c b/src/ivch/ivch.c
index efc74f8..a76e339 100644
--- a/src/ivch/ivch.c
+++ b/src/ivch/ivch.c
@@ -38,17 +38,42 @@
 #include "xf86Crtc.h"
 #define DPMS_SERVER
 #include <X11/extensions/dpms.h>
+#include <unistd.h>
 
 #include "../i2c_vid.h"
+#include "../i830_bios.h"
 #include "ivch_reg.h"
 
 struct ivch_priv {
-    I2CDevRec d;
+    I2CDevRec	    d;
 
-    CARD16 save_VR01;
-    CARD16 save_VR40;
+    xf86OutputPtr   output;
+
+    DisplayModePtr  panel_fixed_mode;
+    Bool	    panel_wants_dither;
+
+    CARD16    	    width;
+    CARD16    	    height;
+
+    CARD16	    save_VR01;
+    CARD16	    save_VR40;
 };
 
+struct vch_capabilities {
+    struct aimdb_block	aimdb_block;
+    CARD8		panel_type;
+    CARD8		set_panel_type;
+    CARD8		slave_address;
+    CARD8		capabilities;
+#define VCH_PANEL_FITTING_SUPPORT	(0x3 << 0)
+#define VCH_PANEL_FITTING_TEXT		(1 << 2)
+#define VCH_PANEL_FITTING_GRAPHICS	(1 << 3)
+#define VCH_PANEL_FITTING_RATIO		(1 << 4)
+#define VCH_DITHERING			(1 << 5)
+    CARD8		backlight_gpio;
+    CARD8		set_panel_type_us_gpios;
+} __attribute__ ((packed));
+
 static void
 ivch_dump_regs(I2CDevPtr d);
 
@@ -129,8 +154,8 @@ ivch_write(struct ivch_priv *priv, int a
 static void *
 ivch_init(I2CBusPtr b, I2CSlaveAddr addr)
 {
-    struct ivch_priv *priv;
-    CARD16 temp;
+    struct	ivch_priv *priv;
+    CARD16	temp;
 
     xf86DrvMsg(b->scrnIndex, X_INFO, "detecting ivch\n");
 
@@ -138,6 +163,7 @@ ivch_init(I2CBusPtr b, I2CSlaveAddr addr
     if (priv == NULL)
 	return NULL;
 
+    priv->output = NULL;
     priv->d.DevName = "i82807aa \"ivch\" LVDS/CMOS panel controller";
     priv->d.SlaveAddr = addr;
     priv->d.pI2CBus = b;
@@ -165,6 +191,10 @@ ivch_init(I2CBusPtr b, I2CSlaveAddr addr
 	goto out;
     }
 
+    ivch_read (priv, VR01, &temp); xf86DrvMsg (priv->d.pI2CBus->scrnIndex, X_INFO,
+					       "ivch VR01 0x%x\n", temp);
+    ivch_read (priv, VR40, &temp); xf86DrvMsg (priv->d.pI2CBus->scrnIndex, X_INFO,
+					       "ivch VR40 0x%x\n", temp);
     return priv;
 
 out:
@@ -172,18 +202,58 @@ out:
     return NULL;
 }
 
+/** Gets the panel mode */
+static Bool
+ivch_setup (I2CDevPtr d, xf86OutputPtr output)
+{
+    struct ivch_priv	*priv = d->DriverPrivate.ptr;
+
+    priv->output = output;
+    ivch_read (priv, VR20, &priv->width);
+    ivch_read (priv, VR21, &priv->height);
+    
+    priv->panel_fixed_mode = i830_bios_get_panel_mode (output->scrn, &priv->panel_wants_dither);
+    if (!priv->panel_fixed_mode)
+    {
+	priv->panel_fixed_mode = i830_dvo_get_current_mode (output);
+	priv->panel_wants_dither = TRUE;
+    }
+
+    return TRUE;
+}
+
 static xf86OutputStatus
 ivch_detect(I2CDevPtr d)
 {
     return XF86OutputStatusUnknown;
 }
 
+static DisplayModePtr
+ivch_get_modes (I2CDevPtr d)
+{
+    struct ivch_priv	*priv = d->DriverPrivate.ptr;
+
+    if (priv->panel_fixed_mode)
+	return xf86DuplicateMode (priv->panel_fixed_mode);
+
+    return NULL;
+}
+
 static ModeStatus
 ivch_mode_valid(I2CDevPtr d, DisplayModePtr mode)
 {
+    struct ivch_priv	*priv = d->DriverPrivate.ptr;
+    DisplayModePtr	panel_fixed_mode = priv->panel_fixed_mode;
+    
     if (mode->Clock > 112000)
 	return MODE_CLOCK_HIGH;
 
+    if (panel_fixed_mode)
+    {
+	if (!xf86ModesEqual (mode, panel_fixed_mode))
+	    return MODE_PANEL;
+    }
+    
     return MODE_OK;
 }
 
@@ -193,37 +263,68 @@ ivch_dpms(I2CDevPtr d, int mode)
 {
     struct ivch_priv *priv = d->DriverPrivate.ptr;
     int i;
-    CARD16 temp;
+    CARD16 vr01, vr30, backlight;
 
     /* Set the new power state of the panel. */
-    if (!ivch_read(priv, VR01, &temp))
+    if (!ivch_read(priv, VR01, &vr01))
 	return;
 
     if (mode == DPMSModeOn)
-	temp |= VR01_LCD_ENABLE | VR01_DVO_ENABLE;
+	backlight = 1;
     else
-	temp &= ~(VR01_LCD_ENABLE | VR01_DVO_ENABLE);
+	backlight = 0;
+    ivch_write(priv, VR80, backlight);
+    
+    if (mode == DPMSModeOn)
+	vr01 |= VR01_LCD_ENABLE | VR01_DVO_ENABLE;
+    else
+	vr01 &= ~(VR01_LCD_ENABLE | VR01_DVO_ENABLE);
+
+    vr01 &= ~VR01_PANEL_FIT_ENABLE;
 
-    ivch_write(priv, VR01, temp);
+    ivch_write(priv, VR01, vr01);
 
     /* Wait for the panel to make its state transition */
-    for (i = 0; i < 1000; i++) {
-	if (!ivch_read(priv, VR30, &temp))
+    for (i = 0; i < 100; i++) {
+	if (!ivch_read(priv, VR30, &vr30))
 	    break;
 
-	if (((temp & VR30_PANEL_ON) != 0) == (mode == DPMSModeOn))
+	if (((vr30 & VR30_PANEL_ON) != 0) == (mode == DPMSModeOn))
 	    break;
+	usleep (1000);
     }
+    /* And wait some more; without this, the vch fails to resync sometimes */
+    usleep (16 * 1000);
 }
 
+static Bool
+ivch_mode_fixup(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode)
+{
+    return TRUE;
+}
+    
 static void
-ivch_mode_set(I2CDevPtr d, DisplayModePtr mode)
+ivch_mode_set(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode)
 {
-    struct ivch_priv *priv = d->DriverPrivate.ptr;
+    struct ivch_priv	*priv = d->DriverPrivate.ptr;
+    CARD16		vr40 = 0;
+    CARD16		vr01;
 
+    ivch_read (priv, VR01, &vr01);
     /* Disable panel fitting for now, until we can test. */
-    ivch_write(priv, VR40, 0);
+    if (adjusted_mode->HDisplay != priv->width || adjusted_mode->VDisplay != priv->height)
+    {
+	vr01 |= VR01_PANEL_FIT_ENABLE;
+	vr40 |= VR40_AUTO_RATIO_ENABLE;
+    }
+    else
+    {
+	vr01 &= ~VR01_PANEL_FIT_ENABLE;
+	vr40 &= ~VR40_AUTO_RATIO_ENABLE;
+    }
 
+    ivch_write(priv, VR01, vr01);
+    ivch_write(priv, VR40, vr40);
     ivch_dpms(d, DPMSModeOn);
 
     ivch_dump_regs(d);
@@ -244,6 +345,33 @@ ivch_dump_regs(I2CDevPtr d)
     ivch_read(priv, VR40, &val);
     xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR40: 0x%04x\n", val);
 
+    /* GPIO registers */
+    ivch_read(priv, VR80, &val);
+    xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR80: 0x%04x\n", val);
+    ivch_read(priv, VR81, &val);
+    xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR81: 0x%04x\n", val);
+    ivch_read(priv, VR82, &val);
+    xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR82: 0x%04x\n", val);
+    ivch_read(priv, VR83, &val);
+    xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR83: 0x%04x\n", val);
+    ivch_read(priv, VR84, &val);
+    xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR84: 0x%04x\n", val);
+    ivch_read(priv, VR85, &val);
+    xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR85: 0x%04x\n", val);
+    ivch_read(priv, VR86, &val);
+    xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR86: 0x%04x\n", val);
+    ivch_read(priv, VR87, &val);
+    xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR87: 0x%04x\n", val);
+    ivch_read(priv, VR88, &val);
+    xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR88: 0x%04x\n", val);
+
+    /* Scratch register 0 - AIM Panel type */
+    ivch_read(priv, VR8E, &val);
+    xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR8E: 0x%04x\n", val);
+
+    /* Scratch register 1 - Status register */
+    ivch_read(priv, VR8F, &val);
+    xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR8F: 0x%04x\n", val);
 }
 
 static void
@@ -267,11 +395,14 @@ ivch_restore(I2CDevPtr d)
 
 I830I2CVidOutputRec ivch_methods = {
     .init = ivch_init,
-    .detect = ivch_detect,
-    .mode_valid = ivch_mode_valid,
-    .mode_set = ivch_mode_set,
+    .setup = ivch_setup,
     .dpms = ivch_dpms,
-    .dump_regs = ivch_dump_regs,
     .save = ivch_save,
     .restore = ivch_restore,
+    .mode_valid = ivch_mode_valid,
+    .mode_fixup = ivch_mode_fixup,
+    .mode_set = ivch_mode_set,
+    .detect = ivch_detect,
+    .get_modes = ivch_get_modes,
+    .dump_regs = ivch_dump_regs,
 };
diff --git a/src/ivch/ivch_reg.h b/src/ivch/ivch_reg.h
index 112c97d..fe5507a 100644
--- a/src/ivch/ivch_reg.h
+++ b/src/ivch/ivch_reg.h
@@ -35,14 +35,14 @@
 #ifndef I82807AA_REG_H
 #define I82807AA_REG_H
 
-/** @defgroup VR00
+/** @defgroup VR00 VCH Revision & GMBus Base Addr
  * @{
  */
 #define VR00		0x00
 # define VR00_BASE_ADDRESS_MASK		0x007f
 /** @} */
 
-/** @defgroup VR01
+/** @defgroup VR01 VCH Functionality Enable
  * @{
  */
 #define VR01		0x01
@@ -59,7 +59,7 @@
 # define VR01_DVO_ENABLE		(1 << 0)
 /** @} */
 
-/** @defgroup VR10
+/** @defgroup VR10 LCD Interface Format
  * @{
  */
 #define VR10		0x10
@@ -75,7 +75,79 @@
 # define VR10_INTERFACE_2X24		(3 << 2)
 /** @} */
 
-/** @defgroup VR30
+/** @defgroup VR11 CMOS Output Control
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR12 LVDS Output Control
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR18 PLL clock select
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR19 PLL clock divisor M
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR1A PLL clock divisor N
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR1F FIFO Pre-load
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR20 LCD Horizontal Display Size
+ * @{
+ */
+#define VR20	0x20
+/** @} */
+
+/** @defgroup VR21 LCD Vertical Display Size
+ * @{
+ */
+#define VR21	0x20
+/** @} */
+
+/** @defgroup VR22 Horizontal TRP to DE Start Delay
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR23 Horizontal TRP to DE End Delay
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR24 Horizontal TRP To LP Start Delay
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR25 Horizontal TRP To LP End Delay
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR26 Vertical TRP To FLM Start Delay
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR27 Vertical TRP To FLM End Delay
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR30 Panel power down status
  * @{
  */
 #define VR30		0x30
@@ -83,6 +155,31 @@
 # define VR30_PANEL_ON			(1 << 15)
 /** @} */
 
+/** @defgroup VR31 Tpon Panel power on sequencing delay
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR32 Tpon Panel power off sequencing delay
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR33 Tstay Panel power off stay down delay
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR34 Maximal FLM Pulse Interval
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR35 Maximal LP Pulse Interval
+ * @{
+ */
+/** @} */
+
 /** @defgroup VR40
  * @{
  */
@@ -90,8 +187,95 @@
 # 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_AUTO_RATIO_ENABLE		(1 << 9)
 # define VR40_PANEL_FIT_ENABLE		(1 << 8)
 /** @} */
 
+/** @defgroup VR41 Panel Fitting Vertical Ratio
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR42 Panel Fitting Horizontal Ratio
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR43 Horizontal Image Size
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR44 Panel Fitting Coefficient 0
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR45 Panel Fitting Coefficient 1
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR46 Panel Fitting Coefficient 2
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR47 Panel Fitting Coefficient 3
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR48 Panel Fitting Coefficient 4
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR49 Panel Fitting Coefficient 5
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR80 GPIO 0
+ * @{
+ */
+/** @} */
+
+#define VR80	    0x80
+#define VR81	    0x81
+#define VR82	    0x82
+#define VR83	    0x83
+#define VR84	    0x84
+#define VR85	    0x85
+#define VR86	    0x86
+#define VR87	    0x87
+    
+/** @defgroup VR88 GPIO 8
+ * @{
+ */
+/** @} */
+
+#define VR88	    0x88
+
+/** @defgroup VR8E Graphics BIOS scratch 0
+ * @{
+ */
+#define VR8E	    0x8E
+# define VR8E_PANEL_TYPE_MASK		(0xf << 0)
+# define VR8E_PANEL_INTERFACE_CMOS	(0 << 4)
+# define VR8E_PANEL_INTERFACE_LVDS	(1 << 4)
+# define VR8E_FORCE_DEFAULT_PANEL	(1 << 5)
+/** @} */
+
+/** @defgroup VR8F Graphics BIOS scratch 1
+ * @{
+ */
+#define VR8F	    0x8F
+# define VR8F_VCH_PRESENT		(1 << 0)
+# define VR8F_DISPLAY_CONN		(1 << 1)
+# define VR8F_POWER_MASK		(0x3c)
+# define VR8F_POWER_POS			(2)
+/** @} */
+
+
 #endif /* I82807AA_REG_H */
diff --git a/src/sil164/sil164.c b/src/sil164/sil164.c
index 80b1b6a..60a03e2 100644
--- a/src/sil164/sil164.c
+++ b/src/sil164/sil164.c
@@ -144,7 +144,7 @@ sil164_mode_valid(I2CDevPtr d, DisplayMo
 }
 
 static void
-sil164_mode_set(I2CDevPtr d, DisplayModePtr mode)
+sil164_mode_set(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode)
 {
     /* 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
diff-tree b28817a87a1608e849e4a9a736dda43533a84b0c (from b31bef1a8effa9acb6de7edd206b9d8c48d88144)
Author: Keith Packard <keithp at dulcimer.keithp.com>
Date:   Wed May 16 13:59:36 2007 -0700

    Add i830_bios_get_aim_data_block to read AIM data from BIOS
    
    Add-in modules have per-module data in the BIOS which contains configuration
    information which cannot be entirely discovered.

diff --git a/src/bios_reader/bios_reader.c b/src/bios_reader/bios_reader.c
index a52bcc7..9ec73c1 100644
--- a/src/bios_reader/bios_reader.c
+++ b/src/bios_reader/bios_reader.c
@@ -30,16 +30,11 @@
 #include <string.h>
 #include <sys/types.h>
 
+#include "../i830_bios.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 {
diff --git a/src/i830_bios.c b/src/i830_bios.c
index 0d00917..7703c80 100644
--- a/src/i830_bios.c
+++ b/src/i830_bios.c
@@ -77,8 +77,8 @@ i830DumpBIOSToFile(ScrnInfoPtr pScrn, un
  * feed an updated VBT back through that, compared to what we'll fetch using
  * this method of groping around in the BIOS data.
  */
-static unsigned char *
-i830GetBIOS(ScrnInfoPtr pScrn)
+unsigned char *
+i830_bios_get (ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     struct vbt_header *vbt;
@@ -131,7 +131,7 @@ i830GetBIOS(ScrnInfoPtr pScrn)
  * detecting the panel mode is preferable.
  */
 DisplayModePtr
-i830_bios_get_panel_mode(ScrnInfoPtr pScrn)
+i830_bios_get_panel_mode(ScrnInfoPtr pScrn, Bool *wants_dither)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     struct vbt_header *vbt;
@@ -140,7 +140,7 @@ i830_bios_get_panel_mode(ScrnInfoPtr pSc
     int panel_type = -1;
     unsigned char *bios;
 
-    bios = i830GetBIOS(pScrn);
+    bios = i830_bios_get (pScrn);
 
     if (bios == NULL)
 	return NULL;
@@ -156,6 +156,7 @@ i830_bios_get_panel_mode(ScrnInfoPtr pSc
 	return NULL;
     }
 
+    *wants_dither = FALSE;
     for (bdb_block_off = bdb->header_size; bdb_block_off < bdb->bdb_size;
 	 bdb_block_off += block_size)
     {
@@ -175,7 +176,7 @@ i830_bios_get_panel_mode(ScrnInfoPtr pSc
 	    lvds1 = (struct lvds_bdb_1 *)(bios + start);
 	    panel_type = lvds1->panel_type;
 	    if (lvds1->caps & LVDS_CAP_DITHER)
-		pI830->panel_wants_dither = TRUE;
+		*wants_dither = TRUE;
 	    break;
 	case 41:
 	    if (panel_type == -1)
@@ -243,3 +244,51 @@ i830_bios_get_panel_mode(ScrnInfoPtr pSc
     xfree(bios);
     return NULL;
 }
+
+unsigned char *
+i830_bios_get_aim_data_block (ScrnInfoPtr pScrn, int aim, int data_block)
+{
+    unsigned char   *bios;
+    int		    bdb_off;
+    int		    vbt_off;
+    int		    aim_off;
+    struct vbt_header *vbt;
+    struct aimdb_header *aimdb;
+    struct aimdb_block *aimdb_block;
+
+    bios = i830_bios_get (pScrn);
+    if (!bios)
+	return NULL;
+
+    vbt_off = INTEL_BIOS_16(0x1a);
+    vbt = (struct vbt_header *)(bios + vbt_off);
+
+    aim_off = vbt->aim_offset[aim];
+    if (!aim_off)
+    {
+	free (bios);
+	return NULL;
+    }
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "aim_off %d\n", aim_off);
+    aimdb = (struct aimdb_header *) (bios + vbt_off + aim_off);
+    bdb_off = aimdb->aimdb_header_size;
+    while (bdb_off < aimdb->aimdb_size)
+    {
+	aimdb_block = (struct aimdb_block *) (bios + vbt_off + aim_off + bdb_off);
+	if (aimdb_block->aimdb_id == data_block)
+	{
+	    unsigned char   *aim = malloc (aimdb_block->aimdb_size + sizeof (struct aimdb_block));
+	    if (!aim)
+	    {
+		free (bios);
+		return NULL;
+	    }
+	    memcpy (aim, aimdb_block, aimdb_block->aimdb_size + sizeof (struct aimdb_block));
+	    free (bios);
+	    return aim;
+	}
+	bdb_off += aimdb_block->aimdb_size + sizeof (struct aimdb_block);
+    }
+    free (bios);
+    return NULL;
+}
diff --git a/src/i830_bios.h b/src/i830_bios.h
index 881d5c8..cb7666e 100644
--- a/src/i830_bios.h
+++ b/src/i830_bios.h
@@ -25,6 +25,11 @@
  *
  */
 
+#ifndef _I830_BIOS_H_
+#define _I830_BIOS_H_
+
+#include <xf86str.h>
+
 struct vbt_header {
     char signature[20];			/**< Always starts with 'VBT$' */
     CARD16 version;			/**< decimal */
@@ -33,10 +38,7 @@ struct vbt_header {
     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 */
+    CARD32 aim_offset[4];		/**< from beginning of VBT */
 } __attribute__((packed));
 
 struct bdb_header {
@@ -114,3 +116,45 @@ struct lvds_bdb_2 {
     CARD8 table_size;	/* not sure on this one */
     struct lvds_bdb_2_entry panels[16];
 } __attribute__((packed));
+
+struct aimdb_header {
+    char    signature[16];
+    char    oem_device[20];
+    CARD16  aimdb_version;
+    CARD16  aimdb_header_size;
+    CARD16  aimdb_size;
+} __attribute__((packed));
+
+struct aimdb_block {
+    CARD8   aimdb_id;
+    CARD16  aimdb_size;
+} __attribute__((packed));
+
+struct vch_bdb_20 {
+} __attribute__((packed));
+
+struct vch_panel_data {
+    CARD16	fp_timing_offset;
+    CARD8	fp_timing_size;
+    CARD16	dvo_timing_offset;
+    CARD8	dvo_timing_size;
+    CARD16	text_fitting_offset;
+    CARD8	text_fitting_size;
+    CARD16	graphics_fitting_offset;
+    CARD8	graphics_fitting_size;
+} __attribute__((packed));
+
+struct vch_bdb_22 {
+    struct aimdb_block	    aimdb_block;
+    struct vch_panel_data   panels[16];
+} __attribute__((packed));
+
+unsigned char *
+i830_bios_get (ScrnInfoPtr pScrn);
+
+DisplayModePtr i830_bios_get_panel_mode(ScrnInfoPtr pScrn, Bool *wants_dither);
+
+unsigned char *
+i830_bios_get_aim_data_block (ScrnInfoPtr pScrn, int aim, int data_block);
+
+#endif /* _I830_BIOS_H_ */
diff-tree b31bef1a8effa9acb6de7edd206b9d8c48d88144 (from 3b769af53e0ef6ef9b56afd679446c73a0e63ea5)
Author: Keith Packard <keithp at work.jf.intel.com>
Date:   Sat May 12 20:04:31 2007 -0700

    Deal with i830 CRT load detection which cannot use FORCE_BORDER.
    
    Chips newer than the i830 can force the border color for the active period
    of the screen, allowing the load detection to easily see the right data. In
    addition, newer chips appear to have more sensible load detection hardware
    which either ignores inactive periods on the screen or performs some
    longer-term averaging. The i830 appears to provide unfiltered samples of the
    detected load.
    
    For the i830, then, emit a border at the bottom of the screen and, for load
    detection, simply turn it purple and wait for the current line to be within
    the border. Sample an entire scanline, counting the number of times the load
    detection sees a monitor. In my testing, the presence of a monitor will
    cause the detection to succeed every time, while the absense will cause it
    to fail about 75% of the time. The code here, checks for presence at least
    75% of the time, which should be adequate.
    
    Also, as the new mode configuration code has already taken care to enable
    the CRT output, eliminate much of the load detection code which is simply
    duplicating functionality from the general mode setting code. This should
    result in faster load detection as this code will now run in no more than
    one frame time. It does burn the CPU the whole time though, polling the
    displayed scanline register.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index c3db5c9..234d124 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -1938,6 +1938,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define TV_V_CHROMA_42		0x684a8
 /** @} */
 
+#define PIPEA_DSL		0x70000
+
 #define PIPEACONF 0x70008
 #define PIPEACONF_ENABLE	(1<<31)
 #define PIPEACONF_DISABLE	0
@@ -1966,6 +1968,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define PIPEAFRAMEPIXEL		0x70044
 
 
+#define PIPEB_DSL		0x71000
+
 #define PIPEBCONF 0x71008
 #define PIPEBCONF_ENABLE	(1<<31)
 #define PIPEBCONF_DISABLE	0
diff --git a/src/i830.h b/src/i830.h
index 7b0ab15..c91be79 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -489,6 +489,7 @@ typedef struct _I830Rec {
    CARD32 saveVTOTAL_A;
    CARD32 saveVBLANK_A;
    CARD32 saveVSYNC_A;
+   CARD32 saveBCLRPAT_A;
    CARD32 saveDSPASTRIDE;
    CARD32 saveDSPASIZE;
    CARD32 saveDSPAPOS;
@@ -504,6 +505,7 @@ typedef struct _I830Rec {
    CARD32 saveVTOTAL_B;
    CARD32 saveVBLANK_B;
    CARD32 saveVSYNC_B;
+   CARD32 saveBCLRPAT_B;
    CARD32 saveDSPBSTRIDE;
    CARD32 saveDSPBSIZE;
    CARD32 saveDSPBPOS;
diff --git a/src/i830_crt.c b/src/i830_crt.c
index fbb4adc..879ae9f 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -97,6 +97,8 @@ static Bool
 i830_crt_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
 		    DisplayModePtr adjusted_mode)
 {
+    /* disable blanking so we can detect monitors */
+    adjusted_mode->CrtcVBlankStart = adjusted_mode->CrtcVTotal - 3;
     return TRUE;
 }
 
@@ -106,7 +108,7 @@ i830_crt_mode_set(xf86OutputPtr output, 
 {
     ScrnInfoPtr		    pScrn = output->scrn;
     I830Ptr		    pI830 = I830PTR(pScrn);
-    xf86CrtcPtr	    crtc = output->crtc;
+    xf86CrtcPtr		    crtc = output->crtc;
     I830CrtcPrivatePtr	    i830_crtc = crtc->driver_private;
     int			    dpll_md_reg;
     CARD32		    adpa, dpll_md;
@@ -132,9 +134,15 @@ i830_crt_mode_set(xf86OutputPtr output, 
 	adpa |= ADPA_VSYNC_ACTIVE_HIGH;
 
     if (i830_crtc->pipe == 0)
+    {
 	adpa |= ADPA_PIPE_A_SELECT;
+	OUTREG(BCLRPAT_A, 0);
+    }
     else
+    {
 	adpa |= ADPA_PIPE_B_SELECT;
+	OUTREG(BCLRPAT_B, 0);
+    }
 
     OUTREG(ADPA, adpa);
 }
@@ -193,58 +201,79 @@ i830_crt_detect_load (xf86CrtcPtr	    cr
     ScrnInfoPtr		    pScrn = output->scrn;
     I830Ptr		    pI830 = I830PTR(pScrn);
     I830CrtcPrivatePtr	    i830_crtc = I830CrtcPrivate(crtc);
-    CARD32		    save_adpa, adpa, pipeconf, bclrpat;
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    CARD32		    save_bclrpat;
+    CARD32		    save_vtotal;
+    CARD32		    vtotal, vactive;
+    CARD32		    vsample;
+    CARD32		    dsl;
     CARD8		    st00;
-    int			    pipeconf_reg, bclrpat_reg, dpll_reg;
+    int			    bclrpat_reg, pipeconf_reg, pipe_dsl_reg;
+    int			    vtotal_reg;
     int			    pipe = i830_crtc->pipe;
+    int			    count, detect;
+    Bool		    present;
 
     if (pipe == 0) 
     {
 	bclrpat_reg = BCLRPAT_A;
+	vtotal_reg = VTOTAL_A;
 	pipeconf_reg = PIPEACONF;
-	dpll_reg = DPLL_A;
+	pipe_dsl_reg = PIPEA_DSL;
     }
     else 
     {
 	bclrpat_reg = BCLRPAT_B;
+	vtotal_reg = VTOTAL_B;
 	pipeconf_reg = PIPEBCONF;
-	dpll_reg = DPLL_B;
+	pipe_dsl_reg = PIPEB_DSL;
     }
 
-    adpa = INREG(ADPA);
-    save_adpa = adpa;
+    save_bclrpat = INREG(bclrpat_reg);
+    save_vtotal = INREG(vtotal_reg);
 
-    /* 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);
+    vtotal = (save_vtotal >> 16) & 0xfff;
+    vactive = save_vtotal & 0x7ff;
+    
+    /* sample the middle of the blanking interval */
+    vsample = ((vtotal - 3) + (vactive)) >> 1;
 
     /* Set the border color to purple. */
-    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);
-
-    /* Read the ST00 VGA status register */
-    st00 = pI830->readStandard(pI830, 0x3c2);
+    OUTREG(bclrpat_reg, 0x500050);
+    
+    /*
+     * Wait for the border to be displayed
+     */
+    while (INREG(pipe_dsl_reg) >= vactive)
+	;
+    while ((dsl = INREG(pipe_dsl_reg)) <= vsample)
+	;
+    /*
+     * Watch ST00 for an entire scanline
+     */
+    detect = 0;
+    count = 0;
+    do {
+	count++;
+	/* Read the ST00 VGA status register */
+	st00 = pI830->readStandard(pI830, 0x3c2);
+	if (st00 & (1 << 4))
+	    detect++;
+    } while ((INREG(pipe_dsl_reg) == dsl));
 
     /* Restore previous settings */
-    OUTREG(bclrpat_reg, bclrpat);
-    OUTREG(pipeconf_reg, pipeconf);
-    OUTREG(ADPA, save_adpa);
+    OUTREG(bclrpat_reg, save_bclrpat);
 
-    if (st00 & (1 << 4))
-	return TRUE;
-    else
-	return FALSE;
+    /*
+     * If more than 3/4 of the scanline detected a monitor,
+     * then it is assumed to be present. This works even on i830,
+     * where there isn't any way to force the border color across
+     * the screen
+     */
+    present = detect * 4 > count * 3;
+    xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "present: %s (%d of %d) at %ld desired %ld temp %d\n",
+		present ? "TRUE" : "FALSE", detect, count, dsl, vsample, intel_output->load_detect_temp);
+    return present;
 }
 
 /**
diff --git a/src/i830_display.c b/src/i830_display.c
index 727d1b2..4b205ba 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -1255,6 +1255,7 @@ i830ReleaseLoadDetectPipe(xf86OutputPtr 
     
     if (intel_output->load_detect_temp) 
     {
+	output->crtc->enabled = FALSE;
 	output->crtc = NULL;
 	intel_output->load_detect_temp = FALSE;
 	xf86DisableUnusedFunctions(pScrn);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 1d8b7f8..b4d9d08 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -744,6 +744,12 @@ I830SetupOutputs(ScrnInfoPtr pScrn)
 	 break;
       case I830_OUTPUT_ANALOG:
 	 crtc_mask = ((1 << 0));
+	 /*
+	  * 915 cannot do double-wide on pipe B
+	  * 830 cannot put CRT on pipe B
+	  */
+	 if (!IS_I915G(pI830) && !IS_I915GM (pI830) && !IS_I830(pI830))
+	    crtc_mask |= ((1 << 1));
 	 clone_mask = ((1 << I830_OUTPUT_ANALOG) |
 		       (1 << I830_OUTPUT_DVO) |
 		       (1 << I830_OUTPUT_SDVO));
@@ -1735,6 +1741,7 @@ SaveHWState(ScrnInfoPtr pScrn)
    pI830->saveVTOTAL_A = INREG(VTOTAL_A);
    pI830->saveVBLANK_A = INREG(VBLANK_A);
    pI830->saveVSYNC_A = INREG(VSYNC_A);
+   pI830->saveBCLRPAT_A = INREG(BCLRPAT_A);
    pI830->saveDSPASTRIDE = INREG(DSPASTRIDE);
    pI830->saveDSPASIZE = INREG(DSPASIZE);
    pI830->saveDSPAPOS = INREG(DSPAPOS);
@@ -1759,6 +1766,7 @@ SaveHWState(ScrnInfoPtr pScrn)
       pI830->saveVTOTAL_B = INREG(VTOTAL_B);
       pI830->saveVBLANK_B = INREG(VBLANK_B);
       pI830->saveVSYNC_B = INREG(VSYNC_B);
+      pI830->saveBCLRPAT_B = INREG(BCLRPAT_B);
       pI830->saveDSPBSTRIDE = INREG(DSPBSTRIDE);
       pI830->saveDSPBSIZE = INREG(DSPBSIZE);
       pI830->saveDSPBPOS = INREG(DSPBPOS);
@@ -1857,6 +1865,7 @@ RestoreHWState(ScrnInfoPtr pScrn)
    OUTREG(VTOTAL_A, pI830->saveVTOTAL_A);
    OUTREG(VBLANK_A, pI830->saveVBLANK_A);
    OUTREG(VSYNC_A, pI830->saveVSYNC_A);
+   OUTREG(BCLRPAT_A, pI830->saveBCLRPAT_A);
    
    OUTREG(DSPASTRIDE, pI830->saveDSPASTRIDE);
    OUTREG(DSPASIZE, pI830->saveDSPASIZE);
@@ -1894,6 +1903,7 @@ RestoreHWState(ScrnInfoPtr pScrn)
       OUTREG(VTOTAL_B, pI830->saveVTOTAL_B);
       OUTREG(VBLANK_B, pI830->saveVBLANK_B);
       OUTREG(VSYNC_B, pI830->saveVSYNC_B);
+      OUTREG(BCLRPAT_B, pI830->saveBCLRPAT_B);
       OUTREG(DSPBSTRIDE, pI830->saveDSPBSTRIDE);
       OUTREG(DSPBSIZE, pI830->saveDSPBSIZE);
       OUTREG(DSPBPOS, pI830->saveDSPBPOS);
diff-tree b930bb9d6da8c24dbe0949afb7bb2aa4bcb24687 (from 775fc125aa7ecd0f054959ef210be2df4dc54345)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu May 3 13:44:12 2007 -0700

    Disable vblank interrupts when no DRI clients are running.
    (cherry picked from commit 6621dd71ada839f4c1742e9e5b272e924cee21d9)

diff --git a/src/i830.h b/src/i830.h
index 8034302..7b0ab15 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -326,6 +326,7 @@ typedef struct _I830Rec {
    unsigned int third_tiled;
    unsigned int depth_tiled;
 
+   Bool want_vblank_interrupts;
 #ifdef DAMAGE
    DamagePtr pDamage;
    RegionRec driRegion;
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 2203c9e..9498661 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -590,13 +590,13 @@ I830DRIScreenInit(ScreenPtr pScreen)
    }
 
    pDRIInfo->TransitionTo2d = I830DRITransitionTo2d;
+   pDRIInfo->TransitionTo3d = I830DRITransitionTo3d;
 
 #if DRIINFO_MAJOR_VERSION > 5 || \
     (DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1)
    if (!pDRIInfo->ClipNotify)
 #endif
    {
-      pDRIInfo->TransitionTo3d = I830DRITransitionTo3d;
       pDRIInfo->TransitionSingleToMulti3D = I830DRITransitionSingleToMulti3d;
       pDRIInfo->TransitionMultiToSingle3D = I830DRITransitionMultiToSingle3d;
    }
@@ -1543,16 +1543,24 @@ I830DRITransitionTo3d(ScreenPtr pScreen)
    I830Ptr pI830 = I830PTR(pScrn);
 
    I830DRISetPfMask(pScreen, pI830->allowPageFlip ? 0x3 : 0);
+
+   pI830->want_vblank_interrupts = TRUE;
+   I830DRISetVBlankInterrupt(pScrn, TRUE);
 }
 
 static void
 I830DRITransitionTo2d(ScreenPtr pScreen)
 {
+   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+   I830Ptr pI830 = I830PTR(pScrn);
    drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScreen);
 
    I830DRISetPfMask(pScreen, 0);
 
    sPriv->pf_enabled = 0;
+
+   pI830->want_vblank_interrupts = FALSE;
+   I830DRISetVBlankInterrupt(pScrn, FALSE);
 }
 
 #if DRI_SUPPORTS_CLIP_NOTIFY
@@ -1684,6 +1692,12 @@ I830DRISetVBlankInterrupt (ScrnInfoPtr p
     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     drmI830VBlankPipe pipe;
 
+    /* If we have no 3d running, then don't bother enabling the vblank
+     * interrupt.
+     */
+    if (!pI830->want_vblank_interrupts)
+	on = FALSE;
+
     if (pI830->directRenderingEnabled && pI830->drmMinor >= 5) {
 	if (on) {
 	    if (xf86_config->num_crtc > 1 && xf86_config->crtc[1]->enabled)
diff-tree 3b769af53e0ef6ef9b56afd679446c73a0e63ea5 (from 775fc125aa7ecd0f054959ef210be2df4dc54345)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu May 3 13:44:12 2007 -0700

    Disable vblank interrupts when no DRI clients are running.

diff --git a/src/i830.h b/src/i830.h
index 8034302..7b0ab15 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -326,6 +326,7 @@ typedef struct _I830Rec {
    unsigned int third_tiled;
    unsigned int depth_tiled;
 
+   Bool want_vblank_interrupts;
 #ifdef DAMAGE
    DamagePtr pDamage;
    RegionRec driRegion;
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 2203c9e..9498661 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -590,13 +590,13 @@ I830DRIScreenInit(ScreenPtr pScreen)
    }
 
    pDRIInfo->TransitionTo2d = I830DRITransitionTo2d;
+   pDRIInfo->TransitionTo3d = I830DRITransitionTo3d;
 
 #if DRIINFO_MAJOR_VERSION > 5 || \
     (DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1)
    if (!pDRIInfo->ClipNotify)
 #endif
    {
-      pDRIInfo->TransitionTo3d = I830DRITransitionTo3d;
       pDRIInfo->TransitionSingleToMulti3D = I830DRITransitionSingleToMulti3d;
       pDRIInfo->TransitionMultiToSingle3D = I830DRITransitionMultiToSingle3d;
    }
@@ -1543,16 +1543,24 @@ I830DRITransitionTo3d(ScreenPtr pScreen)
    I830Ptr pI830 = I830PTR(pScrn);
 
    I830DRISetPfMask(pScreen, pI830->allowPageFlip ? 0x3 : 0);
+
+   pI830->want_vblank_interrupts = TRUE;
+   I830DRISetVBlankInterrupt(pScrn, TRUE);
 }
 
 static void
 I830DRITransitionTo2d(ScreenPtr pScreen)
 {
+   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+   I830Ptr pI830 = I830PTR(pScrn);
    drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScreen);
 
    I830DRISetPfMask(pScreen, 0);
 
    sPriv->pf_enabled = 0;
+
+   pI830->want_vblank_interrupts = FALSE;
+   I830DRISetVBlankInterrupt(pScrn, FALSE);
 }
 
 #if DRI_SUPPORTS_CLIP_NOTIFY
@@ -1684,6 +1692,12 @@ I830DRISetVBlankInterrupt (ScrnInfoPtr p
     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     drmI830VBlankPipe pipe;
 
+    /* If we have no 3d running, then don't bother enabling the vblank
+     * interrupt.
+     */
+    if (!pI830->want_vblank_interrupts)
+	on = FALSE;
+
     if (pI830->directRenderingEnabled && pI830->drmMinor >= 5) {
 	if (on) {
 	    if (xf86_config->num_crtc > 1 && xf86_config->crtc[1]->enabled)
diff-tree 775fc125aa7ecd0f054959ef210be2df4dc54345 (from 34f362d099d255f8f0bb34e9de30f953ee770163)
Author: Dave Airlie <airlied at airlied2.(none)>
Date:   Thu May 3 20:58:50 2007 +1000

    i810: be a bit more verbose about disabling DRI

diff --git a/src/i810_driver.c b/src/i810_driver.c
index 2a8b9fc..baca21c 100644
--- a/src/i810_driver.c
+++ b/src/i810_driver.c
@@ -848,11 +848,11 @@ I810PreInit(ScrnInfoPtr pScrn, int flags
 
    if (!pI810->directRenderingDisabled) {
      if (pI810->noAccel) {
-       xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "DRI is disabled because it "
+       xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DRI is disabled because it "
 		  "needs 2D acceleration.\n");
        pI810->directRenderingDisabled=TRUE;
      } else if (pScrn->depth!=16) {
-       xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "DRI is disabled because it "
+       xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DRI is disabled because it "
 		  "runs only at 16-bit depth.\n");
        pI810->directRenderingDisabled=TRUE;
      }
diff-tree 34f362d099d255f8f0bb34e9de30f953ee770163 (from f850d4727a2ad55c2116d0788f6684b2a0192d24)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed May 2 15:40:49 2007 -0700

    Fix typo s/i/index/ in LoadPalette for depth 16.
    
    Reported by:	Haihao Xiang <haihao.xiang at intel.com>

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 43f4e04..1d8b7f8 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -647,7 +647,7 @@ I830LoadPalette(ScrnInfoPtr pScrn, int n
 	 for (i = 0; i < numColors; i++) {
 	    index = indices[i];
 
-	    if (i <= 31) {
+	    if (index <= 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;
diff-tree f850d4727a2ad55c2116d0788f6684b2a0192d24 (from f3168e3b0c5664a322ca6bb1c81fc94844cb30ab)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed May 2 14:16:21 2007 -0700

    Make up a fixed panel timing for DVO LVDS, and use DVOA for DVO LVDS.
    
    The fixed panel timing will only be available when the LVDS is already on
    at X startup.
    
    So far, our only mostly-working LVDS driver is for the i830, and on i830 the
    LVDS is always on DVOA, so use that for all LVDS chips.  This may need to
    change if we support the ch7017 I've seen used on embedded i845, for example.

diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index 96b29e7..129651c 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -89,13 +89,19 @@ i830_dvo_dpms(xf86OutputPtr output, int 
     I830Ptr		    pI830 = I830PTR(pScrn);
     I830OutputPrivatePtr    intel_output = output->driver_private;
     void *		    dev_priv = intel_output->i2c_drv->dev_priv;
+    unsigned int	    dvo_reg;
+
+    if (intel_output->i2c_drv->type & I830_DVO_CHIP_LVDS)
+	dvo_reg = DVOA;
+    else
+	dvo_reg = DVOC;
 
     if (mode == DPMSModeOn) {
-	OUTREG(DVOC, INREG(DVOC) | DVO_ENABLE);
+	OUTREG(dvo_reg, INREG(dvo_reg) | DVO_ENABLE);
 	(*intel_output->i2c_drv->vid_rec->dpms)(dev_priv, mode);
     } else {
 	(*intel_output->i2c_drv->vid_rec->dpms)(dev_priv, mode);
-	OUTREG(DVOC, INREG(DVOC) & ~DVO_ENABLE);
+	OUTREG(dvo_reg, INREG(dvo_reg) & ~DVO_ENABLE);
     }
 }
 
@@ -166,18 +172,27 @@ i830_dvo_mode_set(xf86OutputPtr output, 
     I830OutputPrivatePtr    intel_output = output->driver_private;
     int			    pipe = intel_crtc->pipe;
     CARD32		    dvo;
+    unsigned int	    dvo_reg, dvo_srcdim_reg;
     int			    dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
 
+    if (intel_output->i2c_drv->type & I830_DVO_CHIP_LVDS) {
+	dvo_reg = DVOA;
+	dvo_srcdim_reg = DVOA_SRCDIM;
+    } else {
+	dvo_reg = DVOC;
+	dvo_srcdim_reg = DVOC_SRCDIM;
+    }
+
     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);
+    dvo = INREG(dvo_reg) & (DVO_PRESERVE_MASK | DVO_DATA_ORDER_GBRG);
     dvo |= DVO_DATA_ORDER_FP | DVO_BORDER_ENABLE | DVO_BLANK_ACTIVE_HIGH;
 
     if (pipe == 1)
 	dvo |= DVO_PIPE_B_SELECT;
-
+    dvo |= DVO_PIPE_STALL;
     if (adjusted_mode->Flags & V_PHSYNC)
 	dvo |= DVO_HSYNC_ACTIVE_HIGH;
     if (adjusted_mode->Flags & V_PVSYNC)
@@ -188,11 +203,11 @@ i830_dvo_mode_set(xf86OutputPtr output, 
     /*OUTREG(DVOB_SRCDIM,
       (adjusted_mode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
       (adjusted_mode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));*/
-    OUTREG(DVOC_SRCDIM,
+    OUTREG(dvo_srcdim_reg,
 	   (adjusted_mode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
 	   (adjusted_mode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));
     /*OUTREG(DVOB, dvo);*/
-    OUTREG(DVOC, dvo);
+    OUTREG(dvo_reg, dvo);
 }
 
 /**
@@ -209,6 +224,33 @@ i830_dvo_detect(xf86OutputPtr output)
     return intel_output->i2c_drv->vid_rec->detect(dev_priv);
 }
 
+static DisplayModePtr
+i830_dvo_get_modes(xf86OutputPtr output)
+{
+    ScrnInfoPtr		    pScrn = output->scrn;
+    I830Ptr		    pI830 = I830PTR(pScrn);
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    DisplayModePtr	    modes;
+
+    /* We should probably have an i2c driver get_modes function for those
+     * devices which will have a fixed set of modes determined by the chip
+     * (TV-out, for example), but for now with just TMDS and LVDS, that's not
+     * the case.
+     */
+    modes = i830_ddc_get_modes(output);
+    if (modes != NULL)
+	return modes;
+
+    if (intel_output->i2c_drv->type & I830_DVO_CHIP_LVDS &&
+	pI830->panel_fixed_mode != NULL)
+    {
+	xf86PrintModeline(pScrn->scrnIndex, pI830->panel_fixed_mode);
+	return xf86DuplicateMode(pI830->panel_fixed_mode);
+    }
+
+    return NULL;
+}
+
 static void
 i830_dvo_destroy (xf86OutputPtr output)
 {
@@ -235,10 +277,47 @@ static const xf86OutputFuncsRec i830_dvo
     .mode_set = i830_dvo_mode_set,
     .commit = i830_output_commit,
     .detect = i830_dvo_detect,
-    .get_modes = i830_ddc_get_modes,
+    .get_modes = i830_dvo_get_modes,
     .destroy = i830_dvo_destroy
 };
 
+/**
+ * Attempts to get a fixed panel timing for LVDS (currently only the i830).
+ *
+ * Other chips with DVO LVDS will need to extend this to deal with the LVDS
+ * chip being on DVOB/C and having multiple pipes.
+ */
+static void
+i830_dvo_get_panel_timings(xf86OutputPtr output)
+{
+    ScrnInfoPtr		    pScrn = output->scrn;
+    I830Ptr		    pI830 = I830PTR(pScrn);
+    CARD32 dvoa = INREG(DVOA);
+
+    if (!IS_I830(pI830))
+	return;
+
+    assert(pI830->fixed_panel_mode == NULL);
+
+    /* If the DVOA port is active, that'll be the LVDS, so we can pull out
+     * its timings to get how the BIOS set up the panel.
+     */
+    if (dvoa & DVO_ENABLE) {
+	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+	int pipe = (dvoa & DVO_PIPE_B_SELECT) ? 1 : 0;
+	xf86CrtcPtr crtc = xf86_config->crtc[pipe];
+
+	pI830->panel_fixed_mode = i830_crtc_mode_get(pScrn, crtc);
+	if (pI830->panel_fixed_mode != NULL)
+	    pI830->panel_fixed_mode->type |= M_T_PREFERRED;
+
+	if (dvoa & DVO_HSYNC_ACTIVE_HIGH)
+	    pI830->panel_fixed_mode->Flags |= V_PHSYNC;
+	if (dvoa & DVO_VSYNC_ACTIVE_HIGH)
+	    pI830->panel_fixed_mode->Flags |= V_PVSYNC;
+    }
+}
+
 void
 i830_dvo_init(ScrnInfoPtr pScrn)
 {
@@ -315,6 +394,9 @@ i830_dvo_init(ScrnInfoPtr pScrn)
 		return;
 	    }
 
+	    if (drv->type & I830_DVO_CHIP_LVDS)
+		i830_dvo_get_panel_timings(output);
+
 	    output->driver_private = intel_output;
 	    output->subpixel_order = SubPixelHorizontalRGB;
 	    output->interlaceAllowed = FALSE;
diff-tree f3168e3b0c5664a322ca6bb1c81fc94844cb30ab (from 1fc630f24f8ad9e304cb0761f9cacca2224203c4)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed May 2 14:08:30 2007 -0700

    Disable non-working GTT decoding on i830, and fix map/unmap of GTT.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index ad88f56..43f4e04 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -544,7 +544,10 @@ I830MapMMIO(ScrnInfoPtr pScrn)
 	    return FALSE;
       }
    } else {
-      pI830->GTTBase = pI830->MMIOBase + I830_PTE_BASE;
+      /* The GTT aperture on i830 is write-only.  We could probably map the
+       * actual physical pages that back it, but leave it alone for now.
+       */
+      pI830->GTTBase = NULL;
    }
 
    return TRUE;
@@ -584,6 +587,15 @@ I830UnmapMMIO(ScrnInfoPtr pScrn)
    xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pI830->MMIOBase,
 		   I810_REG_SIZE);
    pI830->MMIOBase = NULL;
+
+   if (IS_I9XX(pI830)) {
+      if (IS_I965G(pI830))
+	 xf86UnMapVidMem(pScrn->scrnIndex, pI830->GTTBase, 512 * 1024);
+      else {
+	 xf86UnMapVidMem(pScrn->scrnIndex, pI830->GTTBase,
+			 pI830->FbMapSize / 1024);
+      }
+   }
 }
 
 static Bool
@@ -2279,6 +2291,9 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       pI830->used3D = pI8301->used3D;
    }
 
+   /* Need MMIO mapped to do GTT lookups during memory allocation. */
+   I830MapMMIO(pScrn);
+
 #if defined(XF86DRI)
    /*
     * If DRI is potentially usable, check if there is enough memory available
@@ -2419,6 +2434,8 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       allocation_done = TRUE;
    }
 
+   I830UnmapMMIO(pScrn);
+
    i830_describe_allocations(pScrn, 1, "");
 
    if (!IS_I965G(pI830) && pScrn->displayWidth > 2048) {
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 9cf14e4..3ae10cf 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -324,7 +324,13 @@ static unsigned long
 i830_get_gtt_physical(ScrnInfoPtr pScrn, unsigned long offset)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    CARD32 gttentry = INGTT(offset / 1024);
+    CARD32 gttentry;
+
+    /* We don't have GTTBase set up on i830 yet. */
+    if (pI830->GTTBase == NULL)
+	return -1;
+
+    gttentry = INGTT(offset / 1024);
 
     /* Mask out these reserved bits on this hardware. */
     if (!IS_I965G(pI830))
diff-tree 1fc630f24f8ad9e304cb0761f9cacca2224203c4 (from d0ec37e9c0ceab1080700cd7be4a7cc58552d465)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed May 2 13:29:21 2007 -0700

    Add DVO[ABC] register debugging.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index 491c389..c3db5c9 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -1196,6 +1196,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define DVO_PIPE_STALL_UNUSED		(0 << 28)
 #define DVO_PIPE_STALL			(1 << 28)
 #define DVO_PIPE_STALL_TV		(2 << 28)
+#define DVO_PIPE_STALL_MASK		(3 << 28)
 #define DVO_USE_VGA_SYNC		(1 << 15)
 #define DVO_DATA_ORDER_I740		(0 << 14)
 #define DVO_DATA_ORDER_FP		(1 << 14)
diff --git a/src/i830_debug.c b/src/i830_debug.c
index c0261a6..73b5d1c 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -286,6 +286,33 @@ DEBUGSTRING(i830_debug_lvds)
 		     enable, pipe, depth, channels);
 }
 
+DEBUGSTRING(i830_debug_dvo)
+{
+    char *enable = val & DVO_ENABLE ? "enabled" : "disabled";
+    char pipe = val & DVO_PIPE_B_SELECT ? 'B' : 'A';
+    char *stall;
+    char hsync = val & DVO_HSYNC_ACTIVE_HIGH ? '+' : '-';
+    char vsync = val & DVO_VSYNC_ACTIVE_HIGH ? '+' : '-';
+
+    switch (val & DVO_PIPE_STALL_MASK) {
+    case DVO_PIPE_STALL_UNUSED:
+	stall = "no stall";
+	break;
+    case DVO_PIPE_STALL:
+	stall = "stall";
+	break;
+    case DVO_PIPE_STALL_TV:
+	stall = "TV stall";
+	break;
+    default:
+	stall = "unknown stall";
+	break;
+    }
+
+    return XNFprintf("%s, pipe %c, %s, %chsync, %cvsync",
+		     enable, pipe, stall, hsync, vsync);
+}
+
 DEBUGSTRING(i830_debug_sdvo)
 {
     char *enable = val & SDVO_ENABLE ? "enabled" : "disabled";
@@ -339,9 +366,9 @@ static struct i830SnapshotRec {
 
     DEFINEREG2(ADPA, i830_debug_adpa),
     DEFINEREG2(LVDS, i830_debug_lvds),
-    DEFINEREG(DVOA),
-    DEFINEREG(DVOB),
-    DEFINEREG(DVOC),
+    DEFINEREG2(DVOA, i830_debug_dvo),
+    DEFINEREG2(DVOB, i830_debug_dvo),
+    DEFINEREG2(DVOC, i830_debug_dvo),
     DEFINEREG(DVOA_SRCDIM),
     DEFINEREG(DVOB_SRCDIM),
     DEFINEREG(DVOC_SRCDIM),
diff-tree d0ec37e9c0ceab1080700cd7be4a7cc58552d465 (from 490d05f99d2b62dd612d514d9ae0badbac9285ce)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue May 1 15:56:37 2007 -0700

    Make the DVO output name LVDS if it's an LVDS chip.

diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index 4b37228..96b29e7 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -242,7 +242,6 @@ static const xf86OutputFuncsRec i830_dvo
 void
 i830_dvo_init(ScrnInfoPtr pScrn)
 {
-    xf86OutputPtr output;
     I830OutputPrivatePtr intel_output;
     int ret;
     int i;
@@ -251,27 +250,15 @@ i830_dvo_init(ScrnInfoPtr pScrn)
     int gpio_inited = 0;
     I2CBusPtr pI2CBus = NULL;
 
-    output = xf86OutputCreate (pScrn, &i830_dvo_output_funcs,
-				   "TMDS");
-    if (!output)
-	return;
     intel_output = xnfcalloc (sizeof (I830OutputPrivateRec), 1);
     if (!intel_output)
-    {
-	xf86OutputDestroy (output);
 	return;
-    }
     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");
-    if (!ret)
-    {
-	xf86OutputDestroy (output);
+    if (!ret) {
+	xfree(intel_output);
 	return;
     }
 
@@ -311,6 +298,28 @@ i830_dvo_init(ScrnInfoPtr pScrn)
 	    ret_ptr = drv->vid_rec->init(pI2CBus, drv->address);
 
 	if (ret_ptr != NULL) {
+	    xf86OutputPtr output;
+
+	    if (drv->type & I830_DVO_CHIP_LVDS) {
+		output = xf86OutputCreate(pScrn, &i830_dvo_output_funcs,
+					  "LVDS");
+	    } else {
+		output = xf86OutputCreate(pScrn, &i830_dvo_output_funcs,
+					  "TMDS");
+	    }
+	    if (output == NULL) {
+		xf86DestroyI2CBusRec(pI2CBus, TRUE, TRUE);
+		xf86DestroyI2CBusRec(intel_output->pDDCBus, TRUE, TRUE);
+		xfree(intel_output);
+		xf86UnloadSubModule(drv->modhandle);
+		return;
+	    }
+
+	    output->driver_private = intel_output;
+	    output->subpixel_order = SubPixelHorizontalRGB;
+	    output->interlaceAllowed = FALSE;
+	    output->doubleScanAllowed = FALSE;
+
 	    drv->dev_priv = ret_ptr;
 	    intel_output->i2c_drv = drv;
 	    intel_output->pI2CBus = pI2CBus;
@@ -322,5 +331,6 @@ i830_dvo_init(ScrnInfoPtr pScrn)
     /* Didn't find a chip, so tear down. */
     if (pI2CBus != NULL)
 	xf86DestroyI2CBusRec(pI2CBus, TRUE, TRUE);
-    xf86OutputDestroy (output);
+    xf86DestroyI2CBusRec(intel_output->pDDCBus, TRUE, TRUE);
+    xfree(intel_output);
 }
diff-tree 490d05f99d2b62dd612d514d9ae0badbac9285ce (from c7bb34e83d7c459d932d01070cfeffbbf6c703ac)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue May 1 15:47:01 2007 -0700

    Fix typo in previous commit with s/XF86_DRI/XF86DRI/

diff --git a/src/i830_memory.c b/src/i830_memory.c
index 23e7dbc..9cf14e4 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -250,7 +250,7 @@ i830_free_3d_memory(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
 
-#ifdef XF86_DRI
+#ifdef XF86DRI
     i830_free_memory(pScrn, pI830->back_buffer);
     pI830->back_buffer = NULL;
     i830_free_memory(pScrn, pI830->third_buffer);
diff-tree c7bb34e83d7c459d932d01070cfeffbbf6c703ac (from cae0ae237b79fa7d3a82dfc8d3fb595ccb6c63e1)
Author: Dave Airlie <airlied at linux.ie>
Date:   Wed May 2 14:25:39 2007 +1000

    disable all outputs on EnterVT
    
    This disables all outputs on EnterVT as the SDVO output can confuse
    the VGA output if the BIOS has enabled it on the same pipe but X
    isn't going to use the SDVO.
    
    Worked out on irc with keithp

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 4990b8f..ad88f56 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2870,6 +2870,8 @@ I830EnterVT(int scrnIndex, int flags)
 {
    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
    I830Ptr  pI830 = I830PTR(pScrn);
+   xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
+   int o;
 
    DPRINTF(PFX, "Enter VT\n");
 
@@ -2900,6 +2902,11 @@ I830EnterVT(int scrnIndex, int flags)
    memset(pI830->FbBase + pScrn->fbOffset, 0,
 	  pScrn->virtualY * pScrn->displayWidth * pI830->cpp);
 
+   for (o = 0; o < config->num_output; o++) {
+   	xf86OutputPtr  output = config->output[o];
+	output->funcs->dpms(output, DPMSModeOff);
+   }
+
    if (!xf86SetDesiredModes (pScrn))
       return FALSE;
    
diff-tree cae0ae237b79fa7d3a82dfc8d3fb595ccb6c63e1 (from 6748d620fbf39dd98982856c09256bdec0fc82a1)
Author: Samuel Thibault <samuel.thibault at ens-lyon.org>
Date:   Tue May 1 12:41:18 2007 -0700

    Bug #10714: Fix build without DRI.

diff --git a/src/i830.h b/src/i830.h
index f69ad73..8034302 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -307,6 +307,9 @@ typedef struct _I830Rec {
    int *used3D;
 
    i830_memory *logical_context;
+
+   unsigned int front_tiled;
+
 #ifdef XF86DRI
    i830_memory *back_buffer;
    i830_memory *third_buffer;
@@ -319,7 +322,6 @@ typedef struct _I830Rec {
    int mmModeFlags;
    int mmSize;
 
-   unsigned int front_tiled;
    unsigned int back_tiled;
    unsigned int third_tiled;
    unsigned int depth_tiled;
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 2cc9327..23e7dbc 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -231,11 +231,13 @@ i830_reset_allocations(ScrnInfoPtr pScrn
     pI830->exa_965_state = NULL;
     pI830->overlay_regs = NULL;
     pI830->logical_context = NULL;
+#ifdef XF86DRI
     pI830->back_buffer = NULL;
     pI830->third_buffer = NULL;
     pI830->depth_buffer = NULL;
     pI830->textures = NULL;
     pI830->memory_manager = NULL;
+#endif
     pI830->LpRing->mem = NULL;
 
     /* Reset the fence register allocation. */
@@ -248,6 +250,7 @@ i830_free_3d_memory(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
 
+#ifdef XF86_DRI
     i830_free_memory(pScrn, pI830->back_buffer);
     pI830->back_buffer = NULL;
     i830_free_memory(pScrn, pI830->third_buffer);
@@ -258,6 +261,7 @@ i830_free_3d_memory(ScrnInfoPtr pScrn)
     pI830->textures = NULL;
     i830_free_memory(pScrn, pI830->memory_manager);
     pI830->memory_manager = NULL;
+#endif
 }
 
 /**
@@ -691,6 +695,7 @@ i830_describe_allocations(ScrnInfoPtr pS
 	i830_describe_tiling(pScrn, verbosity, prefix, pI830->front_buffer,
 			     pI830->front_tiled);
     }
+#ifdef XF86DRI
     if (pI830->back_buffer != NULL) {
 	i830_describe_tiling(pScrn, verbosity, prefix, pI830->back_buffer,
 			     pI830->back_tiled);
@@ -703,6 +708,7 @@ i830_describe_allocations(ScrnInfoPtr pS
 	i830_describe_tiling(pScrn, verbosity, prefix, pI830->depth_buffer,
 			     pI830->depth_tiled);
     }
+#endif
 }
 
 static Bool
@@ -1330,7 +1336,6 @@ i830_allocate_3d_memory(ScrnInfoPtr pScr
 }
 #endif
 
-#ifdef XF86DRI
 /**
  * Sets up a fence area for the hardware.
  *
@@ -1529,7 +1534,6 @@ i830_set_fence(ScrnInfoPtr pScrn, int nr
 
     pI830->fence[nr] = val;
 }
-#endif
 
 /**
  * Called at EnterVT to grab the AGP GART and bind our allocations.
diff-tree 6748d620fbf39dd98982856c09256bdec0fc82a1 (from a4f1a7872f6f959bb4bc6568face710bee3589de)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Apr 30 17:27:23 2007 -0700

    Ignore VideoRam now that its original purpose is obsolete.
    
    It had been necessary to allow more than a small amount of memory to be
    allocated, but now those old small allocations people had configured are
    getting in the way.

diff --git a/man/intel.man b/man/intel.man
index 178ff0a..daf9030 100644
--- a/man/intel.man
+++ b/man/intel.man
@@ -43,17 +43,10 @@ NetBSD, and Solaris have such kernel dri
 By default, the i810 will use 8 megabytes
 of system memory for graphics.  For the 830M and later, the driver will
 automatically size its memory allocation according to the features it will
-support.  The amount of memory used may be limited by using the
+support.  The
 .B VideoRam
-entry in the config file
-.B "Device"
-section.  Limiting the amount of memory used may result in features being
-disabled, so if you choose to configure it, it is advisable to check the
-__xservername__
-log file to see 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.
+option, which in the past had been necessary to allow more than some small
+amount of memory to be allocated, is now ignored.
 .PP
 The following driver
 .B Options
diff --git a/src/i830_driver.c b/src/i830_driver.c
index e38b77b..4990b8f 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2162,8 +2162,30 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       from = X_DEFAULT;
       pScrn->videoRam = pI830->FbMapSize / KB(1);
    } else {
+#if 0
       from = X_CONFIG;
       pScrn->videoRam = pI830->pEnt->device->videoRam;
+#else
+      /* Disable VideoRam configuration, at least for now.  Previously,
+       * VideoRam was necessary to avoid overly low limits on allocated
+       * memory, so users created larger, yet still small, fixed allocation
+       * limits in their config files.  Now, the driver wants to allocate more,
+       * and the old intention of the VideoRam lines that had been entered is
+       * obsolete.
+       */
+      from = X_DEFAULT;
+      pScrn->videoRam = pI830->FbMapSize / KB(1);
+
+      if (pScrn->videoRam != pI830->pEnt->device->videoRam) {
+	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		    "VideoRam configuration found, which is no longer "
+		    "recommended.\n");
+	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		    "Continuing with default %dkB VideoRam instead of %d "
+		    "kB.\n",
+		    pScrn->videoRam, pI830->pEnt->device->videoRam);
+      }
+#endif
    }
 
    /* Limit videoRam to how much we might be able to allocate from AGP */
diff-tree a4f1a7872f6f959bb4bc6568face710bee3589de (from 7d0d34cfdcc67d07e7667e13a9413743853134f8)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Apr 30 17:13:09 2007 -0700

    Allow physical-memory allocations within stolen memory.
    
    Because stolen memory happens to be a contiguous block of high system memory,
    we can just read the GTT entries for it to get physical addresses for our
    allocations there if needed.  This reduces fragmentation of the aperture space,
    and will often reclaim up to 7 MB of memory that had been left unused since the
    simplified aperture manager was put in place, but without reintroducing the
    complexities of the old aperture manager.

diff --git a/src/common.h b/src/common.h
index f299e5d..f45fc8e 100644
--- a/src/common.h
+++ b/src/common.h
@@ -233,6 +233,7 @@ union intfloat {
 #define INREG8(addr)        *(volatile CARD8  *)(RecPtr->MMIOBase + (addr))
 #define INREG16(addr)       *(volatile CARD16 *)(RecPtr->MMIOBase + (addr))
 #define INREG(addr)         *(volatile CARD32 *)(RecPtr->MMIOBase + (addr))
+#define INGTT(addr)         *(volatile CARD32 *)(RecPtr->GTTBase + (addr))
 #define POSTING_READ(addr)  (void)INREG(addr)
 
 #define OUTREG8(addr, val) do {						\
diff --git a/src/i810_reg.h b/src/i810_reg.h
index bc944fe..491c389 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -526,6 +526,15 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define PGETBL_SIZE_256KB   (1 << 1)
 #define PGETBL_SIZE_128KB   (2 << 1)
 
+#define I830_PTE_BASE			0x10000
+#define PTE_ADDRESS_MASK		0xfffff000
+#define PTE_ADDRESS_MASK_HIGH		0x000000f0 /* i915+ */
+#define PTE_MAPPING_TYPE_UNCACHED	(0 << 1)
+#define PTE_MAPPING_TYPE_DCACHE		(1 << 1) /* i830 only */
+#define PTE_MAPPING_TYPE_CACHED		(3 << 1)
+#define PTE_MAPPING_TYPE_MASK		(3 << 1)
+#define PTE_VALID			(1 << 0)
+
 /** @defgroup PGE_ERR
  * @{
  */
@@ -577,18 +586,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 # define PGTBL_ERR_HOST_GTT_PTE			(1 << 0)
 /** @} */
 
-/* Page table entries loaded via mmio region, p323
- */
-#define PTE_BASE         0x10000
-#define PTE_ADDR_MASK       0x3FFFF000
-#define PTE_TYPE_MASK       0x00000006
-#define PTE_LOCAL           0x00000002
-#define PTE_MAIN_UNCACHED   0x00000000
-#define PTE_MAIN_CACHED     0x00000006
-#define PTE_VALID_MASK      0x00000001
-#define PTE_VALID           0x00000001
-
-
 /* Ring buffer registers, p277, overview p19
  */
 #define LP_RING     0x2030
diff --git a/src/i830.h b/src/i830.h
index d81857b..f69ad73 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -261,6 +261,7 @@ enum last_3d {
 
 typedef struct _I830Rec {
    unsigned char *MMIOBase;
+   unsigned char *GTTBase;
    unsigned char *FbBase;
    int cpp;
 
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 235ee2a..e38b77b 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -521,6 +521,32 @@ I830MapMMIO(ScrnInfoPtr pScrn)
 				   pI830->MMIOAddr, I810_REG_SIZE);
    if (!pI830->MMIOBase)
       return FALSE;
+
+   /* Set up the GTT mapping for the various places it has been moved over
+    * time.
+    */
+   if (IS_I9XX(pI830)) {
+      if (IS_I965G(pI830)) {
+	 pI830->GTTBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags,
+					pI830->PciTag,
+					pI830->MMIOAddr + (512 * 1024),
+					512 * 1024);
+	 if (pI830->GTTBase == NULL)
+	    return FALSE;
+      } else {
+	 CARD32 gttaddr = pI830->PciInfo->memBase[3] & 0xFFFFFF00;
+
+	 pI830->GTTBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags,
+					pI830->PciTag,
+					gttaddr,
+					pI830->FbMapSize / 1024);
+	 if (pI830->GTTBase == NULL)
+	    return FALSE;
+      }
+   } else {
+      pI830->GTTBase = pI830->MMIOBase + I830_PTE_BASE;
+   }
+
    return TRUE;
 }
 
@@ -1136,6 +1162,27 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    }
    xf86CrtcSetSizeRange (pScrn, 320, 200, max_width, max_height);
 
+   if (IS_I830(pI830) || IS_845G(pI830)) {
+      PCITAG bridge;
+      CARD16 gmch_ctrl;
+
+      bridge = pciTag(0, 0, 0);		/* This is always the host bridge */
+      gmch_ctrl = pciReadWord(bridge, I830_GMCH_CTRL);
+      if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_128M) {
+	 pI830->FbMapSize = 0x8000000;
+      } else {
+	 pI830->FbMapSize = 0x4000000; /* 64MB - has this been tested ?? */
+      }
+   } else {
+      if (IS_I9XX(pI830)) {
+	 pI830->FbMapSize = 1UL << pciGetBaseSize(pI830->PciTag, 2, TRUE,
+						  NULL);
+      } else {
+	 /* 128MB aperture for later i8xx series. */
+	 pI830->FbMapSize = 0x8000000;
+      }
+   }
+
    /* Some of the probing needs MMIO access, so map it here. */
    I830MapMMIO(pScrn);
 
@@ -1159,27 +1206,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 		(1 << 23) | (2 << 16));
 #endif
 
-   if (IS_I830(pI830) || IS_845G(pI830)) {
-      PCITAG bridge;
-      CARD16 gmch_ctrl;
-
-      bridge = pciTag(0, 0, 0);		/* This is always the host bridge */
-      gmch_ctrl = pciReadWord(bridge, I830_GMCH_CTRL);
-      if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_128M) {
-	 pI830->FbMapSize = 0x8000000;
-      } else {
-	 pI830->FbMapSize = 0x4000000; /* 64MB - has this been tested ?? */
-      }
-   } else {
-      if (IS_I9XX(pI830)) {
-	 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)
       num_pipe = 1;
    else
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 268d6c5..2cc9327 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -309,6 +309,86 @@ i830_allocator_init(ScrnInfoPtr pScrn, u
     return TRUE;
 }
 
+/**
+ * Reads a GTT entry for the memory at the given offset and returns the
+ * physical address.
+ *
+ * \return physical address if successful.
+ * \return (unsigned long)-1 if unsuccessful.
+ */
+static unsigned long
+i830_get_gtt_physical(ScrnInfoPtr pScrn, unsigned long offset)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD32 gttentry = INGTT(offset / 1024);
+
+    /* Mask out these reserved bits on this hardware. */
+    if (!IS_I965G(pI830))
+	gttentry &= ~PTE_ADDRESS_MASK_HIGH;
+
+    /* If it's not a mapping type we know, then bail. */
+    if ((gttentry & PTE_MAPPING_TYPE_MASK) != PTE_MAPPING_TYPE_UNCACHED &&
+	(gttentry & PTE_MAPPING_TYPE_MASK) != PTE_MAPPING_TYPE_CACHED)
+    {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "Unusable physical mapping type 0x%08x\n",
+		   (unsigned int)(gttentry & PTE_MAPPING_TYPE_MASK));
+	return -1;
+    }
+    /* If we can't represent the address with an unsigned long, bail. */
+    if (sizeof(unsigned long) == 4 &&
+	(gttentry & PTE_ADDRESS_MASK_HIGH) != 0)
+    {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "High memory PTE (0x%08x) on 32-bit system\n",
+		   (unsigned int)gttentry);
+	return -1;
+    }
+    assert((gttentry & PTE_VALID) != 0);
+
+    return (gttentry & PTE_ADDRESS_MASK) |
+	(gttentry & PTE_ADDRESS_MASK_HIGH << (32 - 4));
+}
+
+/**
+ * Reads the GTT entries for stolen memory at the given offset, returning the
+ * physical address.
+ *
+ * \return physical address if successful.
+ * \return (unsigned long)-1 if unsuccessful.
+ */
+static unsigned long
+i830_get_stolen_physical(ScrnInfoPtr pScrn, unsigned long offset,
+			 unsigned long size)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    unsigned long physical, scan;
+
+    /* Check that the requested region is within stolen memory. */
+    if (offset + size >= pI830->stolen_size)
+	return -1;
+
+    physical = i830_get_gtt_physical(pScrn, offset);
+    if (physical == -1)
+	return -1;
+
+    /* Check that the following pages in our allocation follow the first page
+     * contiguously.
+     */
+    for (scan = offset + 4096; scan < offset + size; scan += 4096) {
+	unsigned long scan_physical = i830_get_gtt_physical(pScrn, scan);
+
+	if ((scan - offset) != (scan_physical - physical)) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Non-contiguous GTT entries: (%ld,%ld) vs (%ld,%ld)\n",
+		       scan, scan_physical, offset, physical);
+	    return -1;
+	}
+    }
+
+    return physical;
+}
+
 /* Allocate aperture space for the given size and alignment, and returns the
  * memory allocation.
  *
@@ -341,13 +421,25 @@ i830_allocate_aperture(ScrnInfoPtr pScrn
 	alignment = GTT_PAGE_SIZE;
 
     for (scan = pI830->memory_list; scan->next != NULL; scan = scan->next) {
-	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->offset = ROUND_TO(scan->end, alignment);
+	if ((flags & NEED_PHYSICAL_ADDR) && mem->offset < pI830->stolen_size) {
+	    /* If the allocation is entirely within stolen memory, and we're
+	     * able to get the physical addresses out of the GTT and check that
+	     * it's contiguous (it ought to be), then we can do our physical
+	     * allocations there and not bother the kernel about it.  This
+	     * helps avoid aperture fragmentation from our physical
+	     * allocations.
+	     */
+	    mem->bus_addr = i830_get_stolen_physical(pScrn, mem->offset,
+						     mem->size);
+
+	    if (mem->bus_addr == ((unsigned long)-1)) {
+		/* Move the start of the allocation to just past the end of
+		 * stolen memory.
+		 */
+		mem->offset = ROUND_TO(pI830->stolen_size, alignment);
+	    }
+	}
 
 	mem->end = mem->offset + size;
 	if (flags & ALIGN_BOTH_ENDS)
@@ -385,11 +477,8 @@ i830_allocate_agp_memory(ScrnInfoPtr pSc
     if (mem->key != -1)
 	return TRUE;
 
-    if (mem->offset + mem->size <= pI830->stolen_size &&
-	!(flags & NEED_PHYSICAL_ADDR))
-    {
+    if (mem->offset + mem->size <= pI830->stolen_size)
 	return TRUE;
-    }
 
     if (mem->offset < pI830->stolen_size)
 	mem->agp_offset = pI830->stolen_size;
diff-tree 7d0d34cfdcc67d07e7667e13a9413743853134f8 (from 138ac8f36cb4e4b3776f313955372522646acbb2)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Apr 30 10:39:54 2007 -0700

    Disable some clock gating functions documented to work incorrectly.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index eaa8bb5..bc944fe 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -958,7 +958,101 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 #define D_STATE			0x6104
 #define DSPCLK_GATE_D		0x6200
+# define TVRUNIT_CLOCK_GATE_DISABLE		(1 << 23) /* 915-945 */
+# define TVCUNIT_CLOCK_GATE_DISABLE		(1 << 22) /* 915-945 */
+# define TVFUNIT_CLOCK_GATE_DISABLE		(1 << 21) /* 915-945 */
+# define TVEUNIT_CLOCK_GATE_DISABLE		(1 << 20) /* 915-945 */
+# define DVSUNIT_CLOCK_GATE_DISABLE		(1 << 19) /* 915-945 */
+# define DSSUNIT_CLOCK_GATE_DISABLE		(1 << 18) /* 915-945 */
+# define DDBUNIT_CLOCK_GATE_DISABLE		(1 << 17) /* 915-945 */
+# define DPRUNIT_CLOCK_GATE_DISABLE		(1 << 16) /* 915-945 */
+# define DPFUNIT_CLOCK_GATE_DISABLE		(1 << 15) /* 915-945 */
+# define DPBMUNIT_CLOCK_GATE_DISABLE		(1 << 14) /* 915-945 */
+# define DPLSUNIT_CLOCK_GATE_DISABLE		(1 << 13) /* 915-945 */
+# define DPLUNIT_CLOCK_GATE_DISABLE		(1 << 12) /* 915-945 */
+# define DPOUNIT_CLOCK_GATE_DISABLE		(1 << 11)
+# define DPBUNIT_CLOCK_GATE_DISABLE		(1 << 10)
+# define DPCUNIT_CLOCK_GATE_DISABLE		(1 << 9)
+# define DPUNIT_CLOCK_GATE_DISABLE		(1 << 8)
+# define VRUNIT_CLOCK_GATE_DISABLE		(1 << 7) /* 915+: reserved */
+# define OVHUNIT_CLOCK_GATE_DISABLE		(1 << 6) /* 830-865 */
+# define DPIOUNIT_CLOCK_GATE_DISABLE		(1 << 6) /* 915-945 */
+# define OVFUNIT_CLOCK_GATE_DISABLE		(1 << 5)
+# define OVBUNIT_CLOCK_GATE_DISABLE		(1 << 4)
+/**
+ * This bit must be set on the 830 to prevent hangs when turning off the
+ * overlay scaler.
+ */
+# define OVRUNIT_CLOCK_GATE_DISABLE		(1 << 3)
+# define OVCUNIT_CLOCK_GATE_DISABLE		(1 << 2)
+# define OVUUNIT_CLOCK_GATE_DISABLE		(1 << 1)
+# define ZVUNIT_CLOCK_GATE_DISABLE		(1 << 0) /* 830 */
+# define OVLUNIT_CLOCK_GATE_DISABLE		(1 << 0) /* 845,865 */
+
 #define RENCLK_GATE_D1		0x6204
+# define BLITTER_CLOCK_GATE_DISABLE		(1 << 13) /* 945GM only */
+# define MPEG_CLOCK_GATE_DISABLE		(1 << 12) /* 945GM only */
+# define PC_FE_CLOCK_GATE_DISABLE		(1 << 11)
+# define PC_BE_CLOCK_GATE_DISABLE		(1 << 10)
+# define WINDOWER_CLOCK_GATE_DISABLE		(1 << 9)
+# define INTERPOLATOR_CLOCK_GATE_DISABLE	(1 << 8)
+# define COLOR_CALCULATOR_CLOCK_GATE_DISABLE	(1 << 7)
+# define MOTION_COMP_CLOCK_GATE_DISABLE		(1 << 6)
+# define MAG_CLOCK_GATE_DISABLE			(1 << 5)
+/** This bit must be unset on 855,865 */
+# define MECI_CLOCK_GATE_DISABLE		(1 << 4)
+# define DCMP_CLOCK_GATE_DISABLE		(1 << 3)
+# define MEC_CLOCK_GATE_DISABLE			(1 << 2)
+# define MECO_CLOCK_GATE_DISABLE		(1 << 1)
+/** This bit must be set on 855,865. */
+# define SV_CLOCK_GATE_DISABLE			(1 << 0)
+# define I915_MPEG_CLOCK_GATE_DISABLE		(1 << 16)
+# define I915_VLD_IP_PR_CLOCK_GATE_DISABLE	(1 << 15)
+# define I915_MOTION_COMP_CLOCK_GATE_DISABLE	(1 << 14)
+# define I915_BD_BF_CLOCK_GATE_DISABLE		(1 << 13)
+# define I915_SF_SE_CLOCK_GATE_DISABLE		(1 << 12)
+# define I915_WM_CLOCK_GATE_DISABLE		(1 << 11)
+# define I915_IZ_CLOCK_GATE_DISABLE		(1 << 10)
+# define I915_PI_CLOCK_GATE_DISABLE		(1 << 9)
+# define I915_DI_CLOCK_GATE_DISABLE		(1 << 8)
+# define I915_SH_SV_CLOCK_GATE_DISABLE		(1 << 7)
+# define I915_PL_DG_QC_FT_CLOCK_GATE_DISABLE	(1 << 6)
+# define I915_SC_CLOCK_GATE_DISABLE		(1 << 5)
+# define I915_FL_CLOCK_GATE_DISABLE		(1 << 4)
+# define I915_DM_CLOCK_GATE_DISABLE		(1 << 3)
+# define I915_PS_CLOCK_GATE_DISABLE		(1 << 2)
+# define I915_CC_CLOCK_GATE_DISABLE		(1 << 1)
+# define I915_BY_CLOCK_GATE_DISABLE		(1 << 0)
+
+# define I965_RCZ_CLOCK_GATE_DISABLE		(1 << 30)
+/** This bit must always be set on 965G/965GM */
+# define I965_RCC_CLOCK_GATE_DISABLE		(1 << 29)
+# define I965_RCPB_CLOCK_GATE_DISABLE		(1 << 28)
+# define I965_DAP_CLOCK_GATE_DISABLE		(1 << 27)
+# define I965_ROC_CLOCK_GATE_DISABLE		(1 << 26)
+# define I965_GW_CLOCK_GATE_DISABLE		(1 << 25)
+# define I965_TD_CLOCK_GATE_DISABLE		(1 << 24)
+/** This bit must always be set on 965G */
+# define I965_ISC_CLOCK_GATE_DISABLE		(1 << 23)
+# define I965_IC_CLOCK_GATE_DISABLE		(1 << 22)
+# define I965_EU_CLOCK_GATE_DISABLE		(1 << 21)
+# define I965_IF_CLOCK_GATE_DISABLE		(1 << 20)
+# define I965_TC_CLOCK_GATE_DISABLE		(1 << 19)
+# define I965_SO_CLOCK_GATE_DISABLE		(1 << 17)
+# define I965_FBC_CLOCK_GATE_DISABLE		(1 << 16)
+# define I965_MARI_CLOCK_GATE_DISABLE		(1 << 15)
+# define I965_MASF_CLOCK_GATE_DISABLE		(1 << 14)
+# define I965_MAWB_CLOCK_GATE_DISABLE		(1 << 13)
+# define I965_EM_CLOCK_GATE_DISABLE		(1 << 12)
+# define I965_UC_CLOCK_GATE_DISABLE		(1 << 11)
+# define I965_SI_CLOCK_GATE_DISABLE		(1 << 6)
+# define I965_MT_CLOCK_GATE_DISABLE		(1 << 5)
+# define I965_PL_CLOCK_GATE_DISABLE		(1 << 4)
+# define I965_DG_CLOCK_GATE_DISABLE		(1 << 3)
+# define I965_QC_CLOCK_GATE_DISABLE		(1 << 2)
+# define I965_FT_CLOCK_GATE_DISABLE		(1 << 1)
+# define I965_DM_CLOCK_GATE_DISABLE		(1 << 0)
+
 #define RENCLK_GATE_D2		0x6208
 #define RAMCLK_GATE_D		0x6210		/* CRL only */
 
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 2c1e514..235ee2a 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1653,6 +1653,19 @@ SetHWOperatingState(ScrnInfoPtr pScrn)
 
    DPRINTF(PFX, "SetHWOperatingState\n");
 
+   /* Disable clock gating reported to work incorrectly according to the specs.
+    */
+   if (IS_I965GM(pI830)) {
+      OUTREG(RENCLK_GATE_D1, I965_RCC_CLOCK_GATE_DISABLE);
+   } else if (IS_I965G(pI830)) {
+      OUTREG(RENCLK_GATE_D1,
+	     I965_RCC_CLOCK_GATE_DISABLE | I965_ISC_CLOCK_GATE_DISABLE);
+   } else if (IS_I855(pI830) || IS_I865G(pI830)) {
+      OUTREG(RENCLK_GATE_D1, SV_CLOCK_GATE_DISABLE);
+   } else if (IS_I830(pI830)) {
+      OUTREG(DSPCLK_GATE_D, OVRUNIT_CLOCK_GATE_DISABLE);
+   }
+
    if (!pI830->noAccel)
       SetRingRegs(pScrn);
    SetFenceRegs(pScrn);
diff-tree 138ac8f36cb4e4b3776f313955372522646acbb2 (from 0cd524e5411e35c8483c02ecc5062625809e6fc6)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Sun Apr 29 14:43:19 2007 +0800

    Alloc state mem buffer on 965G for xaa rotation
    
    965G needs state mem buffer to setup render pipeline.
    Thanks Barry Scrott for report this.

diff --git a/src/i830_memory.c b/src/i830_memory.c
index 15d241b..268d6c5 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -957,20 +957,18 @@ i830_allocate_2d_memory(ScrnInfoPtr pScr
 		   "Failed to allocate logical context space.\n");
 	return FALSE;
     }
-#ifdef I830_USE_EXA
-    if (pI830->useEXA) {
-	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, 0);
-	    if (pI830->exa_965_state == NULL) {
-		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-			   "Failed to allocate exa state buffer for 965.\n");
-		return FALSE;
-	    }
+
+    /* even in XAA, 965G needs state mem buffer for rendering */
+    if (IS_I965G(pI830) && !pI830->noAccel && pI830->exa_965_state == NULL) {
+	pI830->exa_965_state =
+	    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_WARNING,
+		    "Failed to allocate exa state buffer for 965.\n");
+	    return FALSE;
 	}
     }
-#endif
 
 #ifdef I830_XV
     /* Allocate overlay register space and optional XAA linear allocator
diff-tree 0cd524e5411e35c8483c02ecc5062625809e6fc6 (from 880314aabe6326ed56517034940f0e10fb16e866)
Author: Kristian Høgsberg <krh at redhat.com>
Date:   Wed Apr 25 18:09:10 2007 -0400

    Implement the custom I2C protocol used by the ivch DVO.
    
    The ihch DVO uses a modified I2C addressing scheme as described
    in section 5.2 of the data sheet.  Implement this by over-riding
    the I2C read and write word routines.

diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index 0bb25bd..4b37228 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -45,13 +45,11 @@ static const char *CH7xxxSymbols[] = {
     "CH7xxxVidOutput",
     NULL
 };
-
-#if 0
 static const char *ivch_symbols[] = {
     "ivch_methods",
     NULL
 };
-#endif
+
 #if 0
 static const char *ch7017_symbols[] = {
     "ch7017_methods",
@@ -66,9 +64,9 @@ struct _I830DVODriver i830_dvo_drivers[]
      (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_LVDS, "ivch", "ivch_methods",
      0x04, ivch_symbols, NULL, NULL, NULL},
+    /*
     {I830_DVO_CHIP_LVDS, "ivch", "ivch_methods",
      0x44, ivch_symbols, NULL, NULL, NULL},
     {I830_DVO_CHIP_LVDS, "ivch", "ivch_methods",
diff --git a/src/ivch/ivch.c b/src/ivch/ivch.c
index 71f41f5..efc74f8 100644
--- a/src/ivch/ivch.c
+++ b/src/ivch/ivch.c
@@ -60,26 +60,69 @@ ivch_dump_regs(I2CDevPtr d);
 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;
-    }
+    I2CBusPtr b = priv->d.pI2CBus;
+    I2CByte *p = (I2CByte *) data;
+
+    if (!b->I2CStart(b, priv->d.StartTimeout))
+	goto fail;
+
+    if (!b->I2CPutByte(&priv->d, priv->d.SlaveAddr | 1))
+	goto fail;
+
+    if (!b->I2CPutByte(&priv->d, addr))
+	goto fail;
+
+    if (!b->I2CGetByte(&priv->d, p++, FALSE))
+	goto fail;
+
+    if (!b->I2CGetByte(&priv->d, p++, TRUE))
+	goto fail;
+
+    b->I2CStop(&priv->d);
+
     return TRUE;
-}
 
+ fail:
+    xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_ERROR,
+	       "ivch: Unable to read register 0x%02x from %s:%02x.\n",
+	       addr, priv->d.pI2CBus->BusName, priv->d.SlaveAddr);
+    b->I2CStop(&priv->d);
+
+    return FALSE;
+}
+ 
 /** 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;
-    }
+    I2CBusPtr b = priv->d.pI2CBus;
+
+    if (!b->I2CStart(b, priv->d.StartTimeout))
+	goto fail;
+
+    if (!b->I2CPutByte(&priv->d, priv->d.SlaveAddr))
+	goto fail;
+
+    if (!b->I2CPutByte(&priv->d, addr))
+	goto fail;
+
+    if (!b->I2CPutByte(&priv->d, data & 0xff))
+	goto fail;
+
+    if (!b->I2CPutByte(&priv->d, data >> 8))
+	goto fail;
+
+    b->I2CStop(&priv->d);
+
     return TRUE;
+
+ fail:
+    b->I2CStop(&priv->d);
+    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;
 }
 
 /** Probes the given bus and slave address for an ivch */
@@ -104,18 +147,18 @@ ivch_init(I2CBusPtr b, I2CSlaveAddr addr
     priv->d.ByteTimeout = b->ByteTimeout;
     priv->d.DriverPrivate.ptr = priv;
 
-    if (!xf86I2CReadWord(&priv->d, VR00, &temp))
+    if (!ivch_read(priv, 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) {
+    if ((temp & VR00_BASE_ADDRESS_MASK) != (priv->d.SlaveAddr >> 1)) {
 	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);
+		   (temp & VR00_BASE_ADDRESS_MASK), priv->d.SlaveAddr >> 1);
     }
 
     if (!xf86I2CDevInit(&priv->d)) {
diff-tree 880314aabe6326ed56517034940f0e10fb16e866 (from b23eae55c8cdd73e0aba1bf7ced283d402ee6470)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Tue Apr 24 11:37:08 2007 -0700

    CRTC Rotation under XAA wasn't hitting accelerated path.
    
    The server rotation code is now using the root window in IncludeInferiors
    mode rather than using the screen pixmap. Change the XAA Composite code
    to check for this case now.

diff --git a/src/i830_xaa.c b/src/i830_xaa.c
index 3440341..790299c 100644
--- a/src/i830_xaa.c
+++ b/src/i830_xaa.c
@@ -782,12 +782,12 @@ i830_xaa_composite(CARD8	op,
     if (pMask != NULL || op != PictOpSrc || pSrc->pDrawable == NULL)
 	goto fallback;
 
-    if (pSrc->pDrawable->type != DRAWABLE_PIXMAP ||
+    if (pSrc->pDrawable->type != DRAWABLE_WINDOW ||
 	pDst->pDrawable->type != DRAWABLE_PIXMAP)
     {
 	goto fallback;
     }
-    pSrcPixmap = (PixmapPtr)pSrc->pDrawable;
+    pSrcPixmap = (*pScreen->GetWindowPixmap) ((WindowPtr) pSrc->pDrawable);
     pDstPixmap = (PixmapPtr)pDst->pDrawable;
 
     /* Check if the dest is one of our shadow pixmaps */
diff-tree b23eae55c8cdd73e0aba1bf7ced283d402ee6470 (from parents)
Merge: 31bf269afed0a830e79cbbd9d4b1ee9843af326c cebdb8bfc6170a0fb441039f4422917fd0c77e70
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Apr 19 20:38:18 2007 -0700

    Merge branch 'origin'

diff-tree 31bf269afed0a830e79cbbd9d4b1ee9843af326c (from 60e891915af7d0f522c9c3f966599fa07779f7aa)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Apr 19 20:03:41 2007 -0700

    Update version to 2.0.0

diff --git a/configure.ac b/configure.ac
index a06d3e4..da9fd3f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -22,7 +22,7 @@
 
 AC_PREREQ(2.57)
 AC_INIT([xf86-video-intel],
-        1.9.94,
+        2.0.0,
         [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
         xf86-video-intel)
 
diff-tree cebdb8bfc6170a0fb441039f4422917fd0c77e70 (from cca389769001c657435f056e1f1c26b0f52a48bd)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Fri Apr 20 10:54:34 2007 +0800

    EXA: set enabling bits properly for i830
    
    This was found when debug exa on a 865GV, we should set
    pipeline state bits properly, otherwise the engine will hang.

diff --git a/src/i830_render.c b/src/i830_render.c
index 36d41f3..077afa1 100644
--- a/src/i830_render.c
+++ b/src/i830_render.c
@@ -515,9 +515,16 @@ i830_prepare_composite(int op, PicturePt
 	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(8) | 0);
 	OUT_RING(S8_ENABLE_COLOR_BLEND | S8_BLENDFUNC_ADD | blendctl | 
 		 S8_ENABLE_COLOR_BUFFER_WRITE);
+
+	OUT_RING(_3DSTATE_ENABLES_1_CMD | DISABLE_LOGIC_OP | 
+		DISABLE_STENCIL_TEST | DISABLE_DEPTH_BIAS | 
+		DISABLE_SPEC_ADD | DISABLE_FOG | DISABLE_ALPHA_TEST | 
+		ENABLE_COLOR_BLEND | DISABLE_DEPTH_TEST);
 	/* We have to explicitly say we don't want write disabled */
-	OUT_RING(_3DSTATE_ENABLES_2_CMD | ENABLE_COLOR_MASK);
-	OUT_RING(MI_NOOP); 
+	OUT_RING(_3DSTATE_ENABLES_2_CMD | ENABLE_COLOR_MASK |
+		DISABLE_STENCIL_WRITE | ENABLE_TEX_CACHE |
+		DISABLE_DITHER | ENABLE_COLOR_WRITE |
+		DISABLE_DEPTH_WRITE);
 	ADVANCE_LP_RING();
     }
 
diff-tree 60e891915af7d0f522c9c3f966599fa07779f7aa (from cca389769001c657435f056e1f1c26b0f52a48bd)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Apr 19 14:02:23 2007 -0700

    Eliminate LinearAlloc option and code.
    
    With the fixes to the 2D frame buffer allocation that allows up to 65536
    lines of 2D frame buffer in XAA mode, the old linear allocation hacks are no
    longer necessary.

diff --git a/man/intel.man b/man/intel.man
index 5ce31ea..178ff0a 100644
--- a/man/intel.man
+++ b/man/intel.man
@@ -121,12 +121,6 @@ other drivers.
 Disable or enable XVideo support.
 Default: XVideo is enabled for configurations where it is supported.
 .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
diff --git a/src/i830.h b/src/i830.h
index 4cb31b6..d81857b 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -298,9 +298,7 @@ typedef struct _I830Rec {
 #ifdef I830_XV
    /* For Xvideo */
    i830_memory *overlay_regs;
-   i830_memory *xaa_linear;
 #endif
-   unsigned long LinearAlloc;
    XF86ModReqInfo shadowReq; /* to test for later libshadow */
    Rotation rotation;
    void (*PointerMoved)(int, int, int);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index e3bf330..2c1e514 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -274,7 +274,6 @@ typedef enum {
    OPTION_VIDEO_KEY,
    OPTION_COLOR_KEY,
    OPTION_CHECKDEVICES,
-   OPTION_LINEARALLOC,
    OPTION_MODEDEBUG,
 #ifdef XF86DRI_MM
    OPTION_INTELTEXPOOL,
@@ -296,7 +295,6 @@ static OptionInfoRec I830Options[] = {
    {OPTION_COLOR_KEY,	"ColorKey",	OPTV_INTEGER,	{0},	FALSE},
    {OPTION_VIDEO_KEY,	"VideoKey",	OPTV_INTEGER,	{0},	FALSE},
    {OPTION_CHECKDEVICES, "CheckDevices",OPTV_BOOLEAN,	{0},	FALSE},
-   {OPTION_LINEARALLOC, "LinearAlloc",  OPTV_INTEGER,   {0},    FALSE},
    {OPTION_MODEDEBUG,	"ModeDebug",	OPTV_BOOLEAN,	{0},	FALSE},
 #ifdef XF86DRI_MM
    {OPTION_INTELTEXPOOL,"Legacy3D",     OPTV_BOOLEAN,	{0},	FALSE},
@@ -1300,13 +1298,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    
 #endif
 
-   pI830->LinearAlloc = 0;
-   if (xf86GetOptValULong(pI830->Options, OPTION_LINEARALLOC,
-			    &(pI830->LinearAlloc))) {
-      if (pI830->LinearAlloc < 0)
-         pI830->LinearAlloc = 0;
-   }
-
    I830PreInitDDC(pScrn);
    for (i = 0; i < num_pipe; i++) {
        i830_crtc_init(pScrn, i);
@@ -2544,17 +2535,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		       "Failed to init memory manager\n");
 	 }
-
-	 if (pI830->xaa_linear != NULL &&
-	     xf86InitFBManagerLinear(pScreen,
-				     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->xaa_linear->size,
-		       pI830->xaa_linear->offset);
-	 }
       } else {
 	 if (!I830InitFBManager(pScreen, &(pI8301->FbMemBox2))) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 20b33bc..15d241b 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -230,7 +230,6 @@ i830_reset_allocations(ScrnInfoPtr pScrn
     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->third_buffer = NULL;
@@ -663,16 +662,6 @@ i830_allocate_overlay(ScrnInfoPtr pScrn)
 	}
     }
 
-    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) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		       "Failed to allocate linear buffer space\n");
-	}
-    }
-
     return TRUE;
 }
 #endif
diff-tree cca389769001c657435f056e1f1c26b0f52a48bd (from 07797fee88d6be0dfb30394a419dd86f8a3c9095)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Apr 19 13:15:23 2007 -0700

    Clean up 1.2 xserver build support.
    
    Convert relative X server source path to absolute.  Check for local copies
    of needed header files before building, rather than requiring server source.
    Remove extra duplicate -I elements in AM_CFLAGS in sub directories.

diff --git a/configure.ac b/configure.ac
index 2d26553..a06d3e4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -131,19 +131,14 @@ if test "x$XSERVER_SOURCE" = x; then
 	fi
 fi
 	
-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
-		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
+	case "$XSERVER_SOURCE" in
+	/*)
+		;;
+	*)
+		XSERVER_SOURCE="`cd $XSERVER_SOURCE && pwd`"
+		;;
+	esac
 	if test -f src/modes/xf86Modes.h; then
 		:
 	else
@@ -156,6 +151,20 @@ if test -d "$XSERVER_SOURCE"; then
 		ln -sf $XSERVER_SOURCE/hw/xfree86/parser src/parser
 	fi
 fi
+
+if test "x$XMODES" = xyes; then
+	AC_MSG_NOTICE([X server has new mode code])
+	AC_DEFINE(XMODES, 1,[X server has built-in mode code])
+	XMODES_CFLAGS=
+else
+	if test -f src/modes/xf86Modes.h -a -f src/parser/xf86Parser.h; then
+		AC_MSG_NOTICE([X server is missing new mode code, using local copy])
+	else
+		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 -I$(top_srcdir)/src/modes -I$(top_srcdir)/src/parser'
+fi
+
 AC_SUBST([XMODES_CFLAGS])
 
 dnl Use lots of warning flags with GCC
diff --git a/src/ch7017/Makefile.am b/src/ch7017/Makefile.am
index 9858941..71c5085 100644
--- a/src/ch7017/Makefile.am
+++ b/src/ch7017/Makefile.am
@@ -3,8 +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 = @WARN_CFLAGS@ @XMODES_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@ \
-	-I$(srcdir)/.. -I$(srcdir)/../modes
+AM_CFLAGS = @WARN_CFLAGS@ @XMODES_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@
 
 ch7017_la_LTLIBRARIES = ch7017.la
 ch7017_la_LDFLAGS = -module -avoid-version
diff --git a/src/ch7xxx/Makefile.am b/src/ch7xxx/Makefile.am
index 49a5aa3..fdf6e9e 100644
--- a/src/ch7xxx/Makefile.am
+++ b/src/ch7xxx/Makefile.am
@@ -3,8 +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 = @WARN_CFLAGS@ @XMODES_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@ \
-	-I$(srcdir)/.. -I$(srcdir)/../modes
+AM_CFLAGS = @WARN_CFLAGS@ @XMODES_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@
 
 ch7xxx_la_LTLIBRARIES = ch7xxx.la
 ch7xxx_la_LDFLAGS = -module -avoid-version
diff --git a/src/ivch/Makefile.am b/src/ivch/Makefile.am
index cf05c01..1dc9cb3 100644
--- a/src/ivch/Makefile.am
+++ b/src/ivch/Makefile.am
@@ -3,8 +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 = @WARN_CFLAGS@ @XMODES_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@ \
-	-I$(srcdir)/.. -I$(srcdir)/../modes
+AM_CFLAGS = @WARN_CFLAGS@ @XMODES_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@
 
 ivch_la_LTLIBRARIES = ivch.la
 ivch_la_LDFLAGS = -module -avoid-version
diff --git a/src/sil164/Makefile.am b/src/sil164/Makefile.am
index de17bd0..497ee9f 100644
--- a/src/sil164/Makefile.am
+++ b/src/sil164/Makefile.am
@@ -3,8 +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 = @WARN_CFLAGS@ @XMODES_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@ \
-	-I$(srcdir)/.. -I$(srcdir)/../modes
+AM_CFLAGS = @WARN_CFLAGS@ @XMODES_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@
 
 sil164_la_LTLIBRARIES = sil164.la
 sil164_la_LDFLAGS = -module -avoid-version
diff-tree 07797fee88d6be0dfb30394a419dd86f8a3c9095 (from 163c565527e8cda1f5a47c7fd63f04c80feaf3c7)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Apr 19 13:01:37 2007 -0700

    Fix mismatching braces when XF86DRI_MM is not defined.
    
    A closing brace was left inside #ifdef XF86DRI_MM while the matching
    open brace was outside.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index c857498..e3bf330 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1294,8 +1294,8 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 		    "Will try to reserve %d kiB of AGP aperture space\n"
 		    "\tfor the DRM memory manager.\n",
 		    pI830->mmSize);
-      }
 #endif
+      }
    } 
    
 #endif
diff-tree 163c565527e8cda1f5a47c7fd63f04c80feaf3c7 (from 378ceea3d9ddbec7a08ac2f07f9a8cd9cf3cef36)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Apr 19 13:00:03 2007 -0700

    Use I2C delay function instead of usleep.
    
    usleep isn't always available, and we have an existing delay mechanism
    available to use.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index e1a4a44..43b55a0 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -302,7 +302,7 @@ i830_sdvo_read_response(xf86OutputPtr ou
 	if (status != SDVO_CMD_STATUS_PENDING)
 	    return status;
 
-        usleep(50);
+        intel_output->pI2CBus->I2CUDelay(intel_output->pI2CBus, 50);
     }
 
     return status;
diff-tree 378ceea3d9ddbec7a08ac2f07f9a8cd9cf3cef36 (from db4b9e18810990e8900bdf54aa3091b876ea2658)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Thu Apr 19 17:30:28 2007 +0800

    Fix mem list order and remove extra unbind call when free memory

diff --git a/src/i830_memory.c b/src/i830_memory.c
index 315f4ba..20b33bc 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -184,8 +184,6 @@ i830_free_memory(ScrnInfoPtr pScrn, i830
     if (mem == NULL)
 	return;
 
-    i830_unbind_memory(pScrn, mem);
-
     /* Disconnect from the list of allocations */
     if (mem->prev != NULL)
 	mem->prev->next = mem->next;
@@ -368,7 +366,7 @@ i830_allocate_aperture(ScrnInfoPtr pScrn
     mem->prev = scan;
     mem->next = scan->next;
     scan->next = mem;
-    mem->next->prev = scan;
+    mem->next->prev = mem;
 
     return mem;
 }
diff-tree db4b9e18810990e8900bdf54aa3091b876ea2658 (from 3f5111940e35989d334aa99cd1b0eb26293ebf1b)
Author: Alan Hourihane <alanh at fairlite.demon.co.uk>
Date:   Wed Apr 18 13:52:08 2007 +0100

    Fix return status

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 53a6ece..e1a4a44 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -305,7 +305,7 @@ i830_sdvo_read_response(xf86OutputPtr ou
         usleep(50);
     }
 
-    return SDVO_CMD_STATUS_SUCCESS;
+    return status;
 }
 
 int
diff-tree 3f5111940e35989d334aa99cd1b0eb26293ebf1b (from 902388fa06f85486fe8010807ab53e4926cc979a)
Author: Alan Hourihane <alanh at fairlite.demon.co.uk>
Date:   Wed Apr 18 13:27:59 2007 +0100

    Update read_response to include the try on PENDING status
    
    and remove it from get attached displays call.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index cf72848..53a6ece 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -271,33 +271,41 @@ i830_sdvo_read_response(xf86OutputPtr ou
     I830OutputPrivatePtr    intel_output = output->driver_private;
     int			    i;
     CARD8		    status;
+    CARD8		    retry = 50;
 
-    /* Read the command response */
-    for (i = 0; i < response_len; i++) {
-	i830_sdvo_read_byte(output, SDVO_I2C_RETURN_0 + i,
+    while (retry--) {
+    	/* 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);
+    	/* Read the return status */
+    	i830_sdvo_read_byte(output, SDVO_I2C_CMD_STATUS, &status);
 
-    /* Write the SDVO command logging */
-    if (pI830->debug_modes) {
-	xf86DrvMsg(intel_output->pI2CBus->scrnIndex, X_INFO,
+    	/* Write the SDVO command logging */
+    	if (pI830->debug_modes) {
+	    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++)
-	    LogWrite(1, "   ");
-	if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP) {
-	    LogWrite(1, "(%s)", cmd_status_names[status]);
-	} else {
-	    LogWrite(1, "(??? %d)", status);
-	}
-	LogWrite(1, "\n");
+	    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) {
+	    	LogWrite(1, "(%s)", cmd_status_names[status]);
+	    } else {
+	    	LogWrite(1, "(??? %d)", status);
+	    }
+	    LogWrite(1, "\n");
+    	}
+
+	if (status != SDVO_CMD_STATUS_PENDING)
+	    return status;
+
+        usleep(50);
     }
 
-    return status;
+    return SDVO_CMD_STATUS_SUCCESS;
 }
 
 int
@@ -1074,19 +1082,12 @@ i830_sdvo_detect(xf86OutputPtr output)
 {
     CARD8 response[2];
     CARD8 status;
-    CARD8 retry = 50;
 
     i830_sdvo_write_cmd(output, SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0);
+    status = i830_sdvo_read_response(output, &response, 2);
 
-    while (retry--) {
-    	status = i830_sdvo_read_response(output, &response, 2);
-
-	if (status == SDVO_CMD_STATUS_SUCCESS)
-	    break;
-    
-    	if (status != SDVO_CMD_STATUS_PENDING)
-	    return XF86OutputStatusUnknown;
-    }
+    if (status != SDVO_CMD_STATUS_SUCCESS)
+	return XF86OutputStatusUnknown;
 
     if (response[0] != 0 || response[1] != 0)
 	return XF86OutputStatusConnected;
diff-tree 902388fa06f85486fe8010807ab53e4926cc979a (from 8abecae202b609375b6754dbd5ecce3d59036daf)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Apr 17 14:21:25 2007 -0700

    Don't try to init the XAA linear region unless we allocated memory for it.
    
    Reported by JM Ibanez

diff --git a/src/i830_driver.c b/src/i830_driver.c
index f0ca973..c857498 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2545,7 +2545,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 		       "Failed to init memory manager\n");
 	 }
 
-	 if (pI830->LinearAlloc &&
+	 if (pI830->xaa_linear != NULL &&
 	     xf86InitFBManagerLinear(pScreen,
 				     pI830->xaa_linear->offset / pI830->cpp,
 				     pI830->xaa_linear->size / pI830->cpp))
diff-tree 8abecae202b609375b6754dbd5ecce3d59036daf (from 2dbe8d678b02b724c4f06255383f49bb4c2708b0)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Apr 17 12:28:43 2007 -0700

    Fix i852 EXA Composite acceleration setup.
    
    Reported by JM Ibanez.

diff --git a/src/i830_exa.c b/src/i830_exa.c
index dfc8f99..1741732 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -487,9 +487,7 @@ I830EXAInit(ScreenPtr pScreen)
     pI830->EXADriverPtr->DoneCopy = I830EXADoneCopy;
 
     /* Composite */
-    if (IS_I865G(pI830) || IS_I855(pI830) ||
-	       IS_845G(pI830) || IS_I830(pI830))
-    {
+    if (!IS_I9XX(pI830)) {
     	pI830->EXADriverPtr->CheckComposite = i830_check_composite;
     	pI830->EXADriverPtr->PrepareComposite = i830_prepare_composite;
     	pI830->EXADriverPtr->Composite = i830_composite;
diff-tree 2dbe8d678b02b724c4f06255383f49bb4c2708b0 (from a089ac11beb4c801928c17780401e913bc0d5257)
Author: Timo Aaltonen <tjaalton at cc.hut.fi>
Date:   Mon Apr 16 14:14:19 2007 -0700

    Fix build against xserver 1.2.

diff --git a/src/ch7017/Makefile.am b/src/ch7017/Makefile.am
index d757b3c..9858941 100644
--- a/src/ch7017/Makefile.am
+++ b/src/ch7017/Makefile.am
@@ -3,9 +3,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 = @XMODES_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@ -I$(srcdir)/.. -I$(srcdir)/../modes
-
-AM_CFLAGS = @WARN_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@ @XMODES_CFLAGS@
+AM_CFLAGS = @WARN_CFLAGS@ @XMODES_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@ \
+	-I$(srcdir)/.. -I$(srcdir)/../modes
 
 ch7017_la_LTLIBRARIES = ch7017.la
 ch7017_la_LDFLAGS = -module -avoid-version
diff-tree a089ac11beb4c801928c17780401e913bc0d5257 (from 37ee68a95ca8c86ebe9abafaaf55b060dd2a2f73)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Apr 17 11:01:05 2007 -0700

    Add all the possible ivch slave addresses (still commented out).

diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index 04750e5..0bb25bd 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -68,7 +68,13 @@ struct _I830DVODriver i830_dvo_drivers[]
      (CH7xxx_ADDR_1<<1), CH7xxxSymbols, NULL , NULL, NULL},
     /*
     {I830_DVO_CHIP_LVDS, "ivch", "ivch_methods",
-     (0x2 << 1), ivch_symbols, NULL, NULL, NULL},
+     0x04, ivch_symbols, NULL, NULL, NULL},
+    {I830_DVO_CHIP_LVDS, "ivch", "ivch_methods",
+     0x44, ivch_symbols, NULL, NULL, NULL},
+    {I830_DVO_CHIP_LVDS, "ivch", "ivch_methods",
+     0x84, ivch_symbols, NULL, NULL, NULL},
+    {I830_DVO_CHIP_LVDS, "ivch", "ivch_methods",
+     0xc4, ivch_symbols, NULL, NULL, NULL},
     */
     /*
     { I830_DVO_CHIP_LVDS, "ch7017", "ch7017_methods",
diff-tree 37ee68a95ca8c86ebe9abafaaf55b060dd2a2f73 (from ac9181c014638dbeb334b40b4029d0ccb2b7a0fc)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Apr 17 10:50:02 2007 -0700

    Bug #10438: Fix 965 XV when sourcing from less than the full image.
    
    Bob deinterlacing in MythTV, and the zoom options in totem would result in
    attempting to source from outside the video instead of scaling appropriately.

diff --git a/src/i965_video.c b/src/i965_video.c
index 9e96527..17d2006 100644
--- a/src/i965_video.c
+++ b/src/i965_video.c
@@ -172,6 +172,7 @@ I965DisplayVideoTextured(ScrnInfoPtr pSc
     struct brw_instruction *ps_kernel;
     struct brw_instruction *sip_kernel;
     float *vb;
+    float src_scale_x, src_scale_y;
     CARD32 *binding_table;
     Bool first_output = TRUE;
     int dest_surf_offset, src_surf_offset, src_sampler_offset, vs_offset;
@@ -672,6 +673,10 @@ I965DisplayVideoTextured(ScrnInfoPtr pSc
     dxo = dstRegion->extents.x1;
     dyo = dstRegion->extents.y1;
 
+    /* Use normalized texture coordinates */
+    src_scale_x = ((float)src_w / width) / (float)drw_w;
+    src_scale_y = ((float)src_h / height) / (float)drw_h;
+
     pbox = REGION_RECTS(dstRegion);
     nbox = REGION_NUM_RECTS(dstRegion);
     while (nbox--) {
@@ -680,7 +685,6 @@ I965DisplayVideoTextured(ScrnInfoPtr pSc
 	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
@@ -691,10 +695,6 @@ I965DisplayVideoTextured(ScrnInfoPtr pSc
 
 	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;
diff-tree ac9181c014638dbeb334b40b4029d0ccb2b7a0fc (from ab5bdee8a62c842ae32aaef57eb841ebcb644d2b)
Author: Alan Hourihane <alanh at fairlite.demon.co.uk>
Date:   Tue Apr 17 16:30:17 2007 +0100

    Check for the PENDING message when reading the attached
    displays. Ensures the command has completed before continuing.
    
    (probably need to check PENDING in other SDVO calls too)

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index f0723a9..cf72848 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -1074,12 +1074,19 @@ i830_sdvo_detect(xf86OutputPtr output)
 {
     CARD8 response[2];
     CARD8 status;
+    CARD8 retry = 50;
 
     i830_sdvo_write_cmd(output, SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0);
-    status = i830_sdvo_read_response(output, &response, 2);
 
-    if (status != SDVO_CMD_STATUS_SUCCESS)
-	return XF86OutputStatusUnknown;
+    while (retry--) {
+    	status = i830_sdvo_read_response(output, &response, 2);
+
+	if (status == SDVO_CMD_STATUS_SUCCESS)
+	    break;
+    
+    	if (status != SDVO_CMD_STATUS_PENDING)
+	    return XF86OutputStatusUnknown;
+    }
 
     if (response[0] != 0 || response[1] != 0)
 	return XF86OutputStatusConnected;
diff --git a/src/i830_sdvo_regs.h b/src/i830_sdvo_regs.h
index 437ff50..72e58a0 100644
--- a/src/i830_sdvo_regs.h
+++ b/src/i830_sdvo_regs.h
@@ -38,7 +38,11 @@
 #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_RGB1    (1 << 9)
+#define SDVO_OUTPUT_CVBS1   (1 << 10)
+#define SDVO_OUTPUT_SVID1   (1 << 11)
+#define SDVO_OUTPUT_YPRPB1  (1 << 12)
+#define SDVO_OUTPUT_SCART1  (1 << 13)
 #define SDVO_OUTPUT_LVDS1   (1 << 14)
 #define SDVO_OUTPUT_LAST    (14)
 
diff-tree ab5bdee8a62c842ae32aaef57eb841ebcb644d2b (from 1a29750b8dba1371d7d0802744cdf2f3bfa83c13)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Tue Apr 17 16:23:46 2007 +0800

    EXA: fix i830 render
    
    Fix tex blend pipeline in case that src/mask pict has no
    alpha. Unmask color buffer write disable bits. These make
    rendercheck run fine on 855GM.

diff --git a/src/i830_render.c b/src/i830_render.c
index ec80c0b..36d41f3 100644
--- a/src/i830_render.c
+++ b/src/i830_render.c
@@ -83,6 +83,7 @@ struct formatinfo {
 #define TB0C_ARG2_SEL_TEXEL3		(9 << 12)
 #define TB0C_ARG1_REPLICATE_ALPHA 	(1<<11)
 #define TB0C_ARG1_INVERT		(1<<10)
+#define TB0C_ARG1_SEL_ONE		(0 << 6)
 #define TB0C_ARG1_SEL_TEXEL0		(6 << 6)
 #define TB0C_ARG1_SEL_TEXEL1		(7 << 6)
 #define TB0C_ARG1_SEL_TEXEL2		(8 << 6)
@@ -107,6 +108,7 @@ struct formatinfo {
 #define TB0A_ARG2_SEL_TEXEL2		(8 << 12)
 #define TB0A_ARG2_SEL_TEXEL3		(9 << 12)
 #define TB0A_ARG1_INVERT		(1<<10)
+#define TB0A_ARG1_SEL_ONE		(0 << 6)
 #define TB0A_ARG1_SEL_TEXEL0		(6 << 6)
 #define TB0A_ARG1_SEL_TEXEL1		(7 << 6)
 #define TB0A_ARG1_SEL_TEXEL2		(8 << 6)
@@ -418,7 +420,7 @@ i830_prepare_composite(int op, PicturePt
     {
 	CARD32 cblend, ablend, blendctl, vf2;
 
-	BEGIN_LP_RING(26);
+	BEGIN_LP_RING(30);
 
 	/* color buffer */
 	OUT_RING(_3DSTATE_BUF_INFO_CMD);
@@ -455,16 +457,28 @@ i830_prepare_composite(int op, PicturePt
 	OUT_RING(vf2); /* TEXCOORDFMT_2D */
 	OUT_RING(S3_CULLMODE_NONE | S3_VERTEXHAS_XY);
 
-	/* For (src In mask) operation */
-	/* IN operator: Multiply src by mask components or mask alpha.*/
-	/* TEXBLENDOP_MODULE: arg1*arg2 */
+	/* We use two pipes for color and alpha, and do (src In mask)
+	   in one stage. Arg1 is from src pict, and arg2 is from mask pict.
+	   Be sure to force 1.0 when src or mask pict has no alpha channel.
+	 */
 	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 (PICT_FORMAT_A(pSrcPicture->format) != 0) {
+	    ablend |= TB0A_ARG1_SEL_TEXEL0;
+	    cblend |= TB0C_ARG1_SEL_TEXEL0;
+	} else {
+	    ablend |= TB0A_ARG1_SEL_ONE;
+	    if (pMask && pMaskPicture->componentAlpha 
+		    && PICT_FORMAT_RGB(pMaskPicture->format)
+		    && i830_blend_op[op].src_alpha)
+		cblend |= TB0C_ARG1_SEL_ONE;
+	    else
+		cblend |= TB0C_ARG1_SEL_TEXEL0;
+	}
+
 	if (pMask) {
 	    if (pMaskPicture->componentAlpha && 
 		    PICT_FORMAT_RGB(pMaskPicture->format)) {
@@ -474,10 +488,16 @@ i830_prepare_composite(int op, PicturePt
 		else 
 		    cblend |= TB0C_ARG2_SEL_TEXEL1;
 	    } else {
-		cblend |= (TB0C_ARG2_SEL_TEXEL1 | 
-			TB0C_ARG2_REPLICATE_ALPHA);
+		if (PICT_FORMAT_A(pMaskPicture->format) != 0)
+		    cblend |= (TB0C_ARG2_SEL_TEXEL1 | 
+			    TB0C_ARG2_REPLICATE_ALPHA);
+		else
+		    cblend |= TB0C_ARG2_SEL_ONE;
 	    }
-	    ablend |= TB0A_ARG2_SEL_TEXEL1;
+	    if (PICT_FORMAT_A(pMaskPicture->format) != 0)
+		ablend |= TB0A_ARG2_SEL_TEXEL1;
+	    else
+		ablend |= TB0A_ARG2_SEL_ONE;
 	} else {
 	    cblend |= TB0C_ARG2_SEL_ONE;
 	    ablend |= TB0A_ARG2_SEL_ONE;
@@ -490,9 +510,14 @@ i830_prepare_composite(int op, PicturePt
 	OUT_RING(0);
 
 	blendctl = i830_get_blend_cntl(op, pMaskPicture, pDstPicture->format);
+	OUT_RING(_3DSTATE_INDPT_ALPHA_BLEND_CMD | DISABLE_INDPT_ALPHA_BLEND);
+	OUT_RING(MI_NOOP);
 	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(8) | 0);
 	OUT_RING(S8_ENABLE_COLOR_BLEND | S8_BLENDFUNC_ADD | blendctl | 
 		 S8_ENABLE_COLOR_BUFFER_WRITE);
+	/* We have to explicitly say we don't want write disabled */
+	OUT_RING(_3DSTATE_ENABLES_2_CMD | ENABLE_COLOR_MASK);
+	OUT_RING(MI_NOOP); 
 	ADVANCE_LP_RING();
     }
 
diff-tree 1a29750b8dba1371d7d0802744cdf2f3bfa83c13 (from 3a634bbd198650c1597dec4306d99928374c30f3)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Mon Apr 16 16:21:39 2007 +0800

    EXA: fix 830/845G pict format
    
    Fallback in 830/845G when pict format is a8, x8r8g8b8 or
    x8b8g8r8. The hw doesn't support them.

diff --git a/src/i830_render.c b/src/i830_render.c
index 380c808..ec80c0b 100644
--- a/src/i830_render.c
+++ b/src/i830_render.c
@@ -149,7 +149,7 @@ static struct formatinfo i830_tex_format
     {PICT_r5g6b5,   MT_16BIT_RGB565   },
     {PICT_a1r5g5b5, MT_16BIT_ARGB1555 },
     {PICT_x1r5g5b5, MT_16BIT_ARGB1555 },
-    {PICT_a8,       MT_8BIT_A8       },	 /* mesa does I8 */
+    {PICT_a8,       MT_8BIT_A8        },
 };
 
 static Bool i830_get_dest_format(PicturePtr pDstPicture, CARD32 *dst_format)
@@ -220,6 +220,8 @@ static CARD32 i830_get_blend_cntl(int op
 
 static Bool i830_check_composite_texture(PicturePtr pPict, int unit)
 {
+    ScrnInfoPtr pScrn = xf86Screens[pPict->pDrawable->pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
     int w = pPict->pDrawable->width;
     int h = pPict->pDrawable->height;
     int i;
@@ -237,6 +239,13 @@ static Bool i830_check_composite_texture
         I830FALLBACK("Unsupported picture format 0x%x\n",
 		     (int)pPict->format);
 
+    if (IS_I830(pI830) || IS_845G(pI830)) {
+	if (pPict->format == PICT_x8r8g8b8 || 
+		pPict->format == PICT_x8b8g8r8 || 
+		pPict->format == PICT_a8)
+	    I830FALLBACK("830/845G don't support a8, x8r8g8b8, x8b8g8r8\n");
+    }
+
     if (pPict->repeat && pPict->repeatType != RepeatNormal)
 	I830FALLBACK("unsupport repeat type\n");
 
diff-tree 3a634bbd198650c1597dec4306d99928374c30f3 (from 3bcb9a0b4ba7f3df346b5708617a7aafcbe2490a)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Mon Apr 16 15:14:49 2007 +0800

    EXA: Add i830 supported pict format XRGB8888, XBGR8888

diff --git a/src/i830_reg.h b/src/i830_reg.h
index 989646f..7a8df9f 100644
--- a/src/i830_reg.h
+++ b/src/i830_reg.h
@@ -659,6 +659,8 @@
 #define    MT_16BIT_DIB_RGB565_8888	   (7<<3)
 #define    MT_32BIT_ARGB8888		   (0<<3) /* SURFACE_32BIT */
 #define    MT_32BIT_ABGR8888		   (1<<3)
+#define    MT_32BIT_XRGB8888		   (2<<3)
+#define    MT_32BIT_XBGR8888		   (3<<3)
 #define    MT_32BIT_BUMP_XLDVDU_8888	   (6<<3)
 #define    MT_32BIT_DIB_8888		   (7<<3)
 #define    MT_411_YUV411		   (0<<3) /* SURFACE_411 */
diff --git a/src/i830_render.c b/src/i830_render.c
index f5e144b..380c808 100644
--- a/src/i830_render.c
+++ b/src/i830_render.c
@@ -143,10 +143,10 @@ static struct blendinfo i830_blend_op[] 
 
 static struct formatinfo i830_tex_formats[] = {
     {PICT_a8r8g8b8, MT_32BIT_ARGB8888 },
-    {PICT_x8r8g8b8, MT_32BIT_ARGB8888 },
+    {PICT_x8r8g8b8, MT_32BIT_XRGB8888 },
     {PICT_a8b8g8r8, MT_32BIT_ABGR8888 },
-    {PICT_x8b8g8r8, MT_32BIT_ABGR8888 },
-    {PICT_r5g6b5,   MT_16BIT_RGB565	  },
+    {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       },	 /* mesa does I8 */
diff-tree 3bcb9a0b4ba7f3df346b5708617a7aafcbe2490a (from 64c30cf896f8bde3ee74c92b970132ab91b418cd)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Mon Apr 16 14:27:49 2007 +0800

    EXA: i830 render misc fix and cleanups
    
    Try to map texture stream when setup texture map, and use
    correct order in load_immediate_1 cmd, which fixed crash on
    845GV. Also remove some flush cmds.

diff --git a/src/i830_render.c b/src/i830_render.c
index d587805..f5e144b 100644
--- a/src/i830_render.c
+++ b/src/i830_render.c
@@ -305,7 +305,7 @@ i830_texture_setup(PicturePtr pPict, Pix
 	else
 	    format |= MAPSURF_32BIT;
 
-	BEGIN_LP_RING(8);
+	BEGIN_LP_RING(10);
 	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | LOAD_TEXTURE_MAP(unit) | 4);
 	OUT_RING((offset & TM0S0_ADDRESS_MASK) | TM0S0_USE_FENCE); 
 	OUT_RING(((pPix->drawable.height - 1) << TM0S1_HEIGHT_SHIFT) |
@@ -318,7 +318,24 @@ i830_texture_setup(PicturePtr pPict, Pix
 		 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);
+	/* map texel stream */
+	OUT_RING(_3DSTATE_MAP_COORD_SETBIND_CMD);
+	if (unit == 0)
+	    OUT_RING(TEXBIND_SET0(TEXCOORDSRC_VTXSET_0) |
+		    TEXBIND_SET1(TEXCOORDSRC_KEEP) |
+		    TEXBIND_SET2(TEXCOORDSRC_KEEP) |
+		    TEXBIND_SET3(TEXCOORDSRC_KEEP));
+	else
+	    OUT_RING(TEXBIND_SET0(TEXCOORDSRC_VTXSET_0) |
+		    TEXBIND_SET1(TEXCOORDSRC_VTXSET_1) |
+		    TEXBIND_SET2(TEXCOORDSRC_KEEP) |
+		    TEXBIND_SET3(TEXCOORDSRC_KEEP));
+	OUT_RING(_3DSTATE_MAP_TEX_STREAM_CMD | (unit << 16) |
+		DISABLE_TEX_STREAM_BUMP | 
+		ENABLE_TEX_STREAM_COORD_SET |
+		TEX_STREAM_COORD_SET(unit) |
+		ENABLE_TEX_STREAM_MAP_IDX |
+		TEX_STREAM_MAP_IDX(unit));
 	ADVANCE_LP_RING();
      }
 
@@ -392,7 +409,7 @@ i830_prepare_composite(int op, PicturePt
     {
 	CARD32 cblend, ablend, blendctl, vf2;
 
-	BEGIN_LP_RING(34);
+	BEGIN_LP_RING(26);
 
 	/* color buffer */
 	OUT_RING(_3DSTATE_BUF_INFO_CMD);
@@ -403,8 +420,6 @@ i830_prepare_composite(int op, PicturePt
 	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);
@@ -421,32 +436,16 @@ i830_prepare_composite(int op, PicturePt
 	OUT_RING(DRAW_YMAX(pDst->drawable.height - 1) |
 		DRAW_XMAX(pDst->drawable.width - 1));
 	OUT_RING(0); /* yorig, xorig */
-	OUT_RING(MI_NOOP);
 
-	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(2) | 
+		I1_LOAD_S(3) | 1);
 	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(vf2); /* TEXCOORDFMT_2D */
+	OUT_RING(S3_CULLMODE_NONE | S3_VERTEXHAS_XY);
 
-      	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 */
@@ -481,9 +480,6 @@ i830_prepare_composite(int op, PicturePt
 	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 = 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 | 
diff-tree 64c30cf896f8bde3ee74c92b970132ab91b418cd (from b67adb6de34cede0e31f02f26cd5ec7b1adfa586)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Mon Apr 16 13:58:50 2007 +0800

    Update intel.man with 965GM chipset support

diff --git a/man/intel.man b/man/intel.man
index 80b327d..5ce31ea 100644
--- a/man/intel.man
+++ b/man/intel.man
@@ -24,7 +24,7 @@ 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.
+865G, 915G, 915GM, 945G, 945GM, 965G, 965Q, 946GZ and 965GM chipsets.
 
 .SH CONFIGURATION DETAILS
 Please refer to __xconfigfile__(__filemansuffix__) for general configuration
@@ -198,4 +198,5 @@ support reworked for XFree86 4.3 by Davi
 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.
+Zhenyu. TV out support added by Zou Nan Hai and Keith Packard. 965GM support
+added by Wang Zhenyu.
diff-tree b67adb6de34cede0e31f02f26cd5ec7b1adfa586 (from b5b243e4120d6a048fb6bbe8814fe3184271e9d9)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Fri Apr 13 22:34:52 2007 +0800

    Fix crash on G965 XAA with LinearAlloc option
    
    We should alloc xaa_linear mem in LinearAlloc case, otherwise
    we get crash when initializing xf86 fb manager.

diff --git a/src/i830_memory.c b/src/i830_memory.c
index b26dd00..315f4ba 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -651,7 +651,7 @@ i830_allocate_overlay(ScrnInfoPtr pScrn)
     I830Ptr pI830 = I830PTR(pScrn);
 
     /* Only allocate if overlay is going to be enabled. */
-    if (!pI830->XvEnabled || IS_I965G(pI830))
+    if (!pI830->XvEnabled)
 	return TRUE;
 
     if (!IS_I965G(pI830)) {
diff-tree b5b243e4120d6a048fb6bbe8814fe3184271e9d9 (from 08cd5f9b0f086e51112008d50de48556372899f9)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Apr 12 12:34:23 2007 -0700

    Add license headers to 965 programs.

diff --git a/src/exa_sf.g4a b/src/exa_sf.g4a
index 8c1398f..5a02399 100644
--- a/src/exa_sf.g4a
+++ b/src/exa_sf.g4a
@@ -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:
+ *    Keith Packard <keithp at keithp.com>
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
 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 };
diff --git a/src/exa_sf_mask.g4a b/src/exa_sf_mask.g4a
index a7e2d32..a0d6efc 100644
--- a/src/exa_sf_mask.g4a
+++ b/src/exa_sf_mask.g4a
@@ -1,3 +1,28 @@
+/*
+ * 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>
+ */
 
 /* FIXME how to setup second coeffient for mask tex coord */
 
diff --git a/src/exa_sf_rotation.g4a b/src/exa_sf_rotation.g4a
index 4c93553..59d40d4 100644
--- a/src/exa_sf_rotation.g4a
+++ b/src/exa_sf_rotation.g4a
@@ -1,3 +1,29 @@
+/*
+ * 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:
+ *    Wang Zhenyu <zhenyu.z.wang at intel.com>
+ */
+
 /* 1/dx */
 send (1) 0 g6<1>F g1.12<0,1,0>F math inv scalar mlen 1 rlen 1 { align1 };
 /* 1/dy */
diff --git a/src/exa_wm_maskca.g4a b/src/exa_wm_maskca.g4a
index fa923f6..0e96aa0 100644
--- a/src/exa_wm_maskca.g4a
+++ b/src/exa_wm_maskca.g4a
@@ -1,4 +1,30 @@
 /*
+ * 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:
+ *    Wang Zhenyu <zhenyu.z.wang at intel.com>
+ */
+
+/*
  * 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
diff --git a/src/exa_wm_maskca_srcalpha.g4a b/src/exa_wm_maskca_srcalpha.g4a
index e233968..a92c9e4 100644
--- a/src/exa_wm_maskca_srcalpha.g4a
+++ b/src/exa_wm_maskca_srcalpha.g4a
@@ -1,4 +1,30 @@
 /*
+ * 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:
+ *    Wang Zhenyu <zhenyu.z.wang at intel.com>
+ */
+
+/*
  * 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
diff --git a/src/exa_wm_masknoca.g4a b/src/exa_wm_masknoca.g4a
index c2049fd..2e9e3c9 100644
--- a/src/exa_wm_masknoca.g4a
+++ b/src/exa_wm_masknoca.g4a
@@ -1,4 +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:
+ *    Wang Zhenyu <zhenyu.z.wang at intel.com>
+ */
+
+/*
  * 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
diff --git a/src/exa_wm_nomask.g4a b/src/exa_wm_nomask.g4a
index 8e851a3..f92dc1a 100644
--- a/src/exa_wm_nomask.g4a
+++ b/src/exa_wm_nomask.g4a
@@ -1,4 +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:
+ *    Wang Zhenyu <zhenyu.z.wang at intel.com>
+ */
+
+/*
  * This's for exa composite operation in no mask picture case.
  * The simplest case is just sending what src picture has to dst picture.
  */
diff --git a/src/exa_wm_rotation.g4a b/src/exa_wm_rotation.g4a
index b12f81c..613a5cb 100644
--- a/src/exa_wm_rotation.g4a
+++ b/src/exa_wm_rotation.g4a
@@ -1,4 +1,30 @@
 /*
+ * 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:
+ *    Wang Zhenyu <zhenyu.z.wang at intel.com>
+ */
+
+/*
  * This's for exa composite operation in no mask picture case.
  * The simplest case is just sending what src picture has to dst picture.
  */
diff --git a/src/packed_yuv_sf.g4a b/src/packed_yuv_sf.g4a
index 8c1398f..5a02399 100644
--- a/src/packed_yuv_sf.g4a
+++ b/src/packed_yuv_sf.g4a
@@ -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:
+ *    Keith Packard <keithp at keithp.com>
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
 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 };
diff --git a/src/packed_yuv_wm.g4a b/src/packed_yuv_wm.g4a
index 4b6391b..5e31f10 100644
--- a/src/packed_yuv_wm.g4a
+++ b/src/packed_yuv_wm.g4a
@@ -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:
+ *    Keith Packard <keithp at keithp.com>
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
 /* The initial payload of the thread is always g0.
  * WM_URB (incoming URB entries) is g3
  * X0_R is g4
diff-tree 08cd5f9b0f086e51112008d50de48556372899f9 (from bf9771e9711361632afe3abeeedca7ce03497005)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Apr 10 11:26:46 2007 -0700

    Bug #10520: i810 manpage not installed despite users expecting it to be there.
    
    Install it as an alias to intel.4x, since we're letting people load the driver
    as "i810" still.

diff --git a/man/Makefile.am b/man/Makefile.am
index bf7ec17..b5510e8 100644
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -27,9 +27,13 @@
 
 drivermandir = $(DRIVER_MAN_DIR)
 
+DRIVER_MAN_DIR_SUFFIX = $(DRIVER_MAN_DIR:@mandir@/man%=%)
+
 driverman_PRE = @DRIVER_NAME at .man
 
-driverman_DATA = $(driverman_PRE:man=@DRIVER_MAN_SUFFIX@)
+driverman_DATA = \
+	$(driverman_PRE:man=@DRIVER_MAN_SUFFIX@) \
+	i810. at DRIVER_MAN_SUFFIX@
 
 EXTRA_DIST = @DRIVER_NAME at .man
 
@@ -57,3 +61,10 @@ SUFFIXES = .$(DRIVER_MAN_SUFFIX) .man
 
 .man.$(DRIVER_MAN_SUFFIX):
 	sed $(MAN_SUBSTS) < $< > $@
+
+BUILT_SOURCES = shadows.DONE
+
+shadows.DONE:
+	-rm -f i810. at DRIVER_MAN_SUFFIX@
+	echo .so man$(DRIVER_MAN_DIR_SUFFIX)/intel.$(DRIVER_MAN_SUFFIX) > \
+		i810. at DRIVER_MAN_SUFFIX@
diff-tree bf9771e9711361632afe3abeeedca7ce03497005 (from 656fbd952542ba5ddc9b018071008ceb38b1bd19)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Apr 9 15:26:05 2007 -0700

    Don't use extended regexps in sed when not necessary.
    
    Some seds require a flag to enable extended regexps.

diff --git a/configure.ac b/configure.ac
index 0f7fca6..2d26553 100644
--- a/configure.ac
+++ b/configure.ac
@@ -27,13 +27,13 @@ AC_INIT([xf86-video-intel],
         xf86-video-intel)
 
 AC_DEFINE_UNQUOTED([INTEL_VERSION_MAJOR],
-		   [$(echo $PACKAGE_VERSION | sed -e 's/^\([[0-9]]\+\)\.[[0-9]]\+\.[[0-9]]\+/\1/')],
+		   [$(echo $PACKAGE_VERSION | sed -e 's/^\([[0-9]]*\)\.[[0-9]]*\.[[0-9]]*/\1/')],
 		   [Major version])
 AC_DEFINE_UNQUOTED([INTEL_VERSION_MINOR],
-		   [$(echo $PACKAGE_VERSION | sed -e 's/^[[0-9]]\+\.\([[0-9]]\+\)\.[[0-9]]\+/\1/')],
+		   [$(echo $PACKAGE_VERSION | sed -e 's/^[[0-9]]*\.\([[0-9]]*\)\.[[0-9]]*/\1/')],
 		   [Minor version])
 AC_DEFINE_UNQUOTED([INTEL_VERSION_PATCH],
-		   [$(echo $PACKAGE_VERSION | sed -e 's/^[[0-9]]\+\.[[0-9]]\+\.\([[0-9]]\+\)/\1/')],
+		   [$(echo $PACKAGE_VERSION | sed -e 's/^[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)/\1/')],
 		   [Patch version])
 
 AC_CONFIG_SRCDIR([Makefile.am])
diff-tree 656fbd952542ba5ddc9b018071008ceb38b1bd19 (from aa850d3c633a510d787ee59e538e26e5c3acbf4a)
Author: Brice Goglin <brice.goglin at ens-lyon.org>
Date:   Mon Apr 9 13:06:46 2007 -0700

    Bug #10515: Fix module version number with more than one digit per field.

diff --git a/configure.ac b/configure.ac
index 06431ab..0f7fca6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -27,13 +27,13 @@ AC_INIT([xf86-video-intel],
         xf86-video-intel)
 
 AC_DEFINE_UNQUOTED([INTEL_VERSION_MAJOR],
-		   [$(echo $PACKAGE_VERSION | sed -e 's/^\([[0-9]]\)\.[[0-9]]\.[[0-9]]/\1/')],
+		   [$(echo $PACKAGE_VERSION | sed -e 's/^\([[0-9]]\+\)\.[[0-9]]\+\.[[0-9]]\+/\1/')],
 		   [Major version])
 AC_DEFINE_UNQUOTED([INTEL_VERSION_MINOR],
-		   [$(echo $PACKAGE_VERSION | sed -e 's/^[[0-9]]\.\([[0-9]]\)\.[[0-9]]/\1/')],
+		   [$(echo $PACKAGE_VERSION | sed -e 's/^[[0-9]]\+\.\([[0-9]]\+\)\.[[0-9]]\+/\1/')],
 		   [Minor version])
 AC_DEFINE_UNQUOTED([INTEL_VERSION_PATCH],
-		   [$(echo $PACKAGE_VERSION | sed -e 's/^[[0-9]]\.[[0-9]]\.\([[0-9]]\)/\1/')],
+		   [$(echo $PACKAGE_VERSION | sed -e 's/^[[0-9]]\+\.[[0-9]]\+\.\([[0-9]]\+\)/\1/')],
 		   [Patch version])
 
 AC_CONFIG_SRCDIR([Makefile.am])
diff-tree aa850d3c633a510d787ee59e538e26e5c3acbf4a (from d2e75d8acde2541b85a0050d9e47182c1db7fc2c)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Apr 9 11:44:25 2007 -0700

    Turn off ALWAYS_SYNC in EXA.
    
    This slipped in as a debugging aid, and never got turned off.  The driver
    appears to work fine without it on an i915 system, and for the non-default EXA
    option, we'd rather see issues found than continue running with debugging aids
    and hiding them behind bad performance.

diff --git a/src/i830_exa.c b/src/i830_exa.c
index bef8fae..dfc8f99 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -42,7 +42,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define DEBUG_I830FALLBACK 1
 #endif
 
-#define ALWAYS_SYNC		1
+#define ALWAYS_SYNC		0
 
 #ifdef DEBUG_I830FALLBACK
 #define I830FALLBACK(s, arg...)				\
diff-tree d2e75d8acde2541b85a0050d9e47182c1db7fc2c (from 9ed446e12bd21b7c8222c6e63a03a8e2ec6b97e2)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Apr 9 11:34:57 2007 -0700

    Avoid a magic number and correct a (currently harmless) ifdef in ResetState().

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 4ee720f..f0ca973 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1559,7 +1559,7 @@ ResetState(ScrnInfoPtr pScrn, Bool flush
    /* God this is ugly */
 #define flush_ring() do { \
       temp = INREG(LP_RING + RING_LEN); \
-      if (temp & 1) { \
+      if (temp & RING_VALID) { \
 	 I830RefreshRing(pScrn); \
 	 I830Sync(pScrn); \
 	 DO_RING_IDLE(); \
@@ -1569,7 +1569,7 @@ ResetState(ScrnInfoPtr pScrn, Bool flush
    if (!pI830->useEXA && flush && pI830->AccelInfoRec)
        flush_ring();
 #endif
-#ifdef I830_USE_XAA
+#ifdef I830_USE_EXA
    if (pI830->useEXA && flush && pI830->EXADriverPtr)
        flush_ring();
 #endif
diff-tree 9ed446e12bd21b7c8222c6e63a03a8e2ec6b97e2 (from d9d05b553ca1f98efc230ef13f34576122311ac1)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Apr 3 11:39:48 2007 -0700

    It's 2007 now.  Didn't I get the memo?

diff --git a/README b/README
index 788acdb..f209baa 100644
--- a/README
+++ b/README
@@ -1,6 +1,6 @@
 Information for Intel graphics driver users
 Eric Anholt
-2006-04-02
+2007-04-02
 
 This document provides a brief summary of the Intel graphics support provided
 by the xf86-video-intel driver.  More information can also be found in the
diff-tree d9d05b553ca1f98efc230ef13f34576122311ac1 (from eb45315b07624cb0506d539f523728a651efb798)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Apr 3 00:15:02 2007 -0700

    Bump version to 1.9.94 for 2.0 RC4.

diff --git a/configure.ac b/configure.ac
index dccfd75..06431ab 100644
--- a/configure.ac
+++ b/configure.ac
@@ -22,7 +22,7 @@
 
 AC_PREREQ(2.57)
 AC_INIT([xf86-video-intel],
-        1.9.93,
+        1.9.94,
         [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
         xf86-video-intel)
 
diff-tree eb45315b07624cb0506d539f523728a651efb798 (from 9b78208f1ef1a8ee98f2aa139956659169e234ab)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Apr 2 18:20:33 2007 -0700

    Move README to being a plain old text file.

diff --git a/Makefile.am b/Makefile.am
index 2b6c46a..8cbe4a9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -21,9 +21,4 @@
 AUTOMAKE_OPTIONS = foreign
 SUBDIRS = src man
 
-if BUILD_LINUXDOC
-README: README.sgml
-	$(MAKE_TEXT) README.sgml && mv README.txt README
-endif
-
-EXTRA_DIST = README.sgml
+EXTRA_DIST = README
diff --git a/README b/README
index e2061c4..788acdb 100644
--- a/README
+++ b/README
@@ -1,177 +1,103 @@
-  Information for Intel graphics driver users
-  Eric Anholt
-  2006-08-04
-  ____________________________________________________________
-
-  Table of Contents
-
-
-  1. Introduction
-  2. Supported Hardware
-  3. Features
-  4. Technical Notes
-  5. Configuration
-  6. Driver Options
-  7. Known Limitations
-  8. Author
-
-
-  ______________________________________________________________________
-
-  11..  IInnttrroodduuccttiioonn
-
-  This document provides a brief summary of the Intel graphics support
-  provided by the xf86-video-intel driver.  More information can also be
-  found in the i810(4) manual page.
-
-
-  22..  SSuuppppoorrtteedd HHaarrddwwaarree
-
-
-  +o  i810,
-
-  +o  i810-dc100,
-
-  +o  i810e
-
-  +o  i815
-
-  +o  i830
-
-  +o  i845
-
-  +o  i852
-
-  +o  i855
-
-  +o  i915
-
-  +o  i945
-
-  +o  i965
-
-
-
-  33..  FFeeaattuurreess
-
-
-  +o  Full support for 8, 15, 16, and 24 bit pixel depths.
-
-  +o  Hardware accelerated 2D drawing engine support for 8, 15, 16 and 24
-     bit pixel depths.
-
-  +o  Hardware accelerated 3D drawing using OpenGL and the DRI.
-
-  +o  Hardware cursor support to reduce sprite flicker.
-
-  +o  Textured video XV implementation on i915 through i965.
-
-  +o  Hardware overlay XV implementation up through i945.
-
-  +o  Screen resize and rotation on chipsets up through i945.
-
-  +o  Screen resize on i965.
-
-
-
-  44..  TTeecchhnniiccaall NNootteess
-
-
-  +o  Interlace modes cannot be supported.
-
-  +o  This driver  requires kernel support for AGP, which is included in
-     Linux kernels 2.3.42 and higher, and FreeBSD 4.1 and higher.
-
-
-
-  55..  CCoonnffiigguurraattiioonn
-
-  The driver auto-detects all device information necessary to initialize
-  the card.  The only lines you should need in the "Device" section of
-  your xorg.conf file are:
-
-         Section "Device"
-             Identifier "Intel i810"
-             Driver     "i810"
-         EndSection
-
-
-
-  In order to use most resolutions, it is necessary to install the
-  "agpgart.o" module.  You will probably have to compile the module
-  yourself (see the notes in the module).
-
-
-  66..  DDrriivveerr OOppttiioonnss
-
-  Please refer to the i810(4) manual page for information on
-  configuration options.
-
-
-
-  77..  KKnnoowwnn LLiimmiittaattiioonnss
-
-
-  +o  Many systems with Intel graphics have issues with setting video
-     modes at larger than some small maximum resolution.  This is not
-     fixed in the current release, but is being actively worked on in
-     the modesetting branch.
-
-  +o  Bug #5795: Some systems have issues with VT switching.  This should
-     be fixed with the modesetting brach integration.
-
-  +o  Bug #5817: Hotkey switching from LVDS to CRT breaks CRT output.
-     This is a known issue, but will not be fixed in the current
-     release.
-
-  +o  Bug #6635: Video is output from an incorrect offset in the
-     framebuffer.  This is expected to be fixed with the modesetting
-     branch integration.
-
-  +o  GL_EXT_texture_compression_s3tc is not supported.  We can't support
-     the extension due to patent restrictions on compression, but may be
-     able to support an option for partial extension support in the
-     future.  For now, this prevents Quake4 and some other games from
-     running.
-
-  +o  Some X Test Suite cases sometimes fail due to a timeout. These
-     cases include: Xt8/XtResizeWindow, Xt8/XtQueryGeometry,
-     Xt9/XtAppAddInput, Xt9/XtRemoveInput, Xt9/XtAppAddTimeOut,
-     Xt9/XtRemoveTimeOut, Xt9/XtAddGrab, Xt9/XtRemoveGrab.
-
-  +o  Some X Test Suite cases fail in 64-bit mode: Xlib9/XDrawArc,
-     XDrawImageString, XDrawLine, XDrawRectangle, XDrawSegments,
-     XFillArc, XFillPolygon, XFillRectangle, XPutImage,
-     Xt11/XtVaGetSubresources, XtSetSubvalues, and XtVaSetSubvalues.
-
-  +o  Some GLEAN test cases fail if DRI is enabled: pointAtten,
-     readPixSanity, texCombine, texCube, texEnv, texgen,
-     coloredTexPerf2, and coloredLitPerf2.
-
-
-
-  88..  AAuutthhoorr
-
-
-  +o  Eric Anholt
-
-  +o  Keith Whitwell
-
-  The X11R7.1 version of this driver originally came from XFree86 4.4
-  rc2.
-
-  The XFree86 version of this driver was donated to The XFree86 Project
-  by:
-
-      Precision Insight, Inc.
-      Cedar Park, TX
-      USA
-
-
-
-  The X.Org version of this driver is maintained by Intel Corporation.
-
-  http://www.intellinuxgraphics.org
-
-
+Information for Intel graphics driver users
+Eric Anholt
+2006-04-02
+
+This document provides a brief summary of the Intel graphics support provided
+by the xf86-video-intel driver.  More information can also be found in the
+intel(4) manual page.
+
+Supported Hardware:
+	i810,
+  	i810-dc100,
+	i810e
+	i815
+	i830
+	i845
+	i852
+	i855
+	i915
+	i945
+	i965
+
+Features
+- Full support for 8, 15, 16, and 24 bit pixel depths.
+- Hardware accelerated 2D drawing engine support for 8, 15, 16 and 24 bit
+  pixel depths.
+- Hardware accelerated 3D drawing using OpenGL and the DRI.
+- Hardware cursor support to reduce sprite flicker.
+- Textured video XV implementation on i915 through i965.
+- Hardware overlay XV implementation up through i945.
+- Screen resize and rotation.
+
+Technical Notes
+- Interlace modes cannot be supported.
+- This driver  requires kernel support for AGP, which is included in Linux
+  kernels 2.3.42 and higher, and FreeBSD 4.1 and higher.
+- This driver may be built against xserver 1.2.0 or newer.  If built
+  from git source against an older server, a copy of xserver 1.3.0 source is
+  needed to complete the build, which is chosen with the --with-xserver-source
+  argument to ./configure.  The compatibility mode with xserver 1.2.0 will have
+  limited functionality, in particular by not supporting RandR 1.2 or the
+  new Damage 1.1 updated needed for 3D applications to work with display
+  rotation.
+
+Configuration
+
+The driver auto-detects all device information necessary to
+initialize the card.  The only lines you should need in the "Device"
+section of your xorg.conf file are:
+
+       Section "Device"
+           Identifier "intel"
+           Driver     "intel"
+       EndSection
+
+Please refer to the intel(4) manual page for information on configuration
+options.
+
+
+Known Limitations
+- Bug #8534: i830 laptop panels not supported.  The driver
+  will fail to recognize them, and only function through VGA output.  Two
+  partial DVO chip drivers (ivch and ch7017) are included which contain some of
+  the code necessary for i830 laptop panel support, but some I2C debugging will
+  be necessary to get those drivers to attach.
+- No support for "zaphod mode" dualhead.  This is the mode in which two
+  Device sections are placed in the config file, and doesn't support DRI or
+  many other features.  Instead, only "MergedFB-style" dualhead is supported.
+- No support for X Screens larger than 2048 pixels in either direction
+  before the 965.  This reflects hardware limitations in the x direction on
+  those older chips, and limits dualhead functionality.  It may be possible to
+  extend the limit vertically on these older chips.
+- i855 XV may cause hangs.  This was present in the previous release, and no
+  workaround is known.
+- SDVO TV-out cards not supported.  This should be fixed in the next
+  release.
+- Gray output with integrated TV-out and PAL TVs.
+- EXA support unstable on i845.
+
+Common issues not caused by the driver
+- Font sizes (DPI) are wrong.  Some displays incorrectly report their
+  physical size, which is harmless on most OSes that always assume 96dpi
+  displays.  This can be fixed through quirks for specific monitors in the X
+  Server, and the output of xrandr --prop along with a physical measurement of
+  the screen size in a bug report against the server can help get that fixed.
+- gnome-panel is located in the middle of the screen.  gnome-panel places
+  itself within head #0's boundaries, which doesn't work well with a second
+  head covering the same area as head #0 but larger.
+- Older resolution-changing applicationss have poor results in
+  multihead systems.  Previous extensions such as RandR 1.1 exposed only a
+  single output to client programs, and those requests map poorly to multi-head
+  systems.  Currently, those requests map to just one of the outputs in the
+  RandR 1.2 environment, and those applications need to be updated to RandR 1.2
+  API when available for better results.
+
+The X11R6 version of this driver originally came from XFree86 4.4 rc2.
+
+The XFree86 version of this driver was donated to The XFree86 Project by:
+    Precision Insight, Inc.
+    Cedar Park, TX
+    USA
 
+The X.Org version of this driver is maintained by Intel Corporation.
+<http://www.intellinuxgraphics.org>
diff --git a/README.sgml b/README.sgml
deleted file mode 100644
index 4a67017..0000000
--- a/README.sgml
+++ /dev/null
@@ -1,147 +0,0 @@
-<!DOCTYPE linuxdoc PUBLIC "-//XFree86//DTD linuxdoc//EN" [
-<!ENTITY % defs SYSTEM "defs.ent"> %defs;
-]>
-
-<article>
-<title>Information for Intel graphics driver users
-<author>Eric Anholt
-<date>2006-04-02
-<toc>
-
-<sect>Introduction
-<p>
-This document provides a brief summary of the Intel graphics support provided
-by the xf86-video-intel driver.  More information can also be found in the
-<htmlurl name="intel(4)" url="intel.4.html"> manual page.
-
-<sect>Supported Hardware
-<p>
-<itemize>
-	<item>i810,
-  	<item>i810-dc100,
-	<item>i810e
-	<item>i815
-	<item>i830
-	<item>i845
-	<item>i852
-	<item>i855
-	<item>i915
-	<item>i945
-	<item>i965
-</itemize>
-
-
-<sect>Features
-<p>
-<itemize>
-  <item>Full support for 8, 15, 16, and 24 bit pixel depths.
-  <item>Hardware accelerated 2D drawing engine support for 8, 15, 16 and
-        24 bit pixel depths.
-  <item>Hardware accelerated 3D drawing using OpenGL and the DRI.
-  <item>Hardware cursor support to reduce sprite flicker.
-  <item>Textured video XV implementation on i915 through i965.
-  <item>Hardware overlay XV implementation up through i945.
-  <item>Screen resize and rotation.
-</itemize>
-
-
-<sect>Technical Notes
-<p>
-<itemize>
-  <item>Interlace modes cannot be supported.
-  <item>This driver  requires kernel support for AGP, which is
-	included in Linux kernels 2.3.42 and higher, and FreeBSD 4.1
-	and higher.
-  <item>This driver may be built against xserver 1.2.0 or newer.  If built
-  from git source against an older server, a copy of xserver 1.3.0 source is
-  needed to complete the build, which is chosen with the --with-xserver-source
-  argument to ./configure.  The compatibility mode with xserver 1.2.0 will have
-  limited functionality, in particular by not supporting RandR 1.2 or the
-  new Damage 1.1 updated needed for 3D applications to work with display
-  rotation.
-</itemize>
-
-
-<sect>Configuration
-<p>
-The driver auto-detects all device information necessary to
-initialize the card.  The only lines you should need in the "Device"
-section of your xorg.conf file are:
-<verb>
-       Section "Device"
-           Identifier "intel"
-           Driver     "intel"
-       EndSection
-</verb>
-
-<sect>Driver Options
-<p>
-Please refer to the <htmlurl name="intel(4)" url="intel.4.html"> manual page
-for information on configuration options.
-
-
-<sect>Known Limitations
-<p>
-<itemize>
-  <item>Bug #8534: i830 laptop panels not supported.  The driver
-  will fail to recognize them, and only function through VGA output.  Two
-  partial DVO chip drivers (ivch and ch7017) are included which contain some of
-  the code necessary for i830 laptop panel support, but some I2C debugging will
-  be necessary to get those drivers to attach.
-  <item>No support for "zaphod mode" dualhead.  This is the mode in which two
-  Device sections are placed in the config file, and doesn't support DRI or
-  many other features.  Instead, only "MergedFB-style" dualhead is supported.
-  <item>No support for X Screens larger than 2048 pixels in either direction
-  before the 965.  This reflects hardware limitations in the x direction on
-  those older chips, and limits dualhead functionality.  It may be possible to
-  extend the limit vertically on these older chips.
-  <item>i855 XV may cause hangs.  This was present in the previous release,
-  and no workaround is known.
-  <item>SDVO TV-out cards not supported.  This should be fixed in the next
-  release.
-  <item>Gray output with integrated TV-out.
-  <item>EXA support unstable on i845.
-</itemize>
-
-<sect>Common issues not caused by the driver
-<itemize>
-  <item>Font sizes (DPI) are wrong.  Some displays incorrectly report their
-  physical size, which is harmless on most OSes that always assume 96dpi
-  displays.  This can be fixed through quirks for specific monitors in the X
-  Server, and the output of xrandr --prop along with a physical measurement of
-  the screen size in a bug report against the server can help get that fixed.
-  <item>gnome-panel is located in the middle of the screen.  gnome-panel places
-  itself within head #0's boundaries, which doesn't work well with a second
-  head covering the same area as head #0 but larger.
-  <item>Older resolution-changing applicationss have poor results in
-  multihead systems.  Previous extensions such as RandR 1.1 exposed only a
-  single output to client programs, and those requests map poorly to multi-head
-  systems.  Currently, those requests map to just one of the outputs in the
-  RandR 1.2 environment, and those applications need to be updated to RandR 1.2
-  API when available for better results.
-  <item>
-</itemize>
-
-<sect>Author
-<p>
-<itemize>
-   <item>Eric Anholt
-   <item>Keith Whitwell
-</itemize>
-
-The X11R&relvers; version of this driver originally came from XFree86 4.4 rc2.
-
-The XFree86 version of this driver was donated to The XFree86 Project by:
-<verb>
-    Precision Insight, Inc.
-    Cedar Park, TX
-    USA
-</verb>
-
-The X.Org version of this driver is maintained by Intel Corporation.
-
-<htmlurl name="http://www.intellinuxgraphics.org"
-          url="http://www.intellinuxgraphics.org">
-
-
-</article>
diff-tree 9b78208f1ef1a8ee98f2aa139956659169e234ab (from 9ea83d440d6b9e30d4627e34168226a6b4b2a841)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Apr 2 18:20:15 2007 -0700

    Move a bunch of debugging verbosity under Option "ModeDebug".

diff --git a/man/intel.man b/man/intel.man
index 3197feb..80b327d 100644
--- a/man/intel.man
+++ b/man/intel.man
@@ -175,6 +175,10 @@ Choose acceleration architecture, either
 (but stable) XFree86 based acceleration architecture.  EXA is a newer and
 simpler acceleration architecture designed to better accelerate the X Render
 extension.  Default: "XAA".
+.TP
+.BI "Option \*qModeDebug\*q \*q" boolean \*q
+Enable printing of additional debugging information about modesetting to
+the server log.
 
 .PP
 The 830M and newer driver supports RandR 1.2, exposing the VGA, LVDS
diff --git a/src/i830.h b/src/i830.h
index e75eb89..4cb31b6 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -527,6 +527,9 @@ typedef struct _I830Rec {
    CARD32 saveBLC_PWM_CTL;
 
    enum last_3d last_3d;
+
+   /** Enables logging of debug output related to mode switching. */
+   Bool debug_modes;
 } I830Rec;
 
 #define I830PTR(p) ((I830Ptr)((p)->driverPrivate))
diff --git a/src/i830_bios.c b/src/i830_bios.c
index cb886b5..0d00917 100644
--- a/src/i830_bios.c
+++ b/src/i830_bios.c
@@ -229,9 +229,11 @@ i830_bios_get_panel_mode(ScrnInfoPtr pSc
 
 	    xf86SetModeDefaultName(fixed_mode);
 
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		       "Found panel mode in BIOS VBT tables:\n");
-	    xf86PrintModeline(pScrn->scrnIndex, fixed_mode);
+	    if (pI830->debug_modes) {
+		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+			   "Found panel mode in BIOS VBT tables:\n");
+		xf86PrintModeline(pScrn->scrnIndex, fixed_mode);
+	    }
 
 	    xfree(bios);
 	    return fixed_mode;
diff --git a/src/i830_display.c b/src/i830_display.c
index b3a7da9..727d1b2 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -884,17 +884,17 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
     if (i830_panel_fitter_pipe (pI830) == pipe)
 	OUTREG(PFIT_CONTROL, 0);
 
-#if 1
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-	       "Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
-    xf86PrintModeline(pScrn->scrnIndex, mode);
-    if (!xf86ModesEqual(mode, adjusted_mode)) {
+    if (pI830->debug_modes) {
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		   "Adjusted mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
+		   "Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
 	xf86PrintModeline(pScrn->scrnIndex, mode);
+	if (!xf86ModesEqual(mode, adjusted_mode)) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		       "Adjusted mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
+	    xf86PrintModeline(pScrn->scrnIndex, mode);
+	}
+	i830PrintPll("chosen", &clock);
     }
-    i830PrintPll("chosen", &clock);
-#endif
 
     if (dpll & DPLL_VCO_ENABLE)
     {
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 229c26b..4ee720f 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -275,6 +275,7 @@ typedef enum {
    OPTION_COLOR_KEY,
    OPTION_CHECKDEVICES,
    OPTION_LINEARALLOC,
+   OPTION_MODEDEBUG,
 #ifdef XF86DRI_MM
    OPTION_INTELTEXPOOL,
    OPTION_INTELMMSIZE,
@@ -296,6 +297,7 @@ static OptionInfoRec I830Options[] = {
    {OPTION_VIDEO_KEY,	"VideoKey",	OPTV_INTEGER,	{0},	FALSE},
    {OPTION_CHECKDEVICES, "CheckDevices",OPTV_BOOLEAN,	{0},	FALSE},
    {OPTION_LINEARALLOC, "LinearAlloc",  OPTV_INTEGER,   {0},    FALSE},
+   {OPTION_MODEDEBUG,	"ModeDebug",	OPTV_BOOLEAN,	{0},	FALSE},
 #ifdef XF86DRI_MM
    {OPTION_INTELTEXPOOL,"Legacy3D",     OPTV_BOOLEAN,	{0},	FALSE},
    {OPTION_INTELMMSIZE, "AperTexSize",  OPTV_INTEGER,	{0},	FALSE},
@@ -975,6 +977,12 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    memcpy(pI830->Options, I830Options, sizeof(I830Options));
    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pI830->Options);
 
+   if (xf86ReturnOptValBool(pI830->Options, OPTION_MODEDEBUG, FALSE)) {
+      pI830->debug_modes = TRUE;
+   } else {
+      pI830->debug_modes = FALSE;
+   }
+
    /* We have to use PIO to probe, because we haven't mapped yet. */
    I830SetPIOAccess(pI830);
 
@@ -1133,8 +1141,10 @@ 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);
+   if (pI830->debug_modes) {
+      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Hardware state on X startup:\n");
+      i830DumpRegs (pScrn);
+   }
 
    i830TakeRegSnapshot(pScrn);
 
@@ -2800,8 +2810,10 @@ I830LeaveVT(int scrnIndex, int flags)
 
    RestoreHWState(pScrn);
 
-   i830CompareRegsToSnapshot(pScrn, "After LeaveVT");
-   i830DumpRegs (pScrn);
+   if (pI830->debug_modes) {
+      i830CompareRegsToSnapshot(pScrn, "After LeaveVT");
+      i830DumpRegs (pScrn);
+   }
 
    if (I830IsPrimary(pScrn))
       i830_unbind_all_memory(pScrn);
@@ -2850,7 +2862,10 @@ I830EnterVT(int scrnIndex, int flags)
    if (!xf86SetDesiredModes (pScrn))
       return FALSE;
    
-   i830DumpRegs (pScrn);
+   if (pI830->debug_modes) {
+      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Hardware state at EnterVT:\n");
+      i830DumpRegs (pScrn);
+   }
    i830DescribeOutputConfiguration(pScrn);
 
    ResetState(pScrn, TRUE);
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index eb533a7..d16eccb 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -473,7 +473,9 @@ i830_lvds_init(ScrnInfoPtr pScrn)
     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)) {
+	    if (pI830->debug_modes &&
+		!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");
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 324d47e..f0723a9 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -214,6 +214,7 @@ static I2CSlaveAddr slaveAddr;
 static void
 i830_sdvo_write_cmd(xf86OutputPtr output, CARD8 cmd, void *args, int args_len)
 {
+    I830Ptr pI830 = I830PTR(output->scrn);
     I830OutputPrivatePtr    intel_output = output->driver_private;
     struct i830_sdvo_priv   *dev_priv = intel_output->dev_priv;
     int			    i;
@@ -222,20 +223,25 @@ i830_sdvo_write_cmd(xf86OutputPtr output
 	ErrorF ("Mismatch slave addr %x != %x\n", slaveAddr, dev_priv->d.SlaveAddr);
 
     /* Write the SDVO command logging */
-    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++)
-	LogWrite(1, "   ");
-    for (i = 0; i < sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]); i++) {
-	if (cmd == sdvo_cmd_names[i].cmd) {
-	    LogWrite(1, "(%s)", sdvo_cmd_names[i].name);
-	    break;
+    if (pI830->debug_modes) {
+	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++)
+	    LogWrite(1, "   ");
+	for (i = 0; i < sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]);
+	     i++)
+	{
+	    if (cmd == sdvo_cmd_names[i].cmd) {
+		LogWrite(1, "(%s)", sdvo_cmd_names[i].name);
+		break;
+	    }
 	}
+	if (i == sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]))
+	    LogWrite(1, "(%02X)", cmd);
+	LogWrite(1, "\n");
     }
-    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++) {
@@ -261,6 +267,7 @@ static const char *cmd_status_names[] = 
 static CARD8
 i830_sdvo_read_response(xf86OutputPtr output, void *response, int response_len)
 {
+    I830Ptr pI830 = I830PTR(output->scrn);
     I830OutputPrivatePtr    intel_output = output->driver_private;
     int			    i;
     CARD8		    status;
@@ -275,19 +282,20 @@ i830_sdvo_read_response(xf86OutputPtr ou
     i830_sdvo_read_byte(output, SDVO_I2C_CMD_STATUS, &status);
 
     /* Write the SDVO command logging */
-    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++)
-	LogWrite(1, "   ");
-    if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP)
-    {
-	LogWrite(1, "(%s)", cmd_status_names[status]);
-    } else {
-	LogWrite(1, "(??? %d)", status);
+    if (pI830->debug_modes) {
+	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++)
+	    LogWrite(1, "   ");
+	if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP) {
+	    LogWrite(1, "(%s)", cmd_status_names[status]);
+	} else {
+	    LogWrite(1, "(??? %d)", status);
+	}
+	LogWrite(1, "\n");
     }
-    LogWrite(1, "\n");
 
     return status;
 }
diff --git a/src/i830_tv.c b/src/i830_tv.c
index df956c9..336214f 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -1312,20 +1312,28 @@ i830_tv_detect_type (xf86CrtcPtr    crtc
      *  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");
+	if (pI830->debug_modes) {
+	    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");
+	if (pI830->debug_modes) {
+	    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");
+	if (pI830->debug_modes) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		       "Detected Component TV connection\n");
+	}
 	type = TV_TYPE_COMPONENT;
     } else {
-	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		"No TV connection detected\n");
+	if (pI830->debug_modes) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		       "No TV connection detected\n");
+	}
 	type = TV_TYPE_NONE;
     }
 
diff-tree 9ea83d440d6b9e30d4627e34168226a6b4b2a841 (from c6d0bf9fb6033339159d98dc2b9fe44759ad9de5)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Apr 2 11:39:27 2007 -0700

    Update README source for new release notes.

diff --git a/README.sgml b/README.sgml
index fd52608..4a67017 100644
--- a/README.sgml
+++ b/README.sgml
@@ -5,14 +5,14 @@
 <article>
 <title>Information for Intel graphics driver users
 <author>Eric Anholt
-<date>2006-08-04
+<date>2006-04-02
 <toc>
 
 <sect>Introduction
 <p>
 This document provides a brief summary of the Intel graphics support provided
 by the xf86-video-intel driver.  More information can also be found in the
-<htmlurl name="i810(4)" url="i810.4.html"> manual page.
+<htmlurl name="intel(4)" url="intel.4.html"> manual page.
 
 <sect>Supported Hardware
 <p>
@@ -41,8 +41,7 @@ by the xf86-video-intel driver.  More in
   <item>Hardware cursor support to reduce sprite flicker.
   <item>Textured video XV implementation on i915 through i965.
   <item>Hardware overlay XV implementation up through i945.
-  <item>Screen resize and rotation on chipsets up through i945.
-  <item>Screen resize on i965.
+  <item>Screen resize and rotation.
 </itemize>
 
 
@@ -53,6 +52,13 @@ by the xf86-video-intel driver.  More in
   <item>This driver  requires kernel support for AGP, which is
 	included in Linux kernels 2.3.42 and higher, and FreeBSD 4.1
 	and higher.
+  <item>This driver may be built against xserver 1.2.0 or newer.  If built
+  from git source against an older server, a copy of xserver 1.3.0 source is
+  needed to complete the build, which is chosen with the --with-xserver-source
+  argument to ./configure.  The compatibility mode with xserver 1.2.0 will have
+  limited functionality, in particular by not supporting RandR 1.2 or the
+  new Damage 1.1 updated needed for 3D applications to work with display
+  rotation.
 </itemize>
 
 
@@ -63,50 +69,58 @@ initialize the card.  The only lines you
 section of your xorg.conf file are:
 <verb>
        Section "Device"
-           Identifier "Intel i810"
-           Driver     "i810"
+           Identifier "intel"
+           Driver     "intel"
        EndSection
 </verb>
 
-In order to use most resolutions, it is necessary to install the
-"agpgart.o" module.  You will probably have to compile the module yourself
-(see the notes in the module).
-
 <sect>Driver Options
 <p>
-Please refer to the <htmlurl name="i810(4)" url="i810.4.html"> manual page
+Please refer to the <htmlurl name="intel(4)" url="intel.4.html"> manual page
 for information on configuration options.
 
 
 <sect>Known Limitations
 <p>
 <itemize>
-  <item>Many systems with Intel graphics have issues with setting video modes
-at larger than some small maximum resolution.  This is not fixed in the current
-release, but is being actively worked on in the modesetting branch.
-  <item>Bug #5795: Some systems have issues with VT switching.  This should
-be fixed with the modesetting brach integration.
-  <item>Bug #5817: Hotkey switching from LVDS to CRT breaks CRT output.  This
-is a known issue, but will not be fixed in the current release.
-  <item>Bug #6635: Video is output from an incorrect offset in the framebuffer.
-This is expected to be fixed with the modesetting branch integration.
-  <item>GL_EXT_texture_compression_s3tc is not supported.  We can't support the
-extension due to patent restrictions on compression, but may be able to support
-an option for partial extension support in the future.  For now, this prevents
-Quake4 and some other games from running.
-  <item>Some X Test Suite cases sometimes fail due to a timeout. These cases
-include: Xt8/XtResizeWindow, Xt8/XtQueryGeometry, Xt9/XtAppAddInput,
-Xt9/XtRemoveInput, Xt9/XtAppAddTimeOut, Xt9/XtRemoveTimeOut, Xt9/XtAddGrab,
-Xt9/XtRemoveGrab.
-  <item>Some X Test Suite cases fail in 64-bit mode: Xlib9/XDrawArc,
-XDrawImageString, XDrawLine, XDrawRectangle, XDrawSegments, XFillArc,
-XFillPolygon, XFillRectangle, XPutImage, Xt11/XtVaGetSubresources,
-XtSetSubvalues, and XtVaSetSubvalues.
-  <item>Some GLEAN test cases fail if DRI is enabled: pointAtten,
-readPixSanity, texCombine, texCube, texEnv, texgen, coloredTexPerf2, and
-coloredLitPerf2.
+  <item>Bug #8534: i830 laptop panels not supported.  The driver
+  will fail to recognize them, and only function through VGA output.  Two
+  partial DVO chip drivers (ivch and ch7017) are included which contain some of
+  the code necessary for i830 laptop panel support, but some I2C debugging will
+  be necessary to get those drivers to attach.
+  <item>No support for "zaphod mode" dualhead.  This is the mode in which two
+  Device sections are placed in the config file, and doesn't support DRI or
+  many other features.  Instead, only "MergedFB-style" dualhead is supported.
+  <item>No support for X Screens larger than 2048 pixels in either direction
+  before the 965.  This reflects hardware limitations in the x direction on
+  those older chips, and limits dualhead functionality.  It may be possible to
+  extend the limit vertically on these older chips.
+  <item>i855 XV may cause hangs.  This was present in the previous release,
+  and no workaround is known.
+  <item>SDVO TV-out cards not supported.  This should be fixed in the next
+  release.
+  <item>Gray output with integrated TV-out.
+  <item>EXA support unstable on i845.
 </itemize>
 
+<sect>Common issues not caused by the driver
+<itemize>
+  <item>Font sizes (DPI) are wrong.  Some displays incorrectly report their
+  physical size, which is harmless on most OSes that always assume 96dpi
+  displays.  This can be fixed through quirks for specific monitors in the X
+  Server, and the output of xrandr --prop along with a physical measurement of
+  the screen size in a bug report against the server can help get that fixed.
+  <item>gnome-panel is located in the middle of the screen.  gnome-panel places
+  itself within head #0's boundaries, which doesn't work well with a second
+  head covering the same area as head #0 but larger.
+  <item>Older resolution-changing applicationss have poor results in
+  multihead systems.  Previous extensions such as RandR 1.1 exposed only a
+  single output to client programs, and those requests map poorly to multi-head
+  systems.  Currently, those requests map to just one of the outputs in the
+  RandR 1.2 environment, and those applications need to be updated to RandR 1.2
+  API when available for better results.
+  <item>
+</itemize>
 
 <sect>Author
 <p>
diff-tree c6d0bf9fb6033339159d98dc2b9fe44759ad9de5 (from c59e5895a0ea1f219c8f63a02b429a024bd1ed66)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Apr 2 10:09:43 2007 -0700

    Remove long-stale TODO file.

diff --git a/TODO b/TODO
deleted file mode 100644
index 17e1449..0000000
--- a/TODO
+++ /dev/null
@@ -1,3 +0,0 @@
-- licensing of new files
-- Figure out what exactly doublescan, interlace mean, and see if we support them.
-- Remove VbeModeInfoData
diff-tree c59e5895a0ea1f219c8f63a02b429a024bd1ed66 (from e119eaabb2ad1ffc1d83f18199f49c52ec71b0fe)
Author: Dave Airlie <airlied at linux.ie>
Date:   Mon Apr 2 07:18:04 2007 +1000

    make warning info only so ppl don't go reporting stupid bugs

diff --git a/src/i830_dri.c b/src/i830_dri.c
index ccc1fac..2203c9e 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -701,9 +701,8 @@ I830DRIScreenInit(ScreenPtr pScreen)
 	 pI830->drmMinor = version->version_minor;
 	 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",
+	       xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+			  "Unable to use TTM-based memory manager with DRM version %d.%d\n",
 			  version->version_major, version->version_minor);
 	       pI830->mmModeFlags &= ~I830_KERNEL_MM;
 
diff-tree e119eaabb2ad1ffc1d83f18199f49c52ec71b0fe (from fd98e88d1a6e0e8d35bda868e7afcb78d2d11524)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Mar 30 17:09:18 2007 -0700

    Warnings cleanup in ch7xxx.

diff --git a/src/ch7xxx/ch7xxx.c b/src/ch7xxx/ch7xxx.c
index 9ce581f..0a96555 100644
--- a/src/ch7xxx/ch7xxx.c
+++ b/src/ch7xxx/ch7xxx.c
@@ -74,11 +74,6 @@ struct ch7xxx_priv {
 
 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 char *ch7xxx_get_id(int vid)
 {
     int i;
@@ -125,7 +120,6 @@ ch7xxx_init(I2CBusPtr b, I2CSlaveAddr ad
     /* this will detect the CH7xxx chip on the specified i2c bus */
     struct ch7xxx_priv *dev_priv;
     CARD8 vendor, device;
-    unsigned char ch;
     char *name;
 
     dev_priv = xcalloc(1, sizeof(struct ch7xxx_priv));
@@ -183,7 +177,7 @@ static xf86OutputStatus
 ch7xxx_detect(I2CDevPtr d)
 {
     struct ch7xxx_priv *dev_priv = d->DriverPrivate.ptr;
-    CARD8 cdet, gpio, orig_pm, pm;
+    CARD8 cdet, orig_pm, pm;
 
     ch7xxx_read(dev_priv, CH7xxx_PM, &orig_pm);
 
diff-tree fd98e88d1a6e0e8d35bda868e7afcb78d2d11524 (from 274b99e5e750228eba9a67773725a40ebaa9bf56)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Mar 30 17:07:29 2007 -0700

    Finish off some function renaming that was missed before.
    
    Thanks to alanc for catching this.

diff --git a/src/ch7017/ch7017.c b/src/ch7017/ch7017.c
index 019dcea..7070c7d 100644
--- a/src/ch7017/ch7017.c
+++ b/src/ch7017/ch7017.c
@@ -59,6 +59,8 @@ struct ch7017_priv {
 
 static void
 ch7017_dump_regs(I2CDevPtr d);
+static void
+ch7017_dpms(I2CDevPtr d, int mode);
 
 static Bool
 ch7017_read(struct ch7017_priv *priv, int addr, CARD8 *val)
@@ -193,7 +195,7 @@ ch7017_mode_set(I2CDevPtr d, DisplayMode
 
     lvds_power_down = (mode->HDisplay & 0x0f00) >> 8;
 
-    ch7017Power(d, FALSE);
+    ch7017_dpms(d, DPMSModeOff);
     ch7017_write(priv, CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT,
 		    horizontal_active_pixel_input);
     ch7017_write(priv, CH7017_HORIZONTAL_ACTIVE_PIXEL_OUTPUT,
@@ -210,7 +212,7 @@ ch7017_mode_set(I2CDevPtr d, DisplayMode
 
     xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO,
 	       "Registers after mode setting\n");
-    ch7017PrintRegs(d);
+    ch7017_dump_regs(d);
 }
 
 /* set the CH7017 power state */
@@ -279,7 +281,7 @@ ch7017_restore(I2CDevPtr d)
     struct ch7017_priv *priv = d->DriverPrivate.ptr;
 
     /* Power down before changing mode */
-    ch7017Power(d, FALSE);
+    ch7017_dpms(d, DPMSModeOff);
 
     ch7017_write(priv, CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT, priv->save_hapi);
     ch7017_write(priv, CH7017_VERTICAL_ACTIVE_LINE_OUTPUT, priv->save_valo);
diff-tree 274b99e5e750228eba9a67773725a40ebaa9bf56 (from aa6a9abb34e93780c07563ab5b21d8c064ea0a1c)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Mar 30 17:06:43 2007 -0700

    Don't forget the warnings CFLAGS in subdirectories.

diff --git a/src/bios_reader/Makefile.am b/src/bios_reader/Makefile.am
index bba969b..8e03693 100644
--- a/src/bios_reader/Makefile.am
+++ b/src/bios_reader/Makefile.am
@@ -1,4 +1,4 @@
-AM_CFLAGS = @XORG_CFLAGS@ @XMODES_CFLAGS@
+AM_CFLAGS = @WARN_CFLAGS@ @XORG_CFLAGS@ @XMODES_CFLAGS@
 
 noinst_PROGRAMS = bios_reader  $(BIOS_DUMPER)
 
diff --git a/src/ch7017/Makefile.am b/src/ch7017/Makefile.am
index 45bf699..d757b3c 100644
--- a/src/ch7017/Makefile.am
+++ b/src/ch7017/Makefile.am
@@ -5,6 +5,8 @@
 # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
 AM_CFLAGS = @XMODES_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@ -I$(srcdir)/.. -I$(srcdir)/../modes
 
+AM_CFLAGS = @WARN_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@ @XMODES_CFLAGS@
+
 ch7017_la_LTLIBRARIES = ch7017.la
 ch7017_la_LDFLAGS = -module -avoid-version
 ch7017_ladir = @moduledir@/drivers
diff --git a/src/ch7xxx/Makefile.am b/src/ch7xxx/Makefile.am
index 68f766c..49a5aa3 100644
--- a/src/ch7xxx/Makefile.am
+++ b/src/ch7xxx/Makefile.am
@@ -3,7 +3,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 = @XMODES_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@ -I$(srcdir)/.. -I$(srcdir)/../modes
+AM_CFLAGS = @WARN_CFLAGS@ @XMODES_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/ivch/Makefile.am b/src/ivch/Makefile.am
index ace076c..cf05c01 100644
--- a/src/ivch/Makefile.am
+++ b/src/ivch/Makefile.am
@@ -3,7 +3,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 = @XMODES_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@ -I$(srcdir)/.. -I$(srcdir)/../modes
+AM_CFLAGS = @WARN_CFLAGS@ @XMODES_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/sil164/Makefile.am b/src/sil164/Makefile.am
index ac1b33c..de17bd0 100644
--- a/src/sil164/Makefile.am
+++ b/src/sil164/Makefile.am
@@ -3,7 +3,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 = @XMODES_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@ -I$(srcdir)/.. -I$(srcdir)/../modes
+AM_CFLAGS = @WARN_CFLAGS@ @XMODES_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/xvmc/Makefile.am b/src/xvmc/Makefile.am
index a9ea9d1..b5c9db9 100644
--- a/src/xvmc/Makefile.am
+++ b/src/xvmc/Makefile.am
@@ -3,7 +3,8 @@ lib_LTLIBRARIES=libI810XvMC.la
 libI810XvMC_la_SOURCES = I810XvMC.c \
 			 I810XvMC.h
 
-libI810XvMC_la_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ -I$(top_srcdir)/src -DTRUE=1 -DFALSE=0
+libI810XvMC_la_CFLAGS = @WARN_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@ \
+	-I$(top_srcdir)/src -DTRUE=1 -DFALSE=0
 libI810XvMC_la_LDFLAGS = -version-number 1:0:0
 libI810XvMC_la_LIBADD = @DRI_LIBS@ 
 endif
diff-tree aa6a9abb34e93780c07563ab5b21d8c064ea0a1c (from parents)
Merge: 670c8521f18f01b9ea899ceb68d2a3dbb884b199 107ac12867eda6b86212159db15c640d3490f2da
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Fri Mar 30 12:10:17 2007 -0700

    Merge branch 'crestline-qa'

diff-tree 670c8521f18f01b9ea899ceb68d2a3dbb884b199 (from 89c84f939f2dbed1d03a5f0e1daae23a229e47bc)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Mar 29 13:43:31 2007 -0700

    Add missing file for old server compatibility build.

diff --git a/src/Makefile.am b/src/Makefile.am
index 830ce69..2b5799c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -46,6 +46,7 @@ XMODE_SRCS=\
 	 modes/xf86cvt.c \
 	 modes/xf86Crtc.h \
 	 modes/xf86Crtc.c \
+	 modes/xf86Cursors.c \
 	 modes/xf86EdidModes.c \
 	 modes/xf86RandR12.c \
 	 modes/xf86RandR12.h \
diff-tree 89c84f939f2dbed1d03a5f0e1daae23a229e47bc (from 6cd3b2c2de4596886aab85988b16cf63e8887add)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Mar 29 13:40:52 2007 -0700

    Whitespace cleanup in Makefile.

diff --git a/src/Makefile.am b/src/Makefile.am
index bd64f50..830ce69 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -46,19 +46,19 @@ XMODE_SRCS=\
 	 modes/xf86cvt.c \
 	 modes/xf86Crtc.h \
 	 modes/xf86Crtc.c \
-         modes/xf86EdidModes.c \
+	 modes/xf86EdidModes.c \
 	 modes/xf86RandR12.c \
 	 modes/xf86RandR12.h \
 	 modes/xf86Rename.h \
 	 modes/xf86Rotate.c \
 	 modes/xf86DiDGA.c
-	 
+
 INTEL_DRI_SRCS = \
          i810_dri.c \
          i810_dri.h \
          i830_dri.c \
          i810_hwmc.c \
-         i830_dri.h 
+         i830_dri.h
 
 intel_drv_la_SOURCES = \
          brw_defines.h \
@@ -144,24 +144,24 @@ EXTRA_DIST = 		\
 	$(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_mask_prog.h: exa_sf_mask.g4a
 	intel-gen4asm -o exa_sf_mask_prog.h exa_sf_mask.g4a
-	
+
 exa_sf_prog.h: exa_sf.g4a
 	intel-gen4asm -o exa_sf_prog.h exa_sf.g4a
 
 exa_sf_rotation_prog.h: exa_sf_rotation.g4a
 	intel-gen4asm -o exa_sf_rotation_prog.h exa_sf_rotation.g4a
-	
+
 exa_wm_maskca_prog.h: exa_wm_maskca.g4a
 	intel-gen4asm -o exa_wm_maskca_prog.h exa_wm_maskca.g4a
 
@@ -170,13 +170,13 @@ exa_wm_maskca_srcalpha_prog.h: exa_wm_ma
 
 exa_wm_masknoca_prog.h: exa_wm_masknoca.g4a
 	intel-gen4asm -o exa_wm_masknoca_prog.h exa_wm_masknoca.g4a
-	
+
 exa_wm_nomask_prog.h: exa_wm_nomask.g4a
 	intel-gen4asm -o exa_wm_nomask_prog.h exa_wm_nomask.g4a
 
 exa_wm_rotation_prog.h: exa_wm_rotation.g4a
 	intel-gen4asm -o exa_wm_rotation_prog.h exa_wm_rotation.g4a
-	
+
 endif
 
 if XMODES
diff-tree 6cd3b2c2de4596886aab85988b16cf63e8887add (from 35b3dd881a333569ce20ddf36b915b095757a1ba)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Tue Mar 27 15:34:32 2007 +0800

    EXA: i830 fix blend action
    
    i830_get_blend_cntl() has already added S8 offset.

diff --git a/src/i830_render.c b/src/i830_render.c
index 9b8f2da..d587805 100644
--- a/src/i830_render.c
+++ b/src/i830_render.c
@@ -486,7 +486,7 @@ i830_prepare_composite(int op, PicturePt
 
 	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) |
+	OUT_RING(S8_ENABLE_COLOR_BLEND | S8_BLENDFUNC_ADD | blendctl | 
 		 S8_ENABLE_COLOR_BUFFER_WRITE);
 	ADVANCE_LP_RING();
     }
diff-tree 35b3dd881a333569ce20ddf36b915b095757a1ba (from df96d9a11d038ad64673022ce14c24223b3bd34c)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Tue Mar 27 15:33:43 2007 +0800

    EXA: fix i830 componentAlpha support
    
    Pick fix from i915 render, change tex blend pipeline for CA.

diff --git a/src/i830_render.c b/src/i830_render.c
index 33a8a8a..9b8f2da 100644
--- a/src/i830_render.c
+++ b/src/i830_render.c
@@ -205,7 +205,8 @@ static CARD32 i830_get_blend_cntl(int op
      * 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 && i830_blend_op[op].src_alpha) {
+    if (pMask && pMask->componentAlpha && PICT_FORMAT_RGB(pMask->format) 
+	    && i830_blend_op[op].src_alpha) {
         if (dblend == BLENDFACTOR_SRC_ALPHA) {
             dblend = BLENDFACTOR_SRC_COLR;
         } else if (dblend == BLENDFACTOR_INV_SRC_ALPHA) {
@@ -339,7 +340,8 @@ i830_check_composite(int op, PicturePtr 
     if (op >= sizeof(i830_blend_op) / sizeof(i830_blend_op[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.
@@ -456,10 +458,17 @@ i830_prepare_composite(int op, PicturePt
 	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);
+	    if (pMaskPicture->componentAlpha && 
+		    PICT_FORMAT_RGB(pMaskPicture->format)) {
+		if (i830_blend_op[op].src_alpha)
+		    cblend |= (TB0C_ARG2_SEL_TEXEL1 | 
+			    TB0C_ARG1_REPLICATE_ALPHA);
+		else 
+		    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;
diff-tree df96d9a11d038ad64673022ce14c24223b3bd34c (from aa78e67553ffe8ca986330f0ee49b5414c71a71f)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Tue Mar 27 15:32:53 2007 +0800

    EXA: fix i830 texture setup
    
    Use LOAD_IMM_2 helper cmd for tex setup. Enable RepeatNormal
    support. Fix A8 format, i830 can support it now.

diff --git a/src/i830_reg.h b/src/i830_reg.h
index f9c1df9..989646f 100644
--- a/src/i830_reg.h
+++ b/src/i830_reg.h
@@ -648,6 +648,7 @@
 #define    MT_8BIT_IDX_ARGB8888	           (7<<3)
 #define    MT_8BIT_I8		           (0<<3) /* SURFACE_8BIT */
 #define    MT_8BIT_L8		           (1<<3)
+#define    MT_8BIT_A8		           (4<<3)
 #define    MT_16BIT_RGB565 		   (0<<3) /* SURFACE_16BIT */
 #define    MT_16BIT_ARGB1555		   (1<<3)
 #define    MT_16BIT_ARGB4444		   (2<<3)
diff --git a/src/i830_render.c b/src/i830_render.c
index 49d8fc1..33a8a8a 100644
--- a/src/i830_render.c
+++ b/src/i830_render.c
@@ -149,12 +149,11 @@ static struct formatinfo i830_tex_format
     {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       },	 /* mesa does I8 */
 };
 
 static Bool i830_get_dest_format(PicturePtr pDstPicture, CARD32 *dst_format)
 {
-    /* XXX: color buffer format for i830 */
     switch (pDstPicture->format) {
     case PICT_a8r8g8b8:
     case PICT_x8r8g8b8:
@@ -167,9 +166,11 @@ static Bool i830_get_dest_format(Picture
     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;
@@ -235,9 +236,8 @@ static Bool i830_check_composite_texture
         I830FALLBACK("Unsupported picture format 0x%x\n",
 		     (int)pPict->format);
 
-    /* FIXME: fix repeat support */
-    if (pPict->repeat)
-	I830FALLBACK("repeat unsupport now\n");
+    if (pPict->repeat && pPict->repeatType != RepeatNormal)
+	I830FALLBACK("unsupport repeat type\n");
 
     if (pPict->filter != PictFilterNearest &&
         pPict->filter != PictFilterBilinear)
@@ -248,6 +248,19 @@ static Bool i830_check_composite_texture
     return TRUE;
 }
 
+static CARD32
+i8xx_get_card_format(PicturePtr pPict)
+{
+    int i;
+    for (i = 0; i < sizeof(i830_tex_formats) / sizeof(i830_tex_formats[0]);
+	    i++)
+    {
+	if (i830_tex_formats[i].fmt == pPict->format)
+	    break;
+    }
+    return i830_tex_formats[i].card_fmt;
+}
+
 static Bool
 i830_texture_setup(PicturePtr pPict, PixmapPtr pPix, int unit)
 {
@@ -255,28 +268,18 @@ i830_texture_setup(PicturePtr pPict, Pix
     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_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;
+    pI830->transform[unit] = pPict->transform;
 
-    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(i830_tex_formats)/ sizeof(i830_tex_formats[0]))
-	I830FALLBACK("unknown texture format\n");
-    format = i830_tex_formats[i].card_fmt;
+    format = i8xx_get_card_format(pPict);
 
     if (pPict->repeat)
-	wrap_mode = TEXCOORDMODE_WRAP; /* XXX: correct ? */
+	wrap_mode = TEXCOORDMODE_WRAP;
 
     switch (pPict->filter) {
     case PictFilterNearest:
@@ -291,51 +294,32 @@ i830_texture_setup(PicturePtr pPict, Pix
 	filter = 0;
         I830FALLBACK("Bad filter 0x%x\n", pPict->filter);
     }
+    filter |= (MIPFILTER_NONE << TM0S3_MIP_FILTER_SHIFT); 
 
     {
 	if (pPix->drawable.bitsPerPixel == 8)
-		format |= MAP_SURFACE_8BIT;
+	    format |= MAPSURF_8BIT;
 	else if (pPix->drawable.bitsPerPixel == 16)
-		format |= MAP_SURFACE_16BIT;
+	    format |= MAPSURF_16BIT;
 	else
-		format |= MAP_SURFACE_32BIT;
+	    format |= MAPSURF_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 */
+	BEGIN_LP_RING(8);
+	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | LOAD_TEXTURE_MAP(unit) | 4);
+	OUT_RING((offset & TM0S0_ADDRESS_MASK) | TM0S0_USE_FENCE); 
+	OUT_RING(((pPix->drawable.height - 1) << TM0S1_HEIGHT_SHIFT) |
+		((pPix->drawable.width - 1) << TM0S1_WIDTH_SHIFT) | format);
+	OUT_RING((pitch/4 - 1) << TM0S2_PITCH_SHIFT | TM0S2_MAP_2D);
+	OUT_RING(filter);
+	OUT_RING(0); /* default color */
 	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...");
@@ -382,7 +366,6 @@ i830_prepare_composite(int op, PicturePt
 		       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;
@@ -407,7 +390,7 @@ i830_prepare_composite(int op, PicturePt
     {
 	CARD32 cblend, ablend, blendctl, vf2;
 
-	BEGIN_LP_RING(22+6);
+	BEGIN_LP_RING(34);
 
 	/* color buffer */
 	OUT_RING(_3DSTATE_BUF_INFO_CMD);
@@ -430,6 +413,14 @@ i830_prepare_composite(int op, PicturePt
 	OUT_RING(_3DSTATE_DFLT_SPEC_CMD);
 	OUT_RING(0);
 
+	OUT_RING(_3DSTATE_DRAW_RECT_CMD);
+	OUT_RING(0);
+	OUT_RING(0); /* ymin, xmin */
+	OUT_RING(DRAW_YMAX(pDst->drawable.height - 1) |
+		DRAW_XMAX(pDst->drawable.width - 1));
+	OUT_RING(0); /* yorig, xorig */
+	OUT_RING(MI_NOOP);
+
 	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);
diff-tree aa78e67553ffe8ca986330f0ee49b5414c71a71f (from parents)
Merge: 768821bd3832aad01e44856199e60c6b7726a83b 2191634dd67b3219bb88f365bcf951d5a58140e8
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Mar 26 22:00:36 2007 -0700

    Merge branch 'master' of git+ssh://git.freedesktop.org/git/xorg/driver/xf86-video-intel

diff-tree 107ac12867eda6b86212159db15c640d3490f2da (from parents)
Merge: 654881794ae1ad7214e85091b9015ae0fbdc5ddc 2191634dd67b3219bb88f365bcf951d5a58140e8
Author: Nian Wu <nian.wu at intel.com>
Date:   Tue Mar 27 12:51:45 2007 +0800

    Merge git://proxy01.pd.intel.com:9419/git/xorg/driver/xf86-video-intel into crestline

diff-tree 768821bd3832aad01e44856199e60c6b7726a83b (from 1c809f92467f97b098bcc89d66e60f6f88d9bade)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Mar 26 21:27:54 2007 -0700

    Bump version to 1.9.93 for 2.0RC3.

diff --git a/configure.ac b/configure.ac
index 451179d..dccfd75 100644
--- a/configure.ac
+++ b/configure.ac
@@ -22,7 +22,7 @@
 
 AC_PREREQ(2.57)
 AC_INIT([xf86-video-intel],
-        1.9.92,
+        1.9.93,
         [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
         xf86-video-intel)
 
diff-tree 2191634dd67b3219bb88f365bcf951d5a58140e8 (from 1c809f92467f97b098bcc89d66e60f6f88d9bade)
Author: Alan Coopersmith <alan.coopersmith at sun.com>
Date:   Mon Mar 26 14:58:41 2007 -0700

    Add Solaris to list of OS'es with agpgart in man page

diff --git a/man/intel.man b/man/intel.man
index 0268d0b..3197feb 100644
--- a/man/intel.man
+++ b/man/intel.man
@@ -38,7 +38,7 @@ memory for video use is required in orde
 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, FreeBSD, OpenBSD,
-and NetBSD have such kernel drivers available.
+NetBSD, and Solaris have such kernel drivers available.
 .PP
 By default, the i810 will use 8 megabytes
 of system memory for graphics.  For the 830M and later, the driver will
diff-tree 1c809f92467f97b098bcc89d66e60f6f88d9bade (from f7befe50af4c13554d1f7aee6b05848ac312411b)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Mar 26 13:03:28 2007 -0700

    Update .gitignore.

diff --git a/.gitignore b/.gitignore
index cb52e9f..8109409 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,6 +15,7 @@ config.log
 config.status
 config.sub
 configure
+configure.lineno
 depcomp
 install-sh
 libtool
@@ -22,3 +23,4 @@ ltmain.sh
 missing
 stamp-h1
 i810.4
+intel.4
diff-tree f7befe50af4c13554d1f7aee6b05848ac312411b (from 827dc457a4fd0b97c95ec696ec9c3cd2f4a4becb)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Mar 26 13:01:11 2007 -0700

    Power on the LVDS B-channel pairs only when we've chosen dual-channel mode.
    
    It was basing off of the clock rate, but we have an override to use the
    existing dual channel state when we can detect it, so the two settings were
    conflicting.

diff --git a/src/i830_display.c b/src/i830_display.c
index d55e0a6..48ea2bc 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -916,7 +916,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
 	/* Set the B0-B3 data pairs corresponding to whether we're going to
 	 * set the DPLLs for dual-channel mode or not.
 	 */
-	if (adjusted_mode->Clock >= I9XX_P2_LVDS_SLOW_LIMIT)
+	if (clock.p2 == 7)
 	    lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
 	else
 	    lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
diff-tree 827dc457a4fd0b97c95ec696ec9c3cd2f4a4becb (from d5727717c9141be28a69b1154ccd23c23207f8f6)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Mar 26 12:45:23 2007 -0700

    Update manpage to remove Rotate option and point at xorg.conf instead.
    
    While here, update a few other bits as well.

diff --git a/man/intel.man b/man/intel.man
index 32aa7c1..0268d0b 100644
--- a/man/intel.man
+++ b/man/intel.man
@@ -37,25 +37,23 @@ i815 family of chipset, operating 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.
+achieved with an "agpgart" or "agp" kernel driver.  Linux, 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
+By default, the i810 will use 8 megabytes
+of system memory for graphics.  For the 830M and later, the driver will
+automatically size its memory allocation according to the features it will
+support.  The amount of memory used may be limited by using 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
+section.  Limiting the amount of memory used may result in features being
+disabled, so if you choose to configure it, it is advisable to check the
 __xservername__
-log file to check if any features have been disabled because of insufficient
+log file to see 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.
+reduce performance for 3D applications.
 .PP
 The following driver
 .B Options
@@ -123,13 +121,6 @@ other drivers.
 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
@@ -185,6 +176,13 @@ Choose acceleration architecture, either
 simpler acceleration architecture designed to better accelerate the X Render
 extension.  Default: "XAA".
 
+.PP
+The 830M and newer driver supports RandR 1.2, exposing the VGA, LVDS
+(laptop panel), TMDS (DVI on SDVO/DVO cards), and TV (on 915GM/945GM)
+outputs.  Per-output configuration is done through the
+.B Monitor
+section of __xconfigfile__(__filemansuffix__).
+
 .SH "SEE ALSO"
 __xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), xorgconfig(__appmansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__)
 .SH AUTHORS
diff-tree 654881794ae1ad7214e85091b9015ae0fbdc5ddc (from parents)
Merge: 6de3edcb52e6258f1af75e4f4bef73de1698445d d5727717c9141be28a69b1154ccd23c23207f8f6
Author: Nian Wu <nian.wu at intel.com>
Date:   Mon Mar 26 17:00:11 2007 +0800

    Merge git://proxy01.pd.intel.com:9419/git/xorg/driver/xf86-video-intel into crestline

diff-tree d5727717c9141be28a69b1154ccd23c23207f8f6 (from 1e6e675524461ef0eb1983de89e2877426571a55)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Sun Mar 25 23:44:59 2007 -0700

    Switch TV_FORMAT property to format XA_ATOM
    
    This allows the driver to report the set of valid formats in the property
    data.

diff --git a/src/i830_tv.c b/src/i830_tv.c
index 43a4dd4..df956c9 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -754,6 +754,8 @@ const static tv_mode_t tv_modes[] = {
     },
 };
 
+#define NUM_TV_MODES sizeof(tv_modes) / sizeof (tv_modes[0])
+
 static const video_levels_t component_level = {
 	.blank = 279, .black = 279 
 };
@@ -1450,10 +1452,29 @@ i830_tv_destroy (xf86OutputPtr output)
 #ifdef RANDR_12_INTERFACE
 #define TV_FORMAT_NAME	"TV_FORMAT"
 static Atom tv_format_atom;
+static Atom tv_format_name_atoms[NUM_TV_MODES];
 static Atom margin_atoms[4];
 static char *margin_names[4] = {
     "LEFT", "TOP", "RIGHT", "BOTTOM"
 };
+
+static Bool
+i830_tv_format_set_property (xf86OutputPtr output)
+{
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    struct i830_tv_priv	    *dev_priv = intel_output->dev_priv;
+    const tv_mode_t	    *tv_mode = i830_tv_mode_lookup (dev_priv->tv_format);
+    int			    err;
+
+    if (!tv_mode)
+	tv_mode = &tv_modes[0];
+    err = RRChangeOutputProperty (output->randr_output, tv_format_atom,
+				  XA_ATOM, 32, PropModeReplace, 1,
+				  &tv_format_name_atoms[tv_mode - tv_modes],
+				  FALSE, TRUE);
+    return err == Success;
+}
+
 #endif /* RANDR_12_INTERFACE */
 
 static void
@@ -1472,8 +1493,14 @@ i830_tv_create_resources(xf86OutputPtr o
     tv_format_atom = MakeAtom(TV_FORMAT_NAME, sizeof(TV_FORMAT_NAME) - 1,
 	TRUE);
 
+    for (i = 0; i < NUM_TV_MODES; i++)
+	tv_format_name_atoms[i] = MakeAtom (tv_modes[i].name,
+					    strlen (tv_modes[i].name),
+					    TRUE);
+
     err = RRConfigureOutputProperty(output->randr_output, tv_format_atom,
-				    TRUE, FALSE, FALSE, 0, NULL);
+				    TRUE, FALSE, FALSE, 
+				    NUM_TV_MODES, (INT32 *) tv_format_name_atoms);
     
     if (err != 0) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
@@ -1481,15 +1508,9 @@ i830_tv_create_resources(xf86OutputPtr o
     }
 
     /* Set the current value of the tv_format property */
-    err = RRChangeOutputProperty(output->randr_output, tv_format_atom,
-				 XA_STRING, 8, PropModeReplace,
-				 strlen (dev_priv->tv_format),
-				 dev_priv->tv_format,
-				 FALSE, TRUE);
-    if (err != 0) {
+    if (!i830_tv_format_set_property (output))
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		   "RRChangeOutputProperty error, %d\n", err);
-    }
 
     for (i = 0; i < 4; i++)
     {
@@ -1502,20 +1523,17 @@ i830_tv_create_resources(xf86OutputPtr o
 	err = RRConfigureOutputProperty(output->randr_output, margin_atoms[i],
 				    TRUE, TRUE, FALSE, 2, range);
     
-	if (err != 0) {
+	if (err != 0)
 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		       "RRConfigureOutputProperty error, %d\n", err);
-	}
 
-	/* Set the current value of the tv_format property */
 	err = RRChangeOutputProperty(output->randr_output, margin_atoms[i],
 				     XA_INTEGER, 32, PropModeReplace,
 				     1, &dev_priv->margin[i],
 				     FALSE, TRUE);
-	if (err != 0) {
+	if (err != 0)
 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		       "RRChangeOutputProperty error, %d\n", err);
-	}
     }
 #endif /* RANDR_12_INTERFACE */
 }
@@ -1531,16 +1549,20 @@ i830_tv_set_property(xf86OutputPtr outpu
     {
 	I830OutputPrivatePtr    intel_output = output->driver_private;
 	struct i830_tv_priv	*dev_priv = intel_output->dev_priv;
+	Atom			atom;
+	char			*name;
 	char			*val;
 
-	if (value->type != XA_STRING || value->format != 8)
+	if (value->type != XA_ATOM || value->format != 32 || value->size != 1)
 	    return FALSE;
 
-	val = xalloc (value->size + 1);
+	memcpy (&atom, value->data, 4);
+	name = NameForAtom (atom);
+	
+	val = xalloc (strlen (name) + 1);
 	if (!val)
 	    return FALSE;
-	memcpy (val, value->data, value->size);
-	val[value->size] = '\0';
+	strcpy (val, name);
 	if (!i830_tv_mode_lookup (val))
 	{
 	    xfree (val);
diff-tree 6de3edcb52e6258f1af75e4f4bef73de1698445d (from parents)
Merge: d874aa31599da4777438cc51469afe9b66601f55 1e6e675524461ef0eb1983de89e2877426571a55
Author: Nian Wu <nian.wu at intel.com>
Date:   Sat Mar 24 17:00:13 2007 +0800

    Merge git://proxy01.pd.intel.com:9419/git/xorg/driver/xf86-video-intel into crestline

diff-tree 1e6e675524461ef0eb1983de89e2877426571a55 (from 28da6f4e307880326dd553f50fe3fff3b9be9f4f)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Fri Mar 23 23:42:52 2007 -0700

    Eliminate calls to RRPostPendingProperty.
    
    RRPostPendingProperty has been removed in favor of RRPostPendingProperties,
    and that call is now managed outside of the driver.

diff --git a/src/i830_tv.c b/src/i830_tv.c
index ac521c1..43a4dd4 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -1486,7 +1486,6 @@ i830_tv_create_resources(xf86OutputPtr o
 				 strlen (dev_priv->tv_format),
 				 dev_priv->tv_format,
 				 FALSE, TRUE);
-    RRPostPendingProperty (output->randr_output, tv_format_atom);
     if (err != 0) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		   "RRChangeOutputProperty error, %d\n", err);
@@ -1513,7 +1512,6 @@ i830_tv_create_resources(xf86OutputPtr o
 				     XA_INTEGER, 32, PropModeReplace,
 				     1, &dev_priv->margin[i],
 				     FALSE, TRUE);
-	RRPostPendingProperty (output->randr_output, margin_atoms[i]);
 	if (err != 0) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		       "RRChangeOutputProperty error, %d\n", err);
@@ -1522,16 +1520,6 @@ i830_tv_create_resources(xf86OutputPtr o
 #endif /* RANDR_12_INTERFACE */
 }
 
-static void
-i830_tv_commit (xf86OutputPtr output)
-{
-#ifdef RANDR_12_INTERFACE
-    if (output->randr_output)
-	RRPostPendingProperty (output->randr_output, tv_format_atom);
-#endif    
-    i830_output_commit (output);
-}
-
 #ifdef RANDR_12_INTERFACE
 static Bool
 i830_tv_set_property(xf86OutputPtr output, Atom property,
@@ -1593,7 +1581,7 @@ static const xf86OutputFuncsRec i830_tv_
     .mode_fixup = i830_tv_mode_fixup,
     .prepare = i830_output_prepare,
     .mode_set = i830_tv_mode_set,
-    .commit = i830_tv_commit,
+    .commit = i830_output_commit,
     .detect = i830_tv_detect,
     .get_modes = i830_tv_get_modes,
     .destroy = i830_tv_destroy,
diff-tree 28da6f4e307880326dd553f50fe3fff3b9be9f4f (from ab19439cf4592e4607dc0bfc602aba3d56645a42)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Fri Mar 23 14:36:42 2007 -0700

    Record 3D state loss at EnterVT in last_3d value.
    
    last_3d set to LAST_3D_OTHER indicates that the 3D hardware has unknown
    state.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 624f986..893f491 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2903,6 +2903,7 @@ I830EnterVT(int scrnIndex, int flags)
 
    /* Force invarient 3D state to be emitted */
    *pI830->used3D = 1<<31;
+   pI830->last_3d = LAST_3D_OTHER;
 
    return TRUE;
 }
diff-tree ab19439cf4592e4607dc0bfc602aba3d56645a42 (from 26f32ef680a19e63af4b7c8c84141fe32263f298)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Fri Mar 23 14:34:27 2007 -0700

    Don't call AdjustFrame on EnterVT.
    
    AdjustFrame is strictly for legacy compatibility; calling it on EnterVT
    wrecks crtc positions.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index f41beb0..624f986 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2734,7 +2734,7 @@ i830AdjustFrame(int scrnIndex, int x, in
    {
       /* Sync the engine before adjust frame */
       i830WaitSync(pScrn);
-      i830PipeSetBase(crtc, output->initial_x + x, output->initial_y + y);
+      i830PipeSetBase(crtc, crtc->desiredX + x, crtc->desiredY + y);
       crtc->x = output->initial_x + x;
       crtc->y = output->initial_y + y;
    }
@@ -2851,8 +2851,6 @@ I830EnterVT(int scrnIndex, int flags)
    ResetState(pScrn, TRUE);
    SetHWOperatingState(pScrn);
 
-   pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
-
 #ifdef XF86DRI
    if (pI830->directRenderingEnabled) {
 
diff-tree d874aa31599da4777438cc51469afe9b66601f55 (from parents)
Merge: 94dbc3725358d63fe0ac8e6749489c993d24ede2 26f32ef680a19e63af4b7c8c84141fe32263f298
Author: Nian Wu <nian.wu at intel.com>
Date:   Fri Mar 23 17:00:12 2007 +0800

    Merge git://proxy01.pd.intel.com:9419/git/xorg/driver/xf86-video-intel into crestline

diff-tree 26f32ef680a19e63af4b7c8c84141fe32263f298 (from f48dc501fbf74e0ac348f0b77750016597849ef4)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Fri Mar 23 01:17:58 2007 -0700

    Property size is in units, not bytes.
    
    Several places were using byte lengths instead of unit lengths for
    properties.

diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index 8248510..a05d15d 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -334,7 +334,7 @@ i830_lvds_create_resources(xf86OutputPtr
     /* 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,
+				 XA_INTEGER, 32, PropModeReplace, 1, &data,
 				 FALSE, TRUE);
     if (err != 0) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
@@ -356,7 +356,7 @@ i830_lvds_set_property(xf86OutputPtr out
 	INT32 val;
 
 	if (value->type != XA_INTEGER || value->format != 32 ||
-	    value->size != 4)
+	    value->size != 1)
 	{
 	    return FALSE;
 	}
diff --git a/src/i830_tv.c b/src/i830_tv.c
index dc58cd6..ac521c1 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -1511,7 +1511,7 @@ i830_tv_create_resources(xf86OutputPtr o
 	/* Set the current value of the tv_format property */
 	err = RRChangeOutputProperty(output->randr_output, margin_atoms[i],
 				     XA_INTEGER, 32, PropModeReplace,
-				     4, &dev_priv->margin[i],
+				     1, &dev_priv->margin[i],
 				     FALSE, TRUE);
 	RRPostPendingProperty (output->randr_output, margin_atoms[i]);
 	if (err != 0) {
diff-tree f48dc501fbf74e0ac348f0b77750016597849ef4 (from 20b26854abdacb6dc45cba2d81d515b2e47e25f1)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Fri Mar 23 01:08:08 2007 -0700

    TV output properties: TV_FORMAT, LEFT, TOP, RIGHT, BOTTOM.
    
    Remove TV format from mode name, instead use an explicit output property and
    split the input resolution from the tv format. Add properties to set the
    blank area on all four sides of the image.

diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index 6f7750a..8248510 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -335,7 +335,7 @@ i830_lvds_create_resources(xf86OutputPtr
     data = pI830->backlight_duty_cycle;
     err = RRChangeOutputProperty(output->randr_output, backlight_atom,
 				 XA_INTEGER, 32, PropModeReplace, 4, &data,
-				 FALSE);
+				 FALSE, TRUE);
     if (err != 0) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		   "RRChangeOutputProperty error, %d\n", err);
@@ -356,7 +356,7 @@ i830_lvds_set_property(xf86OutputPtr out
 	INT32 val;
 
 	if (value->type != XA_INTEGER || value->format != 32 ||
-	    value->size != 1)
+	    value->size != 4)
 	{
 	    return FALSE;
 	}
@@ -365,8 +365,11 @@ i830_lvds_set_property(xf86OutputPtr out
 	if (val < 0 || val > i830_lvds_get_max_backlight(pScrn))
 	    return FALSE;
 
-	i830_lvds_set_backlight(pScrn, val);
-	pI830->backlight_duty_cycle = val;
+	if (val != pI830->backlight_duty_cycle)
+	{
+	    i830_lvds_set_backlight(pScrn, val);
+	    pI830->backlight_duty_cycle = val;
+	}
 	return TRUE;
     }
 
diff --git a/src/i830_tv.c b/src/i830_tv.c
index d7f4f56..dc58cd6 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -36,7 +36,9 @@
 #include "xf86.h"
 #include "i830.h"
 #include "i830_display.h"
+#include "X11/Xatom.h"
 #include <string.h>
+
 enum tv_type {
     TV_TYPE_NONE,
     TV_TYPE_UNKNOWN,
@@ -45,9 +47,16 @@ enum tv_type {
     TV_TYPE_COMPONENT
 };
 
+enum tv_margin {
+    TV_MARGIN_LEFT, TV_MARGIN_TOP,
+    TV_MARGIN_RIGHT, TV_MARGIN_BOTTOM
+};
+
 /** Private structure for the integrated TV support */
 struct i830_tv_priv {
     int type;
+    char *tv_format;
+    int margin[4];
     CARD32 save_TV_H_CTL_1;
     CARD32 save_TV_H_CTL_2;
     CARD32 save_TV_H_CTL_3;
@@ -151,6 +160,7 @@ static const CARD32 filter_table[] = {
 typedef struct {
     char *name;
     int	clock;
+    double refresh;
     CARD32 oversample;
     int hsync_end, hblank_start, hblank_end, htotal;
     Bool progressive, trilevel_sync, component_only;
@@ -215,6 +225,7 @@ const static tv_mode_t tv_modes[] = {
     {
 	.name		= "NTSC-M",
 	.clock		= 107520,	
+	.refresh	= 29.97,
 	.oversample	= TV_OVERSAMPLE_8X,
 	.component_only = 0,
 	/* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */
@@ -265,6 +276,7 @@ const static tv_mode_t tv_modes[] = {
     {
 	.name		= "NTSC-443",
 	.clock		= 107520,	
+	.refresh	= 29.97,
 	.oversample	= TV_OVERSAMPLE_8X,
 	.component_only = 0,
 	/* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 4.43MHz */
@@ -314,6 +326,7 @@ const static tv_mode_t tv_modes[] = {
     {
 	.name		= "NTSC-J",
 	.clock		= 107520,	
+	.refresh	= 29.97,
 	.oversample	= TV_OVERSAMPLE_8X,
 	.component_only = 0,
 
@@ -364,6 +377,7 @@ const static tv_mode_t tv_modes[] = {
     {
 	.name		= "PAL-M",
 	.clock		= 107520,	
+	.refresh	= 29.97,
 	.oversample	= TV_OVERSAMPLE_8X,
 	.component_only = 0,
 
@@ -415,6 +429,7 @@ const static tv_mode_t tv_modes[] = {
 	/* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */
 	.name	    = "PAL-N",
 	.clock		= 107520,	
+	.refresh	= 25.0,
 	.oversample	= TV_OVERSAMPLE_8X,
 	.component_only = 0,
 
@@ -467,6 +482,7 @@ const static tv_mode_t tv_modes[] = {
 	/* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */
 	.name	    = "PAL",
 	.clock		= 107520,	
+	.refresh	= 25.0,
 	.oversample	= TV_OVERSAMPLE_8X,
 	.component_only = 0,
 
@@ -516,6 +532,7 @@ const static tv_mode_t tv_modes[] = {
     {
 	.name       = "480p at 59.94Hz",
 	.clock 	= 107520,	
+	.refresh	= 59.94,
 	.oversample     = TV_OVERSAMPLE_4X,
 	.component_only = 1,
 
@@ -539,6 +556,7 @@ const static tv_mode_t tv_modes[] = {
     {
 	.name       = "480p at 60Hz",
 	.clock 	= 107520,	
+	.refresh	= 60.0,
 	.oversample     = TV_OVERSAMPLE_4X,
 	.component_only = 1,
 
@@ -562,6 +580,7 @@ const static tv_mode_t tv_modes[] = {
     {
 	.name       = "576p",
 	.clock 	= 107520,	
+	.refresh	= 59.94,
 	.oversample     = TV_OVERSAMPLE_4X,
 	.component_only = 1,
 
@@ -585,6 +604,7 @@ const static tv_mode_t tv_modes[] = {
     {
 	.name       = "720p at 60Hz",
 	.clock		= 148800,	
+	.refresh	= 60.0,
 	.oversample     = TV_OVERSAMPLE_2X,
 	.component_only = 1,
 
@@ -608,6 +628,7 @@ const static tv_mode_t tv_modes[] = {
     {
 	.name       = "720p at 59.94Hz",
 	.clock		= 148800,	
+	.refresh	= 59.94,
 	.oversample     = TV_OVERSAMPLE_2X,
 	.component_only = 1,
 
@@ -631,6 +652,7 @@ const static tv_mode_t tv_modes[] = {
     {
 	.name       = "720p at 50Hz",
 	.clock		= 148800,	
+	.refresh	= 50.0,
 	.oversample     = TV_OVERSAMPLE_2X,
 	.component_only = 1,
 
@@ -655,6 +677,7 @@ const static tv_mode_t tv_modes[] = {
     {
 	.name       = "1080i at 50Hz",
 	.clock		= 148800,	
+	.refresh	= 25.0,
 	.oversample     = TV_OVERSAMPLE_2X,
 	.component_only = 1,
 
@@ -680,6 +703,7 @@ const static tv_mode_t tv_modes[] = {
     {
 	.name       = "1080i at 60Hz",
 	.clock		= 148800,	
+	.refresh	= 30.0,
 	.oversample     = TV_OVERSAMPLE_2X,
 	.component_only = 1,
 
@@ -705,6 +729,7 @@ const static tv_mode_t tv_modes[] = {
     {
 	.name       = "1080i at 59.94Hz",
 	.clock		= 148800,	
+	.refresh	= 29.97,
 	.oversample     = TV_OVERSAMPLE_2X,
 	.component_only = 1,
 
@@ -895,10 +920,38 @@ i830_tv_restore(xf86OutputPtr output)
     OUTREG(TV_CTL, dev_priv->save_TV_CTL);
 }
 
+static const tv_mode_t *
+i830_tv_mode_lookup (char *tv_format)
+{
+    int			    i;
+    
+    for (i = 0; i < sizeof(tv_modes) / sizeof (tv_modes[0]); i++) 
+    {
+	const tv_mode_t	*tv_mode = &tv_modes[i];
+
+	if (xf86nameCompare (tv_format, tv_mode->name) == 0)
+	    return tv_mode;
+    }
+    return NULL;
+}
+
+static const tv_mode_t *
+i830_tv_mode_find (xf86OutputPtr output)
+{
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    struct i830_tv_priv	    *dev_priv = intel_output->dev_priv;
+
+    return i830_tv_mode_lookup (dev_priv->tv_format);
+}
+
 static int
-i830_tv_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
+i830_tv_mode_valid(xf86OutputPtr output, DisplayModePtr mode)
 {
+    const tv_mode_t	*tv_mode = i830_tv_mode_find (output);
+    
+    if (tv_mode && fabs (tv_mode->refresh - xf86ModeVRefresh (mode)) < 1.0)
 	return MODE_OK;
+    return MODE_CLOCK_RANGE;
 }
 
 
@@ -906,24 +959,24 @@ static Bool
 i830_tv_mode_fixup(xf86OutputPtr output, DisplayModePtr 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;
+    const tv_mode_t	*tv_mode = i830_tv_mode_find (output);
+
+    if (!tv_mode)
+	return FALSE;
+    
+    for (i = 0; i < xf86_config->num_output; i++) 
+    {
+	xf86OutputPtr other_output = xf86_config->output[i];
 
-	/* XXX: fill me in */
+	if (other_output != output && other_output->crtc == output->crtc)
+	    return FALSE;
+    }
 
-	return TRUE;
+    adjusted_mode->Clock = tv_mode->clock;
+    return TRUE;
 }
 
 static CARD32
@@ -973,7 +1026,7 @@ 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;
-    const tv_mode_t	    *tv_mode;
+    const tv_mode_t	    *tv_mode = i830_tv_mode_find (output);
     CARD32		    tv_ctl;
     CARD32		    hctl1, hctl2, hctl3;
     CARD32		    vctl1, vctl2, vctl3, vctl4, vctl5, vctl6, vctl7;
@@ -982,11 +1035,10 @@ i830_tv_mode_set(xf86OutputPtr output, D
     const video_levels_t	*video_levels;
     const color_conversion_t	*color_conversion;
     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;	
-    }
+    
+    if (!tv_mode)
+	return;	/* can't happen (mode_prepare prevents this) */
+    
     tv_ctl = 0;
 
     switch (dev_priv->type) {
@@ -1157,6 +1209,12 @@ i830_tv_mode_set(xf86OutputPtr output, D
 	else
 	    ysize = 2*tv_mode->nbr_end + 1;
 
+	xpos += dev_priv->margin[TV_MARGIN_LEFT];
+	ypos += dev_priv->margin[TV_MARGIN_TOP];
+	xsize -= (dev_priv->margin[TV_MARGIN_LEFT] + 
+		  dev_priv->margin[TV_MARGIN_RIGHT]);
+	ysize -= (dev_priv->margin[TV_MARGIN_TOP] + 
+		  dev_priv->margin[TV_MARGIN_BOTTOM]);
 	OUTREG(TV_WIN_POS, (xpos<<16)|ypos);
 	OUTREG(TV_WIN_SIZE, (xsize<<16)|ysize);
 
@@ -1333,62 +1391,51 @@ static struct input_res {
 static DisplayModePtr
 i830_tv_get_modes(xf86OutputPtr output)
 {
-    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);
+    DisplayModePtr	ret = NULL, mode_ptr;
+    int			j;
+    const tv_mode_t	*tv_mode = i830_tv_mode_find (output);
+
+    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;
+	
+	if (tv_mode->max_srcw && input->w > tv_mode->max_srcw)
+	    continue;
 
-	if (dev_priv->type != TV_TYPE_COMPONENT && tv_mode->component_only)
+	if (input->w > 1024 && (!tv_mode->progressive 
+				&& !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;
-	} 
-    }
+	mode_ptr = xnfcalloc(1, sizeof(DisplayModeRec));
+    	mode_ptr->name = xnfalloc(strlen(tv_mode->name) + 
+				  strlen(input->name) + 4);
+	sprintf(mode_ptr->name, "%s", input->name);
+
+
+	mode_ptr->HDisplay = hactive_s;
+	mode_ptr->HSyncStart = hactive_s + 1;
+	mode_ptr->HSyncEnd = hactive_s + 64;
+	if ( mode_ptr->HSyncEnd <= mode_ptr->HSyncStart)
+	    mode_ptr->HSyncEnd = mode_ptr->HSyncStart  + 1;
+	mode_ptr->HTotal = hactive_s + 96;
+
+	mode_ptr->VDisplay = vactive_s;
+	mode_ptr->VSyncStart = vactive_s + 1;
+	mode_ptr->VSyncEnd = vactive_s + 32;
+	if ( mode_ptr->VSyncEnd <= mode_ptr->VSyncStart)
+	    mode_ptr->VSyncEnd = mode_ptr->VSyncStart  + 1;
+	mode_ptr->VTotal = vactive_s + 33;
+
+	mode_ptr->Clock = (int) (tv_mode->refresh * 
+				 mode_ptr->VTotal * 
+				 mode_ptr->HTotal / 1000.0);
+	
+	mode_ptr->type = M_T_DRIVER;
+	mode_ptr->next = ret;
+	ret = mode_ptr;
+    } 
 
     return ret;
 }
@@ -1400,7 +1447,145 @@ i830_tv_destroy (xf86OutputPtr output)
 	xfree (output->driver_private);
 }
 
+#ifdef RANDR_12_INTERFACE
+#define TV_FORMAT_NAME	"TV_FORMAT"
+static Atom tv_format_atom;
+static Atom margin_atoms[4];
+static char *margin_names[4] = {
+    "LEFT", "TOP", "RIGHT", "BOTTOM"
+};
+#endif /* RANDR_12_INTERFACE */
+
+static void
+i830_tv_create_resources(xf86OutputPtr output)
+{
+#ifdef RANDR_12_INTERFACE
+    ScrnInfoPtr		    pScrn = output->scrn;
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    struct i830_tv_priv	    *dev_priv = intel_output->dev_priv;
+    int			    err;
+    int			    i;
+
+    /* Set up the tv_format property, which takes effect on mode set
+     * and accepts strings that match exactly
+     */
+    tv_format_atom = MakeAtom(TV_FORMAT_NAME, sizeof(TV_FORMAT_NAME) - 1,
+	TRUE);
+
+    err = RRConfigureOutputProperty(output->randr_output, tv_format_atom,
+				    TRUE, FALSE, FALSE, 0, NULL);
+    
+    if (err != 0) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "RRConfigureOutputProperty error, %d\n", err);
+    }
+
+    /* Set the current value of the tv_format property */
+    err = RRChangeOutputProperty(output->randr_output, tv_format_atom,
+				 XA_STRING, 8, PropModeReplace,
+				 strlen (dev_priv->tv_format),
+				 dev_priv->tv_format,
+				 FALSE, TRUE);
+    RRPostPendingProperty (output->randr_output, tv_format_atom);
+    if (err != 0) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "RRChangeOutputProperty error, %d\n", err);
+    }
+
+    for (i = 0; i < 4; i++)
+    {
+	INT32	range[2];
+	margin_atoms[i] = MakeAtom(margin_names[i], strlen (margin_names[i]),
+				   TRUE);
+
+	range[0] = 0;
+	range[1] = 100;
+	err = RRConfigureOutputProperty(output->randr_output, margin_atoms[i],
+				    TRUE, TRUE, FALSE, 2, range);
+    
+	if (err != 0) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "RRConfigureOutputProperty error, %d\n", err);
+	}
+
+	/* Set the current value of the tv_format property */
+	err = RRChangeOutputProperty(output->randr_output, margin_atoms[i],
+				     XA_INTEGER, 32, PropModeReplace,
+				     4, &dev_priv->margin[i],
+				     FALSE, TRUE);
+	RRPostPendingProperty (output->randr_output, margin_atoms[i]);
+	if (err != 0) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "RRChangeOutputProperty error, %d\n", err);
+	}
+    }
+#endif /* RANDR_12_INTERFACE */
+}
+
+static void
+i830_tv_commit (xf86OutputPtr output)
+{
+#ifdef RANDR_12_INTERFACE
+    if (output->randr_output)
+	RRPostPendingProperty (output->randr_output, tv_format_atom);
+#endif    
+    i830_output_commit (output);
+}
+
+#ifdef RANDR_12_INTERFACE
+static Bool
+i830_tv_set_property(xf86OutputPtr output, Atom property,
+		       RRPropertyValuePtr value)
+{
+    int	i;
+    
+    if (property == tv_format_atom) 
+    {
+	I830OutputPrivatePtr    intel_output = output->driver_private;
+	struct i830_tv_priv	*dev_priv = intel_output->dev_priv;
+	char			*val;
+
+	if (value->type != XA_STRING || value->format != 8)
+	    return FALSE;
+
+	val = xalloc (value->size + 1);
+	if (!val)
+	    return FALSE;
+	memcpy (val, value->data, value->size);
+	val[value->size] = '\0';
+	if (!i830_tv_mode_lookup (val))
+	{
+	    xfree (val);
+	    return FALSE;
+	}
+	xfree (dev_priv->tv_format);
+	dev_priv->tv_format = val;
+	return TRUE;
+    }
+    for (i = 0; i < 4; i++)
+    {
+	if (property == margin_atoms[i])
+	{
+	    I830OutputPrivatePtr    intel_output = output->driver_private;
+	    struct i830_tv_priv	*dev_priv = intel_output->dev_priv;
+	    INT32		val;
+
+	    if (value->type != XA_INTEGER || value->format != 32 ||
+		value->size != 1)
+		return FALSE;
+
+	    memcpy (&val, value->data, 4);
+	    dev_priv->margin[i] = val;
+	    return TRUE;
+	}
+    }
+
+    return TRUE;
+}
+#endif /* RANDR_12_INTERFACE */
+
 static const xf86OutputFuncsRec i830_tv_output_funcs = {
+    .create_resources = i830_tv_create_resources,
     .dpms = i830_tv_dpms,
     .save = i830_tv_save,
     .restore = i830_tv_restore,
@@ -1408,10 +1593,13 @@ static const xf86OutputFuncsRec i830_tv_
     .mode_fixup = i830_tv_mode_fixup,
     .prepare = i830_output_prepare,
     .mode_set = i830_tv_mode_set,
-    .commit = i830_output_commit,
+    .commit = i830_tv_commit,
     .detect = i830_tv_detect,
     .get_modes = i830_tv_get_modes,
-    .destroy = i830_tv_destroy
+    .destroy = i830_tv_destroy,
+#ifdef RANDR_12_INTERFACE
+    .set_property = i830_tv_set_property,
+#endif
 };
 
 void
@@ -1466,6 +1654,25 @@ i830_tv_init(ScrnInfoPtr pScrn)
     intel_output->dev_priv = dev_priv;
     dev_priv->type = TV_TYPE_UNKNOWN;
 
+    dev_priv->tv_format = NULL;
+    
+    /* BIOS margin values */
+    dev_priv->margin[TV_MARGIN_LEFT] = 54;
+    dev_priv->margin[TV_MARGIN_TOP] = 36;
+    dev_priv->margin[TV_MARGIN_RIGHT] = 46;
+    dev_priv->margin[TV_MARGIN_BOTTOM] = 37;
+    
+    if (output->conf_monitor)
+    {
+	char	*tv_format;
+	
+	tv_format = xf86findOptionValue (output->conf_monitor->mon_option_lst, "TV Format");
+	if (tv_format)
+	    dev_priv->tv_format = xstrdup (tv_format);
+    }
+    if (!dev_priv->tv_format)
+	dev_priv->tv_format = xstrdup (tv_modes[0].name);
+    
     output->driver_private = intel_output;
     output->interlaceAllowed = FALSE;
     output->doubleScanAllowed = FALSE;
diff-tree 94dbc3725358d63fe0ac8e6749489c993d24ede2 (from parents)
Merge: 28af380ab133eb14d21dc650c77bdbab66576255 20b26854abdacb6dc45cba2d81d515b2e47e25f1
Author: Nian Wu <nian.wu at intel.com>
Date:   Thu Mar 22 17:00:15 2007 +0800

    Merge git://proxy01.pd.intel.com:9419/git/xorg/driver/xf86-video-intel into crestline

diff-tree 20b26854abdacb6dc45cba2d81d515b2e47e25f1 (from 3025fa0fb2bf5ace7076796e45e2560fe8410e8d)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Thu Mar 22 10:33:15 2007 +0800

    EXA: don't smash vertex header in G965
    
    Originally we smashed vertex header to store texture
    coordinates, this is working as we only use sf/wm kernel
    and disable all other stages on pipeline. But better to
    not do this. This also cleans up vertex elements state
    and makes vertex buffer order looks "normal".

diff --git a/src/i965_render.c b/src/i965_render.c
index 3cf694f..bfbb77e 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -817,7 +817,8 @@ i965_prepare_composite(int op, PicturePt
     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;
+    /* don't smash vertex header, read start from dw8 */
+    sf_state->thread3.urb_entry_read_offset = 1;
     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;
@@ -1005,37 +1006,38 @@ i965_prepare_composite(int op, PicturePt
 	/* Set up our vertex elements, sourced from the single vertex buffer.
 	 */
    	OUT_RING(BRW_3DSTATE_VERTEX_ELEMENTS | ((2 * nelem) - 1));
+	/* vertex coordinates */
    	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) |
-	     	 ((pMask ? BRW_VFCOMPONENT_NOSTORE: BRW_VFCOMPONENT_STORE_1_FLT)
-		  << VE1_VFCOMPONENT_2_SHIFT) |
-	    	 ((pMask ? BRW_VFCOMPONENT_NOSTORE: BRW_VFCOMPONENT_STORE_1_FLT)
-		  << VE1_VFCOMPONENT_3_SHIFT) |
-	    	 (0 << VE1_DESTINATION_ELEMENT_OFFSET_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));
+	/* u0, v0 */
+   	OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
+	    	 VE0_VALID |
+	    	 (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
+	    	 (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_NOSTORE << VE1_VFCOMPONENT_2_SHIFT) |
+	    	 (BRW_VFCOMPONENT_NOSTORE << VE1_VFCOMPONENT_3_SHIFT) |
+	    	 (8 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); /* VUE offset in dwords */
+	/* u1, v1 */
    	if (pMask) {
 	    OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
 		     VE0_VALID |
 		     (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
-		     (8 << VE0_OFFSET_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_NOSTORE << VE1_VFCOMPONENT_2_SHIFT) |
 		     (BRW_VFCOMPONENT_NOSTORE << VE1_VFCOMPONENT_3_SHIFT) |
-		     (2 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
+		     (10 << 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();
     }
@@ -1089,34 +1091,34 @@ i965_composite(PixmapPtr pDst, int srcX,
 
     i = 0;
     /* rect (x2,y2) */
+    vb[i++] = (float)(dstX + w);
+    vb[i++] = (float)(dstY + h);
     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)dstX;
+    vb[i++] = (float)(dstY + h);
     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)dstX;
+    vb[i++] = (float)dstY;
     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);
diff-tree 28af380ab133eb14d21dc650c77bdbab66576255 (from parents)
Merge: 300e893cec19dca48e00ee25014b8714dc13b278 e06c5f727fb2e2de111ac9e691a877c56d2ca1b4
Author: Nian Wu <nian.wu at intel.com>
Date:   Wed Mar 21 17:00:04 2007 +0800

    Merge branch 'crestline' of git://otc-graphics.jf.intel.com/git/xorg/driver/xf86-video-intel into crestline

diff-tree e06c5f727fb2e2de111ac9e691a877c56d2ca1b4 (from parents)
Merge: 02023998663cc7f0735fadfb1719d93dc2e5a112 3025fa0fb2bf5ace7076796e45e2560fe8410e8d
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Mar 21 15:04:21 2007 +0800

    Merge branch 'master' into crestline

diff-tree 02023998663cc7f0735fadfb1719d93dc2e5a112 (from 3e9ec78b4f54defb9986e11e6f2ac3475755849d)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Mar 21 00:00:56 2007 -0700

    Whitespace and symbolic reg names cleanup in i830_panel_fitter_pipe().

diff --git a/src/i830_display.c b/src/i830_display.c
index 5cedd77..0d0cdf0 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -673,23 +673,23 @@ i830_get_core_clock_speed(ScrnInfoPtr pS
  * or -1 if the panel fitter is not present or not in use
  */
 static int
-i830_panel_fitter_pipe (I830Ptr	pI830)
+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;
+	return (pfit_control & PFIT_PIPE_MASK) >> PFIT_PIPE_SHIFT;
 
     /* older chips can only use pipe 1 */
     return 1;
diff-tree 3e9ec78b4f54defb9986e11e6f2ac3475755849d (from a50009604152bf9237c40bd098b3b1da3d018929)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Mar 20 23:58:48 2007 -0700

    Set the panel fitter to the right pipe on Crestline.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index e4bebaf..eaa8bb5 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -830,6 +830,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 #define PFIT_CONTROL	0x61230
 # define PFIT_ENABLE				(1 << 31)
+# define PFIT_PIPE_MASK				(3 << 29)
+# define PFIT_PIPE_SHIFT			29
 # define VERT_INTERP_DISABLE			(0 << 10)
 # define VERT_INTERP_BILINEAR			(1 << 10)
 # define VERT_INTERP_MASK			(3 << 10)
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index 7e5ce67..2ad52a7 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -216,6 +216,7 @@ i830_lvds_mode_set(xf86OutputPtr output,
 {
     ScrnInfoPtr pScrn = output->scrn;
     I830Ptr pI830 = I830PTR(pScrn);
+    I830CrtcPrivatePtr intel_crtc = output->crtc->driver_private;
     CARD32 pfit_control;
 
     /* The LVDS pin pair will already have been turned on in the
@@ -230,9 +231,12 @@ i830_lvds_mode_set(xf86OutputPtr output,
 		    VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
 		    VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR);
 
-    if (!IS_I965G(pI830))
+    if (!IS_I965G(pI830)) {
 	if (pI830->panel_wants_dither)
 	    pfit_control |= PANEL_8TO6_DITHER_ENABLE;
+    } else {
+	pfit_control |= intel_crtc->pipe << PFIT_PIPE_SHIFT;
+    }
 
     OUTREG(PFIT_CONTROL, pfit_control);
 }
diff-tree 3025fa0fb2bf5ace7076796e45e2560fe8410e8d (from 223944878cf38f86580df5a7d3102d86cfc061b9)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Mar 21 14:50:45 2007 +0800

    EXA: try to enable rotation for G965
    
    The new sf/wm should handle the texture sampling only in
    rotated case. Also fix possible hole in VUE slot.

diff --git a/src/Makefile.am b/src/Makefile.am
index c65c1e7..bd64f50 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -120,20 +120,24 @@ INTEL_G4A =				\
 	packed_yuv_wm.g4a		\
 	exa_sf.g4a 			\
 	exa_sf_mask.g4a 		\
+	exa_sf_rotation.g4a		\
 	exa_wm_maskca.g4a 		\
 	exa_wm_maskca_srcalpha.g4a 	\
 	exa_wm_masknoca.g4a 		\
-	exa_wm_nomask.g4a
+	exa_wm_nomask.g4a		\
+	exa_wm_rotation.g4a
 
 INTEL_G4H = 				\
 	sf_prog.h			\
 	wm_prog.h 			\
 	exa_sf_mask_prog.h		\
 	exa_sf_prog.h 			\
+	exa_sf_rotation_prog.h		\
 	exa_wm_maskca_prog.h		\
 	exa_wm_maskca_srcalpha_prog.h	\
 	exa_wm_masknoca_prog.h		\
-	exa_wm_nomask_prog.h
+	exa_wm_nomask_prog.h		\
+	exa_wm_rotation_prog.h
 
 EXTRA_DIST = 		\
 	$(XMODE_SRCS)	\
@@ -154,6 +158,9 @@ exa_sf_mask_prog.h: exa_sf_mask.g4a
 	
 exa_sf_prog.h: exa_sf.g4a
 	intel-gen4asm -o exa_sf_prog.h exa_sf.g4a
+
+exa_sf_rotation_prog.h: exa_sf_rotation.g4a
+	intel-gen4asm -o exa_sf_rotation_prog.h exa_sf_rotation.g4a
 	
 exa_wm_maskca_prog.h: exa_wm_maskca.g4a
 	intel-gen4asm -o exa_wm_maskca_prog.h exa_wm_maskca.g4a
@@ -166,6 +173,9 @@ exa_wm_masknoca_prog.h: exa_wm_masknoca.
 	
 exa_wm_nomask_prog.h: exa_wm_nomask.g4a
 	intel-gen4asm -o exa_wm_nomask_prog.h exa_wm_nomask.g4a
+
+exa_wm_rotation_prog.h: exa_wm_rotation.g4a
+	intel-gen4asm -o exa_wm_rotation_prog.h exa_wm_rotation.g4a
 	
 endif
 
diff --git a/src/exa_sf_rotation.g4a b/src/exa_sf_rotation.g4a
new file mode 100644
index 0000000..4c93553
--- /dev/null
+++ b/src/exa_sf_rotation.g4a
@@ -0,0 +1,29 @@
+/* 1/dx */
+send (1) 0 g6<1>F g1.12<0,1,0>F math inv scalar mlen 1 rlen 1 { align1 };
+/* 1/dy */
+send (1) 0 g6.4<1>F g1.20<0,1,0>F math inv scalar mlen 1 rlen 1 { align1 };
+/* du, dv */
+mul (1) g7<1>F g3<0,1,0>F -1.0F { align1 };
+mul (1) g7.4<1>F g3.4<0,1,0>F -1.0F { align1 };
+add (1) g7<1>F g4<0,1,0>F g7<0,1,0>F { align1 };
+add (1) g7.4<1>F g4.4<0,1,0>F g7.4<0,1,0>F { align1 };
+
+/* du/dy */
+mul (1) g7<1>F g7<0,1,0>F g6.4<0,1,0>F { align1 };
+/* dv/dx */
+mul (1) g7.4<1>F g7.4<0,1,0>F g6<0,1,0>F { align1 };
+/* Cx */
+mov (8) m1<1>F g7<0,1,0>F { align1 };
+/* Cy */
+mov (8) m2<1>F g7.4<0,1,0>F { align1 };
+/* Co */
+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_rotation_prog.h b/src/exa_sf_rotation_prog.h
new file mode 100644
index 0000000..9589130
--- /dev/null
+++ b/src/exa_sf_rotation_prog.h
@@ -0,0 +1,20 @@
+   { 0x00000031, 0x20c01fbd, 0x0000002c, 0x01110081 },
+   { 0x00000031, 0x20c41fbd, 0x00000034, 0x01110081 },
+   { 0x00000041, 0x20e07fbd, 0x00000060, 0xbf800000 },
+   { 0x00000041, 0x20e47fbd, 0x00000064, 0xbf800000 },
+   { 0x00000040, 0x20e077bd, 0x00000080, 0x000000e0 },
+   { 0x00000040, 0x20e477bd, 0x00000084, 0x000000e4 },
+   { 0x00000041, 0x20e077bd, 0x000000e0, 0x000000c4 },
+   { 0x00000041, 0x20e477bd, 0x000000e4, 0x000000c0 },
+   { 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_rotation.g4a b/src/exa_wm_rotation.g4a
new file mode 100644
index 0000000..b12f81c
--- /dev/null
+++ b/src/exa_wm_rotation.g4a
@@ -0,0 +1,158 @@
+/*
+ * 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 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. */
+/* for rotation, texture y is from ssX.x, so g4,g5 will be Y */
+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 };
+
+/* texture Y is from ssX.x */
+    /* 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.16<0,1,0>F { align1 };
+mul (8) g7<1>F g7<8,8,1>F g3.16<0,1,0>F { align1 };
+    /* add in texture Y offset */
+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 };
+
+/* 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 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 }; 
+
+/* 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_rotation_prog.h b/src/exa_wm_rotation_prog.h
new file mode 100644
index 0000000..890d2cf
--- /dev/null
+++ b/src/exa_wm_rotation_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, 0x00000074 },
+   { 0x00600041, 0x20a077bd, 0x008d00a0, 0x00000074 },
+   { 0x00600040, 0x208077bd, 0x008d0080, 0x0000007c },
+   { 0x00600040, 0x20a077bd, 0x008d00a0, 0x0000007c },
+   { 0x00600040, 0x20c077bd, 0x008d00c0, 0x00004024 },
+   { 0x00600040, 0x20e077bd, 0x008d00e0, 0x00004024 },
+   { 0x00600041, 0x20c077bd, 0x008d00c0, 0x00000070 },
+   { 0x00600041, 0x20e077bd, 0x008d00e0, 0x00000070 },
+   { 0x00600040, 0x20c077bd, 0x008d00c0, 0x0000006c },
+   { 0x00600040, 0x20e077bd, 0x008d00e0, 0x0000006c },
+   { 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, 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_render.c b/src/i965_render.c
index 8d06c22..3cf694f 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -335,6 +335,10 @@ static const CARD32 sf_kernel_static_mas
 #include "exa_sf_mask_prog.h"
 };
 
+static const CARD32 sf_kernel_static_rotation[][4] = {
+#include "exa_sf_rotation_prog.h"
+};
+
 /* ps kernels */
 #define PS_KERNEL_NUM_GRF   32
 #define PS_MAX_THREADS	   32
@@ -355,7 +359,12 @@ static const CARD32 ps_kernel_static_mas
 #include "exa_wm_masknoca_prog.h"
 };
 
-static CARD32 i965_get_card_format(PicturePtr pPict)
+static const CARD32 ps_kernel_static_rotation [][4] = {
+#include "exa_wm_rotation_prog.h"
+};
+
+static CARD32 
+i965_get_card_format(PicturePtr pPict)
 {
     int i;
 
@@ -368,6 +377,21 @@ static CARD32 i965_get_card_format(Pictu
     return i965_tex_formats[i].card_fmt;
 }
 
+static Bool
+i965_check_rotation_transform(PictTransformPtr t)
+{
+    /* XXX this is arbitrary */
+    int a, b;
+    a = xFixedToInt(t->matrix[0][1]);
+    b = xFixedToInt(t->matrix[1][0]);
+    if (a == -1 && b == 1)
+	return TRUE;
+    else if (a == 1 && b == -1)
+	return TRUE;
+    else
+	return FALSE;
+}
+
 Bool
 i965_prepare_composite(int op, PicturePtr pSrcPicture,
 		       PicturePtr pMaskPicture, PicturePtr pDstPicture,
@@ -378,6 +402,7 @@ i965_prepare_composite(int op, PicturePt
     CARD32 src_offset, src_pitch;
     CARD32 mask_offset = 0, mask_pitch = 0;
     CARD32 dst_format, dst_offset, dst_pitch;
+    Bool rotation_program = FALSE;
 
 #ifdef XF86DRI
     if (pI830->directRenderingEnabled) {
@@ -406,6 +431,9 @@ i965_prepare_composite(int op, PicturePt
 	pI830->transform[1] = NULL;
 	pI830->scale_units[1][0] = -1;
 	pI830->scale_units[1][1] = -1;
+	if (pI830->transform[0] && 
+		i965_check_rotation_transform(pI830->transform[0]))
+	    rotation_program = TRUE;
     } else {
 	pI830->transform[1] = pMaskPicture->transform;
 	pI830->scale_units[1][0] = pMask->drawable.width;
@@ -442,7 +470,9 @@ i965_prepare_composite(int op, PicturePt
     sf_kernel_offset = ALIGN(next_offset, 64);
     if (pMask)
 	next_offset = sf_kernel_offset + sizeof (sf_kernel_static_mask);
-    else
+    else if (rotation_program)
+	next_offset = sf_kernel_offset + sizeof (sf_kernel_static_rotation);
+    else 
 	next_offset = sf_kernel_offset + sizeof (sf_kernel_static);
 
     ps_kernel_offset = ALIGN(next_offset, 64);
@@ -459,6 +489,8 @@ i965_prepare_composite(int op, PicturePt
         } else
 	    next_offset = ps_kernel_offset + 
                           sizeof(ps_kernel_static_masknoca);
+    } else if (rotation_program) {
+   	next_offset = ps_kernel_offset + sizeof (ps_kernel_static_rotation);
     } else {
    	next_offset = ps_kernel_offset + sizeof (ps_kernel_static_nomask);
     }
@@ -762,6 +794,9 @@ i965_prepare_composite(int op, PicturePt
      */
     if (pMask)
 	memcpy(sf_kernel, sf_kernel_static_mask, sizeof (sf_kernel_static));
+    else if (rotation_program)
+	memcpy(sf_kernel, sf_kernel_static_rotation, 
+		sizeof (sf_kernel_static_rotation));
     else
 	memcpy(sf_kernel, sf_kernel_static, sizeof (sf_kernel_static));
 
@@ -808,6 +843,9 @@ i965_prepare_composite(int op, PicturePt
         } else
    	    memcpy(ps_kernel, ps_kernel_static_masknoca,
 		   sizeof (ps_kernel_static_masknoca));
+    } else if (rotation_program) {
+   	memcpy(ps_kernel, ps_kernel_static_rotation,
+	       sizeof (ps_kernel_static_rotation));
     } else {
    	memcpy(ps_kernel, ps_kernel_static_nomask,
 	       sizeof (ps_kernel_static_nomask));
@@ -973,8 +1011,10 @@ i965_prepare_composite(int op, PicturePt
 	    	 (0 << VE0_OFFSET_SHIFT));
    	OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
 	    	 (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
-	     	 (BRW_VFCOMPONENT_NOSTORE << VE1_VFCOMPONENT_2_SHIFT) |
-	    	 (BRW_VFCOMPONENT_NOSTORE << VE1_VFCOMPONENT_3_SHIFT) |
+	     	 ((pMask ? BRW_VFCOMPONENT_NOSTORE: BRW_VFCOMPONENT_STORE_1_FLT)
+		  << VE1_VFCOMPONENT_2_SHIFT) |
+	    	 ((pMask ? BRW_VFCOMPONENT_NOSTORE: BRW_VFCOMPONENT_STORE_1_FLT)
+		  << VE1_VFCOMPONENT_3_SHIFT) |
 	    	 (0 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
    	if (pMask) {
 	    OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
diff-tree a50009604152bf9237c40bd098b3b1da3d018929 (from parents)
Merge: 0a612e7115ff993bb8e9a00df13c0b0d20122fd6 223944878cf38f86580df5a7d3102d86cfc061b9
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Mar 20 23:32:19 2007 -0700

    Merge branch 'master' into crestline
    
    Conflicts:
    
    	src/i810_reg.h
    	src/i830_display.c

diff --cc src/i810_reg.h
index f50646b,4c6e582..e4bebaf
@@@ -1128,110 -1128,58 +1128,145 @@@
  #define DVO_SRCDIM_HORIZONTAL_SHIFT	12
  #define DVO_SRCDIM_VERTICAL_SHIFT	0
  
+ /** @defgroup LVDS
+  * @{
+  */
+ /**
+  * This register controls the LVDS output enable, pipe selection, and data
+  * format selection.
+  *
+  * All of the clock/data pairs are force powered down by power sequencing.
+  */
  #define LVDS			0x61180
+ /**
+  * Enables the LVDS port.  This bit must be set before DPLLs are enabled, as
+  * the DPLL semantics change when the LVDS is assigned to that pipe.
+  */
  # define LVDS_PORT_EN			(1 << 31)
+ /** Selects pipe B for LVDS data.  Must be set on pre-965. */
  # define LVDS_PIPEB_SELECT		(1 << 30)
  
 +/* on 965, dithering is enabled in this register, not PFIT_CONTROL */
 +# define LVDS_DITHER_ENABLE		(1 << 25)
 +
 +/*
 + * Selects between .0 and .1 formats:
 + *
 + * 0 = 1x18.0, 2x18.0, 1x24.0 or 2x24.0
 + * 1 = 1x24.1 or 2x24.1
 + */
 +# define LVDS_DATA_FORMAT_DOT_ONE	(1 << 24)
 +
 +/* Using LE instead of HS on second channel control signal */
 +# define LVDS_LE_CONTROL_ENABLE		(1 << 23)
 +
 +/* Using LF instead of VS on second channel control signal */
 +# define LVDS_LF_CONTROL_ENABLE		(1 << 22)
 +
 +/* invert vsync signal polarity */
 +# define LVDS_VSYNC_POLARITY_INVERT	(1 << 21)
 +
 +/* invert hsync signal polarity */
 +# define LVDS_HSYNC_POLARITY_INVERT	(1 << 20)
 +
 +/* invert display enable signal polarity */
 +# define LVDS_DE_POLARITY_INVERT	(1 << 19)
 +
 +/*
 + * Control signals for second channel, ignored in single channel modes
 + */
 +
 +/* send DE, HS, VS on second channel */
 +# define LVDS_SECOND_CHANNEL_DE_HS_VS	(0 << 17)
 +
 +# define LVDS_SECOND_CHANNEL_RESERVED	(1 << 17)
 +
 +/* Send zeros instead of DE, HS, VS on second channel */
 +# define LVDS_SECOND_CHANNEL_ZEROS	(2 << 17)
 +
 +/* Set DE=0, HS=LE, VS=LF on second channel */
 +# define LVDS_SECOND_CHANNEL_HS_VS	(3 << 17)
 +
 +/*
 + * Send duplicate data for channel reserved bits, otherwise send zeros
 + */
 +# define LVDS_CHANNEL_DUP_RESERVED	(1 << 16)
 +
 +/*
 + * Enable border for unscaled (or aspect-scaled) display
 + */
 +# define LVDS_BORDER_ENABLE		(1 << 15)
 +
 +/*
 + * Tri-state the LVDS buffers when powered down, otherwise
 + * they are set to 0V
 + */
 +# define LVDS_POWER_DOWN_TRI_STATE	(1 << 10)
 +
- /*
-  * Clock A control; overridden by LVDS power sequencing
+ /**
+  * Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per
+  * pixel.
   */
+ # define LVDS_A0A2_CLKA_POWER_MASK	(3 << 8)
+ # define LVDS_A0A2_CLKA_POWER_DOWN	(0 << 8)
+ # define LVDS_A0A2_CLKA_POWER_UP	(3 << 8)
+ /**
+  * Controls the A3 data pair, which contains the additional LSBs for 24 bit
+  * mode.  Only enabled if LVDS_A0A2_CLKA_POWER_UP also indicates it should be
+  * on.
+  */
+ # define LVDS_A3_POWER_MASK		(3 << 6)
+ # define LVDS_A3_POWER_DOWN		(0 << 6)
+ # define LVDS_A3_POWER_UP		(3 << 6)
+ /**
+  * Controls the CLKB pair.  This should only be set when LVDS_B0B3_POWER_UP
+  * is set.
+  */
+ # define LVDS_CLKB_POWER_MASK		(3 << 4)
+ # define LVDS_CLKB_POWER_DOWN		(0 << 4)
+ # define LVDS_CLKB_POWER_UP		(3 << 4)
  
- /* power down everything including A3 (0V) */
- # define LVDS_CLKA_POWER_DOWN		(0 << 8)
- 
- /* Partially active. A0, A1, A2 set to 0, timing active, clock active */
- # define LVDS_CLKA_POWER_PARTIAL	(1 << 8)
+ /**
+  * Controls the B0-B3 data pairs.  This must be set to match the DPLL p2
+  * setting for whether we are in dual-channel mode.  The B3 pair will
+  * additionally only be powered up when LVDS_A3_POWER_UP is set.
+  */
+ # define LVDS_B0B3_POWER_MASK		(3 << 2)
+ # define LVDS_B0B3_POWER_DOWN		(0 << 2)
+ # define LVDS_B0B3_POWER_UP		(3 << 2)
  
- /* running, data and clock active */
- # define LVDS_CLKA_POWER_UP		(3 << 8)
+ /** @} */
  
 +/*
 + * Two channel clock control. Turn this on if you need clkb for two channel mode
 + * Overridden by global LVDS power sequencing
 + */
 +
 +/* clkb off */
 +# define LVDS_CLKB_POWER_DOWN		(0 << 4)
 +
 +/* powered up, but clkb forced to 0 */
 +# define LVDS_CLKB_POWER_PARTIAL	(1 << 4)
 +
 +/* clock B running */
 +# define LVDS_CLKB_POWER_UP		(3 << 4)
 +
 +/*
 + * Two channel mode B0-B2 control. Sets state when power is on.
 + * Set to POWER_DOWN in single channel mode, other settings enable
 + * two channel mode. The CLKB power control controls whether that clock
 + * is enabled during two channel mode.
 + *
 + */
 +/* Everything is off, including B3 and CLKB */
 +# define LVDS_B_POWER_DOWN		(0 << 2)
 +
 +/* B0, B1, B2 and data lines forced to 0. timing is active */
 +# define LVDS_B_POWER_PARTIAL		(1 << 2)
 +
 +/* data lines active (both timing and colour) */
 +# define LVDS_B_POWER_UP		(3 << 2)
 +
  /** @defgroup TV_CTL
   * @{
   */
diff --cc src/i830_display.c
index 2810a8b,d55e0a6..5cedd77
@@@ -890,22 -904,28 +904,37 @@@
  	usleep(150);
      }
  
+     /* 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.
+      */
      if (is_lvds)
      {
- 	CARD32	lvds = INREG(LVDS);
+ 	CARD32 lvds = INREG(LVDS);
+ 
+ 	lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP | LVDS_PIPEB_SELECT;
+ 	/* Set the B0-B3 data pairs corresponding to whether we're going to
+ 	 * set the DPLLs for dual-channel mode or not.
+ 	 */
+ 	if (adjusted_mode->Clock >= I9XX_P2_LVDS_SLOW_LIMIT)
+ 	    lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
+ 	else
+ 	    lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
  
- 	/* 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.
+ 	/* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
+ 	 * appropriately here, but we need to look more thoroughly into how
+ 	 * panels behave in the two modes.
  	 */
- 	lvds |= LVDS_PORT_EN | LVDS_PIPEB_SELECT;
+ 
++	/* Enable dithering if we're in 18-bit mode. */
 +	if (IS_I965G(pI830))
 +	{
- 	    if (pI830->panel_wants_dither)
++	    if ((lvds & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP)
 +		lvds |= LVDS_DITHER_ENABLE;
 +	    else
 +		lvds &= ~LVDS_DITHER_ENABLE;
 +	}
++
  	OUTREG(LVDS, lvds);
  	POSTING_READ(LVDS);
      }
diff-tree 300e893cec19dca48e00ee25014b8714dc13b278 (from parents)
Merge: 96e86994f3d1b4938e99a751454ee99bebfe40d3 02023998663cc7f0735fadfb1719d93dc2e5a112
Author: Nian Wu <nian.wu at intel.com>
Date:   Wed Mar 21 08:55:50 2007 +0800

    Merge branch 'crestline' of git://otc-graphics.jf.intel.com/git/xorg/driver/xf86-video-intel into crestline

diff-tree 223944878cf38f86580df5a7d3102d86cfc061b9 (from 4c4faf260eb4dad1b1919c6168fa9ef477b98a39)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Mar 20 14:33:53 2007 -0700

    Attempt to fix single/dual-channel issues on i9xx LVDS panels.
    
    - Use the existing single/dual-channel state when available, as changing it
      doesn't appear to work out.
    - Set the power state of the CLKB and B0-B3 pairs according to whether
      choose to go dual-channel or not.
    - Restore the LVDS register at the appropriate point (before DPLLs are
      re-programmed.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index d63be02..4c6e582 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -1128,11 +1128,57 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define DVO_SRCDIM_HORIZONTAL_SHIFT	12
 #define DVO_SRCDIM_VERTICAL_SHIFT	0
 
+/** @defgroup LVDS
+ * @{
+ */
+/**
+ * This register controls the LVDS output enable, pipe selection, and data
+ * format selection.
+ *
+ * All of the clock/data pairs are force powered down by power sequencing.
+ */
 #define LVDS			0x61180
+/**
+ * Enables the LVDS port.  This bit must be set before DPLLs are enabled, as
+ * the DPLL semantics change when the LVDS is assigned to that pipe.
+ */
 # define LVDS_PORT_EN			(1 << 31)
+/** Selects pipe B for LVDS data.  Must be set on pre-965. */
 # define LVDS_PIPEB_SELECT		(1 << 30)
-# define LVDS_CLKA_POWER_DOWN		(0 << 8)
-# define LVDS_CLKA_POWER_UP		(3 << 8)
+
+/**
+ * Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per
+ * pixel.
+ */
+# define LVDS_A0A2_CLKA_POWER_MASK	(3 << 8)
+# define LVDS_A0A2_CLKA_POWER_DOWN	(0 << 8)
+# define LVDS_A0A2_CLKA_POWER_UP	(3 << 8)
+/**
+ * Controls the A3 data pair, which contains the additional LSBs for 24 bit
+ * mode.  Only enabled if LVDS_A0A2_CLKA_POWER_UP also indicates it should be
+ * on.
+ */
+# define LVDS_A3_POWER_MASK		(3 << 6)
+# define LVDS_A3_POWER_DOWN		(0 << 6)
+# define LVDS_A3_POWER_UP		(3 << 6)
+/**
+ * Controls the CLKB pair.  This should only be set when LVDS_B0B3_POWER_UP
+ * is set.
+ */
+# define LVDS_CLKB_POWER_MASK		(3 << 4)
+# define LVDS_CLKB_POWER_DOWN		(0 << 4)
+# define LVDS_CLKB_POWER_UP		(3 << 4)
+
+/**
+ * Controls the B0-B3 data pairs.  This must be set to match the DPLL p2
+ * setting for whether we are in dual-channel mode.  The B3 pair will
+ * additionally only be powered up when LVDS_A3_POWER_UP is set.
+ */
+# define LVDS_B0B3_POWER_MASK		(3 << 2)
+# define LVDS_B0B3_POWER_DOWN		(0 << 2)
+# define LVDS_B0B3_POWER_UP		(3 << 2)
+
+/** @} */
 
 /** @defgroup TV_CTL
  * @{
diff --git a/src/i830_debug.c b/src/i830_debug.c
index c746d35..c0261a6 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -269,8 +269,21 @@ DEBUGSTRING(i830_debug_lvds)
 {
     char pipe = val & LVDS_PIPEB_SELECT ? 'B' : 'A';
     char *enable = val & LVDS_PORT_EN ? "enabled" : "disabled";
+    int depth;
+    char *channels;
 
-    return XNFprintf("%s, pipe %c", enable, pipe);
+    if ((val & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP)
+	depth = 24;
+    else
+	depth = 18;
+    if ((val & LVDS_B0B3_POWER_MASK) == LVDS_B0B3_POWER_UP)
+	channels = "2 channels";
+    else
+	channels = "1 channel";
+
+
+    return XNFprintf("%s, pipe %c, %d bit, %s",
+		     enable, pipe, depth, channels);
 }
 
 DEBUGSTRING(i830_debug_sdvo)
diff --git a/src/i830_display.c b/src/i830_display.c
index faa3781..d55e0a6 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -298,8 +298,9 @@ i830PllIsValid(xf86CrtcPtr crtc, intel_c
 }
 
 /**
- * Returns a set of divisors for the desired target clock with the given refclk,
- * or FALSE.  Divisor values are the actual divisors for
+ * Returns a set of divisors for the desired target clock with the given
+ * refclk, or FALSE.  The returned values represent the clock equation:
+ * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
  */
 static Bool
 i830FindBestPLL(xf86CrtcPtr crtc, int target, int refclk, intel_clock_t *best_clock)
@@ -310,10 +311,23 @@ i830FindBestPLL(xf86CrtcPtr crtc, int ta
     const intel_limit_t   *limit = intel_limit (crtc);
     int err = target;
 
-    if (target < limit->p2.dot_limit)
-	clock.p2 = limit->p2.p2_slow;
-    else
-	clock.p2 = limit->p2.p2_fast;
+    if (IS_I9XX(pI830) && i830PipeHasType(crtc, I830_OUTPUT_LVDS) &&
+	(INREG(LVDS) & LVDS_PORT_EN) != 0)
+    {
+	/* For LVDS, if the panel is on, just rely on its current settings for
+	 * dual-channel.  We haven't figured out how to reliably set up
+	 * different single/dual channel state, if we even can.
+	 */
+	if ((INREG(LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP)
+	    clock.p2 = limit->p2.p2_fast;
+	else
+	    clock.p2 = limit->p2.p2_slow;
+    } else {
+	if (target < limit->p2.dot_limit)
+	    clock.p2 = limit->p2.p2_slow;
+	else
+	    clock.p2 = limit->p2.p2_fast;
+    }
 
     memset (best_clock, 0, sizeof (*best_clock));
 
@@ -890,13 +904,29 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
 	usleep(150);
     }
 
+    /* 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.
+     */
     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.
+	CARD32 lvds = INREG(LVDS);
+
+	lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP | LVDS_PIPEB_SELECT;
+	/* Set the B0-B3 data pairs corresponding to whether we're going to
+	 * set the DPLLs for dual-channel mode or not.
+	 */
+	if (adjusted_mode->Clock >= I9XX_P2_LVDS_SLOW_LIMIT)
+	    lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
+	else
+	    lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
+
+	/* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
+	 * appropriately here, but we need to look more thoroughly into how
+	 * panels behave in the two modes.
 	 */
-	OUTREG(LVDS, INREG(LVDS) | LVDS_PORT_EN | LVDS_PIPEB_SELECT);
+
+	OUTREG(LVDS, lvds);
 	POSTING_READ(LVDS);
     }
 
diff --git a/src/i830_driver.c b/src/i830_driver.c
index c6aea5c..f41beb0 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1729,6 +1729,8 @@ SaveHWState(ScrnInfoPtr pScrn)
    pI830->saveSWF[15] = INREG(SWF31);
    pI830->saveSWF[16] = INREG(SWF32);
 
+   if (IS_MOBILE(pI830) && !IS_I830(pI830))
+      pI830->saveLVDS = INREG(LVDS);
    pI830->savePFIT_CONTROL = INREG(PFIT_CONTROL);
 
    for (i = 0; i < xf86_config->num_output; i++) {
@@ -1771,6 +1773,9 @@ RestoreHWState(ScrnInfoPtr pScrn)
    }
    i830WaitForVblank(pScrn);
 
+   if (IS_MOBILE(pI830) && !IS_I830(pI830))
+      OUTREG(LVDS, pI830->saveLVDS);
+
    if (!IS_I830(pI830) && !IS_845G(pI830))
      OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL);
 
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index adfbe4f..6f7750a 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -98,7 +98,7 @@ i830_lvds_dpms (xf86OutputPtr output, in
     else
 	i830SetLVDSPanelPower(pScrn, FALSE);
 
-    /* XXX: We never power down the LVDS pair. */
+    /* XXX: We never power down the LVDS pairs. */
 }
 
 static void
@@ -109,7 +109,6 @@ i830_lvds_save (xf86OutputPtr output)
 
     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);
@@ -133,7 +132,6 @@ i830_lvds_restore(xf86OutputPtr output)
     OUTREG(LVDSPP_ON, pI830->savePP_ON);
     OUTREG(LVDSPP_OFF, pI830->savePP_OFF);
     OUTREG(PP_CYCLE, pI830->savePP_CYCLE);
-    OUTREG(LVDS, pI830->saveLVDS);
     OUTREG(PP_CONTROL, pI830->savePP_CONTROL);
     if (pI830->savePP_CONTROL & POWER_TARGET_ON)
 	i830SetLVDSPanelPower(pScrn, TRUE);
@@ -204,11 +202,6 @@ i830_lvds_mode_fixup(xf86OutputPtr outpu
 	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.
-     */
-
     /* 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.
diff-tree 96e86994f3d1b4938e99a751454ee99bebfe40d3 (from parents)
Merge: f465c23750adf908c0ea874f95aad98ebd2f1015 0a612e7115ff993bb8e9a00df13c0b0d20122fd6
Author: Nian Wu <nian.wu at intel.com>
Date:   Tue Mar 20 13:11:09 2007 +0800

    Merge branch 'crestline' of git://otc-graphics.jf.intel.com/git/xorg/driver/xf86-video-intel into crestline

diff-tree 0a612e7115ff993bb8e9a00df13c0b0d20122fd6 (from parents)
Merge: 8bb677889d3f71cde671f17a3589939acad2c3b3 4c4faf260eb4dad1b1919c6168fa9ef477b98a39
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Tue Mar 20 11:34:40 2007 +0800

    Merge branch 'master' of git://proxy.ims.intel.com:9419/git/xorg/driver/xf86-video-intel into crestline
    
    Conflicts:
    
    	src/i830_display.c
    
    Change LVDS output and postread like upstream. This might
    need to be retested on 965GM LVDS.

diff --cc src/i830_display.c
index 784dce7,faa3781..2810a8b
@@@ -917,32 -896,13 +898,21 @@@
  	 * 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);
 +	lvds |= LVDS_PORT_EN | LVDS_PIPEB_SELECT;
 +	if (IS_I965G(pI830))
 +	{
 +	    if (pI830->panel_wants_dither)
 +		lvds |= LVDS_DITHER_ENABLE;
 +	    else
 +		lvds &= ~LVDS_DITHER_ENABLE;
 +	}
 +	OUTREG(LVDS, lvds);
+ 	POSTING_READ(LVDS);
      }
-     
-     /* Disable the panel fitter if it was on our pipe */
-     if (i830_panel_fitter_pipe (pI830) == pipe)
- 	OUTREG(PFIT_CONTROL, 0);
  
-     i830PrintPll("chosen", &clock);
-     ErrorF("clock regs: 0x%08x, 0x%08x\n", (int)dpll, (int)fp);
- 
-     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);
+     POSTING_READ(dpll_reg);
      /* Wait for the clocks to stabilize. */
      usleep(150);
      
diff-tree 4c4faf260eb4dad1b1919c6168fa9ef477b98a39 (from 64c14204453bea3f98d19861c450612e718e6c69)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Mar 19 13:36:37 2007 -0700

    Set the CURSOR_SIZE register when present.
    
    Failure to do so gets you a lot of pretty colors.

diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index d97b246..667b0a6 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -95,6 +95,9 @@ I830InitHWCursor(ScrnInfoPtr pScrn)
 
     DPRINTF(PFX, "I830InitHWCursor\n");
 
+    if (!IS_I9XX(pI830))
+       OUTREG(CURSOR_SIZE, (I810_CURSOR_Y << 12) | I810_CURSOR_X);
+
     /* Initialise the HW cursor registers, leaving the cursor hidden. */
     for (i = 0; i < xf86_config->num_crtc; i++)
     {
diff-tree 64c14204453bea3f98d19861c450612e718e6c69 (from 3ce802414a20ca8af128a00e6925a099dd90ceb4)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Mar 19 13:35:43 2007 -0700

    Print the mode actually being set per pipe.

diff --git a/src/i830_display.c b/src/i830_display.c
index 98137a2..faa3781 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -870,8 +870,17 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
     if (i830_panel_fitter_pipe (pI830) == pipe)
 	OUTREG(PFIT_CONTROL, 0);
 
+#if 1
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+	       "Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
+    xf86PrintModeline(pScrn->scrnIndex, mode);
+    if (!xf86ModesEqual(mode, adjusted_mode)) {
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		   "Adjusted mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
+	xf86PrintModeline(pScrn->scrnIndex, mode);
+    }
     i830PrintPll("chosen", &clock);
-    ErrorF("clock regs: 0x%08x, 0x%08x\n", (int)dpll, (int)fp);
+#endif
 
     if (dpll & DPLL_VCO_ENABLE)
     {
diff-tree 3ce802414a20ca8af128a00e6925a099dd90ceb4 (from c21b88d838fda1f00f6f6bcfe7855d32543c6f3f)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Mar 19 11:35:11 2007 -0700

    Add debug output for ADPA.

diff --git a/src/i830_debug.c b/src/i830_debug.c
index 7fd9441..c746d35 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -254,6 +254,17 @@ DEBUGSTRING(i830_debug_dpll_test)
 		     dpllbndiv, dpllbmdiv, dpllbinput);
 }
 
+DEBUGSTRING(i830_debug_adpa)
+{
+    char pipe = (val & ADPA_PIPE_B_SELECT) ? 'B' : 'A';
+    char *enable = (val & ADPA_DAC_ENABLE) ? "enabled" : "disabled";
+    char hsync = (val & ADPA_HSYNC_ACTIVE_HIGH) ? '+' : '-';
+    char vsync = (val & ADPA_VSYNC_ACTIVE_HIGH) ? '+' : '-';
+
+    return XNFprintf("%s, pipe %c, %chsync, %cvsync",
+		     enable, pipe, hsync, vsync);
+}
+
 DEBUGSTRING(i830_debug_lvds)
 {
     char pipe = val & LVDS_PIPEB_SELECT ? 'B' : 'A';
@@ -313,7 +324,7 @@ static struct i830SnapshotRec {
     DEFINEREG(DSPFW2),
     DEFINEREG(DSPFW3),
 
-    DEFINEREG(ADPA),
+    DEFINEREG2(ADPA, i830_debug_adpa),
     DEFINEREG2(LVDS, i830_debug_lvds),
     DEFINEREG(DVOA),
     DEFINEREG(DVOB),
diff-tree c21b88d838fda1f00f6f6bcfe7855d32543c6f3f (from 991719c21a6cc1b5d9b7cbe30d4b333718b3e686)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Mon Mar 19 10:45:58 2007 +0100

    Fix build when DAMAGE is not defined.

diff --git a/src/i830_dri.c b/src/i830_dri.c
index 0fcce58..ccc1fac 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -126,8 +126,8 @@ static void I830DRITransitionTo2d(Screen
 static void I830DRITransitionTo3d(ScreenPtr pScreen);
 static void I830DRITransitionMultiToSingle3d(ScreenPtr pScreen);
 static void I830DRITransitionSingleToMulti3d(ScreenPtr pScreen);
-#if DRIINFO_MAJOR_VERSION > 5 || \
-    (DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1)
+#if defined(DAMAGE) && (DRIINFO_MAJOR_VERSION > 5 ||		\
+			(DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1))
 #define DRI_SUPPORTS_CLIP_NOTIFY 1
 #endif
 
@@ -576,7 +576,8 @@ I830DRIScreenInit(ScreenPtr pScreen)
    pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
 
    {
-#if DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1
+#if DRI_SUPPORTS_CLIP_NOTIFY && DRIINFO_MAJOR_VERSION == 5 && \
+    DRIINFO_MINOR_VERSION >= 1
       int major, minor, patch;
 
       DRIQueryVersion(&major, &minor, &patch);
@@ -1200,7 +1201,9 @@ I830DRISwapContext(ScreenPtr pScreen, DR
    } else if (syncType == DRI_2D_SYNC &&
 	      oldContextType == DRI_NO_CONTEXT &&
 	      newContextType == DRI_2D_CONTEXT) {
+#ifdef DAMAGE
       drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScreen);
+#endif
 
       if (I810_DEBUG & DEBUG_VERBOSE_DRI)
 	 ErrorF("i830DRISwapContext (out)\n");
diff-tree 991719c21a6cc1b5d9b7cbe30d4b333718b3e686 (from 9118122a232d4cf7760bcb0874fe970c25251378)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Sun Mar 18 23:05:33 2007 -0700

    Make i830_sdvo_write_sdvox write everything twice.
    
    For some reason, certain chips don't correctly enable the SDVO hardware when
    this register is written only once. We're following what the BIOS code does
    and writing it twice now, but with extra posting reads to boot. Yes, this is
    cult-and-paste, but it fixes problems found on deployed hardware.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index fb6a7c8..b67ecbc 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -90,12 +90,26 @@ static void i830_sdvo_write_sdvox(xf86Ou
     I830OutputPrivatePtr    intel_output = output->driver_private;
     struct i830_sdvo_priv   *dev_priv = intel_output->dev_priv;
     I830Ptr		    pI830 = I830PTR(pScrn);
+    CARD32		    bval = val, cval = val;
+    int			    i;
 
-    if (dev_priv->output_device == SDVOC)
-	OUTREG(SDVOB, INREG(SDVOB));
-    OUTREG(dev_priv->output_device, val);
     if (dev_priv->output_device == SDVOB)
-	OUTREG(SDVOC, INREG(SDVOC));
+	cval = INREG(SDVOC);
+    else
+	bval = INREG(SDVOB);
+    
+    /*
+     * Write the registers twice for luck. Sometimes,
+     * writing them only once doesn't appear to 'stick'.
+     * The BIOS does this too. Yay, magic
+     */
+    for (i = 0; i < 2; i++)
+    {
+	OUTREG(SDVOB, bval);
+	POSTING_READ(SDVOB);
+	OUTREG(SDVOC, cval);
+	POSTING_READ(SDVOC);
+    }
 }
 
 /** Read a single byte from the given address on the SDVO device. */
@@ -740,7 +754,6 @@ i830_sdvo_dpms(xf86OutputPtr output, int
 	    temp = INREG(dev_priv->output_device);
 	    if ((temp & SDVO_ENABLE) != 0) {
 		i830_sdvo_write_sdvox(output, temp & ~SDVO_ENABLE);
-		POSTING_READ(dev_priv->output_device);
 	    }
 	}
     } else {
@@ -750,19 +763,7 @@ i830_sdvo_dpms(xf86OutputPtr output, int
 
 	temp = INREG(dev_priv->output_device);
 	if ((temp & SDVO_ENABLE) == 0)
-	{
 	    i830_sdvo_write_sdvox(output, temp | SDVO_ENABLE);
-	    POSTING_READ(dev_priv->output_device);
-#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.
-	     */
-	    i830_sdvo_write_sdvox(output, INREG(dev_priv->output_device) |
-				  SDVO_ENABLE);
-	    POSTING_READ(dev_priv->output_device);
-#endif
-	}
 	for (i = 0; i < 2; i++)
 	    i830WaitForVblank(pScrn);
 
diff-tree 9118122a232d4cf7760bcb0874fe970c25251378 (from 62a5399d70ac3f8579441d617f8d80c94942a32a)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Sat Mar 17 21:34:03 2007 -0700

    Allocate 4 separate buffers for HW Cursors on Linux.
    
    Linux cannot allocate a large fixed buffer for the HW cursors as needed for
    FreeBSD; instead, allocate four separate buffers. The code now prefers to
    allocate one buffer (less overhead) and falls back to separate buffers only
    when necessary.

diff --git a/src/i830.h b/src/i830.h
index f8416de..e75eb89 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -226,7 +226,6 @@ typedef struct _I830CrtcPrivateRec {
 #ifdef I830_USE_EXA
     ExaOffscreenArea *rotate_mem_exa;
 #endif
-
     /* Card virtual address of the cursor */
     unsigned long cursor_offset;
     unsigned long cursor_argb_offset;
@@ -282,7 +281,11 @@ typedef struct _I830Rec {
 
    i830_memory *front_buffer;
    i830_memory *front_buffer_2;
+   /* One big buffer for all cursors for kernels that support this */
    i830_memory *cursor_mem;
+   /* separate small buffers for kernels that support this */
+   i830_memory *cursor_mem_classic[2];
+   i830_memory *cursor_mem_argb[2];
    i830_memory *xaa_scratch;
    i830_memory *xaa_scratch_2;
 #ifdef I830_USE_EXA
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 440618a..b26dd00 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -62,7 +62,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * The allocations we might do:
  *
  * - Ring buffer
- * - HW cursor block
+ * - HW cursor block (either one block or four)
  * - Overlay registers
  * - XAA linear allocator (optional)
  * - EXA 965 state buffer
@@ -211,6 +211,7 @@ void
 i830_reset_allocations(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
+    int	    p;
 
     /* While there is any memory between the start and end markers, free it. */
     while (pI830->memory_list->next->next != NULL)
@@ -220,6 +221,10 @@ i830_reset_allocations(ScrnInfoPtr pScrn
      * kind of gross, but at least it's just one place now.
      */
     pI830->cursor_mem = NULL;
+    for (p = 0; p < 2; p++) {
+	pI830->cursor_mem_classic[p] = NULL;
+	pI830->cursor_mem_argb[p] = NULL;
+    }
     pI830->front_buffer = NULL;
     pI830->front_buffer_2 = NULL;
     pI830->xaa_scratch = NULL;
@@ -882,7 +887,47 @@ i830_allocate_cursor_buffers(ScrnInfoPtr
 	return TRUE;
     }
 
-    return FALSE;
+    /*
+     * Allocate four separate buffers when the kernel doesn't support
+     * large allocations as on Linux. If any of these fail, just
+     * bail back to software cursors everywhere
+     */
+    for (i = 0; i < xf86_config->num_crtc; i++)
+    {
+	xf86CrtcPtr	    crtc = xf86_config->crtc[i];
+	I830CrtcPrivatePtr  intel_crtc = crtc->driver_private;
+	
+	pI830->cursor_mem_classic[i] = i830_allocate_memory (pScrn, 
+							     "Core cursor",
+							     HWCURSOR_SIZE,
+							     GTT_PAGE_SIZE,
+							     flags);
+	if (!pI830->cursor_mem_classic[i])
+	    return FALSE;
+	pI830->cursor_mem_argb[i] = i830_allocate_memory (pScrn, "ARGB cursor",
+							  HWCURSOR_SIZE_ARGB,
+							  GTT_PAGE_SIZE,
+							  flags);
+	if (!pI830->cursor_mem_argb[i])
+	    return FALSE;
+
+	/*
+	 * Set up the pointers into the allocations
+	 */
+	if (pI830->CursorNeedsPhysical)
+	{
+	    intel_crtc->cursor_addr = pI830->cursor_mem_classic[i]->bus_addr;
+	    intel_crtc->cursor_argb_addr = pI830->cursor_mem_argb[i]->bus_addr;
+	}
+	else
+	{
+	    intel_crtc->cursor_addr = pI830->cursor_mem_classic[i]->offset;
+	    intel_crtc->cursor_argb_addr = pI830->cursor_mem_argb[i]->offset;
+	}
+	intel_crtc->cursor_offset = pI830->cursor_mem_classic[i]->offset;
+	intel_crtc->cursor_argb_offset = pI830->cursor_mem_argb[i]->offset;
+    }
+    return TRUE;
 }
 
 /*
diff-tree 62a5399d70ac3f8579441d617f8d80c94942a32a (from 05e0021147a89254182c277007236448f315231c)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Sat Mar 17 21:32:36 2007 -0700

    Elide I830DRIClipNotify for older DRI versions.
    
    I830DRIClipNotify is passed to newer versions of DRI; don't include it in
    the server when building against older versions.

diff --git a/src/i830_dri.c b/src/i830_dri.c
index b24c839..0fcce58 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -126,7 +126,14 @@ static void I830DRITransitionTo2d(Screen
 static void I830DRITransitionTo3d(ScreenPtr pScreen);
 static void I830DRITransitionMultiToSingle3d(ScreenPtr pScreen);
 static void I830DRITransitionSingleToMulti3d(ScreenPtr pScreen);
+#if DRIINFO_MAJOR_VERSION > 5 || \
+    (DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1)
+#define DRI_SUPPORTS_CLIP_NOTIFY 1
+#endif
+
+#ifdef DRI_SUPPORTS_CLIP_NOTIFY
 static void I830DRIClipNotify(ScreenPtr pScreen, WindowPtr *ppWin, int num);
+#endif
 
 extern void GlxSetVisualConfigs(int nconfigs,
 				__GLXvisualConfig * configs,
@@ -576,8 +583,7 @@ I830DRIScreenInit(ScreenPtr pScreen)
 
       if (minor >= 1)
 #endif
-#if DRIINFO_MAJOR_VERSION > 5 || \
-    (DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1)
+#if DRI_SUPPORTS_CLIP_NOTIFY
 	 pDRIInfo->ClipNotify = I830DRIClipNotify;
 #endif
    }
@@ -1547,6 +1553,7 @@ I830DRITransitionTo2d(ScreenPtr pScreen)
    sPriv->pf_enabled = 0;
 }
 
+#if DRI_SUPPORTS_CLIP_NOTIFY
 static void
 I830DRIClipNotify(ScreenPtr pScreen, WindowPtr *ppWin, int num)
 {
@@ -1595,7 +1602,7 @@ I830DRIClipNotify(ScreenPtr pScreen, Win
 
    I830DRISetPfMask(pScreen, pfMask);
 }
-
+#endif /* DRI_SUPPORTS_CLIP_NOTIFY */
 
 /**
  * Update the SAREA fields with the most recent values.
diff-tree 05e0021147a89254182c277007236448f315231c (from d05bb5362e986c9d27bc03c7e1a939ba28824810)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Sat Mar 17 21:31:04 2007 -0700

    Cast ARGB cursor address to CARD32 * to eliminate warning.
    
    While we're just doing a memcpy, it's nice for the two argument types to
    match.

diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index dec619f..d97b246 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -154,7 +154,7 @@ i830_crtc_load_cursor_argb (xf86CrtcPtr 
     I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
     CARD32		*pcurs;
 
-    pcurs = pI830->FbBase + intel_crtc->cursor_argb_offset;
+    pcurs = (CARD32 *) (pI830->FbBase + intel_crtc->cursor_argb_offset);
 
     intel_crtc->cursor_is_argb = TRUE;
     memcpy (pcurs, image, I810_CURSOR_Y * I810_CURSOR_X * 4);
diff-tree d05bb5362e986c9d27bc03c7e1a939ba28824810 (from 44d1b544cec2e75735d2e27d66a9240317b962c2)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Sat Mar 17 20:21:59 2007 -0700

    Increase DDC I2C RiseFallTime to handle older monitors
    
    Changing this value slows the entire I2C bus down, making it far more
    reliable on older monitors. Note the same change has been made in the core X
    server code; this change is included here to ensure that older X servers
    work reliably with this driver.

diff --git a/src/i830_i2c.c b/src/i830_i2c.c
index 08ff522..da8f38e 100644
--- a/src/i830_i2c.c
+++ b/src/i830_i2c.c
@@ -377,6 +377,7 @@ I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr
     pI2CBus->StartTimeout = 550;
     pI2CBus->BitTimeout = 40;
     pI2CBus->AcknTimeout = 40;
+    pI2CBus->RiseFallTime = 20;
 
     if (!xf86I2CBusInit(pI2CBus))
 	return FALSE;
diff-tree 44d1b544cec2e75735d2e27d66a9240317b962c2 (from a58befe9d243bd562cb4b2f08ec5c9f754148c20)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Sat Mar 17 17:15:43 2007 -0700

    Build fix for pre-XF86DRI_MM environments.
    
    Misplaced brace broke builds with older DRM libraries.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 5650faf..c6aea5c 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1280,8 +1280,8 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 		    "\tfor the DRM memory manager.\n",
 		    pI830->mmSize);
       }
-   } 
 #endif
+   } 
    
 #endif
 
diff-tree a58befe9d243bd562cb4b2f08ec5c9f754148c20 (from 9d6d9ace4bd3180a4484321c3b96a83bc4adaf84)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Sat Mar 17 17:12:37 2007 -0700

    Remove extra (and incorrect) I2C ByteTimeout setting.
    
    Setting the value correctly and then immediately breaking it caused many I2C
    transactions to timeout with slow monitors. Oops.

diff --git a/src/i830_i2c.c b/src/i830_i2c.c
index 319e8da..08ff522 100644
--- a/src/i830_i2c.c
+++ b/src/i830_i2c.c
@@ -368,10 +368,14 @@ I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr
 
     /* Assume all busses are used for DDCish stuff */
     
+    /* 
+     * These were set incorrectly in the server pre-1.3, Having
+     * duplicate settings is sub-optimal, but this lets the driver
+     * work with older servers
+     */
     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))
diff-tree 9d6d9ace4bd3180a4484321c3b96a83bc4adaf84 (from a117bc9e3eb824f2056ee6416859ea3ab1fdcc30)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Mar 16 19:41:54 2007 -0700

    Move vendor ID check in the utils to after pci_device_probe.
    
    Even current libpciaccess seems to require this.

diff --git a/src/bios_reader/bios_dumper.c b/src/bios_reader/bios_dumper.c
index 071419b..c0dbdcf 100644
--- a/src/bios_reader/bios_dumper.c
+++ b/src/bios_reader/bios_dumper.c
@@ -60,15 +60,15 @@ int main(int argc, char **argv)
     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);
     }
 
+    if (dev->vendor_id != 0x8086)
+	errx(1, "Graphics card is non-intel");
+
     bios = malloc(dev->rom_size);
     if (bios == NULL)
 	errx(1, "Couldn't allocate memory for BIOS data\n");
diff --git a/src/reg_dumper/main.c b/src/reg_dumper/main.c
index 50c7923..b3c50de 100644
--- a/src/reg_dumper/main.c
+++ b/src/reg_dumper/main.c
@@ -52,15 +52,15 @@ int main(int argc, char **argv)
     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);
     }
 
+    if (dev->vendor_id != 0x8086)
+	errx(1, "Graphics card is non-intel");
+
     i830.PciInfo = &i830.pci_info_rec;
     i830.PciInfo->chipType = dev->device_id;
 
diff-tree a117bc9e3eb824f2056ee6416859ea3ab1fdcc30 (from 29446cdb4f72e12c5249b0d4b79ea56d9fe19934)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Mar 16 19:39:34 2007 -0700

    Add the (afaict) correct ch7017 I2C slave address.

diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index 629e9c7..04750e5 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -72,7 +72,7 @@ struct _I830DVODriver i830_dvo_drivers[]
     */
     /*
     { I830_DVO_CHIP_LVDS, "ch7017", "ch7017_methods",
-      (CH7017_ADDR_1 << 1), ch7017_symbols, NULL, NULL, NULL }
+      0xea, ch7017_symbols, NULL, NULL, NULL }
     */
 };
 
diff-tree 29446cdb4f72e12c5249b0d4b79ea56d9fe19934 (from 213394fbaaf353404cbb3aaa4c20860f48ee1079)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Mar 16 19:18:37 2007 -0700

    Fix compile failure due to needed types being in inttypes.h on Linux.

diff --git a/src/reg_dumper/reg_dumper.h b/src/reg_dumper/reg_dumper.h
index a52d662..07ddf6f 100644
--- a/src/reg_dumper/reg_dumper.h
+++ b/src/reg_dumper/reg_dumper.h
@@ -25,7 +25,7 @@
  *
  */
 
-#include <sys/types.h>
+#include <inttypes.h>
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
diff-tree 213394fbaaf353404cbb3aaa4c20860f48ee1079 (from 316ee682d342556b65cbd60409201591e916aac5)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Mar 15 19:13:28 2007 -0700

    Fix crashes and other failures when a cursor allocation fails.
    
    Now, we allocate one single block of memory for cursors, and either succeed or
    fail once, rather than trying to support partial fallback modes that generally
    resulted in pain due to being untested.  In particular, this fixes cursors on
    FreeBSD, which only allowed one large physically-contiguous allocation.

diff --git a/src/i830.h b/src/i830.h
index 661d27e..f8416de 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -227,8 +227,14 @@ typedef struct _I830CrtcPrivateRec {
     ExaOffscreenArea *rotate_mem_exa;
 #endif
 
-    i830_memory *cursor_mem;
-    i830_memory *cursor_mem_argb;
+    /* Card virtual address of the cursor */
+    unsigned long cursor_offset;
+    unsigned long cursor_argb_offset;
+    /* Physical or virtual addresses of the cursor for setting in the cursor
+     * registers.
+     */
+    unsigned long cursor_addr;
+    unsigned long cursor_argb_addr;
     Bool	cursor_is_argb;
 } I830CrtcPrivateRec, *I830CrtcPrivatePtr;
 
@@ -276,6 +282,7 @@ typedef struct _I830Rec {
 
    i830_memory *front_buffer;
    i830_memory *front_buffer_2;
+   i830_memory *cursor_mem;
    i830_memory *xaa_scratch;
    i830_memory *xaa_scratch_2;
 #ifdef I830_USE_EXA
diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index 9cc92dc..dec619f 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -75,21 +75,14 @@ I830SetPipeCursorBase (xf86CrtcPtr crtc)
     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);
-    i830_memory		*cursor_mem;
-    CARD32		value;
+    int			cursor_base;
 
+    cursor_base = (pipe == 0) ? CURSOR_A_BASE : CURSOR_B_BASE;
+    
     if (intel_crtc->cursor_is_argb)
-	cursor_mem = intel_crtc->cursor_mem_argb;
-    else
-	cursor_mem = intel_crtc->cursor_mem;
-
-    if (pI830->CursorNeedsPhysical)
-	value = cursor_mem->bus_addr;
+       OUTREG(cursor_base, intel_crtc->cursor_argb_addr);
     else
-	value = cursor_mem->offset;
-    
-    OUTREG(cursor_base, value);
+       OUTREG(cursor_base, intel_crtc->cursor_addr);
 }
 
 void
@@ -143,11 +136,11 @@ I830CursorInit(ScreenPtr pScreen)
 void
 i830_crtc_load_cursor_image (xf86CrtcPtr crtc, unsigned char *src)
 {
-    ScrnInfoPtr		scrn = crtc->scrn;
-    I830Ptr		pI830 = I830PTR(scrn);
+    I830Ptr		pI830 = I830PTR(crtc->scrn);
     I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
-    CARD8		*pcurs = (CARD8 *) (pI830->FbBase +
-					    intel_crtc->cursor_mem->offset);
+    CARD8		*pcurs;
+
+    pcurs = pI830->FbBase + intel_crtc->cursor_offset;
 
     intel_crtc->cursor_is_argb = FALSE;
     memcpy (pcurs, src, I810_CURSOR_X * I810_CURSOR_Y / 4);
@@ -157,11 +150,11 @@ i830_crtc_load_cursor_image (xf86CrtcPtr
 void
 i830_crtc_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image)
 {
-    ScrnInfoPtr		scrn = crtc->scrn;
-    I830Ptr		pI830 = I830PTR(scrn);
+    I830Ptr		pI830 = I830PTR(crtc->scrn);
     I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
-    CARD32		*pcurs = (CARD32 *) (pI830->FbBase +
-					     intel_crtc->cursor_mem_argb->offset);
+    CARD32		*pcurs;
+
+    pcurs = pI830->FbBase + intel_crtc->cursor_argb_offset;
 
     intel_crtc->cursor_is_argb = TRUE;
     memcpy (pcurs, image, I810_CURSOR_Y * I810_CURSOR_X * 4);
diff --git a/src/i830_memory.c b/src/i830_memory.c
index a20e743..440618a 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -62,10 +62,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * The allocations we might do:
  *
  * - Ring buffer
- * - HW cursor 1
- * - HW cursor 2
- * - HW ARGB cursor 1
- * - HW ARGB cursor 2
+ * - HW cursor block
  * - Overlay registers
  * - XAA linear allocator (optional)
  * - EXA 965 state buffer
@@ -214,8 +211,6 @@ void
 i830_reset_allocations(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-    int i;
 
     /* While there is any memory between the start and end markers, free it. */
     while (pI830->memory_list->next->next != NULL)
@@ -224,13 +219,7 @@ i830_reset_allocations(ScrnInfoPtr pScrn
     /* 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;
-    }
-
+    pI830->cursor_mem = NULL;
     pI830->front_buffer = NULL;
     pI830->front_buffer_2 = NULL;
     pI830->xaa_scratch = NULL;
@@ -849,51 +838,51 @@ i830_allocate_framebuffer(ScrnInfoPtr pS
 }
 
 static Bool
-i830_allocate_cursor_buffers(xf86CrtcPtr crtc)
+i830_allocate_cursor_buffers(ScrnInfoPtr pScrn)
 {
-    ScrnInfoPtr pScrn = crtc->scrn;
-    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
     I830Ptr pI830 = I830PTR(pScrn);
-    long size;
+    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     int flags = pI830->CursorNeedsPhysical ? NEED_PHYSICAL_ADDR : 0;
+    int i;
+    long size;
 
-    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.
+    /* Try to allocate one big blob for our cursor memory.  This works
+     * around a limitation in the FreeBSD AGP driver that allows only one
+     * physical allocation larger than a page, and could allos us
+     * to pack the cursors smaller.
      */
+    size = xf86_config->num_crtc * (HWCURSOR_SIZE + HWCURSOR_SIZE_ARGB);
 
-    size = HWCURSOR_SIZE;
+    pI830->cursor_mem = i830_allocate_memory(pScrn, "HW cursors",
+					     size, GTT_PAGE_SIZE,
+					     flags);
+    if (pI830->cursor_mem != NULL) {
+	unsigned long cursor_offset_base = pI830->cursor_mem->offset;
+	unsigned long cursor_addr_base, offset = 0;
 
-    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) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		       "Failed to allocate HW cursor space.\n");
-	    return FALSE;
-	}
-    }
+	if (pI830->CursorNeedsPhysical)
+	    cursor_addr_base = pI830->cursor_mem->bus_addr;
+	else
+	    cursor_addr_base = pI830->cursor_mem->offset;
 
-    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) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		       "Failed to allocate HW (ARGB) cursor space.\n");
+	/* Set up the offsets for our cursors in each CRTC. */
+	for (i = 0; i < xf86_config->num_crtc; i++) {
+	    xf86CrtcPtr crtc = xf86_config->crtc[i];
+	    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+
+	    intel_crtc->cursor_argb_addr = cursor_addr_base + offset;
+	    intel_crtc->cursor_argb_offset = cursor_offset_base + offset;
+	    offset += HWCURSOR_SIZE_ARGB;
+
+	    intel_crtc->cursor_addr = cursor_addr_base + offset;
+	    intel_crtc->cursor_offset = cursor_offset_base + offset;
+	    offset += HWCURSOR_SIZE;
 	}
+
+	return TRUE;
     }
 
-    return TRUE;
+    return FALSE;
 }
 
 /*
@@ -904,10 +893,8 @@ Bool
 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;
-    int i;
 
     if (!pI830->StolenOnly &&
 	(!xf86AgpGARTSupported() || !xf86AcquireGART(pScrn->scrnIndex))) {
@@ -923,19 +910,11 @@ i830_allocate_2d_memory(ScrnInfoPtr pScr
     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]) &&
-		!pI830->SWCursor)
-		{
-		    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-			       "Disabling HW cursor because the cursor memory "
-			       "allocation failed.\n");
-		    pI830->SWCursor = TRUE;
-		    break;
-		}
-	}
+    if (!pI830->SWCursor && !i830_allocate_cursor_buffers(pScrn)) {
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		   "Disabling HW cursor because the cursor memory "
+		   "allocation failed.\n");
+	pI830->SWCursor = TRUE;
     }
 
     /* Space for the X Server's 3D context.  32k is fine for right now. */
diff-tree 316ee682d342556b65cbd60409201591e916aac5 (from 8b06ab50bbd79dfaf4c90a6f76116ace64b85b77)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Mar 15 18:53:55 2007 -0700

    Don't reload the cursors if we haven't set up the screen yet.
    
    This avoids a crash during preinit if we set a mode for load detecting.

diff --git a/src/i830_display.c b/src/i830_display.c
index 2fc81b9..98137a2 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -578,7 +578,8 @@ static void
 i830_crtc_commit (xf86CrtcPtr crtc)
 {
     crtc->funcs->dpms (crtc, DPMSModeOn);
-    xf86_reload_cursors (crtc->scrn->pScreen);
+    if (crtc->scrn->pScreen != NULL)
+	xf86_reload_cursors (crtc->scrn->pScreen);
 }
 
 void
diff-tree 8b06ab50bbd79dfaf4c90a6f76116ace64b85b77 (from 8ae6ad93329e2842c6f2d5b20ffeb0c14d10c0de)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Mar 15 10:12:14 2007 -0700

    Fix sparse warnings about using 0 for NULL.

diff --git a/src/i810_driver.c b/src/i810_driver.c
index 6666d7f..3689446 100644
--- a/src/i810_driver.c
+++ b/src/i810_driver.c
@@ -2217,7 +2217,7 @@ I810ScreenInit(int scrnIndex, ScreenPtr 
       }
    }
 
-   fbPictureInit(pScreen, 0, 0);
+   fbPictureInit(pScreen, NULL, 0);
 
    xf86SetBlackWhitePixels(pScreen);
 
@@ -2276,18 +2276,18 @@ I810ScreenInit(int scrnIndex, ScreenPtr 
    /* Use driver specific palette load routines for Direct Color support. -jens */
    if (pScrn->bitsPerPixel == 16) {
       if (pScrn->depth == 15) {
-	 if (!xf86HandleColormaps(pScreen, 256, 8, I810LoadPalette15, 0,
+	 if (!xf86HandleColormaps(pScreen, 256, 8, I810LoadPalette15, NULL,
 				  CMAP_PALETTED_TRUECOLOR |
 				  CMAP_RELOAD_ON_MODE_SWITCH))
 	    return FALSE;
       } else {
-	 if (!xf86HandleColormaps(pScreen, 256, 8, I810LoadPalette16, 0,
+	 if (!xf86HandleColormaps(pScreen, 256, 8, I810LoadPalette16, NULL,
 				  CMAP_PALETTED_TRUECOLOR |
 				  CMAP_RELOAD_ON_MODE_SWITCH))
 	    return FALSE;
       }
    } else {
-      if (!xf86HandleColormaps(pScreen, 256, 8, I810LoadPalette24, 0,
+      if (!xf86HandleColormaps(pScreen, 256, 8, I810LoadPalette24, NULL,
 			       CMAP_PALETTED_TRUECOLOR |
 			       CMAP_RELOAD_ON_MODE_SWITCH))
 	 return FALSE;
@@ -2535,19 +2535,19 @@ I810CloseScreen(int scrnIndex, ScreenPtr
 
    if (pI810->ScanlineColorExpandBuffers) {
       xfree(pI810->ScanlineColorExpandBuffers);
-      pI810->ScanlineColorExpandBuffers = 0;
+      pI810->ScanlineColorExpandBuffers = NULL;
    }
 
    if (infoPtr) {
       if (infoPtr->ScanlineColorExpandBuffers)
 	 xfree(infoPtr->ScanlineColorExpandBuffers);
       XAADestroyInfoRec(infoPtr);
-      pI810->AccelInfoRec = 0;
+      pI810->AccelInfoRec = NULL;
    }
 
    if (pI810->CursorInfoRec) {
       xf86DestroyCursorInfoRec(pI810->CursorInfoRec);
-      pI810->CursorInfoRec = 0;
+      pI810->CursorInfoRec = NULL;
    }
 
    /* Free all allocated video ram.
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 497a4ab..5650faf 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -555,7 +555,7 @@ I830UnmapMMIO(ScrnInfoPtr pScrn)
 
    xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pI830->MMIOBase,
 		   I810_REG_SIZE);
-   pI830->MMIOBase = 0;
+   pI830->MMIOBase = NULL;
 }
 
 static Bool
@@ -565,7 +565,7 @@ I830UnmapMem(ScrnInfoPtr pScrn)
 
    xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pI830->FbBase,
 		   pI830->FbMapSize);
-   pI830->FbBase = 0;
+   pI830->FbBase = NULL;
    I830UnmapMMIO(pScrn);
    return TRUE;
 }
@@ -903,7 +903,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
     } else 
         pI830->entityPrivate = NULL;
 
-   if (xf86RegisterResources(pI830->pEnt->index, 0, ResNone)) {
+   if (xf86RegisterResources(pI830->pEnt->index, NULL, ResNone)) {
       PreInitCleanup(pScrn);
       return FALSE;
    }
@@ -2568,7 +2568,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       }
    }
 
-   fbPictureInit(pScreen, 0, 0);
+   fbPictureInit(pScreen, NULL, 0);
 
    xf86SetBlackWhitePixels(pScreen);
 
@@ -2605,7 +2605,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       return FALSE;
 
    DPRINTF(PFX, "assert( if(!xf86HandleColormaps(pScreen, ...)) )\n");
-   if (!xf86HandleColormaps(pScreen, 256, 8, I830LoadPalette, 0,
+   if (!xf86HandleColormaps(pScreen, 256, 8, I830LoadPalette, NULL,
 			    CMAP_RELOAD_ON_MODE_SWITCH |
 			    CMAP_PALETTED_TRUECOLOR)) {
       return FALSE;
@@ -2962,7 +2962,7 @@ I830CloseScreen(int scrnIndex, ScreenPtr
 
    if (pI830->ScanlineColorExpandBuffers) {
       xfree(pI830->ScanlineColorExpandBuffers);
-      pI830->ScanlineColorExpandBuffers = 0;
+      pI830->ScanlineColorExpandBuffers = NULL;
    }
 #ifdef I830_USE_XAA
    if (infoPtr) {
diff-tree 8ae6ad93329e2842c6f2d5b20ffeb0c14d10c0de (from 9fbef2de9edbbed9c2f6a80c4074b9b245547c45)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Thu Mar 15 00:00:51 2007 -0700

    Use new driver-independent CRTC-based cursor layer.
    
    This eliminates all of the cursor rotation code and other cursor management
    infrastructure, leaving a fairly simple hardware layer in its place.

diff --git a/src/i830.h b/src/i830.h
index d4be403..661d27e 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -229,6 +229,7 @@ typedef struct _I830CrtcPrivateRec {
 
     i830_memory *cursor_mem;
     i830_memory *cursor_mem_argb;
+    Bool	cursor_is_argb;
 } I830CrtcPrivateRec, *I830CrtcPrivatePtr;
 
 #define I830CrtcPrivate(c) ((I830CrtcPrivatePtr) (c)->driver_private)
@@ -328,9 +329,7 @@ typedef struct _I830Rec {
    int backPitch;
 
    Bool CursorNeedsPhysical;
-   Bool CursorIsARGB;
-   CursorPtr pCurs;
-
+ 
    DGAModePtr DGAModes;
    int numDGAModes;
    Bool DGAactive;
@@ -366,7 +365,6 @@ typedef struct _I830Rec {
    Bool useEXA;
    Bool noAccel;
    Bool SWCursor;
-   Bool cursorOn;
 #ifdef I830_USE_XAA
    XAAInfoRecPtr AccelInfoRec;
 
@@ -382,7 +380,6 @@ typedef struct _I830Rec {
 			 int w, int h);
    void (*xaa_done_composite)(PixmapPtr pDst);
 #endif
-   xf86CursorInfoPtr CursorInfoRec;
    CloseScreenProcPtr CloseScreen;
 
 #ifdef I830_USE_EXA
@@ -542,6 +539,27 @@ extern void I830EmitInvarientState(ScrnI
 extern void I915EmitInvarientState(ScrnInfoPtr pScrn);
 extern void I830SelectBuffer(ScrnInfoPtr pScrn, int buffer);
 
+/* CRTC-based cursor functions */
+void
+i830_crtc_load_cursor_image (xf86CrtcPtr crtc, unsigned char *src);
+
+#ifdef ARGB_CURSOR
+void
+i830_crtc_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image);
+#endif
+
+void
+i830_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y);
+
+void
+i830_crtc_show_cursor (xf86CrtcPtr crtc);
+
+void
+i830_crtc_hide_cursor (xf86CrtcPtr crtc);
+
+void
+i830_crtc_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg);
+
 extern void I830RefreshRing(ScrnInfoPtr pScrn);
 extern void I830EmitFlush(ScrnInfoPtr pScrn);
 
diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index 8578511..9cc92dc 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -68,17 +68,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 #include "i830.h"
 
-static void I830LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src);
-static void I830ShowCursor(ScrnInfoPtr pScrn);
-static void I830HideCursor(ScrnInfoPtr pScrn);
-static void I830SetCursorColors(ScrnInfoPtr pScrn, int bg, int fb);
-static void I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y);
-static Bool I830UseHWCursor(ScreenPtr pScrn, CursorPtr pCurs);
-#ifdef ARGB_CURSOR
-static void I830LoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs);
-static Bool I830UseHWCursorARGB(ScreenPtr pScrn, CursorPtr pCurs);
-#endif
-
 static void
 I830SetPipeCursorBase (xf86CrtcPtr crtc)
 {
@@ -86,533 +75,207 @@ 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);
     i830_memory		*cursor_mem;
+    CARD32		value;
 
-    if (pipe >= xf86_config->num_crtc)
-	FatalError("Bad pipe number for cursor base setting\n");
-
-    if (pI830->CursorIsARGB)
+    if (intel_crtc->cursor_is_argb)
 	cursor_mem = intel_crtc->cursor_mem_argb;
     else
 	cursor_mem = intel_crtc->cursor_mem;
 
-    if (pI830->CursorNeedsPhysical) {
-	OUTREG(cursor_base, cursor_mem->bus_addr);
-    } else {
-	OUTREG(cursor_base, cursor_mem->offset);
-    }
+    if (pI830->CursorNeedsPhysical)
+	value = cursor_mem->bus_addr;
+    else
+	value = cursor_mem->offset;
+    
+    OUTREG(cursor_base, value);
 }
 
 void
-I830SetPipeCursor (xf86CrtcPtr crtc, Bool force)
+I830InitHWCursor(ScrnInfoPtr pScrn)
 {
-    ScrnInfoPtr		pScrn = crtc->scrn;
-    I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
-    int			pipe = intel_crtc->pipe;
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     I830Ptr		pI830 = I830PTR(pScrn);
     CARD32		temp;
-    Bool		show;
-    
-    if (!crtc->enabled)
-	return;
+    int			i;
 
-    show = pI830->cursorOn && crtc->cursorInRange;
-    if (show && (force || !crtc->cursorShown))
-    {
-	if (IS_MOBILE(pI830) || IS_I9XX(pI830)) {
-	    int	cursor_control;
-	    if (pipe == 0)
-		cursor_control = CURSOR_A_CONTROL;
-	    else
-		cursor_control = CURSOR_B_CONTROL;
-	    temp = INREG(cursor_control);
-	    temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
-	    if (pI830->CursorIsARGB) {
-		temp |= CURSOR_MODE_64_ARGB_AX | 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);
-	} else {
-	    temp = INREG(CURSOR_CONTROL);
-	    temp &= ~(CURSOR_FORMAT_MASK);
-	    temp |= CURSOR_ENABLE;
-	    if (pI830->CursorIsARGB) {
-		temp |= CURSOR_FORMAT_ARGB | CURSOR_GAMMA_ENABLE;
-	    } else
-		temp |= CURSOR_FORMAT_3C;
-	    OUTREG(CURSOR_CONTROL, temp);
-	}
-	crtc->cursorShown = TRUE;
-    }
-    else if (!show && (force || crtc->cursorShown))
+    DPRINTF(PFX, "I830InitHWCursor\n");
+
+    /* Initialise the HW cursor registers, leaving the cursor hidden. */
+    for (i = 0; i < xf86_config->num_crtc; i++)
     {
+	int   cursor_control = i == 0 ? CURSOR_A_CONTROL : CURSOR_B_CONTROL;
+	
+	temp = INREG(cursor_control);
 	if (IS_MOBILE(pI830) || IS_I9XX(pI830)) 
 	{
-	    int	cursor_control;
-	    if (pipe == 0)
-		cursor_control = CURSOR_A_CONTROL;
-	    else
-		cursor_control = CURSOR_B_CONTROL;
-	    temp = INREG(cursor_control);
-	    temp &= ~(CURSOR_MODE|MCURSOR_GAMMA_ENABLE);
+	    temp &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE |
+		      MCURSOR_MEM_TYPE_LOCAL |
+		      MCURSOR_PIPE_SELECT);
+	    temp |= (i << 28);
 	    temp |= CURSOR_MODE_DISABLE;
-	    OUTREG(cursor_control, temp);
-	} else {
-	    temp = INREG(CURSOR_CONTROL);
+	}
+	else
+	{
 	    temp &= ~(CURSOR_ENABLE|CURSOR_GAMMA_ENABLE);
-	    OUTREG(CURSOR_CONTROL, temp);
 	}
-	crtc->cursorShown = FALSE;
+	
+	/* Need to set control, then address. */
+	OUTREG(cursor_control, temp);
+	I830SetPipeCursorBase(xf86_config->crtc[i]);
     }
-
-    /* Flush cursor changes. */
-    I830SetPipeCursorBase(crtc);
-}
-
-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 < 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 < xf86_config->num_crtc; i++)
-      {
-	 int   cursor_control = i == 0 ? CURSOR_A_CONTROL : CURSOR_B_CONTROL;
-	 temp = INREG(cursor_control);
-	 temp &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE |
-		   MCURSOR_MEM_TYPE_LOCAL |
-		   MCURSOR_PIPE_SELECT);
-	 temp |= (i << 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_control, temp);
-	 I830SetPipeCursorBase(xf86_config->crtc[i]);
-      }
-   } else {
-      temp = INREG(CURSOR_CONTROL);
-      temp &= ~(CURSOR_FORMAT_MASK | CURSOR_GAMMA_ENABLE |
-		CURSOR_ENABLE  | CURSOR_STRIDE_MASK);
-      if (pI830->CursorIsARGB)
-         temp |= CURSOR_FORMAT_ARGB | CURSOR_GAMMA_ENABLE;
-      else 
-         temp |= CURSOR_FORMAT_3C;
-      /* This initialises the format and leave the cursor disabled. */
-      OUTREG(CURSOR_CONTROL, temp);
-      /* Need to set address and size after disabling. */
-      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);
-   }
 }
 
 Bool
 I830CursorInit(ScreenPtr pScreen)
 {
-   ScrnInfoPtr pScrn;
-   I830Ptr pI830;
-   xf86CursorInfoPtr infoPtr;
-
-   DPRINTF(PFX, "I830CursorInit\n");
-   pScrn = xf86Screens[pScreen->myNum];
-   pI830 = I830PTR(pScrn);
-   pI830->CursorInfoRec = infoPtr = xf86CreateCursorInfoRec();
-   if (!infoPtr)
-      return FALSE;
-
-   infoPtr->MaxWidth = I810_CURSOR_X;
-   infoPtr->MaxHeight = I810_CURSOR_Y;
-   infoPtr->Flags = (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
-		     HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
-		     HARDWARE_CURSOR_INVERT_MASK |
-		     HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK |
-		     HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
-		     HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 | 0);
-
-   infoPtr->SetCursorColors = I830SetCursorColors;
-   infoPtr->SetCursorPosition = I830SetCursorPosition;
-   infoPtr->LoadCursorImage = I830LoadCursorImage;
-   infoPtr->HideCursor = I830HideCursor;
-   infoPtr->ShowCursor = I830ShowCursor;
-   infoPtr->UseHWCursor = I830UseHWCursor;
-#ifdef ARGB_CURSOR
-   infoPtr->UseHWCursorARGB = I830UseHWCursorARGB;
-   infoPtr->LoadCursorARGB = I830LoadCursorARGB;
-#endif
-
-   pI830->pCurs = NULL;
-
-
-   I830HideCursor(pScrn);
-
-   return xf86InitCursor(pScreen, infoPtr);
+    return xf86_cursors_init (pScreen, I810_CURSOR_X, I810_CURSOR_Y,
+			      (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
+			       HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
+			       HARDWARE_CURSOR_INVERT_MASK |
+			       HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK |
+			       HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
+			       HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 |
+			       HARDWARE_CURSOR_ARGB));
 }
 
-static Bool
-I830UseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
-{
-   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-   I830Ptr pI830 = I830PTR(pScrn);
-
-   pI830->pCurs = pCurs;
-
-   return TRUE;
-}
-
-static void
-I830CRTCLoadCursorImage(xf86CrtcPtr crtc, unsigned char *src)
-{
-   ScrnInfoPtr pScrn = crtc->scrn;
-   I830Ptr pI830 = I830PTR(pScrn);
-   I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
-   CARD8 *pcurs = (CARD8 *) (pI830->FbBase + intel_crtc->cursor_mem->offset);
-   int x, y;
-
-   DPRINTF(PFX, "I830LoadCursorImage\n");
-
-#ifdef ARGB_CURSOR
-   pI830->CursorIsARGB = FALSE;
-#endif
- 
-   memset(pcurs, 0, 64 * 64 / 4);
-
-#define GetBit(image, x, y)\
-    ((int)((*(image + ((x) / 8) + ((y) * (128/8))) &\
-	    (1 << ( 7 -((x) % 8) ))) ? 1 : 0))
-
-#define SetBit(image, x, y)\
-    (*(image + (x) / 8 + (y) * (128/8)) |=\
-     (int) (1 <<  (7-((x) % 8))))
-
-   switch (crtc->rotation) {
-      case RR_Rotate_90:
-         for (y = 0; y < 64; y++) {
-            for (x = 0; x < 64; x++) {
-               if (GetBit(src, 64 - y - 1, x))
-                  SetBit(pcurs, x, y);
-               if (GetBit(src, 128 - y - 1, x))
-                  SetBit(pcurs, x + 64, y);
-            }
-         }
-
-         return;
-      case RR_Rotate_180:
-         for (y = 0; y < 64; y++) {
-            for (x = 0; x < 64; x++) {
-               if (GetBit(src, 64 - x - 1, 64 - y - 1))
-                  SetBit(pcurs, x, y);
-               if (GetBit(src, 128 - x - 1, 64 - y - 1))
-                  SetBit(pcurs, x + 64, y);
-            }
-         }
-
-         return;
-      case RR_Rotate_270:
-         for (y = 0; y < 64; y++) {
-            for (x = 0; x < 64; x++) {
-               if (GetBit(src, y, 64 - x - 1))
-                  SetBit(pcurs, x, y);
-               if (GetBit(src, y + 64, 64 - x - 1))
-                  SetBit(pcurs, x + 64, y);
-            }
-         }
-
-         return;
-   }
-
-   for (y = 0; y < 64; y++) {
-      for (x = 0; x < 64 / 4; x++) {
-	 *pcurs++ = *src++;
-      }
-   }
-}
-
-static void
-I830LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
+void
+i830_crtc_load_cursor_image (xf86CrtcPtr crtc, unsigned char *src)
 {
-    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-    int pipe;
+    ScrnInfoPtr		scrn = crtc->scrn;
+    I830Ptr		pI830 = I830PTR(scrn);
+    I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
+    CARD8		*pcurs = (CARD8 *) (pI830->FbBase +
+					    intel_crtc->cursor_mem->offset);
 
-    for (pipe = 0; pipe < xf86_config->num_crtc; pipe++) {
-       I830CRTCLoadCursorImage(xf86_config->crtc[pipe], src);
-    }
+    intel_crtc->cursor_is_argb = FALSE;
+    memcpy (pcurs, src, I810_CURSOR_X * I810_CURSOR_Y / 4);
 }
 
 #ifdef ARGB_CURSOR
-#include "cursorstr.h"
-
-static Bool I830UseHWCursorARGB (ScreenPtr pScreen, CursorPtr pCurs)
+void
+i830_crtc_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image)
 {
-   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;
-
-   /* 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 == NULL)
-	 return FALSE;
-   }
-
-   if (pScrn->bitsPerPixel == 8)
-      return FALSE;
-
-   if (pCurs->bits->height <= 64 && pCurs->bits->width <= 64) 
-	return TRUE;
+    ScrnInfoPtr		scrn = crtc->scrn;
+    I830Ptr		pI830 = I830PTR(scrn);
+    I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
+    CARD32		*pcurs = (CARD32 *) (pI830->FbBase +
+					     intel_crtc->cursor_mem_argb->offset);
 
-   return FALSE;
+    intel_crtc->cursor_is_argb = TRUE;
+    memcpy (pcurs, image, I810_CURSOR_Y * I810_CURSOR_X * 4);
 }
+#endif
 
-static void I830CRTCLoadCursorARGB (xf86CrtcPtr crtc, CursorPtr pCurs)
+void
+i830_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
 {
-   I830Ptr pI830 = I830PTR(crtc->scrn);
-   I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
-   CARD32 *dst = (CARD32 *) (pI830->FbBase +
-			     intel_crtc->cursor_mem_argb->offset);
-   CARD32 *image = (CARD32 *)pCurs->bits->argb;
-   int x, y, w, h;
-
-   DPRINTF(PFX, "I830LoadCursorARGB\n");
+    ScrnInfoPtr		scrn = crtc->scrn;
+    I830Ptr		pI830 = I830PTR(scrn);
+    I830CrtcPrivatePtr	intel_crtc = I830CrtcPrivate(crtc);
+    CARD32		temp;
 
-   if (!image)
-	return;	/* XXX can't happen */
+    temp = 0;
+    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);
+
+    switch (intel_crtc->pipe) {
+    case 0:
+	OUTREG(CURSOR_A_POSITION, temp);
+	break;
+    case 1:
+	OUTREG(CURSOR_B_POSITION, temp);
+	break;
+    }
     
-   pI830->CursorIsARGB = TRUE;
-
-   w = pCurs->bits->width;
-   h = pCurs->bits->height;
-
-   switch (crtc->rotation) {
-      case RR_Rotate_90:
-         for (y = 0; y < h; y++) {
-            for (x = 0; x < w; x++)
-               dst[(y) + ((64 - x - 1) * 64)] = *image++;
-            for(; x < 64; x++)
-               dst[(y) + ((64 - x - 1) * 64)] = 0;
-         }
-         for(; y < 64; y++) {
-   	    for(x = 0; x < 64; x++)
-               dst[(y) + ((64 - x - 1) * 64)] = 0;
-         }
-         return;
-
-      case RR_Rotate_180:
-         for (y = 0; y < h; y++) {
-            for (x = 0; x < w; x++)
-               dst[(64 - x - 1) + ((64 - y - 1) * 64)] = *image++;
-            for(; x < 64; x++)
-               dst[(64 - x - 1) + ((64 - y - 1) * 64)] = 0;
-         }
-         for(; y < 64; y++) {
-            for(x = 0; x < 64; x++)
-               dst[(64 - x - 1) + ((64 - y - 1) * 64)] = 0;
-         }
-         return;
-
-      case RR_Rotate_270:
-         for (y = 0; y < h; y++) {
-            for (x = 0; x < w; x++)
-               dst[(64 - y - 1) + (x * 64)] = *image++;
-            for(; x < 64; x++)
-               dst[(64 - y - 1) + (x * 64)] = 0;
-         }
-         for(; y < 64; y++) {
-            for(x = 0; x < 64; x++)
-               dst[(64 - y - 1) + (x * 64)] = 0;
-         }
-         return;
-   }
-
-   for(y = 0; y < h; y++) {
-      for(x = 0; x < w; x++)
-          *dst++ = *image++;
-      for(; x < 64; x++)
-          *dst++ = 0;
-   }
-
-   for(; y < 64; y++) {
-      for(x = 0; x < 64; x++)
-          *dst++ = 0;
-   }
+    if (crtc->cursor_shown)
+	I830SetPipeCursorBase (crtc);
 }
 
-static void
-I830LoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs)
+void
+i830_crtc_show_cursor (xf86CrtcPtr crtc)
 {
-    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-    int pipe;
+    ScrnInfoPtr		scrn = crtc->scrn;
+    I830Ptr		pI830 = I830PTR(scrn);
+    I830CrtcPrivatePtr	intel_crtc = I830CrtcPrivate(crtc);
+    int			pipe = intel_crtc->pipe;
+    CARD32		temp;
+    int			cursor_control = (pipe == 0 ? CURSOR_A_CONTROL :
+					  CURSOR_B_CONTROL);
+    
+    temp = INREG(cursor_control);
+    
+    if (IS_MOBILE(pI830) || IS_I9XX(pI830)) 
+    {
+	temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
+	if (intel_crtc->cursor_is_argb)
+	    temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
+	else
+	    temp |= CURSOR_MODE_64_4C_AX;
 
-    for (pipe = 0; pipe < xf86_config->num_crtc; pipe++) {
-       I830CRTCLoadCursorARGB(xf86_config->crtc[pipe], pCurs);
+	temp |= (pipe << 28); /* Connect to correct pipe */
     }
-}
-#endif
-
-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;
-    int root_x = x, root_y = y;
-    int pipe;
-
-    root_x = x + pScrn->frameX0; /* undo what xf86HWCurs did */
-    root_y = y + pScrn->frameY0;
-
-    for (pipe = 0; pipe < xf86_config->num_crtc; pipe++)
+    else 
     {
-	xf86CrtcPtr	    crtc = xf86_config->crtc[pipe];
-	DisplayModePtr	    mode = &crtc->mode;
-	int		    thisx = 0;
-	int		    thisy = 0;
-	int hotspotx = 0, hotspoty = 0;
-
-	if (!crtc->enabled)
-	    continue;
-
-	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->HDisplay - (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
-	 * 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);
-
-	crtc->cursorInRange = inrange;
-	
-        I830SetPipeCursor (crtc, FALSE);
+	temp &= ~(CURSOR_FORMAT_MASK);
+	temp |= CURSOR_ENABLE;
+	if (intel_crtc->cursor_is_argb)
+	    temp |= CURSOR_FORMAT_ARGB | CURSOR_GAMMA_ENABLE;
+	else
+	    temp |= CURSOR_FORMAT_3C;
     }
+    
+    /* Need to set mode, then address. */
+    OUTREG(cursor_control, temp);
+    I830SetPipeCursorBase (crtc);
 }
 
-static void
-I830ShowCursor(ScrnInfoPtr pScrn)
+void
+i830_crtc_hide_cursor (xf86CrtcPtr crtc)
 {
-    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-    I830Ptr pI830 = I830PTR(pScrn);
-    int pipe;
-
-    DPRINTF(PFX, "I830ShowCursor\n");
-
-    pI830->cursorOn = TRUE;
-    for (pipe = 0; pipe < xf86_config->num_crtc; pipe++)
-	I830SetPipeCursor (xf86_config->crtc[pipe], TRUE);
-}
+    ScrnInfoPtr		scrn = crtc->scrn;
+    I830Ptr		pI830 = I830PTR(scrn);
+    I830CrtcPrivatePtr	intel_crtc = I830CrtcPrivate(crtc);
+    int			pipe = intel_crtc->pipe;
+    CARD32		temp;
+    int			cursor_control = (pipe == 0 ? CURSOR_A_CONTROL :
+					  CURSOR_B_CONTROL);
+    
+    temp = INREG(cursor_control);
+    
+    if (IS_MOBILE(pI830) || IS_I9XX(pI830)) 
+    {
+	temp &= ~(CURSOR_MODE|MCURSOR_GAMMA_ENABLE);
+	temp |= CURSOR_MODE_DISABLE;
+    }
+    else
+	temp &= ~(CURSOR_ENABLE|CURSOR_GAMMA_ENABLE);
 
-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 < xf86_config->num_crtc; pipe++)
-	I830SetPipeCursor (xf86_config->crtc[pipe], TRUE);
+    /* Need to set mode, then address. */
+    OUTREG(cursor_control, temp);
+    I830SetPipeCursorBase (crtc);
 }
 
-static void
-I830SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
+void
+i830_crtc_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg)
 {
-   xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-   I830Ptr pI830 = I830PTR(pScrn);
-   int pipe; 
-
-#ifdef ARGB_CURSOR
-    /* Don't recolour cursors set with SetCursorARGB. */
-    if (pI830->CursorIsARGB)
-       return;
-#endif
-
-   DPRINTF(PFX, "I830SetCursorColors\n");
+    ScrnInfoPtr		scrn = crtc->scrn;
+    I830Ptr		pI830 = I830PTR(scrn);
+    I830CrtcPrivatePtr	intel_crtc = I830CrtcPrivate(crtc);
+    int			pipe = intel_crtc->pipe;
+    int			pal0 = pipe == 0 ? CURSOR_A_PALETTE0 : CURSOR_B_PALETTE0;
 
-   for (pipe = 0; pipe < xf86_config->num_crtc; pipe++)
-   {
-      xf86CrtcPtr	crtc = xf86_config->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);
-      }
-   }
+    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 6e64961..2fc81b9 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -578,6 +578,7 @@ static void
 i830_crtc_commit (xf86CrtcPtr crtc)
 {
     crtc->funcs->dpms (crtc, DPMSModeOn);
+    xf86_reload_cursors (crtc->scrn->pScreen);
 }
 
 void
@@ -1334,6 +1335,12 @@ static const xf86CrtcFuncsRec i830_crtc_
     .shadow_create = i830_crtc_shadow_create,
     .shadow_allocate = i830_crtc_shadow_allocate,
     .shadow_destroy = i830_crtc_shadow_destroy,
+    .set_cursor_colors = i830_crtc_set_cursor_colors,
+    .set_cursor_position = i830_crtc_set_cursor_position,
+    .show_cursor = i830_crtc_show_cursor,
+    .hide_cursor = i830_crtc_hide_cursor,
+/*    .load_cursor_image = i830_crtc_load_cursor_image, */
+    .load_cursor_argb = i830_crtc_load_cursor_argb,
     .destroy = NULL, /* XXX */
 };
 
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 1be9fdd..497a4ab 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1563,9 +1563,8 @@ ResetState(ScrnInfoPtr pScrn, Bool flush
    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);
+
+   xf86_hide_cursors (pScrn);
 }
 
 static void
@@ -2585,9 +2584,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       }
    }
 
-   if (!I830EnterVT(scrnIndex, 0))
-      return FALSE;
-
    miInitializeBackingStore(pScreen);
    xf86SetBackingStore(pScreen);
    xf86SetSilkenMouse(pScreen);
@@ -2601,6 +2597,9 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    } else
       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Initializing SW Cursor!\n");
 
+   if (!I830EnterVT(scrnIndex, 0))
+      return FALSE;
+
    DPRINTF(PFX, "assert( if(!miCreateDefColormap(pScreen)) )\n");
    if (!miCreateDefColormap(pScreen))
       return FALSE;
@@ -2785,8 +2784,7 @@ I830LeaveVT(int scrnIndex, int flags)
    }
 #endif
 
-   if (pI830->CursorInfoRec && pI830->CursorInfoRec->HideCursor)
-      pI830->CursorInfoRec->HideCursor(pScrn);
+   xf86_hide_cursors (pScrn);
 
    ResetState(pScrn, TRUE);
 
@@ -2981,10 +2979,7 @@ I830CloseScreen(int scrnIndex, ScreenPtr
        pI830->EXADriverPtr = NULL;
    }
 #endif
-   if (pI830->CursorInfoRec) {
-      xf86DestroyCursorInfoRec(pI830->CursorInfoRec);
-      pI830->CursorInfoRec = 0;
-   }
+   xf86_cursors_fini (pScreen);
 
    i830_reset_allocations(pScrn);
 
diff-tree 9fbef2de9edbbed9c2f6a80c4074b9b245547c45 (from 555b801a75cafa082808bc9bb683e700fc97d79a)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Mar 14 12:34:34 2007 -0700

    Bump to 1.9.92 for RC2.

diff --git a/configure.ac b/configure.ac
index 52cc07b..451179d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -22,7 +22,7 @@
 
 AC_PREREQ(2.57)
 AC_INIT([xf86-video-intel],
-        1.9.91,
+        1.9.92,
         [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
         xf86-video-intel)
 
diff-tree 555b801a75cafa082808bc9bb683e700fc97d79a (from 66fdb08c83d353fbe4e917900c54b555c869eb80)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Wed Mar 14 11:41:50 2007 +0100

    Make sure the legacy texture area is there when needed.
    
    This currently only matters when the DRM memory manager is not available and
    Option "Legacy3D" "off" is specified, but that hasn't always been the case and
    might change again in the future.

diff --git a/src/i830.h b/src/i830.h
index dc8041c..d4be403 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -591,6 +591,7 @@ void i830_free_3d_memory(ScrnInfoPtr pSc
 void i830_free_memory(ScrnInfoPtr pScrn, i830_memory *mem);
 extern long I830CheckAvailableMemory(ScrnInfoPtr pScrn);
 Bool i830_allocate_2d_memory(ScrnInfoPtr pScrn);
+Bool i830_allocate_texture_memory(ScrnInfoPtr pScrn);
 Bool i830_allocate_3d_memory(ScrnInfoPtr pScrn);
 
 extern Bool I830IsPrimary(ScrnInfoPtr pScrn);
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 8fae4b7..b24c839 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -702,6 +702,16 @@ I830DRIScreenInit(ScreenPtr pScreen)
 
 	       i830_free_memory(pScrn, pI830->memory_manager);
 	       pI830->memory_manager = NULL;
+
+	       if (!(pI830->mmModeFlags & I830_KERNEL_TEX)) {
+		  pI830->mmModeFlags |= I830_KERNEL_TEX;
+
+		  if (!i830_allocate_texture_memory(pScrn)) {
+		     I830DRICloseScreen(pScreen);
+		     drmFreeVersion(version);
+		     return FALSE;
+		  }
+	       }
 	    }
 	 }
 #ifdef DAMAGE
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 0742d8c..a20e743 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -1156,7 +1156,7 @@ i830_allocate_depthbuffer(ScrnInfoPtr pS
     return TRUE;
 }
 
-static Bool
+Bool
 i830_allocate_texture_memory(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
diff-tree 66fdb08c83d353fbe4e917900c54b555c869eb80 (from 44708bdd9ebfef0328302c9a964b80deb46e57c6)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Mar 13 17:07:10 2007 -0700

    Refine the i855 LVDS clock code.  In particular, p2 is always 14.
    
    This gets correct clocks detected on most harware.  The SSC is always assumed
    to be 66Mhz, which may not be true, but we'll fix that when we find example
    hardware.

diff --git a/src/i830_debug.c b/src/i830_debug.c
index dccaa7e..7fd9441 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -187,25 +187,24 @@ DEBUGSTRING(i830_debug_dpll)
     } 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);
+	    p2 = 14;
 	} else {
 	    mode = "DAC/serial";
 	    if (val & PLL_P1_DIVIDE_BY_TWO) {
 		p1 = 2;
 	    } else {
-		/* Map the number in the field to (1, 31) */
+		/* Map the number in the field to (3, 33) */
 		p1 = ((val & DPLL_FPA01_P1_POST_DIV_MASK_I830) >>
 		      DPLL_FPA01_P1_POST_DIV_SHIFT) + 2;
 	    }
+	    if (val & PLL_P2_DIVIDE_BY_4)
+		p2 = 4;
+	    else
+		p2 = 2;
 	}
     }
 
diff --git a/src/i830_display.c b/src/i830_display.c
index a5d8df8..6e64961 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -85,15 +85,14 @@ 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		     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_P1_MIN		      2
+#define I8XX_P1_MAX		     33
+#define I8XX_P1_LVDS_MIN	      1
+#define I8XX_P1_LVDS_MAX	      6
+#define I8XX_P2_SLOW		      4
+#define I8XX_P2_FAST		      2
+#define I8XX_P2_LVDS_SLOW	      14
+#define I8XX_P2_LVDS_FAST	      14 /* No fast option */
 #define I8XX_P2_SLOW_LIMIT	 165000
 
 #define I9XX_DOT_MIN		  20000
@@ -149,7 +148,7 @@ static const intel_limit_t intel_limits[
         .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 },
+		 .p2_slow = I8XX_P2_LVDS_SLOW,	.p2_fast = I8XX_P2_LVDS_FAST },
     },
     { /* INTEL_LIMIT_I9XX_SDVO_DAC */
         .dot = { .min = I9XX_DOT_MIN,		.max = I9XX_DOT_MAX },
@@ -206,7 +205,7 @@ static const intel_limit_t *intel_limit 
 static void i8xx_clock(int refclk, intel_clock_t *clock)
 {
     clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
-    clock->p = (clock->p1 + 2) << (clock->p2 + 1);
+    clock->p = clock->p1 * clock->p2;
     clock->vco = refclk * clock->m / (clock->n + 2);
     clock->dot = clock->vco / clock->p;
 }
@@ -797,15 +796,15 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
 	    dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT);
     } else {
 	if (is_lvds) {
-	    /* map (-1 to 4) to ((1 << 0) to (1 << 5)). */
-	    dpll |= (1 << (clock.p1 + 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
+	    dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
 	} else {
-	    if (clock.p1 == 0)
+	    if (clock.p1 == 2)
 		dpll |= PLL_P1_DIVIDE_BY_TWO;
 	    else
-		dpll |= clock.p1 << DPLL_FPA01_P1_POST_DIV_SHIFT;
+		dpll |= (clock.p1 - 2) << DPLL_FPA01_P1_POST_DIV_SHIFT;
+	    if (clock.p2 == 4)
+		dpll |= PLL_P2_DIVIDE_BY_4;
 	}
-	dpll |= clock.p2 << 23;
     }
 
     if (is_tv)
@@ -1255,26 +1254,28 @@ i830_crtc_clock_get(ScrnInfoPtr pScrn, x
 	Bool is_lvds = (pipe == 1) && (INREG(LVDS) & LVDS_PORT_EN);
 
 	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;
+			   DPLL_FPA01_P1_POST_DIV_SHIFT);
+	    clock.p2 = 14;
+
+	    if ((dpll & PLL_REF_INPUT_MASK) == PLLB_REF_INPUT_SPREADSPECTRUMIN)
+		i8xx_clock(66000, &clock); /* XXX: might not be 66MHz */
+	    else
+		i8xx_clock(48000, &clock);		
 	} else {
 	    if (dpll & PLL_P1_DIVIDE_BY_TWO) {
-		clock.p1 = 0;
+		clock.p1 = 2;
 	    } 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);
+		    DPLL_FPA01_P1_POST_DIV_SHIFT) + 2;
 	    }
 	    if (dpll & PLL_P2_DIVIDE_BY_4)
-		clock.p2 = 1;
+		clock.p2 = 4;
 	    else
-		clock.p2 = 0;
-	}
+		clock.p2 = 2;
 
-	/* XXX: Deal with other refclocks */
-	i8xx_clock(48000, &clock);
+	    i8xx_clock(48000, &clock);
+	}
     }
 
     /* XXX: It would be nice to validate the clocks, but we can't reuse
diff-tree 44708bdd9ebfef0328302c9a964b80deb46e57c6 (from 5135b3a79f9c30ebce78c84c49846bba83607fed)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Mar 13 16:55:38 2007 -0700

    Get SDVO DPMS working on the Mac Mini by writing SDVOB and SDVOC together.
    
    Also, add code for setting the encoder power state like the BIOS does, but this
    doesn't appear to work.  We do much more than the BIOS does in powering things
    down, so perhaps that's interfering somehow.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index cd0b115..fb6a7c8 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -79,6 +79,25 @@ struct i830_sdvo_priv {
     /** @} */
 };
 
+/**
+ * Writes the SDVOB or SDVOC with the given value, but always writes both
+ * SDVOB and SDVOC to work around apparent hardware issues (according to
+ * comments in the BIOS).
+ */
+static void i830_sdvo_write_sdvox(xf86OutputPtr output, CARD32 val)
+{
+    ScrnInfoPtr		    pScrn = output->scrn;
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    struct i830_sdvo_priv   *dev_priv = intel_output->dev_priv;
+    I830Ptr		    pI830 = I830PTR(pScrn);
+
+    if (dev_priv->output_device == SDVOC)
+	OUTREG(SDVOB, INREG(SDVOB));
+    OUTREG(dev_priv->output_device, val);
+    if (dev_priv->output_device == SDVOB)
+	OUTREG(SDVOC, INREG(SDVOC));
+}
+
 /** Read a single byte from the given address on the SDVO device. */
 static Bool i830_sdvo_read_byte(xf86OutputPtr output, int addr,
 				unsigned char *ch)
@@ -163,6 +182,9 @@ const static struct _sdvo_cmd_name {
     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_GET_SUPPORTED_POWER_STATES),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ENCODER_POWER_STATE),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ENCODER_POWER_STATE),
     SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_RESOLUTION_SUPPORT),
     SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTROL_BUS_SWITCH),
 };
@@ -346,6 +368,34 @@ i830_sdvo_set_active_outputs(xf86OutputP
     return (status == SDVO_CMD_STATUS_SUCCESS);
 }
 
+static Bool
+i830_sdvo_set_encoder_power_state(xf86OutputPtr output, int mode)
+{
+    CARD8 status;
+    CARD8 state;
+
+    switch (mode) {
+    case DPMSModeOn:
+	state = SDVO_ENCODER_STATE_ON;
+	break;
+    case DPMSModeStandby:
+	state = SDVO_ENCODER_STATE_STANDBY;
+	break;
+    case DPMSModeSuspend:
+	state = SDVO_ENCODER_STATE_SUSPEND;
+	break;
+    case DPMSModeOff:
+	state = SDVO_ENCODER_STATE_OFF;
+	break;
+    }
+
+    i830_sdvo_write_cmd(output, SDVO_CMD_SET_ENCODER_POWER_STATE, &state,
+			sizeof(state));
+    status = i830_sdvo_read_response(output, NULL, 0);
+
+    return (status == SDVO_CMD_STATUS_SUCCESS);
+}
+
 /**
  * Returns the pixel clock range limits of the current target input in kHz.
  */
@@ -669,7 +719,7 @@ i830_sdvo_mode_set(xf86OutputPtr output,
 	sdvox |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT;
     }
 
-    OUTREG(dev_priv->output_device, sdvox);
+    i830_sdvo_write_sdvox(output, sdvox);
 }
 
 static void
@@ -683,9 +733,16 @@ i830_sdvo_dpms(xf86OutputPtr output, int
 
     if (mode != DPMSModeOn) {
 	i830_sdvo_set_active_outputs(output, 0);
-	temp = INREG(dev_priv->output_device);
-	if ((temp & SDVO_ENABLE) != 0)
-	    OUTREG(dev_priv->output_device, temp & ~SDVO_ENABLE);
+	if (0)
+	    i830_sdvo_set_encoder_power_state(output, mode);
+
+	if (mode == DPMSModeOff) {
+	    temp = INREG(dev_priv->output_device);
+	    if ((temp & SDVO_ENABLE) != 0) {
+		i830_sdvo_write_sdvox(output, temp & ~SDVO_ENABLE);
+		POSTING_READ(dev_priv->output_device);
+	    }
+	}
     } else {
 	Bool input1, input2;
 	int i;
@@ -694,14 +751,15 @@ 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_write_sdvox(output, temp | SDVO_ENABLE);
 	    POSTING_READ(dev_priv->output_device);
 #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.
+	    /* 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);
+	    i830_sdvo_write_sdvox(output, INREG(dev_priv->output_device) |
+				  SDVO_ENABLE);
 	    POSTING_READ(dev_priv->output_device);
 #endif
 	}
@@ -717,6 +775,8 @@ i830_sdvo_dpms(xf86OutputPtr output, int
 		       SDVO_NAME(dev_priv));
 	}
 
+	if (0)
+	    i830_sdvo_set_encoder_power_state(output, mode);
 	i830_sdvo_set_active_outputs(output, dev_priv->active_outputs);
     }
 }
@@ -764,7 +824,6 @@ i830_sdvo_restore(xf86OutputPtr output)
     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;
     int			    i;
     Bool		    input1, input2;
@@ -794,7 +853,7 @@ i830_sdvo_restore(xf86OutputPtr output)
 
     i830_sdvo_set_clock_rate_mult(output, dev_priv->save_sdvo_mult);
 
-    OUTREG(dev_priv->output_device, dev_priv->save_SDVOX);
+    i830_sdvo_write_sdvox(output, dev_priv->save_SDVOX);
 
     if (dev_priv->save_SDVOX & SDVO_ENABLE)
     {
diff --git a/src/i830_sdvo_regs.h b/src/i830_sdvo_regs.h
index 59b2aa8..437ff50 100644
--- a/src/i830_sdvo_regs.h
+++ b/src/i830_sdvo_regs.h
@@ -307,6 +307,14 @@ struct i830_sdvo_set_target_input_args {
 
 #define SDVO_CMD_SET_TV_FORMAT				0x29
 
+#define SDVO_CMD_GET_SUPPORTED_POWER_STATES		0x2a
+#define SDVO_CMD_GET_ENCODER_POWER_STATE		0x2b
+#define SDVO_CMD_SET_ENCODER_POWER_STATE		0x2c
+# define SDVO_ENCODER_STATE_ON					(1 << 0)
+# define SDVO_ENCODER_STATE_STANDBY				(1 << 1)
+# define SDVO_ENCODER_STATE_SUSPEND				(1 << 2)
+# define SDVO_ENCODER_STATE_OFF					(1 << 3)
+
 #define SDVO_CMD_SET_TV_RESOLUTION_SUPPORT		0x93
 
 #define SDVO_CMD_SET_CONTROL_BUS_SWITCH			0x7a
diff-tree 5135b3a79f9c30ebce78c84c49846bba83607fed (from 578da7ca705c5a58c0bd397b0831e2f95140f8ae)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Mar 13 10:21:06 2007 -0700

    Use a POSTING_READ(reg) macro instead of using the (void)INREG(reg) pattern.

diff --git a/src/common.h b/src/common.h
index f596eb8..a634895 100644
--- a/src/common.h
+++ b/src/common.h
@@ -233,6 +233,7 @@ union intfloat {
 #define INREG8(addr)        *(volatile CARD8  *)(RecPtr->MMIOBase + (addr))
 #define INREG16(addr)       *(volatile CARD16 *)(RecPtr->MMIOBase + (addr))
 #define INREG(addr)         *(volatile CARD32 *)(RecPtr->MMIOBase + (addr))
+#define POSTING_READ(addr)  (void)INREG(addr)
 
 #define OUTREG8(addr, val) do {						\
    *(volatile CARD8 *)(RecPtr->MMIOBase  + (addr)) = (val);		\
diff --git a/src/i830_display.c b/src/i830_display.c
index e5390b3..a5d8df8 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -383,12 +383,12 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x,
 
     if (IS_I965G(pI830)) {
         OUTREG(dspbase, Offset);
-	(void) INREG(dspbase);
+	POSTING_READ(dspbase);
         OUTREG(dspsurf, Start);
-	(void) INREG(dspsurf);
+	POSTING_READ(dspsurf);
     } else {
 	OUTREG(dspbase, Start + Offset);
-	(void) INREG(dspbase);
+	POSTING_READ(dspbase);
     }
 
 #ifdef XF86DRI
@@ -447,15 +447,15 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mod
 	if ((temp & DPLL_VCO_ENABLE) == 0)
 	{
 	    OUTREG(dpll_reg, temp);
-	    (void)INREG(dpll_reg);
+	    POSTING_READ(dpll_reg);
 	    /* Wait for the clocks to stabilize. */
 	    usleep(150);
 	    OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE);
-	    (void)INREG(dpll_reg);
+	    POSTING_READ(dpll_reg);
 	    /* Wait for the clocks to stabilize. */
 	    usleep(150);
 	    OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE);
-	    (void)INREG(dpll_reg);
+	    POSTING_READ(dpll_reg);
 	    /* Wait for the clocks to stabilize. */
 	    usleep(150);
 	}
@@ -493,7 +493,7 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mod
 	    OUTREG(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
 	    /* Flush the plane changes */
 	    OUTREG(dspbase_reg, INREG(dspbase_reg));
-	    (void)INREG(dspbase_reg);
+	    POSTING_READ(dspbase_reg);
 	}
 
 	if (!IS_I9XX(pI830)) {
@@ -505,7 +505,7 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mod
 	temp = INREG(pipeconf_reg);
 	if ((temp & PIPEACONF_ENABLE) != 0) {
 	    OUTREG(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
-	    (void)INREG(pipeconf_reg);
+	    POSTING_READ(pipeconf_reg);
 	}
 
 	/* Wait for vblank for the disable to take effect. */
@@ -514,7 +514,7 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mod
 	temp = INREG(dpll_reg);
 	if ((temp & DPLL_VCO_ENABLE) != 0) {
 	    OUTREG(dpll_reg, temp & ~DPLL_VCO_ENABLE);
-	    (void)INREG(dpll_reg);
+	    POSTING_READ(dpll_reg);
 	}
 
 	/* Wait for the clocks to turn off. */
@@ -876,7 +876,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
     {
 	OUTREG(fp_reg, fp);
 	OUTREG(dpll_reg, dpll & ~DPLL_VCO_ENABLE);
-	(void)INREG(dpll_reg);
+	POSTING_READ(dpll_reg);
 	usleep(150);
     }
 
@@ -887,12 +887,12 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
 	 * things on.
 	 */
 	OUTREG(LVDS, INREG(LVDS) | LVDS_PORT_EN | LVDS_PIPEB_SELECT);
-	(void)INREG(LVDS);
+	POSTING_READ(LVDS);
     }
 
     OUTREG(fp_reg, fp);
     OUTREG(dpll_reg, dpll);
-    (void)INREG(dpll_reg);
+    POSTING_READ(dpll_reg);
     /* Wait for the clocks to stabilize. */
     usleep(150);
     
@@ -904,7 +904,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
 	/* write it again -- the BIOS does, after all */
 	OUTREG(dpll_reg, dpll);
     }
-    (void)INREG(dpll_reg);
+    POSTING_READ(dpll_reg);
     /* Wait for the clocks to stabilize. */
     usleep(150);
 
@@ -928,7 +928,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
     OUTREG(dsppos_reg, 0);
     OUTREG(pipesrc_reg, ((mode->HDisplay - 1) << 16) | (mode->VDisplay - 1));
     OUTREG(pipeconf_reg, pipeconf);
-    (void)INREG(pipeconf_reg);
+    POSTING_READ(pipeconf_reg);
     i830WaitForVblank(pScrn);
 
     OUTREG(dspcntr_reg, dspcntr);
diff --git a/src/i830_i2c.c b/src/i830_i2c.c
index 7fac63c..319e8da 100644
--- a/src/i830_i2c.c
+++ b/src/i830_i2c.c
@@ -336,7 +336,7 @@ i830I2CPutBits(I2CBusPtr b, int clock, i
 	clock_bits = GPIO_CLOCK_DIR_OUT|GPIO_CLOCK_DIR_MASK|GPIO_CLOCK_VAL_MASK;
     
     OUTREG(b->DriverPrivate.uval, reserved | data_bits | clock_bits);
-    (void)INREG(b->DriverPrivate.uval);
+    POSTING_READ(b->DriverPrivate.uval);
 }
 
 #endif
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 4c543db..cd0b115 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -695,14 +695,14 @@ i830_sdvo_dpms(xf86OutputPtr output, int
 	if ((temp & SDVO_ENABLE) == 0)
 	{
 	    OUTREG(dev_priv->output_device, temp | SDVO_ENABLE);
-	    (void)INREG(dev_priv->output_device);
+	    POSTING_READ(dev_priv->output_device);
 #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);
-	    (void)INREG(dev_priv->output_device);
+	    POSTING_READ(dev_priv->output_device);
 #endif
 	}
 	for (i = 0; i < 2; i++)
diff-tree 578da7ca705c5a58c0bd397b0831e2f95140f8ae (from cf33abe43bd95c9437fad8e6201a24084ff96cb8)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Mar 13 10:11:29 2007 -0700

    Add PCI write posting protection to i2c putbits.

diff --git a/src/i830_i2c.c b/src/i830_i2c.c
index 450f9de..7fac63c 100644
--- a/src/i830_i2c.c
+++ b/src/i830_i2c.c
@@ -336,6 +336,7 @@ i830I2CPutBits(I2CBusPtr b, int clock, i
 	clock_bits = GPIO_CLOCK_DIR_OUT|GPIO_CLOCK_DIR_MASK|GPIO_CLOCK_VAL_MASK;
     
     OUTREG(b->DriverPrivate.uval, reserved | data_bits | clock_bits);
+    (void)INREG(b->DriverPrivate.uval);
 }
 
 #endif
diff-tree cf33abe43bd95c9437fad8e6201a24084ff96cb8 (from 9d30f0007203157e6b82fa0ffc57324490eb2ca0)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Mar 13 10:08:57 2007 -0700

    Add write posting protection for the SDVO DPMS-on path.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index a3db517..4c543db 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -695,12 +695,14 @@ i830_sdvo_dpms(xf86OutputPtr output, int
 	if ((temp & SDVO_ENABLE) == 0)
 	{
 	    OUTREG(dev_priv->output_device, temp | SDVO_ENABLE);
+	    (void)INREG(dev_priv->output_device);
 #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);
+	    (void)INREG(dev_priv->output_device);
 #endif
 	}
 	for (i = 0; i < 2; i++)
diff-tree 9d30f0007203157e6b82fa0ffc57324490eb2ca0 (from 9c17c6e9c63563cad5edff837519a73fe0afe313)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Mar 13 10:04:06 2007 -0700

    Replace #if 0ed LVDS register setting with updated comment.

diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index f554b38..adfbe4f 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -225,13 +225,9 @@ 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.
+    /* The LVDS pin pair will already have been turned on in the
+     * i830_crtc_mode_set since it has a large impact on the DPLL settings.
      */
-    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-tree 9c17c6e9c63563cad5edff837519a73fe0afe313 (from 2824ec7ccbf44ba413a6133f735f4a548c73b3cd)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Mar 13 09:55:49 2007 -0700

    Add write posting protections to relevant register writes in the mode-set path.

diff --git a/src/i830_display.c b/src/i830_display.c
index d230f74..e5390b3 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -447,12 +447,15 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mod
 	if ((temp & DPLL_VCO_ENABLE) == 0)
 	{
 	    OUTREG(dpll_reg, temp);
+	    (void)INREG(dpll_reg);
 	    /* Wait for the clocks to stabilize. */
 	    usleep(150);
 	    OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE);
+	    (void)INREG(dpll_reg);
 	    /* Wait for the clocks to stabilize. */
 	    usleep(150);
 	    OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE);
+	    (void)INREG(dpll_reg);
 	    /* Wait for the clocks to stabilize. */
 	    usleep(150);
 	}
@@ -490,6 +493,7 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mod
 	    OUTREG(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
 	    /* Flush the plane changes */
 	    OUTREG(dspbase_reg, INREG(dspbase_reg));
+	    (void)INREG(dspbase_reg);
 	}
 
 	if (!IS_I9XX(pI830)) {
@@ -499,15 +503,19 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mod
 
 	/* Next, disable display pipes */
 	temp = INREG(pipeconf_reg);
-	if ((temp & PIPEACONF_ENABLE) != 0)
+	if ((temp & PIPEACONF_ENABLE) != 0) {
 	    OUTREG(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
+	    (void)INREG(pipeconf_reg);
+	}
 
 	/* Wait for vblank for the disable to take effect. */
 	i830WaitForVblank(pScrn);
 
 	temp = INREG(dpll_reg);
-	if ((temp & DPLL_VCO_ENABLE) != 0)
+	if ((temp & DPLL_VCO_ENABLE) != 0) {
 	    OUTREG(dpll_reg, temp & ~DPLL_VCO_ENABLE);
+	    (void)INREG(dpll_reg);
+	}
 
 	/* Wait for the clocks to turn off. */
 	usleep(150);
@@ -856,15 +864,6 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
     pipeconf |= PIPEACONF_ENABLE;
     dpll |= DPLL_VCO_ENABLE;
 #endif
-
-    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 (i830_panel_fitter_pipe (pI830) == pipe)
@@ -877,10 +876,23 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
     {
 	OUTREG(fp_reg, fp);
 	OUTREG(dpll_reg, dpll & ~DPLL_VCO_ENABLE);
+	(void)INREG(dpll_reg);
 	usleep(150);
     }
+
+    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);
+	(void)INREG(LVDS);
+    }
+
     OUTREG(fp_reg, fp);
     OUTREG(dpll_reg, dpll);
+    (void)INREG(dpll_reg);
     /* Wait for the clocks to stabilize. */
     usleep(150);
     
@@ -889,9 +901,10 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
 	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);
+	/* write it again -- the BIOS does, after all */
+	OUTREG(dpll_reg, dpll);
     }
+    (void)INREG(dpll_reg);
     /* Wait for the clocks to stabilize. */
     usleep(150);
 
@@ -915,8 +928,9 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
     OUTREG(dsppos_reg, 0);
     OUTREG(pipesrc_reg, ((mode->HDisplay - 1) << 16) | (mode->VDisplay - 1));
     OUTREG(pipeconf_reg, pipeconf);
+    (void)INREG(pipeconf_reg);
     i830WaitForVblank(pScrn);
-    
+
     OUTREG(dspcntr_reg, dspcntr);
     /* Flush the plane changes */
     i830PipeSetBase(crtc, x, y);
diff-tree 2824ec7ccbf44ba413a6133f735f4a548c73b3cd (from 1ed3843f73a0d8efa405daff3483ebe70bf6134f)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Mar 13 09:53:35 2007 -0700

    Fix uninitialized string use in SDVO non-TMDS case.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index b7cf843..a3db517 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -1205,6 +1205,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
 		   "%s: No active TMDS outputs (0x%02x%02x)\n",
 		   SDVO_NAME(dev_priv),
 		   bytes[0], bytes[1]);
+	name_prefix="Unknown";
     }
     strcpy (name, name_prefix);
     strcat (name, name_suffix);
diff-tree f465c23750adf908c0ea874f95aad98ebd2f1015 (from parents)
Merge: d33e8daa6874ced978d2a1f687c48922555f2524 1ed3843f73a0d8efa405daff3483ebe70bf6134f
Author: Nian Wu <nian.wu at intel.com>
Date:   Tue Mar 13 17:00:44 2007 +0800

    Merge git://proxy01.pd.intel.com:9419/git/xorg/driver/xf86-video-intel into crestline

diff-tree 1ed3843f73a0d8efa405daff3483ebe70bf6134f (from 7aa257154685bd2520649ce87a3a84e55644d02c)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Mar 12 17:47:32 2007 -0700

    Make the 965 use Y-major tiling for the depth buffer, as required by the spec.
    
    An example of the failure can be seen with the reflect demo when set to
    depth buffer mode.
    
    Reported by:	Haihao Xiang <haihao.xiang at intel.com>

diff --git a/src/i830_memory.c b/src/i830_memory.c
index e5168e1..0742d8c 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -1122,12 +1122,19 @@ i830_allocate_depthbuffer(ScrnInfoPtr pS
     /* First try allocating it tiled */
     if (!pI830->disableTiling && IsTileable(pScrn, pitch))
     {
+	enum tile_format tile_format;
+
 	size = ROUND_TO_PAGE(pitch * ALIGN(height, 16));
 
+	/* The 965 requires that the depth buffer be in Y Major format, while
+	 * the rest appear to fail when handed that format.
+	 */
+	tile_format = IS_I965G(pI830) ? TILING_YMAJOR: TILING_XMAJOR;
+
 	pI830->depth_buffer =
 	    i830_allocate_memory_tiled(pScrn, "depth buffer", size, pitch,
 				       GTT_PAGE_SIZE, ALIGN_BOTH_ENDS,
-				       TILING_XMAJOR);
+				       tile_format);
 	pI830->depth_tiled = FENCE_XMAJOR;
     }
 
diff-tree 7aa257154685bd2520649ce87a3a84e55644d02c (from 7c561956a28e90667fef140bc3cfa0edca464f15)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Mon Mar 12 19:00:14 2007 +0100

    Fix build against released libdrm.

diff --git a/src/i830_dri.c b/src/i830_dri.c
index 96061bd..8fae4b7 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -83,6 +83,23 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #include "i915_drm.h"
 
+/* This block and the corresponding configure test can be removed when
+ * libdrm >= 2.3.1 is required.
+ */
+#ifndef HAVE_I915_FLIP
+
+#define DRM_VBLANK_FLIP 0x8000000
+
+typedef struct drm_i915_flip {
+   int pipes;
+} drm_i915_flip_t;
+
+#undef DRM_IOCTL_I915_FLIP
+#define DRM_IOCTL_I915_FLIP DRM_IOW(DRM_COMMAND_BASE + DRM_I915_FLIP, \
+				    drm_i915_flip_t)
+
+#endif
+
 #include "dristruct.h"
 
 static char I830KernelDriverName[] = "i915";
@@ -1510,23 +1527,6 @@ I830DRITransitionTo3d(ScreenPtr pScreen)
    I830DRISetPfMask(pScreen, pI830->allowPageFlip ? 0x3 : 0);
 }
 
-/* This block and the corresponding configure test can be removed when
- * libdrm >= 2.3.1 is required.
- */
-#ifndef HAVE_I915_FLIP
-
-#define DRM_VBLANK_FLIP 0x8000000
-
-typedef struct drm_i915_flip {
-   int pipes;
-} drm_i915_flip_t;
-
-#undef DRM_IOCTL_I915_FLIP
-#define DRM_IOCTL_I915_FLIP DRM_IOW(DRM_COMMAND_BASE + DRM_I915_FLIP, \
-				    drm_i915_flip_t)
-
-#endif
-
 static void
 I830DRITransitionTo2d(ScreenPtr pScreen)
 {
diff-tree 7c561956a28e90667fef140bc3cfa0edca464f15 (from fe59ab9f562fd10118563d80eb3351a4d3b48b3f)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Mon Mar 12 18:55:27 2007 +0100

    Defer flipping pages back to normal until the end of the DRI block handler.
    
    Doing it earlier can result in the wrong page being visible, giving the
    appearance of a frozen X server.

diff --git a/src/i830_dri.c b/src/i830_dri.c
index 5a3aec0..96061bd 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1167,6 +1167,8 @@ I830DRISwapContext(ScreenPtr pScreen, DR
    } else if (syncType == DRI_2D_SYNC &&
 	      oldContextType == DRI_NO_CONTEXT &&
 	      newContextType == DRI_2D_CONTEXT) {
+      drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScreen);
+
       if (I810_DEBUG & DEBUG_VERBOSE_DRI)
 	 ErrorF("i830DRISwapContext (out)\n");
 
@@ -1194,6 +1196,33 @@ I830DRISwapContext(ScreenPtr pScreen, DR
 
       I830EmitFlush(pScrn);
 
+#ifdef DAMAGE
+      /* Try flipping back to the front page if necessary */
+      if (sPriv && !sPriv->pf_enabled && sPriv->pf_current_page != 0) {
+	 drm_i915_flip_t flip = { .pipes = 0 };
+
+	 if (sPriv->pf_current_page & (0x3 << 2)) {
+	    sPriv->pf_current_page = sPriv->pf_current_page & 0x3;
+	    sPriv->pf_current_page |= (sPriv->third_handle ? 2 : 1) << 2;
+
+	    flip.pipes |= 0x2;
+	 }
+
+	 if (sPriv->pf_current_page & 0x3) {
+	    sPriv->pf_current_page = sPriv->pf_current_page & (0x3 << 2);
+	    sPriv->pf_current_page |= sPriv->third_handle ? 2 : 1;
+
+	    flip.pipes |= 0x1;
+	 }
+
+	 drmCommandWrite(pI830->drmSubFD, DRM_I915_FLIP, &flip, sizeof(flip));
+
+	 if (sPriv->pf_current_page != 0)
+	    xf86DrvMsg(pScreen->myNum, X_WARNING,
+		       "[dri] %s: kernel failed to unflip buffers.\n", __func__);
+      }
+#endif
+
       pI830->LockHeld = 0;
    } else if (I810_DEBUG & DEBUG_VERBOSE_DRI)
       ErrorF("i830DRISwapContext (other)\n");
@@ -1448,7 +1477,7 @@ I830DRISetPfMask(ScreenPtr pScreen, int 
       pSAREAPriv->pf_enabled = pI830->allowPageFlip;
       pSAREAPriv->pf_active = pfMask;
    } else
-      pSAREAPriv->pf_enabled = pSAREAPriv->pf_active = 0;
+      pSAREAPriv->pf_active = 0;
 }
 
 static void
@@ -1501,36 +1530,11 @@ typedef struct drm_i915_flip {
 static void
 I830DRITransitionTo2d(ScreenPtr pScreen)
 {
-   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-   I830Ptr pI830 = I830PTR(pScrn);
    drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScreen);
 
-   /* Try flipping back to the front page if necessary */
-   if (sPriv->pf_current_page != 0) {
-      drm_i915_flip_t flip = { .pipes = 0 };
-
-      if (sPriv->pf_current_page & (0x3 << 2)) {
-	 sPriv->pf_current_page = sPriv->pf_current_page & 0x3;
-	 sPriv->pf_current_page |= (sPriv->third_handle ? 2 : 1) << 2;
-
-	 flip.pipes |= 0x2;
-      }
-
-      if (sPriv->pf_current_page & 0x3) {
-	 sPriv->pf_current_page = sPriv->pf_current_page & (0x3 << 2);
-	 sPriv->pf_current_page |= sPriv->third_handle ? 2 : 1;
-
-	 flip.pipes |= 0x1;
-      }
-
-      drmCommandWrite(pI830->drmSubFD, DRM_I915_FLIP, &flip, sizeof(flip));
-   }
-
-   if (sPriv->pf_current_page != 0)
-      xf86DrvMsg(pScreen->myNum, X_WARNING,
-		 "[dri] %s: kernel failed to unflip buffers.\n", __func__);
-
    I830DRISetPfMask(pScreen, 0);
+
+   sPriv->pf_enabled = 0;
 }
 
 static void
diff-tree fe59ab9f562fd10118563d80eb3351a4d3b48b3f (from ba55ff15df974197bebd871e28bb96d817ae41c7)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Mon Mar 12 13:03:47 2007 +0100

    Disable page flipping if the DRM is older than 1.9.
    
    Older versions don't support the functionality we need.

diff --git a/src/i830_dri.c b/src/i830_dri.c
index 52c30eb..5a3aec0 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -687,6 +687,14 @@ I830DRIScreenInit(ScreenPtr pScreen)
 	       pI830->memory_manager = NULL;
 	    }
 	 }
+#ifdef DAMAGE
+	 if (pI830->allowPageFlip && pI830->drmMinor < 9) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		       "DRM version 1.9 or newer required for Page flipping. "
+		       "Disabling.\n");
+	    pI830->allowPageFlip = FALSE;
+	 }
+#endif	 
 	 drmFreeVersion(version);
       }
    }
diff-tree ba55ff15df974197bebd871e28bb96d817ae41c7 (from c4a23c5ef8ce56ee0fe547fbc7c6623c021f801b)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Mon Mar 12 13:01:00 2007 +0100

    Fix attempt to flip pages back to normal when the last 3D window disappears.
    
    When this succeeds, 2D rendering does not have to be synchronized to back
    buffers until the next 3D window appears.

diff --git a/configure.ac b/configure.ac
index fbb9c64..52cc07b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -180,6 +180,14 @@ if test "$DRI" = yes; then
 	if test "$have_damage_h" = yes; then
 		AC_DEFINE(DAMAGE,1,[Use Damage extension])
 	fi
+
+	save_CFLAGS="$CFLAGS"
+	CFLAGS="$DRI_CFLAGS"
+	AC_CHECK_TYPE(drm_i915_flip_t,
+		      [AC_DEFINE(HAVE_I915_FLIP, 1,
+			         [Have drm_i915_flip_t and related definitions])],
+		      [], [#include <i915_drm.h>])
+	CFLAGS="$save_CFLAGS"
 fi
 
 AM_CONDITIONAL(VIDEO_DEBUG, test x$VIDEO_DEBUG = xyes)
diff --git a/src/i830_dri.c b/src/i830_dri.c
index f55fa71..52c30eb 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -81,6 +81,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "i830.h"
 #include "i830_dri.h"
 
+#include "i915_drm.h"
+
 #include "dristruct.h"
 
 static char I830KernelDriverName[] = "i915";
@@ -563,12 +565,13 @@ I830DRIScreenInit(ScreenPtr pScreen)
 #endif
    }
 
+   pDRIInfo->TransitionTo2d = I830DRITransitionTo2d;
+
 #if DRIINFO_MAJOR_VERSION > 5 || \
     (DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1)
    if (!pDRIInfo->ClipNotify)
 #endif
    {
-      pDRIInfo->TransitionTo2d = I830DRITransitionTo2d;
       pDRIInfo->TransitionTo3d = I830DRITransitionTo3d;
       pDRIInfo->TransitionSingleToMulti3D = I830DRITransitionSingleToMulti3d;
       pDRIInfo->TransitionMultiToSingle3D = I830DRITransitionMultiToSingle3d;
@@ -1470,6 +1473,22 @@ I830DRITransitionTo3d(ScreenPtr pScreen)
    I830DRISetPfMask(pScreen, pI830->allowPageFlip ? 0x3 : 0);
 }
 
+/* This block and the corresponding configure test can be removed when
+ * libdrm >= 2.3.1 is required.
+ */
+#ifndef HAVE_I915_FLIP
+
+#define DRM_VBLANK_FLIP 0x8000000
+
+typedef struct drm_i915_flip {
+   int pipes;
+} drm_i915_flip_t;
+
+#undef DRM_IOCTL_I915_FLIP
+#define DRM_IOCTL_I915_FLIP DRM_IOW(DRM_COMMAND_BASE + DRM_I915_FLIP, \
+				    drm_i915_flip_t)
+
+#endif
 
 static void
 I830DRITransitionTo2d(ScreenPtr pScreen)
@@ -1479,10 +1498,27 @@ I830DRITransitionTo2d(ScreenPtr pScreen)
    drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScreen);
 
    /* Try flipping back to the front page if necessary */
-   if (sPriv->pf_current_page == 1)
-      drmCommandNone(pI830->drmSubFD, DRM_I830_FLIP);
+   if (sPriv->pf_current_page != 0) {
+      drm_i915_flip_t flip = { .pipes = 0 };
+
+      if (sPriv->pf_current_page & (0x3 << 2)) {
+	 sPriv->pf_current_page = sPriv->pf_current_page & 0x3;
+	 sPriv->pf_current_page |= (sPriv->third_handle ? 2 : 1) << 2;
+
+	 flip.pipes |= 0x2;
+      }
+
+      if (sPriv->pf_current_page & 0x3) {
+	 sPriv->pf_current_page = sPriv->pf_current_page & (0x3 << 2);
+	 sPriv->pf_current_page |= sPriv->third_handle ? 2 : 1;
+
+	 flip.pipes |= 0x1;
+      }
+
+      drmCommandWrite(pI830->drmSubFD, DRM_I915_FLIP, &flip, sizeof(flip));
+   }
 
-   if (sPriv->pf_current_page == 1)
+   if (sPriv->pf_current_page != 0)
       xf86DrvMsg(pScreen->myNum, X_WARNING,
 		 "[dri] %s: kernel failed to unflip buffers.\n", __func__);
 
diff-tree c4a23c5ef8ce56ee0fe547fbc7c6623c021f801b (from 797aa6fcb1231587bde1efb47bc8430c4c8d8110)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Sat Mar 10 16:15:33 2007 +0100

    Remove unused have3DWindows from pI830.

diff --git a/src/i830.h b/src/i830.h
index 82a4166..dc8041c 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -306,7 +306,6 @@ typedef struct _I830Rec {
 
    int TexGranularity;
    int drmMinor;
-   Bool have3DWindows;
    int mmModeFlags;
    int mmSize;
 
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 38e11e7..f55fa71 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1468,7 +1468,6 @@ I830DRITransitionTo3d(ScreenPtr pScreen)
    I830Ptr pI830 = I830PTR(pScrn);
 
    I830DRISetPfMask(pScreen, pI830->allowPageFlip ? 0x3 : 0);
-   pI830->have3DWindows = 1;
 }
 
 
@@ -1488,8 +1487,6 @@ I830DRITransitionTo2d(ScreenPtr pScreen)
 		 "[dri] %s: kernel failed to unflip buffers.\n", __func__);
 
    I830DRISetPfMask(pScreen, 0);
-
-   pI830->have3DWindows = 0;
 }
 
 static void
diff-tree d33e8daa6874ced978d2a1f687c48922555f2524 (from parents)
Merge: 58aeb87f2e335d15eba73ce9dd1982e867c52403 797aa6fcb1231587bde1efb47bc8430c4c8d8110
Author: Nian Wu <nian.wu at intel.com>
Date:   Mon Mar 12 09:03:52 2007 +0800

    Merge git://proxy01.pd.intel.com:9419/git/xorg/driver/xf86-video-intel into crestline

diff-tree 797aa6fcb1231587bde1efb47bc8430c4c8d8110 (from 43a80ef9094efcb49027c83f0e726f907fecfbb2)
Author: Dave Airlie <airlied at linux.ie>
Date:   Sun Mar 11 12:58:50 2007 +1100

    fixup missing assert includes

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 599edc3..1be9fdd 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -165,6 +165,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define PRINT_MODE_INFO 0
 #endif
 
+#include <assert.h>
 #include <string.h>
 #include <stdio.h>
 #include <unistd.h>
diff --git a/src/i830_memory.c b/src/i830_memory.c
index d6338ec..e5168e1 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -99,6 +99,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "config.h"
 #endif
 
+#include <assert.h>
 #include <string.h>
 
 #include "xf86.h"
diff --git a/src/i830_xaa.c b/src/i830_xaa.c
index 46ea7ec..3440341 100644
--- a/src/i830_xaa.c
+++ b/src/i830_xaa.c
@@ -48,6 +48,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "config.h"
 #endif
 
+#include <assert.h>
 #include "xf86.h"
 #include "xaarop.h"
 #include "i830.h"
diff --git a/src/i965_render.c b/src/i965_render.c
index 78f1146..8d06c22 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -30,6 +30,7 @@
 #include "config.h"
 #endif
 
+#include <assert.h>
 #include "xf86.h"
 #include "i830.h"
 #include "i915_reg.h"
diff-tree 43a80ef9094efcb49027c83f0e726f907fecfbb2 (from 0d33fd3d03cef3a7e63d88ae441354390b37a937)
Author: Dave Airlie <airlied at linux.ie>
Date:   Sun Mar 11 12:58:26 2007 +1100

    fixup brace alignment for older X.org

diff --git a/src/i830_dri.c b/src/i830_dri.c
index 5293574..38e11e7 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -549,8 +549,8 @@ I830DRIScreenInit(ScreenPtr pScreen)
    pDRIInfo->MoveBuffers = I830DRIMoveBuffers;
    pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
 
-#if DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1
    {
+#if DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1
       int major, minor, patch;
 
       DRIQueryVersion(&major, &minor, &patch);
diff-tree 0d33fd3d03cef3a7e63d88ae441354390b37a937 (from 3c2d6e07bdf8daef6486b594aef0d22460eb2585)
Author: Dave Airlie <airlied at linux.ie>
Date:   Sun Mar 11 12:58:02 2007 +1100

    add XMODES flags to the i2c drivers

diff --git a/src/ch7017/Makefile.am b/src/ch7017/Makefile.am
index 7fbb440..45bf699 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@ -I$(srcdir)/.. -I$(srcdir)/../modes
+AM_CFLAGS = @XMODES_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/ch7xxx/Makefile.am b/src/ch7xxx/Makefile.am
index b827bf8..68f766c 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)/.. -I$(srcdir)/../modes
+AM_CFLAGS = @XMODES_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/ivch/Makefile.am b/src/ivch/Makefile.am
index 40e2627..ace076c 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@ -I$(srcdir)/.. -I$(srcdir)/../modes
+AM_CFLAGS = @XMODES_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/sil164/Makefile.am b/src/sil164/Makefile.am
index 4cf717c..ac1b33c 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)/.. -I$(srcdir)/../modes
+AM_CFLAGS = @XMODES_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@ -I$(srcdir)/.. -I$(srcdir)/../modes
 
 sil164_la_LTLIBRARIES = sil164.la
 sil164_la_LDFLAGS = -module -avoid-version
diff-tree 3c2d6e07bdf8daef6486b594aef0d22460eb2585 (from 7518b8959ee7598f3526365a83ea7e143a5d6a4e)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Fri Mar 9 23:49:46 2007 +0100

    Don't crash when the SAREA pointer is NULL.

diff --git a/src/i830_display.c b/src/i830_display.c
index 7855712..d230f74 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -395,6 +395,9 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x,
     if (pI830->directRenderingEnabled) {
 	drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScrn->pScreen);
 
+	if (!sPriv)
+	    return;
+
 	switch (pipe) {
 	case 0:
 	    sPriv->pipeA_x = x;
@@ -516,6 +519,9 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mod
 	drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScrn->pScreen);
 	Bool enabled = crtc->enabled && mode != DPMSModeOff;
 
+	if (!sPriv)
+	    return;
+
 	switch (pipe) {
 	case 0:
 	    sPriv->pipeA_w = enabled ? crtc->mode.HDisplay : 0;
diff-tree 7518b8959ee7598f3526365a83ea7e143a5d6a4e (from 1991a90ae90b388c914985d20d6f8c3637856e9a)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Fri Mar 9 19:50:03 2007 +0100

    Revert change accidentally included in previous commit.

diff --git a/src/i830_exa.c b/src/i830_exa.c
index dfc8f99..bef8fae 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -42,7 +42,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define DEBUG_I830FALLBACK 1
 #endif
 
-#define ALWAYS_SYNC		0
+#define ALWAYS_SYNC		1
 
 #ifdef DEBUG_I830FALLBACK
 #define I830FALLBACK(s, arg...)				\
diff-tree 1991a90ae90b388c914985d20d6f8c3637856e9a (from aef161853033907c6916337cebe88c8f111dd542)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Fri Mar 9 19:47:13 2007 +0100

    Update SAREA pipe sizes in i830_crtc_dpms instead of i830PipeSetBase.
    
    This allows setting the size to 0 when a pipe gets disabled.

diff --git a/src/i830_display.c b/src/i830_display.c
index 8a2494f..7855712 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -399,14 +399,10 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x,
 	case 0:
 	    sPriv->pipeA_x = x;
 	    sPriv->pipeA_y = y;
-	    sPriv->pipeA_w = crtc->mode.HDisplay;
-	    sPriv->pipeA_h = crtc->mode.VDisplay;
 	    break;
 	case 1:
 	    sPriv->pipeB_x = x;
 	    sPriv->pipeB_y = y;
-	    sPriv->pipeB_w = crtc->mode.HDisplay;
-	    sPriv->pipeB_h = crtc->mode.VDisplay;
 	    break;
 	default:
 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
@@ -514,6 +510,28 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mod
 	usleep(150);
 	break;
     }
+
+#ifdef XF86DRI
+    if (pI830->directRenderingEnabled) {
+	drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScrn->pScreen);
+	Bool enabled = crtc->enabled && mode != DPMSModeOff;
+
+	switch (pipe) {
+	case 0:
+	    sPriv->pipeA_w = enabled ? crtc->mode.HDisplay : 0;
+	    sPriv->pipeA_h = enabled ? crtc->mode.VDisplay : 0;
+	    break;
+	case 1:
+	    sPriv->pipeB_w = enabled ? crtc->mode.HDisplay : 0;
+	    sPriv->pipeB_h = enabled ? crtc->mode.VDisplay : 0;
+	    break;
+	default:
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Can't update pipe %d in SAREA\n", pipe);
+	    break;
+	}
+    }
+#endif
 }
 
 static Bool
diff --git a/src/i830_exa.c b/src/i830_exa.c
index bef8fae..dfc8f99 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -42,7 +42,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define DEBUG_I830FALLBACK 1
 #endif
 
-#define ALWAYS_SYNC		1
+#define ALWAYS_SYNC		0
 
 #ifdef DEBUG_I830FALLBACK
 #define I830FALLBACK(s, arg...)				\
diff-tree aef161853033907c6916337cebe88c8f111dd542 (from parents)
Merge: 1b54ee493fb96f944aa81e56fa6f00a8067f87fc 14ee9195d203192d3f613919f230b20b900ffdba
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Fri Mar 9 15:14:48 2007 +0100

    Merge remote branch 'origin/master' into i830-pageflip

diff-tree 1b54ee493fb96f944aa81e56fa6f00a8067f87fc (from parents)
Merge: e972265261c421268e4fb806e587378d0adec577 81722a21d232fa6cfb11fbe3d984abab50e89bcc
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Fri Mar 9 15:13:50 2007 +0100

    Merge remote branch 'origin/master' into i830-pageflip
    
    Conflicts:
    
    	src/i830_dri.c

diff --cc src/i830_dri.c
index 9931acc,680a28e..5293574
@@@ -107,12 -107,7 +107,8 @@@
  static void I830DRITransitionTo3d(ScreenPtr pScreen);
  static void I830DRITransitionMultiToSingle3d(ScreenPtr pScreen);
  static void I830DRITransitionSingleToMulti3d(ScreenPtr pScreen);
 +static void I830DRIClipNotify(ScreenPtr pScreen, WindowPtr *ppWin, int num);
  
- #if 0
- static void I830DRIShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf);
- #endif
- 
  extern void GlxSetVisualConfigs(int nconfigs,
  				__GLXvisualConfig * configs,
  				void **configprivs);
@@@ -1418,24 -1254,8 +1414,20 @@@
   * allocate and free 3d-specific memory on demand.
   */
  
- 
- 
- 
- 
 +/* Use the miext/shadow module to maintain a list of dirty rectangles.
 + * These are blitted to the back buffer to keep both buffers clean
 + * during page-flipping when the 3d application isn't fullscreen.
 + *
 + * Unlike most use of the shadow code, both buffers are in video
 + * memory.
 + *
 + * An alternative to this would be to organize for all on-screen
 + * drawing operations to be duplicated for the two buffers.  That
 + * might be faster, but seems like a lot more work...
 + */
 +
  static void
 -I830EnablePageFlip(ScreenPtr pScreen)
 +I830DRISetPfMask(ScreenPtr pScreen, int pfMask)
  {
     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
diff-tree 14ee9195d203192d3f613919f230b20b900ffdba (from a5f0522b1d34236278861fe15bac2df099f0a2c7)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Mar 7 13:00:03 2007 -0800

    Bug #10157: Fix cursor corruption on server regen.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 30558ac..18a05ef 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2962,6 +2962,8 @@ I830CloseScreen(int scrnIndex, ScreenPtr
       pI830->CursorInfoRec = 0;
    }
 
+   i830_reset_allocations(pScrn);
+
    if (I830IsPrimary(pScrn)) {
       xf86GARTCloseScreen(scrnIndex);
 
diff-tree 58aeb87f2e335d15eba73ce9dd1982e867c52403 (from parents)
Merge: a4e7e814a24dbe30a33e6ad45baeb41d190a2724 81722a21d232fa6cfb11fbe3d984abab50e89bcc
Author: Nian Wu <nian.wu at intel.com>
Date:   Wed Mar 7 16:02:03 2007 -0500

    Merge git://proxy01.pd.intel.com:9419/git/xorg/driver/xf86-video-intel into crestline

diff-tree a5f0522b1d34236278861fe15bac2df099f0a2c7 (from 81722a21d232fa6cfb11fbe3d984abab50e89bcc)
Author: Alan Hourihane <alanh at fairlite.demon.co.uk>
Date:   Wed Mar 7 15:49:47 2007 +0000

    Add some additional checks when XAA is enabled.

diff --git a/src/i810_accel.c b/src/i810_accel.c
index efbe290..1f859b8 100644
--- a/src/i810_accel.c
+++ b/src/i810_accel.c
@@ -597,7 +597,8 @@ I810RefreshRing(ScrnInfoPtr pScrn)
    if (pI810->LpRing->space < 0)
       pI810->LpRing->space += pI810->LpRing->mem.Size;
 
-   pI810->AccelInfoRec->NeedToSync = TRUE;
+   if (pI810->AccelInfoRec)
+      pI810->AccelInfoRec->NeedToSync = TRUE;
 }
 
 /* Emit on gaining VT?
diff --git a/src/i810_dri.c b/src/i810_dri.c
index 3e32283..72718d3 100644
--- a/src/i810_dri.c
+++ b/src/i810_dri.c
@@ -222,6 +222,7 @@ I810InitVisualConfigs(ScreenPtr pScreen)
 	       pConfigs[i].redSize = 5;
 	       pConfigs[i].greenSize = 6;
 	       pConfigs[i].blueSize = 5;
+	       pConfigs[i].alphaSize = 0;
 	       pConfigs[i].redMask = 0x0000F800;
 	       pConfigs[i].greenMask = 0x000007E0;
 	       pConfigs[i].blueMask = 0x0000001F;
@@ -1173,7 +1174,9 @@ I810DRIInitBuffers(WindowPtr pWin, Regio
       pbox++;
    }
    I810SelectBuffer(pScrn, I810_SELECT_FRONT);
-   pI810->AccelInfoRec->NeedToSync = TRUE;
+
+   if (pI810->AccelInfoRec)
+   	pI810->AccelInfoRec->NeedToSync = TRUE;
 }
 
 /* This routine is a modified form of XAADoBitBlt with the calls to
@@ -1332,7 +1335,8 @@ I810DRIMoveBuffers(WindowPtr pParent, DD
       DEALLOCATE_LOCAL(pboxNew1);
    }
 
-   pI810->AccelInfoRec->NeedToSync = TRUE;
+   if (pI810->AccelInfoRec)
+	pI810->AccelInfoRec->NeedToSync = TRUE;
 }
 
 
diff-tree 81722a21d232fa6cfb11fbe3d984abab50e89bcc (from 04f50961e2f1610c39e7e4b45811f2a6b517cad6)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Tue Mar 6 23:16:53 2007 -0800

    Remove usage of 'shadow' module. Use xf86CrtcScreenInit.
    
    With the new mode setting code, rotation is handled outside of the driver,
    so the old usage of the 'shadow' module is no longer needed. Code to
    initialize the crtc structures has been moved out of the driver and into the
    modes code.

diff --git a/src/common.h b/src/common.h
index 6e8ddbd..f596eb8 100644
--- a/src/common.h
+++ b/src/common.h
@@ -87,7 +87,6 @@ extern const char *I810ddcSymbols[];
 extern const char *I810fbSymbols[];
 extern const char *I810xaaSymbols[];
 extern const char *I810shadowFBSymbols[];
-extern const char *I810shadowSymbols[];
 #ifdef XF86DRI
 extern const char *I810driSymbols[];
 extern const char *I810drmSymbols[];
diff --git a/src/i810_driver.c b/src/i810_driver.c
index 04166b7..6666d7f 100644
--- a/src/i810_driver.c
+++ b/src/i810_driver.c
@@ -341,12 +341,6 @@ const char *I810driSymbols[] = {
 
 #endif /* I830_ONLY */
 
-const char *I810shadowSymbols[] = {
-    "shadowSetup",
-    "shadowAdd",
-    NULL
-};
-
 const char *I810i2cSymbols[] = {
     "xf86CreateI2CBusRec",
     "xf86I2CBusInit",
@@ -435,7 +429,6 @@ i810Setup(pointer module, pointer opts, 
 			I810drmSymbols,
 			I810driSymbols,
 #endif
-			I810shadowSymbols,
 			I810shadowFBSymbols,
 			I810vbeSymbols, vbeOptionalSymbols,
 			I810ddcSymbols, I810int10Symbols, NULL);
diff --git a/src/i830_dri.c b/src/i830_dri.c
index f81251a..680a28e 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -108,10 +108,6 @@ 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,
 				void **configprivs);
@@ -981,16 +977,7 @@ I830DRIFinishScreenInit(ScreenPtr pScree
 
    DPRINTF(PFX, "I830DRIFinishScreenInit\n");
 
-   /* Have shadow run only while there is 3d active.
-    */
-#if 0
-   if (pI830->allowPageFlip && pI830->drmMinor >= 1) {
-      shadowAdd(pScreen, 0, I830DRIShadowUpdate, 0, 0, 0);
-   }
-   else
-#endif
-      pI830->allowPageFlip = 0;
-
+   pI830->allowPageFlip = 0;
 
    if (!DRIFinishScreenInit(pScreen))
       return FALSE;
@@ -1267,70 +1254,6 @@ I830DRIMoveBuffers(WindowPtr pParent, DD
  * allocate and free 3d-specific memory on demand.
  */
 
-
-
-
-
-/* Use the miext/shadow module to maintain a list of dirty rectangles.
- * These are blitted to the back buffer to keep both buffers clean
- * during page-flipping when the 3d application isn't fullscreen.
- *
- * Unlike most use of the shadow code, both buffers are in video
- * memory.
- *
- * An alternative to this would be to organize for all on-screen
- * drawing operations to be duplicated for the two buffers.  That
- * might be faster, but seems like a lot more work...
- */
-
-
-#if 0
-/* This should be done *before* XAA syncs,
- * Otherwise will have to sync again???
- */
-static void
-I830DRIShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf)
-{
-   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-   I830Ptr pI830 = I830PTR(pScrn);
-   RegionPtr damage = &pBuf->damage;
-   int i, num =  REGION_NUM_RECTS(damage);
-   BoxPtr pbox = REGION_RECTS(damage);
-   drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScreen);
-   int cmd, br13;
-
-   /* Don't want to do this when no 3d is active and pages are
-    * right-way-round :
-    */
-   if (!pSAREAPriv->pf_active && pSAREAPriv->pf_current_page == 0)
-      return;
-
-   br13 = (pScrn->displayWidth * pI830->cpp) | (0xcc << 16);
-
-   if (pScrn->bitsPerPixel == 32) {
-      cmd = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
-	     XY_SRC_COPY_BLT_WRITE_RGB);
-      br13 |= 3 << 24;
-   } else {
-      cmd = (XY_SRC_COPY_BLT_CMD);
-      br13 |= 1 << 24;
-   }
-
-   for (i = 0 ; i < num ; i++, pbox++) {
-      BEGIN_LP_RING(8);
-      OUT_RING(cmd);
-      OUT_RING(br13);
-      OUT_RING((pbox->y1 << 16) | pbox->x1);
-      OUT_RING((pbox->y2 << 16) | pbox->x2);
-      OUT_RING(pI830->back_buffer->offset);
-      OUT_RING((pbox->y1 << 16) | pbox->x1);
-      OUT_RING(br13 & 0xffff);
-      OUT_RING(pI830->front_buffer->offset);
-      ADVANCE_LP_RING();
-   }
-}
-#endif
-
 static void
 I830EnablePageFlip(ScreenPtr pScreen)
 {
diff --git a/src/i830_driver.c b/src/i830_driver.c
index ada334b..30558ac 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1297,17 +1297,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    I830SetupOutputs(pScrn);
 
    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 < xf86_config->num_output; i++) 
-   {
-      xf86OutputPtr	      output = xf86_config->output[i];
-
-      output->status = (*output->funcs->detect) (output);
-   }
-
    if (!xf86InitialConfiguration (pScrn, FALSE))
    {
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
@@ -1414,13 +1403,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       pI830->SWCursor = TRUE;
    }
 
-   if (!xf86RandR12PreInit (pScrn))
-   {
-      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "RandR initialization failure\n");
-      PreInitCleanup(pScrn);
-      return FALSE;
-   }	
-
    if (pScrn->modes == NULL) {
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n");
       PreInitCleanup(pScrn);
@@ -1467,7 +1449,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 
       memset(&req, 0, sizeof(req));
       req.majorversion = 2;
-      req.minorversion = 0;
+      req.minorversion = 1;
       if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL, &req,
 		&errmaj, &errmin)) {
 	 LoaderErrorMsg(NULL, "exa", errmaj, errmin);
@@ -1511,29 +1493,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    }
 #endif
 
-   /* rotation requires the newer libshadow */
-   if (I830IsPrimary(pScrn)) {
-      int errmaj, errmin;
-      pI830->shadowReq.majorversion = 1;
-      pI830->shadowReq.minorversion = 1;
-
-      if (!LoadSubModule(pScrn->module, "shadow", NULL, NULL, NULL,
-			       &pI830->shadowReq, &errmaj, &errmin)) {
-         pI830->shadowReq.minorversion = 0;
-         if (!LoadSubModule(pScrn->module, "shadow", NULL, NULL, NULL,
-			       &pI830->shadowReq, &errmaj, &errmin)) {
-            LoaderErrorMsg(NULL, "shadow", errmaj, errmin);
-	    return FALSE;
-         }
-      }
-   } else {
-      I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
-      pI830->shadowReq.majorversion = pI8301->shadowReq.majorversion;
-      pI830->shadowReq.minorversion = pI8301->shadowReq.minorversion;
-      pI830->shadowReq.patchlevel = pI8301->shadowReq.patchlevel;
-   }
-   xf86LoaderReqSymLists(I810shadowSymbols, NULL);
-
    pI830->preinit = FALSE;
 
    return TRUE;
@@ -1942,22 +1901,6 @@ I830PointerMoved(int index, int x, int y
 }
 
 static Bool
-I830CreateScreenResources (ScreenPtr pScreen)
-{
-   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-   I830Ptr pI830 = I830PTR(pScrn);
-
-   pScreen->CreateScreenResources = pI830->CreateScreenResources;
-   if (!(*pScreen->CreateScreenResources)(pScreen))
-      return FALSE;
-
-   if (!xf86RandR12CreateScreenResources (pScreen))
-      return FALSE;
-
-   return TRUE;
-}
-
-static Bool
 I830InitFBManager(
     ScreenPtr pScreen,  
     BoxPtr FullBox
@@ -2685,38 +2628,12 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    pI830->CloseScreen = pScreen->CloseScreen;
    pScreen->CloseScreen = I830CloseScreen;
 
-   if (pI830->shadowReq.minorversion >= 1) {
-      /* Rotation */
-      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RandR enabled, ignore the following RandR disabled message.\n");
-      xf86DisableRandR(); /* Disable built-in RandR extension */
-      shadowSetup(pScreen);
-      /* support all rotations */
-      xf86RandR12Init (pScreen);
-      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;
-      pScreen->CreateScreenResources = I830CreateScreenResources;
-   } else {
-      /* Rotation */
-      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "libshadow is version %d.%d.%d, required 1.1.0 or greater for rotation.\n",pI830->shadowReq.majorversion,pI830->shadowReq.minorversion,pI830->shadowReq.patchlevel);
-   }
+   if (!xf86CrtcScreenInit (pScreen))
+       return FALSE;
+       
+   /* Wrap pointer motion to flip touch screen around */
+   pI830->PointerMoved = pScrn->PointerMoved;
+   pScrn->PointerMoved = I830PointerMoved;
 
    if (serverGeneration == 1)
       xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
diff-tree 04f50961e2f1610c39e7e4b45811f2a6b517cad6 (from b07dfbba5df7728232b38211c623185116dcea5c)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Mar 6 14:23:06 2007 -0800

    Bug #9898: Fix a crash with NoAccel set.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index bc6e07c..ada334b 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -537,8 +537,10 @@ I830MapMem(ScrnInfoPtr pScrn)
    if (!pI830->FbBase)
       return FALSE;
 
-   if (I830IsPrimary(pScrn))
-   pI830->LpRing->virtual_start = pI830->FbBase + pI830->LpRing->mem->offset;
+   if (I830IsPrimary(pScrn) && pI830->LpRing->mem != NULL) {
+      pI830->LpRing->virtual_start =
+	 pI830->FbBase + pI830->LpRing->mem->offset;
+   }
 
    return TRUE;
 }
diff-tree b07dfbba5df7728232b38211c623185116dcea5c (from 94c37f35872487c04136fb659526bffefd9c46ad)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Mar 6 13:59:14 2007 -0800

    Remove leftover code that was disabling tiling after we set it up.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 1aa06b9..bc6e07c 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1913,18 +1913,6 @@ RestoreHWState(ScrnInfoPtr pScrn)
 }
 
 static void
-InitRegisterRec(ScrnInfoPtr pScrn)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   int i;
-
-   if (!I830IsPrimary(pScrn)) return;
-
-   for (i = 0; i < 8; i++)
-      pI830->fence[i] = 0;
-}
-
-static void
 I830PointerMoved(int index, int x, int y)
 {
    ScrnInfoPtr pScrn = xf86Screens[index];
@@ -2505,8 +2493,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    }
 #endif
 
-   InitRegisterRec(pScrn);
-
 #ifdef XF86DRI
    /*
     * pI830->directRenderingDisabled is set once in PreInit.  Reinitialise
diff-tree 94c37f35872487c04136fb659526bffefd9c46ad (from 30bb719ca0abc2599ffb89e59f297fa9a0a00c3c)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Mar 6 13:57:04 2007 -0800

    Make the depth buffer X tiled instead of Y, and fix a Y tiling nit on 945.
    
    The previous code claimed to set the depth buffer up as Y tiled, but due to
    lack of implementation in SetFence, it ended up being X tiled.  Actually
    setting the Y tiling flag in the new version broke the depth buffer, so just
    switch the depth buffer to X tiling, which appears to work fine.

diff --git a/src/i830_memory.c b/src/i830_memory.c
index ea6b90d..f0b50aa 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -1121,8 +1121,8 @@ i830_allocate_depthbuffer(ScrnInfoPtr pS
 	pI830->depth_buffer =
 	    i830_allocate_memory_tiled(pScrn, "depth buffer", size, pitch,
 				       GTT_PAGE_SIZE, ALIGN_BOTH_ENDS,
-				       TILING_YMAJOR);
-	pI830->depth_tiled = FENCE_YMAJOR;
+				       TILING_XMAJOR);
+	pI830->depth_tiled = FENCE_XMAJOR;
     }
 
     /* Otherwise, allocate it linear. */
@@ -1369,7 +1369,9 @@ i830_set_fence(ScrnInfoPtr pScrn, int nr
    	}
     }
 
-    if (IS_I9XX(pI830))
+    if ((IS_I945G(pI830) || IS_I945GM(pI830)) && tile_format == TILING_YMAJOR)
+	fence_pitch = pitch / 128;
+    else if (IS_I9XX(pI830))
 	fence_pitch = pitch / 512;
     else
 	fence_pitch = pitch / 128;
diff-tree a4e7e814a24dbe30a33e6ad45baeb41d190a2724 (from parents)
Merge: 862088ba6a91d3e7cf8d37126b1d9f4ee03a1f73 4042b27f01fdb94e7fc0d4e991e054fff88479ea
Author: Nian Wu <nian.wu at intel.com>
Date:   Tue Mar 6 16:01:40 2007 -0500

    Merge git://proxy01.pd.intel.com:9419/git/xorg/driver/xf86-video-intel into crestline

diff-tree 30bb719ca0abc2599ffb89e59f297fa9a0a00c3c (from 1e1b45fa6ed1683cba4ae73ac98933e74c3ab9d6)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Mar 6 12:23:43 2007 -0800

    Continue to allocate the legacy texture pool by default.
    
    This is a partial revert of 7358642e64ab6d13bc1dc1a44703ee66d715ff61
    
    If we don't allocate it now, when the DRM version is too low there won't be any
    memory allocated and DRI will fail.  Instead, waste the memory in the i915tex
    case for now, and leave fixing it right (check DRM version up front and decide
    which memory manager to set up) to later.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index a27d805..1aa06b9 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1234,14 +1234,13 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       pI830->mmModeFlags = 0;
 
       if (!pI830->directRenderingDisabled) {
+	 pI830->mmModeFlags = I830_KERNEL_TEX;
 #ifdef XF86DRI_MM
 	 Bool tmp = FALSE;
 
 	 if (!IS_I965G(pI830))
 	    pI830->mmModeFlags |= I830_KERNEL_MM;
-	 else
 #endif
-	    pI830->mmModeFlags |= I830_KERNEL_TEX;
 
 	 from = X_PROBED;
 
diff-tree e972265261c421268e4fb806e587378d0adec577 (from 3c08bc7d6974a1a6cf5f9cb81898617032966c52)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Tue Mar 6 16:54:16 2007 +0100

    Fix build failure.
    
    Not sure how I missed this before... Thanks to Todd Merrill for reporting.

diff --git a/src/i830_dri.c b/src/i830_dri.c
index bb9de1e..9931acc 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -756,8 +756,9 @@ I830DRIMapScreenRegions(ScrnInfoPtr pScr
 	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		    "[drm] drmAddMap(third_handle) failed. Triple buffering "
 		    "inactive\n");
-	 i830_free_memory(pI830->third_buffer);
-	 sarea->third_handle = pI830->third_buffer = NULL;
+	 i830_free_memory(pScrn, pI830->third_buffer);
+	 pI830->third_buffer = NULL;
+	 sarea->third_handle = 0;
       } else
 	 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Third Buffer = 0x%08x\n",
 		    (int)sarea->third_handle);
diff-tree 862088ba6a91d3e7cf8d37126b1d9f4ee03a1f73 (from parents)
Merge: 11e91586169b4f4bf2b41c0e0e620a69670c2f07 d717d9d566fe3c0866b06840114e1c1990bd7be0
Author: Nian Wu <nian.wu at intel.com>
Date:   Tue Mar 6 07:43:16 2007 -0500

    Merge git://proxy01.pd.intel.com:9419/git/xorg/driver/xf86-video-intel into crestline

diff-tree 1e1b45fa6ed1683cba4ae73ac98933e74c3ab9d6 (from 4042b27f01fdb94e7fc0d4e991e054fff88479ea)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Tue Mar 6 10:28:41 2007 +0100

    Fix reduced DRI memory manager size.
    
    pI830->mmSize is in kB.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 0977511..a27d805 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2346,7 +2346,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 	    /* For this allocation, switch to a smaller DRI memory manager
 	     * size.
 	     */
-	    pI830->mmSize = I830_MM_MINPAGES * GTT_PAGE_SIZE;
+	    pI830->mmSize = I830_MM_MINPAGES * GTT_PAGE_SIZE / KB(1);
 	 } else {
 	    pI830->mmSize = savedMMSize;
 	 }
diff-tree 3c08bc7d6974a1a6cf5f9cb81898617032966c52 (from c25cfafbe1eb380b58b5fc16e94f5cc6f422f0cd)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Tue Mar 6 10:14:47 2007 +0100

    Fix some conditionals related to triple buffering.
    
    Guard code that dereferences pI830->third_buffer with tests for that instead of
    pI830->TripleBuffer. It could happen that we want to enable triple buffering
    but (temporarily) can't because the third buffer couldn't be allocated.

diff --git a/src/i830_dri.c b/src/i830_dri.c
index d69ab3f..bb9de1e 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -748,18 +748,19 @@ I830DRIMapScreenRegions(ScrnInfoPtr pScr
    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Back Buffer = 0x%08x\n",
               (int)sarea->back_handle);
 
-   if (pI830->TripleBuffer) {
+   if (pI830->third_buffer) {
       if (drmAddMap(pI830->drmSubFD,
 		    (drm_handle_t)(sarea->third_offset + pI830->LinearAddr),
 		    sarea->third_size, DRM_AGP, 0,
 		    (drmAddress) &sarea->third_handle) < 0) {
-	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		   "[drm] drmAddMap(third_handle) failed. Disabling DRI\n");
-	DRICloseScreen(pScreen);
-	return FALSE;
-      }
-      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Third Buffer = 0x%08x\n",
-		 (int)sarea->third_handle);
+	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		    "[drm] drmAddMap(third_handle) failed. Triple buffering "
+		    "inactive\n");
+	 i830_free_memory(pI830->third_buffer);
+	 sarea->third_handle = pI830->third_buffer = NULL;
+      } else
+	 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Third Buffer = 0x%08x\n",
+		    (int)sarea->third_handle);
    }
 
    if (drmAddMap(pI830->drmSubFD,
@@ -1103,7 +1104,7 @@ I830DRIRefreshArea (ScrnInfoPtr pScrn, i
 
    I830DRIDoRefreshArea(pScrn, num, pbox, pI830->back_buffer->offset);
 
-   if (pI830->TripleBuffer) {
+   if (pI830->third_buffer) {
       I830DRIDoRefreshArea(pScrn, num, pbox, pI830->third_buffer->offset);
    }
 
@@ -1207,7 +1208,7 @@ I830DRIInitBuffers(WindowPtr pWin, Regio
       I830SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1,
 				  pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
 
-      if (I830PTR(pScrn)->TripleBuffer) {
+      if (I830PTR(pScrn)->third_buffer) {
 	 I830SelectBuffer(pScrn, I830_SELECT_THIRD);
 	 I830SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1,
 				     pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
@@ -1386,7 +1387,7 @@ I830DRIMoveBuffers(WindowPtr pParent, DD
 
       I830SelectBuffer(pScrn, I830_SELECT_BACK);
       I830SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h);
-      if (pI830->TripleBuffer) {
+      if (pI830->third_buffer) {
 	 I830SelectBuffer(pScrn, I830_SELECT_THIRD);
 	 I830SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h);
       }
@@ -1582,8 +1583,13 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, 
    sarea->height = pScreen->height;
    sarea->back_offset = pI830->back_buffer->offset;
    sarea->back_size = pI830->back_buffer->size;
-   sarea->third_offset = pI830->third_buffer->offset;
-   sarea->third_size = pI830->third_buffer->size;
+   if (pI830->third_buffer != NULL) {
+      sarea->third_offset = pI830->third_buffer->offset;
+      sarea->third_size = pI830->third_buffer->size;
+   } else {
+      sarea->third_offset = 0;
+      sarea->third_size = 0;
+   }
    sarea->depth_offset = pI830->depth_buffer->offset;
    sarea->depth_size = pI830->depth_buffer->size;
    if (pI830->textures != NULL) {
diff-tree c25cfafbe1eb380b58b5fc16e94f5cc6f422f0cd (from e787d7b698d320a7c45df35d58c5113413561fe2)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Tue Mar 6 10:00:12 2007 +0100

    Unify allocation of back buffers.

diff --git a/src/i830_memory.c b/src/i830_memory.c
index 17cad73..54cd6be 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -1064,7 +1064,8 @@ myLog2(unsigned int n)
 }
 
 static Bool
-i830_allocate_backbuffer(ScrnInfoPtr pScrn)
+i830_allocate_backbuffer(ScrnInfoPtr pScrn, i830_memory **buffer,
+			 unsigned int *tiled, const char *name)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     unsigned int pitch = pScrn->displayWidth * pI830->cpp;
@@ -1080,69 +1081,23 @@ i830_allocate_backbuffer(ScrnInfoPtr pSc
     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,
-				       ALIGN_BOTH_ENDS,
-				       TILING_XMAJOR);
-	pI830->back_tiled = FENCE_XMAJOR;
+	*buffer = i830_allocate_memory_tiled(pScrn, name, size, pitch,
+					     GTT_PAGE_SIZE, ALIGN_BOTH_ENDS,
+					     TILING_XMAJOR);
+	*tiled = FENCE_XMAJOR;
     }
 
     /* Otherwise, just allocate it linear */
-    if (pI830->back_buffer == NULL) {
+    if (*buffer == NULL) {
 	size = ROUND_TO_PAGE(pitch * height);
-	pI830->back_buffer = i830_allocate_memory(pScrn, "back buffer",
-						  size, GTT_PAGE_SIZE,
-						  ALIGN_BOTH_ENDS);
-	pI830->back_tiled = FENCE_LINEAR;
+	*buffer = i830_allocate_memory(pScrn, name, size, GTT_PAGE_SIZE,
+				       ALIGN_BOTH_ENDS);
+	*tiled = FENCE_LINEAR;
     }
 
-    if (pI830->back_buffer == NULL) {
+    if (*buffer == NULL) {
 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		   "Failed to allocate back buffer space.\n");
-	return FALSE;
-    }
-
-    return TRUE;
-}
-
-static Bool
-i830_allocate_thirdbuffer(ScrnInfoPtr pScrn)
-{
-    I830Ptr pI830 = I830PTR(pScrn);
-    unsigned int pitch = pScrn->displayWidth * pI830->cpp;
-    unsigned long size;
-    int height;
-
-    if (pI830->rotation & (RR_Rotate_0 | RR_Rotate_180))
-	height = pScrn->virtualY;
-    else
-	height = pScrn->virtualX;
-
-    /* Try to allocate on the best tile-friendly boundaries. */
-    if (!pI830->disableTiling && IsTileable(pScrn, pitch))
-    {
-	size = ROUND_TO_PAGE(pitch * ALIGN(height, 16));
-	pI830->third_buffer =
-	    i830_allocate_memory_tiled(pScrn, "third buffer",
-				       size, pitch, GTT_PAGE_SIZE,
-				       ALIGN_BOTH_ENDS,
-				       TILING_XMAJOR);
-	pI830->third_tiled = FENCE_XMAJOR;
-    }
-
-    /* Otherwise, just allocate it linear */
-    if (pI830->third_buffer == NULL) {
-	size = ROUND_TO_PAGE(pitch * height);
-	pI830->third_buffer = i830_allocate_memory(pScrn, "third buffer",
-						   size, GTT_PAGE_SIZE,
-						   ALIGN_BOTH_ENDS);
-	pI830->third_tiled = FENCE_LINEAR;
-    }
-
-    if (pI830->third_buffer == NULL) {
-	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		   "Failed to allocate third buffer space.\n");
+		   "Failed to allocate %s space.\n", name);
 	return FALSE;
     }
 
@@ -1246,10 +1201,14 @@ i830_allocate_3d_memory(ScrnInfoPtr pScr
 
     DPRINTF(PFX, "i830_allocate_3d_memory\n");
 
-    if (!i830_allocate_backbuffer(pScrn))
+    if (!i830_allocate_backbuffer(pScrn, &pI830->back_buffer,
+				  &pI830->back_tiled, "back buffer"))
 	return FALSE;
 
-    if (pI830->TripleBuffer && !i830_allocate_thirdbuffer(pScrn)) {
+    if (pI830->TripleBuffer && !i830_allocate_backbuffer(pScrn,
+							 &pI830->third_buffer,
+							 &pI830->third_tiled,
+							 "third buffer")) {
        xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		  "Failed to allocate third buffer, triple buffering "
 		  "inactive\n");
diff-tree e787d7b698d320a7c45df35d58c5113413561fe2 (from 6c299aea8e87e72c68c96c03594706c976601ede)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Tue Mar 6 09:35:42 2007 +0100

    Remove warnings about potential artifacts with page flipping and mixed 2D/3D.
    
    The artifacts only seemed to occur when EXA was falling back to software for
    the front buffer.

diff --git a/man/intel.man b/man/intel.man
index 05a91f7..32aa7c1 100644
--- a/man/intel.man
+++ b/man/intel.man
@@ -161,9 +161,9 @@ Default: 32768.
 .TP
 .BI "Option \*qPageFlip\*q \*q" boolean \*q
 Enable support for page flipping. This should improve 3D performance at the
-potential cost of worse performance or artifacts with mixed 2D/3D. Also note
-that this gives no benefit without corresponding support in the Mesa 3D driver
-and may not give the full benefit without triple buffering (see
+potential cost of worse performance with mixed 2D/3D. Also note that this gives
+no benefit without corresponding support in the Mesa 3D driver and may not give
+the full benefit without triple buffering (see
 .B "Option \*qTripleBuffer\*q"
 ).
 Default for i810: The option is not used.
diff-tree 6c299aea8e87e72c68c96c03594706c976601ede (from parents)
Merge: 330815251dee808754b328cd2fd60db39f2460eb 4042b27f01fdb94e7fc0d4e991e054fff88479ea
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Tue Mar 6 09:28:52 2007 +0100

    Merge remote branch 'origin/master' into i830-pageflip
    
    Conflicts:
    
    	src/i830_display.c
    	src/i830_driver.c

diff --cc src/i830_driver.c
index 8379b6b,0977511..0de4d0d
@@@ -272,9 -272,10 +272,11 @@@
     OPTION_COLOR_KEY,
     OPTION_CHECKDEVICES,
     OPTION_LINEARALLOC,
+ #ifdef XF86DRI_MM
     OPTION_INTELTEXPOOL,
 -   OPTION_INTELMMSIZE
 +   OPTION_INTELMMSIZE,
+ #endif
 +   OPTION_TRIPLEBUFFER,
  } I830Opts;
  
  static OptionInfoRec I830Options[] = {
@@@ -291,9 -292,10 +293,11 @@@
     {OPTION_VIDEO_KEY,	"VideoKey",	OPTV_INTEGER,	{0},	FALSE},
     {OPTION_CHECKDEVICES, "CheckDevices",OPTV_BOOLEAN,	{0},	FALSE},
     {OPTION_LINEARALLOC, "LinearAlloc",  OPTV_INTEGER,   {0},    FALSE},
+ #ifdef XF86DRI_MM
     {OPTION_INTELTEXPOOL,"Legacy3D",     OPTV_BOOLEAN,	{0},	FALSE},
     {OPTION_INTELMMSIZE, "AperTexSize",  OPTV_INTEGER,	{0},	FALSE},
+ #endif
 +   {OPTION_TRIPLEBUFFER, "TripleBuffer", OPTV_BOOLEAN,	{0},	FALSE},
     {-1,			NULL,		OPTV_NONE,	{0},	FALSE}
  };
  /* *INDENT-ON* */
diff-tree 4042b27f01fdb94e7fc0d4e991e054fff88479ea (from 55ee46aebbf1ec1a8ce914fbd0c8894fc857db8f)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Mon Mar 5 22:32:52 2007 -0800

    Move EnterVT mode setting code to xf86SetDesiredModes.
    
    Make the application of crtc desiredModes generic code instead of
    per-driver by creating xf86SetDesiredModes from the code that was in EnterVT
    and calling it.
    
    Also, move the frame buffer clear until just before mode setting to make
    sure things are mapped correctly.

diff --git a/src/i830.h b/src/i830.h
index 08d9e3e..dfa94d8 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -255,8 +255,6 @@ typedef struct _I830Rec {
    unsigned char *FbBase;
    int cpp;
 
-   DisplayModePtr currentMode;
-
    I830EntPtr entityPrivate;	
    int init;
 
diff --git a/src/i830_display.h b/src/i830_display.h
index 31ab615..07dfe93 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -28,9 +28,6 @@
 #include "xorgVersion.h"
 
 /* i830_display.c */
-DisplayModePtr
-i830PipeFindClosestMode(xf86CrtcPtr crtc, 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);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 7ab2cdc..0977511 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2885,9 +2885,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;
 
    DPRINTF(PFX, "Enter VT\n");
 
@@ -2902,12 +2900,6 @@ I830EnterVT(int scrnIndex, int flags)
 
    pI830->leaving = FALSE;
 
-#if 1
-   /* Clear the framebuffer */
-   memset(pI830->FbBase + pScrn->fbOffset, 0,
-	  pScrn->virtualY * pScrn->displayWidth * pI830->cpp);
-#endif
-
    if (I830IsPrimary(pScrn))
       if (!i830_bind_all_memory(pScrn))
          return FALSE;
@@ -2920,27 +2912,13 @@ I830EnterVT(int scrnIndex, int flags)
    ResetState(pScrn, FALSE);
    SetHWOperatingState(pScrn);
 
-   for (i = 0; i < xf86_config->num_crtc; i++)
-   {
-      xf86CrtcPtr	crtc = xf86_config->crtc[i];
-
-      /* Mark that we'll need to re-set the mode for sure */
-      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,
-			    crtc->desiredX, crtc->desiredY))
-	 return FALSE;
-   }
-
-   xf86DisableUnusedFunctions(pScrn);
+   /* Clear the framebuffer */
+   memset(pI830->FbBase + pScrn->fbOffset, 0,
+	  pScrn->virtualY * pScrn->displayWidth * pI830->cpp);
 
+   if (!xf86SetDesiredModes (pScrn))
+      return FALSE;
+   
    i830DumpRegs (pScrn);
    i830DescribeOutputConfiguration(pScrn);
 
@@ -3003,8 +2981,6 @@ I830EnterVT(int scrnIndex, int flags)
    if (pI830->checkDevices)
       pI830->devicesTimer = TimerSet(NULL, 0, 1000, I830CheckDevicesTimer, pScrn);
 
-   pI830->currentMode = pScrn->currentMode;
-
    /* Force invarient 3D state to be emitted */
    *pI830->used3D = 1<<31;
 
@@ -3014,17 +2990,10 @@ I830EnterVT(int scrnIndex, int flags)
 static Bool
 I830SwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
 {
-
    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
    I830Ptr pI830 = I830PTR(pScrn);
-   Bool ret = TRUE;
-
-   DPRINTF(PFX, "I830SwitchMode: mode == %p\n", mode);
-
-   if (!i830SetMode(pScrn, mode, pI830->rotation))
-      pI830->currentMode = mode;
 
-   return ret;
+   return xf86SetSingleMode (pScrn, mode, pI830->rotation);
 }
 
 static Bool
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 7bcf48e..ea6b90d 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -835,6 +835,8 @@ i830_allocate_framebuffer(ScrnInfoPtr pS
 	return NULL;
     }
 
+    if (pI830->FbBase)
+	memset (pI830->FbBase + front_buffer->offset, 0, size);
     return front_buffer;
 }
 
diff-tree 55ee46aebbf1ec1a8ce914fbd0c8894fc857db8f (from parents)
Merge: 5c720147e2b86ca4046b7c3812c1ca6b0fb78c9d 50aa09425f54c4eeca7f8b0fae9579209b10b9c4
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Tue Mar 6 12:45:08 2007 +0800

    Merge branch 'master' of git://proxy.ims.intel.com:9419/git/xorg/driver/xf86-video-intel

diff-tree 5c720147e2b86ca4046b7c3812c1ca6b0fb78c9d (from d717d9d566fe3c0866b06840114e1c1990bd7be0)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Tue Mar 6 12:44:04 2007 +0800

    EXA: try to always alloc exa i965 state buffer in stolen mem
    
    I think this is a safe way to work around any possible chip
    error.

diff --git a/src/i830_memory.c b/src/i830_memory.c
index 5cddf17..7bcf48e 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -936,6 +936,20 @@ i830_allocate_2d_memory(ScrnInfoPtr pScr
 		   "Failed to allocate logical context space.\n");
 	return FALSE;
     }
+#ifdef I830_USE_EXA
+    if (pI830->useEXA) {
+	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, 0);
+	    if (pI830->exa_965_state == NULL) {
+		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+			   "Failed to allocate exa state buffer for 965.\n");
+		return FALSE;
+	    }
+	}
+    }
+#endif
 
 #ifdef I830_XV
     /* Allocate overlay register space and optional XAA linear allocator
@@ -982,17 +996,6 @@ i830_allocate_2d_memory(ScrnInfoPtr pScr
 		return FALSE;
 	    }
 	}
-
-	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, 0);
-	    if (pI830->exa_965_state == NULL) {
-		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-			   "Failed to allocate exa state buffer for 965.\n");
-		return FALSE;
-	    }
-	}
     }
 #endif /* I830_USE_EXA */
 
diff-tree 11e91586169b4f4bf2b41c0e0e620a69670c2f07 (from parents)
Merge: a24962af9ed39fabca0152cae1265a29fe6237d3 015027034e970f1e3bb6ab239f7e0119235e404f
Author: Nian Wu <nian.wu at intel.com>
Date:   Mon Mar 5 16:00:20 2007 -0500

    Merge git://proxy01.pd.intel.com:9419/git/xorg/driver/xf86-video-intel into crestline

diff-tree a24962af9ed39fabca0152cae1265a29fe6237d3 (from parents)
Merge: 35e9310ef59873877422dcaf9a65b38789fc8ad6 8bb677889d3f71cde671f17a3589939acad2c3b3
Author: Nian Wu <nian.wu at intel.com>
Date:   Mon Mar 5 16:00:11 2007 -0500

    Merge branch 'crestline' of git://otc-graphics.jf.intel.com/git/xorg/driver/xf86-video-intel into crestline

diff-tree 50aa09425f54c4eeca7f8b0fae9579209b10b9c4 (from parents)
Merge: d717d9d566fe3c0866b06840114e1c1990bd7be0 c2c62559e702e7de1fa2ef309fa647ab13564dc3
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Mon Mar 5 11:28:46 2007 -0800

    Merge branch 'modesetting'

diff-tree c2c62559e702e7de1fa2ef309fa647ab13564dc3 (from af565872a49a1a464ee4154c27136660b184c4c1)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Sat Mar 3 23:12:54 2007 -0800

    Move single mode setting code to X server.
    
    Code to drive the global configuration from a single mode setting operation
    (from RandR 1.1, XFree86-VidModeExtension or XFree86-DGA) has been included
    in the X server now, so remove it from this driver.

diff --git a/src/i830_display.c b/src/i830_display.c
index d0b21a9..e9c997a 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -393,107 +393,6 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x,
 }
 
 /**
- * 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
- * - Closer in size to the requested mode, but no larger
- * - Closer in refresh rate to the requested mode.
- */
-DisplayModePtr
-i830PipeFindClosestMode(xf86CrtcPtr crtc, DisplayModePtr pMode)
-{
-    ScrnInfoPtr	pScrn = crtc->scrn;
-    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 < xf86_config->num_output; i++) 
-    {
-	xf86OutputPtr  output = xf86_config->output[i];
-	if (output->crtc == crtc && output->probed_modes != NULL)
-	{
-	    pScan = output->probed_modes;
-	    break;
-	}
-    }
-
-    /* If the pipe doesn't have any detected modes, just let the system try to
-     * 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", intel_crtc->pipe);
-	return pMode;
-    }
-
-    for (; pScan != NULL; pScan = pScan->next) {
-	assert(pScan->VRefresh != 0.0);
-
-	/* If there's an exact match, we're done. */
-	if (xf86ModesEqual(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 (!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,
-		   pBest->HDisplay, pBest->VDisplay, pBest->VRefresh,
-		   pMode->HDisplay, pMode->VDisplay, pMode->VRefresh);
-	pMode = pBest;
-    }
-    return pMode;
-}
-
-/**
  * Sets the power management mode of the pipe and plane.
  *
  * This code should probably grow support for turning the cursor off and back
@@ -1140,46 +1039,6 @@ i830_crtc_shadow_destroy(xf86CrtcPtr crt
 }
 
 
-/**
- * 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, Rotation rotation)
-{
-    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
-    Bool ok = TRUE;
-    xf86CrtcPtr crtc = config->output[config->compat_output]->crtc;
-
-    DPRINTF(PFX, "i830SetMode\n");
-
-    if (crtc && crtc->enabled)
-    {
-	ok = xf86CrtcSetMode(crtc,
-			     i830PipeFindClosestMode(crtc, pMode),
-			     rotation, 0, 0);
-	if (!ok)
-	    goto done;
-	crtc->desiredMode = *pMode;
-    }
-
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Mode bandwidth is %d Mpixel/s\n",
-	       (int)(pMode->HDisplay * pMode->VDisplay *
-		     pMode->VRefresh / 1000000));
-
-    xf86DisableUnusedFunctions(pScrn);
-
-    i830DescribeOutputConfiguration(pScrn);
-
-#ifdef XF86DRI
-   I830DRISetVBlankInterrupt (pScrn, TRUE);
-#endif
-done:
-    i830DumpRegs (pScrn);
-    i830_sdvo_dump(pScrn);
-    return ok;
-}
-
 void
 i830DescribeOutputConfiguration(ScrnInfoPtr pScrn)
 {
diff-tree 35e9310ef59873877422dcaf9a65b38789fc8ad6 (from parents)
Merge: c8e6f0bac13e0e407f9771b1bbf126f023c1511b b27fa2c257ccc49c6f29a20a3e672ebaaf58e7aa
Author: Nian Wu <nian.wu at intel.com>
Date:   Mon Mar 5 09:01:55 2007 -0500

    Merge branch 'modesetting' of git://proxy01.pd.intel.com:9419/git/xorg/driver/xf86-video-intel into crestline

diff-tree 8bb677889d3f71cde671f17a3589939acad2c3b3 (from a0c83af3430b6705ab2ecae59085d1c74e890c19)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Mar 5 05:08:51 2007 -0800

    Fix 965GM SDVO by not setting fields in SDVO[BC] which have new meanings.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index b7cf843..ab01028 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -647,16 +647,20 @@ i830_sdvo_mode_set(xf86OutputPtr output,
     }
 
     /* Set the SDVO control regs. */
-    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;
+    if (IS_I965GM(pI830)) {
+	sdvox = SDVO_BORDER_ENABLE;
+    } else {
+	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 |= (9 << 19) | SDVO_BORDER_ENABLE;
     }
-    sdvox |= (9 << 19) | SDVO_BORDER_ENABLE;
     if (intel_crtc->pipe == 1)
 	sdvox |= SDVO_PIPE_B_SELECT;
 
diff-tree 330815251dee808754b328cd2fd60db39f2460eb (from parents)
Merge: 50ba1fff886a7f51b178ac6d3a1ba79a3014b214 015027034e970f1e3bb6ab239f7e0119235e404f
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Mon Mar 5 13:05:20 2007 +0100

    Merge remote branch 'origin/master' into i830-pageflip
    
    Conflicts:
    
    	src/i830.h
    	src/i830_dri.c
    	src/i830_dri.h
    	src/i830_driver.c
    	src/i830_memory.c
    	src/i830_xaa.c

diff --cc src/i830.h
index e26556f,08d9e3e..c704372
@@@ -291,12 -295,13 +298,14 @@@
     CreateScreenResourcesProcPtr    CreateScreenResources;
     int *used3D;
  
-    I830MemRange ContextMem;
+    i830_memory *logical_context;
  #ifdef XF86DRI
-    I830MemRange BackBuffer;
-    I830MemRange ThirdBuffer;
-    I830MemRange DepthBuffer;
-    I830MemRange TexMem;
+    i830_memory *back_buffer;
++   i830_memory *third_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;
diff --cc src/i830_accel.c
index c76c748,49a9c13..045b3b6
@@@ -226,13 -226,10 +226,13 @@@
     switch (buffer) {
  #ifdef XF86DRI
     case I830_SELECT_BACK:
-       pI830->bufferOffset = pI830->BackBuffer.Start;
+       pI830->bufferOffset = pI830->back_buffer->offset;
        break;
 +   case I830_SELECT_THIRD:
-       pI830->bufferOffset = pI830->ThirdBuffer.Start;
++      pI830->bufferOffset = pI830->third_buffer->offset;
 +      break;
     case I830_SELECT_DEPTH:
-       pI830->bufferOffset = pI830->DepthBuffer.Start;
+       pI830->bufferOffset = pI830->depth_buffer->offset;
        break;
  #endif
     default:
diff --cc src/i830_display.c
index 04159e7,d0b21a9..f5a2faa
@@@ -358,34 -387,9 +387,34 @@@
          OUTREG(dspsurf, Start);
  	(void) INREG(dspsurf);
      } else {
- 	OUTREG(dspbase, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
+ 	OUTREG(dspbase, Start + Offset);
  	(void) INREG(dspbase);
      }
 +
 +#ifdef XF86DRI
 +    if (pI830->directRenderingEnabled) {
 +	drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScrn->pScreen);
 +
 +	switch (pipe) {
 +	case 0:
 +	    sPriv->pipeA_x = x;
 +	    sPriv->pipeA_y = y;
 +	    sPriv->pipeA_w = crtc->mode.HDisplay;
 +	    sPriv->pipeA_h = crtc->mode.VDisplay;
 +	    break;
 +	case 1:
 +	    sPriv->pipeB_x = x;
 +	    sPriv->pipeB_y = y;
 +	    sPriv->pipeB_w = crtc->mode.HDisplay;
 +	    sPriv->pipeB_h = crtc->mode.VDisplay;
 +	    break;
 +	default:
 +	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 +		       "Can't update pipe %d in SAREA\n", pipe);
 +	    break;
 +	}
 +    }
 +#endif
  }
  
  /**
diff --cc src/i830_dri.c
index dba1a07,f81251a..d69ab3f
@@@ -1059,61 -1022,6 +1056,61 @@@
     }
  }
  
 +#ifdef DAMAGE
 +/* This should be done *before* XAA syncs,
 + * Otherwise will have to sync again???
 + */
 +static void
 +I830DRIDoRefreshArea (ScrnInfoPtr pScrn, int num, BoxPtr pbox, CARD32 dst)
 +{
 +   I830Ptr pI830 = I830PTR(pScrn);
 +   int i, cmd, br13 = (pScrn->displayWidth * pI830->cpp) | (0xcc << 16);
 +
 +   if (pScrn->bitsPerPixel == 32) {
 +      cmd = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
 +	     XY_SRC_COPY_BLT_WRITE_RGB);
 +      br13 |= 3 << 24;
 +   } else {
 +      cmd = (XY_SRC_COPY_BLT_CMD);
 +      br13 |= 1 << 24;
 +   }
 +
 +   for (i = 0 ; i < num ; i++, pbox++) {
 +      BEGIN_LP_RING(8);
 +      OUT_RING(cmd);
 +      OUT_RING(br13);
 +      OUT_RING((pbox->y1 << 16) | pbox->x1);
 +      OUT_RING((pbox->y2 << 16) | pbox->x2);
 +      OUT_RING(dst);
 +      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();
 +   }
 +}
 +
 +static void
 +I830DRIRefreshArea (ScrnInfoPtr pScrn, int num, BoxPtr pbox)
 +{
 +   I830Ptr pI830 = I830PTR(pScrn);
 +   drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
 +
 +   /* Don't want to do this when no 3d is active and pages are
 +    * right-way-round :
 +    */
 +   if (!pSAREAPriv->pf_active && pSAREAPriv->pf_current_page == 0)
 +      return;
 +
-    I830DRIDoRefreshArea(pScrn, num, pbox, pI830->BackBuffer.Start);
++   I830DRIDoRefreshArea(pScrn, num, pbox, pI830->back_buffer->offset);
 +
 +   if (pI830->TripleBuffer) {
-       I830DRIDoRefreshArea(pScrn, num, pbox, pI830->ThirdBuffer.Start);
++      I830DRIDoRefreshArea(pScrn, num, pbox, pI830->third_buffer->offset);
 +   }
 +
 +   DamageEmpty(pI830->pDamage);
 +}
 +#endif
 +
  static void
  I830DRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
  		   DRIContextType oldContextType, void *oldContext,
@@@ -1582,14 -1458,17 +1580,19 @@@
  
     sarea->width = pScreen->width;
     sarea->height = pScreen->height;
-    sarea->back_offset = pI830->BackBuffer.Start;
-    sarea->back_size = pI830->BackBuffer.Size;
-    sarea->third_offset = pI830->ThirdBuffer.Start;
-    sarea->third_size = pI830->ThirdBuffer.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->third_offset = pI830->third_buffer->offset;
++   sarea->third_size = pI830->third_buffer->size;
+    sarea->depth_offset = pI830->depth_buffer->offset;
+    sarea->depth_size = pI830->depth_buffer->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 --cc src/i830_driver.c
index c950149,ac4e38c..8379b6b
@@@ -854,11 -837,9 +839,8 @@@
     char *s;
     pointer pVBEModule = NULL;
     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;
@@@ -2490,7 -2136,250 +2147,254 @@@
     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 (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
+     * for it, and if there's also enough to allow tiling to be enabled.
+     */
+ 
+    if (!I830CheckDRIAvailable(pScrn)) {
+       pI830->directRenderingDisabled = TRUE;
+       pI830->mmSize = 0;
+    }
+ 
+    if (!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;
+ 	    }
+ 	 }
+       }
+ 
+       /* 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;
+       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;
++	    if (pI830->allowPageFlip)
++	       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
++			  "Couldn't allocate tiled memory, page flipping "
++			  "disabled\n");
+ 	    pI830->allowPageFlip = FALSE;
+ 	 }
+ 
+ 	 if (i & 1) {
+ 	    /* For this allocation, switch to a smaller DRI memory manager
+ 	     * size.
+ 	     */
+ 	    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");
+       pI830->disableTiling = TRUE;
+       pI830->directRenderingDisabled = TRUE;
+    }
+ 
+    pScrn->displayWidth = pScrn->displayWidth;
  
  #ifdef HAS_MTRR_SUPPORT
     {
@@@ -2663,30 -2512,9 +2527,12 @@@
     pI830->directRenderingEnabled = FALSE;
  #endif
  
-    /*
-     * 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;
-    }
- 
  #ifdef XF86DRI
-    if (pI830->directRenderingEnabled) {
-       I830SetupMemoryTiling(pScrn);
+    if (pI830->directRenderingEnabled)
        pI830->directRenderingEnabled = I830DRIDoMappings(pScreen);
-    }
 +
 +   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Page Flipping %sabled\n",
 +	      pI830->allowPageFlip ? "en" : "dis");
  #endif
  
     DPRINTF(PFX, "assert( if(!I830MapMem(pScrn)) )\n");
diff --cc src/i830_memory.c
index a952b70,5cddf17..f5cffba
@@@ -62,259 -107,514 +107,521 @@@
  #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)
  {
-    unsigned long i;
+     I830Ptr pI830 = I830PTR(pScrn);
+     unsigned long i;
+     unsigned long start;
+ 
+     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);
  
-    for (i = KB(512); i < size; i <<= 1)
-       ;
+ 	for (i = start; i < size; i <<= 1)
+ 	    ;
  
-    if (i > MB(64))
-       i = MB(64);
+ 	return i;
+     }
+ }
+ 
+ static Bool
+ i830_bind_memory(ScrnInfoPtr pScrn, i830_memory *mem)
+ {
+     I830Ptr pI830 = I830PTR(pScrn);
+ 
+     if (mem == NULL || mem->key == -1 || mem->bound || !pI830->gtt_acquired)
+ 	return TRUE;
  
-    return i;
+     if (xf86BindGARTMemory(pScrn->scrnIndex, mem->key, mem->agp_offset)) {
+ 	mem->bound = TRUE;
+ 	return TRUE;
+     } else {
+ 	return FALSE;
+     }
+ 
+     return TRUE;
  }
  
- /*
-  * Allocate memory from the given pool.  Grow the pool if needed and if
-  * possible.
+ 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;
+     }
+ }
+ 
+ void
+ i830_free_memory(ScrnInfoPtr pScrn, i830_memory *mem)
+ {
+     if (mem == NULL)
+ 	return;
+ 
+     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.
   */
- static unsigned long
- AllocFromPool(ScrnInfoPtr pScrn, I830MemRange *result, I830MemPool *pool,
- 	      long size, unsigned long alignment, int flags)
+ void
+ i830_reset_allocations(ScrnInfoPtr pScrn)
  {
-    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;
- 
-       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;
+     I830Ptr pI830 = I830PTR(pScrn);
+     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+     int i;
+ 
+     /* 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);
+ 
+     /* 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;
+     }
+ 
+     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->third_buffer = NULL;
+     pI830->depth_buffer = NULL;
+     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));
  }
  
- static unsigned long
- AllocFromAGP(ScrnInfoPtr pScrn, I830MemRange *result, long size,
- 	     unsigned long alignment, int flags)
+ void
+ i830_free_3d_memory(ScrnInfoPtr pScrn)
+ {
+     I830Ptr pI830 = I830PTR(pScrn);
+ 
+     i830_free_memory(pScrn, pI830->back_buffer);
+     pI830->back_buffer = NULL;
++    i830_free_memory(pScrn, pI830->third_buffer);
++    pI830->third_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.
+  */
+ Bool
+ i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset,
+ 		    unsigned long size)
  {
-    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);
+     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;
+     }
+ 
+     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;
+     }
+     /* Only allocate page-sized increments. */
+     size = ALIGN(size, GTT_PAGE_SIZE);
+     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 = 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);
+ 	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;
+ 
+     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 &&
+ 	!(flags & NEED_PHYSICAL_ADDR))
+     {
+ 	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 (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;
+     }
+ 
+     if (!i830_bind_memory(pScrn, mem)) {
+ 	return FALSE;
+     }
+ 
+     return TRUE;
+ }
+ 
+ 
+ /* 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)
+ {
+     i830_memory *mem;
+ 
+     mem = i830_allocate_aperture(pScrn, name, size, alignment, flags);
+     if (mem == NULL)
+ 	return NULL;
+ 
+     if (!i830_allocate_agp_memory(pScrn, mem, flags)) {
+ 	i830_free_memory(pScrn, mem);
+ 	return NULL;
+     }
+ 
+     return mem;
+ }
+ 
+ /* 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 (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))
+ 	    return NULL;
+     } else {
+ 	if (size > MB(64))
+ 	    return NULL;
+     }
  
-    return size;
+     aper_size = i830_get_fence_size(pScrn, size);
+     if (IS_I965G(pI830)) {
+ 	aper_align = GTT_PAGE_SIZE;
+     } else {
+ 	/* 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);
+ 	}
+     }
+ 
+     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 " : "");
  }
  
  void
- I830FreeVidMem(ScrnInfoPtr pScrn, I830MemRange *range)
+ i830_describe_allocations(ScrnInfoPtr pScrn, int verbosity, const char *prefix)
  {
-    I830Ptr pI830 = I830PTR(pScrn);
+     I830Ptr pI830 = I830PTR(pScrn);
+     i830_memory *mem;
  
-    if (!range || range->Size == 0)
-       return;
+     if (pI830->memory_list == NULL) {
+ 	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+ 		       "%sMemory allocator not initialized\n", prefix);
+ 	return;
+     }
+ 
+     if (pI830->memory_list->next->next == NULL) {
+ 	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+ 		       "%sNo memory allocations\n", prefix);
+ 	return;
+     }
  
-    if (range->Key != -1)
-       xf86DeallocateGARTMemory(pScrn->scrnIndex, range->Key);
- 
-    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 += 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);
- 
-    if (!result)
-       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;
-    }
+     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, 0x%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->third_buffer != NULL) {
++	i830_describe_tiling(pScrn, verbosity, prefix, pI830->third_buffer,
++			     pI830->third_tiled);
++    }
+     if (pI830->depth_buffer != NULL) {
+ 	i830_describe_tiling(pScrn, verbosity, prefix, pI830->depth_buffer,
+ 			     pI830->depth_tiled);
+     }
  }
  
  static Bool
@@@ -1045,567 -1042,293 +1049,344 @@@
  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)
+ static Bool
+ i830_allocate_backbuffer(ScrnInfoPtr pScrn)
  {
-    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 int pitch = pScrn->displayWidth * pI830->cpp;
+     unsigned long size;
+     int height;
+ 
+     if (pI830->rotation & (RR_Rotate_0 | RR_Rotate_180))
+ 	height = pScrn->virtualY;
+     else
+ 	height = pScrn->virtualX;
+ 
+     /* Try to allocate on the best tile-friendly boundaries. */
+     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,
+ 				       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,
+ 						  ALIGN_BOTH_ENDS);
+ 	pI830->back_tiled = FENCE_LINEAR;
+     }
  
-    return TRUE;
+     if (pI830->back_buffer == NULL) {
+ 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ 		   "Failed to allocate back buffer space.\n");
+ 	return FALSE;
+     }
+ 
+     return TRUE;
  }
  
- Bool
- I830AllocateThirdBuffer(ScrnInfoPtr pScrn, const int flags)
+ static Bool
++i830_allocate_thirdbuffer(ScrnInfoPtr pScrn)
 +{
-    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;
- 
-    /* Third Buffer */
-    memset(&(pI830->ThirdBuffer), 0, sizeof(pI830->ThirdBuffer));
-    pI830->ThirdBuffer.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->ThirdBuffer),
- 				   &(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->ThirdBuffer),
- 				&(pI830->StolenPool), size, align,
- 				flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
-    }
-    if (alloced < size) {
-       if (!dryrun) {
- 	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- 		    "Failed to allocate third buffer space.\n");
-       }
-       return FALSE;
-    }
-    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
- 		  "%sAllocated %ld kB for the third buffer at 0x%lx.\n", s,
- 		  alloced / 1024, pI830->ThirdBuffer.Start);
++    I830Ptr pI830 = I830PTR(pScrn);
++    unsigned int pitch = pScrn->displayWidth * pI830->cpp;
++    unsigned long size;
++    int height;
++
++    if (pI830->rotation & (RR_Rotate_0 | RR_Rotate_180))
++	height = pScrn->virtualY;
++    else
++	height = pScrn->virtualX;
++
++    /* Try to allocate on the best tile-friendly boundaries. */
++    if (!pI830->disableTiling && IsTileable(pScrn, pitch))
++    {
++	size = ROUND_TO_PAGE(pitch * ALIGN(height, 16));
++	pI830->third_buffer =
++	    i830_allocate_memory_tiled(pScrn, "third buffer",
++				       size, pitch, GTT_PAGE_SIZE,
++				       ALIGN_BOTH_ENDS,
++				       TILING_XMAJOR);
++	pI830->third_tiled = FENCE_XMAJOR;
++    }
++
++    /* Otherwise, just allocate it linear */
++    if (pI830->third_buffer == NULL) {
++	size = ROUND_TO_PAGE(pitch * height);
++	pI830->third_buffer = i830_allocate_memory(pScrn, "third buffer",
++						   size, GTT_PAGE_SIZE,
++						   ALIGN_BOTH_ENDS);
++	pI830->third_tiled = FENCE_LINEAR;
++    }
 +
-    return TRUE;
++    if (pI830->third_buffer == NULL) {
++	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
++		   "Failed to allocate third buffer space.\n");
++	return FALSE;
++    }
++
++    return TRUE;
 +}
 +
- Bool
- I830AllocateDepthBuffer(ScrnInfoPtr pScrn, const int flags)
++static Bool
+ i830_allocate_depthbuffer(ScrnInfoPtr pScrn)
  {
-    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;
+     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;
+ 
+     /* First try allocating it tiled */
+     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, ALIGN_BOTH_ENDS,
+ 				       TILING_YMAJOR);
+ 	pI830->depth_tiled = FENCE_YMAJOR;
+     }
+ 
+     /* 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,
+ 				 0);
+ 	pI830->depth_tiled = FENCE_LINEAR;
+     }
  
-    return TRUE;
+     if (pI830->depth_buffer == NULL) {
+ 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ 		   "Failed to allocate depth buffer space.\n");
+ 	return FALSE;
+     }
+ 
+     return TRUE;
  }
  
- Bool
- I830AllocateTextureMemory(ScrnInfoPtr pScrn, const int flags)
+ static Bool
+ i830_allocate_texture_memory(ScrnInfoPtr pScrn)
  {
-    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) {
+     I830Ptr pI830 = I830PTR(pScrn);
+     unsigned long size;
+     int i;
+ 
+     if (pI830->mmModeFlags & I830_KERNEL_MM) {
+ 	pI830->memory_manager =
+ 	    i830_allocate_aperture(pScrn, "DRI memory manager",
+ 				   pI830->mmSize * KB(1), GTT_PAGE_SIZE,
+ 				   ALIGN_BOTH_ENDS);
+ 	/* XXX: try memory manager size backoff here? */
+ 	if (pI830->memory_manager == NULL)
+ 	    return FALSE;
+     }
+ 
+     if (pI830->mmModeFlags & I830_KERNEL_TEX) {
+ 	/* XXX: auto-sizing */
+ 	size = MB(32);
+ 	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)) {
  	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- 		       "Less than 512 kBytes for texture space (real %ld kBytes).\n", 
+ 		       "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,
+ 	    return FALSE;
+ 	}
+ 	pI830->textures = i830_allocate_memory(pScrn, "textures", size,
+ 					       GTT_PAGE_SIZE, 0);
+ 	if (pI830->textures == NULL) {
+ 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
  		       "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 FALSE;
+ 	}
+     }
  
-    return TRUE;
+     return TRUE;
  }
  
  Bool
- I830Allocate3DMemory(ScrnInfoPtr pScrn, const int flags)
+ i830_allocate_3d_memory(ScrnInfoPtr pScrn)
  {
-    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;
- 
-    if (pI830->TripleBuffer && !I830AllocateThirdBuffer(pScrn, flags))
-       return FALSE;
- 
-    if (!I830AllocateDepthBuffer(pScrn, flags))
-       return FALSE;
++    I830Ptr pI830 = I830PTR(pScrn);
 +
-    if (!I830AllocateTextureMemory(pScrn, flags))
-       return FALSE;
+     DPRINTF(PFX, "i830_allocate_3d_memory\n");
  
-    return TRUE;
- }
- #endif
+     if (!i830_allocate_backbuffer(pScrn))
+ 	return FALSE;
  
- /* Allocate pool space that isn't pre-allocated */
- Bool
- I830DoPoolAllocation(ScrnInfoPtr pScrn, I830MemPool *pool)
- {
-    I830Ptr pI830 = I830PTR(pScrn);
++    if (pI830->TripleBuffer && !i830_allocate_thirdbuffer(pScrn)) {
++       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
++		  "Failed to allocate third buffer, triple buffering "
++		  "inactive\n");
++    }
 +
-    DPRINTF(PFX, "I830DoPoolAllocation\n");
+     if (!i830_allocate_depthbuffer(pScrn))
+ 	return FALSE;
  
-    if (!pool)
-       return FALSE;
+     if (!i830_allocate_texture_memory(pScrn))
+ 	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;
+     return TRUE;
  }
+ #endif
  
- 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.
+ #ifdef XF86DRI
+ /**
+  * Sets up a fence area for the hardware.
   *
+  * The fences control automatic tiled address swizzling for CPU access of the
+  * framebuffer.
   */
- #define PACK_RANGES 0
- #define POOL_RANGES 0
+ static void
+ 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);
+     CARD32 val;
+     CARD32 fence_mask = 0;
+     unsigned int fence_pitch;
  
- Bool
- I830FixOffset(ScrnInfoPtr pScrn, I830MemRange *mem)
- {
- #if POOL_RANGES
-    I830Ptr pI830 = I830PTR(pScrn);
- #endif
+     DPRINTF(PFX, "i830_set_fence(): %d, 0x%08x, %d, %d kByte\n",
+ 	    nr, offset, pitch, size / 1024);
  
-    if (!mem)
-       return FALSE;
+     assert(tile_format != TILING_NONE);
  
-    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;
- }
+     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;
+ 	}
  
- 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->ThirdBuffer));
-       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));
+ 	/* The end marker is the address of the last page in the allocation. */
+ 	pI830->fence[FENCE_NEW_NR + nr] = offset + size - 4096;
+ 	return;
      }
- #endif
-    return TRUE;
- }
  
- #ifdef XF86DRI
- /* Tiled memory is good... really, really good...
-  *
-  * 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'.
-  */
- 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;
-    }
+     if (nr < 0 || nr >= FENCE_NR) {
+ 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ 		   "i830_set_fence(): fence %d out of range\n",nr);
+ 	return;
+     }
  
-    i830Reg->Fence[nr] = 0;
+     pI830->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 (offset & fence_mask) {
+ 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ 		   "i830_set_fence(): %d: offset (0x%08x) is not %s aligned\n",
+ 		   nr, offset, (IS_I9XX(pI830)) ? "1MB" : "512k");
+ 	return;
+     }
+ 
+     if (offset % size) {
+ 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ 		   "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,
+ 		   "i830_set_fence(): %d: pitch (%d) not a multiple of 128 "
+ 		   "bytes\n",
+ 		   nr, pitch);
+ 	return;
+     }
+ 
+     val = offset | FENCE_VALID;
  
-    val = (start | FENCE_X_MAJOR | 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)) {
+     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(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;
+ 	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_ERROR,
+ 		       "i830_set_fence(): %d: illegal size (%d kByte)\n",
+ 		       nr, size / 1024);
+ 	    return;
     	}
      } else {
     	switch (size) {
diff --cc src/i830_xaa.c
index 9b11973,9ecf706..46ea7ec
@@@ -279,13 -279,17 +279,22 @@@
     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->back_buffer != NULL &&
+ 	  pI830->bufferOffset == pI830->back_buffer->offset &&
+ 	  pI830->back_tiled == FENCE_XMAJOR) {
           tiled = 1;
-       if (pI830->bufferOffset == pI830->ThirdBuffer.Start && pI830->third_tiled == FENCE_XMAJOR)
+       }
++      if (pI830->third_buffer != NULL &&
++	  pI830->bufferOffset == pI830->third_buffer->offset &&
++	  pI830->third_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->depth_buffer != NULL &&
+ 	  pI830->bufferOffset == pI830->depth_buffer->offset &&
+ 	  pI830->depth_tiled == FENCE_XMAJOR) {
           tiled = 1;
+       }
     }
  
     return tiled;
diff-tree d717d9d566fe3c0866b06840114e1c1990bd7be0 (from 7358642e64ab6d13bc1dc1a44703ee66d715ff61)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Mon Mar 5 12:57:21 2007 +0100

    Fix DRM memory manager initialization.
    
    It takes the offset and size in pages, not bytes.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 373c636..7ab2cdc 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2764,13 +2764,17 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 	 I830DRICloseScreen(pScreen);
 	 pI830->directRenderingEnabled = FALSE;
       } else {
+	 unsigned long aperEnd = ROUND_DOWN_TO(pI830->memory_manager->offset +
+					       pI830->memory_manager->size,
+					       GTT_PAGE_SIZE) / GTT_PAGE_SIZE;
+	 unsigned long aperStart = ROUND_TO(pI830->memory_manager->offset,
+					    GTT_PAGE_SIZE) / GTT_PAGE_SIZE;
+
 #ifndef XSERVER_LIBDRM_MM
-	 if (I830DrmMMInit(pI830->drmSubFD, pI830->memory_manager->offset,
-			   pI830->memory_manager->size,
+	 if (I830DrmMMInit(pI830->drmSubFD, aperStart, aperEnd - aperStart,
 			   DRM_BO_MEM_TT)) {
 #else
-	 if (drmMMInit(pI830->drmSubFD, pI830->memory_manager->offset,
-		       pI830->memory_manager->size,
+	 if (drmMMInit(pI830->drmSubFD, aperStart, aperEnd - aperStart,
 		       DRM_BO_MEM_TT)) {
 #endif	   
 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 
diff-tree a0c83af3430b6705ab2ecae59085d1c74e890c19 (from parents)
Merge: c0f99b4962553e560a5cb882a5060d95db5477a4 bc20b54c34088356a277beaebcc90bb4a7063e19
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Mar 5 03:37:53 2007 -0800

    Merge branch 'modesetting' into crestline

diff-tree 7358642e64ab6d13bc1dc1a44703ee66d715ff61 (from 015027034e970f1e3bb6ab239f7e0119235e404f)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Mon Mar 5 11:53:09 2007 +0100

    Fix handling of new vs. old texture pools.
    
    Only one of them can be active.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index ac4e38c..373c636 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -272,8 +272,10 @@ typedef enum {
    OPTION_COLOR_KEY,
    OPTION_CHECKDEVICES,
    OPTION_LINEARALLOC,
+#ifdef XF86DRI_MM
    OPTION_INTELTEXPOOL,
    OPTION_INTELMMSIZE
+#endif
 } I830Opts;
 
 static OptionInfoRec I830Options[] = {
@@ -290,8 +292,10 @@ static OptionInfoRec I830Options[] = {
    {OPTION_VIDEO_KEY,	"VideoKey",	OPTV_INTEGER,	{0},	FALSE},
    {OPTION_CHECKDEVICES, "CheckDevices",OPTV_BOOLEAN,	{0},	FALSE},
    {OPTION_LINEARALLOC, "LinearAlloc",  OPTV_INTEGER,   {0},    FALSE},
+#ifdef XF86DRI_MM
    {OPTION_INTELTEXPOOL,"Legacy3D",     OPTV_BOOLEAN,	{0},	FALSE},
    {OPTION_INTELMMSIZE, "AperTexSize",  OPTV_INTEGER,	{0},	FALSE},
+#endif
    {-1,			NULL,		OPTV_NONE,	{0},	FALSE}
 };
 /* *INDENT-ON* */
@@ -1230,30 +1234,38 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       pI830->mmModeFlags = 0;
 
       if (!pI830->directRenderingDisabled) {
+#ifdef XF86DRI_MM
 	 Bool tmp = FALSE;
 
-	 pI830->mmModeFlags |= I830_KERNEL_TEX;
-#ifdef XF86DRI_MM
 	 if (!IS_I965G(pI830))
 	    pI830->mmModeFlags |= I830_KERNEL_MM;
+	 else
 #endif
+	    pI830->mmModeFlags |= I830_KERNEL_TEX;
 
 	 from = X_PROBED;
+
+#ifdef XF86DRI_MM
 	 if (xf86GetOptValBool(pI830->Options, 
 			       OPTION_INTELTEXPOOL, &tmp)) {
 	    from = X_CONFIG;
 	    if (tmp) {
 	       pI830->mmModeFlags |= I830_KERNEL_TEX;
+	       pI830->mmModeFlags &= ~I830_KERNEL_MM;
 	    } else {
 	       pI830->mmModeFlags &= ~I830_KERNEL_TEX;
+	       pI830->mmModeFlags |= I830_KERNEL_MM;
 	    }	       
 	 }
+#endif
+
 	 xf86DrvMsg(pScrn->scrnIndex, from,
 		    "Will %stry to allocate texture pool "
 		    "for old Mesa 3D driver.\n",
 		    (pI830->mmModeFlags & I830_KERNEL_TEX) ?
 		    "" : "not ");
 
+#ifdef XF86DRI_MM
 	 pI830->mmSize = I830_MM_MAXSIZE;
 	 from = X_INFO;
 	 if (xf86GetOptValInteger(pI830->Options, OPTION_INTELMMSIZE,
@@ -1266,6 +1278,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 		    pI830->mmSize);
       }
    } 
+#endif
    
 #endif
 
@@ -2129,8 +2142,10 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    MessageType from;
 #ifdef XF86DRI
    Bool driDisabled;
+#ifdef XF86DRI_MM
    unsigned long savedMMSize;
 #endif
+#endif
 
    pScrn = xf86Screens[pScreen->myNum];
    pI830 = I830PTR(pScrn);
@@ -2257,7 +2272,9 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 
    if (!I830CheckDRIAvailable(pScrn)) {
       pI830->directRenderingDisabled = TRUE;
+#ifdef XF86DRI_MM
       pI830->mmSize = 0;
+#endif
    }
 
    if (!pI830->directRenderingDisabled) {
@@ -2307,18 +2324,24 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
        */
 
       pI830->disableTiling = FALSE;
+#ifdef XF86DRI_MM
       savedMMSize = pI830->mmSize;
-      for (i = 0; i < 4; i++) {
+#define MM_TURNS 4
+#else
+#define MM_TURNS 2
+#endif
+      for (i = 0; i < MM_TURNS; i++) {
 	 if (!tiled && i < 2)
 	    continue;
 
-	 if (i >= 2) {
+	 if (i >= MM_TURNS/2) {
 	    /* For further allocations, disable tiling */
 	    pI830->disableTiling = TRUE;
 	    pScrn->displayWidth = savedDisplayWidth;
 	    pI830->allowPageFlip = FALSE;
 	 }
 
+#ifdef XF86DRI_MM
 	 if (i & 1) {
 	    /* For this allocation, switch to a smaller DRI memory manager
 	     * size.
@@ -2333,6 +2356,11 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 		    "\t       %s DRI memory manager reservation:\n",
 		    (i & 2) ? "untiled" : "tiled",
 		    (i & 1) ? "small" : "large");
+#else
+	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		    "Attempting memory allocation with %s buffers:\n",
+		    (i & 1) ? "untiled" : "tiled");
+#endif
 
 	 if (i830_allocate_2d_memory(pScrn) &&
 	     i830_allocate_3d_memory(pScrn))
@@ -2351,10 +2379,12 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 	 i830_reset_allocations(pScrn);
       }
 
-      if (i == 4) {
+      if (i == MM_TURNS) {
 	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		    "Not enough video memory.  Disabling DRI.\n");
+#ifdef XF86DRI_MM
 	 pI830->mmSize = 0;
+#endif
 	 pI830->directRenderingDisabled = TRUE;
       }
    } else
diff-tree 50ba1fff886a7f51b178ac6d3a1ba79a3014b214 (from 36cad3fcb65e3dcd88e58e301cd60adb121cb96b)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Mon Mar 5 10:22:07 2007 +0100

    Be more verbose when page flipping can't be enabled for various reasons.

diff --git a/src/i830_dri.c b/src/i830_dri.c
index e546066..dba1a07 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1146,7 +1146,7 @@ I830DRISwapContext(ScreenPtr pScreen, DR
 	 if (pI830->pDamage == NULL) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
                        "No screen damage record, page flipping disabled\n");
-            pI830->allowPageFlip = 0;
+            pI830->allowPageFlip = FALSE;
 	 } else {
 	    DamageRegister(&pPix->drawable, pI830->pDamage);
 
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 9bd7029..c950149 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -853,7 +853,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    int i;
    char *s;
    pointer pVBEModule = NULL;
-   Bool enable;
    const char *chipname;
    int num_pipe;
    int max_width, max_height;
@@ -1479,14 +1478,14 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 	      pI830->colorKey);
 #endif
 
-   pI830->allowPageFlip = FALSE;
-   enable = xf86ReturnOptValBool(pI830->Options, OPTION_PAGEFLIP, FALSE);
 #ifdef XF86DRI
-   if (!pI830->directRenderingDisabled) {
-      pI830->allowPageFlip = enable;
-      xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "page flipping %s\n",
-		 enable ? "enabled" : "disabled");
-   }
+   pI830->allowPageFlip = FALSE;
+   from = (!pI830->directRenderingDisabled &&
+	   xf86GetOptValBool(pI830->Options, OPTION_PAGEFLIP,
+			     &pI830->allowPageFlip)) ? X_CONFIG : X_DEFAULT;
+
+   xf86DrvMsg(pScrn->scrnIndex, from, "Will%s try to enable page flipping\n",
+	      pI830->allowPageFlip ? "" : " not");
 #endif
 
 #ifdef XF86DRI
@@ -1676,6 +1675,9 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 			     -pI830->MemoryAperture.Size / 1024);
 	       }
 	       pScrn->displayWidth = savedDisplayWidth;
+	       if (pI830->allowPageFlip)
+		  xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+			     "Can't enable page flipping due to the above\n");
 	       pI830->allowPageFlip = FALSE;
 	    } else if (pScrn->displayWidth != savedDisplayWidth) {
 	       xf86DrvMsg(pScrn->scrnIndex, X_INFO,
@@ -2682,6 +2684,9 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       I830SetupMemoryTiling(pScrn);
       pI830->directRenderingEnabled = I830DRIDoMappings(pScreen);
    }
+
+   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Page Flipping %sabled\n",
+	      pI830->allowPageFlip ? "en" : "dis");
 #endif
 
    DPRINTF(PFX, "assert( if(!I830MapMem(pScrn)) )\n");
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 2d1cca9..a952b70 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -1762,6 +1762,9 @@ I830SetupMemoryTiling(ScrnInfoPtr pScrn)
       xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		 "I830SetupMemoryTiling: Not tileable 0x%x\n",
 		 pScrn->displayWidth * pI830->cpp);
+      if (pI830->allowPageFlip)
+	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		    "Can't enable page flipping due to the above\n");
       pI830->allowPageFlip = FALSE;
       return;
    }
@@ -1778,14 +1781,20 @@ I830SetupMemoryTiling(ScrnInfoPtr pScrn)
 		       "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");
+	    if (pI830->allowPageFlip)
+	       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+			  "Can't enable page flipping due to the above\n");
+	    pI830->allowPageFlip = FALSE;
 	 }
       } else {
-	 pI830->allowPageFlip = FALSE;
 	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		 "Alignment bad for the front buffer\n");
+	 if (pI830->allowPageFlip)
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		       "Can't enable page flipping due to the above\n");
+	 pI830->allowPageFlip = FALSE;
       }
    }
 
@@ -1803,6 +1812,9 @@ I830SetupMemoryTiling(ScrnInfoPtr pScrn)
       } else {
 	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		    "MakeTiles failed for the back buffer.\n");
+	 if (pI830->allowPageFlip)
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		       "Can't enable page flipping due to the above\n");
 	 pI830->allowPageFlip = FALSE;
       }
    }
@@ -1815,6 +1827,9 @@ I830SetupMemoryTiling(ScrnInfoPtr pScrn)
       } else {
 	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		    "MakeTiles failed for the third buffer.\n");
+	 if (pI830->allowPageFlip)
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		       "Can't enable page flipping due to the above\n");
 	 pI830->allowPageFlip = FALSE;
       }
    }
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 af565872a49a1a464ee4154c27136660b184c4c1 (from bc20b54c34088356a277beaebcc90bb4a7063e19)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Sun Mar 4 21:20:33 2007 -0800

    Set version number to 2.0 RC1 (1.9.91).

diff --git a/configure.ac b/configure.ac
index 772b40b..c8b99c7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -22,7 +22,7 @@
 
 AC_PREREQ(2.57)
 AC_INIT([xf86-video-intel],
-        1.9.90,
+        1.9.91,
         [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
         xf86-video-intel)
 
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 c8e6f0bac13e0e407f9771b1bbf126f023c1511b (from parents)
Merge: 0ed5a2fdcfe9674175aa9af155c20695ef41cadc c0f99b4962553e560a5cb882a5060d95db5477a4
Author: Nian Wu <nian.wu at intel.com>
Date:   Sun Mar 4 09:00:12 2007 -0500

    Merge branch 'crestline' of git://otc-graphics.jf.intel.com/git/xorg/driver/xf86-video-intel into crestline

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 c0f99b4962553e560a5cb882a5060d95db5477a4 (from 0fa3d4f51b5ee0dba3882fd74b6ac4e7da708f8f)
Author: Keith Packard <keithp at gamba.jf.intel.com>
Date:   Sat Mar 3 22:36:46 2007 -0800

    LVDS dither control moved from PFIT to LVDS register for Crestline
    
    The LVDS register now contains lots of new controls for dual-channel LVDS control
    along with dither enabling. The PFIT register has a lot fewer controls as a result.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index d63be02..f50646b 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -1131,9 +1131,107 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define LVDS			0x61180
 # define LVDS_PORT_EN			(1 << 31)
 # define LVDS_PIPEB_SELECT		(1 << 30)
+
+/* on 965, dithering is enabled in this register, not PFIT_CONTROL */
+# define LVDS_DITHER_ENABLE		(1 << 25)
+
+/*
+ * Selects between .0 and .1 formats:
+ *
+ * 0 = 1x18.0, 2x18.0, 1x24.0 or 2x24.0
+ * 1 = 1x24.1 or 2x24.1
+ */
+# define LVDS_DATA_FORMAT_DOT_ONE	(1 << 24)
+
+/* Using LE instead of HS on second channel control signal */
+# define LVDS_LE_CONTROL_ENABLE		(1 << 23)
+
+/* Using LF instead of VS on second channel control signal */
+# define LVDS_LF_CONTROL_ENABLE		(1 << 22)
+
+/* invert vsync signal polarity */
+# define LVDS_VSYNC_POLARITY_INVERT	(1 << 21)
+
+/* invert hsync signal polarity */
+# define LVDS_HSYNC_POLARITY_INVERT	(1 << 20)
+
+/* invert display enable signal polarity */
+# define LVDS_DE_POLARITY_INVERT	(1 << 19)
+
+/*
+ * Control signals for second channel, ignored in single channel modes
+ */
+
+/* send DE, HS, VS on second channel */
+# define LVDS_SECOND_CHANNEL_DE_HS_VS	(0 << 17)
+
+# define LVDS_SECOND_CHANNEL_RESERVED	(1 << 17)
+
+/* Send zeros instead of DE, HS, VS on second channel */
+# define LVDS_SECOND_CHANNEL_ZEROS	(2 << 17)
+
+/* Set DE=0, HS=LE, VS=LF on second channel */
+# define LVDS_SECOND_CHANNEL_HS_VS	(3 << 17)
+
+/*
+ * Send duplicate data for channel reserved bits, otherwise send zeros
+ */
+# define LVDS_CHANNEL_DUP_RESERVED	(1 << 16)
+
+/*
+ * Enable border for unscaled (or aspect-scaled) display
+ */
+# define LVDS_BORDER_ENABLE		(1 << 15)
+
+/*
+ * Tri-state the LVDS buffers when powered down, otherwise
+ * they are set to 0V
+ */
+# define LVDS_POWER_DOWN_TRI_STATE	(1 << 10)
+
+/*
+ * Clock A control; overridden by LVDS power sequencing
+ */
+
+/* power down everything including A3 (0V) */
 # define LVDS_CLKA_POWER_DOWN		(0 << 8)
+
+/* Partially active. A0, A1, A2 set to 0, timing active, clock active */
+# define LVDS_CLKA_POWER_PARTIAL	(1 << 8)
+
+/* running, data and clock active */
 # define LVDS_CLKA_POWER_UP		(3 << 8)
 
+/*
+ * Two channel clock control. Turn this on if you need clkb for two channel mode
+ * Overridden by global LVDS power sequencing
+ */
+
+/* clkb off */
+# define LVDS_CLKB_POWER_DOWN		(0 << 4)
+
+/* powered up, but clkb forced to 0 */
+# define LVDS_CLKB_POWER_PARTIAL	(1 << 4)
+
+/* clock B running */
+# define LVDS_CLKB_POWER_UP		(3 << 4)
+
+/*
+ * Two channel mode B0-B2 control. Sets state when power is on.
+ * Set to POWER_DOWN in single channel mode, other settings enable
+ * two channel mode. The CLKB power control controls whether that clock
+ * is enabled during two channel mode.
+ *
+ */
+/* Everything is off, including B3 and CLKB */
+# define LVDS_B_POWER_DOWN		(0 << 2)
+
+/* B0, B1, B2 and data lines forced to 0. timing is active */
+# define LVDS_B_POWER_PARTIAL		(1 << 2)
+
+/* data lines active (both timing and colour) */
+# define LVDS_B_POWER_UP		(3 << 2)
+
 /** @defgroup TV_CTL
  * @{
  */
diff --git a/src/i830_display.c b/src/i830_display.c
index e9666de..97d2660 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -884,11 +884,21 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
 
     if (is_lvds)
     {
+	CARD32	lvds = INREG(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);
+	lvds |= LVDS_PORT_EN | LVDS_PIPEB_SELECT;
+	if (IS_I965G(pI830))
+	{
+	    if (pI830->panel_wants_dither)
+		lvds |= LVDS_DITHER_ENABLE;
+	    else
+		lvds &= ~LVDS_DITHER_ENABLE;
+	}
+	OUTREG(LVDS, lvds);
     }
     
     /* Disable the panel fitter if it was on our pipe */
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index 642dd8a..1df8a92 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -241,8 +241,9 @@ i830_lvds_mode_set(xf86OutputPtr output,
 		    VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
 		    VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR);
 
-    if (pI830->panel_wants_dither)
-	pfit_control |= PANEL_8TO6_DITHER_ENABLE;
+    if (!IS_I965G(pI830))
+	if (pI830->panel_wants_dither)
+	    pfit_control |= PANEL_8TO6_DITHER_ENABLE;
 
     OUTREG(PFIT_CONTROL, pfit_control);
 }
diff-tree 0fa3d4f51b5ee0dba3882fd74b6ac4e7da708f8f (from parents)
Merge: 10655c4674cdac8a231c50dd9afc5d43fe43b4bd fd52d635603b7093c5a2b7fa9c987cf59f9be27c
Author: Keith Packard <keithp at gamba.jf.intel.com>
Date:   Sat Mar 3 21:02:17 2007 -0800

    Merge branch 'modesetting' into crestline

diff-tree 0ed5a2fdcfe9674175aa9af155c20695ef41cadc (from parents)
Merge: 7ba80cc3a5e0f469e3ee55c7537fdc952cd85911 fd52d635603b7093c5a2b7fa9c987cf59f9be27c
Author: Nian Wu <nian.wu at intel.com>
Date:   Sat Mar 3 09:00:20 2007 -0500

    Merge branch 'modesetting' of git://proxy01.pd.intel.com:9419/git/xorg/driver/xf86-video-intel into crestline

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 7ba80cc3a5e0f469e3ee55c7537fdc952cd85911 (from parents)
Merge: 9796cb7ac4bd74d5336986bb194ff5875b028121 d5df52be59a7dd950e73336ce5698e73480108b0
Author: Nian Wu <nian.wu at intel.com>
Date:   Fri Mar 2 09:01:46 2007 -0500

    Merge branch 'modesetting' of git://proxy01.pd.intel.com:9419/git/xorg/driver/xf86-video-intel into crestline

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 9796cb7ac4bd74d5336986bb194ff5875b028121 (from parents)
Merge: 42deb1e10fc445d152b74e2b225daeaee2abb3d1 1f5d1666c8386ca4597c6f2c1ec239f9d821da4c
Author: Nian Wu <nian.wu at intel.com>
Date:   Thu Mar 1 09:02:22 2007 -0500

    Merge branch 'modesetting' of git://proxy01.pd.intel.com:9419/git/xorg/driver/xf86-video-intel into crestline

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 36cad3fcb65e3dcd88e58e301cd60adb121cb96b (from b5316fb2623e9630cbd58020e0a7c95bf354c587)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Wed Feb 28 17:52:42 2007 +0100

    Update vblank pipe setup when setting a mode.

diff --git a/src/i830_display.c b/src/i830_display.c
index 258897e..04159e7 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -864,6 +864,9 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
     OUTREG(dspcntr_reg, dspcntr);
     /* Flush the plane changes */
     i830PipeSetBase(crtc, x, y);
+#ifdef XF86DRI
+   I830DRISetVBlankInterrupt (pScrn, TRUE);
+#endif
     
     i830WaitForVblank(pScrn);
 }
@@ -1041,9 +1044,6 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
 
     i830DescribeOutputConfiguration(pScrn);
 
-#ifdef XF86DRI
-   I830DRISetVBlankInterrupt (pScrn, TRUE);
-#endif
 done:
     i830DumpRegs (pScrn);
     i830_sdvo_dump(pScrn);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 3c8ec1a..9bd7029 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3085,10 +3085,6 @@ I830EnterVT(int scrnIndex, int flags)
    i830DumpRegs (pScrn);
    i830DescribeOutputConfiguration(pScrn);
 
-#ifdef XF86DRI
-   I830DRISetVBlankInterrupt (pScrn, TRUE);
-#endif
-
    ResetState(pScrn, TRUE);
    SetHWOperatingState(pScrn);
 
diff-tree b5316fb2623e9630cbd58020e0a7c95bf354c587 (from f5ab9e0ad3a65c972861dd53be6e33e1aac13191)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Wed Feb 28 17:50:56 2007 +0100

    I830DRIClipNotify: Fix initialization of crtcBox[1].[xy]2.

diff --git a/src/i830_dri.c b/src/i830_dri.c
index afc7de0..e546066 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1523,8 +1523,8 @@ I830DRIClipNotify(ScreenPtr pScreen, Win
       crtcBox[0].y2 = crtcBox[0].y1 + sPriv->pipeA_h;
       crtcBox[1].x1 = sPriv->pipeB_x;
       crtcBox[1].y1 = sPriv->pipeB_y;
-      crtcBox[1].x2 = crtcBox[0].x1 + sPriv->pipeB_w;
-      crtcBox[1].y2 = crtcBox[0].y1 + sPriv->pipeB_h;
+      crtcBox[1].x2 = crtcBox[1].x1 + sPriv->pipeB_w;
+      crtcBox[1].y2 = crtcBox[1].y1 + sPriv->pipeB_h;
 
       for (i = 0; i < 2; i++) {
 	 for (j = 0; j < num; j++) {
diff-tree 42deb1e10fc445d152b74e2b225daeaee2abb3d1 (from parents)
Merge: 76aac382659bc1dab7dca078f703b9cf48b4ad74 3e8e75e5d83a2fa7e9fc6e9a3fbb07dac548ea5a
Author: Nian Wu <nian.wu at intel.com>
Date:   Wed Feb 28 09:00:24 2007 -0500

    Merge branch 'modesetting' of git://proxy01.pd.intel.com:9419/git/xorg/driver/xf86-video-intel into crestline

diff-tree 76aac382659bc1dab7dca078f703b9cf48b4ad74 (from parents)
Merge: 42fc06c85a0c487cfa26b9d4aa396402dbc4c2fe 1ac83f51ee46d65237eae1b5c767e106ac9e29bc
Author: Nian Wu <nian at tinderbox.sh.intel.com>
Date:   Tue Feb 27 14:42:42 2007 -0500

    Merge branch 'modesetting' of git://proxy01.pd.intel.com:9419/git/xorg/driver/xf86-video-intel into crestline

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 10655c4674cdac8a231c50dd9afc5d43fe43b4bd (from 9417af8630fce0476273b693ebac12129415e0cf)
Author: Zou Nan hai <nanhai.zou at intel.com>
Date:   Mon Feb 26 09:23:14 2007 +0800

      for merge with external tree

diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
deleted file mode 100644
index da25577..0000000
--- a/src/i830_xf86Crtc.c
+++ /dev/null
@@ -1,1559 +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_randr.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,
-} 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)
-{
-    char    *option_name;
-    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);
-    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;
-}
-
-xf86OutputPtr
-xf86OutputCreate (ScrnInfoPtr		    scrn,
-		  const xf86OutputFuncsRec *funcs,
-		  const char		    *name)
-{
-    xf86OutputPtr	output, *outputs;
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
-    int			len = strlen (name);
-
-    output = xcalloc (sizeof (xf86OutputRec) + len + 1, 1);
-    if (!output)
-	return NULL;
-    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 = NULL;
-#endif
-    xf86OutputSetMonitor (output);
-    
-    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);
-    char    *newname = xalloc (len + 1);
-    
-    if (!newname)
-	return FALSE;	/* so sorry... */
-    
-    strcpy (newname, name);
-    if (output->name != (char *) (output + 1))
-	xfree (output->name);
-    output->name = newname;
-    xf86OutputSetMonitor (output);
-    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 != (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
-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, 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 (i830xf86ModeCompare (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];
-	I830OutputPrivatePtr intel_output = output->driver_private;
-	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);
-	if (intel_output->type != I830_OUTPUT_TVOUT)	
-		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 = i830xf86SortModes (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-tree 9417af8630fce0476273b693ebac12129415e0cf (from 00dadaa115951c36de9caf2a9d78909811ef34bc)
Author: Zou Nan hai <nanhai.zou at intel.com>
Date:   Mon Feb 26 08:02:50 2007 +0800

      fix conflict with external branch

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-tree 42fc06c85a0c487cfa26b9d4aa396402dbc4c2fe (from parents)
Merge: 10655c4674cdac8a231c50dd9afc5d43fe43b4bd 3bce8bf0e95e5842399959a5d6f6413e96f03adb
Author: Nian Wu <nian at graphics.(none)>
Date:   Sun Feb 25 12:53:47 2007 -0800

    Merge branch 'modesetting' of git://proxy01.pd.intel.com:9419/git/xorg/driver/xf86-video-intel into crestline

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 f5ab9e0ad3a65c972861dd53be6e33e1aac13191 (from 8cce74f195e5ef6ce5599ecd52f35bcfcb0d7913)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Thu Feb 22 18:57:23 2007 +0100

    I830DRISwapContext: Some cleanups.
    
    Also call I830EmitFlush() when entering/leaving the server context. Doesn't
    seem to help for artifacts with page flipping and mixed 2D/3D unfortunately.

diff --git a/src/i830_dri.c b/src/i830_dri.c
index 6c91cdc..afc7de0 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1135,6 +1135,8 @@ I830DRISwapContext(ScreenPtr pScreen, DR
       pI830->LockHeld = 1;
       I830RefreshRing(pScrn);
 
+      I830EmitFlush(pScrn);
+
 #ifdef DAMAGE
       if (!pI830->pDamage && pI830->allowPageFlip) {
 	 PixmapPtr pPix  = pScreen->GetScreenPixmap(pScreen);
@@ -1159,10 +1161,12 @@ I830DRISwapContext(ScreenPtr pScreen, DR
    } else if (syncType == DRI_2D_SYNC &&
 	      oldContextType == DRI_NO_CONTEXT &&
 	      newContextType == DRI_2D_CONTEXT) {
-      pI830->LockHeld = 0;
       if (I810_DEBUG & DEBUG_VERBOSE_DRI)
 	 ErrorF("i830DRISwapContext (out)\n");
 
+      if (!pScrn->vtSema)
+     	 return;
+
 #ifdef DAMAGE
       if (pI830->pDamage) {
 	 RegionPtr pDamageReg = DamageRegion(pI830->pDamage);
@@ -1181,6 +1185,10 @@ I830DRISwapContext(ScreenPtr pScreen, DR
 	 }
       }
 #endif
+
+      I830EmitFlush(pScrn);
+
+      pI830->LockHeld = 0;
    } else if (I810_DEBUG & DEBUG_VERBOSE_DRI)
       ErrorF("i830DRISwapContext (other)\n");
 }
diff-tree 8cce74f195e5ef6ce5599ecd52f35bcfcb0d7913 (from f346549183a407a4bff6521ec2450dacb97442e9)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Thu Feb 22 18:27:59 2007 +0100

    Do not sync DRI windows between pages when possible.

diff --git a/src/i830.h b/src/i830.h
index bbbb4a8..e26556f 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -310,6 +310,7 @@ typedef struct _I830Rec {
 
 #ifdef DAMAGE
    DamagePtr pDamage;
+   RegionRec driRegion;
 #endif
 #endif
 
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 65736cd..6c91cdc 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -980,6 +980,10 @@ I830DRICloseScreen(ScreenPtr pScreen)
 
    DPRINTF(PFX, "I830DRICloseScreen\n");
 
+#ifdef DAMAGE
+   REGION_UNINIT(pScreen, &pI830->driRegion);
+#endif
+
    if (pI830DRI->irq) {
        drmCtlUninstHandler(pI830->drmSubFD);
        pI830DRI->irq = 0;
@@ -1164,10 +1168,16 @@ I830DRISwapContext(ScreenPtr pScreen, DR
 	 RegionPtr pDamageReg = DamageRegion(pI830->pDamage);
 
 	 if (pDamageReg) {
-	    int nrects = REGION_NUM_RECTS(pDamageReg);
+	    RegionRec region;
+	    int nrects;
 
-	    if (nrects)
-	       I830DRIRefreshArea(pScrn, nrects, REGION_RECTS(pDamageReg));
+	    REGION_NULL(pScreen, &region);
+	    REGION_SUBTRACT(pScreen, &region, pDamageReg, &pI830->driRegion);
+
+	    if ((nrects = REGION_NUM_RECTS(&region)))
+	       I830DRIRefreshArea(pScrn, nrects, REGION_RECTS(&region));
+
+	    REGION_UNINIT(pScreen, &region);
 	 }
       }
 #endif
@@ -1486,8 +1496,13 @@ I830DRITransitionTo2d(ScreenPtr pScreen)
 static void
 I830DRIClipNotify(ScreenPtr pScreen, WindowPtr *ppWin, int num)
 {
+   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+   I830Ptr pI830 = I830PTR(pScrn);
    unsigned pfMask = 0;
 
+   REGION_UNINIT(pScreen, &pI830->driRegion);
+   REGION_NULL(pScreen, &pI830->driRegion);
+
    if (num > 0) {
       drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScreen);
       BoxRec crtcBox[2];
@@ -1505,15 +1520,24 @@ I830DRIClipNotify(ScreenPtr pScreen, Win
 
       for (i = 0; i < 2; i++) {
 	 for (j = 0; j < num; j++) {
-	    if (ppWin[j] && RECT_IN_REGION(pScreen, &ppWin[j]->clipList,
-					   &crtcBox[i]) != rgnOUT)
-	       numvisible[i]++;
+	    WindowPtr pWin = ppWin[j];
+
+	    if (pWin) {
+	       if (RECT_IN_REGION(pScreen, &pWin->clipList, &crtcBox[i]) !=
+		   rgnOUT)
+		  numvisible[i]++;
+
+	       if (i == 0)
+		  REGION_UNION(pScreen, &pI830->driRegion, &pWin->clipList,
+			       &pI830->driRegion);
+	    }
 	 }
 
 	 if (numvisible[i] == 1)
 	    pfMask |= 1 << i;
       }
-   }
+   } else
+      REGION_NULL(pScreen, &pI830->driRegion);
 
    I830DRISetPfMask(pScreen, pfMask);
 }
diff-tree f346549183a407a4bff6521ec2450dacb97442e9 (from 0bee64f4bc7581de7ab28ca438581d215e85c610)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Wed Feb 21 09:19:54 2007 +0100

    intel.man: Fix typo.

diff --git a/man/intel.man b/man/intel.man
index 503b52a..05a91f7 100644
--- a/man/intel.man
+++ b/man/intel.man
@@ -170,7 +170,7 @@ Default for i810: The option is not used
 Default for i830 and above: Disabled.
 .TP
 .BI "Option \*qTripleBuffer\*q \*q" boolean \*q
-Enable support for triple flipping. This should improve 3D performance at the
+Enable support for triple buffering. This should improve 3D performance at the
 potential cost of worse performance with mixed 2D/3D. Also note that this gives
 no benefit without corresponding support in the Mesa 3D driver and may not give
 any benefit without page flipping either (see
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 0bee64f4bc7581de7ab28ca438581d215e85c610 (from 2212baa8454abb4c7948c3f2e20e337f831d1b86)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Tue Feb 20 19:09:37 2007 +0100

    Add support for triple buffering using a third static buffer.
    
    Need to bump the DRI DDX version minor for the added SAREA fields.

diff --git a/man/intel.man b/man/intel.man
index 3f4cff8..503b52a 100644
--- a/man/intel.man
+++ b/man/intel.man
@@ -162,9 +162,22 @@ Default: 32768.
 .BI "Option \*qPageFlip\*q \*q" boolean \*q
 Enable support for page flipping. This should improve 3D performance at the
 potential cost of worse performance or artifacts with mixed 2D/3D. Also note
-that this gives no benefit without corresponding support in the Mesa 3D driver.
+that this gives no benefit without corresponding support in the Mesa 3D driver
+and may not give the full benefit without triple buffering (see
+.B "Option \*qTripleBuffer\*q"
+).
 Default for i810: The option is not used.
-Default for i9xx: Disabled.
+Default for i830 and above: Disabled.
+.TP
+.BI "Option \*qTripleBuffer\*q \*q" boolean \*q
+Enable support for triple flipping. This should improve 3D performance at the
+potential cost of worse performance with mixed 2D/3D. Also note that this gives
+no benefit without corresponding support in the Mesa 3D driver and may not give
+any benefit without page flipping either (see
+.B "Option \*qPageFlip\*q"
+).
+Default for i810: The option is not used.
+Default for i830 and above: Disabled.
 .TP
 .BI "Option \*qAccelMethod\*q \*q" string \*q
 Choose acceleration architecture, either "XAA" or "EXA".  XAA is the old
diff --git a/src/i830.h b/src/i830.h
index 78381fb..bbbb4a8 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -294,6 +294,7 @@ typedef struct _I830Rec {
    I830MemRange ContextMem;
 #ifdef XF86DRI
    I830MemRange BackBuffer;
+   I830MemRange ThirdBuffer;
    I830MemRange DepthBuffer;
    I830MemRange TexMem;
    int TexGranularity;
@@ -304,6 +305,7 @@ typedef struct _I830Rec {
 
    unsigned int front_tiled;
    unsigned int back_tiled;
+   unsigned int third_tiled;
    unsigned int depth_tiled;
 
 #ifdef DAMAGE
@@ -313,6 +315,7 @@ typedef struct _I830Rec {
 
    Bool NeedRingBufferLow;
    Bool allowPageFlip;
+   Bool TripleBuffer;
    Bool disableTiling;
 
    int backPitch;
@@ -511,6 +514,7 @@ typedef struct _I830Rec {
 #define I830_SELECT_FRONT	0
 #define I830_SELECT_BACK	1
 #define I830_SELECT_DEPTH	2
+#define I830_SELECT_THIRD	3
 
 /* I830 specific functions */
 extern int I830WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis);
@@ -539,6 +543,7 @@ 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 I830AllocateThirdBuffer(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);
diff --git a/src/i830_accel.c b/src/i830_accel.c
index db3168a..c76c748 100644
--- a/src/i830_accel.c
+++ b/src/i830_accel.c
@@ -228,6 +228,9 @@ I830SelectBuffer(ScrnInfoPtr pScrn, int 
    case I830_SELECT_BACK:
       pI830->bufferOffset = pI830->BackBuffer.Start;
       break;
+   case I830_SELECT_THIRD:
+      pI830->bufferOffset = pI830->ThirdBuffer.Start;
+      break;
    case I830_SELECT_DEPTH:
       pI830->bufferOffset = pI830->DepthBuffer.Start;
       break;
diff --git a/src/i830_common.h b/src/i830_common.h
index 79455b6..f853ccd 100644
--- a/src/i830_common.h
+++ b/src/i830_common.h
@@ -130,6 +130,12 @@ typedef struct {
 	int pipeB_y;
 	int pipeB_w;
 	int pipeB_h;
+
+	/* Triple buffering */
+	drm_handle_t third_handle;
+	int third_offset;
+	int third_size;
+	unsigned int third_tiled;
 } drmI830Sarea;
 
 /* Flags for perf_boxes
diff --git a/src/i830_dri.c b/src/i830_dri.c
index d655183..65736cd 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -751,6 +751,20 @@ I830DRIMapScreenRegions(ScrnInfoPtr pScr
    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Back Buffer = 0x%08x\n",
               (int)sarea->back_handle);
 
+   if (pI830->TripleBuffer) {
+      if (drmAddMap(pI830->drmSubFD,
+		    (drm_handle_t)(sarea->third_offset + pI830->LinearAddr),
+		    sarea->third_size, DRM_AGP, 0,
+		    (drmAddress) &sarea->third_handle) < 0) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "[drm] drmAddMap(third_handle) failed. Disabling DRI\n");
+	DRICloseScreen(pScreen);
+	return FALSE;
+      }
+      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Third Buffer = 0x%08x\n",
+		 (int)sarea->third_handle);
+   }
+
    if (drmAddMap(pI830->drmSubFD,
                  (drm_handle_t)sarea->depth_offset + pI830->LinearAddr,
                  sarea->depth_size, DRM_AGP, 0,
@@ -794,6 +808,10 @@ I830DRIUnmapScreenRegions(ScrnInfoPtr pS
       drmRmMap(pI830->drmSubFD, sarea->back_handle);
       sarea->back_handle = 0;
    }
+   if (sarea->third_handle) {
+      drmRmMap(pI830->drmSubFD, sarea->third_handle);
+      sarea->third_handle = 0;
+   }
    if (sarea->depth_handle) {
       drmRmMap(pI830->drmSubFD, sarea->depth_handle);
       sarea->depth_handle = 0;
@@ -870,6 +888,7 @@ I830DRIDoMappings(ScreenPtr pScreen)
    /* init to zero to be safe */
    sarea->front_handle = 0;
    sarea->back_handle = 0;
+   sarea->third_handle = 0;
    sarea->depth_handle = 0;
    sarea->tex_handle = 0;
 
@@ -1041,17 +1060,10 @@ I830DRIFinishScreenInit(ScreenPtr pScree
  * Otherwise will have to sync again???
  */
 static void
-I830DRIRefreshArea (ScrnInfoPtr pScrn, int num, BoxPtr pbox)
+I830DRIDoRefreshArea (ScrnInfoPtr pScrn, int num, BoxPtr pbox, CARD32 dst)
 {
    I830Ptr pI830 = I830PTR(pScrn);
    int i, cmd, br13 = (pScrn->displayWidth * pI830->cpp) | (0xcc << 16);
-   drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
-
-   /* Don't want to do this when no 3d is active and pages are
-    * right-way-round :
-    */
-   if (!pSAREAPriv->pf_active && pSAREAPriv->pf_current_page == 0)
-      return;
 
    if (pScrn->bitsPerPixel == 32) {
       cmd = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
@@ -1068,12 +1080,31 @@ I830DRIRefreshArea (ScrnInfoPtr pScrn, i
       OUT_RING(br13);
       OUT_RING((pbox->y1 << 16) | pbox->x1);
       OUT_RING((pbox->y2 << 16) | pbox->x2);
-      OUT_RING(pI830->BackBuffer.Start);
+      OUT_RING(dst);
       OUT_RING((pbox->y1 << 16) | pbox->x1);
       OUT_RING(br13 & 0xffff);
       OUT_RING(pI830->FrontBuffer.Start);
       ADVANCE_LP_RING();
    }
+}
+
+static void
+I830DRIRefreshArea (ScrnInfoPtr pScrn, int num, BoxPtr pbox)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+   drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
+
+   /* Don't want to do this when no 3d is active and pages are
+    * right-way-round :
+    */
+   if (!pSAREAPriv->pf_active && pSAREAPriv->pf_current_page == 0)
+      return;
+
+   I830DRIDoRefreshArea(pScrn, num, pbox, pI830->BackBuffer.Start);
+
+   if (pI830->TripleBuffer) {
+      I830DRIDoRefreshArea(pScrn, num, pbox, pI830->ThirdBuffer.Start);
+   }
 
    DamageEmpty(pI830->pDamage);
 }
@@ -1160,6 +1191,13 @@ I830DRIInitBuffers(WindowPtr pWin, Regio
       I830SelectBuffer(pScrn, I830_SELECT_BACK);
       I830SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1,
 				  pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
+
+      if (I830PTR(pScrn)->TripleBuffer) {
+	 I830SelectBuffer(pScrn, I830_SELECT_THIRD);
+	 I830SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1,
+				     pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
+      }
+
       pbox++;
    }
 
@@ -1333,6 +1371,10 @@ I830DRIMoveBuffers(WindowPtr pParent, DD
 
       I830SelectBuffer(pScrn, I830_SELECT_BACK);
       I830SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h);
+      if (pI830->TripleBuffer) {
+	 I830SelectBuffer(pScrn, I830_SELECT_THIRD);
+	 I830SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h);
+      }
       if (!IS_I965G(pI830)) {
          I830SelectBuffer(pScrn, I830_SELECT_DEPTH);
          I830SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h);
@@ -1492,6 +1534,7 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, 
 
    sarea->front_tiled = pI830->front_tiled;
    sarea->back_tiled = pI830->back_tiled;
+   sarea->third_tiled = pI830->third_tiled;
    sarea->depth_tiled = pI830->depth_tiled;
    sarea->rotated_tiled = FALSE;
 
@@ -1509,6 +1552,8 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, 
    sarea->height = pScreen->height;
    sarea->back_offset = pI830->BackBuffer.Start;
    sarea->back_size = pI830->BackBuffer.Size;
+   sarea->third_offset = pI830->ThirdBuffer.Start;
+   sarea->third_size = pI830->ThirdBuffer.Size;
    sarea->depth_offset = pI830->DepthBuffer.Start;
    sarea->depth_size = pI830->DepthBuffer.Size;
    sarea->tex_offset = pI830->TexMem.Start;
diff --git a/src/i830_dri.h b/src/i830_dri.h
index a140497..a2cf78e 100644
--- a/src/i830_dri.h
+++ b/src/i830_dri.h
@@ -9,8 +9,8 @@
 #define I830_MAX_DRAWABLES 256
 
 #define I830_MAJOR_VERSION 1
-#define I830_MINOR_VERSION 7
-#define I830_PATCHLEVEL 2
+#define I830_MINOR_VERSION 8
+#define I830_PATCHLEVEL 0
 
 #define I830_REG_SIZE 0x80000
 
diff --git a/src/i830_driver.c b/src/i830_driver.c
index d1f83e5..3c8ec1a 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -273,7 +273,8 @@ typedef enum {
    OPTION_CHECKDEVICES,
    OPTION_LINEARALLOC,
    OPTION_INTELTEXPOOL,
-   OPTION_INTELMMSIZE
+   OPTION_INTELMMSIZE,
+   OPTION_TRIPLEBUFFER,
 } I830Opts;
 
 static OptionInfoRec I830Options[] = {
@@ -292,6 +293,7 @@ static OptionInfoRec I830Options[] = {
    {OPTION_LINEARALLOC, "LinearAlloc",  OPTV_INTEGER,   {0},    FALSE},
    {OPTION_INTELTEXPOOL,"Legacy3D",     OPTV_BOOLEAN,	{0},	FALSE},
    {OPTION_INTELMMSIZE, "AperTexSize",  OPTV_INTEGER,	{0},	FALSE},
+   {OPTION_TRIPLEBUFFER, "TripleBuffer", OPTV_BOOLEAN,	{0},	FALSE},
    {-1,			NULL,		OPTV_NONE,	{0},	FALSE}
 };
 /* *INDENT-ON* */
@@ -1487,6 +1489,16 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    }
 #endif
 
+#ifdef XF86DRI
+   pI830->TripleBuffer = FALSE;
+   from =  (!pI830->directRenderingDisabled &&
+	    xf86GetOptValBool(pI830->Options, OPTION_TRIPLEBUFFER,
+			      &pI830->TripleBuffer)) ? X_CONFIG : X_DEFAULT;
+
+   xf86DrvMsg(pScrn->scrnIndex, from, "Triple buffering %sabled\n",
+	      pI830->TripleBuffer ? "en" : "dis");
+#endif
+
    /*
     * If the driver can do gamma correction, it should call xf86SetGamma() here.
     */
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 29d9d31..2d1cca9 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -1118,6 +1118,69 @@ I830AllocateBackBuffer(ScrnInfoPtr pScrn
 }
 
 Bool
+I830AllocateThirdBuffer(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;
+
+   /* Third Buffer */
+   memset(&(pI830->ThirdBuffer), 0, sizeof(pI830->ThirdBuffer));
+   pI830->ThirdBuffer.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->ThirdBuffer),
+				   &(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->ThirdBuffer),
+				&(pI830->StolenPool), size, align,
+				flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
+   }
+   if (alloced < size) {
+      if (!dryrun) {
+	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		    "Failed to allocate third buffer space.\n");
+      }
+      return FALSE;
+   }
+   xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		  "%sAllocated %ld kB for the third buffer at 0x%lx.\n", s,
+		  alloced / 1024, pI830->ThirdBuffer.Start);
+
+   return TRUE;
+}
+
+Bool
 I830AllocateDepthBuffer(ScrnInfoPtr pScrn, const int flags)
 {
    I830Ptr pI830 = I830PTR(pScrn);
@@ -1271,6 +1334,9 @@ I830Allocate3DMemory(ScrnInfoPtr pScrn, 
    if (!I830AllocateBackBuffer(pScrn, flags))
       return FALSE;
 
+   if (pI830->TripleBuffer && !I830AllocateThirdBuffer(pScrn, flags))
+      return FALSE;
+
    if (!I830AllocateDepthBuffer(pScrn, flags))
       return FALSE;
 
@@ -1439,6 +1505,7 @@ I830FixupOffsets(ScrnInfoPtr pScrn)
    if (pI830->directRenderingEnabled) {
       I830FixOffset(pScrn, &(pI830->ContextMem));
       I830FixOffset(pScrn, &(pI830->BackBuffer));
+      I830FixOffset(pScrn, &(pI830->ThirdBuffer));
       I830FixOffset(pScrn, &(pI830->DepthBuffer));
       if (pI830->mmModeFlags & I830_KERNEL_TEX) {
 	 I830FixOffset(pScrn, &(pI830->TexMem));
@@ -1701,6 +1768,7 @@ I830SetupMemoryTiling(ScrnInfoPtr pScrn)
 
    pI830->front_tiled = FENCE_LINEAR;
    pI830->back_tiled = FENCE_LINEAR;
+   pI830->third_tiled = FENCE_LINEAR;
    pI830->depth_tiled = FENCE_LINEAR;
 
    if (pI830->allowPageFlip) {
@@ -1739,6 +1807,18 @@ I830SetupMemoryTiling(ScrnInfoPtr pScrn)
       }
    }
 
+   if (pI830->ThirdBuffer.Alignment >= KB(512)) {
+      if (MakeTiles(pScrn, &(pI830->ThirdBuffer), FENCE_XMAJOR)) {
+	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		    "Activating tiled memory for the third buffer.\n");
+         pI830->third_tiled = FENCE_XMAJOR;
+      } else {
+	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		    "MakeTiles failed for the third buffer.\n");
+	 pI830->allowPageFlip = FALSE;
+      }
+   }
+
    if (pI830->DepthBuffer.Alignment >= KB(512)) {
       if (MakeTiles(pScrn, &(pI830->DepthBuffer), FENCE_YMAJOR)) {
 	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
@@ -1825,6 +1905,8 @@ I830BindAGPMemory(ScrnInfoPtr pScrn)
 	    return FALSE;
 	 if (!BindMemRange(pScrn, &(pI830->BackBuffer)))
 	    return FALSE;
+	 if (pI830->TripleBuffer && !BindMemRange(pScrn, &(pI830->ThirdBuffer)))
+	    return FALSE;
 	 if (!BindMemRange(pScrn, &(pI830->DepthBuffer)))
 	    return FALSE;
 	 if ((pI830->mmModeFlags & I830_KERNEL_TEX) && 
@@ -1919,6 +2001,8 @@ I830UnbindAGPMemory(ScrnInfoPtr pScrn)
 	    return FALSE;
 	 if (!UnbindMemRange(pScrn, &(pI830->BackBuffer)))
 	    return FALSE;
+	 if (pI830->TripleBuffer && !UnbindMemRange(pScrn, &(pI830->ThirdBuffer)))
+	    return FALSE;
 	 if (!UnbindMemRange(pScrn, &(pI830->DepthBuffer)))
 	    return FALSE;
 	 if ((pI830->mmModeFlags & I830_KERNEL_TEX) && 
diff --git a/src/i830_xaa.c b/src/i830_xaa.c
index 5ef5d3c..9b11973 100644
--- a/src/i830_xaa.c
+++ b/src/i830_xaa.c
@@ -281,6 +281,8 @@ CheckTiling(ScrnInfoPtr pScrn)
          tiled = 1;
       if (pI830->bufferOffset == pI830->BackBuffer.Start && pI830->back_tiled == FENCE_XMAJOR)
          tiled = 1;
+      if (pI830->bufferOffset == pI830->ThirdBuffer.Start && pI830->third_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;
diff-tree 2212baa8454abb4c7948c3f2e20e337f831d1b86 (from fac8f2eb49de22abd853ca75f3c985d4d94e3633)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Tue Feb 20 18:39:13 2007 +0100

    Don't mark page flipping as active when it really isn't.

diff --git a/src/i830_dri.c b/src/i830_dri.c
index b368c99..d655183 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1382,8 +1382,11 @@ I830DRISetPfMask(ScreenPtr pScreen, int 
    I830Ptr pI830 = I830PTR(pScrn);
    drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScreen);
 
-   pSAREAPriv->pf_enabled = pI830->allowPageFlip;
-   pSAREAPriv->pf_active = pfMask;
+   if (pI830->allowPageFlip && pfMask) {
+      pSAREAPriv->pf_enabled = pI830->allowPageFlip;
+      pSAREAPriv->pf_active = pfMask;
+   } else
+      pSAREAPriv->pf_enabled = pSAREAPriv->pf_active = 0;
 }
 
 static void
diff-tree fac8f2eb49de22abd853ca75f3c985d4d94e3633 (from 55c7b017ed718107b9b11467030addf225728b84)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Tue Feb 20 18:38:40 2007 +0100

    Document Option "PageFlip".

diff --git a/man/intel.man b/man/intel.man
index b932632..3f4cff8 100644
--- a/man/intel.man
+++ b/man/intel.man
@@ -159,6 +159,13 @@ atctivate the legacy texture pool (see 
 gain some performance by increasing this value.
 Default: 32768.
 .TP
+.BI "Option \*qPageFlip\*q \*q" boolean \*q
+Enable support for page flipping. This should improve 3D performance at the
+potential cost of worse performance or artifacts with mixed 2D/3D. Also note
+that this gives no benefit without corresponding support in the Mesa 3D driver.
+Default for i810: The option is not used.
+Default for i9xx: Disabled.
+.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
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 55c7b017ed718107b9b11467030addf225728b84 (from 3bd8edb95fcbbb49e97a1a2bdd5c8eae4f83d3a8)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Wed Feb 14 16:45:22 2007 +0100

    Use new DRI ClipNotify hook to track page flipping per CRTC when available.

diff --git a/src/i830_dri.c b/src/i830_dri.c
index 05171d3..b368c99 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -107,6 +107,7 @@ static void I830DRITransitionTo2d(Screen
 static void I830DRITransitionTo3d(ScreenPtr pScreen);
 static void I830DRITransitionMultiToSingle3d(ScreenPtr pScreen);
 static void I830DRITransitionSingleToMulti3d(ScreenPtr pScreen);
+static void I830DRIClipNotify(ScreenPtr pScreen, WindowPtr *ppWin, int num);
 
 #if 0
 static void I830DRIShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf);
@@ -551,10 +552,31 @@ I830DRIScreenInit(ScreenPtr pScreen)
    pDRIInfo->InitBuffers = I830DRIInitBuffers;
    pDRIInfo->MoveBuffers = I830DRIMoveBuffers;
    pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
-   pDRIInfo->TransitionTo2d = I830DRITransitionTo2d;
-   pDRIInfo->TransitionTo3d = I830DRITransitionTo3d;
-   pDRIInfo->TransitionSingleToMulti3D = I830DRITransitionSingleToMulti3d;
-   pDRIInfo->TransitionMultiToSingle3D = I830DRITransitionMultiToSingle3d;
+
+#if DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1
+   {
+      int major, minor, patch;
+
+      DRIQueryVersion(&major, &minor, &patch);
+
+      if (minor >= 1)
+#endif
+#if DRIINFO_MAJOR_VERSION > 5 || \
+    (DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1)
+	 pDRIInfo->ClipNotify = I830DRIClipNotify;
+#endif
+   }
+
+#if DRIINFO_MAJOR_VERSION > 5 || \
+    (DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1)
+   if (!pDRIInfo->ClipNotify)
+#endif
+   {
+      pDRIInfo->TransitionTo2d = I830DRITransitionTo2d;
+      pDRIInfo->TransitionTo3d = I830DRITransitionTo3d;
+      pDRIInfo->TransitionSingleToMulti3D = I830DRITransitionSingleToMulti3d;
+      pDRIInfo->TransitionMultiToSingle3D = I830DRITransitionMultiToSingle3d;
+   }
 
    /* do driver-independent DRI screen initialization here */
    if (!DRIScreenInit(pScreen, pDRIInfo, &pI830->drmSubFD)) {
@@ -1354,41 +1376,35 @@ I830DRIMoveBuffers(WindowPtr pParent, DD
  */
 
 static void
-I830EnablePageFlip(ScreenPtr pScreen)
+I830DRISetPfMask(ScreenPtr pScreen, int pfMask)
 {
    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
    I830Ptr pI830 = I830PTR(pScrn);
    drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScreen);
 
    pSAREAPriv->pf_enabled = pI830->allowPageFlip;
-   pSAREAPriv->pf_active = pI830->allowPageFlip;
+   pSAREAPriv->pf_active = pfMask;
 }
 
 static void
-I830DisablePageFlip(ScreenPtr pScreen)
-{
-   drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScreen);
-
-   pSAREAPriv->pf_active = 0;
-}
-
-
-static void
 I830DRITransitionSingleToMulti3d(ScreenPtr pScreen)
 {
    /* Tell the clients not to pageflip.  How?
     *   -- Field in sarea, plus bumping the window counters.
     *   -- DRM needs to cope with Front-to-Back swapbuffers.
     */
-   I830DisablePageFlip(pScreen);
+   I830DRISetPfMask(pScreen, 0);
 }
 
 static void
 I830DRITransitionMultiToSingle3d(ScreenPtr pScreen)
 {
+   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+   I830Ptr pI830 = I830PTR(pScrn);
+
    /* Let the remaining 3d app start page flipping again.
     */
-   I830EnablePageFlip(pScreen);
+   I830DRISetPfMask(pScreen, pI830->allowPageFlip ? 0x3 : 0);
 }
 
 static void
@@ -1397,7 +1413,7 @@ I830DRITransitionTo3d(ScreenPtr pScreen)
    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
    I830Ptr pI830 = I830PTR(pScrn);
 
-   I830EnablePageFlip(pScreen);
+   I830DRISetPfMask(pScreen, pI830->allowPageFlip ? 0x3 : 0);
    pI830->have3DWindows = 1;
 }
 
@@ -1417,11 +1433,46 @@ I830DRITransitionTo2d(ScreenPtr pScreen)
       xf86DrvMsg(pScreen->myNum, X_WARNING,
 		 "[dri] %s: kernel failed to unflip buffers.\n", __func__);
 
-   I830DisablePageFlip(pScreen);
+   I830DRISetPfMask(pScreen, 0);
 
    pI830->have3DWindows = 0;
 }
 
+static void
+I830DRIClipNotify(ScreenPtr pScreen, WindowPtr *ppWin, int num)
+{
+   unsigned pfMask = 0;
+
+   if (num > 0) {
+      drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScreen);
+      BoxRec crtcBox[2];
+      unsigned numvisible[2] = { 0, 0 };
+      int i, j;
+
+      crtcBox[0].x1 = sPriv->pipeA_x;
+      crtcBox[0].y1 = sPriv->pipeA_y;
+      crtcBox[0].x2 = crtcBox[0].x1 + sPriv->pipeA_w;
+      crtcBox[0].y2 = crtcBox[0].y1 + sPriv->pipeA_h;
+      crtcBox[1].x1 = sPriv->pipeB_x;
+      crtcBox[1].y1 = sPriv->pipeB_y;
+      crtcBox[1].x2 = crtcBox[0].x1 + sPriv->pipeB_w;
+      crtcBox[1].y2 = crtcBox[0].y1 + sPriv->pipeB_h;
+
+      for (i = 0; i < 2; i++) {
+	 for (j = 0; j < num; j++) {
+	    if (ppWin[j] && RECT_IN_REGION(pScreen, &ppWin[j]->clipList,
+					   &crtcBox[i]) != rgnOUT)
+	       numvisible[i]++;
+	 }
+
+	 if (numvisible[i] == 1)
+	    pfMask |= 1 << i;
+      }
+   }
+
+   I830DRISetPfMask(pScreen, pfMask);
+}
+
 
 /**
  * Update the SAREA fields with the most recent values.
diff-tree 3bd8edb95fcbbb49e97a1a2bdd5c8eae4f83d3a8 (from 1d22bad33b634aaf61976907cb2ceeec8a9ebe4d)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Fri Feb 2 17:41:18 2007 +0100

    Revive i830 page flipping support.
    
    Use the damage layer directly instead of via shadowfb.

diff --git a/configure.ac b/configure.ac
index d45185a..219fbe6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -94,6 +94,8 @@ if test "$DRI" != no; then
                       [have_sarea_h="yes"], [have_sarea_h="no"])
         AC_CHECK_FILE([${sdkdir}/dristruct.h],
                       [have_dristruct_h="yes"], [have_dristruct_h="no"])
+	AC_CHECK_FILE([${sdkdir}/damage.h],
+                      [have_damage_h="yes"], [have_damage_h="no"])
 fi
 
 AC_MSG_CHECKING([whether to include DRI support])
@@ -127,6 +129,9 @@ if test "$DRI" = yes; then
 	if test "x$DRI_MM" = xyes; then
 		AC_DEFINE(XF86DRI_MM,1,[Extended DRI memory management])
 	fi
+	if test "$have_damage_h" = yes; then
+		AC_DEFINE(DAMAGE,1,[Use Damage extension])
+	fi
 fi
 
 AM_CONDITIONAL(VIDEO_DEBUG, test x$VIDEO_DEBUG = xyes)
diff --git a/src/i830.h b/src/i830.h
index 96972eb..78381fb 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -68,6 +68,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "dri.h"
 #include "GL/glxint.h"
 #include "i830_dri.h"
+#ifdef DAMAGE
+#include "damage.h"
+#endif
 #endif
 
 #ifdef I830_USE_EXA
@@ -302,6 +305,10 @@ typedef struct _I830Rec {
    unsigned int front_tiled;
    unsigned int back_tiled;
    unsigned int depth_tiled;
+
+#ifdef DAMAGE
+   DamagePtr pDamage;
+#endif
 #endif
 
    Bool NeedRingBufferLow;
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 3531bf5..05171d3 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -984,17 +984,6 @@ I830DRIFinishScreenInit(ScreenPtr pScree
 
    DPRINTF(PFX, "I830DRIFinishScreenInit\n");
 
-   /* Have shadow run only while there is 3d active.
-    */
-#if 0
-   if (pI830->allowPageFlip && pI830->drmMinor >= 1) {
-      shadowAdd(pScreen, 0, I830DRIShadowUpdate, 0, 0, 0);
-   }
-   else
-#endif
-      pI830->allowPageFlip = 0;
-
-
    if (!DRIFinishScreenInit(pScreen))
       return FALSE;
 
@@ -1025,6 +1014,49 @@ I830DRIFinishScreenInit(ScreenPtr pScree
    }
 }
 
+#ifdef DAMAGE
+/* This should be done *before* XAA syncs,
+ * Otherwise will have to sync again???
+ */
+static void
+I830DRIRefreshArea (ScrnInfoPtr pScrn, int num, BoxPtr pbox)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+   int i, cmd, br13 = (pScrn->displayWidth * pI830->cpp) | (0xcc << 16);
+   drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
+
+   /* Don't want to do this when no 3d is active and pages are
+    * right-way-round :
+    */
+   if (!pSAREAPriv->pf_active && pSAREAPriv->pf_current_page == 0)
+      return;
+
+   if (pScrn->bitsPerPixel == 32) {
+      cmd = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
+	     XY_SRC_COPY_BLT_WRITE_RGB);
+      br13 |= 3 << 24;
+   } else {
+      cmd = (XY_SRC_COPY_BLT_CMD);
+      br13 |= 1 << 24;
+   }
+
+   for (i = 0 ; i < num ; i++, pbox++) {
+      BEGIN_LP_RING(8);
+      OUT_RING(cmd);
+      OUT_RING(br13);
+      OUT_RING((pbox->y1 << 16) | pbox->x1);
+      OUT_RING((pbox->y2 << 16) | pbox->x2);
+      OUT_RING(pI830->BackBuffer.Start);
+      OUT_RING((pbox->y1 << 16) | pbox->x1);
+      OUT_RING(br13 & 0xffff);
+      OUT_RING(pI830->FrontBuffer.Start);
+      ADVANCE_LP_RING();
+   }
+
+   DamageEmpty(pI830->pDamage);
+}
+#endif
+
 static void
 I830DRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
 		   DRIContextType oldContextType, void *oldContext,
@@ -1045,12 +1077,47 @@ I830DRISwapContext(ScreenPtr pScreen, DR
      	 return;
       pI830->LockHeld = 1;
       I830RefreshRing(pScrn);
+
+#ifdef DAMAGE
+      if (!pI830->pDamage && pI830->allowPageFlip) {
+	 PixmapPtr pPix  = pScreen->GetScreenPixmap(pScreen);
+	 pI830->pDamage = DamageCreate(NULL, NULL, DamageReportNone, TRUE,
+				       pScreen, pPix);
+
+	 if (pI830->pDamage == NULL) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+                       "No screen damage record, page flipping disabled\n");
+            pI830->allowPageFlip = 0;
+	 } else {
+	    DamageRegister(&pPix->drawable, pI830->pDamage);
+
+	    DamageDamageRegion(&pPix->drawable,
+			       &WindowTable[pScreen->myNum]->winSize);
+
+            xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+                       "Damage tracking initialized for page flipping\n");
+	 }
+    }
+#endif
    } else if (syncType == DRI_2D_SYNC &&
 	      oldContextType == DRI_NO_CONTEXT &&
 	      newContextType == DRI_2D_CONTEXT) {
       pI830->LockHeld = 0;
       if (I810_DEBUG & DEBUG_VERBOSE_DRI)
 	 ErrorF("i830DRISwapContext (out)\n");
+
+#ifdef DAMAGE
+      if (pI830->pDamage) {
+	 RegionPtr pDamageReg = DamageRegion(pI830->pDamage);
+
+	 if (pDamageReg) {
+	    int nrects = REGION_NUM_RECTS(pDamageReg);
+
+	    if (nrects)
+	       I830DRIRefreshArea(pScrn, nrects, REGION_RECTS(pDamageReg));
+	 }
+      }
+#endif
    } else if (I810_DEBUG & DEBUG_VERBOSE_DRI)
       ErrorF("i830DRISwapContext (other)\n");
 }
@@ -1286,54 +1353,6 @@ I830DRIMoveBuffers(WindowPtr pParent, DD
  * might be faster, but seems like a lot more work...
  */
 
-
-#if 0
-/* This should be done *before* XAA syncs,
- * Otherwise will have to sync again???
- */
-static void
-I830DRIShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf)
-{
-   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-   I830Ptr pI830 = I830PTR(pScrn);
-   RegionPtr damage = &pBuf->damage;
-   int i, num =  REGION_NUM_RECTS(damage);
-   BoxPtr pbox = REGION_RECTS(damage);
-   drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScreen);
-   int cmd, br13;
-
-   /* Don't want to do this when no 3d is active and pages are
-    * right-way-round :
-    */
-   if (!pSAREAPriv->pf_active && pSAREAPriv->pf_current_page == 0)
-      return;
-
-   br13 = (pScrn->displayWidth * pI830->cpp) | (0xcc << 16);
-
-   if (pScrn->bitsPerPixel == 32) {
-      cmd = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
-	     XY_SRC_COPY_BLT_WRITE_RGB);
-      br13 |= 3 << 24;
-   } else {
-      cmd = (XY_SRC_COPY_BLT_CMD);
-      br13 |= 1 << 24;
-   }
-
-   for (i = 0 ; i < num ; i++, pbox++) {
-      BEGIN_LP_RING(8);
-      OUT_RING(cmd);
-      OUT_RING(br13);
-      OUT_RING((pbox->y1 << 16) | pbox->x1);
-      OUT_RING((pbox->y2 << 16) | pbox->x2);
-      OUT_RING(pI830->BackBuffer.Start);
-      OUT_RING((pbox->y1 << 16) | pbox->x1);
-      OUT_RING(br13 & 0xffff);
-      OUT_RING(pI830->FrontBuffer.Start);
-      ADVANCE_LP_RING();
-   }
-}
-#endif
-
 static void
 I830EnablePageFlip(ScreenPtr pScreen)
 {
@@ -1342,32 +1361,7 @@ I830EnablePageFlip(ScreenPtr pScreen)
    drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScreen);
 
    pSAREAPriv->pf_enabled = pI830->allowPageFlip;
-   pSAREAPriv->pf_active = 0;
-
-   if (pI830->allowPageFlip) {
-      int br13 = (pScrn->displayWidth * pI830->cpp) | (0xcc << 16);
-
-      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);
-	 br13 |= 3 << 24;
-      } else {
-	 OUT_RING(XY_SRC_COPY_BLT_CMD);
-	 br13 |= 1 << 24;
-      }
-
-      OUT_RING(br13);
-      OUT_RING(0);
-      OUT_RING((pScrn->virtualY << 16) | pScrn->virtualX);
-      OUT_RING(pI830->BackBuffer.Start);
-      OUT_RING(0);
-      OUT_RING(br13 & 0xffff);
-      OUT_RING(pI830->FrontBuffer.Start);
-      ADVANCE_LP_RING();
-
-      pSAREAPriv->pf_active = 1;
-   }
+   pSAREAPriv->pf_active = pI830->allowPageFlip;
 }
 
 static void
@@ -1419,14 +1413,13 @@ I830DRITransitionTo2d(ScreenPtr pScreen)
    if (sPriv->pf_current_page == 1)
       drmCommandNone(pI830->drmSubFD, DRM_I830_FLIP);
 
-   /* Shut down shadowing if we've made it back to the front page:
-    */
-   if (sPriv->pf_current_page == 0) {
-      I830DisablePageFlip(pScreen);
-   }
+   if (sPriv->pf_current_page == 1)
+      xf86DrvMsg(pScreen->myNum, X_WARNING,
+		 "[dri] %s: kernel failed to unflip buffers.\n", __func__);
 
-   pI830->have3DWindows = 0;
+   I830DisablePageFlip(pScreen);
 
+   pI830->have3DWindows = 0;
 }
 
 
diff --git a/src/i830_driver.c b/src/i830_driver.c
index cb3dd87..d1f83e5 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3168,6 +3168,15 @@ I830CloseScreen(int scrnIndex, ScreenPtr
    pI830->closing = TRUE;
 #ifdef XF86DRI
    if (pI830->directRenderingOpen) {
+#ifdef DAMAGE
+      if (pI830->pDamage) {
+	 PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen);
+
+	 DamageUnregister(&pPix->drawable, pI830->pDamage);
+	 DamageDestroy(pI830->pDamage);
+	 pI830->pDamage = NULL;
+      }
+#endif
 #ifdef XF86DRI_MM
       if (pI830->mmModeFlags & I830_KERNEL_MM) {
 #ifndef XSERVER_LIBDRM_MM
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 6ceb05b..29d9d31 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -515,7 +515,7 @@ I830AllocateFramebuffer(ScrnInfoPtr pScr
    int verbosity = dryrun ? 4 : 1;
    const char *s = dryrun ? "[dryrun] " : "";
    Bool tileable;
-   int align, alignflags;
+   int align;
    long size, alloced, fb_height;
 
    /* Clear everything first. */
@@ -586,16 +586,6 @@ I830AllocateFramebuffer(ScrnInfoPtr pScr
 
    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);
@@ -603,10 +593,26 @@ I830AllocateFramebuffer(ScrnInfoPtr pScr
 		  "%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 (tileable) {
+      align = GetBestTileAlignment(size);
+
+      for (align = GetBestTileAlignment(size);
+	   align >= (IS_I9XX(pI830) ? MB(1) : KB(512)); align >>= 1) {
+	 alloced = I830AllocVidMem(pScrn, FrontBuffer, StolenPool, size, align,
+				   flags | FROM_ANYWHERE | ALLOCATE_AT_TOP |
+				   ALIGN_BOTH_ENDS);
+	 if (alloced >= size)
+	    break;
+      }
+   } else {
+      align = KB(64);
+
+      alloced = I830AllocVidMem(pScrn, FrontBuffer,
+				StolenPool, size, align,
+				flags | FROM_ANYWHERE | ALLOCATE_AT_BOTTOM);
+   }
+
    if (alloced < size) {
       if (!dryrun) {
 	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate "
@@ -718,7 +724,7 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
    int verbosity = dryrun ? 4 : 1;
    const char *s = dryrun ? "[dryrun] " : "";
    Bool tileable;
-   int align, alignflags, i;
+   int align, i;
 
    DPRINTF(PFX, "I830Allocate2DMemory: inital is %s\n",
 	   BOOLTOSTRING(flags & ALLOC_INITIAL));
@@ -877,20 +883,26 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
 	 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;
+	    align = GetBestTileAlignment(size);
+
+	    for (align = GetBestTileAlignment(size);
+		 align >= (IS_I9XX(pI830) ? MB(1) : KB(512)); align >>= 1) {
+	       alloced = I830AllocVidMem(pScrn, &(pI830->FrontBuffer),
+					 &(pI830->StolenPool), size, align,
+					 flags | FROM_ANYWHERE |
+					 ALLOCATE_AT_TOP | ALIGN_BOTH_ENDS);
+	       if (alloced >= size)
+		  break;
+	    }
 	 } else {
-	    align = KB(64);
-	    alignflags = 0;
+	    alloced = I830AllocVidMem(pScrn, &(pI830->FrontBuffer),
+				      &(pI830->StolenPool), maxFb, align,
+				      flags |
+				      FROM_ANYWHERE | ALLOCATE_AT_BOTTOM);
 	 }
-	 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,
diff-tree 1d22bad33b634aaf61976907cb2ceeec8a9ebe4d (from 0df490938af10d3a748221e2fb5467b0f244f9eb)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Wed Feb 14 12:57:12 2007 +0100

    Update SAREA pipe fields in i830PipeSetBase.

diff --git a/src/i830_display.c b/src/i830_display.c
index 345eea9..258897e 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -361,6 +361,31 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x,
 	OUTREG(dspbase, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
 	(void) INREG(dspbase);
     }
+
+#ifdef XF86DRI
+    if (pI830->directRenderingEnabled) {
+	drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScrn->pScreen);
+
+	switch (pipe) {
+	case 0:
+	    sPriv->pipeA_x = x;
+	    sPriv->pipeA_y = y;
+	    sPriv->pipeA_w = crtc->mode.HDisplay;
+	    sPriv->pipeA_h = crtc->mode.VDisplay;
+	    break;
+	case 1:
+	    sPriv->pipeB_x = x;
+	    sPriv->pipeB_y = y;
+	    sPriv->pipeB_w = crtc->mode.HDisplay;
+	    sPriv->pipeB_h = crtc->mode.VDisplay;
+	    break;
+	default:
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Can't update pipe %d in SAREA\n", pipe);
+	    break;
+	}
+    }
+#endif
 }
 
 /**
diff-tree 0df490938af10d3a748221e2fb5467b0f244f9eb (from 1623b47c4863f5362587cdac855e3e11c109b007)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Thu Dec 21 11:27:28 2006 +0100

    If the DRM can handle it, enable vertical blank interrupts for both pipes.

diff --git a/src/i830_dri.c b/src/i830_dri.c
index 70e7e49..3531bf5 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1497,7 +1497,10 @@ I830DRISetVBlankInterrupt (ScrnInfoPtr p
     if (pI830->directRenderingEnabled && pI830->drmMinor >= 5) {
 	if (on) {
 	    if (xf86_config->num_crtc > 1 && xf86_config->crtc[1]->enabled)
-		pipe.pipe = DRM_I830_VBLANK_PIPE_B;
+		if (pI830->drmMinor >= 6)
+		    pipe.pipe = DRM_I830_VBLANK_PIPE_A | DRM_I830_VBLANK_PIPE_B;
+		else
+		    pipe.pipe = DRM_I830_VBLANK_PIPE_B;
 	    else
 		pipe.pipe = DRM_I830_VBLANK_PIPE_A;
 	} else {
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 00dadaa115951c36de9caf2a9d78909811ef34bc (from 920aeaf8478f706ab3b1de4f20f5d351e64a0197)
Author: Zou Nan hai <nanhai.zou at intel.com>
Date:   Fri Feb 9 11:14:50 2007 +0800

      set DPLL before detect

diff --git a/src/i830_tv.c b/src/i830_tv.c
index 9e62c46..5ee8866 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -1294,6 +1294,7 @@ i830_tv_detect(xf86OutputPtr output)
             /* 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);
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 920aeaf8478f706ab3b1de4f20f5d351e64a0197 (from 6d9757e466863594300c83f3806fd4376bea0504)
Author: Zou Nan hai <nanhai.zou at intel.com>
Date:   Wed Feb 7 13:15:52 2007 +0800

      Make TV code same with external tree.
      Fallback to old filter table.
      4 spaces indent reformat.
      Auto scaling seem to not work well on some low res interlace mode when input width > 1024, filter those modes.
      Fix some subcarriar number

diff --git a/src/i830_tv.c b/src/i830_tv.c
index 6131b28..9e62c46 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -93,7 +93,7 @@ typedef struct {
     float   rv, gv, bv, av;
 } color_conversion_t;
 
-static const CARD32 filter_table_hres[] = {
+static const CARD32 filter_table[] = {
     0xB1403000, 0x2E203500, 0x35002E20, 0x3000B140,
     0x35A0B160, 0x2DC02E80, 0xB1403480, 0xB1603000,
     0x2EA03640, 0x34002D80, 0x3000B120, 0x36E0B160,
@@ -148,51 +148,6 @@ static const CARD32 filter_table_hres[] 
     0x28003100, 0x28002F00, 0x00003100,
 };
 
-static const CARD32 filter_table_ntsc[] = {
-	0xB0603000, 0x1920B3E0, 0xB3E01900, 0x3000B060, 0xB380B080,
-	0x18A01980, 0xB040B440, 0xB0A03000, 0x19D0B300, 0xB4801840,
-	0x3000B020, 0xB260B0E0, 0x2FE01A10, 0x3000B4C0, 0xB1003000,
-	0x1A60B1C0, 0xB4E02F00, 0x30003020, 0xB120B140, 0x2E401AB0,
-	0x3020B500, 0xB1803000, 0x1B00B060, 0xB5202D60, 0x30003040,
-	0x3080B1A0, 0x2CA01B30, 0x3040B520, 0xB1E03020, 0x1B703160,
-	0xB5202BC0, 0x30203040, 0x3260B220, 0x2B001B98, 0x3060B520,
-	0xB2603020, 0x1BD03360, 0xB5002A20, 0x30203060, 0x3480B2A0,
-	0x29601BF0, 0x3060B4E0, 0xB2E03020, 0x1C1835C0, 0xB4C02880,
-	0x30403060, 0x3700B340, 0x3F801C30, 0x3060B4A0, 0xB3803040,
-	0x1C403840, 0xB4603E00, 0x30403060, 0x39A0B3C0, 0x3C801C50,
-	0x3040B420, 0xB4003040, 0x1C603B00, 0xB4003B00, 0x00003040,
-	0x38A03000, 0x3C803AE0, 0x3AE03C80, 0x300038A0, 0x3B0038E0,
-	0x3C803C80, 0x38403AE0, 0x39203000, 0x3C803B00, 0x3AE03C80,
-	0x30203800, 0x3B003960, 0x3C803C80, 0x37A03AE0, 0x39803040,
-	0x3C603B20, 0x3AE03C80, 0x30403760, 0x3B2039C0, 0x3C803C80,
-	0x37003AE0, 0x39E03080, 0x3C603B40, 0x3AE03C80, 0x30A036A0,
-	0x3B603A20, 0x3C803C40, 0x36403AE0, 0x3A4030C0, 0x3C403B60,
-	0x3AE03C80, 0x31003600, 0x3B803A60, 0x3C603C40, 0x35A03AE0,
-	0x3A803140, 0x3C403B80, 0x3AE03C60, 0x31803540, 0x3BA03A80,
-	0x3C603C40, 0x34E03AE0, 0x3AA031C0, 0x3C403BC0, 0x3AE03C40,
-	0x32003480, 0x3BC03AC0, 0x3C403C40, 0x34203AE0, 0x3AC03260,
-	0x3C403BE0, 0x3AE03C20, 0x32A033C0, 0x3C003AC0, 0x3C203C40,
-	0x33603AE0, 0x3AE03300, 0x3C403C00, 0x3AE03C00, 0x00003300,
-	0x38C030C0, 0x2B802B60, 0x30C038C0, 0x2BA03940, 0x38402B40,
-	0x39C030C0, 0x2B402BA0, 0x30C037C0, 0x2BC03A40, 0x37802B00,
-	0x3AC03100, 0x2AC02BE0, 0x31003700, 0x2BE03B40, 0x36802AC0,
-	0x3BC03100, 0x2A802C20, 0x31403600, 0x2C203C40, 0x35C02A40,
-	0x3CC03140, 0x2A402C20, 0x31803540, 0x2C203D40, 0x35002A00,
-	0x3DC03180, 0x29C02C60, 0x31C03480, 0x2C603E40, 0x34402980,
-	0x3F003200, 0x29402C40, 0x32003400, 0x2C803F80, 0x33802900,
-	0x3FC03240, 0x29002C60, 0x32803340, 0x2C402840, 0x330028C0,
-	0x288032C0, 0x28802C40, 0x000032C0, 0x38C030C0, 0x2B802B60,
-	0x30C038C0, 0x2BA03940, 0x38402B40, 0x39C030C0, 0x2B402BA0,
-	0x30C037C0, 0x2BC03A40, 0x37802B00, 0x3AC03100, 0x2AC02BE0,
-	0x31003700, 0x2BE03B40, 0x36802AC0, 0x3BC03100, 0x2A802C20,
-	0x31403600, 0x2C203C40, 0x35C02A40, 0x3CC03140, 0x2A402C20,
-	0x31803540, 0x2C203D40, 0x35002A00, 0x3DC03180, 0x29C02C60,
-	0x31C03480, 0x2C603E40, 0x34402980, 0x3F003200, 0x29402C40,
-	0x32003400, 0x2C803F80, 0x33802900, 0x3FC03240, 0x29002C60,
-	0x32803340, 0x2C402840, 0x330028C0, 0x288032C0, 0x28802C40,
-	0x000032C0,
-};
-
 typedef struct {
     char *name;
     int	clock;
@@ -266,18 +221,18 @@ const static tv_mode_t tv_modes[] = {
 
 	.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,
@@ -305,548 +260,472 @@ 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_ntsc,
+	.filter_table = filter_table,
     },
     {
-         .name		= "NTSC-443",
-	 .clock		= 107520,	
-	 .oversample	= TV_OVERSAMPLE_8X,
-	 .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,	    .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 4.4336180 actual 4.4336180 clock 107.52 */
-	 .dda1_inc	=   168,
-	 .dda2_inc	=   4093,	    .dda2_size		=  27456,
-	 .dda3_inc	=   525,	    .dda3_size		=  310,
-	 .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,
-	 },
-	.filter_table = filter_table_ntsc,
+	.name		= "NTSC-443",
+	.clock		= 107520,	
+	.oversample	= TV_OVERSAMPLE_8X,
+	.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,	    .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,
-	    .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,
-	    },
-	    .filter_table = filter_table_ntsc,
+	.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,
+	.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,
+	},
+	.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	=    135,
-	    .dda2_inc	=    16704,	    .dda2_size		=  27456,
-	    .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_ntsc,
+	.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-N",
-	    .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	= 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	=    135,
-	    .dda2_inc	=  23578,	.dda2_size	=  27648,
-	    .dda3_inc	=     134,	.dda3_size	=  625,
-	    .sc_reset   = TV_SC_RESET_EVERY_8,
-	    .pal_burst  = TRUE,
-
-	    .composite_levels = { .blank = 225, .black = 267, .burst = 118 },
-	    .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 = 139 },
-	    .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_ntsc,
+	/* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */
+	.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,    .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	= 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 = 225, .black = 267, .burst = 118 },
+	.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 = 139 },
+	.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",
-	    .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	= 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	=   4122,	.dda2_size	=  27648,
-	    .dda3_inc	=     67,	.dda3_size	=  625,
-	    .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,
-	    },
-	    .filter_table = filter_table_ntsc,
+	/* 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,
+	.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,
+	},
+	.filter_table = filter_table,
     },
     {
-	    .name       = "480p at 59.94Hz",
-	    .clock 	= 107520,	
-	    .oversample     = TV_OVERSAMPLE_4X,
-	    .component_only = 1,
-
-	    .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,
-
-	    .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,
-	    },
-	    .filter_table = filter_table_hres,
+	.name       = "480p at 59.94Hz",
+	.clock 	= 107520,	
+	.oversample     = TV_OVERSAMPLE_4X,
+	.component_only = 1,
+
+	.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,
     },
     {
-	    .name       = "480p at 60Hz",
-	    .clock 	= 107520,	
-	    .oversample     = TV_OVERSAMPLE_4X,
-	    .component_only = 1,
-
-	    .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,
-
-	    .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,
-	    },
-	    .filter_table = filter_table_hres,
+	.name       = "480p at 60Hz",
+	.clock 	= 107520,	
+	.oversample     = TV_OVERSAMPLE_4X,
+	.component_only = 1,
+
+	.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,
     },
     {
-	    .name       = "576p",
-	    .clock 	= 107520,	
-	    .oversample     = TV_OVERSAMPLE_4X,
-	    .component_only = 1,
-
-	    .hsync_end      = 64,               .hblank_end         = 139,
-	    .hblank_start   = 859,              .htotal             = 863,
-
-	    .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,
-
-	    .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,
-	    },
-	    .filter_table = filter_table_hres,
+	.name       = "576p",
+	.clock 	= 107520,	
+	.oversample     = TV_OVERSAMPLE_4X,
+	.component_only = 1,
+
+	.hsync_end      = 64,               .hblank_end         = 139,
+	.hblank_start   = 859,              .htotal             = 863,
+
+	.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,
+	.name       = "720p at 60Hz",
+	.clock		= 148800,	
+	.oversample     = TV_OVERSAMPLE_2X,
+	.component_only = 1,
 
-	    .hsync_end      = 80,               .hblank_end         = 300,
-	    .hblank_start   = 1580,             .htotal             = 1649,
+	.hsync_end      = 80,               .hblank_end         = 300,
+	.hblank_start   = 1580,             .htotal             = 1649,
 
-	    .progressive    = TRUE, 	    .trilevel_sync = TRUE,
+	.progressive    = TRUE, 	    .trilevel_sync = TRUE,
 
-	    .vsync_start_f1 = 10,               .vsync_start_f2     = 10,
-	    .vsync_len      = 10,
+	.vsync_start_f1 = 10,               .vsync_start_f2     = 10,
+	.vsync_len      = 10,
 
-	    .veq_ena        = FALSE,
+	.veq_ena        = FALSE,
 
-	    .vi_end_f1      = 29,               .vi_end_f2          = 29,
-	    .nbr_end        = 719,
+	.vi_end_f1      = 29,               .vi_end_f2          = 29,
+	.nbr_end        = 719,
 
-	    .burst_ena      = FALSE,
+	.burst_ena      = FALSE,
 
-	    .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,
-	    },
-	    .filter_table = filter_table_hres,
+	.filter_table = filter_table,
     },
     {
-	    .name       = "720p at 59.94Hz",
-	    .clock		= 148800,	
-	    .oversample     = TV_OVERSAMPLE_2X,
-	    .component_only = 1,
+	.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,
+	.hsync_end      = 80,               .hblank_end         = 300,
+	.hblank_start   = 1580,             .htotal             = 1651,
 
-	    .progressive    = TRUE, 	    .trilevel_sync = TRUE,
+	.progressive    = TRUE, 	    .trilevel_sync = TRUE,
 
-	    .vsync_start_f1 = 10,               .vsync_start_f2     = 10,
-	    .vsync_len      = 10,
+	.vsync_start_f1 = 10,               .vsync_start_f2     = 10,
+	.vsync_len      = 10,
 
-	    .veq_ena        = FALSE,
+	.veq_ena        = FALSE,
 
-	    .vi_end_f1      = 29,               .vi_end_f2          = 29,
-	    .nbr_end        = 719,
+	.vi_end_f1      = 29,               .vi_end_f2          = 29,
+	.nbr_end        = 719,
 
-	    .burst_ena      = FALSE,
+	.burst_ena      = FALSE,
 
-	    .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,
-	    },
-	    .filter_table = filter_table_hres,
+	.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,
-
-	    .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,
-	    },
-	    .filter_table = filter_table_hres,
-	    .max_srcw = 800
+	.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,
+	.name       = "1080i at 50Hz",
+	.clock		= 148800,	
+	.oversample     = TV_OVERSAMPLE_2X,
+	.component_only = 1,
 
-	    .hsync_end      = 88,               .hblank_end         = 235,
-	    .hblank_start   = 2155,             .htotal             = 2639,
+	.hsync_end      = 88,               .hblank_end         = 235,
+	.hblank_start   = 2155,             .htotal             = 2639,
 
-	    .progressive    = FALSE, 	    .trilevel_sync = TRUE,
+	.progressive    = FALSE, 	    .trilevel_sync = TRUE,
 
-	    .vsync_start_f1 = 4,              .vsync_start_f2     = 5,
-	    .vsync_len      = 10,
+	.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,
+	.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,
+	.vi_end_f1      = 21,           .vi_end_f2          = 22,
+	.nbr_end        = 539,
 
-	    .burst_ena      = FALSE,
+	.burst_ena      = FALSE,
 
-	    .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,
-	    },
-	    .filter_table = filter_table_hres,
+	.filter_table = filter_table,
     },
     {
-	    .name       = "1080i at 60Hz",
-	    .clock		= 148800,	
-	    .oversample     = TV_OVERSAMPLE_2X,
-	    .component_only = 1,
+	.name       = "1080i at 60Hz",
+	.clock		= 148800,	
+	.oversample     = TV_OVERSAMPLE_2X,
+	.component_only = 1,
 
-	    .hsync_end      = 88,               .hblank_end         = 235,
-	    .hblank_start   = 2155,             .htotal             = 2199,
+	.hsync_end      = 88,               .hblank_end         = 235,
+	.hblank_start   = 2155,             .htotal             = 2199,
 
-	    .progressive    = FALSE, 	    .trilevel_sync = TRUE,
+	.progressive    = FALSE, 	    .trilevel_sync = TRUE,
 
-	    .vsync_start_f1 = 4,               .vsync_start_f2     = 5,
-	    .vsync_len      = 10,
+	.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,
+	.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,
+	.vi_end_f1      = 21,               .vi_end_f2          = 22,
+	.nbr_end        = 539,
 
-	    .burst_ena      = FALSE,
+	.burst_ena      = FALSE,
 
-	    .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,
-	    },
-	    .filter_table = filter_table_hres,
+	.filter_table = filter_table,
     },
     {
-	    .name       = "1080i at 59.94Hz",
-	    .clock		= 148800,	
-	    .oversample     = TV_OVERSAMPLE_2X,
-	    .component_only = 1,
+	.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,
+	.hsync_end      = 88,               .hblank_end         = 235,
+	.hblank_start   = 2155,             .htotal             = 2200,
 
-	    .progressive    = FALSE, 	    .trilevel_sync = TRUE,
+	.progressive    = FALSE, 	    .trilevel_sync = TRUE,
 
-	    .vsync_start_f1 = 4,            .vsync_start_f2    = 5,
-	    .vsync_len      = 10,
+	.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,
+	.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,
+	.vi_end_f1      = 21,           .vi_end_f2         	= 22,
+	.nbr_end        = 539,
 
-	    .burst_ena      = FALSE,
+	.burst_ena      = FALSE,
 
-	    .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,
-	    },
-	    .filter_table = filter_table_hres,
+	.filter_table = filter_table,
     },
 };
 
@@ -855,165 +734,165 @@ static const video_levels_t component_le
 };
 
 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,
+    .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,
+    .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)
 {
-	ScrnInfoPtr pScrn = output->scrn;
-	I830Ptr pI830 = I830PTR(pScrn);
+    ScrnInfoPtr pScrn = output->scrn;
+    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;
-	}
+    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(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;
-	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);
-	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_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));
+    ScrnInfoPtr		    pScrn = output->scrn;
+    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_DAC = INREG(TV_DAC);
-	dev_priv->save_TV_CTL = INREG(TV_CTL);
+    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_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);
 }
 
 static void
 i830_tv_restore(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;
-	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);
-	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_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);
-
-	{
-		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);
-		}
+    ScrnInfoPtr		    pScrn = output->scrn;
+    I830Ptr		    pI830 = I830PTR(pScrn);
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    struct i830_tv_priv	    *dev_priv = intel_output->dev_priv;
+    int			    i;
 
-		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 and TV_WIN_POS */
-		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));
+    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);
+    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_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);
+
+    {
+	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);
 	}
 
-	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(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]);
+    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);
+    OUTREG(TV_DAC, dev_priv->save_TV_DAC);
+    OUTREG(TV_CTL, dev_priv->save_TV_CTL);
 }
 
 static int
@@ -1050,271 +929,271 @@ i830_tv_mode_fixup(xf86OutputPtr output,
 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;
+    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;
+    CARD16  ret;
 
-	ret = (f * (1 << 9));
-	return ret;
+    ret = (f * (1 << 9));
+    return ret;
 }
 
 static void
 i830_tv_mode_set(xf86OutputPtr output, DisplayModePtr mode,
 		DisplayModePtr adjusted_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;
-	const tv_mode_t	    *tv_mode;
-	CARD32		    tv_ctl;
-	CARD32		    hctl1, hctl2, hctl3;
-	CARD32		    vctl1, vctl2, vctl3, vctl4, vctl5, vctl6, vctl7;
-	CARD32		    scctl1, scctl2, scctl3;
-	int			    i, j;
-	const video_levels_t	*video_levels;
-	const color_conversion_t	*color_conversion;
-	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;	
-	}
+    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;
+    const tv_mode_t	    *tv_mode;
+    CARD32		    tv_ctl;
+    CARD32		    hctl1, hctl2, hctl3;
+    CARD32		    vctl1, vctl2, vctl3, vctl4, vctl5, vctl6, vctl7;
+    CARD32		    scctl1, scctl2, scctl3;
+    int			    i, j;
+    const video_levels_t	*video_levels;
+    const color_conversion_t	*color_conversion;
+    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;
+    }
+    hctl1 = (tv_mode->hsync_end << TV_HSYNC_END_SHIFT) |
+	(tv_mode->htotal << TV_HTOTAL_SHIFT);
 
-	tv_ctl = 0;
+    hctl2 = (tv_mode->hburst_start << 16) |
+	(tv_mode->hburst_len << TV_HBURST_LEN_SHIFT);
 
-	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);
+    if (burst_ena)
+	hctl2 |= TV_BURST_ENA;
 
-	hctl2 = (tv_mode->hburst_start << 16) |
-		(tv_mode->hburst_len << TV_HBURST_LEN_SHIFT);
-	if (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);
-
-	if (intel_crtc->pipe == 1)
-		tv_ctl |= TV_ENC_PIPEB_SELECT;
-	tv_ctl |= tv_mode->oversample;
+    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);
+
+    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;
+
+    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;
+
+    scctl2 = tv_mode->dda2_size << TV_SCDDA2_SIZE_SHIFT |
+	tv_mode->dda2_inc << TV_SCDDA2_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)
+	tv_ctl |= TV_ENC_C0_FIX | TV_ENC_SDP_FIX;
+
+    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_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, 0x10606000);
+    OUTREG(TV_CLR_LEVEL, ((video_levels->black << TV_BLACK_LEVEL_SHIFT) |
+		(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)
-		tv_ctl |= TV_PROGRESSIVE;
-	if (tv_mode->trilevel_sync)
-		tv_ctl |= TV_TRILEVEL_SYNC;
-	if (tv_mode->pal_burst)
-		tv_ctl |= TV_PAL_BURST;
-	if (tv_mode->oversample == TV_OVERSAMPLE_8X)
-		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;
-
-	scctl2 = tv_mode->dda2_size << TV_SCDDA2_SIZE_SHIFT |
-		tv_mode->dda2_inc << TV_SCDDA2_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)
-		tv_ctl |= TV_ENC_C0_FIX | TV_ENC_SDP_FIX;
-
-
-	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_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, 0x10606000);
-	OUTREG(TV_CLR_LEVEL, ((video_levels->black << TV_BLACK_LEVEL_SHIFT) |
-				(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);
-		}
+	    ysize = tv_mode->nbr_end + 1;
+	else
+	    ysize = 2*tv_mode->nbr_end + 1;
 
-		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 and TV_WIN_POS */
-		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), tv_mode->filter_table[j++]);
-	for (i = 0; i < 60; 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), tv_mode->filter_table[j++]);
-	for (i = 0; i < 43; i++)
-		OUTREG(TV_V_CHROMA_0 + (i<<2), tv_mode->filter_table[j++]);
-	OUTREG(TV_DAC, 0);
-	OUTREG(TV_CTL, tv_ctl);
+	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), tv_mode->filter_table[j++]);
+    for (i = 0; i < 60; 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), tv_mode->filter_table[j++]);
+    for (i = 0; i < 43; 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 = 107520,
-		.HDisplay   = 1280,
-		.HSyncStart = 1368,
-		.HSyncEnd   = 1496,
-		.HTotal     = 1712,
-
-		.VDisplay   = 1024,
-		.VSyncStart = 1027,
-		.VSyncEnd   = 1034,
-		.VTotal     = 1104,
-		.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
+    },
 };
 
 /**
@@ -1329,68 +1208,68 @@ static void
 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;
+    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 |
+		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);
-	/*
-	 * 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 |
-				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,
-				"No TV connection detected\n");
-		type = TV_TYPE_NONE;
-	}
+	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,
+		"No TV connection detected\n");
+	type = TV_TYPE_NONE;
+    }
 
-	dev_priv->type = type;
+    dev_priv->type = type;
 }
 
 /**
@@ -1415,7 +1294,6 @@ 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, 0, 0);
         }
         i830_tv_detect_type (crtc, output);
         i830ReleaseLoadDetectPipe (output);
@@ -1432,16 +1310,16 @@ i830_tv_detect(xf86OutputPtr output)
 }
 
 struct input_res {
-	char *name;
-	int w, h;	
-}input_res_table[] = 
+    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}
+	{"1280x720", 1280, 720},
 };
 
 /**
@@ -1454,124 +1332,127 @@ struct input_res {
 static DisplayModePtr
 i830_tv_get_modes(xf86OutputPtr output)
 {
-	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;
-			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;
-		} 
-	}
+    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 ret;
+    return ret;
 }
 
 static void
 i830_tv_destroy (xf86OutputPtr output)
 {
-	if (output->driver_private)
-		xfree (output->driver_private);
+    if (output->driver_private)
+	xfree (output->driver_private);
 }
 
 static const xf86OutputFuncsRec i830_tv_output_funcs = {
-	.dpms = i830_tv_dpms,
-	.save = i830_tv_save,
-	.restore = i830_tv_restore,
-	.mode_valid = i830_tv_mode_valid,
-	.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
+    .dpms = i830_tv_dpms,
+    .save = i830_tv_save,
+    .restore = i830_tv_restore,
+    .mode_valid = i830_tv_mode_valid,
+    .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
 };
 
 void
 i830_tv_init(ScrnInfoPtr pScrn)
 {
-	I830Ptr		    pI830 = I830PTR(pScrn);
-	xf86OutputPtr	    output;
-	I830OutputPrivatePtr    intel_output;
-	struct i830_tv_priv	    *dev_priv;
-	CARD32		    tv_dac_on, tv_dac_off, save_tv_dac;
+    I830Ptr		    pI830 = I830PTR(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;
+    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)
+	    (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);
@@ -1581,7 +1462,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 6d9757e466863594300c83f3806fd4376bea0504 (from b3633506dcd4fd58f0f9519cd67f6e75d6fb2042)
Author: Zou Nanhai <nanhai.zou at intel.com>
Date:   Mon Feb 5 14:59:53 2007 +0800

    Fix hang when TV is not connect.

diff --git a/src/i830_tv.c b/src/i830_tv.c
index 4c55b35..6131b28 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -943,6 +943,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);
@@ -967,8 +972,6 @@ i830_tv_restore(xf86OutputPtr output)
 	OUTREG(TV_CLR_LEVEL, dev_priv->save_TV_CLR_LEVEL);
 
 	{
-		xf86CrtcPtr	    crtc = output->crtc;
-		I830CrtcPrivatePtr	    intel_crtc = crtc->driver_private;
 		int pipeconf_reg = (intel_crtc->pipe == 0)?PIPEACONF:PIPEBCONF;
 		int dspcntr_reg = (intel_crtc->pipe == 0)?DSPACNTR : DSPBCNTR;
 		int pipeconf = INREG(pipeconf_reg);
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 b3633506dcd4fd58f0f9519cd67f6e75d6fb2042 (from 380129a17c61c783d77a87685ad5333e8b1c253c)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Fri Feb 2 11:35:44 2007 +0800

    Add Intel 965GM chipset support

diff --git a/src/common.h b/src/common.h
index 91e31b5..cc68239 100644
--- a/src/common.h
+++ b/src/common.h
@@ -314,6 +314,11 @@ extern int I810_DEBUG;
 #define PCI_CHIP_I946_GZ_BRIDGE 	0x2970
 #endif
 
+#ifndef PCI_CHIP_I965_GM
+#define PCI_CHIP_I965_GM        0x2A02
+#define PCI_CHIP_I965_GM_BRIDGE 0x2A00
+#endif
+
 #define IS_I810(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I810 ||	\
 			pI810->PciInfo->chipType == PCI_CHIP_I810_DC100 || \
 			pI810->PciInfo->chipType == PCI_CHIP_I810_E)
@@ -329,10 +334,11 @@ extern int I810_DEBUG;
 #define IS_I915GM(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I915_GM)
 #define IS_I945G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I945_G)
 #define IS_I945GM(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I945_GM)
-#define IS_I965G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I965_G || pI810->PciInfo->chipType == PCI_CHIP_I965_G_1 || pI810->PciInfo->chipType == PCI_CHIP_I965_Q || pI810->PciInfo->chipType == PCI_CHIP_I946_GZ)
+#define IS_I965GM(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I965_GM)
+#define IS_I965G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I965_G || pI810->PciInfo->chipType == PCI_CHIP_I965_G_1 || pI810->PciInfo->chipType == PCI_CHIP_I965_Q || pI810->PciInfo->chipType == PCI_CHIP_I946_GZ || pI810->PciInfo->chipType == PCI_CHIP_I965_GM)
 #define IS_I9XX(pI810) (IS_I915G(pI810) || IS_I915GM(pI810) || IS_I945G(pI810) || IS_I945GM(pI810) || IS_I965G(pI810))
 
-#define IS_MOBILE(pI810) (IS_I830(pI810) || IS_I85X(pI810) || IS_I915GM(pI810) || IS_I945GM(pI810))
+#define IS_MOBILE(pI810) (IS_I830(pI810) || IS_I85X(pI810) || IS_I915GM(pI810) || IS_I945GM(pI810) || IS_I965GM(pI810))
 
 #define GTT_PAGE_SIZE			KB(4)
 #define ROUND_TO(x, y)			(((x) + (y) - 1) / (y) * (y))
diff --git a/src/i810_driver.c b/src/i810_driver.c
index e7c8507..ab3a200 100644
--- a/src/i810_driver.c
+++ b/src/i810_driver.c
@@ -144,6 +144,7 @@ static SymTabRec I810Chipsets[] = {
    {PCI_CHIP_I965_G_1,		"965G"},
    {PCI_CHIP_I965_Q,		"965Q"},
    {PCI_CHIP_I946_GZ,		"946GZ"},
+   {PCI_CHIP_I965_GM,		"965GM"},
    {-1,				NULL}
 };
 
@@ -167,6 +168,7 @@ static PciChipsets I810PciChipsets[] = {
    {PCI_CHIP_I965_G_1,		PCI_CHIP_I965_G_1,	RES_SHARED_VGA},
    {PCI_CHIP_I965_Q,		PCI_CHIP_I965_Q,	RES_SHARED_VGA},
    {PCI_CHIP_I946_GZ,		PCI_CHIP_I946_GZ,	RES_SHARED_VGA},
+   {PCI_CHIP_I965_GM,		PCI_CHIP_I965_GM,	RES_SHARED_VGA},
    {-1,				-1, RES_UNDEFINED }
 };
 
@@ -601,6 +603,7 @@ I810Probe(DriverPtr drv, int flags)
 	    case PCI_CHIP_I965_G_1:
 	    case PCI_CHIP_I965_Q:
 	    case PCI_CHIP_I946_GZ:
+	    case PCI_CHIP_I965_GM:
     	       xf86SetEntitySharable(usedChips[i]);
 
     	       /* Allocate an entity private if necessary */		
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 0f66311..701abd7 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -232,6 +232,7 @@ static SymTabRec I830Chipsets[] = {
    {PCI_CHIP_I965_G_1,		"965G"},
    {PCI_CHIP_I965_Q,		"965Q"},
    {PCI_CHIP_I946_GZ,		"946GZ"},
+   {PCI_CHIP_I965_GM,		"965GM"},
    {-1,				NULL}
 };
 
@@ -249,6 +250,7 @@ static PciChipsets I830PciChipsets[] = {
    {PCI_CHIP_I965_G_1,		PCI_CHIP_I965_G_1,	RES_SHARED_VGA},
    {PCI_CHIP_I965_Q,		PCI_CHIP_I965_Q,	RES_SHARED_VGA},
    {PCI_CHIP_I946_GZ,		PCI_CHIP_I946_GZ,	RES_SHARED_VGA},
+   {PCI_CHIP_I965_GM,		PCI_CHIP_I965_GM,	RES_SHARED_VGA},
    {-1,				-1,			RES_UNDEFINED}
 };
 
@@ -1045,6 +1047,9 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    case PCI_CHIP_I946_GZ:
       chipname = "946GZ";
       break;
+   case PCI_CHIP_I965_GM:
+      chipname = "965GM";
+      break;
    default:
       chipname = "unknown chipset";
       break;
diff-tree 380129a17c61c783d77a87685ad5333e8b1c253c (from f7489bbec150349bf03bea8d9d55451dbc92bfc2)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Fri Feb 2 11:33:46 2007 +0800

    Revert original crestline pci id patch

diff --git a/src/common.h b/src/common.h
index 92dc2cf..91e31b5 100644
--- a/src/common.h
+++ b/src/common.h
@@ -314,11 +314,6 @@ extern int I810_DEBUG;
 #define PCI_CHIP_I946_GZ_BRIDGE 	0x2970
 #endif
 
-#ifndef PCI_CHIP_CRESTLINE		//XXX: fix with official name
-#define PCI_CHIP_CRESTLINE		0x2A02
-#define PCI_CHIP_CRESTLINE_BRIDGE 	0x2A00
-#endif
-
 #define IS_I810(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I810 ||	\
 			pI810->PciInfo->chipType == PCI_CHIP_I810_DC100 || \
 			pI810->PciInfo->chipType == PCI_CHIP_I810_E)
@@ -334,11 +329,10 @@ extern int I810_DEBUG;
 #define IS_I915GM(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I915_GM)
 #define IS_I945G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I945_G)
 #define IS_I945GM(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I945_GM)
-#define IS_I965G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I965_G || pI810->PciInfo->chipType == PCI_CHIP_I965_G_1 || pI810->PciInfo->chipType == PCI_CHIP_I965_Q || pI810->PciInfo->chipType == PCI_CHIP_I946_GZ || pI810->PciInfo->chipType == PCI_CHIP_CRESTLINE)
+#define IS_I965G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I965_G || pI810->PciInfo->chipType == PCI_CHIP_I965_G_1 || pI810->PciInfo->chipType == PCI_CHIP_I965_Q || pI810->PciInfo->chipType == PCI_CHIP_I946_GZ)
 #define IS_I9XX(pI810) (IS_I915G(pI810) || IS_I915GM(pI810) || IS_I945G(pI810) || IS_I945GM(pI810) || IS_I965G(pI810))
-#define IS_CRESTLINE(pI810) (pI810->PciInfo->chipType == PCI_CHIP_CRESTLINE) // XXX: IS_965GM ?
 
-#define IS_MOBILE(pI810) (IS_I830(pI810) || IS_I85X(pI810) || IS_I915GM(pI810) || IS_I945GM(pI810) || IS_CRESTLINE(pI810))
+#define IS_MOBILE(pI810) (IS_I830(pI810) || IS_I85X(pI810) || IS_I915GM(pI810) || IS_I945GM(pI810))
 
 #define GTT_PAGE_SIZE			KB(4)
 #define ROUND_TO(x, y)			(((x) + (y) - 1) / (y) * (y))
diff --git a/src/i810_driver.c b/src/i810_driver.c
index 74100cd..e7c8507 100644
--- a/src/i810_driver.c
+++ b/src/i810_driver.c
@@ -144,7 +144,6 @@ static SymTabRec I810Chipsets[] = {
    {PCI_CHIP_I965_G_1,		"965G"},
    {PCI_CHIP_I965_Q,		"965Q"},
    {PCI_CHIP_I946_GZ,		"946GZ"},
-   {PCI_CHIP_CRESTLINE,		"Crestline"},
    {-1,				NULL}
 };
 
@@ -168,7 +167,6 @@ static PciChipsets I810PciChipsets[] = {
    {PCI_CHIP_I965_G_1,		PCI_CHIP_I965_G_1,	RES_SHARED_VGA},
    {PCI_CHIP_I965_Q,		PCI_CHIP_I965_Q,	RES_SHARED_VGA},
    {PCI_CHIP_I946_GZ,		PCI_CHIP_I946_GZ,	RES_SHARED_VGA},
-   {PCI_CHIP_CRESTLINE,		PCI_CHIP_CRESTLINE,	RES_SHARED_VGA},
    {-1,				-1, RES_UNDEFINED }
 };
 
@@ -603,7 +601,6 @@ I810Probe(DriverPtr drv, int flags)
 	    case PCI_CHIP_I965_G_1:
 	    case PCI_CHIP_I965_Q:
 	    case PCI_CHIP_I946_GZ:
-	    case PCI_CHIP_CRESTLINE:
     	       xf86SetEntitySharable(usedChips[i]);
 
     	       /* Allocate an entity private if necessary */		
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 12b72ac..0f66311 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -232,7 +232,6 @@ static SymTabRec I830Chipsets[] = {
    {PCI_CHIP_I965_G_1,		"965G"},
    {PCI_CHIP_I965_Q,		"965Q"},
    {PCI_CHIP_I946_GZ,		"946GZ"},
-   {PCI_CHIP_CRESTLINE,		"Crestline"},
    {-1,				NULL}
 };
 
@@ -250,7 +249,6 @@ static PciChipsets I830PciChipsets[] = {
    {PCI_CHIP_I965_G_1,		PCI_CHIP_I965_G_1,	RES_SHARED_VGA},
    {PCI_CHIP_I965_Q,		PCI_CHIP_I965_Q,	RES_SHARED_VGA},
    {PCI_CHIP_I946_GZ,		PCI_CHIP_I946_GZ,	RES_SHARED_VGA},
-   {PCI_CHIP_CRESTLINE,		PCI_CHIP_CRESTLINE,	RES_SHARED_VGA},
    {-1,				-1,			RES_UNDEFINED}
 };
 
@@ -1047,9 +1045,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    case PCI_CHIP_I946_GZ:
       chipname = "946GZ";
       break;
-   case PCI_CHIP_CRESTLINE:
-      chipname = "Crestline";
-      break;
    default:
       chipname = "unknown chipset";
       break;
diff-tree f7489bbec150349bf03bea8d9d55451dbc92bfc2 (from parents)
Merge: f1285ecb72e807ac10db398fa983bf69d4154d97 ae6d3585a4d96aa4dc05ca8563cebfa7796324ef
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Fri Feb 2 11:26:57 2007 +0800

    Merge branch 'modesetting' into crestline
    
    Conflicts:
    
    	src/i830_display.c
    	src/i830_tv.c
    	src/i830_xf86Crtc.c

diff --cc src/i830_tv.c
index 48167f6,79b6ae8..4c55b35
@@@ -1399,48 -1052,35 +1399,48 @@@
  static xf86OutputStatus
  i830_tv_detect(xf86OutputPtr output)
  {
- 	xf86CrtcPtr		    crtc;
- 	DisplayModeRec	    mode;
- 	I830OutputPrivatePtr    intel_output = output->driver_private;
- 	struct i830_tv_priv	    *dev_priv = intel_output->dev_priv;
+     xf86CrtcPtr		    crtc;
+     DisplayModeRec	    mode;
+     I830OutputPrivatePtr    intel_output = output->driver_private;
+     struct i830_tv_priv	    *dev_priv = intel_output->dev_priv;
  
- 	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);
- 			i830PipeSetMode (crtc, &mode, FALSE);
- 		}
- 		i830_tv_detect_type (crtc, output);
- 		i830ReleaseLoadDetectPipe (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);
++            xf86CrtcSetMode (crtc, &mode, RR_Rotate_0, 0, 0);
++        }
++        i830_tv_detect_type (crtc, output);
++        i830ReleaseLoadDetectPipe (output);
+     }
 -    
 +
- 	switch (dev_priv->type) {
- 		case TV_TYPE_NONE:
- 			return XF86OutputStatusDisconnected;
- 		case TV_TYPE_UNKNOWN:
- 			return XF86OutputStatusUnknown;
- 		default:
- 			return XF86OutputStatusConnected;
- 	}
+     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.
   *
diff-tree ae6d3585a4d96aa4dc05ca8563cebfa7796324ef (from parents)
Merge: 6d549ed280d3fcf3fe611b095d9f8adc0196bfb6 1ba45a3fcd40aaf4d373447fb9f252ca053f9105
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Fri Feb 2 11:21:59 2007 +0800

    Merge branch 'modesetting' of git://proxy.ims.intel.com:9419/git/xorg/driver/xf86-video-intel into modesetting

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 f1285ecb72e807ac10db398fa983bf69d4154d97 (from 0620a7650f758652d05a0c25d159587f641aaf3e)
Author: Zou Nan hai <nanhai.zou at intel.com>
Date:   Wed Jan 31 14:58:08 2007 +0800

      tune

diff --git a/src/i830_tv.c b/src/i830_tv.c
index ccffe5b..48167f6 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -148,51 +148,6 @@ static const CARD32 filter_table_hres[] 
     0x28003100, 0x28002F00, 0x00003100,
 };
 
-static const CARD32 filter_table_pal[] = {
-	0xB0603000, 0x1920B3E0, 0xB3E01900, 0x3000B060, 0xB380B080,
-	0x18A01980, 0xB040B440, 0xB0A03000, 0x19D0B300, 0xB4801840,
-	0x3000B020, 0xB260B0E0, 0x2FE01A10, 0x3000B4C0, 0xB1003000,
-	0x1A60B1C0, 0xB4E02F00, 0x30003020, 0xB120B140, 0x2E401AB0,
-	0x3020B500, 0xB1803000, 0x1B00B060, 0xB5202D60, 0x30003040,
-	0x3080B1A0, 0x2CA01B30, 0x3040B520, 0xB1E03020, 0x1B703160,
-	0xB5202BC0, 0x30203040, 0x3260B220, 0x2B001B98, 0x3060B520,
-	0xB2603020, 0x1BD03360, 0xB5002A20, 0x30203060, 0x3480B2A0,
-	0x29601BF0, 0x3060B4E0, 0xB2E03020, 0x1C1835C0, 0xB4C02880,
-	0x30403060, 0x3700B340, 0x3F801C30, 0x3060B4A0, 0xB3803040,
-	0x1C403840, 0xB4603E00, 0x30403060, 0x39A0B3C0, 0x3C801C50,
-	0x3040B420, 0xB4003040, 0x1C603B00, 0xB4003B00, 0x00003040,
-	0x36E03640, 0x3CA03960, 0x39603CA0, 0x364036E0, 0x398036E0,
-	0x3C803CC0, 0x36E03940, 0x37003640, 0x3CC039A0, 0x39203C80,
-	0x364036C0, 0x39C03700, 0x3C603CC0, 0x36C03920, 0x37203640,
-	0x3CC039E0, 0x39003C40, 0x364036C0, 0x3A003720, 0x3C403CE0,
-	0x36A038E0, 0x37203640, 0x3D203A00, 0x38C03C20, 0x364036A0,
-	0x3A203740, 0x3C003D20, 0x36A038A0, 0x37403640, 0x3D003A40,
-	0x38A03C00, 0x364036A0, 0x3A603760, 0x3BE03D20, 0x36803880,
-	0x37603660, 0x3D203A80, 0x38603BC0, 0x36603680, 0x3AA03780,
-	0x3BA03D20, 0x36803840, 0x37803660, 0x3D003AC0, 0x38403BA0,
-	0x36603680, 0x3AE037A0, 0x3B803D00, 0x36803820, 0x37C03660,
-	0x3D203B00, 0x38003B60, 0x36603660, 0x3B0037C0, 0x3B403D40,
-	0x36603800, 0x37E03660, 0x3D403B20, 0x37E03B20, 0x00003660,
-	0x38C030C0, 0x2B802B60, 0x30C038C0, 0x2BA03940, 0x38402B40,
-	0x39C030C0, 0x2B402BA0, 0x30C037C0, 0x2BC03A40, 0x37802B00,
-	0x3AC03100, 0x2AC02BE0, 0x31003700, 0x2BE03B40, 0x36802AC0,
-	0x3BC03100, 0x2A802C20, 0x31403600, 0x2C203C40, 0x35C02A40,
-	0x3CC03140, 0x2A402C20, 0x31803540, 0x2C203D40, 0x35002A00,
-	0x3DC03180, 0x29C02C60, 0x31C03480, 0x2C603E40, 0x34402980,
-	0x3F003200, 0x29402C40, 0x32003400, 0x2C803F80, 0x33802900,
-	0x3FC03240, 0x29002C60, 0x32803340, 0x2C402840, 0x330028C0,
-	0x288032C0, 0x28802C40, 0x000032C0, 0x38C030C0, 0x2B802B60,
-	0x30C038C0, 0x2BA03940, 0x38402B40, 0x39C030C0, 0x2B402BA0,
-	0x30C037C0, 0x2BC03A40, 0x37802B00, 0x3AC03100, 0x2AC02BE0,
-	0x31003700, 0x2BE03B40, 0x36802AC0, 0x3BC03100, 0x2A802C20,
-	0x31403600, 0x2C203C40, 0x35C02A40, 0x3CC03140, 0x2A402C20,
-	0x31803540, 0x2C203D40, 0x35002A00, 0x3DC03180, 0x29C02C60,
-	0x31C03480, 0x2C603E40, 0x34402980, 0x3F003200, 0x29402C40,
-	0x32003400, 0x2C803F80, 0x33802900, 0x3FC03240, 0x29002C60,
-	0x32803340, 0x2C402840, 0x330028C0, 0x288032C0, 0x28802C40,
-	0x000032C0,
-};
-
 static const CARD32 filter_table_ntsc[] = {
 	0xB0603000, 0x1920B3E0, 0xB3E01900, 0x3000B060, 0xB380B080,
 	0x18A01980, 0xB040B440, 0xB0A03000, 0x19D0B300, 0xB4801840,
@@ -499,7 +454,7 @@ 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_pal,
+	    .filter_table = filter_table_ntsc,
     },
     {
 	    /* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */
@@ -550,7 +505,7 @@ 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_pal,
+	    .filter_table = filter_table_ntsc,
     },
     {
 	    /* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */
@@ -601,7 +556,7 @@ 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_pal,
+	    .filter_table = filter_table_ntsc,
     },
     {
 	    .name       = "480p at 59.94Hz",
diff-tree 0620a7650f758652d05a0c25d159587f641aaf3e (from 12441e217a1968dea3a6b0646b6c5d0e2ede0e7e)
Author: Zou Nan hai <nanhai.zou at intel.com>
Date:   Wed Jan 31 11:21:11 2007 +0800

      fix

diff --git a/src/i830_tv.c b/src/i830_tv.c
index 56b5450..ccffe5b 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -800,7 +800,6 @@ const static tv_mode_t tv_modes[] = {
 	    .filter_table = filter_table_hres,
 	    .max_srcw = 800
     },
-/*
     {
 	    .name       = "1080i at 50Hz",
 	    .clock		= 148800,	
@@ -894,7 +893,6 @@ const static tv_mode_t tv_modes[] = {
 	    },
 	    .filter_table = filter_table_hres,
     },
-*/
 };
 
 static const video_levels_t component_level = {
diff-tree 12441e217a1968dea3a6b0646b6c5d0e2ede0e7e (from 726c7dd89627409820ee5cf9bf657d5a926b3648)
Author: Zou Nan hai <nanhai.zou at intel.com>
Date:   Wed Jan 31 11:20:23 2007 +0800

      add 720p at 50Hz,
      however 720p in this freq seems to not support src width,
      hactive > 800, so skip those inputs.

diff --git a/src/i830_tv.c b/src/i830_tv.c
index 1452c5c..56b5450 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -266,6 +266,7 @@ 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;
 
 
@@ -769,6 +770,38 @@ const static tv_mode_t tv_modes[] = {
 	    .filter_table = filter_table_hres,
     },
     {
+	    .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,
+
+	    .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,
+	    },
+	    .filter_table = filter_table_hres,
+	    .max_srcw = 800
+    },
+/*
+    {
 	    .name       = "1080i at 50Hz",
 	    .clock		= 148800,	
 	    .oversample     = TV_OVERSAMPLE_2X,
@@ -800,7 +833,7 @@ const static tv_mode_t tv_modes[] = {
 	    .filter_table = filter_table_hres,
     },
     {
-	    .name       = "1080i at 30Hz",
+	    .name       = "1080i at 60Hz",
 	    .clock		= 148800,	
 	    .oversample     = TV_OVERSAMPLE_2X,
 	    .component_only = 1,
@@ -831,7 +864,7 @@ const static tv_mode_t tv_modes[] = {
 	    .filter_table = filter_table_hres,
     },
     {
-	    .name       = "1080i at 29.97Hz",
+	    .name       = "1080i at 59.94Hz",
 	    .clock		= 148800,	
 	    .oversample     = TV_OVERSAMPLE_2X,
 	    .component_only = 1,
@@ -861,6 +894,7 @@ const static tv_mode_t tv_modes[] = {
 	    },
 	    .filter_table = filter_table_hres,
     },
+*/
 };
 
 static const video_levels_t component_level = {
@@ -1281,8 +1315,7 @@ i830_tv_mode_set(xf86OutputPtr output, D
 		i830WaitForVblank(pScrn);
 
 		/* Filter ctl must be set before TV_WIN_SIZE and TV_WIN_POS */
-		OUTREG(TV_FILTER_CTL_1, TV_AUTO_SCALE);
-
+		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;
@@ -1490,7 +1523,8 @@ i830_tv_get_modes(xf86OutputPtr output)
 			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;
 			mode_ptr = xnfcalloc(1, sizeof(DisplayModeRec));
 			mode_ptr->name = xnfalloc(strlen(tv_mode->name) + 
 					strlen(input->name) + 4);
diff-tree 726c7dd89627409820ee5cf9bf657d5a926b3648 (from 5a67f3d3690903a181ca854d060cfa8b4c2aca26)
Author: Zou Nan hai <nanhai.zou at intel.com>
Date:   Wed Jan 31 10:34:39 2007 +0800

       TV fixes.

diff --git a/src/i830_tv.c b/src/i830_tv.c
index 1b75e87..1452c5c 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -93,12 +93,157 @@ typedef struct {
     float   rv, gv, bv, av;
 } color_conversion_t;
 
+static const CARD32 filter_table_hres[] = {
+    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,
+};
+
+static const CARD32 filter_table_pal[] = {
+	0xB0603000, 0x1920B3E0, 0xB3E01900, 0x3000B060, 0xB380B080,
+	0x18A01980, 0xB040B440, 0xB0A03000, 0x19D0B300, 0xB4801840,
+	0x3000B020, 0xB260B0E0, 0x2FE01A10, 0x3000B4C0, 0xB1003000,
+	0x1A60B1C0, 0xB4E02F00, 0x30003020, 0xB120B140, 0x2E401AB0,
+	0x3020B500, 0xB1803000, 0x1B00B060, 0xB5202D60, 0x30003040,
+	0x3080B1A0, 0x2CA01B30, 0x3040B520, 0xB1E03020, 0x1B703160,
+	0xB5202BC0, 0x30203040, 0x3260B220, 0x2B001B98, 0x3060B520,
+	0xB2603020, 0x1BD03360, 0xB5002A20, 0x30203060, 0x3480B2A0,
+	0x29601BF0, 0x3060B4E0, 0xB2E03020, 0x1C1835C0, 0xB4C02880,
+	0x30403060, 0x3700B340, 0x3F801C30, 0x3060B4A0, 0xB3803040,
+	0x1C403840, 0xB4603E00, 0x30403060, 0x39A0B3C0, 0x3C801C50,
+	0x3040B420, 0xB4003040, 0x1C603B00, 0xB4003B00, 0x00003040,
+	0x36E03640, 0x3CA03960, 0x39603CA0, 0x364036E0, 0x398036E0,
+	0x3C803CC0, 0x36E03940, 0x37003640, 0x3CC039A0, 0x39203C80,
+	0x364036C0, 0x39C03700, 0x3C603CC0, 0x36C03920, 0x37203640,
+	0x3CC039E0, 0x39003C40, 0x364036C0, 0x3A003720, 0x3C403CE0,
+	0x36A038E0, 0x37203640, 0x3D203A00, 0x38C03C20, 0x364036A0,
+	0x3A203740, 0x3C003D20, 0x36A038A0, 0x37403640, 0x3D003A40,
+	0x38A03C00, 0x364036A0, 0x3A603760, 0x3BE03D20, 0x36803880,
+	0x37603660, 0x3D203A80, 0x38603BC0, 0x36603680, 0x3AA03780,
+	0x3BA03D20, 0x36803840, 0x37803660, 0x3D003AC0, 0x38403BA0,
+	0x36603680, 0x3AE037A0, 0x3B803D00, 0x36803820, 0x37C03660,
+	0x3D203B00, 0x38003B60, 0x36603660, 0x3B0037C0, 0x3B403D40,
+	0x36603800, 0x37E03660, 0x3D403B20, 0x37E03B20, 0x00003660,
+	0x38C030C0, 0x2B802B60, 0x30C038C0, 0x2BA03940, 0x38402B40,
+	0x39C030C0, 0x2B402BA0, 0x30C037C0, 0x2BC03A40, 0x37802B00,
+	0x3AC03100, 0x2AC02BE0, 0x31003700, 0x2BE03B40, 0x36802AC0,
+	0x3BC03100, 0x2A802C20, 0x31403600, 0x2C203C40, 0x35C02A40,
+	0x3CC03140, 0x2A402C20, 0x31803540, 0x2C203D40, 0x35002A00,
+	0x3DC03180, 0x29C02C60, 0x31C03480, 0x2C603E40, 0x34402980,
+	0x3F003200, 0x29402C40, 0x32003400, 0x2C803F80, 0x33802900,
+	0x3FC03240, 0x29002C60, 0x32803340, 0x2C402840, 0x330028C0,
+	0x288032C0, 0x28802C40, 0x000032C0, 0x38C030C0, 0x2B802B60,
+	0x30C038C0, 0x2BA03940, 0x38402B40, 0x39C030C0, 0x2B402BA0,
+	0x30C037C0, 0x2BC03A40, 0x37802B00, 0x3AC03100, 0x2AC02BE0,
+	0x31003700, 0x2BE03B40, 0x36802AC0, 0x3BC03100, 0x2A802C20,
+	0x31403600, 0x2C203C40, 0x35C02A40, 0x3CC03140, 0x2A402C20,
+	0x31803540, 0x2C203D40, 0x35002A00, 0x3DC03180, 0x29C02C60,
+	0x31C03480, 0x2C603E40, 0x34402980, 0x3F003200, 0x29402C40,
+	0x32003400, 0x2C803F80, 0x33802900, 0x3FC03240, 0x29002C60,
+	0x32803340, 0x2C402840, 0x330028C0, 0x288032C0, 0x28802C40,
+	0x000032C0,
+};
+
+static const CARD32 filter_table_ntsc[] = {
+	0xB0603000, 0x1920B3E0, 0xB3E01900, 0x3000B060, 0xB380B080,
+	0x18A01980, 0xB040B440, 0xB0A03000, 0x19D0B300, 0xB4801840,
+	0x3000B020, 0xB260B0E0, 0x2FE01A10, 0x3000B4C0, 0xB1003000,
+	0x1A60B1C0, 0xB4E02F00, 0x30003020, 0xB120B140, 0x2E401AB0,
+	0x3020B500, 0xB1803000, 0x1B00B060, 0xB5202D60, 0x30003040,
+	0x3080B1A0, 0x2CA01B30, 0x3040B520, 0xB1E03020, 0x1B703160,
+	0xB5202BC0, 0x30203040, 0x3260B220, 0x2B001B98, 0x3060B520,
+	0xB2603020, 0x1BD03360, 0xB5002A20, 0x30203060, 0x3480B2A0,
+	0x29601BF0, 0x3060B4E0, 0xB2E03020, 0x1C1835C0, 0xB4C02880,
+	0x30403060, 0x3700B340, 0x3F801C30, 0x3060B4A0, 0xB3803040,
+	0x1C403840, 0xB4603E00, 0x30403060, 0x39A0B3C0, 0x3C801C50,
+	0x3040B420, 0xB4003040, 0x1C603B00, 0xB4003B00, 0x00003040,
+	0x38A03000, 0x3C803AE0, 0x3AE03C80, 0x300038A0, 0x3B0038E0,
+	0x3C803C80, 0x38403AE0, 0x39203000, 0x3C803B00, 0x3AE03C80,
+	0x30203800, 0x3B003960, 0x3C803C80, 0x37A03AE0, 0x39803040,
+	0x3C603B20, 0x3AE03C80, 0x30403760, 0x3B2039C0, 0x3C803C80,
+	0x37003AE0, 0x39E03080, 0x3C603B40, 0x3AE03C80, 0x30A036A0,
+	0x3B603A20, 0x3C803C40, 0x36403AE0, 0x3A4030C0, 0x3C403B60,
+	0x3AE03C80, 0x31003600, 0x3B803A60, 0x3C603C40, 0x35A03AE0,
+	0x3A803140, 0x3C403B80, 0x3AE03C60, 0x31803540, 0x3BA03A80,
+	0x3C603C40, 0x34E03AE0, 0x3AA031C0, 0x3C403BC0, 0x3AE03C40,
+	0x32003480, 0x3BC03AC0, 0x3C403C40, 0x34203AE0, 0x3AC03260,
+	0x3C403BE0, 0x3AE03C20, 0x32A033C0, 0x3C003AC0, 0x3C203C40,
+	0x33603AE0, 0x3AE03300, 0x3C403C00, 0x3AE03C00, 0x00003300,
+	0x38C030C0, 0x2B802B60, 0x30C038C0, 0x2BA03940, 0x38402B40,
+	0x39C030C0, 0x2B402BA0, 0x30C037C0, 0x2BC03A40, 0x37802B00,
+	0x3AC03100, 0x2AC02BE0, 0x31003700, 0x2BE03B40, 0x36802AC0,
+	0x3BC03100, 0x2A802C20, 0x31403600, 0x2C203C40, 0x35C02A40,
+	0x3CC03140, 0x2A402C20, 0x31803540, 0x2C203D40, 0x35002A00,
+	0x3DC03180, 0x29C02C60, 0x31C03480, 0x2C603E40, 0x34402980,
+	0x3F003200, 0x29402C40, 0x32003400, 0x2C803F80, 0x33802900,
+	0x3FC03240, 0x29002C60, 0x32803340, 0x2C402840, 0x330028C0,
+	0x288032C0, 0x28802C40, 0x000032C0, 0x38C030C0, 0x2B802B60,
+	0x30C038C0, 0x2BA03940, 0x38402B40, 0x39C030C0, 0x2B402BA0,
+	0x30C037C0, 0x2BC03A40, 0x37802B00, 0x3AC03100, 0x2AC02BE0,
+	0x31003700, 0x2BE03B40, 0x36802AC0, 0x3BC03100, 0x2A802C20,
+	0x31403600, 0x2C203C40, 0x35C02A40, 0x3CC03140, 0x2A402C20,
+	0x31803540, 0x2C203D40, 0x35002A00, 0x3DC03180, 0x29C02C60,
+	0x31C03480, 0x2C603E40, 0x34402980, 0x3F003200, 0x29402C40,
+	0x32003400, 0x2C803F80, 0x33802900, 0x3FC03240, 0x29002C60,
+	0x32803340, 0x2C402840, 0x330028C0, 0x288032C0, 0x28802C40,
+	0x000032C0,
+};
+
 typedef struct {
     char *name;
     int	clock;
     CARD32 oversample;
     int hsync_end, hblank_start, hblank_end, htotal;
-    Bool progressive, trilevel_sync;
+    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 +265,9 @@ typedef struct {
      */
     video_levels_t	composite_levels, svideo_levels;
     color_conversion_t	composite_color, svideo_color;
+    const CARD32 *filter_table;
 } tv_mode_t;
 
-#define TV_PLL_CLOCK	107520
 
 /*
  * Sub carrier DDA
@@ -157,9 +302,10 @@ 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,
@@ -203,108 +349,264 @@ 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_ntsc,
     },
     {
-	.name		= "NTSC-Japan 480i",
-	.clock		= 107520,	
-	.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,	    .trilevel_sync = FALSE,
+         .name		= "NTSC-443",
+	 .clock		= 107520,	
+	 .oversample	= TV_OVERSAMPLE_8X,
+	 .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,	    .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 4.4336180 actual 4.4336180 clock 107.52 */
+	 .dda1_inc	=   168,
+	 .dda2_inc	=   4093,	    .dda2_size		=  27456,
+	 .dda3_inc	=   525,	    .dda3_size		=  310,
+	 .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,
+	 },
+	.filter_table = filter_table_ntsc,
+    },
+    {
+	    .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,
+	    .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,
 
-	.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,
+	    .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,
+	    },
 
-	/* 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,
+	    .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,
+	    },
+	    .filter_table = filter_table_ntsc,
+    },
+    {
+	    .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	=    135,
+	    .dda2_inc	=    16704,	    .dda2_size		=  27456,
+	    .dda3_inc	=      0,	    .dda3_size		=      0,
+	    .sc_reset	= TV_SC_RESET_EVERY_8,
+	    .pal_burst  = TRUE,
 
-	.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,
-	},
+	    .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 = 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,
-	},
+	    .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_pal,
     },
     {
-	/* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */
-	.name	    = "PAL 576i",
-	.clock		= 107520,	
-	.oversample	= TV_OVERSAMPLE_8X,
+	    /* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */
+	    .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,    .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	= 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	=    135,
+	    .dda2_inc	=  23578,	.dda2_size	=  27648,
+	    .dda3_inc	=     134,	.dda3_size	=  625,
+	    .sc_reset   = TV_SC_RESET_EVERY_8,
+	    .pal_burst  = TRUE,
 
-	.hsync_end	= 64,		    .hblank_end		= 128,
-	.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,
+	    .composite_levels = { .blank = 225, .black = 267, .burst = 118 },
+	    .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,
+	    },
 
-	.vi_end_f1	= 24,		    .vi_end_f2		= 25,
-	.nbr_end	= 286,
+	    .svideo_levels    = { .blank = 266, .black = 316, .burst = 139 },
+	    .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_pal,
+    },
+    {
+	    /* 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	= 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	=   4122,	.dda2_size	=  27648,
+	    .dda3_inc	=     67,	.dda3_size	=  625,
+	    .sc_reset   = TV_SC_RESET_EVERY_8,
+	    .pal_burst  = TRUE,
 
-	.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,
-	},
+	    .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,
-	},
+	    .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,
+	    },
+	    .filter_table = filter_table_pal,
     },
     {
-	    .name       = "480p",
+	    .name       = "480p at 59.94Hz",
 	    .clock 	= 107520,	
 	    .oversample     = TV_OVERSAMPLE_4X,
+	    .component_only = 1,
 
 	    .hsync_end      = 64,               .hblank_end         = 122,
 	    .hblank_start   = 842,              .htotal             = 857,
@@ -334,11 +636,49 @@ 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_hres,
+    },
+    {
+	    .name       = "480p at 60Hz",
+	    .clock 	= 107520,	
+	    .oversample     = TV_OVERSAMPLE_4X,
+	    .component_only = 1,
+
+	    .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,
+
+	    .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,
+	    },
+	    .filter_table = filter_table_hres,
     },
     {
 	    .name       = "576p",
 	    .clock 	= 107520,	
 	    .oversample     = TV_OVERSAMPLE_4X,
+	    .component_only = 1,
 
 	    .hsync_end      = 64,               .hblank_end         = 139,
 	    .hblank_start   = 859,              .htotal             = 863,
@@ -368,571 +708,613 @@ 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_hres,
     },
     {
-        .name       = "720p",
-	.clock		= 148800,	
-        .oversample     = TV_OVERSAMPLE_2X,
-
-        .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,
-
-        .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,
-        },
+	    .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,
+
+	    .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,
+	    },
+	    .filter_table = filter_table_hres,
     },
     {
-        .name       = "1080i",
-	.clock		= 148800,	
-        .oversample     = TV_OVERSAMPLE_2X,
+	    .name       = "720p at 59.94Hz",
+	    .clock		= 148800,	
+	    .oversample     = TV_OVERSAMPLE_2X,
+	    .component_only = 1,
 
-        .hsync_end      = 88,               .hblank_end         = 235,
-        .hblank_start   = 2155,             .htotal             = 2639,
+	    .hsync_end      = 80,               .hblank_end         = 300,
+	    .hblank_start   = 1580,             .htotal             = 1651,
 
-        .progressive    = FALSE, 	    .trilevel_sync = TRUE,
+	    .progressive    = TRUE, 	    .trilevel_sync = TRUE,
 
-        .vsync_start_f1 = 4,               .vsync_start_f2     = 5,
-        .vsync_len      = 10,
+	    .vsync_start_f1 = 10,               .vsync_start_f2     = 10,
+	    .vsync_len      = 10,
 
-	.veq_ena	= TRUE,		    .veq_start_f1    	= 4,
-	.veq_start_f2	= 4,		    .veq_len		= 10,
-	
+	    .veq_ena        = FALSE,
 
-        .vi_end_f1      = 21,               .vi_end_f2          = 22,
-        .nbr_end        = 539,
+	    .vi_end_f1      = 29,               .vi_end_f2          = 29,
+	    .nbr_end        = 719,
 
-        .burst_ena      = FALSE,
+	    .burst_ena      = FALSE,
 
-        .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,
-        },
+	    .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,
+	    },
+	    .filter_table = filter_table_hres,
+    },
+    {
+	    .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,
+
+	    .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,
+	    },
+	    .filter_table = filter_table_hres,
+    },
+    {
+	    .name       = "1080i at 30Hz",
+	    .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,
+
+	    .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,
+	    },
+	    .filter_table = filter_table_hres,
+    },
+    {
+	    .name       = "1080i at 29.97Hz",
+	    .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,
+
+	    .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,
+	    },
+	    .filter_table = filter_table_hres,
     },
 };
 
 static const video_levels_t component_level = {
-    .blank = 279, .black = 279 
+	.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,
+	.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,
+	.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)
 {
-    ScrnInfoPtr pScrn = output->scrn;
-    I830Ptr pI830 = I830PTR(pScrn);
+	ScrnInfoPtr pScrn = output->scrn;
+	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;
-    }
+	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(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;
-    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);
-    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_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));
+	ScrnInfoPtr		    pScrn = output->scrn;
+	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);
+	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_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);
+	dev_priv->save_TV_DAC = INREG(TV_DAC);
+	dev_priv->save_TV_CTL = INREG(TV_CTL);
 }
 
 static void
 i830_tv_restore(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;
-    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);
-    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_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]);
+	ScrnInfoPtr		    pScrn = output->scrn;
+	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);
+	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_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);
+
+	{
+		xf86CrtcPtr	    crtc = output->crtc;
+		I830CrtcPrivatePtr	    intel_crtc = crtc->driver_private;
+		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 and TV_WIN_POS */
+		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]);
+	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);
+	OUTREG(TV_DAC, dev_priv->save_TV_DAC);
+	OUTREG(TV_CTL, dev_priv->save_TV_CTL);
 }
 
 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
 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;
+	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;
+	CARD16  ret;
 
-    ret = (f * (1 << 9));
-    return ret;
+	ret = (f * (1 << 9));
+	return ret;
 }
 
 static void
 i830_tv_mode_set(xf86OutputPtr output, DisplayModePtr mode,
-		 DisplayModePtr adjusted_mode)
+		DisplayModePtr adjusted_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;
-    const tv_mode_t	    *tv_mode;
-    CARD32		    tv_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.
-     */
-	
-    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;
-    }
-    hctl1 = (tv_mode->hsync_end << TV_HSYNC_END_SHIFT) |
-	(tv_mode->htotal << TV_HTOTAL_SHIFT);
+	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;
+	const tv_mode_t	    *tv_mode;
+	CARD32		    tv_ctl;
+	CARD32		    hctl1, hctl2, hctl3;
+	CARD32		    vctl1, vctl2, vctl3, vctl4, vctl5, vctl6, vctl7;
+	CARD32		    scctl1, scctl2, scctl3;
+	int			    i, j;
+	const video_levels_t	*video_levels;
+	const color_conversion_t	*color_conversion;
+	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;	
+	}
 
-    hctl2 = (tv_mode->hburst_start << 16) |
-	(tv_mode->hburst_len << TV_HBURST_LEN_SHIFT);
-    if (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);
-
-    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;
-    if (tv_mode->oversample == TV_OVERSAMPLE_8X)
-	    scctl1 = TV_SC_DDA1_EN;
+	tv_ctl = 0;
 
-    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;
-
-    scctl2 = tv_mode->dda2_size << TV_SCDDA2_SIZE_SHIFT |
-	tv_mode->dda2_inc << TV_SCDDA2_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)
-	tv_ctl |= TV_ENC_C0_FIX | TV_ENC_SDP_FIX;
-
-
-    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_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)));
-    {
-	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);
+	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);
 
-	/* Filter ctl must be set before TV_WIN_SIZE and TV_WIN_POS */
-    	OUTREG(TV_FILTER_CTL_1, TV_AUTO_SCALE);
+	hctl2 = (tv_mode->hburst_start << 16) |
+		(tv_mode->hburst_len << TV_HBURST_LEN_SHIFT);
+	if (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);
+
+	if (intel_crtc->pipe == 1)
+		tv_ctl |= TV_ENC_PIPEB_SELECT;
+	tv_ctl |= tv_mode->oversample;
 
-	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));
-
-    } 	
-    
-    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);
+		tv_ctl |= TV_PROGRESSIVE;
+	if (tv_mode->trilevel_sync)
+		tv_ctl |= TV_TRILEVEL_SYNC;
+	if (tv_mode->pal_burst)
+		tv_ctl |= TV_PAL_BURST;
+	if (tv_mode->oversample == TV_OVERSAMPLE_8X)
+		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;
+
+	scctl2 = tv_mode->dda2_size << TV_SCDDA2_SIZE_SHIFT |
+		tv_mode->dda2_inc << TV_SCDDA2_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)
+		tv_ctl |= TV_ENC_C0_FIX | TV_ENC_SDP_FIX;
+
+
+	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_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, 0x10606000);
+	OUTREG(TV_CLR_LEVEL, ((video_levels->black << TV_BLACK_LEVEL_SHIFT) |
+				(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 and TV_WIN_POS */
+		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), tv_mode->filter_table[j++]);
+	for (i = 0; i < 60; 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), tv_mode->filter_table[j++]);
+	for (i = 0; i < 43; 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,
+		.Clock = 107520,
 		.HDisplay   = 1280,
 		.HSyncStart = 1368,
 		.HSyncEnd   = 1496,
@@ -950,76 +1332,76 @@ static const DisplayModeRec reported_mod
  * 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);
-    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;
+	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 |
-		   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,
-		   "No TV connection detected\n");
-	type = TV_TYPE_NONE;
-    }
-    
-    dev_priv->type = type;
+	/*
+	 * 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 |
+				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,
+				"No TV connection detected\n");
+		type = TV_TYPE_NONE;
+	}
+
+	dev_priv->type = type;
 }
 
 /**
@@ -1031,33 +1413,33 @@ i830_tv_detect_type (xf86CrtcPtr    crtc
 static xf86OutputStatus
 i830_tv_detect(xf86OutputPtr output)
 {
-    xf86CrtcPtr		    crtc;
-    DisplayModeRec	    mode;
-    I830OutputPrivatePtr    intel_output = output->driver_private;
-    struct i830_tv_priv	    *dev_priv = intel_output->dev_priv;
+	xf86CrtcPtr		    crtc;
+	DisplayModeRec	    mode;
+	I830OutputPrivatePtr    intel_output = output->driver_private;
+	struct i830_tv_priv	    *dev_priv = intel_output->dev_priv;
 
-    crtc = i830GetLoadDetectPipe (output);
-    if (crtc)
-    {
-	if (intel_output->load_detect_temp)
+	crtc = i830GetLoadDetectPipe (output);
+	if (crtc)
 	{
-	    /* we only need the pixel clock set correctly here */
-	    mode = reported_modes[0];
-	    xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
-	    i830PipeSetMode (crtc, &mode, FALSE);
+		if (intel_output->load_detect_temp)
+		{
+			/* we only need the pixel clock set correctly here */
+			mode = reported_modes[0];
+			xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
+			i830PipeSetMode (crtc, &mode, FALSE);
+		}
+		i830_tv_detect_type (crtc, output);
+		i830ReleaseLoadDetectPipe (output);
+	}
+
+	switch (dev_priv->type) {
+		case TV_TYPE_NONE:
+			return XF86OutputStatusDisconnected;
+		case TV_TYPE_UNKNOWN:
+			return XF86OutputStatusUnknown;
+		default:
+			return XF86OutputStatusConnected;
 	}
-	i830_tv_detect_type (crtc, output);
-	i830ReleaseLoadDetectPipe (output);
-    }
-    
-    switch (dev_priv->type) {
-    case TV_TYPE_NONE:
-	return XF86OutputStatusDisconnected;
-    case TV_TYPE_UNKNOWN:
-	return XF86OutputStatusUnknown;
-    default:
-	return XF86OutputStatusConnected;
-    }
 }
 
 struct input_res {
@@ -1083,89 +1465,94 @@ struct input_res {
 static DisplayModePtr
 i830_tv_get_modes(xf86OutputPtr output)
 {
-    DisplayModePtr  ret = NULL, mode_ptr;
-    int		    i, j;
-    	
-    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:
+	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);
-	
-	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;
-	
-		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 ret;
+		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;
+
+			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 ret;
 }
 
 static void
 i830_tv_destroy (xf86OutputPtr output)
 {
-    if (output->driver_private)
-	xfree (output->driver_private);
+	if (output->driver_private)
+		xfree (output->driver_private);
 }
 
 static const xf86OutputFuncsRec i830_tv_output_funcs = {
-    .dpms = i830_tv_dpms,
-    .save = i830_tv_save,
-    .restore = i830_tv_restore,
-    .mode_valid = i830_tv_mode_valid,
-    .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
+	.dpms = i830_tv_dpms,
+	.save = i830_tv_save,
+	.restore = i830_tv_restore,
+	.mode_valid = i830_tv_mode_valid,
+	.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
 };
 
 void
 i830_tv_init(ScrnInfoPtr pScrn)
 {
-    I830Ptr		    pI830 = I830PTR(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;
+	I830Ptr		    pI830 = I830PTR(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
      */
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 5a67f3d3690903a181ca854d060cfa8b4c2aca26 (from parents)
Merge: 3cc583ec8e79ec65103308220dd6047a4a7acddf 98110591001dfaf2b8b5ac440bea0c38456da718
Author: Nian Wu <nian.wu at intel.com>
Date:   Thu Jan 25 13:40:50 2007 -0800

    Merge branch 'crestline' of /git/xorg/driver/xf86-video-intel into crestline

diff-tree 3cc583ec8e79ec65103308220dd6047a4a7acddf (from parents)
Merge: 566e1d397744d0b477de4da6a206919906176f49 effe579e691b044e3ce59b41b5c0eaaac4368dda
Author: Nian Wu <nian.wu at intel.com>
Date:   Thu Jan 25 13:37:05 2007 -0800

    Merge branch 'modesetting' of git://proxy01.pd.intel.com:9419/git/xorg/driver/xf86-video-intel into crestline

diff-tree 6d549ed280d3fcf3fe611b095d9f8adc0196bfb6 (from parents)
Merge: 75f4df278e9db360967d77cdba4756cbde622d56 effe579e691b044e3ce59b41b5c0eaaac4368dda
Author: Nian Wu <nian.wu at intel.com>
Date:   Thu Jan 25 13:36:33 2007 -0800

    Merge branch 'modesetting' of git://proxy01.pd.intel.com:9419/git/xorg/driver/xf86-video-intel into modesetting
    
    Conflicts:
    
    	src/i830_driver.c

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 98110591001dfaf2b8b5ac440bea0c38456da718 (from 566e1d397744d0b477de4da6a206919906176f49)
Author: Zou Nan hai <nanhai.zou at intel.com>
Date:   Wed Jan 17 10:45:59 2007 +0800

      enable all TV modes

diff --git a/src/i830_display.c b/src/i830_display.c
index f47a9db..553d2d2 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -960,13 +960,14 @@ i830PipeSetMode(xf86CrtcPtr crtc, Displa
 	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 (plane_enable) {
+	    /* 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
diff --git a/src/i830_tv.c b/src/i830_tv.c
index 92e417e..1b75e87 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,
@@ -96,9 +95,10 @@ typedef struct {
 
 typedef struct {
     char *name;
+    int	clock;
     CARD32 oversample;
     int hsync_end, hblank_start, hblank_end, htotal;
-    Bool progressive;
+    Bool progressive, trilevel_sync;
     int vsync_start_f1, vsync_start_f2, vsync_len;
     Bool veq_ena;
     int veq_start_f1, veq_start_f2, veq_len;
@@ -158,15 +158,15 @@ typedef struct {
 const static tv_mode_t tv_modes[] = {
     {
 	.name		= "NTSC 480i",
+	.clock		= 107520,	
 	.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,
-	
+	.progressive	= FALSE,	    .trilevel_sync = FALSE,
+
 	.vsync_start_f1	= 6,		    .vsync_start_f2	= 7,
 	.vsync_len	= 6,
 	
@@ -206,14 +206,15 @@ const static tv_mode_t tv_modes[] = {
     },
     {
 	.name		= "NTSC-Japan 480i",
+	.clock		= 107520,	
 	.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,
-	
+	.progressive	= FALSE,	    .trilevel_sync = FALSE,
+
 	.vsync_start_f1	= 6,		    .vsync_start_f2	= 7,
 	.vsync_len	= 6,
 	
@@ -254,12 +255,14 @@ const static tv_mode_t tv_modes[] = {
     {
 	/* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */
 	.name	    = "PAL 576i",
+	.clock		= 107520,	
 	.oversample	= TV_OVERSAMPLE_8X,
 
 	.hsync_end	= 64,		    .hblank_end		= 128,
 	.hblank_start	= 844,		    .htotal		= 863,
 	
-	.progressive	= FALSE,
+	.progressive	= FALSE,	   .trilevel_sync = FALSE,
+	
 	
 	.vsync_start_f1	= 6,		    .vsync_start_f2	= 7,
 	.vsync_len	= 6,
@@ -297,105 +300,145 @@ 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,
 	},
-    }
-#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,
-	},
+	    .name       = "480p",
+	    .clock 	= 107520,	
+	    .oversample     = TV_OVERSAMPLE_4X,
+
+	    .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,
+
+	    .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,
-	},
+	    .name       = "576p",
+	    .clock 	= 107520,	
+	    .oversample     = TV_OVERSAMPLE_4X,
+
+	    .hsync_end      = 64,               .hblank_end         = 139,
+	    .hblank_start   = 859,              .htotal             = 863,
+
+	    .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,
+
+	    .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,
+	    },
     },
     {
-	/* 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,
-	},
+        .name       = "720p",
+	.clock		= 148800,	
+        .oversample     = TV_OVERSAMPLE_2X,
+
+        .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,
+
+        .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 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       = "1080i",
+	.clock		= 148800,	
+        .oversample     = TV_OVERSAMPLE_2X,
 
-	.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      = 88,               .hblank_end         = 235,
+        .hblank_start   = 2155,             .htotal             = 2639,
 
-	.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    = 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,
+
+        .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,
+        },
     },
-#endif
 };
 
 static const video_levels_t component_level = {
@@ -674,7 +717,7 @@ 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;
@@ -687,7 +730,12 @@ i830_tv_mode_set(xf86OutputPtr output, D
      * mode.  For now, just set the first one in the list, with
      * NTSC format.
      */
-    tv_mode = &tv_modes[0];
+	
+    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;
 
@@ -755,15 +803,17 @@ 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;
+    if (tv_mode->oversample == TV_OVERSAMPLE_8X)
+	    scctl1 = TV_SC_DDA1_EN;
 
-    scctl1 = TV_SC_DDA1_EN;
-    
     if (tv_mode->dda2_inc)
 	scctl1 |= TV_SC_DDA2_EN;
     
@@ -784,9 +834,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);
@@ -828,13 +875,47 @@ i830_tv_mode_set(xf86OutputPtr output, D
     OUTREG(TV_CLR_KNOBS, 0x00606000);
     OUTREG(TV_CLR_LEVEL, ((video_levels->black << TV_BLACK_LEVEL_SHIFT) |
 			  (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 and TV_WIN_POS */
+    	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));
+
+    } 	
     
-    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++)
@@ -863,108 +944,6 @@ static const DisplayModeRec reported_mod
 		.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
-	},
 };
 
 /**
@@ -1081,34 +1060,78 @@ i830_tv_detect(xf86OutputPtr output)
     }
 }
 
+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++)
+    DisplayModePtr  ret = NULL, mode_ptr;
+    int		    i, j;
+    	
+    for (i = 0; i < sizeof(tv_modes) / sizeof (tv_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;
+	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);
+	
+	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;
+	
+		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
diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index ceb8f2e..1148c28 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -30,7 +30,7 @@
 
 #include "xf86.h"
 #include "xf86DDC.h"
-/*#include "i830.h" */
+#include "i830.h"
 #include "i830_xf86Crtc.h"
 #include "i830_xf86Modes.h"
 #include "i830_randr.h"
@@ -793,6 +793,7 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn,
     for (o = 0; o < config->num_output; o++) 
     {
 	xf86OutputPtr	    output = config->output[o];
+	I830OutputPrivatePtr intel_output = output->driver_private;
 	DisplayModePtr	    mode;
 	DisplayModePtr	    config_modes = NULL, output_modes, default_modes;
 	char		    *preferred_mode;
@@ -803,7 +804,6 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn,
 	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);
 
@@ -902,8 +902,8 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn,
 	    mon_rec.nVrefresh = 1;
 	}
 	default_modes = i830xf86GetDefaultModes (output->interlaceAllowed,
-						 output->doubleScanAllowed);
-	
+			output->doubleScanAllowed);
+
 	if (sync_source == sync_config)
 	{
 	    /* 
@@ -926,8 +926,9 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn,
 	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);
-	
+	if (intel_output->type != I830_OUTPUT_TVOUT)	
+		output->probed_modes = xf86ModesAdd (output->probed_modes, default_modes);
+
 	/*
 	 * Check all modes against max size
 	 */
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 9a5106401a65c90df32cb71987fca7126dc22e81 (from 319be199ba657d2b82ba034edf3581aea6dcc3f0)
Author: Emilio Scalise <emisca.ml at gmail.com>
Date:   Mon Jan 15 17:22:27 2007 +0000

    patch to control mergedfb options, bug #9664

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 11c23ca..f7c700a 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -270,6 +270,9 @@ typedef enum {
    OPTION_SECONDHSYNC,
    OPTION_SECONDVREFRESH,
    OPTION_SECONDPOSITION,
+   OPTION_SECONDISSCRN0,
+   OPTION_MERGEDFBNONRECT,
+   OPTION_MERGEDFBMOUSER,
    OPTION_INTELXINERAMA,
    OPTION_INTELTEXPOOL,
    OPTION_INTELMMSIZE
@@ -299,6 +302,9 @@ static OptionInfoRec I830BIOSOptions[] =
    {OPTION_SECONDHSYNC,	"SecondMonitorHorizSync",OPTV_STRING,	{0}, FALSE },
    {OPTION_SECONDVREFRESH,"SecondMonitorVertRefresh",OPTV_STRING,{0}, FALSE },
    {OPTION_SECONDPOSITION,"SecondPosition",OPTV_STRING,	{0},	FALSE },
+   {OPTION_SECONDISSCRN0,"MergedXineramaSecondIsScreen0", OPTV_BOOLEAN, {0}, FALSE },
+   {OPTION_MERGEDFBNONRECT,"MergedNonRectangular",OPTV_BOOLEAN,	{0},	FALSE},
+   {OPTION_MERGEDFBMOUSER,"MergedMouseRestriction",OPTV_BOOLEAN, {0},    FALSE},
    {OPTION_INTELXINERAMA,"MergedXinerama",OPTV_BOOLEAN,	{0},	TRUE},
    {OPTION_INTELTEXPOOL,"Legacy3D",     OPTV_BOOLEAN,	{0},	FALSE},
    {OPTION_INTELMMSIZE, "AperTexSize",  OPTV_INTEGER,	{0},	FALSE},
@@ -4755,6 +4761,27 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
          }
          xfree(tempstr);
       }
+
+      /* If OPTION_SECONDISSCRN0 is true then swap screens */
+      if(xf86GetOptValBool(pI830->Options, OPTION_SECONDISSCRN0, TRUE)) {
+         if (pI830->SecondIsScrn0) 
+	    pI830->SecondIsScrn0 = FALSE;
+         else 
+	    pI830->SecondIsScrn0 = TRUE;
+      }
+
+      /* Set pI830->NonRect according to OPTION_MERGEDFBNONRECT */
+      if(xf86GetOptValBool(pI830->Options, OPTION_MERGEDFBNONRECT, TRUE))
+	 pI830->NonRect = TRUE;
+      else
+	 pI830->NonRect = FALSE;
+	
+      /* Set pI830->MouseRestrictions according to OPTION_MERGEDFBMOUSER */
+      if(xf86GetOptValBool(pI830->Options, OPTION_MERGEDFBMOUSER, TRUE))
+         pI830->MouseRestrictions = TRUE;
+      else
+         pI830->MouseRestrictions = FALSE;
+							 
       if((s = (char *)xf86GetOptValString(pI830->Options, OPTION_METAMODES))) {
          pI830->MetaModes = xalloc(strlen(s) + 1);
 	 if(pI830->MetaModes) 
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 319be199ba657d2b82ba034edf3581aea6dcc3f0 (from 85de57947570de6b3dc9197647be3e9237480880)
Author: root <root at jetpack.demon.co.uk>
Date:   Sat Jan 13 21:34:00 2007 +0000

    Tweak to bug #9639

diff --git a/src/xvmc/Makefile.am b/src/xvmc/Makefile.am
index 69d164a..a9ea9d1 100644
--- a/src/xvmc/Makefile.am
+++ b/src/xvmc/Makefile.am
@@ -4,5 +4,6 @@ libI810XvMC_la_SOURCES = I810XvMC.c \
 			 I810XvMC.h
 
 libI810XvMC_la_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ -I$(top_srcdir)/src -DTRUE=1 -DFALSE=0
-libI810XvMC_la_LDFLAGS = @DRI_LIBS@ -version-number 1:0:0
+libI810XvMC_la_LDFLAGS = -version-number 1:0:0
+libI810XvMC_la_LIBADD = @DRI_LIBS@ 
 endif
diff-tree 85de57947570de6b3dc9197647be3e9237480880 (from efb75f56053ee06f1dbd4edfaea9986b27162afb)
Author: Alan Hourihane <alanh at fairlite.demon.co.uk>
Date:   Sat Jan 13 19:18:24 2007 +0000

    Fix bug #9639, i810 XvMC needs linking against libdrm.

diff --git a/src/xvmc/Makefile.am b/src/xvmc/Makefile.am
index 5cd5b25..69d164a 100644
--- a/src/xvmc/Makefile.am
+++ b/src/xvmc/Makefile.am
@@ -4,5 +4,5 @@ libI810XvMC_la_SOURCES = I810XvMC.c \
 			 I810XvMC.h
 
 libI810XvMC_la_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ -I$(top_srcdir)/src -DTRUE=1 -DFALSE=0
-libI810XvMC_la_LDFLAGS = -version-number 1:0:0
-endif
\ No newline at end of file
+libI810XvMC_la_LDFLAGS = @DRI_LIBS@ -version-number 1:0:0
+endif
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 efb75f56053ee06f1dbd4edfaea9986b27162afb (from 33c0fac6d63d9a509a24c7a5e5a46a0d6ee4dc5d)
Author: Alan Hourihane <alanh at fairlite.demon.co.uk>
Date:   Tue Jan 9 14:05:43 2007 +0000

    Bump to 1.7.4

diff --git a/configure.ac b/configure.ac
index 48b39a1..a232f18 100644
--- a/configure.ac
+++ b/configure.ac
@@ -22,7 +22,7 @@
 
 AC_PREREQ(2.57)
 AC_INIT([xf86-video-i810],
-        1.7.3,
+        1.7.4,
         [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
         xf86-video-i810)
 
diff --git a/src/i810_dri.h b/src/i810_dri.h
index 70ea899..5aa4338 100644
--- a/src/i810_dri.h
+++ b/src/i810_dri.h
@@ -10,7 +10,7 @@
 
 #define I810_MAJOR_VERSION 1
 #define I810_MINOR_VERSION 7
-#define I810_PATCHLEVEL 3
+#define I810_PATCHLEVEL 4
 
 typedef struct {
    drm_handle_t regs;
diff --git a/src/i830_dri.h b/src/i830_dri.h
index 969eb60..91891a5 100644
--- a/src/i830_dri.h
+++ b/src/i830_dri.h
@@ -10,7 +10,7 @@
 
 #define I830_MAJOR_VERSION 1
 #define I830_MINOR_VERSION 7
-#define I830_PATCHLEVEL 3
+#define I830_PATCHLEVEL 4
 
 #define I830_REG_SIZE 0x80000
 
diff-tree 33c0fac6d63d9a509a24c7a5e5a46a0d6ee4dc5d (from 1975fa5b010100196af201e40f43b30a149b7750)
Author: Alan Hourihane <alanh at fairlite.demon.co.uk>
Date:   Tue Jan 9 14:02:47 2007 +0000

    Fix bug #8536, i915 BIOS fails when restarting Xserver.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index e950d7c..11c23ca 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -7087,7 +7087,7 @@ IntelEmitInvarientState(ScrnInfoPtr pScr
    I830Ptr pI830 = I830PTR(pScrn);
    CARD32 ctx_addr;
 
-   if (pI830->noAccel)
+   if (pI830->noAccel || !I830IsPrimary(pScrn))
       return;
 
    ctx_addr = pI830->ContextMem.Start;
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 566e1d397744d0b477de4da6a206919906176f49 (from parents)
Merge: b13d6386dfb3a00bd9d21ac0695cdce9f812d1f3 da6a00f787e4d13e6b75768c1976f1c44ae5bf72
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Mon Jan 8 12:37:49 2007 -0800

    Merge branch 'modesetting' into crestline

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 b13d6386dfb3a00bd9d21ac0695cdce9f812d1f3 (from 7473e7d5297f94164e0f35822166713fb21a11bd)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Sun Jan 7 22:56:37 2007 -0800

    Back out rotation changes for RandR 1.2 which won't work.
    
    RandR 1.2 requires a new rotation structure for per-CRTC rotation.

diff --git a/src/i830.h b/src/i830.h
index a03f877..f89d022 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -195,8 +195,6 @@ extern const char *i830_output_type_name
 
 typedef struct _I830CrtcPrivateRec {
     int			    pipe;
-    Rotation 		    rotation;    /* current rotation, mirror from pI830->rotation */
-    Rotation		    rotations;  /* all */
     /* Lookup table values to be set when the CRTC is enabled */
     CARD8 lut_r[256], lut_g[256], lut_b[256];
 } I830CrtcPrivateRec, *I830CrtcPrivatePtr;
diff --git a/src/i830_display.c b/src/i830_display.c
index 3f9d882..f47a9db 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -821,9 +821,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
 	((adjusted_mode->CrtcVBlankEnd - 1) << 16));
     OUTREG(vsync_reg, (adjusted_mode->CrtcVSyncStart - 1) |
 	((adjusted_mode->CrtcVSyncEnd - 1) << 16));
-  /* XXX we might always set real line stride, rotation can change it */
-  //  OUTREG(dspstride_reg, pScrn->displayWidth * pI830->cpp);
-    OUTREG(dspstride_reg, pI830->displayWidth * pI830->cpp);
+    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.
      */
diff --git a/src/i830_randr.c b/src/i830_randr.c
index 79b16e8..533322b 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -371,14 +371,6 @@ xf86RandR12GetRotation(ScreenPtr pScreen
     return randrp->rotation;
 }
 
-Rotation
-xf86RandR12GetRotation12(RRCrtcPtr randr_crtc)
-{
-    xf86CrtcPtr		crtc = randr_crtc->devPrivate;
-    I830CrtcPrivatePtr  intel_crtc = I830CrtcPrivate(crtc);
-    return intel_crtc->rotation;
-}
-
 Bool
 xf86RandR12CreateScreenResources (ScreenPtr pScreen)
 {
@@ -498,29 +490,12 @@ xf86RandR12Init (ScreenPtr pScreen)
     return TRUE;
 }
 
-/* RandR12 should have been initialized, so we might set rotations
-   to Crtc object. 
- */
 void
 xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotations)
 {
     XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
-#if RANDR_12_INTERFACE
-    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
-    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
-    int c;
-#endif
 
     randrp->supported_rotations = rotations;
-#if RANDR_12_INTERFACE
-    for (c = 0; c < config->num_crtc ; c++) {
-	xf86CrtcPtr    crtc = config->crtc[c];
-	I830CrtcPrivatePtr intel_crtc = I830CrtcPrivate(crtc);
-	crtc->randr_crtc->rotations = rotations;
-	intel_crtc->rotations = rotations;
-	intel_crtc->rotation = RR_Rotate_0; /*XXX initial rotation fix */
-    }
-#endif
 }
 
 void
@@ -566,7 +541,7 @@ xf86RandR12CrtcNotify (RRCrtcPtr	randr_c
 	return FALSE;
     x = crtc->x;
     y = crtc->y;
-    rotation = xf86RandR12GetRotation12(randr_crtc);
+    rotation = RR_Rotate_0;
     numOutputs = 0;
     randr_mode = NULL;
     for (i = 0; i < config->num_output; i++)
@@ -597,9 +572,6 @@ xf86RandR12CrtcNotify (RRCrtcPtr	randr_c
     return ret;
 }
 
-extern Bool i830RandR12Rotate(ScreenPtr pScreen, RRCrtcPtr randr_crtc, 
-		DisplayModePtr mode, Rotation rotation);
-
 static Bool
 xf86RandR12CrtcSet (ScreenPtr	pScreen,
 		  RRCrtcPtr	randr_crtc,
@@ -616,8 +588,6 @@ xf86RandR12CrtcSet (ScreenPtr	pScreen,
     DisplayModePtr	mode = randr_mode ? randr_mode->devPrivate : NULL;
     Bool		changed = FALSE;
     Bool		pos_changed;
-    Bool		rotation_changed = FALSE;
-    Rotation 		old_rotation;
     int			o, ro;
     xf86CrtcPtr		*save_crtcs;
     Bool		save_enabled = crtc->enabled;
@@ -631,14 +601,6 @@ xf86RandR12CrtcSet (ScreenPtr	pScreen,
     pos_changed = changed;
     if (x != crtc->x || y != crtc->y)
 	pos_changed = TRUE;
-
-    old_rotation = xf86RandR12GetRotation12(randr_crtc);
-    if (rotation != old_rotation) {
-	changed = TRUE;
-	rotation_changed = TRUE;
-	pos_changed = TRUE;
-    }
-
     for (o = 0; o < config->num_output; o++) 
     {
 	xf86OutputPtr  output = config->output[o];
@@ -674,14 +636,6 @@ xf86RandR12CrtcSet (ScreenPtr	pScreen,
 	    pI830->AccelInfoRec->NeedToSync = FALSE;
 	}
 
-	/* rotation should take effect when crtc enabled*/
-	if (rotation_changed && crtc->enabled) {
-	    randr_crtc->rotation = rotation;
-	    if (!i830RandR12Rotate(pScreen, randr_crtc, mode, rotation)) {
-	        randr_crtc->rotation = old_rotation;
-  	    }
-        }
-
 	if (mode)
 	{
 	    if (!i830PipeSetMode (crtc, mode, TRUE))
diff --git a/src/i830_rotate.c b/src/i830_rotate.c
index 081690b..029f439 100644
--- a/src/i830_rotate.c
+++ b/src/i830_rotate.c
@@ -60,13 +60,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "i830.h"
 #include "i915_reg.h"
 #include "i915_3d.h"
-#include "i830_xf86Crtc.h"
-#include "i830_randr.h"
 #include "brw_defines.h"
 #include "brw_structs.h"
 
-#include "brw_defines.h"
-#include "brw_structs.h"
 #ifdef XF86DRI
 #include "dri.h"
 #endif
@@ -1345,268 +1341,6 @@ I830UpdateRotate (ScreenPtr      pScreen
 #endif
 }
 
-static
-Bool i830_setup_shadowfb(ScrnInfoPtr pScrn, xf86CrtcPtr crtc)
-{
-    I830Ptr  		pI830 = I830PTR(pScrn);
-    I830CrtcPrivatePtr  intel_crtc = I830CrtcPrivate(crtc);
-    ShadowUpdateProc    func = NULL;
-
-    if (pI830->noAccel)
-        func = LoaderSymbol("shadowUpdateRotatePacked");
-    else {
-      if (IS_I9XX(pI830)) {
-	 if (IS_I965G(pI830))
-	     func = I965UpdateRotate;
-	 else 
-	     func = I915UpdateRotate;
-      } else
-	 func = I830UpdateRotate;
-    }
-
-    if (!func)
-	return FALSE;
-
-   shadowRemove (pScrn->pScreen, NULL);
-   if (intel_crtc->rotation != RR_Rotate_0) {
-      shadowAdd (pScrn->pScreen, 
-		 (*pScrn->pScreen->GetScreenPixmap) (pScrn->pScreen),
-		 func, I830WindowLinear, intel_crtc->rotation, 0);
-   }
-
-   if (intel_crtc->rotation != RR_Rotate_0)
-       pScrn->fbOffset = pI830->RotatedMem.Start;
-   else
-       pScrn->fbOffset = pI830->FrontBuffer.Start;
-
-   I830SelectBuffer(pScrn, I830_SELECT_FRONT);
-
-   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)(pI830->FbBase + pScrn->fbOffset));
-   (*pScrn->EnableDisableFBAccess) (pScrn->pScreen->myNum, FALSE);
-   (*pScrn->EnableDisableFBAccess) (pScrn->pScreen->myNum, TRUE);
-   
-   return TRUE;
-}
-
-static
-Bool i830_rotate_mem_realloc(ScrnInfoPtr pScrn, xf86CrtcPtr crtc)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   I830CrtcPrivatePtr intel_crtc = I830CrtcPrivate(crtc);
-#ifdef XF86DRI
-    Bool 		didLock = FALSE;
-#endif
-    int i;
-
-#ifdef XF86DRI
-   if (pI830->directRenderingEnabled) {
-      didLock = I830DRILock(pScrn);
-      
-      /* Do heap teardown here
-       */
-      if (pI830->mmModeFlags & I830_KERNEL_TEX) {
-	 drmI830MemDestroyHeap destroy;
-	 destroy.region = I830_MEM_REGION_AGP;
-	 
-	 if (drmCommandWrite(pI830->drmSubFD, 
-			     DRM_I830_DESTROY_HEAP, 
-			     &destroy, sizeof(destroy))) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		       "[dri] I830 destroy heap failed\n");
-	 }
-      }
-      
-      if (pI830->mmModeFlags & I830_KERNEL_TEX) {
-	 if (pI830->TexMem.Key != -1)
-	    xf86UnbindGARTMemory(pScrn->scrnIndex, pI830->TexMem.Key);
-	 I830FreeVidMem(pScrn, &(pI830->TexMem));
-      }
-      if (pI830->StolenPool.Allocated.Key != -1) {
-         xf86UnbindGARTMemory(pScrn->scrnIndex, pI830->StolenPool.Allocated.Key);
-         xf86DeallocateGARTMemory(pScrn->scrnIndex, pI830->StolenPool.Allocated.Key);
-      }
-      if (pI830->DepthBuffer.Key != -1)
-         xf86UnbindGARTMemory(pScrn->scrnIndex, pI830->DepthBuffer.Key);
-      I830FreeVidMem(pScrn, &(pI830->DepthBuffer));
-      if (pI830->BackBuffer.Key != -1)
-         xf86UnbindGARTMemory(pScrn->scrnIndex, pI830->BackBuffer.Key);
-      I830FreeVidMem(pScrn, &(pI830->BackBuffer));
-   }
-#endif
-
-      if (pI830->RotatedMem.Key != -1)
-         xf86UnbindGARTMemory(pScrn->scrnIndex, pI830->RotatedMem.Key);
- 
-      I830FreeVidMem(pScrn, &(pI830->RotatedMem));
-      memset(&(pI830->RotatedMem), 0, sizeof(pI830->RotatedMem));
-      pI830->RotatedMem.Key = -1;
-
-      if (IS_I965G(pI830)) {
-         if (pI830->RotateStateMem.Key != -1)
-            xf86UnbindGARTMemory(pScrn->scrnIndex, pI830->RotateStateMem.Key);
- 
-         I830FreeVidMem(pScrn, &(pI830->RotateStateMem));
-         memset(&(pI830->RotateStateMem), 0, sizeof(pI830->RotateStateMem));
-      	 pI830->RotateStateMem.Key = -1;
-      }
-
-      if (intel_crtc->rotation != RR_Rotate_0) {
-         if (!I830AllocateRotatedBuffer(pScrn, pI830->disableTiling ? ALLOC_NO_TILING : 0))
-            goto BAIL1;
-
-         I830FixOffset(pScrn, &(pI830->RotatedMem));
-         if (pI830->RotatedMem.Key != -1)
-            xf86BindGARTMemory(pScrn->scrnIndex, pI830->RotatedMem.Key, pI830->RotatedMem.Offset);
-	 if (IS_I965G(pI830)) {
-            I830FixOffset(pScrn, &(pI830->RotateStateMem));
-            if (pI830->RotateStateMem.Key != -1)
-            	xf86BindGARTMemory(pScrn->scrnIndex, pI830->RotateStateMem.Key, 
-				   pI830->RotateStateMem.Offset);
-	 }
-      }
-  
-#ifdef XF86DRI
-   if (pI830->directRenderingEnabled) {
-      if (!I830AllocateBackBuffer(pScrn,
-			      pI830->disableTiling ? ALLOC_NO_TILING : 0))
-         goto BAIL2;
-
-      if (!I830AllocateDepthBuffer(pScrn,
-			      pI830->disableTiling ? ALLOC_NO_TILING : 0))
-         goto BAIL3;
-
-      if (pI830->mmModeFlags & I830_KERNEL_TEX) {
-	 if (!I830AllocateTextureMemory(pScrn,
-					pI830->disableTiling ? ALLOC_NO_TILING : 0))
-	    goto BAIL4;
-      }
-
-      I830DoPoolAllocation(pScrn, &(pI830->StolenPool));
-
-      I830FixOffset(pScrn, &(pI830->BackBuffer));
-      I830FixOffset(pScrn, &(pI830->DepthBuffer));
-
-      if (pI830->BackBuffer.Key != -1)
-         xf86BindGARTMemory(pScrn->scrnIndex, pI830->BackBuffer.Key, pI830->BackBuffer.Offset);
-      if (pI830->DepthBuffer.Key != -1)
-         xf86BindGARTMemory(pScrn->scrnIndex, pI830->DepthBuffer.Key, pI830->DepthBuffer.Offset);
-      if (pI830->StolenPool.Allocated.Key != -1)
-         xf86BindGARTMemory(pScrn->scrnIndex, pI830->StolenPool.Allocated.Key, pI830->StolenPool.Allocated.Offset);
-      if (pI830->mmModeFlags & I830_KERNEL_TEX) {
-	 if (pI830->TexMem.Key != -1)
-	    xf86BindGARTMemory(pScrn->scrnIndex, pI830->TexMem.Key, pI830->TexMem.Offset);
-      }
-      I830SetupMemoryTiling(pScrn);
-      /* 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, pI830->ModeReg.Fence[i]);
-      }
-
-      {
-         drmI830Sarea *sarea = DRIGetSAREAPrivate(pScrn->pScreen);
-         I830UpdateDRIBuffers(pScrn, sarea );
-      }
-      
-      if (didLock)
-	 I830DRIUnlock(pScrn);
-   }
-#endif
-
-   return TRUE;
-BAIL1:
-BAIL2:
-BAIL3:
-BAIL4:
-   //XXX alloc failure
-   return FALSE;
-}
-
-Bool
-i830RandR12Rotate(ScreenPtr pScreen, RRCrtcPtr randr_crtc, 
-		DisplayModePtr mode, Rotation rotation)
-{
-    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
-    I830Ptr  		pI830 = I830PTR(pScrn);
-    xf86CrtcPtr		crtc = randr_crtc->devPrivate;
-    I830CrtcPrivatePtr  intel_crtc = I830CrtcPrivate(crtc);
-    Rotation		old_rotation = intel_crtc->rotation;
-
-    if (old_rotation == rotation)
-	return TRUE;
-    intel_crtc->rotation = rotation;
-    pI830->rotation = rotation;
-
-   *pI830->used3D |= 1<<31; /* use high bit to denote new rotation occured */
-
-
-    /* user should have already changed screen size. */
-    /* pI830->displayWidth should always trigger current width in use, 
-       pScrn->displayWidth is current config in use. */
-   switch (intel_crtc->rotation) {
-      case RR_Rotate_0:
-	ErrorF("Rotating Screen to 0 degrees\n");
-         pScrn->displayWidth = pI830->displayWidth;
-         break;
-      case RR_Rotate_90:
-	ErrorF("Rotating Screen to 90 degrees\n");
-         pScrn->displayWidth = pScrn->pScreen->width;
-         break;
-      case RR_Rotate_180:
-	ErrorF("Rotating Screen to 180 degrees\n");
-         pScrn->displayWidth = pI830->displayWidth;
-         break;
-      case RR_Rotate_270:
-	ErrorF("Rotating Screen to 270 degrees\n");
-         pScrn->displayWidth = pScrn->pScreen->width;
-         break;
-   }
-   ErrorF("pScrn->displayWidth %d\n", pScrn->displayWidth);
-
-   if (!i830_rotate_mem_realloc(pScrn, crtc)) {
-	intel_crtc->rotation = old_rotation;
-	return FALSE;
-   }
-   
-   if (!i830_setup_shadowfb(pScrn, crtc)) {
-	intel_crtc->rotation = old_rotation;
-	return FALSE;
-   }
-
-
-#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 (intel_crtc->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;
-}
-
 Bool
 I830Rotate(ScrnInfoPtr pScrn, DisplayModePtr mode)
 {
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index b66d226..ea62ad9 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -1095,6 +1095,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
     output->doubleScanAllowed = FALSE;
     
     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.
@@ -1218,7 +1219,7 @@ 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);
-    intel_output->type = I830_OUTPUT_SDVO;
+
     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 	       "%s device VID/DID: %02X:%02X.%02X, "
 	       "clock range %.1fMHz - %.1fMHz, "
diff --git a/src/i830_tv.c b/src/i830_tv.c
index 0ba2339..92e417e 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -422,15 +422,13 @@ i830_tv_dpms(xf86OutputPtr output, int m
 
     switch(mode) {
     case DPMSModeOn:
-            /* Wait for a Vblank when reenable TV encoder */
-	    i830WaitForVblank(pScrn);
-	    OUTREG(TV_CTL, INREG(TV_CTL) | TV_ENC_ENABLE);
-	    break;
+	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;
+	OUTREG(TV_CTL, INREG(TV_CTL) & ~TV_ENC_ENABLE);
+	break;
     }
 }
 
@@ -689,10 +687,10 @@ i830_tv_mode_set(xf86OutputPtr output, D
      * mode.  For now, just set the first one in the list, with
      * NTSC format.
      */
-    OUTREG(TV_CTL, INREG(TV_CTL) & ~TV_ENC_ENABLE);
     tv_mode = &tv_modes[0];
     
     tv_ctl = 0;
+
     switch (dev_priv->type) {
     default:
     case TV_TYPE_UNKNOWN:
@@ -783,8 +781,8 @@ i830_tv_mode_set(xf86OutputPtr output, D
 	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) 
-	    tv_ctl |= TV_ENC_C0_FIX | TV_ENC_SDP_FIX;
+    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)
diff-tree 7473e7d5297f94164e0f35822166713fb21a11bd (from parents)
Merge: cdde9e7f4a0645ab1ee3e124de54433c1a250097 a87801f73a73e53524237be7835b8cd8b3eb282c
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Sun Jan 7 22:50:27 2007 -0800

    Merge branch 'crestline-otc' into crestline

diff-tree cdde9e7f4a0645ab1ee3e124de54433c1a250097 (from parents)
Merge: 3110630e04f37e184609c91494fa7f9f4d59b93f 0fd2752f199928f846fe03c9087f7b6d48cc28d9
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Sun Jan 7 22:50:12 2007 -0800

    Merge branch 'modesetting' into crestline

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 3110630e04f37e184609c91494fa7f9f4d59b93f (from parents)
Merge: be9b635b82c0c77ccc0555f178f94de6e5338e27 736d82a6b43f174cb95b425faacd4b0b889916fa
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Sun Jan 7 22:44:36 2007 -0800

    Merge branch 'modesetting' into crestline
    
    Conflicts:
    
    	src/i830_rotate.c
    
    Pull in upstream changes to crestline branch leaving only
    the PCI-IDs as local changes.

diff --cc src/i830_rotate.c
index 1f1824b,029f439..081690b
@@@ -60,11 -60,9 +60,13 @@@
  #include "i830.h"
  #include "i915_reg.h"
  #include "i915_3d.h"
 +#include "i830_xf86Crtc.h"
 +#include "i830_randr.h"
+ #include "brw_defines.h"
+ #include "brw_structs.h"
  
 +#include "brw_defines.h"
 +#include "brw_structs.h"
  #ifdef XF86DRI
  #include "dri.h"
  #endif
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 a87801f73a73e53524237be7835b8cd8b3eb282c (from 9cf759a2cb2580c4ac5f8cdc983389642f3cfce0)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Thu Jan 4 14:47:48 2007 +0800

    Fix TV load detect
    
    Actually load TV, otherwise we don't have expected
    reg state to probe.

diff --git a/src/i830_tv.c b/src/i830_tv.c
index 0580a95..5bd9eca 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -1067,6 +1067,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);
 	}
 	i830_tv_detect_type (crtc, output);
 	i830ReleaseLoadDetectPipe (output);
diff-tree 9cf759a2cb2580c4ac5f8cdc983389642f3cfce0 (from 9e48808fccf5b153c2fb4027f9a09944574fdace)
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 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 be9b635b82c0c77ccc0555f178f94de6e5338e27 (from parents)
Merge: 9e48808fccf5b153c2fb4027f9a09944574fdace 5a793b0dcf2d5de408b55073858fcfba6d99f994
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Wed Jan 3 22:15:53 2007 -0800

    Merge branch 'modesetting' into crestline

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 9e48808fccf5b153c2fb4027f9a09944574fdace (from ebd636dbd62cb69ed7defbd86f297c6bc7dac5dd)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Thu Jan 4 11:25:31 2007 +0800

    Fix EXA mem binding
    
    We should check if EXA is really enabled.

diff --git a/src/i830_memory.c b/src/i830_memory.c
index 29108c5..3a3836c 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -863,7 +863,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);
@@ -1535,9 +1535,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;
 }
@@ -1949,10 +1951,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 ebd636dbd62cb69ed7defbd86f297c6bc7dac5dd (from parents)
Merge: 75f0033ec41a34bbe695cfd4a9bc9aa60e919c99 3d9ea6f3c8a274f930d286fc15d3665dfaa8327a
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Thu Jan 4 10:13:55 2007 +0800

    Merge branch 'modesetting' into crestline
    
    Conflicts:
    
    	src/i830.h
    	src/i830_randr.c

diff --cc src/i830.h
index 6c03a73,d5ca5d4..a03f877
@@@ -195,9 -194,8 +195,10 @@@
  
  typedef struct _I830CrtcPrivateRec {
      int			    pipe;
-     Bool		    gammaEnabled;
 +    Rotation 		    rotation;    /* current rotation, mirror from pI830->rotation */
 +    Rotation		    rotations;  /* all */
+     /* 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)
diff --cc src/i830_memory.c
index 6944863,5bbf3e3..29108c5
@@@ -682,262 -801,46 +823,65 @@@
           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);
        }
 +      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;
diff --cc src/i830_sdvo.c
index 8e38779,19b4b93..4fc5921
@@@ -1091,8 -1091,11 +1091,10 @@@
  	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;
  
      /* 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-tree 3d9ea6f3c8a274f930d286fc15d3665dfaa8327a (from parents)
Merge: 75f4df278e9db360967d77cdba4756cbde622d56 394124ceaadb46d976ad5c3bdeb1b77d351c57f6
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Thu Jan 4 10:12:50 2007 +0800

    Merge branch 'modesetting' of git+ssh://zhen@git.freedesktop.org/git/xorg/driver/xf86-video-intel into modesetting
    
    Conflicts:
    
    	src/i830_driver.c

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 75f0033ec41a34bbe695cfd4a9bc9aa60e919c99 (from fbd3f588f0d412c20cc3f86dfad73700734a9a76)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Sun Dec 31 15:16:59 2006 +0800

    Issue current virtual size to mode valid.
    
    Revert change in rotation patch.

diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index 6e836bd..0c482a2 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -517,7 +517,6 @@ xf86SetScrnInfoModes (ScrnInfoPtr pScrn)
     xf86CrtcPtr		crtc;
     DisplayModePtr	last, mode;
     int			originalVirtualX, originalVirtualY;
-    I830Ptr		pI830 = I830PTR(pScrn);
 
     output = config->output[config->compat_output];
     if (!output->crtc)
@@ -550,10 +549,9 @@ xf86SetScrnInfoModes (ScrnInfoPtr pScrn)
     /* Disable modes in the XFree86 DDX list that are larger than the current
      * virtual size.
      */
-    /* pass real line pitch, rotation might change this */
     i830xf86ValidateModesSize(pScrn, pScrn->modes,
 			      originalVirtualX, originalVirtualY,
-			      pI830->displayWidth);
+			      pScrn->displayWidth);
 
     /* Strip out anything that we threw out for virtualX/Y. */
     i830xf86PruneInvalidModes(pScrn, &pScrn->modes, TRUE);
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 fbd3f588f0d412c20cc3f86dfad73700734a9a76 (from a1796bfb51d90fd545973909404e1a77ad27c9cc)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Fri Dec 29 10:47:52 2006 +0800

    rotation support for randr-1.2
    
    This patch trys to resolve rotation regression with randr-1.2.
    Tested with Crestline VGA output. See bug 83.

diff --git a/src/i830.h b/src/i830.h
index 20bcde6..6c03a73 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -196,6 +196,8 @@ extern const char *i830_output_type_name
 typedef struct _I830CrtcPrivateRec {
     int			    pipe;
     Bool		    gammaEnabled;
+    Rotation 		    rotation;    /* current rotation, mirror from pI830->rotation */
+    Rotation		    rotations;  /* all */
 } I830CrtcPrivateRec, *I830CrtcPrivatePtr;
 
 #define I830CrtcPrivate(c) ((I830CrtcPrivatePtr) (c)->driver_private)
diff --git a/src/i830_display.c b/src/i830_display.c
index c5880d6..b70f1eb 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -821,7 +821,9 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
 	((adjusted_mode->CrtcVBlankEnd - 1) << 16));
     OUTREG(vsync_reg, (adjusted_mode->CrtcVSyncStart - 1) |
 	((adjusted_mode->CrtcVSyncEnd - 1) << 16));
-    OUTREG(dspstride_reg, pScrn->displayWidth * pI830->cpp);
+  /* XXX we might always set real line stride, rotation can change it */
+  //  OUTREG(dspstride_reg, pScrn->displayWidth * pI830->cpp);
+    OUTREG(dspstride_reg, pI830->displayWidth * pI830->cpp);
     /* pipesrc and dspsize control the size that is scaled from, which should
      * always be the user's requested size.
      */
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 23729de..5e66038 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2950,11 +2950,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;
diff --git a/src/i830_randr.c b/src/i830_randr.c
index 3d6febc..019e71c 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -333,6 +333,14 @@ xf86RandR12GetRotation(ScreenPtr pScreen
     return randrp->rotation;
 }
 
+Rotation
+xf86RandR12GetRotation12(RRCrtcPtr randr_crtc)
+{
+    xf86CrtcPtr		crtc = randr_crtc->devPrivate;
+    I830CrtcPrivatePtr  intel_crtc = I830CrtcPrivate(crtc);
+    return intel_crtc->rotation;
+}
+
 Bool
 xf86RandR12CreateScreenResources (ScreenPtr pScreen)
 {
@@ -422,12 +430,29 @@ xf86RandR12Init (ScreenPtr pScreen)
     return TRUE;
 }
 
+/* RandR12 should have been initialized, so we might set rotations
+   to Crtc object. 
+ */
 void
 xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotations)
 {
     XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
+#if RANDR_12_INTERFACE
+    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int c;
+#endif
 
     randrp->supported_rotations = rotations;
+#if RANDR_12_INTERFACE
+    for (c = 0; c < config->num_crtc ; c++) {
+	xf86CrtcPtr    crtc = config->crtc[c];
+	I830CrtcPrivatePtr intel_crtc = I830CrtcPrivate(crtc);
+	crtc->randr_crtc->rotations = rotations;
+	intel_crtc->rotations = rotations;
+	intel_crtc->rotation = RR_Rotate_0; /*XXX initial rotation fix */
+    }
+#endif
 }
 
 void
@@ -468,11 +493,13 @@ xf86RandR12ScreenSetSize (ScreenPtr	pScr
     }
     if (pRoot)
 	(*pScrn->EnableDisableFBAccess) (pScreen->myNum, FALSE);
-    pScrn->virtualX = width;
-    pScrn->virtualY = height;
-
-    pScreen->width = pScrn->virtualX;
-    pScreen->height = pScrn->virtualY;
+    /* XXX don't change the actual draw window size */
+    /*pScrn->virtualX = width;
+     *pScrn->virtualY = height;
+     *pScreen->width = pScrn->virtualX;
+     *pScreen->height = pScrn->virtualY;*/
+    pScreen->width = width;
+    pScreen->height = height;
     pScreen->mmWidth = mmWidth;
     pScreen->mmHeight = mmHeight;
 
@@ -509,7 +536,7 @@ xf86RandR12CrtcNotify (RRCrtcPtr	randr_c
 	return FALSE;
     x = crtc->x;
     y = crtc->y;
-    rotation = RR_Rotate_0;
+    rotation = xf86RandR12GetRotation12(randr_crtc);
     numOutputs = 0;
     randr_mode = NULL;
     for (i = 0; i < config->num_output; i++)
@@ -540,6 +567,9 @@ xf86RandR12CrtcNotify (RRCrtcPtr	randr_c
     return ret;
 }
 
+extern Bool i830RandR12Rotate(ScreenPtr pScreen, RRCrtcPtr randr_crtc, 
+		DisplayModePtr mode, Rotation rotation);
+
 static Bool
 xf86RandR12CrtcSet (ScreenPtr	pScreen,
 		  RRCrtcPtr	randr_crtc,
@@ -556,6 +586,8 @@ xf86RandR12CrtcSet (ScreenPtr	pScreen,
     DisplayModePtr	mode = randr_mode ? randr_mode->devPrivate : NULL;
     Bool		changed = FALSE;
     Bool		pos_changed;
+    Bool		rotation_changed = FALSE;
+    Rotation 		old_rotation;
     int			o, ro;
     xf86CrtcPtr		*save_crtcs;
     Bool		save_enabled = crtc->enabled;
@@ -569,6 +601,14 @@ xf86RandR12CrtcSet (ScreenPtr	pScreen,
     pos_changed = changed;
     if (x != crtc->x || y != crtc->y)
 	pos_changed = TRUE;
+
+    old_rotation = xf86RandR12GetRotation12(randr_crtc);
+    if (rotation != old_rotation) {
+	changed = TRUE;
+	rotation_changed = TRUE;
+	pos_changed = TRUE;
+    }
+
     for (o = 0; o < config->num_output; o++) 
     {
 	xf86OutputPtr  output = config->output[o];
@@ -604,6 +644,14 @@ xf86RandR12CrtcSet (ScreenPtr	pScreen,
 	    pI830->AccelInfoRec->NeedToSync = FALSE;
 	}
 
+	/* rotation should take effect when crtc enabled*/
+	if (rotation_changed && crtc->enabled) {
+	    randr_crtc->rotation = rotation;
+	    if (!i830RandR12Rotate(pScreen, randr_crtc, mode, rotation)) {
+	        randr_crtc->rotation = old_rotation;
+  	    }
+        }
+
 	if (mode)
 	{
 	    if (!i830PipeSetMode (crtc, mode, TRUE))
diff --git a/src/i830_rotate.c b/src/i830_rotate.c
index b2587b2..1f1824b 100644
--- a/src/i830_rotate.c
+++ b/src/i830_rotate.c
@@ -60,9 +60,11 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "i830.h"
 #include "i915_reg.h"
 #include "i915_3d.h"
+#include "i830_xf86Crtc.h"
+#include "i830_randr.h"
+
 #include "brw_defines.h"
 #include "brw_structs.h"
-
 #ifdef XF86DRI
 #include "dri.h"
 #endif
@@ -1341,6 +1343,268 @@ I830UpdateRotate (ScreenPtr      pScreen
 #endif
 }
 
+static
+Bool i830_setup_shadowfb(ScrnInfoPtr pScrn, xf86CrtcPtr crtc)
+{
+    I830Ptr  		pI830 = I830PTR(pScrn);
+    I830CrtcPrivatePtr  intel_crtc = I830CrtcPrivate(crtc);
+    ShadowUpdateProc    func = NULL;
+
+    if (pI830->noAccel)
+        func = LoaderSymbol("shadowUpdateRotatePacked");
+    else {
+      if (IS_I9XX(pI830)) {
+	 if (IS_I965G(pI830))
+	     func = I965UpdateRotate;
+	 else 
+	     func = I915UpdateRotate;
+      } else
+	 func = I830UpdateRotate;
+    }
+
+    if (!func)
+	return FALSE;
+
+   shadowRemove (pScrn->pScreen, NULL);
+   if (intel_crtc->rotation != RR_Rotate_0) {
+      shadowAdd (pScrn->pScreen, 
+		 (*pScrn->pScreen->GetScreenPixmap) (pScrn->pScreen),
+		 func, I830WindowLinear, intel_crtc->rotation, 0);
+   }
+
+   if (intel_crtc->rotation != RR_Rotate_0)
+       pScrn->fbOffset = pI830->RotatedMem.Start;
+   else
+       pScrn->fbOffset = pI830->FrontBuffer.Start;
+
+   I830SelectBuffer(pScrn, I830_SELECT_FRONT);
+
+   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)(pI830->FbBase + pScrn->fbOffset));
+   (*pScrn->EnableDisableFBAccess) (pScrn->pScreen->myNum, FALSE);
+   (*pScrn->EnableDisableFBAccess) (pScrn->pScreen->myNum, TRUE);
+   
+   return TRUE;
+}
+
+static
+Bool i830_rotate_mem_realloc(ScrnInfoPtr pScrn, xf86CrtcPtr crtc)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+   I830CrtcPrivatePtr intel_crtc = I830CrtcPrivate(crtc);
+#ifdef XF86DRI
+    Bool 		didLock = FALSE;
+#endif
+    int i;
+
+#ifdef XF86DRI
+   if (pI830->directRenderingEnabled) {
+      didLock = I830DRILock(pScrn);
+      
+      /* Do heap teardown here
+       */
+      if (pI830->mmModeFlags & I830_KERNEL_TEX) {
+	 drmI830MemDestroyHeap destroy;
+	 destroy.region = I830_MEM_REGION_AGP;
+	 
+	 if (drmCommandWrite(pI830->drmSubFD, 
+			     DRM_I830_DESTROY_HEAP, 
+			     &destroy, sizeof(destroy))) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "[dri] I830 destroy heap failed\n");
+	 }
+      }
+      
+      if (pI830->mmModeFlags & I830_KERNEL_TEX) {
+	 if (pI830->TexMem.Key != -1)
+	    xf86UnbindGARTMemory(pScrn->scrnIndex, pI830->TexMem.Key);
+	 I830FreeVidMem(pScrn, &(pI830->TexMem));
+      }
+      if (pI830->StolenPool.Allocated.Key != -1) {
+         xf86UnbindGARTMemory(pScrn->scrnIndex, pI830->StolenPool.Allocated.Key);
+         xf86DeallocateGARTMemory(pScrn->scrnIndex, pI830->StolenPool.Allocated.Key);
+      }
+      if (pI830->DepthBuffer.Key != -1)
+         xf86UnbindGARTMemory(pScrn->scrnIndex, pI830->DepthBuffer.Key);
+      I830FreeVidMem(pScrn, &(pI830->DepthBuffer));
+      if (pI830->BackBuffer.Key != -1)
+         xf86UnbindGARTMemory(pScrn->scrnIndex, pI830->BackBuffer.Key);
+      I830FreeVidMem(pScrn, &(pI830->BackBuffer));
+   }
+#endif
+
+      if (pI830->RotatedMem.Key != -1)
+         xf86UnbindGARTMemory(pScrn->scrnIndex, pI830->RotatedMem.Key);
+ 
+      I830FreeVidMem(pScrn, &(pI830->RotatedMem));
+      memset(&(pI830->RotatedMem), 0, sizeof(pI830->RotatedMem));
+      pI830->RotatedMem.Key = -1;
+
+      if (IS_I965G(pI830)) {
+         if (pI830->RotateStateMem.Key != -1)
+            xf86UnbindGARTMemory(pScrn->scrnIndex, pI830->RotateStateMem.Key);
+ 
+         I830FreeVidMem(pScrn, &(pI830->RotateStateMem));
+         memset(&(pI830->RotateStateMem), 0, sizeof(pI830->RotateStateMem));
+      	 pI830->RotateStateMem.Key = -1;
+      }
+
+      if (intel_crtc->rotation != RR_Rotate_0) {
+         if (!I830AllocateRotatedBuffer(pScrn, pI830->disableTiling ? ALLOC_NO_TILING : 0))
+            goto BAIL1;
+
+         I830FixOffset(pScrn, &(pI830->RotatedMem));
+         if (pI830->RotatedMem.Key != -1)
+            xf86BindGARTMemory(pScrn->scrnIndex, pI830->RotatedMem.Key, pI830->RotatedMem.Offset);
+	 if (IS_I965G(pI830)) {
+            I830FixOffset(pScrn, &(pI830->RotateStateMem));
+            if (pI830->RotateStateMem.Key != -1)
+            	xf86BindGARTMemory(pScrn->scrnIndex, pI830->RotateStateMem.Key, 
+				   pI830->RotateStateMem.Offset);
+	 }
+      }
+  
+#ifdef XF86DRI
+   if (pI830->directRenderingEnabled) {
+      if (!I830AllocateBackBuffer(pScrn,
+			      pI830->disableTiling ? ALLOC_NO_TILING : 0))
+         goto BAIL2;
+
+      if (!I830AllocateDepthBuffer(pScrn,
+			      pI830->disableTiling ? ALLOC_NO_TILING : 0))
+         goto BAIL3;
+
+      if (pI830->mmModeFlags & I830_KERNEL_TEX) {
+	 if (!I830AllocateTextureMemory(pScrn,
+					pI830->disableTiling ? ALLOC_NO_TILING : 0))
+	    goto BAIL4;
+      }
+
+      I830DoPoolAllocation(pScrn, &(pI830->StolenPool));
+
+      I830FixOffset(pScrn, &(pI830->BackBuffer));
+      I830FixOffset(pScrn, &(pI830->DepthBuffer));
+
+      if (pI830->BackBuffer.Key != -1)
+         xf86BindGARTMemory(pScrn->scrnIndex, pI830->BackBuffer.Key, pI830->BackBuffer.Offset);
+      if (pI830->DepthBuffer.Key != -1)
+         xf86BindGARTMemory(pScrn->scrnIndex, pI830->DepthBuffer.Key, pI830->DepthBuffer.Offset);
+      if (pI830->StolenPool.Allocated.Key != -1)
+         xf86BindGARTMemory(pScrn->scrnIndex, pI830->StolenPool.Allocated.Key, pI830->StolenPool.Allocated.Offset);
+      if (pI830->mmModeFlags & I830_KERNEL_TEX) {
+	 if (pI830->TexMem.Key != -1)
+	    xf86BindGARTMemory(pScrn->scrnIndex, pI830->TexMem.Key, pI830->TexMem.Offset);
+      }
+      I830SetupMemoryTiling(pScrn);
+      /* 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, pI830->ModeReg.Fence[i]);
+      }
+
+      {
+         drmI830Sarea *sarea = DRIGetSAREAPrivate(pScrn->pScreen);
+         I830UpdateDRIBuffers(pScrn, sarea );
+      }
+      
+      if (didLock)
+	 I830DRIUnlock(pScrn);
+   }
+#endif
+
+   return TRUE;
+BAIL1:
+BAIL2:
+BAIL3:
+BAIL4:
+   //XXX alloc failure
+   return FALSE;
+}
+
+Bool
+i830RandR12Rotate(ScreenPtr pScreen, RRCrtcPtr randr_crtc, 
+		DisplayModePtr mode, Rotation rotation)
+{
+    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+    I830Ptr  		pI830 = I830PTR(pScrn);
+    xf86CrtcPtr		crtc = randr_crtc->devPrivate;
+    I830CrtcPrivatePtr  intel_crtc = I830CrtcPrivate(crtc);
+    Rotation		old_rotation = intel_crtc->rotation;
+
+    if (old_rotation == rotation)
+	return TRUE;
+    intel_crtc->rotation = rotation;
+    pI830->rotation = rotation;
+
+   *pI830->used3D |= 1<<31; /* use high bit to denote new rotation occured */
+
+
+    /* user should have already changed screen size. */
+    /* pI830->displayWidth should always trigger current width in use, 
+       pScrn->displayWidth is current config in use. */
+   switch (intel_crtc->rotation) {
+      case RR_Rotate_0:
+	ErrorF("Rotating Screen to 0 degrees\n");
+         pScrn->displayWidth = pI830->displayWidth;
+         break;
+      case RR_Rotate_90:
+	ErrorF("Rotating Screen to 90 degrees\n");
+         pScrn->displayWidth = pScrn->pScreen->width;
+         break;
+      case RR_Rotate_180:
+	ErrorF("Rotating Screen to 180 degrees\n");
+         pScrn->displayWidth = pI830->displayWidth;
+         break;
+      case RR_Rotate_270:
+	ErrorF("Rotating Screen to 270 degrees\n");
+         pScrn->displayWidth = pScrn->pScreen->width;
+         break;
+   }
+   ErrorF("pScrn->displayWidth %d\n", pScrn->displayWidth);
+
+   if (!i830_rotate_mem_realloc(pScrn, crtc)) {
+	intel_crtc->rotation = old_rotation;
+	return FALSE;
+   }
+   
+   if (!i830_setup_shadowfb(pScrn, crtc)) {
+	intel_crtc->rotation = old_rotation;
+	return FALSE;
+   }
+
+
+#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 (intel_crtc->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;
+}
+
 Bool
 I830Rotate(ScrnInfoPtr pScrn, DisplayModePtr mode)
 {
diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index 0c482a2..6e836bd 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -517,6 +517,7 @@ xf86SetScrnInfoModes (ScrnInfoPtr pScrn)
     xf86CrtcPtr		crtc;
     DisplayModePtr	last, mode;
     int			originalVirtualX, originalVirtualY;
+    I830Ptr		pI830 = I830PTR(pScrn);
 
     output = config->output[config->compat_output];
     if (!output->crtc)
@@ -549,9 +550,10 @@ xf86SetScrnInfoModes (ScrnInfoPtr pScrn)
     /* Disable modes in the XFree86 DDX list that are larger than the current
      * virtual size.
      */
+    /* pass real line pitch, rotation might change this */
     i830xf86ValidateModesSize(pScrn, pScrn->modes,
 			      originalVirtualX, originalVirtualY,
-			      pScrn->displayWidth);
+			      pI830->displayWidth);
 
     /* Strip out anything that we threw out for virtualX/Y. */
     i830xf86PruneInvalidModes(pScrn, &pScrn->modes, TRUE);
diff-tree a1796bfb51d90fd545973909404e1a77ad27c9cc (from parents)
Merge: 84915ac8afeb4bbc03df8f94ab3ba351788d6501 fabfccd3d8a55a83138d361f66c53cb7e6d371a8
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Fri Dec 29 10:10:26 2006 +0800

    Merge branch 'crestline' of git+ssh://zhen@otc-graphics.jf.intel.com/git/xorg/driver/xf86-video-intel into crestline

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 fabfccd3d8a55a83138d361f66c53cb7e6d371a8 (from ddefce4f02eb3272ad37e890350f73f03eff73c9)
Author: Zou Nan hai <nanhai.zou at intel.com>
Date:   Thu Dec 28 14:48:54 2006 +0800

      Fix

diff --git a/src/i830_tv.c b/src/i830_tv.c
index 7e5daa6..9048d08 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -1064,7 +1064,7 @@ i830_tv_detect(xf86OutputPtr output)
 	if (intel_output->load_detect_temp)
 	{
 	    /* we only need the pixel clock set correctly here */
-	    mode = crtc->desiredMode;
+	    mode = reported_modes[0];
 	    xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
 	}
 	i830_tv_detect_type (crtc, output);
diff-tree ddefce4f02eb3272ad37e890350f73f03eff73c9 (from c5205595f2abacc9f736e1f53666302ec551cbc4)
Author: Zou Nan hai <nanhai.zou at intel.com>
Date:   Thu Dec 28 14:45:53 2006 +0800

     support NTSC 480i M-J 1280x1024 1024x768 800x600 640x480
     PAL 576i 1280x1024 1024x768 800x600 640x480
    
     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 0b43908..7e5daa6 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -249,6 +249,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
     {
@@ -645,7 +692,6 @@ i830_tv_mode_set(xf86OutputPtr output, D
     tv_mode = &tv_modes[0];
     
     tv_ctl = 0;
-
     switch (dev_priv->type) {
     default:
     case TV_TYPE_UNKNOWN:
@@ -804,22 +850,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
+	},
 };
 
 /**
@@ -918,9 +1064,8 @@ i830_tv_detect(xf86OutputPtr output)
 	if (intel_output->load_detect_temp)
 	{
 	    /* we only need the pixel clock set correctly here */
-	    mode = reported_modes[0];
+	    mode = crtc->desiredMode;
 	    xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
-	    i830PipeSetMode (crtc, &mode, FALSE);
 	}
 	i830_tv_detect_type (crtc, output);
 	i830ReleaseLoadDetectPipe (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 c5205595f2abacc9f736e1f53666302ec551cbc4 (from parents)
Merge: b8f3ec77104882fc755ddc88f2583cd5d15387a4 4c0c1aa882cfec77b2183baec93cbc4cfaf4abe0
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Dec 21 02:51:33 2006 -0800

    Merge branch 'modesetting' into crestline

diff --cc src/i830_tv.c
index 05b6825,6231891..0b43908
@@@ -400,12 -639,35 +641,36 @@@
       * mode.  For now, just set the first one in the list, with
       * NTSC format.
       */
 +    OUTREG(TV_CTL, INREG(TV_CTL) & ~TV_ENC_ENABLE);
      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);
  
@@@ -450,41 -711,30 +714,30 @@@
-     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)
 -	tv_ctl |= TV_ENC_C0_FIX | TV_ENC_SDP_FIX;
 +    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)
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 b8f3ec77104882fc755ddc88f2583cd5d15387a4 (from b83cbec34a8d1ff39bd303fcd27fc03dcdb1d6c3)
Author: Zou Nan hai <nanhai.zou at intel.com>
Date:   Thu Dec 21 10:46:17 2006 +0800

      This fix should be better, I830SetMode will call i830_sdvo_dump,
      if the sdvo is not initialized, X will crash. So any application which
      SetMode will crash X if there is no SDVO output.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index df5f130..8e38779 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -981,7 +981,7 @@ i830_sdvo_dump(ScrnInfoPtr pScrn)
 	xf86OutputPtr	output = xf86_config->output[i];
 	I830OutputPrivatePtr	intel_output = output->driver_private;
 	
-	if (intel_output->type == I830_OUTPUT_SDVO && (intel_output->pI2CBus))
+	if (intel_output->type == I830_OUTPUT_SDVO)
 	    i830_sdvo_dump_device(output);
     }
 }
@@ -1093,7 +1093,6 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
     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.
@@ -1212,7 +1211,7 @@ 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);
-
+    intel_output->type = I830_OUTPUT_SDVO;
     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 	       "%s device VID/DID: %02X:%02X.%02X, "
 	       "clock range %.1fMHz - %.1fMHz, "
diff-tree b83cbec34a8d1ff39bd303fcd27fc03dcdb1d6c3 (from 07d3f141712e2abf704cb68a59cd5d5c3390e2ca)
Author: Zou Nan hai <nanhai.zou at intel.com>
Date:   Wed Dec 20 17:32:05 2006 +0800

    fix null pointer reference,
    I hit this when running doom3-demo

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index cb68802..df5f130 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -981,7 +981,7 @@ i830_sdvo_dump(ScrnInfoPtr pScrn)
 	xf86OutputPtr	output = xf86_config->output[i];
 	I830OutputPrivatePtr	intel_output = output->driver_private;
 	
-	if (intel_output->type == I830_OUTPUT_SDVO)
+	if (intel_output->type == I830_OUTPUT_SDVO && (intel_output->pI2CBus))
 	    i830_sdvo_dump_device(output);
     }
 }
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 07d3f141712e2abf704cb68a59cd5d5c3390e2ca (from parents)
Merge: 0cd1a11d4493ef4a2d05ccf8aadec743504dba5f c28075e1d70c98b39fc9829a6a01da171a9b9426
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Tue Dec 19 22:01:02 2006 -0800

    Merge branch 'modesetting' into crestline

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 0cd1a11d4493ef4a2d05ccf8aadec743504dba5f (from 65cd18b97bc533b24031d6eb882fd3074779ceba)
Author: Zou Nan hai <nanhai.zou at intel.com>
Date:   Tue Dec 19 14:03:19 2006 +0800

      fix for bug #108

diff --git a/src/i830_tv.c b/src/i830_tv.c
index af9826b..46ce046 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -171,13 +171,15 @@ i830_tv_dpms(xf86OutputPtr output, int m
 
     switch(mode) {
     case DPMSModeOn:
-	OUTREG(TV_CTL, INREG(TV_CTL) | TV_ENC_ENABLE);
-	break;
+            /* Wait for a Vblank when reenable TV encoder */
+	    i830WaitForVblank(pScrn);
+	    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;
+	    /*OUTREG(TV_CTL, INREG(TV_CTL) & ~TV_ENC_ENABLE);*/
+	    break;
     }
 }
 
@@ -398,6 +400,7 @@ i830_tv_mode_set(xf86OutputPtr output, D
      * mode.  For now, just set the first one in the list, with
      * NTSC format.
      */
+    OUTREG(TV_CTL, INREG(TV_CTL) & ~TV_ENC_ENABLE);
     tv_mode = &tv_modes[0];
     sc_mode = &tv_sc_modes[TV_SC_NTSC_MJ];
 
@@ -480,8 +483,8 @@ i830_tv_mode_set(xf86OutputPtr output, D
 	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;
+    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)
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 1975fa5b010100196af201e40f43b30a149b7750 (from 08575331ac75783c9910cfb6e78db701a29983ac)
Author: Eamon Walsh <ewalsh at tycho.nsa.gov>
Date:   Mon Dec 18 14:08:55 2006 -0500

    Revert "Convert callers of LookupWindow() to dixLookupWindow()."
    
    This reverts commit 08575331ac75783c9910cfb6e78db701a29983ac.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index e133c85..e950d7c 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1760,9 +1760,8 @@ I830ProcXineramaGetState(ClientPtr clien
     register int		n;
 
     REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
-    n = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess);
-    if (n != Success)
-	return n;
+    pWin = LookupWindow(stuff->window, client);
+    if(!pWin) return BadWindow;
 
     rep.type = X_Reply;
     rep.length = 0;
@@ -1786,9 +1785,8 @@ I830ProcXineramaGetScreenCount(ClientPtr
     register int			n;
 
     REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
-    n = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess);
-    if (n != Success)
-	return n;
+    pWin = LookupWindow(stuff->window, client);
+    if(!pWin) return BadWindow;
 
     rep.type = X_Reply;
     rep.length = 0;
@@ -1812,9 +1810,8 @@ I830ProcXineramaGetScreenSize(ClientPtr 
     register int			n;
 
     REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
-    n = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess);
-    if (n != Success)
-	return n;
+    pWin = LookupWindow (stuff->window, client);
+    if(!pWin)  return BadWindow;
 
     rep.type = X_Reply;
     rep.length = 0;
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 65cd18b97bc533b24031d6eb882fd3074779ceba (from parents)
Merge: bf43f8ce736d91659c2757fb39b13e63bc5891a4 6823ca87f3b1ef3b28ed167254dcfce2a80467df
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Sun Dec 17 17:32:24 2006 -0800

    Merge branch 'modesetting' into crestline

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 08575331ac75783c9910cfb6e78db701a29983ac (from e3604fc63243ab0f31673a923d20e23131b607f6)
Author: Eamon Walsh <ewalsh at tycho.nsa.gov>
Date:   Fri Dec 15 17:44:44 2006 -0500

    Convert callers of LookupWindow() to dixLookupWindow().

diff --git a/src/i830_driver.c b/src/i830_driver.c
index e950d7c..e133c85 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1760,8 +1760,9 @@ I830ProcXineramaGetState(ClientPtr clien
     register int		n;
 
     REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
-    pWin = LookupWindow(stuff->window, client);
-    if(!pWin) return BadWindow;
+    n = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess);
+    if (n != Success)
+	return n;
 
     rep.type = X_Reply;
     rep.length = 0;
@@ -1785,8 +1786,9 @@ I830ProcXineramaGetScreenCount(ClientPtr
     register int			n;
 
     REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
-    pWin = LookupWindow(stuff->window, client);
-    if(!pWin) return BadWindow;
+    n = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess);
+    if (n != Success)
+	return n;
 
     rep.type = X_Reply;
     rep.length = 0;
@@ -1810,8 +1812,9 @@ I830ProcXineramaGetScreenSize(ClientPtr 
     register int			n;
 
     REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
-    pWin = LookupWindow (stuff->window, client);
-    if(!pWin)  return BadWindow;
+    n = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess);
+    if (n != Success)
+	return n;
 
     rep.type = X_Reply;
     rep.length = 0;
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 e3604fc63243ab0f31673a923d20e23131b607f6 (from 99f6f84076b25af69dc226e6d4704c74d207e657)
Author: Alan Hourihane <alanh at fairlite.demon.co.uk>
Date:   Wed Dec 13 15:42:53 2006 +0000

    Delete ChangeLog

diff --git a/ChangeLog b/ChangeLog
deleted file mode 100644
index d77176b..0000000
--- a/ChangeLog
+++ /dev/null
@@ -1,138 +0,0 @@
-2006-05-01  Matthieu Herrb <matthieu.herrb at laas.fr>
-
-	* src/common.h:
-	Fix build on non-dri systems.
-
-2006-04-07  Adam Jackson  <ajax at freedesktop.org>
-
-	* configure.ac:
-	* src/i810.h:
-	Bump to 1.6.0.
-
-2006-04-07  Aaron Plattner  <aplattner at nvidia.com>
-
-	* src/i810_video.c: (I810PutImage):
-	* src/i830_video.c: (I830PutImage):
-	Add a DrawablePtr argument to the XV functions to pave the way for
-	redirected video.
-
-2006-04-05  Dave Airlie  <airlied at linux.ie>
-
-	* src/i810_hwmc.c: (I810XvMCCreateContext),
-	(I810XvMCCreateSurface), (I810XvMCCreateSubpicture):
-	* src/i810_memory.c: (I810SetTiledMemory):
-	* src/i830_memory.c: (SetFence):
-	Fix some argument inversions in xf86DrvMsg function calls
-
-2006-04-04  Kristian Høgsberg  <krh at redhat.com>
-
-	* src/i810_dri.c:
-	* src/i810_driver.c:
-	* src/i830_dri.c:
-	* src/i830_driver.c: Add more missing #include's, in particular
-	assert.h.
-
-2006-03-22  Kristian Høgsberg  <krh at redhat.com>
-
-	* src/*.c: Drop libc wrapper; don't include xf86_ansic.h and add
-	includes now missing.
-
-2006-03-10  Alan Hourihane  <alanh at fairlite.demon.co.uk>
-
-	* src/i830_cursor.c: (I830InitHWCursor), (I830ShowCursor),
-	(I830HideCursor):
-	Enable gamma for hw cursor when ARGB cursor in use (Lukas Hejtmanek)
-
-2006-03-03  Alan Hourihane  <alanh at fairlite.demon.co.uk>
-
-	* configure.ac:
-	* src/i810.h:
-	* src/i830.h:
-	* src/i830_dri.h:
-	* src/i830_driver.c: (I830BIOSPreInit), (I830BIOSScreenInit),
-	(I830BIOSCloseScreen):
-	* src/i830_video.c:
-	Check the version of shadow being used and turn off rotation if
-	it isn't the right one.
-	Bump the Xvideo resolution support from 1920x1080 to 1920x1088.
-
-2006-02-20  Alan Hourihane  <alanh at fairlite.demon.co.uk>
-
-	* src/i830_rotate.c: (I915UpdateRotate), (I830UpdateRotate):
-	Fix a rotation problem when DRI is disabled
-
-2005-01-25  Alan Hourihane   <alanh at fairlite.demon.co.uk>
-
-	* src/i830_driver.c: When going dual head only take a portion of
-	  memory for the second head instead of doubling the requirements.
-
-2005-01-25  Alan Hourihane   <alanh at fairlite.demon.co.uk>
-
-	* src/i830_driver.c: Fix a glitch in a dual head fix from #3105
-
-2005-01-24  Alan Hourihane   <alanh at fairlite.demon.co.uk>
-
-	* configure.ac, man/i810.man, src/Makefile.am, src/common.h,
-	  src/i810.h, src/i810_dri.c, src/i810_driver.c, src/i830.h,
-	  src/i830_common.h, src/i830_cursor.c, src/i830_dga.c,
-	  src/i830_dri.c, src/i830_dri.h, src/i830_driver.c,
-	  src/i830_memory.c, src/i830_modes.c, src/i830_randr.c,
-	  src/i830_rotate.c, src/i830_shadow.c, src/i830_video.c: 
-	  Bump version to 1.5.0.0 
-	  Add Intel 945GM support 
-	  Add RandR rotation support (full 3D acceleration, HWcursor & 
-	  Xvideo rotated too)
-	  Remove older shadow framebuffer rotation code 
-	  Add a new LinearAlloc option to allow more offscreen memory 
-	  to be allocated for XVideo applications. This allows HDTV movies
-	  to be played via Xvideo.
-
-2005-12-20  Kevin E. Martin  <kem-at-freedesktop-dot-org>
-
-	* configure.ac:
-	Update package version for X11R7 release.
-
-2005-12-14  Kevin E. Martin  <kem-at-freedesktop-dot-org>
-
-	* configure.ac:
-	Update package version number for final X11R7 release candidate.
-
-2005-12-06  Kevin E. Martin  <kem-at-freedesktop-dot-org>
-
-	* man/Makefile.am:
-	Change *man_SOURCES ==> *man_PRE to fix autotools warnings.
-
-2005-12-03  Kevin E. Martin  <kem-at-freedesktop-dot-org>
-
-	* configure.ac:
-	Update package version number for X11R7 RC3 release.
-
-2005-12-01  Kevin E. Martin  <kem-at-freedesktop-dot-org>
-
-	* configure.ac:
-	Remove extraneous AC_MSG_RESULT.
-
-2005-11-30  Adam Jackson  <ajax at freedesktop.org>
-
-	* configure.ac:
-	Bump libdrm dep to 2.0.
-
-2005-11-29  Adam Jackson  <ajax at freedesktop.org>
-
-	* configure.ac:
-	Only build dlloader modules by default.
-
-2005-11-19  Kevin E. Martin  <kem-at-freedesktop-dot-org>
-
-	* configure.ac:
-	Update dependencies to work with separate build roots.
-
-2005-11-09  Kevin E. Martin  <kem-at-freedesktop-dot-org>
-
-	* configure.ac:
-	Update package version number for X11R7 RC2 release.
-
-2005-11-01  Kevin E. Martin  <kem-at-freedesktop-dot-org>
-
-	* configure.ac:
-	Update pkgcheck dependencies to work with separate build roots.
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 bf43f8ce736d91659c2757fb39b13e63bc5891a4 (from parents)
Merge: 684ea26b740d07ec8f6b0d223c1171e70c073bfa 94523215127a3458a28d0f1217224a27c8870884
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Fri Dec 8 14:17:43 2006 +0800

    Merge branch 'modesetting' into crestline

diff-tree 94523215127a3458a28d0f1217224a27c8870884 (from parents)
Merge: 75f4df278e9db360967d77cdba4756cbde622d56 fde52de870c84821ab457e17634c334a10cf71ab
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Fri Dec 8 14:15:06 2006 +0800

    Merge branch 'modesetting' of git+ssh://zhen@git.freedesktop.org/git/xorg/driver/xf86-video-intel into modesetting

diff-tree 684ea26b740d07ec8f6b0d223c1171e70c073bfa (from parents)
Merge: 64269de3c34db047e78b788dc5681abdc009f8aa 6b977f0eca388a295ca7348f5960bd8e0192cf1d
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Fri Dec 8 14:03:10 2006 +0800

    Merge branch 'exa-i965' of git+ssh://zhen@git.freedesktop.org/git/xorg/driver/xf86-video-intel into crestline

diff --cc src/i830_memory.c
index 43fde11,4a8d480..6944863
@@@ -1559,11 -1561,14 +1578,16 @@@
        I830FixOffset(pScrn, &(pI830->ContextMem));
        I830FixOffset(pScrn, &(pI830->BackBuffer));
        I830FixOffset(pScrn, &(pI830->DepthBuffer));
 -      I830FixOffset(pScrn, &(pI830->TexMem));
 +      if (pI830->mmModeFlags & I830_KERNEL_TEX) {
 +	 I830FixOffset(pScrn, &(pI830->TexMem));
 +      }
     }
  #endif
+ #ifdef I830_USE_EXA
+    I830FixOffset(pScrn, &(pI830->Offscreen));
+    if (IS_I965G(pI830))
+        I830FixOffset(pScrn, &(pI830->EXAStateMem));
+ #endif
     return TRUE;
  }
  
diff-tree 99f6f84076b25af69dc226e6d4704c74d207e657 (from 6781575f734f05547d7d5ceef4116fc157bba44d)
Author: Alan Hourihane <alanh at fairlite.demon.co.uk>
Date:   Thu Dec 7 09:47:34 2006 +0000

    Bump to 1.7.3

diff --git a/configure.ac b/configure.ac
index fc0f9cd..48b39a1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -22,7 +22,7 @@
 
 AC_PREREQ(2.57)
 AC_INIT([xf86-video-i810],
-        1.7.2,
+        1.7.3,
         [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
         xf86-video-i810)
 
diff --git a/src/i810_dri.h b/src/i810_dri.h
index f090b92..70ea899 100644
--- a/src/i810_dri.h
+++ b/src/i810_dri.h
@@ -10,7 +10,7 @@
 
 #define I810_MAJOR_VERSION 1
 #define I810_MINOR_VERSION 7
-#define I810_PATCHLEVEL 2
+#define I810_PATCHLEVEL 3
 
 typedef struct {
    drm_handle_t regs;
diff --git a/src/i830_dri.h b/src/i830_dri.h
index a140497..969eb60 100644
--- a/src/i830_dri.h
+++ b/src/i830_dri.h
@@ -10,7 +10,7 @@
 
 #define I830_MAJOR_VERSION 1
 #define I830_MINOR_VERSION 7
-#define I830_PATCHLEVEL 2
+#define I830_PATCHLEVEL 3
 
 #define I830_REG_SIZE 0x80000
 
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 64269de3c34db047e78b788dc5681abdc009f8aa (from parents)
Merge: 8ddbc26b276016b922487f7b1e8997998b655a7d 182d2f503a7a1be90d93a4a15059585a564fd3ce
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Wed Dec 6 18:09:28 2006 -0800

    Merge branch 'modesetting' into crestline

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 6b977f0eca388a295ca7348f5960bd8e0192cf1d (from 041f0029c78620ca1b50e7e5d11f5d022e189641)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Dec 6 13:24:44 2006 +0800

    fix Makefile.am

diff --git a/src/Makefile.am b/src/Makefile.am
index 890e90f..d7da2c6 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -70,7 +70,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
@@ -78,8 +77,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 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 041f0029c78620ca1b50e7e5d11f5d022e189641 (from 583619cdb2b6a469299dd5bf658bf5b51ee999fe)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Dec 6 10:43:29 2006 +0800

    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.

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 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 583619cdb2b6a469299dd5bf658bf5b51ee999fe (from f28d5fc30ccf60d72d5832bb6542522dc7f1c463)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Mon Dec 4 15:48:04 2006 +0800

    set correct default border color

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 f28d5fc30ccf60d72d5832bb6542522dc7f1c463 (from db391e8e4c4d87bfe3ccad0de14dd5b47b69b8fe)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Mon Dec 4 15:47:31 2006 +0800

    fix typo in ps kernel
    
    fix corrupt in some subspans

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 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 8ddbc26b276016b922487f7b1e8997998b655a7d (from parents)
Merge: 93975a526086432cdeb8d7ead721a862d632c1e7 16f9a56070a01c7ada8e566d9b73fcf7900136e0
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Fri Dec 1 10:57:16 2006 -0800

    Merge branch 'modesetting' into crestline
    
    Use new TV output condition (all 9xx except 915g)

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 93975a526086432cdeb8d7ead721a862d632c1e7 (from parents)
Merge: 08b6569dc663ddf38cb36a6875de6d4ab55acac9 e603cd0c73344ef137d3276b5cfcbcf4df340778
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Fri Dec 1 10:28:58 2006 -0800

    Merge branch 'modesetting' into crestline

diff --cc src/i830_driver.c
index 441eba4,3aafe3a..4cb854f
@@@ -669,12 -707,36 +709,36 @@@
     } else {
        i830_dvo_init(pScrn);
     }
- #if 1
 -   if (IS_I915GM(pI830) || IS_I945GM(pI830))
 +   if (IS_I915GM(pI830) || IS_I945GM(pI830) || IS_I965G(pI830))
        i830_tv_init(pScrn);
- #endif
  }
  
+ /**
+  * 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)
  {
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 db391e8e4c4d87bfe3ccad0de14dd5b47b69b8fe (from 290f15cd4cda97727ebcaadacbbbf7650278934b)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Nov 29 17:16:46 2006 +0800

    shut up warning

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 290f15cd4cda97727ebcaadacbbbf7650278934b (from 3d4edd325f3859c749ee42df102bb4239eac5287)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Nov 29 17:14:55 2006 +0800

    fix alpha blending state

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 3d4edd325f3859c749ee42df102bb4239eac5287 (from a704120b15efae47344a90d972e7f3da64a202a6)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Nov 29 17:05:32 2006 +0800

    Add in sf/wm program for mask picture without CA

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 a704120b15efae47344a90d972e7f3da64a202a6 (from e3c70c68e39183226e498271c44e98ef1b96a681)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Nov 29 16:52:44 2006 +0800

    misc cleanup for G965 vs/sf/wm states

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 e3c70c68e39183226e498271c44e98ef1b96a681 (from aa515c54f0cfd9025fc38dc4b7938ff17a8a13fb)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Nov 29 16:40:15 2006 +0800

    WM kernel needs scratch space

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 aa515c54f0cfd9025fc38dc4b7938ff17a8a13fb (from b6eba96584bcd2c024f6443d9f3728eb65b234fb)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Nov 29 16:37:06 2006 +0800

    Setup default border color for our samplers

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 b6eba96584bcd2c024f6443d9f3728eb65b234fb (from 453842c9ff733af45fa665d9db6a35164f45c60a)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Nov 29 16:30:53 2006 +0800

    fix vertex buffer size

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 453842c9ff733af45fa665d9db6a35164f45c60a (from 18ad7d5cf04081d89a9f978ccc7794116f7c498b)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Nov 29 16:24:24 2006 +0800

    clean up issue cmd to ring buffer
    
    Make it easy to track different part of ring state, and
    use rectlist primitive instead.

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 18ad7d5cf04081d89a9f978ccc7794116f7c498b (from 3d5bd0c14eea7951540f7a12eee257428f78e2d1)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Nov 29 16:04:16 2006 +0800

    remove wrong scale_units

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 3d5bd0c14eea7951540f7a12eee257428f78e2d1 (from a06beb5f80f097fac3b718e742742bb32f1c1194)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Nov 29 16:02:16 2006 +0800

    Rename exa sf/wm program files
    
    Also fix some minors in wm program.

diff --git a/src/Makefile.am b/src/Makefile.am
index 494a921..890e90f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -78,8 +78,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 a06beb5f80f097fac3b718e742742bb32f1c1194 (from 4198f1216eb13b30d1e92d4395e98861f4324c38)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Nov 29 15:47:19 2006 +0800

    EXA state mem for G965
    
    Not split offscreen mem for exa, but alloc a dedicated one
    for G965 states.

diff --git a/src/i830.h b/src/i830.h
index df1c171..2a68499 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
@@ -243,6 +244,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 9b2e6b2..8b07ecb 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -424,7 +424,6 @@ IntelEXADoneComposite(PixmapPtr pDst)
 #endif
 }
 
-#define BRW_LINEAR_EXTRA (32*1024)
 /*
  * TODO:
  *   - Dual head?
@@ -447,11 +446,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 e3307d6..4a8d480 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -905,6 +905,25 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
 		       "offscreen memory at 0x%lx, size %ld KB\n", 
 			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;
@@ -1545,6 +1564,11 @@ I830FixupOffsets(ScrnInfoPtr pScrn)
       I830FixOffset(pScrn, &(pI830->TexMem));
    }
 #endif
+#ifdef I830_USE_EXA
+   I830FixOffset(pScrn, &(pI830->Offscreen));
+   if (IS_I965G(pI830))
+       I830FixOffset(pScrn, &(pI830->EXAStateMem));
+#endif
    return TRUE;
 }
 
@@ -1945,6 +1969,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;
    }
 
@@ -2029,6 +2059,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 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 6781575f734f05547d7d5ceef4116fc157bba44d (from e065324661ad08b3b359136f48090232f6138959)
Author: Alan Hourihane <alanh at fairlite.demon.co.uk>
Date:   Wed Nov 22 16:49:57 2006 +0000

    Be a little more verbose when rejecting modes.

diff --git a/src/i830_modes.c b/src/i830_modes.c
index 7d14519..002c004 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -394,7 +394,6 @@ CheckMode(ScrnInfoPtr pScrn, vbeInfoPtr 
 	!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.
@@ -410,6 +409,9 @@ CheckMode(ScrnInfoPtr pScrn, vbeInfoPtr 
 	    if (status == MODE_OK) {
 		modeOK = TRUE;
 		break;
+	    } else {
+    		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Not using mode \"%s\" (%s)\n", p->name,
+	       			xf86ModeStatusToString(status));
 	    }
 	}
 	if (p) {
@@ -442,6 +444,9 @@ CheckMode(ScrnInfoPtr pScrn, vbeInfoPtr 
 			newMode = p;
 		}
 		modeOK = TRUE;
+	    } else {
+    		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Not using mode \"%s\" (%s)\n", p->name,
+	       			xf86ModeStatusToString(status));
 	    }
 	}
 	if (newMode) {
@@ -487,8 +492,11 @@ CheckMode(ScrnInfoPtr pScrn, vbeInfoPtr 
 				modeOK = FALSE;
 			} else
 			    modeOK = TRUE;
-	            } else
+	            } else {
 	    	        modeOK = FALSE;
+    		   	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Not using mode \"%s\" (%s)\n", pMode->name,
+	       			xf86ModeStatusToString(status));
+	            }
   	            pMode->status = status;
 	        } else { 
 	            modeOK = FALSE;
diff-tree e065324661ad08b3b359136f48090232f6138959 (from b649f95ea6fd3555d073fdbf8f2f035dfe1afd33)
Author: Alan Hourihane <alanh at fairlite.demon.co.uk>
Date:   Wed Nov 22 16:49:36 2006 +0000

    update port attributes immediately when overlay is on.

diff --git a/src/i830_video.c b/src/i830_video.c
index 054d26b..1a1b968 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -934,14 +934,16 @@ I830SetPortAttribute(ScrnInfoPtr pScrn,
       pPriv->brightness = value;
       overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff);
       ErrorF("BRIGHTNESS\n");
-      OVERLAY_UPDATE;
+      if (*pI830->overlayOn)
+         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_UPDATE;
+      if (*pI830->overlayOn)
+         OVERLAY_UPDATE;
    } else if (pI830->Clone && attribute == xvPipe) {
       if ((value < 0) || (value > 1))
          return BadValue;
@@ -955,7 +957,8 @@ I830SetPortAttribute(ScrnInfoPtr pScrn,
       else 
          overlay->OCONFIG |= OVERLAY_PIPE_B;
       ErrorF("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))) {
@@ -982,7 +985,8 @@ I830SetPortAttribute(ScrnInfoPtr pScrn,
 	 break;
       }
       ErrorF("COLORKEY\n");
-      OVERLAY_UPDATE;
+      if (*pI830->overlayOn)
+         OVERLAY_UPDATE;
       REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
    } else if(attribute == xvDoubleBuffer) {
       if ((value < 0) || (value > 1))
@@ -1000,13 +1004,8 @@ I830SetPortAttribute(ScrnInfoPtr pScrn,
         attribute == xvGamma3 ||
         attribute == xvGamma4 ||
         attribute == xvGamma5) && (IS_I9XX(pI830))) {
-	CARD32 r = overlay->OCMD & OVERLAY_ENABLE;
         ErrorF("GAMMA\n");
-        overlay->OCMD &= ~OVERLAY_ENABLE;
-        OVERLAY_UPDATE;
 	I830UpdateGamma(pScrn);
-        overlay->OCMD |= r;
-        OVERLAY_UPDATE;
    }
 
    return Success;
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 08b6569dc663ddf38cb36a6875de6d4ab55acac9 (from 05202cabbd23f15330b811ae6b8d708ad042bc40)
Author: Eric Anholt <eric at anholt.net>
Date:   Sun Nov 19 16:15:45 2006 -0800

    Enable TV output on Crestline (untested).

diff --git a/src/i830_driver.c b/src/i830_driver.c
index f61e0f0..441eba4 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -670,7 +670,7 @@ I830SetupOutputs(ScrnInfoPtr pScrn)
       i830_dvo_init(pScrn);
    }
 #if 1
-   if (IS_I915GM(pI830) || IS_I945GM(pI830))
+   if (IS_I915GM(pI830) || IS_I945GM(pI830) || IS_I965G(pI830))
       i830_tv_init(pScrn);
 #endif
 }
diff-tree 05202cabbd23f15330b811ae6b8d708ad042bc40 (from parents)
Merge: ee502dd92a3dfccdc2efcfb76fc652694bc89e3b b945a650e952f98c2d101b71bd3ec0f390478da5
Author: Eric Anholt <eric at anholt.net>
Date:   Sun Nov 19 16:14:18 2006 -0800

    Merge branch 'modesetting-origin' into crestline

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 ee502dd92a3dfccdc2efcfb76fc652694bc89e3b (from parents)
Merge: 15ff17c756e42f392306820e3f7ffbdcc56b9892 2fe6107ac68e86ed183d8602436633348340678d
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Nov 17 14:57:41 2006 -0800

    Merge branch 'crestline-origin' into crestline

diff-tree 15ff17c756e42f392306820e3f7ffbdcc56b9892 (from parents)
Merge: 9cc2f3313d77487dea372e6ab32d6d9c06617ae3 816fc1a76a5ac738e41b172ba8f43137c1521328
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Nov 17 11:48:53 2006 -0800

    Merge branch 'modesetting' into crestline
    
    This works for analog, but SDVO output appears to not work yet.
    
    Conflicts:
    
    	src/i830_driver.c

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 2fe6107ac68e86ed183d8602436633348340678d (from 9cc2f3313d77487dea372e6ab32d6d9c06617ae3)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Fri Nov 17 13:11:36 2006 +0800

    Rotation support for 965GM

diff --git a/src/i830.h b/src/i830.h
index 0df41e3..5c7a488 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -277,6 +277,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 287217a..ef05dd0 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -7219,6 +7219,10 @@ I830BIOSScreenInit(int scrnIndex, Screen
       /* 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
@@ -7636,11 +7640,7 @@ I830BIOSScreenInit(int scrnIndex, Screen
       xf86DisableRandR(); /* Disable built-in RandR extension */
       shadowSetup(pScreen);
       /* support all rotations */
-      if (IS_I965G(pI830)) {
-	 I830RandRInit(pScreen, RR_Rotate_0); /* only 0 degrees for I965G */
-      } else {
-	 I830RandRInit(pScreen, RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270);
-      }
+      I830RandRInit(pScreen, RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270);
       pI830->PointerMoved = pScrn->PointerMoved;
       pScrn->PointerMoved = I830PointerMoved;
       pI830->CreateScreenResources = pScreen->CreateScreenResources;
@@ -8428,8 +8428,7 @@ I830BIOSSwitchMode(int scrnIndex, Displa
     * 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 09ef5be..96d6efc 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -526,6 +526,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;
 }
 
@@ -1753,8 +1775,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;
@@ -1824,6 +1851,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,
@@ -1834,7 +1864,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 0471b55..ba41c0c 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)
@@ -737,11 +1451,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;
@@ -818,6 +1536,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);
@@ -900,6 +1627,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);
+	 }
       }
    }
    
@@ -967,8 +1700,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 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 9cc2f3313d77487dea372e6ab32d6d9c06617ae3 (from 49a6bea7d969dbfd1dd542c0c3e02abc330d6850)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Nov 16 15:12:43 2006 -0800

    Replace broken PCI resource size detection with pciGetBaseSize() call.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index c28b8b7..287217a 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -4192,16 +4192,12 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
       }
    } 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 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 b649f95ea6fd3555d073fdbf8f2f035dfe1afd33 (from fbb376bd1a4daad4c86e349df98438989ce173f1)
Author: Alan Hourihane <alanh at fairlite.demon.co.uk>
Date:   Wed Nov 8 19:01:25 2006 +0000

    Disable some debug message

diff --git a/src/i915_video.c b/src/i915_video.c
index 0833d50..78907ef 100644
--- a/src/i915_video.c
+++ b/src/i915_video.c
@@ -65,8 +65,10 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
    int nbox, dxo, dyo;
    Bool planar;
 
+#if 0
    ErrorF("I915DisplayVideo: %dx%d (pitch %d)\n", width, height,
 	  video_pitch);
+#endif
 
    switch (id) {
    case FOURCC_UYVY:
@@ -78,7 +80,9 @@ I915DisplayVideoTextured(ScrnInfoPtr pSc
       planar = TRUE;
       break;
    default:
+#if 0
       ErrorF("Unknown format 0x%x\n", id);
+#endif
       planar = FALSE;
       break;
    }
diff-tree 75f4df278e9db360967d77cdba4756cbde622d56 (from e5c572f841b626b8b6f21a6966a33956d3b0b35b)
Author: root <root at localhost.localdomain>
Date:   Wed Nov 8 13:56:32 2006 +0800

    855 fix

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 8464b39..ce3e442 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2851,7 +2851,8 @@ RestoreHWState(ScrnInfoPtr pScrn)
 
    OUTREG(PIPEACONF, pI830->savePIPEACONF);
    OUTREG(PIPEBCONF, pI830->savePIPEBCONF);
-
+   if (IS_I855(pI830))
+	usleep(10);
    OUTREG(VGACNTRL, pI830->saveVGACNTRL);
    OUTREG(DSPACNTR, pI830->saveDSPACNTR);
    OUTREG(DSPBCNTR, pI830->saveDSPBCNTR);
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 49a6bea7d969dbfd1dd542c0c3e02abc330d6850 (from parents)
Merge: 64447c7a059775e7ea8649f4714df7565e932c60 fbb376bd1a4daad4c86e349df98438989ce173f1
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Mon Nov 6 10:25:23 2006 +0800

    Merge branch 'master' into crestline

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 64447c7a059775e7ea8649f4714df7565e932c60 (from b7e57deebbda527e878326cf3e6358c0a48d7817)
Author: Zou Nanhai <nanhai.zou at intel.com>
Date:   Wed Nov 1 14:36:20 2006 +0800

    walk around to VBIOS bug in Crestline B0

diff --git a/src/i830_driver.c b/src/i830_driver.c
index cdf005a..ea6cd17 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -6514,7 +6514,7 @@ I830VESASetMode(ScrnInfoPtr pScrn, Displ
 
    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Mode bandwidth is %d Mpixel/s\n",
 	      pMode->HDisplay * pMode->VDisplay * refresh / 1000000);
-
+   if (0)
    {
       int maxBandwidth, bandwidthA, bandwidthB;
 
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 fbb376bd1a4daad4c86e349df98438989ce173f1 (from c0ee50c4ee5ff2c594fdf60c9cb8b952e25644de)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Mon Oct 30 14:15:12 2006 +0800

    Bug 8594: Fix Xv hang with G965

diff --git a/src/packed_yuv_wm.g4a b/src/packed_yuv_wm.g4a
index d312d17..4b6391b 100644
--- a/src/packed_yuv_wm.g4a
+++ b/src/packed_yuv_wm.g4a
@@ -144,7 +144,7 @@ mac.sat (8) m8<1>F g15<8,8,1>F 1F { alig
     */
 mov (8) m1<1>UD g1<8,8,1>UD { align1 mask_disable };
    /* Send framebuffer write message: XXX: acc0? */
-send (16) 0 null g0<8,8,1>UW write (
+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 */
diff --git a/src/wm_prog.h b/src/wm_prog.h
index 708e6eb..d72c651 100644
--- a/src/wm_prog.h
+++ b/src/wm_prog.h
@@ -71,7 +71,7 @@
    { 0x00600041, 0x20007fbc, 0x008d0220, 0x40011687 },
    { 0x80600048, 0x21007fbe, 0x008d01e0, 0x3f800000 },
    { 0x00600201, 0x20200022, 0x008d0020, 0x00000000 },
-   { 0x00800031, 0x20001d3c, 0x008d0000, 0x85a04800 },
+   { 0x00800031, 0x24001d28, 0x008d0000, 0x85a04800 },
    { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
    { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
    { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
diff-tree c0ee50c4ee5ff2c594fdf60c9cb8b952e25644de (from 7d67324fa3a5b5cf0227550316c366752fe4abfb)
Author: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Date:   Fri Oct 27 19:13:33 2006 +0200

    Add support for the new DRM memory manager.
    Some code are duplicated with the new libdrm.
    Once this code has been released with xserver,
    it can be removed.
    
    See the man page for new options and backwards
    3D driver compatibility.

diff --git a/configure.ac b/configure.ac
index c91b1df..fc0f9cd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -122,7 +122,7 @@ 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
diff --git a/man/i810.man b/man/i810.man
index 50c2668..a3f25ec 100644
--- a/man/i810.man
+++ b/man/i810.man
@@ -203,6 +203,30 @@ 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 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.
+ 
 
 .SH "SEE ALSO"
 __xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), xorgconfig(__appmansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__)
diff --git a/src/i810_driver.c b/src/i810_driver.c
index cd6d9d7..5143fd4 100644
--- a/src/i810_driver.c
+++ b/src/i810_driver.c
@@ -313,6 +313,12 @@ const char *I810drmSymbols[] = {
    "drmGetLibVersion",
    "drmGetVersion",
    "drmRmMap",
+#ifdef XSERVER_LIBDRM_MM 
+   "drmMMInit",
+   "drmMMTakedown",
+   "drmMMLock",
+   "drmMMUnlock",
+#endif
    NULL
 };
 
diff --git a/src/i830.h b/src/i830.h
index 38a880f..0df41e3 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -107,6 +107,13 @@ typedef struct _VESARec {
 } 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,
@@ -285,6 +292,8 @@ typedef struct _I830Rec {
    int TexGranularity;
    int drmMinor;
    Bool have3DWindows;
+   int mmModeFlags;
+   int mmSize;
 
    unsigned int front_tiled;
    unsigned int back_tiled;
@@ -573,4 +582,10 @@ Rotation I830GetRotation(ScreenPtr pScre
 #define _845_DRAM_RW_CONTROL 0x90
 #define DRAM_WRITE    0x33330000
 
+/* 
+ * Xserver MM compatibility. Remove code guarded by this when the
+ * XServer contains the libdrm mm code
+ */
+#undef XSERVER_LIBDRM_MM
+
 #endif /* _I830_H_ */
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 21af651..524c4de 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1,4 +1,4 @@
-/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_dri.c,v 1.15 2003/06/18 13:14:17 dawes Exp $ */
+/* $xfree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_dri.c,v 1.15 2003/06/18 13:14:17 dawes Exp $ */
 /**************************************************************************
 
 Copyright 2001 VA Linux Systems Inc., Fremont, California.
@@ -84,8 +84,9 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "dristruct.h"
 
 static char I830KernelDriverName[] = "i915";
-static char I830ClientDriverName[] = "i915";
+static char I830ClientDriverName[] = "i915tex";
 static char I965ClientDriverName[] = "i965";
+static char I830LegacyClientDriverName[] = "i915";
 
 static Bool I830InitVisualConfigs(ScreenPtr pScreen);
 static Bool I830CreateContext(ScreenPtr pScreen, VisualPtr visual,
@@ -644,10 +645,31 @@ I830DRIScreenInit(ScreenPtr pScreen)
 	    return FALSE;
 	 }
 	 pI830->drmMinor = version->version_minor;
+	 if (!(pI830->mmModeFlags & I830_KERNEL_TEX)) {
+	    if ((version->version_major > 1) ||
+		((version->version_minor >= 7) && 
+		 (version->version_major == 1))) {
+	       pI830->mmModeFlags |= I830_KERNEL_MM;
+	    } else {
+	       pI830->mmModeFlags |= I830_KERNEL_TEX;
+	    }		
+	 } else {
+	    xf86DrvMsg(pScreen->myNum, X_INFO, 
+		       "Not enabling the DRM memory manager.\n");
+	 } 
 	 drmFreeVersion(version);
       }
    }
 
+   /*
+    * Backwards compatibility
+    */
+
+   if ((pDRIInfo->clientDriverName == I830ClientDriverName) && 
+       (pI830->mmModeFlags & I830_KERNEL_TEX)) {
+      pDRIInfo->clientDriverName = I830LegacyClientDriverName;
+   }
+
    return TRUE;
 }
 
@@ -707,18 +729,20 @@ I830DRIMapScreenRegions(ScrnInfoPtr pScr
    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Depth Buffer = 0x%08x\n",
               (int)sarea->depth_handle);
 
-   if (drmAddMap(pI830->drmSubFD,
-		 (drm_handle_t)sarea->tex_offset + pI830->LinearAddr,
-		 sarea->tex_size, DRM_AGP, 0,
-		 (drmAddress) &sarea->tex_handle) < 0) {
-      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		 "[drm] drmAddMap(tex_handle) failed. Disabling DRI\n");
-      DRICloseScreen(pScreen);
-      return FALSE;
-   }
-   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] textures = 0x%08x\n",
-	      (int)sarea->tex_handle);
+   if (pI830->mmModeFlags & I830_KERNEL_TEX) {
+      if (drmAddMap(pI830->drmSubFD,
+		    (drm_handle_t)sarea->tex_offset + pI830->LinearAddr,
+		    sarea->tex_size, DRM_AGP, 0,
+		    (drmAddress) &sarea->tex_handle) < 0) {
+	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		    "[drm] drmAddMap(tex_handle) failed. Disabling DRI\n");
+	 DRICloseScreen(pScreen);
+	 return FALSE;
+      }
 
+      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] textures = 0x%08x\n",
+		 (int)sarea->tex_handle);
+   }
    return TRUE;
 }
 
@@ -1475,7 +1499,7 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, 
 
    success = I830DRIMapScreenRegions(pScrn, sarea);
 
-   if (success)
+   if (success && (pI830->mmModeFlags & I830_KERNEL_TEX))
       I830InitTextureHeap(pScrn, sarea);
 
    return success;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 432f0cb..e950d7c 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -197,6 +197,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #ifdef XF86DRI
 #include "dri.h"
+#include <sys/ioctl.h>
+#include <errno.h>
 #endif
 
 #define BIT(x) (1 << (x))
@@ -268,7 +270,9 @@ typedef enum {
    OPTION_SECONDHSYNC,
    OPTION_SECONDVREFRESH,
    OPTION_SECONDPOSITION,
-   OPTION_INTELXINERAMA
+   OPTION_INTELXINERAMA,
+   OPTION_INTELTEXPOOL,
+   OPTION_INTELMMSIZE
 } I830Opts;
 
 static OptionInfoRec I830BIOSOptions[] = {
@@ -296,6 +300,8 @@ static OptionInfoRec I830BIOSOptions[] =
    {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* */
@@ -3825,6 +3831,28 @@ I830IsPrimary(ScrnInfoPtr pScrn)
    return TRUE;
 }
 
+#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)
 {
@@ -3847,6 +3875,9 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
    const char *chipname;
    unsigned int ver;
    char v[5];
+#ifdef XF86DRI
+   unsigned long savedMMSize;
+#endif
 
    if (pScrn->numEntities != 1)
       return FALSE;
@@ -4243,7 +4274,46 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
 		    "runs only at depths 16 and 24.\n");
 	 pI830->directRenderingDisabled = TRUE;
       }
-   }
+
+      pI830->mmModeFlags = 0;
+
+      if (!pI830->directRenderingDisabled) {
+	 Bool tmp = FALSE;
+
+	 if (IS_I965G(pI830))
+	    pI830->mmModeFlags |= I830_KERNEL_TEX;
+
+	 from = X_PROBED;
+	 if (xf86GetOptValBool(pI830->Options, 
+			       OPTION_INTELTEXPOOL, &tmp)) {
+	    from = X_CONFIG;
+	    if (tmp) {
+	       pI830->mmModeFlags |= I830_KERNEL_TEX;
+	    } else {
+	       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 ");
+	 }
+	 pI830->mmSize = I830_MM_MAXSIZE;
+	 from = X_INFO;
+	 if (xf86GetOptValInteger(pI830->Options, OPTION_INTELMMSIZE,
+				  &(pI830->mmSize))) {
+	    from = X_CONFIG;
+	 }
+	 xf86DrvMsg(pScrn->scrnIndex, from, 
+		    "Will try to reserve %d kiB of AGP aperture space\n"
+		    "\tfor the DRM memory manager.\n",
+		    pI830->mmSize);
+      }
+   } 
+   
 #endif
 
    pI830->LinearAlloc = 0;
@@ -5351,9 +5421,15 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
     * 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))
+   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;
@@ -5395,7 +5471,9 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
        * If the displayWidth is a tilable pitch, test if there's enough
        * memory available to enable tiling.
        */
+      savedMMSize = pI830->mmSize;
       if (pScrn->displayWidth == pitches[i]) {
+      retry_dryrun:
 	 I830ResetAllocations(pScrn, 0);
 	 if (I830Allocate2DMemory(pScrn, ALLOCATE_DRY_RUN | ALLOC_INITIAL) &&
 	     I830Allocate3DMemory(pScrn, ALLOCATE_DRY_RUN)) {
@@ -5407,7 +5485,13 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
 			     "required to\n\tenable tiling mode for DRI.\n",
 			     (memNeeded + 1023) / 1024);
 	       }
-	       if (pI830->MemoryAperture.Size < 0) {
+	       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;
+		  }
+
 		  xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 			     "Allocation with DRI tiling enabled would "
 			     "exceed the\n"
@@ -5435,7 +5519,9 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
 	  * 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)) {
@@ -5448,6 +5534,11 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
 			     (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"
@@ -5456,6 +5547,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
 			     pI830->FbMapSize / 1024,
 			     -pI830->MemoryAperture.Size / 1024);
 	       }
+	       pI830->mmSize = 0;
 	       pI830->directRenderingDisabled = TRUE;
 	       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling DRI.\n");
 	    }
@@ -7020,6 +7112,87 @@ 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
+
+#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)
 {
@@ -7527,9 +7700,52 @@ I830BIOSScreenInit(int scrnIndex, Screen
          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)
 {
@@ -7683,7 +7899,13 @@ I830BIOSLeaveVT(int scrnIndex, int flags
 #ifdef XF86DRI
    if (pI830->directRenderingOpen) {
       DRILock(screenInfo.screens[pScrn->scrnIndex], 0);
-   
+      if (pI830->mmModeFlags & I830_KERNEL_MM) {
+#ifndef XSERVER_LIBDRM_MM
+	 I830DrmMMLock(pI830->drmSubFD, DRM_BO_MEM_TT);
+#else
+	 drmMMLock(pI830->drmSubFD, DRM_BO_MEM_TT);
+#endif
+      }
       I830DRISetVBlankInterrupt (pScrn, FALSE);
       
       drmCtlUninstHandler(pI830->drmSubFD);
@@ -8138,6 +8360,14 @@ I830BIOSEnterVT(int scrnIndex, int flags
 	 for(i = 0; i < I830_NR_TEX_REGIONS+1 ; i++)
 	    sarea->texList[i].age = sarea->texAge;
 
+	 if (pI830->mmModeFlags & I830_KERNEL_MM) {
+#ifndef XSERVER_LIBDRM_MM
+	    I830DrmMMUnlock(pI830->drmSubFD, DRM_BO_MEM_TT);
+#else
+	    drmMMUnlock(pI830->drmSubFD, DRM_BO_MEM_TT);
+#endif
+	 }
+
 	 DPRINTF(PFX, "calling dri unlock\n");
 	 DRIUnlock(screenInfo.screens[pScrn->scrnIndex]);
       }
@@ -8351,6 +8581,13 @@ I830BIOSCloseScreen(int scrnIndex, Scree
    pI830->closing = TRUE;
 #ifdef XF86DRI
    if (pI830->directRenderingOpen) {
+      if (pI830->mmModeFlags & I830_KERNEL_MM) {
+#ifndef XSERVER_LIBDRM_MM
+	 I830DrmMMTakedown(pI830->drmSubFD, DRM_BO_MEM_TT);
+#else
+	 drmMMTakedown(pI830->drmSubFD, DRM_BO_MEM_TT);	 
+#endif
+      }
       pI830->directRenderingOpen = FALSE;
       I830DRICloseScreen(pScreen);
    }
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 2d09b2d..09ef5be 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -1107,6 +1107,12 @@ I830ResetAllocations(ScrnInfoPtr 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;
 #if ALLOCATE_ALL_BIOSMEM
@@ -1286,37 +1292,41 @@ I830AllocateTextureMemory(ScrnInfoPtr pS
    /* Allocate the remaining space for textures. */
    memset(&(pI830->TexMem), 0, sizeof(pI830->TexMem));
    pI830->TexMem.Key = -1;
-   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);
+
+   if (pI830->mmModeFlags & I830_KERNEL_TEX) {
+
+      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;
       }
-      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");
+      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;
       }
-      return FALSE;
+      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		     "%sAllocated %ld kB for textures at 0x%lx\n", s,
+		     alloced / 1024, pI830->TexMem.Start);
    }
-   xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-		  "%sAllocated %ld kB for textures at 0x%lx\n", s,
-		  alloced / 1024, pI830->TexMem.Start);
 
    return TRUE;
 }
@@ -1514,7 +1524,9 @@ I830FixupOffsets(ScrnInfoPtr pScrn)
       I830FixOffset(pScrn, &(pI830->ContextMem));
       I830FixOffset(pScrn, &(pI830->BackBuffer));
       I830FixOffset(pScrn, &(pI830->DepthBuffer));
-      I830FixOffset(pScrn, &(pI830->TexMem));
+      if (pI830->mmModeFlags & I830_KERNEL_TEX) {
+	 I830FixOffset(pScrn, &(pI830->TexMem));
+      }
    }
 #endif
    return TRUE;
@@ -1913,7 +1925,8 @@ I830BindAGPMemory(ScrnInfoPtr pScrn)
 	    return FALSE;
 	 if (!BindMemRange(pScrn, &(pI830->DepthBuffer)))
 	    return FALSE;
-	 if (!BindMemRange(pScrn, &(pI830->TexMem)))
+	 if ((pI830->mmModeFlags & I830_KERNEL_TEX) && 
+	     !BindMemRange(pScrn, &(pI830->TexMem)))
 	    return FALSE;
       }
 #endif
@@ -1997,7 +2010,8 @@ I830UnbindAGPMemory(ScrnInfoPtr pScrn)
 	    return FALSE;
 	 if (!UnbindMemRange(pScrn, &(pI830->DepthBuffer)))
 	    return FALSE;
-	 if (!UnbindMemRange(pScrn, &(pI830->TexMem)))
+	 if ((pI830->mmModeFlags & I830_KERNEL_TEX) && 
+	     !UnbindMemRange(pScrn, &(pI830->TexMem)))
 	    return FALSE;
       }
 #endif
diff --git a/src/i830_rotate.c b/src/i830_rotate.c
index 020d7e6..0471b55 100644
--- a/src/i830_rotate.c
+++ b/src/i830_rotate.c
@@ -778,7 +778,7 @@ I830Rotate(ScrnInfoPtr pScrn, DisplayMod
       
       /* Do heap teardown here
        */
-      {
+      if (pI8301->mmModeFlags & I830_KERNEL_TEX) {
 	 drmI830MemDestroyHeap destroy;
 	 destroy.region = I830_MEM_REGION_AGP;
 	 
@@ -790,10 +790,11 @@ I830Rotate(ScrnInfoPtr pScrn, DisplayMod
 	 }
       }
       
-      
-      if (pI8301->TexMem.Key != -1)
-         xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->TexMem.Key);
-      I830FreeVidMem(pScrn1, &(pI8301->TexMem));
+      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);
@@ -943,9 +944,11 @@ I830Rotate(ScrnInfoPtr pScrn, DisplayMod
 			      pI8301->disableTiling ? ALLOC_NO_TILING : 0))
          goto BAIL3;
 
-      if (!I830AllocateTextureMemory(pScrn1,
-			      pI8301->disableTiling ? ALLOC_NO_TILING : 0))
-         goto BAIL4;
+      if (pI8301->mmModeFlags & I830_KERNEL_TEX) {
+	 if (!I830AllocateTextureMemory(pScrn1,
+					pI8301->disableTiling ? ALLOC_NO_TILING : 0))
+	    goto BAIL4;
+      }
 
       I830DoPoolAllocation(pScrn1, &(pI8301->StolenPool));
 
@@ -958,8 +961,10 @@ I830Rotate(ScrnInfoPtr pScrn, DisplayMod
          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->TexMem.Key != -1)
-         xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->TexMem.Key, pI8301->TexMem.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++) 
@@ -1031,7 +1036,6 @@ I830Rotate(ScrnInfoPtr pScrn, DisplayMod
       pI830->AccelInfoRec->maxOffPixWidth = 1;
       pI830->AccelInfoRec->maxOffPixHeight = 1;
    }
-
    return TRUE;
 
 BAIL4:
@@ -1175,11 +1179,12 @@ BAIL0:
 			      pI8301->disableTiling ? ALLOC_NO_TILING : 0))
          xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 
 		    "Oh dear, the depth buffer failed - badness\n");
-
-      if (!I830AllocateTextureMemory(pScrn1,
-			      pI8301->disableTiling ? ALLOC_NO_TILING : 0))
-         xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 
-		    "Oh dear, the texture cache 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));
 
@@ -1192,8 +1197,10 @@ BAIL0:
          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->TexMem.Key != -1)
-         xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->TexMem.Key, pI8301->TexMem.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++) 
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 7d67324fa3a5b5cf0227550316c366752fe4abfb (from 20d263805a365be548279758bc39d027d6e56d63)
Author: Alan Hourihane <alanh at fairlite.demon.co.uk>
Date:   Mon Oct 23 17:29:17 2006 +0100

    Add some MergedFB checks for accelerator limitations

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 3cee1c8..432f0cb 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -5468,6 +5468,16 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
 #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);
diff-tree 20d263805a365be548279758bc39d027d6e56d63 (from parents)
Merge: 8548fa53746c9886eccfb67d022136471d8f3316 5ac927d6f05ba6f9608d7e758cbac66e8b3a9db1
Author: Alan Hourihane <alanh at fairlite.demon.co.uk>
Date:   Mon Oct 23 14:24:41 2006 +0100

    Merge branch 'master' of git+ssh://git.freedesktop.org/git/xorg/driver/xf86-video-intel

diff-tree 8548fa53746c9886eccfb67d022136471d8f3316 (from adae75ef2f8a655a699e982ca8f26b934dbe950a)
Author: Alan Hourihane <alanh at fairlite.demon.co.uk>
Date:   Mon Oct 23 14:23:29 2006 +0100

    Fix manpage to report 8160 instead of 6144 for LinearAlloc.

diff --git a/man/i810.man b/man/i810.man
index fcc5dd8..50c2668 100644
--- a/man/i810.man
+++ b/man/i810.man
@@ -201,7 +201,7 @@ Default: 0 degrees.
 .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).
 
 .SH "SEE ALSO"
diff-tree 5ac927d6f05ba6f9608d7e758cbac66e8b3a9db1 (from adae75ef2f8a655a699e982ca8f26b934dbe950a)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Tue Oct 17 13:27:40 2006 +0200

    Don't crash if SetCursorPosition is called with pScrn->currentMode == NULL.
    
    This allows the driver to work with servers that don't have the fix for this
    that was only recently pushed to git.

diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index c5c904c..8343b6b 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -520,11 +520,17 @@ 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;
-   if (x <= -I810_CURSOR_X) x = -I810_CURSOR_X + 1;
-   if (y <= -I810_CURSOR_Y) y = -I810_CURSOR_Y + 1;
+   if (pScrn->currentMode) {
+      /* 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;
+   } else {
+      /* Can't ensure the cursor will be visible, so hide it */
+      hide = TRUE;
+      show = FALSE;
+   }
 
 #if 0
    /*
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 adae75ef2f8a655a699e982ca8f26b934dbe950a (from 1d4cfaa391ac41099de11b8f3b21e5eb56543909)
Author: Alan Hourihane <alanh at fairlite.demon.co.uk>
Date:   Fri Oct 13 17:10:27 2006 +0100

    Make VIDEO_DEBUG into a configure option

diff --git a/configure.ac b/configure.ac
index 042d67d..c91b1df 100644
--- a/configure.ac
+++ b/configure.ac
@@ -65,6 +65,11 @@ AC_ARG_ENABLE(dri, AC_HELP_STRING([--dis
               [DRI="$enableval"],
               [DRI=auto])
 
+AC_ARG_ENABLE(video-debug, AC_HELP_STRING([--enable-video-debug],
+                                  [Enable video debugging support [[default=no]]]),
+              [VIDEO_DEBUG="$enableval"],
+              [VIDEO_DEBUG=no])
+
 
 # Checks for extensions
 XORG_DRIVER_CHECK_EXT(XINERAMA, xineramaproto)
@@ -122,6 +127,11 @@ if test "$DRI" = yes; then
         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([moduledir])
diff --git a/src/i830_video.c b/src/i830_video.c
index db21d87..054d26b 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -1,4 +1,3 @@
-#define VIDEO_DEBUG 0
 /***************************************************************************
  
 Copyright 2000 Intel Corporation.  All Rights Reserved. 
diff-tree 1d4cfaa391ac41099de11b8f3b21e5eb56543909 (from cd9e51cd3ab0b36d2f97dfc6d8850dafe169c221)
Author: Alan Hourihane <alanh at fairlite.demon.co.uk>
Date:   Fri Oct 13 13:55:10 2006 +0100

    Bump to 1.7.2

diff --git a/configure.ac b/configure.ac
index 136ff6e..042d67d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -22,7 +22,7 @@
 
 AC_PREREQ(2.57)
 AC_INIT([xf86-video-i810],
-        1.7.1,
+        1.7.2,
         [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
         xf86-video-i810)
 
diff --git a/src/i810_dri.h b/src/i810_dri.h
index f5016b6..f090b92 100644
--- a/src/i810_dri.h
+++ b/src/i810_dri.h
@@ -10,7 +10,7 @@
 
 #define I810_MAJOR_VERSION 1
 #define I810_MINOR_VERSION 7
-#define I810_PATCHLEVEL 1
+#define I810_PATCHLEVEL 2
 
 typedef struct {
    drm_handle_t regs;
diff --git a/src/i830_dri.h b/src/i830_dri.h
index a4f5dee..a140497 100644
--- a/src/i830_dri.h
+++ b/src/i830_dri.h
@@ -10,7 +10,7 @@
 
 #define I830_MAJOR_VERSION 1
 #define I830_MINOR_VERSION 7
-#define I830_PATCHLEVEL 1
+#define I830_PATCHLEVEL 2
 
 #define I830_REG_SIZE 0x80000
 
diff-tree cd9e51cd3ab0b36d2f97dfc6d8850dafe169c221 (from 334aa062c333f2c59bc40e1b9239d3ea71c88a8f)
Author: Alan Hourihane <alanh at fairlite.demon.co.uk>
Date:   Fri Oct 13 13:54:31 2006 +0100

    Ugh. Turn off debugging.

diff --git a/src/i830_video.c b/src/i830_video.c
index 78ad636..db21d87 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -1,4 +1,4 @@
-#define VIDEO_DEBUG 1
+#define VIDEO_DEBUG 0
 /***************************************************************************
  
 Copyright 2000 Intel Corporation.  All Rights Reserved. 
diff-tree 334aa062c333f2c59bc40e1b9239d3ea71c88a8f (from 8045a7a0af1b276cd7f46ce99d034fd5d503e67c)
Author: Alan Hourihane <alanh at fairlite.demon.co.uk>
Date:   Fri Oct 13 12:59:30 2006 +0100

    Bump to 1.7.1

diff --git a/configure.ac b/configure.ac
index 2429353..136ff6e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -22,7 +22,7 @@
 
 AC_PREREQ(2.57)
 AC_INIT([xf86-video-i810],
-        1.7.0,
+        1.7.1,
         [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
         xf86-video-i810)
 
diff --git a/src/i810_dri.h b/src/i810_dri.h
index 027a47a..f5016b6 100644
--- a/src/i810_dri.h
+++ b/src/i810_dri.h
@@ -9,8 +9,8 @@
 #define I810_MAX_DRAWABLES 256
 
 #define I810_MAJOR_VERSION 1
-#define I810_MINOR_VERSION 6
-#define I810_PATCHLEVEL 3
+#define I810_MINOR_VERSION 7
+#define I810_PATCHLEVEL 1
 
 typedef struct {
    drm_handle_t regs;
diff --git a/src/i830_dri.h b/src/i830_dri.h
index 3a4cfaf..a4f5dee 100644
--- a/src/i830_dri.h
+++ b/src/i830_dri.h
@@ -10,7 +10,7 @@
 
 #define I830_MAJOR_VERSION 1
 #define I830_MINOR_VERSION 7
-#define I830_PATCHLEVEL 0
+#define I830_PATCHLEVEL 1
 
 #define I830_REG_SIZE 0x80000
 
diff-tree 8045a7a0af1b276cd7f46ce99d034fd5d503e67c (from 6596333b077a692c669f8cb4ae32e145f8da6731)
Author: Alan Hourihane <alanh at fairlite.demon.co.uk>
Date:   Fri Oct 13 12:53:53 2006 +0100

    Fix bug #8553 & #8542 - suspend/resume regression from 1.5 driver

diff --git a/src/i830_driver.c b/src/i830_driver.c
index a69a9a3..3cee1c8 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -8041,7 +8041,11 @@ I830BIOSEnterVT(int scrnIndex, int flags
       * the Video BIOS with our saved devices, and only when that fails,
       * we'll warm boot it.
       */
-      if (!I830Set640x480(pScrn)) {
+      /* Check Pipe conf registers or possibly HTOTAL/VTOTAL for 0x00000000)*/
+      CARD32 temp;
+      Bool set = I830Set640x480(pScrn);
+      temp = pI830->pipe ? INREG(PIPEBCONF) : INREG(PIPEACONF);
+      if (!set || !(temp & 0x80000000)) {
          xf86Int10InfoPtr pInt;
 
          xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
diff-tree 6596333b077a692c669f8cb4ae32e145f8da6731 (from c7a23908a0ef45b14b438f656a5f15582bfcbc1c)
Author: Alan Hourihane <alanh at fairlite.demon.co.uk>
Date:   Fri Oct 13 12:48:16 2006 +0100

    Fix some warnings

diff --git a/src/i830_video.c b/src/i830_video.c
index 0eeaccb..78ad636 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -1,4 +1,4 @@
-#define VIDEO_DEBUG 0
+#define VIDEO_DEBUG 1
 /***************************************************************************
  
 Copyright 2000 Intel Corporation.  All Rights Reserved. 
@@ -160,7 +160,7 @@ Edummy(const char *dummy, ...)
    do { 								\
       BEGIN_LP_RING(8);							\
       OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE);                       	\
-      OUT_RING(MI_NOOP);    						\  
+      OUT_RING(MI_NOOP);    						\
       if (!*pI830->overlayOn) {						\
 	 OUT_RING(MI_NOOP);						\
 	 OUT_RING(MI_NOOP);						\
@@ -188,7 +188,7 @@ Edummy(const char *dummy, ...)
 	 int spin = 1000000;						\
 	 BEGIN_LP_RING(6);						\
          OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE);                   	\
-         OUT_RING(MI_NOOP);    						\  
+         OUT_RING(MI_NOOP);    						\
 	 OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_OFF);		\
          if (IS_I965G(pI830)) 						\
             OUT_RING(pI830->OverlayMem->Start | OFC_UPDATE); 		\
@@ -881,9 +881,6 @@ I830StopVideo(ScrnInfoPtr pScrn, pointer
    I830PortPrivPtr pPriv = (I830PortPrivPtr) data;
    I830Ptr pI830 = I830PTR(pScrn);
 
-   I830OverlayRegPtr overlay =
-	 (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start);
-
    if (pPriv->textured)
       return;
 
@@ -3267,8 +3264,6 @@ I830BlockHandler(int i,
    ScrnInfoPtr pScrn = xf86Screens[i];
    I830Ptr pI830 = I830PTR(pScrn);
    I830PortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
-   I830OverlayRegPtr overlay =
-	 (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start);
 
    pScreen->BlockHandler = pI830->BlockHandler;
 
@@ -3398,9 +3393,6 @@ I830StopSurface(XF86SurfacePtr surface)
    if (pPriv->isOn) {
       I830Ptr pI830 = I830PTR(pScrn);
 
-      I830OverlayRegPtr overlay =
-	    (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start);
-
       ErrorF("StopSurface\n");
 
       I830ResetVideo(pScrn);
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 4198f1216eb13b30d1e92d4395e98861f4324c38 (from d485c1f2de11db92b515690fbe38b6aeb6207605)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Tue Oct 10 15:50:10 2006 +0800

    Mark current ps kernel is experimential with little test.

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 d485c1f2de11db92b515690fbe38b6aeb6207605 (from 92c5020bbd31e02c7224798a8f094d237afa19a0)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Tue Oct 10 14:11:35 2006 +0800

    Use sf_prog.h instead

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 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 c7a23908a0ef45b14b438f656a5f15582bfcbc1c (from 07cdc60be8ebe5d0c21149f3cd2aeb8fed05022a)
Author: Alan Hourihane <alanh at fairlite.demon.co.uk>
Date:   Fri Oct 6 13:35:39 2006 +0100

    Fix server regeneration problem mapping the aperture

diff --git a/src/i810_driver.c b/src/i810_driver.c
index 22635c8..cd6d9d7 100644
--- a/src/i810_driver.c
+++ b/src/i810_driver.c
@@ -1186,14 +1186,13 @@ I810MapMem(ScrnInfoPtr pScrn)
    long i;
 
    for (i = 2; i < pI810->FbMapSize; i <<= 1) ;
-   pI810->FbMapSize = i;
 
    if (!I810MapMMIO(pScrn))
       return FALSE;
 
    pI810->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
 				 pI810->PciTag,
-				 pI810->LinearAddr, pI810->FbMapSize);
+				 pI810->LinearAddr, i);
    if (!pI810->FbBase)
       return FALSE;
 
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 07cdc60be8ebe5d0c21149f3cd2aeb8fed05022a (from 8da10d15f84ccc992b828546af5ba0d848e7263e)
Author: Alan Hourihane <alanh at fairlite.demon.co.uk>
Date:   Wed Oct 4 11:05:30 2006 +0100

    Fix bug #5795, VT switching fails because of a bad test on some platforms.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 9c86fe5..a69a9a3 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2620,37 +2620,15 @@ static Bool
 I830Set640x480(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
-   int m = 0x30; /* 640x480 8bpp */
+   int m;
 
-   switch (pScrn->depth) {
-   case 15:
-	 m = 0x40;
-	 break;
-   case 16:
-	 m = 0x41;
-	 break;
-   case 24:
-	 m = 0x50;
-	 break;
-   }
-
-   m |= (1 << 15) | (1 << 14);
+   /* 640x480 8bpp */
+   m = 0x30 | (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);
+   m = 0x32 | (1 << 15) | (1 << 14);
 
    if (VBESetVBEMode(pI830->pVbe, m, NULL))
 	   return TRUE;
diff-tree 8da10d15f84ccc992b828546af5ba0d848e7263e (from f337eea9e73cbf5c71d07df50d2e5b661a1f34cf)
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.
    (cherry picked from 1bc1cedbcdf6ea4d2a3e8b07b553ac50b3c126f4 commit)

diff --git a/src/i830_video.c b/src/i830_video.c
index 2c357d6..0eeaccb 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -681,8 +681,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);
@@ -690,10 +689,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;
@@ -752,8 +749,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");
@@ -1031,7 +1027,7 @@ I830GetPortAttribute(ScrnInfoPtr pScrn,
       *value = pPriv->brightness;
    } else if (attribute == xvContrast) {
       *value = pPriv->contrast;
-   } 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 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 f337eea9e73cbf5c71d07df50d2e5b661a1f34cf (from 2b9bdd8a4021231e4b5f4c5831a46c9ff1e38081)
Author: Alan Hourihane <alanh at fairlite.demon.co.uk>
Date:   Mon Oct 2 11:16:42 2006 +0100

    silence warning

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 2506f53..9c86fe5 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1343,7 +1343,7 @@ I830UpdateXineramaScreenInfo(ScrnInfoPtr
     Bool usenonrect = pI830->NonRect;
     const char *rectxine = "\t... setting up rectangular Xinerama layout\n";
 #ifdef XF86DRI
-    drmI830Sarea *sarea;
+    drmI830Sarea *sarea = NULL;
 
     if (pI830->directRenderingEnabled) {
        sarea = (drmI830Sarea *) DRIGetSAREAPrivate(pScrn1->pScreen);
diff-tree 2b9bdd8a4021231e4b5f4c5831a46c9ff1e38081 (from eca082ca0fec12973a4dbb0106b841136b5b6cdb)
Author: Alan Hourihane <alanh at fairlite.demon.co.uk>
Date:   Mon Oct 2 11:12:23 2006 +0100

    bump to 1.7.0

diff --git a/configure.ac b/configure.ac
index a27822e..2429353 100644
--- a/configure.ac
+++ b/configure.ac
@@ -22,7 +22,7 @@
 
 AC_PREREQ(2.57)
 AC_INIT([xf86-video-i810],
-        1.6.5,
+        1.7.0,
         [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
         xf86-video-i810)
 
diff-tree eca082ca0fec12973a4dbb0106b841136b5b6cdb (from cece9a455b54ab184a3277c164ee6dfa65b70f48)
Author: Alan Hourihane <alanh at fairlite.demon.co.uk>
Date:   Sat Sep 30 13:44:43 2006 +0100

    Missing gamma bit

diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index c9e04e9..c5c904c 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -655,7 +655,7 @@ I830ShowCursor(ScrnInfoPtr pScrn)
       temp &= ~(CURSOR_FORMAT_MASK | CURSOR_GAMMA_ENABLE);
       temp |= CURSOR_ENABLE;
       if (pI830->CursorIsARGB)
-         temp |= CURSOR_FORMAT_ARGB;
+         temp |= CURSOR_FORMAT_ARGB | CURSOR_GAMMA_ENABLE;
       else 
          temp |= CURSOR_FORMAT_3C;
       OUTREG(CURSOR_CONTROL, temp);
diff-tree cece9a455b54ab184a3277c164ee6dfa65b70f48 (from 2013b839de3733fd12becb2cc3c1daadde329eb4)
Author: Alan Hourihane <alanh at fairlite.demon.co.uk>
Date:   Sat Sep 30 13:27:27 2006 +0100

    Fix issues with Xv locking up the engine. bug #7915.

diff --git a/src/i830_video.c b/src/i830_video.c
index b87e4eb..2c357d6 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -158,11 +158,11 @@ Edummy(const char *dummy, ...)
 
 #define OVERLAY_UPDATE						\
    do { 								\
-      BEGIN_LP_RING(6);							\
-      OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE);			\
-      OUT_RING(MI_NOOP);						\
+      BEGIN_LP_RING(8);							\
+      OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE);                       	\
+      OUT_RING(MI_NOOP);    						\  
       if (!*pI830->overlayOn) {						\
-         OUT_RING(MI_NOOP);						\
+	 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");			\
@@ -172,10 +172,12 @@ Edummy(const char *dummy, ...)
 	 OUT_RING(MI_NOOP);						\
 	 OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_CONTINUE);		\
       }									\
-      if (IS_I965G(pI830)) 					\
+      if (IS_I965G(pI830)) 						\
          OUT_RING(pI830->OverlayMem->Start | OFC_UPDATE); 		\
       else								\
 	 OUT_RING(pI830->OverlayMem->Physical | OFC_UPDATE);		\
+      OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);		\
+      OUT_RING(MI_NOOP);						\
       ADVANCE_LP_RING();						\
       ErrorF("OVERLAY_UPDATE\n");					\
    } while(0)
@@ -184,20 +186,11 @@ Edummy(const char *dummy, ...)
    do { 								\
       if (*pI830->overlayOn) {						\
 	 int spin = 1000000;						\
-	 BEGIN_LP_RING(12);						\
-	 OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE);			\
-	 OUT_RING(MI_NOOP);						\
-	 OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);	\
-	 OUT_RING(MI_NOOP);						\
-	 OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_CONTINUE);		\
-         if (IS_I965G(pI830)) 					\
-            OUT_RING(pI830->OverlayMem->Start | OFC_UPDATE); 		\
-         else								\
-	    OUT_RING(pI830->OverlayMem->Physical | OFC_UPDATE);		\
-	 OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);	\
-	 OUT_RING(MI_NOOP);						\
+	 BEGIN_LP_RING(6);						\
+         OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE);                   	\
+         OUT_RING(MI_NOOP);    						\  
 	 OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_OFF);		\
-         if (IS_I965G(pI830)) 					\
+         if (IS_I965G(pI830)) 						\
             OUT_RING(pI830->OverlayMem->Start | OFC_UPDATE); 		\
          else								\
 	    OUT_RING(pI830->OverlayMem->Physical | OFC_UPDATE);		\
@@ -420,7 +413,7 @@ I830InitVideo(ScreenPtr pScreen)
    XF86VideoAdaptorPtr overlayAdaptor = NULL, texturedAdaptor = NULL;
    int num_adaptors;
 
-   DPRINTF(PFX, "I830InitVideo\n");
+   ErrorF("I830InitVideo\n");
 
 #if 0
    {
@@ -494,7 +487,7 @@ I830ResetVideo(ScrnInfoPtr pScrn)
    I830OverlayRegPtr overlay =
 	 (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start);
 
-   DPRINTF(PFX, "I830ResetVideo: base: %p, offset: 0x%lx, obase: %p\n",
+   ErrorF("I830ResetVideo: base: %p, offset: 0x%lx, obase: %p\n",
 	   pI830->FbBase, pI830->OverlayMem->Start, overlay);
    /*
     * Default to maximum image size in YV12
@@ -663,7 +656,7 @@ I830SetupImageVideoOverlay(ScreenPtr pSc
    I830PortPrivPtr pPriv;
    XF86AttributePtr att;
 
-   DPRINTF(PFX, "I830SetupImageVideoOverlay\n");
+   ErrorF("I830SetupImageVideoOverlay\n");
 
    if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
 			 sizeof(I830PortPrivRec) + sizeof(DevUnion))))
@@ -789,7 +782,7 @@ I830SetupImageVideoTextured(ScreenPtr pS
    int nports = 16, i;
    int nAttributes;
 
-   DPRINTF(PFX, "I830SetupImageVideoOverlay\n");
+   ErrorF("I830SetupImageVideoOverlay\n");
 
    nAttributes = NUM_TEXTURED_ATTRIBUTES;
 
@@ -898,18 +891,16 @@ I830StopVideo(ScrnInfoPtr pScrn, pointer
    if (pPriv->textured)
       return;
 
-   DPRINTF(PFX, "I830StopVideo\n");
+   ErrorF("I830StopVideo\n");
 
    REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
 
    if (shutdown) {
       if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
 
-	 overlay->OCMD &= ~OVERLAY_ENABLE;
+	 I830ResetVideo(pScrn);
 	 OVERLAY_UPDATE;
-#if 1
 	 OVERLAY_OFF;
-#endif
 
          if (pI830->entityPrivate)
             pI830->entityPrivate->XvInUse = -1;
@@ -1671,8 +1662,11 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
       I830ResetVideo(pScrn);
 
    /* Ensure overlay is turned on with OVERLAY_ENABLE at 0 */
-   if (!*pI830->overlayOn)
+   if (!*pI830->overlayOn) {
+      ErrorF("TURNING ON OVERLAY BEFORE UPDATE\n");
+      I830ResetVideo(pScrn);
       OVERLAY_UPDATE;
+   }
 
    /* Fix up the dstBox if outside the visible screen */
    {
@@ -2873,7 +2867,7 @@ I830AllocateMemory(ScrnInfoPtr pScrn, FB
    ScreenPtr pScreen;
    FBLinearPtr new_linear = NULL;
 
-   DPRINTF(PFX, "I830AllocateMemory\n");
+   ErrorF("I830AllocateMemory\n");
 
    if (linear) {
       if (linear->size >= size)
@@ -2945,7 +2939,7 @@ I830PutImage(ScrnInfoPtr pScrn,
    int pitchAlignMask;
    int extraLinear;
 
-   DPRINTF(PFX, "I830PutImage: src: (%d,%d)(%d,%d), dst: (%d,%d)(%d,%d)\n"
+   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);
 
@@ -3296,11 +3290,10 @@ I830BlockHandler(int i,
 	 if (pPriv->offTime < now) {
 	    /* Turn off the overlay */
 	    ErrorF("BLOCKHANDLER\n");
-	    overlay->OCMD &= ~OVERLAY_ENABLE;
+
+	    I830ResetVideo(pScrn);
             OVERLAY_UPDATE;
-#if 1
             OVERLAY_OFF;
-#endif
 
 	    pPriv->videoStatus = FREE_TIMER;
 	    pPriv->freeTime = now + FREE_DELAY;
@@ -3413,11 +3406,10 @@ I830StopSurface(XF86SurfacePtr surface)
 	    (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start);
 
       ErrorF("StopSurface\n");
-      overlay->OCMD &= ~OVERLAY_ENABLE;
+
+      I830ResetVideo(pScrn);
       OVERLAY_UPDATE;
-#if 1
       OVERLAY_OFF;
-#endif
 
       if (pI830->entityPrivate)
          pI830->entityPrivate->XvInUse = -1;
diff-tree 2013b839de3733fd12becb2cc3c1daadde329eb4 (from fe691953f08b4d299295f91450412404ba42810b)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Thu Sep 28 13:49:44 2006 +0200

    Always call I830UpdateXineramaScreenInfo() unconditionally, and document why.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index fc768af..2506f53 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2064,9 +2064,6 @@ I830XineramaExtensionInit(ScrnInfoPtr pS
        pI830->I830XineramaVY = 0;
 
     }
-
-    I830UpdateXineramaScreenInfo(pScrn);
-
 }
 
 static void
@@ -7491,6 +7488,9 @@ I830BIOSScreenInit(int scrnIndex, Screen
       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "libshadow is version %d.%d.%d, required 1.1.0 or greater for rotation.\n",pI830->shadowReq.majorversion,pI830->shadowReq.minorversion,pI830->shadowReq.patchlevel);
    }
 
+   /* Call this unconditionally, as it also sets some fields in the SAREA */
+   I830UpdateXineramaScreenInfo(pScrn);
+
    if (serverGeneration == 1)
       xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
 
@@ -8235,6 +8235,7 @@ I830BIOSSwitchMode(int scrnIndex, Displa
 
    /* Since RandR (indirectly) uses SwitchMode(), we need to
     * update our Xinerama info here, too, in case of resizing
+    * Call this unconditionally, as it also sets some fields in the SAREA
     */
    I830UpdateXineramaScreenInfo(pScrn);
 
diff-tree 92c5020bbd31e02c7224798a8f094d237afa19a0 (from 518802843284973f1f86132afd805c0e662e1ba6)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Thu Sep 28 13:55:52 2006 +0800

    Fix picture's transform checking

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 518802843284973f1f86132afd805c0e662e1ba6 (from 25ff5baad95c205c7c690da72fc0f252b3ed9289)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Thu Sep 28 11:15:33 2006 +0800

    Fallback in mask picture for now
    
    Do it later after finish wm kernel program.

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 25ff5baad95c205c7c690da72fc0f252b3ed9289 (from c3a49b5123d094280b5ff358ceef961958319ce4)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Thu Sep 28 11:09:52 2006 +0800

    Fix compile, add wm header file.

diff --git a/src/Makefile.am b/src/Makefile.am
index e7132bc..494a921 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -70,6 +70,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 c3a49b5123d094280b5ff358ceef961958319ce4 (from 185df8a18102eea79b8c8e11304dfee148ac2002)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Thu Sep 28 10:36:00 2006 +0800

    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.

diff --git a/src/Makefile.am b/src/Makefile.am
index f08d9a7..e7132bc 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -77,6 +77,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 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 fe691953f08b4d299295f91450412404ba42810b (from 06c5f7bd076e9ba4b925e061a40b837714bc8267)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Thu Aug 31 18:35:10 2006 +0200

    Store viewport limits of both pipes in SAREA.
    
    This allows DRI clients to determine which pipe they should synchronize buffer
    swaps of each window to.

diff --git a/src/i830_common.h b/src/i830_common.h
index c3ef4cd..79455b6 100644
--- a/src/i830_common.h
+++ b/src/i830_common.h
@@ -121,6 +121,15 @@ typedef struct {
         unsigned int depth_tiled;
         unsigned int rotated_tiled;
         unsigned int rotated2_tiled;
+
+	int pipeA_x;
+	int pipeA_y;
+	int pipeA_w;
+	int pipeA_h;
+	int pipeB_x;
+	int pipeB_y;
+	int pipeB_w;
+	int pipeB_h;
 } drmI830Sarea;
 
 /* Flags for perf_boxes
diff --git a/src/i830_dri.h b/src/i830_dri.h
index 41f8a90..3a4cfaf 100644
--- a/src/i830_dri.h
+++ b/src/i830_dri.h
@@ -9,8 +9,8 @@
 #define I830_MAX_DRAWABLES 256
 
 #define I830_MAJOR_VERSION 1
-#define I830_MINOR_VERSION 6
-#define I830_PATCHLEVEL 4
+#define I830_MINOR_VERSION 7
+#define I830_PATCHLEVEL 0
 
 #define I830_REG_SIZE 0x80000
 
diff --git a/src/i830_driver.c b/src/i830_driver.c
index ffa93f8..fc768af 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1342,15 +1342,49 @@ I830UpdateXineramaScreenInfo(ScrnInfoPtr
     Bool infochanged = FALSE;
     Bool usenonrect = pI830->NonRect;
     const char *rectxine = "\t... setting up rectangular Xinerama layout\n";
+#ifdef XF86DRI
+    drmI830Sarea *sarea;
+
+    if (pI830->directRenderingEnabled) {
+       sarea = (drmI830Sarea *) DRIGetSAREAPrivate(pScrn1->pScreen);
+    }
+#endif
 
     pI830->MBXNR1XMAX = pI830->MBXNR1YMAX = pI830->MBXNR2XMAX = pI830->MBXNR2YMAX = 65536;
     pI830->HaveNonRect = pI830->HaveOffsRegions = FALSE;
 
-    if(!pI830->MergedFB) return;
+    if(!pI830->MergedFB) {
+#ifdef XF86DRI
+       if (pI830->directRenderingEnabled) {
+          sarea->pipeA_x = sarea->pipeA_y = sarea->pipeB_x = sarea->pipeB_y = 0;
 
-    if(I830noPanoramiXExtension) return;
+          if (pI830->planeEnabled[0]) {
+             sarea->pipeA_w = pScrn1->virtualX;
+             sarea->pipeA_h = pScrn1->virtualY;
+          } else {
+             sarea->pipeA_w = 0;
+             sarea->pipeA_h = 0;
+          }
+
+          if (pI830->planeEnabled[1]) {
+             sarea->pipeB_w = pScrn1->virtualX;
+             sarea->pipeB_h = pScrn1->virtualY;
+          } else {
+             sarea->pipeB_w = 0;
+             sarea->pipeB_h = 0;
+          }
+       }
+#endif
 
-    if(!I830XineramadataPtr) return;
+       return;
+    }
+
+    if (I830noPanoramiXExtension || !I830XineramadataPtr) {
+#ifdef XF86DRI
+       if (!pI830->directRenderingEnabled)
+#endif
+	  return;
+    }
 
     if(pI830->SecondIsScrn0) {
        scrnnum1 = 1;
@@ -1631,14 +1665,30 @@ I830UpdateXineramaScreenInfo(ScrnInfoPtr
 
     }
 
-    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;
+#ifdef XF86DRI
+    if (pI830->directRenderingEnabled) {
+       sarea->pipeA_x = x1;
+       sarea->pipeA_y = y1;
+       sarea->pipeA_w = w1;
+       sarea->pipeA_h = h1;
+       sarea->pipeB_x = x2;
+       sarea->pipeB_y = y2;
+       sarea->pipeB_w = w2;
+       sarea->pipeB_h = h2;
+    }
+#endif
+
+    if (I830XineramadataPtr && !I830noPanoramiXExtension) {
+       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;
+    } else
+       return;
 
     if(infochanged) {
        xf86DrvMsg(pScrn1->scrnIndex, X_INFO,
@@ -8186,9 +8236,7 @@ I830BIOSSwitchMode(int scrnIndex, Displa
    /* Since RandR (indirectly) uses SwitchMode(), we need to
     * update our Xinerama info here, too, in case of resizing
     */
-   if(pI830->MergedFB) {
-      I830UpdateXineramaScreenInfo(pScrn);
-   }
+   I830UpdateXineramaScreenInfo(pScrn);
 
    return ret;
 }
diff-tree 06c5f7bd076e9ba4b925e061a40b837714bc8267 (from 89cbc6e215a5f313ccc17370424c35630cf75892)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Wed Aug 30 19:45:33 2006 +0200

    If the DRM can handle it, enable vertical blank interrupts for both pipes.

diff --git a/src/i830_dri.c b/src/i830_dri.c
index 92f8d4a..21af651 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1489,9 +1489,12 @@ I830DRISetVBlankInterrupt (ScrnInfoPtr p
 
     if (pI830->directRenderingEnabled && pI830->drmMinor >= 5) {
 	if (on) {
-	    if (pI830->planeEnabled[1])
-		pipe.pipe = DRM_I830_VBLANK_PIPE_B;
-	    else
+	    if (pI830->planeEnabled[1]) {
+		if (pI830->drmMinor >= 6)
+		    pipe.pipe = DRM_I830_VBLANK_PIPE_A | DRM_I830_VBLANK_PIPE_B;
+		else
+		    pipe.pipe = DRM_I830_VBLANK_PIPE_B;
+	    } else
 		pipe.pipe = DRM_I830_VBLANK_PIPE_A;
 	} else {
 	    pipe.pipe = 0;
diff-tree 89cbc6e215a5f313ccc17370424c35630cf75892 (from 6614b4bda2e079fd1e56e0825894481b80e2df58)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Thu Aug 24 10:30:27 2006 +0200

    Only enable the IRQ after DRIFinishScreenInit.
    
    This makes sure we've been assigned a context ID, so the interrupt context
    won't mess things up if it grabs the HW lock.

diff --git a/src/i830_dri.c b/src/i830_dri.c
index c9b52c4..92f8d4a 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -835,29 +835,6 @@ I830DRIDoMappings(ScreenPtr pScreen)
       I830SetParam(pScrn, I830_SETPARAM_USE_MI_BATCHBUFFER_START, 1 );
    }
 
-   /* Okay now initialize the dma engine */
-   {
-      pI830DRI->irq = drmGetInterruptFromBusID(pI830->drmSubFD,
-					       ((pciConfigPtr) pI830->
-						PciInfo->thisCard)->busnum,
-					       ((pciConfigPtr) pI830->
-						PciInfo->thisCard)->devnum,
-					       ((pciConfigPtr) pI830->
-						PciInfo->thisCard)->funcnum);
-
-      if (drmCtlInstHandler(pI830->drmSubFD, pI830DRI->irq)) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		    "[drm] failure adding irq handler\n");
-	 pI830DRI->irq = 0;
-	 DRICloseScreen(pScreen);
-	 return FALSE;
-      }
-      else
-	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		    "[drm] dma control initialized, using IRQ %d\n",
-		    pI830DRI->irq);
-   }
-
    pI830DRI = (I830DRIPtr) pI830->pDRIInfo->devPrivate;
    pI830DRI->deviceID = pI830->PciInfo->chipType;
    pI830DRI->width = pScrn->virtualX;
@@ -982,7 +959,34 @@ I830DRIFinishScreenInit(ScreenPtr pScree
       pI830->allowPageFlip = 0;
 
 
-   return DRIFinishScreenInit(pScreen);
+   if (!DRIFinishScreenInit(pScreen))
+      return FALSE;
+
+   /* Okay now initialize the dma engine */
+   {
+      I830DRIPtr pI830DRI = (I830DRIPtr) pI830->pDRIInfo->devPrivate;
+
+      pI830DRI->irq = drmGetInterruptFromBusID(pI830->drmSubFD,
+					       ((pciConfigPtr) pI830->
+						PciInfo->thisCard)->busnum,
+					       ((pciConfigPtr) pI830->
+						PciInfo->thisCard)->devnum,
+					       ((pciConfigPtr) pI830->
+						PciInfo->thisCard)->funcnum);
+
+      if (drmCtlInstHandler(pI830->drmSubFD, pI830DRI->irq)) {
+	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		    "[drm] failure adding irq handler\n");
+	 pI830DRI->irq = 0;
+	 DRICloseScreen(pScreen);
+	 return FALSE;
+      }
+      else
+	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		    "[drm] dma control initialized, using IRQ %d\n",
+		    pI830DRI->irq);
+	 return TRUE;
+   }
 }
 
 void
diff-tree 185df8a18102eea79b8c8e11304dfee148ac2002 (from 1422d4f04ac2d57899eee91f6522f8670f7263da)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Sep 27 16:48:43 2006 +0800

    Add mask sampler state

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 1422d4f04ac2d57899eee91f6522f8670f7263da (from 52a4f2a02b8f38108bfa866bf74b1596b8125512)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Wed Sep 27 13:54:14 2006 +0800

    change some src sampler states
    
    sampler for mask should also be set up, and fix
    default border texel.

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 6614b4bda2e079fd1e56e0825894481b80e2df58 (from parents)
Merge: d6ca9feb78a9211758510751bbf47013caabff49 b3ddcf3348365873aed4a2b8b2750b330fb4cf26
Author: Alan Hourihane <alanh at fairlite.demon.co.uk>
Date:   Mon Sep 25 12:04:01 2006 +0100

    Merge branch 'master' of git+ssh://git.freedesktop.org/git/xorg/driver/xf86-video-intel

diff-tree d6ca9feb78a9211758510751bbf47013caabff49 (from 564c830a91afda76706a8c4c2f3287d0b8d514e9)
Author: Alan Hourihane <alanh at fairlite.demon.co.uk>
Date:   Mon Sep 25 12:03:27 2006 +0100

    Fix bug #7943 where video flickers when changing
    attributes. This code was a leftover from testing lockups
    and shouldn't be needed anymore.

diff --git a/src/i830_video.c b/src/i830_video.c
index c044ddd..b87e4eb 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -951,22 +951,14 @@ I830SetPortAttribute(ScrnInfoPtr pScrn,
       pPriv->brightness = value;
       overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff);
       ErrorF("BRIGHTNESS\n");
-      overlay->OCMD &= ~OVERLAY_ENABLE;
       OVERLAY_UPDATE;
-#if 1
-      OVERLAY_OFF;
-#endif
    } 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->OCMD &= ~OVERLAY_ENABLE;
       OVERLAY_UPDATE;
-#if 1
-      OVERLAY_OFF;
-#endif
    } else if (pI830->Clone && attribute == xvPipe) {
       if ((value < 0) || (value > 1))
          return BadValue;
@@ -980,11 +972,7 @@ I830SetPortAttribute(ScrnInfoPtr pScrn,
       else 
          overlay->OCONFIG |= OVERLAY_PIPE_B;
       ErrorF("PIPE CHANGE\n");
-      overlay->OCMD &= ~OVERLAY_ENABLE;
       OVERLAY_UPDATE;
-#if 1
-      OVERLAY_OFF;
-#endif
    } else if (attribute == xvGamma0 && (IS_I9XX(pI830))) {
       pPriv->gamma0 = value; 
    } else if (attribute == xvGamma1 && (IS_I9XX(pI830))) {
@@ -1011,11 +999,7 @@ I830SetPortAttribute(ScrnInfoPtr pScrn,
 	 break;
       }
       ErrorF("COLORKEY\n");
-      overlay->OCMD &= ~OVERLAY_ENABLE;
       OVERLAY_UPDATE;
-#if 1
-      OVERLAY_OFF;
-#endif
       REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
    } else if(attribute == xvDoubleBuffer) {
       if ((value < 0) || (value > 1))
@@ -1026,20 +1010,20 @@ I830SetPortAttribute(ScrnInfoPtr pScrn,
    } else
       return BadMatch;
 
-   /* We've already confirmed that the overlay is off, ready for updating */
+   /* Ensure that the overlay is off, ready for updating */
    if ((attribute == xvGamma0 ||
         attribute == xvGamma1 ||
         attribute == xvGamma2 ||
         attribute == xvGamma3 ||
         attribute == xvGamma4 ||
         attribute == xvGamma5) && (IS_I9XX(pI830))) {
+	CARD32 r = overlay->OCMD & OVERLAY_ENABLE;
         ErrorF("GAMMA\n");
         overlay->OCMD &= ~OVERLAY_ENABLE;
         OVERLAY_UPDATE;
-#if 1
-        OVERLAY_OFF;
-#endif
 	I830UpdateGamma(pScrn);
+        overlay->OCMD |= r;
+        OVERLAY_UPDATE;
    }
 
    return Success;
diff-tree 52a4f2a02b8f38108bfa866bf74b1596b8125512 (from f272f0d811f9ee059e8f8617a516e6c8bff917a1)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Mon Sep 25 14:35:51 2006 +0800

    Add file for i965 exa composite
    
    This does not include ps program, which will be added
    in g4a form.

diff --git a/src/Makefile.am b/src/Makefile.am
index 163cc3f..f08d9a7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -69,7 +69,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 a1c7546..9b2e6b2 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -120,6 +120,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
@@ -418,6 +423,8 @@ IntelEXADoneComposite(PixmapPtr pDst)
     I830Sync(pScrn);
 #endif
 }
+
+#define BRW_LINEAR_EXTRA (32*1024)
 /*
  * TODO:
  *   - Dual head?
@@ -440,7 +447,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,
@@ -490,6 +501,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 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 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 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 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 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 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 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 b7e57deebbda527e878326cf3e6358c0a48d7817 (from 43daaec63929c1f0e54a5125375d8147629da4b9)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Tue Aug 22 19:38:13 2006 +0800

    pci id update for Crestline
    
    The "Crestline" banner should be replaced with official
    name later.

diff --git a/src/common.h b/src/common.h
index ad5ee1d..d808b21 100644
--- a/src/common.h
+++ b/src/common.h
@@ -301,6 +301,11 @@ extern int I810_DEBUG;
 #define PCI_CHIP_I946_GZ_BRIDGE 	0x2970
 #endif
 
+#ifndef PCI_CHIP_CRESTLINE		//XXX: fix with official name
+#define PCI_CHIP_CRESTLINE		0x2A02
+#define PCI_CHIP_CRESTLINE_BRIDGE 	0x2A00
+#endif
+
 #define IS_I810(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I810 ||	\
 			pI810->PciInfo->chipType == PCI_CHIP_I810_DC100 || \
 			pI810->PciInfo->chipType == PCI_CHIP_I810_E)
@@ -316,10 +321,11 @@ extern int I810_DEBUG;
 #define IS_I915GM(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I915_GM)
 #define IS_I945G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I945_G)
 #define IS_I945GM(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I945_GM)
-#define IS_I965G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I965_G || pI810->PciInfo->chipType == PCI_CHIP_I965_G_1 || pI810->PciInfo->chipType == PCI_CHIP_I965_Q || pI810->PciInfo->chipType == PCI_CHIP_I946_GZ)
+#define IS_I965G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I965_G || pI810->PciInfo->chipType == PCI_CHIP_I965_G_1 || pI810->PciInfo->chipType == PCI_CHIP_I965_Q || pI810->PciInfo->chipType == PCI_CHIP_I946_GZ || pI810->PciInfo->chipType == PCI_CHIP_CRESTLINE)
 #define IS_I9XX(pI810) (IS_I915G(pI810) || IS_I915GM(pI810) || IS_I945G(pI810) || IS_I945GM(pI810) || IS_I965G(pI810))
+#define IS_CRESTLINE(pI810) (pI810->PciInfo->chipType == PCI_CHIP_CRESTLINE) // XXX: IS_965GM ?
 
-#define IS_MOBILE(pI810) (IS_I830(pI810) || IS_I85X(pI810) || IS_I915GM(pI810) || IS_I945GM(pI810))
+#define IS_MOBILE(pI810) (IS_I830(pI810) || IS_I85X(pI810) || IS_I915GM(pI810) || IS_I945GM(pI810) || IS_CRESTLINE(pI810))
 
 #define GTT_PAGE_SIZE			KB(4)
 #define ROUND_TO(x, y)			(((x) + (y) - 1) / (y) * (y))
diff --git a/src/i810_driver.c b/src/i810_driver.c
index 3481d0b..48e1463 100644
--- a/src/i810_driver.c
+++ b/src/i810_driver.c
@@ -144,6 +144,7 @@ static SymTabRec I810Chipsets[] = {
    {PCI_CHIP_I965_G_1,		"965G"},
    {PCI_CHIP_I965_Q,		"965Q"},
    {PCI_CHIP_I946_GZ,		"946GZ"},
+   {PCI_CHIP_CRESTLINE,		"Crestline"},
    {-1,				NULL}
 };
 
@@ -167,6 +168,7 @@ static PciChipsets I810PciChipsets[] = {
    {PCI_CHIP_I965_G_1,		PCI_CHIP_I965_G_1,	RES_SHARED_VGA},
    {PCI_CHIP_I965_Q,		PCI_CHIP_I965_Q,	RES_SHARED_VGA},
    {PCI_CHIP_I946_GZ,		PCI_CHIP_I946_GZ,	RES_SHARED_VGA},
+   {PCI_CHIP_CRESTLINE,		PCI_CHIP_CRESTLINE,	RES_SHARED_VGA},
    {-1,				-1, RES_UNDEFINED }
 };
 
@@ -589,6 +591,7 @@ I810Probe(DriverPtr drv, int flags)
 	    case PCI_CHIP_I965_G_1:
 	    case PCI_CHIP_I965_Q:
 	    case PCI_CHIP_I946_GZ:
+	    case PCI_CHIP_CRESTLINE:
     	       xf86SetEntitySharable(usedChips[i]);
 
     	       /* Allocate an entity private if necessary */		
diff --git a/src/i830_driver.c b/src/i830_driver.c
index c0d9672..cdf005a 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -218,6 +218,7 @@ static SymTabRec I830BIOSChipsets[] = {
    {PCI_CHIP_I965_G_1,		"965G"},
    {PCI_CHIP_I965_Q,		"965Q"},
    {PCI_CHIP_I946_GZ,		"946GZ"},
+   {PCI_CHIP_CRESTLINE,		"Crestline"},
    {-1,				NULL}
 };
 
@@ -235,6 +236,7 @@ static PciChipsets I830BIOSPciChipsets[]
    {PCI_CHIP_I965_G_1,		PCI_CHIP_I965_G_1,	RES_SHARED_VGA},
    {PCI_CHIP_I965_Q,		PCI_CHIP_I965_Q,	RES_SHARED_VGA},
    {PCI_CHIP_I946_GZ,		PCI_CHIP_I946_GZ,	RES_SHARED_VGA},
+   {PCI_CHIP_CRESTLINE,		PCI_CHIP_CRESTLINE,	RES_SHARED_VGA},
    {-1,				-1,			RES_UNDEFINED}
 };
 
@@ -4022,6 +4024,9 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
    case PCI_CHIP_I946_GZ:
       chipname = "946GZ";
       break;
+   case PCI_CHIP_CRESTLINE:
+      chipname = "Crestline";
+      break;
    default:
       chipname = "unknown chipset";
       break;
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 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 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 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 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 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 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 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