xf86-video-intel: Branch 'glucose' - 37 commits - configure.ac src/bios_reader/Makefile.am src/ch7017/ch7017.c src/ch7017/ch7017_reg.h src/ch7xxx/ch7xxx.c src/i830_common.h src/i830_cursor.c src/i830_dri.c src/i830_driver.c src/i830_dvo.c src/i830.h src/i830_memory.c src/i830_quirks.c src/i830_render.c src/i830_video.c src/ivch/ivch.c src/Makefile.am src/sil164/sil164.c src/sil164/sil164_reg.h src/tfp410/tfp410.c src/tfp410/tfp410_reg.h

Alan Hourihane alanh at kemper.freedesktop.org
Mon Oct 15 14:18:14 PDT 2007


 configure.ac                |    8 
 src/Makefile.am             |    2 
 src/bios_reader/Makefile.am |    2 
 src/ch7017/ch7017.c         |   67 +++--
 src/ch7017/ch7017_reg.h     |   13 -
 src/ch7xxx/ch7xxx.c         |   27 +-
 src/i830.h                  |   34 +-
 src/i830_common.h           |    2 
 src/i830_cursor.c           |   58 ++++
 src/i830_dri.c              |  369 ++++++++++++++---------------
 src/i830_driver.c           |  197 ++++++++-------
 src/i830_dvo.c              |   22 +
 src/i830_memory.c           |  553 ++++++++++++++++++++------------------------
 src/i830_quirks.c           |    6 
 src/i830_render.c           |    3 
 src/i830_video.c            |    1 
 src/ivch/ivch.c             |   20 +
 src/sil164/sil164.c         |   20 -
 src/sil164/sil164_reg.h     |    1 
 src/tfp410/tfp410.c         |   28 +-
 src/tfp410/tfp410_reg.h     |    2 
 21 files changed, 785 insertions(+), 650 deletions(-)

New commits:
commit 14423147e6c506806eb5074ef720bf3873e7227b
Merge: 9711717... d66e924...
Author: Alan Hourihane <alanh at tungstengraphics.com>
Date:   Mon Oct 15 22:18:02 2007 +0100

    Merge git+ssh://git.freedesktop.org/git/xorg/driver/xf86-video-intel into glucose

diff --cc src/i830.h
index ac4f2fb,57f0544..14eb0e5
--- a/src/i830.h
+++ b/src/i830.h
@@@ -389,19 -405,9 +405,9 @@@ typedef struct _I830Rec 
     int NumScanlineColorExpandBuffers;
     int nextColorExpandBuf;
  
-     /**
-      * 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 fence_used[FENCE_NEW_NR];
  
 -   Bool useEXA;
 +   int AccelMethod;
     Bool noAccel;
     Bool SWCursor;
  #ifdef I830_USE_XAA
commit d66e924680a3504aa1feb9c228145a95d1a16b1e
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Oct 15 11:31:51 2007 -0700

    In update_front_offset(), set pScrn->fbOffset even at EnterVT during init.
    
    Failure to do so led to the memset() at EnterVT being done to an invalid
    offset.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index bfc006a..1d4e154 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -793,21 +793,21 @@ i830_update_front_offset(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)))
+
+   /* 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) {
+      if (!pScreen->ModifyPixmapHeader(pScreen->GetScreenPixmap(pScreen),
+				       -1, -1, -1, -1, -1,
+				       (pointer)(pI830->FbBase +
+						 pScrn->fbOffset)))
        FatalError("Couldn't adjust screen pixmap\n");
+   }
 }
 
 /**
commit c94cdfd6ddbc580523737f596e97b96a7ce100b9
Author: Jesse Barnes <jbarnes at jbarnes-mobile.amr.corp.intel.com>
Date:   Sat Oct 13 15:57:45 2007 -0700

    Fix palette save/restore
    
    When restoring the palette, we weren't checking to make sure the
    associated pipe was enabled before writing the registers.  In some
    configurations, this led to a driver crash.  Add new routines to handle
    palette save/restore and verify that the pipes are on before we touch
    the registers (could easily be changed to enable/disable the pipes
    around the save/restore as well).

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 0eb6e2d..bfc006a 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1732,7 +1732,6 @@ 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));
@@ -1840,6 +1839,52 @@ SetHWOperatingState(ScrnInfoPtr pScrn)
       I830InitHWCursor(pScrn);
 }
 
+enum pipe {
+    PIPE_A = 0,
+    PIPE_B,
+};
+
+static Bool
+i830_pipe_enabled(I830Ptr pI830, enum pipe pipe)
+{
+    if (pipe == PIPE_A)
+	return (INREG(PIPEACONF) & PIPEACONF_ENABLE);
+    else
+	return (INREG(PIPEBCONF) & PIPEBCONF_ENABLE);
+}
+
+static void
+i830_save_palette(I830Ptr pI830, enum pipe pipe)
+{
+    int i;
+
+    if (!i830_pipe_enabled(pI830, pipe))
+	return;
+
+    for(i= 0; i < 256; i++) {
+	if (pipe == PIPE_A)
+	    pI830->savePaletteA[i] = INREG(PALETTE_A + (i << 2));
+	else
+	    pI830->savePaletteB[i] = INREG(PALETTE_B + (i << 2));
+    }
+}
+
+static void
+i830_restore_palette(I830Ptr pI830, enum pipe pipe)
+{
+    int i;
+
+    if (!i830_pipe_enabled(pI830, pipe))
+	return;
+
+    for(i= 0; i < 256; i++) {
+	if (pipe == PIPE_A)
+	    OUTREG(PALETTE_A + (i << 2), pI830->savePaletteA[i]);
+	else
+	    OUTREG(PALETTE_B + (i << 2), pI830->savePaletteB[i]);
+    }
+}
+
 static Bool
 SaveHWState(ScrnInfoPtr pScrn)
 {
@@ -1877,9 +1922,7 @@ SaveHWState(ScrnInfoPtr pScrn)
    pI830->saveDSPAPOS = INREG(DSPAPOS);
    pI830->saveDSPABASE = INREG(DSPABASE);
 
-   for(i= 0; i < 256; i++) {
-      pI830->savePaletteA[i] = INREG(PALETTE_A + (i << 2));
-   }
+   i830_save_palette(pI830, PIPE_A);
 
    if(xf86_config->num_crtc == 2) {
       pI830->savePIPEBCONF = INREG(PIPEBCONF);
@@ -1901,9 +1944,8 @@ SaveHWState(ScrnInfoPtr pScrn)
       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));
-      }
+
+      i830_save_palette(pI830, PIPE_B);
    }
 
    if (IS_I965G(pI830)) {
@@ -2069,15 +2111,8 @@ RestoreHWState(ScrnInfoPtr pScrn)
    OUTREG(VCLK_DIVISOR_VGA1, pI830->saveVCLK_DIVISOR_VGA1);
    OUTREG(VCLK_POST_DIV, pI830->saveVCLK_POST_DIV);
 
-   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]);
-      }
-   }
+   i830_restore_palette(pI830, PIPE_A);
+   i830_restore_palette(pI830, PIPE_B);
 
    for(i = 0; i < 7; i++) {
       OUTREG(SWF0 + (i << 2), pI830->saveSWF[i]);
commit e04333a6352040bc883655d606923c912d005981
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Oct 12 12:42:45 2007 -0700

    Fix failure in tiling setup on non-power-of-two allocations on pre-965.

diff --git a/src/i830.h b/src/i830.h
index 031781e..57f0544 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -145,6 +145,11 @@ struct _i830_memory {
      */
     unsigned long size;
     /**
+     * Allocated aperture size, taking into account padding to allow for
+     * tiling.
+     */
+    unsigned long allocated_size;
+    /**
      * Physical (or more properly, bus) address of the allocation.
      * Only set if requested during allocation.
      */
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 35e19f9..2ddc454 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -190,7 +190,7 @@ i830_bind_memory(ScrnInfoPtr pScrn, i830_memory *mem)
 
     if (mem->tiling != TILE_NONE) {
 	mem->fence_nr = i830_set_tiling(pScrn, mem->offset, mem->pitch,
-					mem->size, mem->tiling);
+					mem->allocated_size, mem->tiling);
     }
 
     /* Mark the pages accessible now that they're bound. */
@@ -617,6 +617,7 @@ i830_allocate_aperture(ScrnInfoPtr pScrn, const char *name,
     /* Only allocate page-sized increments. */
     size = ALIGN(size, GTT_PAGE_SIZE);
     mem->size = size;
+    mem->allocated_size = size;
 
     if (alignment < GTT_PAGE_SIZE)
 	alignment = GTT_PAGE_SIZE;
@@ -754,6 +755,7 @@ i830_allocate_memory_bo(ScrnInfoPtr pScrn, const char *name,
     mem->offset = -1;
     mem->end = -1;
     mem->size = size;
+    mem->allocated_size = size;
     if (flags & NEED_LIFETIME_FIXED)
 	mem->lifetime_fixed_offset = TRUE;
 
commit a1612b7728d4153499fe86b6713a13c8702cc7d9
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Oct 12 12:42:06 2007 -0700

    Use mprotect on unbound AGP memory to attempt to catch use while unbound.
    
    This doesn't help with the most common use-while-unbound cases, which are
    from the hardware side.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 9ca1222..0eb6e2d 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -171,6 +171,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include <unistd.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <sys/mman.h>
 
 #include "xf86.h"
 #include "xf86_OSproc.h"
@@ -667,6 +668,15 @@ I830MapMem(ScrnInfoPtr pScrn)
 	 pI830->FbBase + pI830->LpRing->mem->offset;
    }
 
+   /* Mark the pages we haven't yet bound into AGP as inaccessible. */
+   if (pI830->FbMapSize > pI830->stolen_size) {
+      if (mprotect(pI830->FbBase + pI830->stolen_size,
+		   pI830->FbMapSize - pI830->stolen_size, PROT_NONE) != 0) {
+	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		    "Failed to mprotect unbound AGP: %s\n", strerror(errno));
+      }
+   }
+
    return TRUE;
 }
 
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 9dfe43e..35e19f9 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -98,6 +98,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #include <assert.h>
 #include <string.h>
+#include <errno.h>
+#include <sys/mman.h>
 
 #include "xf86.h"
 #include "xf86_OSproc.h"
@@ -191,15 +193,31 @@ i830_bind_memory(ScrnInfoPtr pScrn, i830_memory *mem)
 					mem->size, mem->tiling);
     }
 
+    /* Mark the pages accessible now that they're bound. */
+    if (mprotect(pI830->FbBase + mem->offset, ALIGN(mem->size, GTT_PAGE_SIZE),
+		 PROT_READ | PROT_WRITE) != 0) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "Failed to mprotect %s: %s\n", mem->name, strerror(errno));
+    }
+
     return TRUE;
 }
 
 static Bool
 i830_unbind_memory(ScrnInfoPtr pScrn, i830_memory *mem)
 {
+    I830Ptr pI830 = I830PTR(pScrn);
+
     if (mem == NULL || !mem->bound)
 	return TRUE;
 
+    /* Mark the pages accessible now that they're bound. */
+    if (mprotect(pI830->FbBase + mem->offset, ALIGN(mem->size, GTT_PAGE_SIZE),
+		 PROT_NONE) != 0) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "Failed to mprotect %s: %s\n", mem->name, strerror(errno));
+    }
+
     if (mem->tiling != TILE_NONE)
 	i830_clear_tiling(pScrn, mem->fence_nr);
 
commit 3af442ba52550a9d183e215d49cc12dac0cb9e4b
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Oct 11 11:56:06 2007 -0700

    Don't double-free the memory manager allocation.

diff --git a/src/i830_memory.c b/src/i830_memory.c
index 0b046f6..9dfe43e 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -279,8 +279,18 @@ i830_reset_allocations(ScrnInfoPtr pScrn)
     int	    p;
 
     /* While there is any memory between the start and end markers, free it. */
-    while (pI830->memory_list->next->next != NULL)
+    while (pI830->memory_list->next->next != NULL) {
+	i830_memory *mem = pI830->memory_list->next;
+
+	/* Don't reset BO allocator, which we set up at init. */
+	if (pI830->memory_manager == mem) {
+	    mem = mem->next;
+	    if (mem->next == NULL)
+		break;
+	}
+
 	i830_free_memory(pScrn, pI830->memory_list->next);
+    }
 
     /* Free any allocations in buffer objects */
 #ifdef XF86DRI_MM
commit 6c485ff5bd25e9aa6a3c1eb669843e6b969d94df
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Oct 5 15:52:56 2007 -0700

    Update memory manager sizing for the current set of LIFETIME_FIXED bufffers.

diff --git a/src/i830_memory.c b/src/i830_memory.c
index 277f698..0b046f6 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -403,7 +403,18 @@ i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset, unsigned long size)
 	 * physical-address allocations of cursor/overlay registers.
 	 */
 	mmsize = size;
-	/* Overlay is always set up as fixed, currently. */
+
+	/* EXA area is fixed. */
+	if (pI830->useEXA) {
+	    mmsize -= ROUND_TO_PAGE(3 * pScrn->displayWidth * pI830->cpp *
+				    pScrn->virtualY);
+	}
+	/* Classic textures are fixed. */
+	if (pI830->allocate_classic_textures)
+	    mmsize -= MB(32);
+	/* Overlay and cursors, if physical, need to be allocated outside
+	 * of the kernel memory manager.
+	 */
 	if (!OVERLAY_NOPHYSICAL(pI830) && !IS_I965G(pI830)) {
 	    mmsize -= ROUND_TO(OVERLAY_SIZE, GTT_PAGE_SIZE);
 	}
commit d47cf148776d74f9035863b23eefdc2b5893af08
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Oct 5 15:45:51 2007 -0700

    Move tiling fence register setup to bind time instead of allocate time.
    
    This allows us to allocate tiled buffers in buffer objects.  In the process
    I removed the fence division that we had for tiled buffers on pre-965.  If we
    resurrect that code, it should probably be managed by just dividing all the
    objects in roughly half and fencing those halves (to reduce the alignment
    requirement), instead of using giant fences until we run out of space and then
    trying to deal with scarce space on the last (or not) buffer.  Halving
    our tiled objects would use 6/8 of our fence registers on that hardware.

diff --git a/src/i830.h b/src/i830.h
index a34be61..031781e 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -163,6 +163,13 @@ struct _i830_memory {
     unsigned long agp_offset;
 
     enum tile_format tiling;
+    /**
+     * Index of the fence register representing the tiled surface, when
+     * bound.
+     */
+    int fence_nr;
+    /** Pitch value in bytes for tiled surfaces */
+    unsigned int pitch;
 
     /** Description of the allocation, for logging */
     char *name;
@@ -393,17 +400,7 @@ typedef struct _I830Rec {
    int NumScanlineColorExpandBuffers;
    int nextColorExpandBuf;
 
-    /**
-     * 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 fence_used[FENCE_NEW_NR];
 
    Bool useEXA;
    Bool noAccel;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 339fe25..9ca1222 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1732,16 +1732,6 @@ ResetState(ScrnInfoPtr pScrn, Bool flush)
    if (pI830->entityPrivate)
       pI830->entityPrivate->RingRunning = 0;
 
-   /* Reset the fence registers to 0 */
-   if (IS_I965G(pI830)) {
-      for (i = 0; i < FENCE_NEW_NR; i++) {
-	 OUTREG(FENCE_NEW + i * 8, 0);
-	 OUTREG(FENCE_NEW + 4 + i * 8, 0);
-      }
-   } else {
-      for (i = 0; i < FENCE_NR; i++)
-         OUTREG(FENCE + i * 4, 0);
-   }
    /* Flush the ring buffer (if enabled), then disable it. */
    /* God this is ugly */
 #define flush_ring() do { \
@@ -1770,34 +1760,6 @@ ResetState(ScrnInfoPtr pScrn, Bool flush)
 }
 
 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->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->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->fence[i]);
-         if (I810_DEBUG & DEBUG_VERBOSE_VGA)
-	    ErrorF("Fence Register : %x\n", pI830->fence[i]);
-      }
-   }
-}
-
-static void
 SetRingRegs(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
@@ -1864,7 +1826,6 @@ SetHWOperatingState(ScrnInfoPtr pScrn)
 
    if (!pI830->noAccel)
       SetRingRegs(pScrn);
-   SetFenceRegs(pScrn);
    if (!pI830->SWCursor)
       I830InitHWCursor(pScrn);
 }
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 4d55ca7..277f698 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -115,10 +115,12 @@ 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,
+static int i830_set_tiling(ScrnInfoPtr pScrn, unsigned int offset,
 			   unsigned int pitch, unsigned int size,
 			   enum tile_format tile_format);
 
+static void i830_clear_tiling(ScrnInfoPtr pScrn, unsigned int fence_nr);
+
 /**
  * Returns the fence size for a tiled area of the given size.
  */
@@ -162,26 +164,31 @@ i830_bind_memory(ScrnInfoPtr pScrn, i830_memory *mem)
 	int ret;
 
 	ret = drmBOSetPin(pI830->drmSubFD, &mem->bo, 1);
-	if (ret == 0) {
-	    mem->bound = TRUE;
-	    mem->offset = mem->bo.offset;
-	    mem->end = mem->bo.offset + mem->size;
-	    return TRUE;
-	} else {
+	if (ret != 0)
 	    return FALSE;
-	}
+
+	mem->bound = TRUE;
+	mem->offset = mem->bo.offset;
+	mem->end = mem->bo.offset + mem->size;
     }
 #endif
 
-    if (!pI830->gtt_acquired)
-	return TRUE;
+    if (!mem->bound) {
+	if (!pI830->gtt_acquired)
+	    return TRUE;
+
+	if (mem->key != -1 && 
+	    !xf86BindGARTMemory(pScrn->scrnIndex, mem->key, mem->agp_offset))
+	{
+	    return FALSE;
+	}
 
-    if (mem->key == -1 ||
-	xf86BindGARTMemory(pScrn->scrnIndex, mem->key, mem->agp_offset)) {
 	mem->bound = TRUE;
-	return TRUE;
-    } else {
-	return FALSE;
+    }
+
+    if (mem->tiling != TILE_NONE) {
+	mem->fence_nr = i830_set_tiling(pScrn, mem->offset, mem->pitch,
+					mem->size, mem->tiling);
     }
 
     return TRUE;
@@ -193,6 +200,9 @@ i830_unbind_memory(ScrnInfoPtr pScrn, i830_memory *mem)
     if (mem == NULL || !mem->bound)
 	return TRUE;
 
+    if (mem->tiling != TILE_NONE)
+	i830_clear_tiling(pScrn, mem->fence_nr);
+
 #ifdef XF86DRI_MM
     if (mem->bo.size != 0) {
 	I830Ptr pI830 = I830PTR(pScrn);
@@ -303,10 +313,6 @@ i830_reset_allocations(ScrnInfoPtr pScrn)
     pI830->textures = NULL;
 #endif
     pI830->LpRing->mem = NULL;
-
-    /* Reset the fence register allocation. */
-    pI830->next_fence = 0;
-    memset(pI830->fence, 0, sizeof(pI830->fence));
 }
 
 void
@@ -797,17 +803,10 @@ i830_allocate_memory_tiled(ScrnInfoPtr pScrn, const char *name,
     unsigned long aper_size;
     unsigned long aper_align;
     i830_memory *mem;
-    int fence_divide, i;
 
     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);
 
@@ -832,51 +831,13 @@ i830_allocate_memory_tiled(ScrnInfoPtr pScrn, const char *name,
     if (aper_align < alignment)
 	aper_align = alignment;
 
-    fence_divide = 1;
     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
-	 * 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_memory(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;
-    }
-
-    /* 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;
     mem->tiling = tile_format;
+    mem->pitch = pitch;
+    mem->fence_nr = -1;
 
     return mem;
 }
@@ -1222,9 +1183,6 @@ i830_allocate_cursor_buffers(ScrnInfoPtr pScrn)
      */
     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,
@@ -1654,203 +1612,216 @@ i830_allocate_3d_memory(ScrnInfoPtr pScrn)
 #endif
 
 /**
- * Sets up a fence area for the hardware.
+ * Sets up tiled surface registers ("fences") for the hardware.
  *
  * The fences control automatic tiled address swizzling for CPU access of the
- * framebuffer.
+ * framebuffer, and may be used in many rendering operations instead of
+ * manually supplying tiling enables per surface.
  */
-static void
-i830_set_fence(ScrnInfoPtr pScrn, int nr, unsigned int offset,
-	       unsigned int pitch, unsigned int size,
-	       enum tile_format tile_format)
+static int
+i830_set_tiling(ScrnInfoPtr pScrn, 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;
+    unsigned int max_fence;
+    unsigned int fence_nr;
 
-    DPRINTF(PFX, "i830_set_fence(): %d, 0x%08x, %d, %d kByte\n",
-	    nr, offset, pitch, size / 1024);
+    DPRINTF(PFX, "i830_set_tiling(): 0x%08x, %d, %d kByte\n",
+	    offset, pitch, size / 1024);
 
     assert(tile_format != TILE_NONE);
 
+    if (IS_I965G(pI830))
+	max_fence = FENCE_NEW_NR;
+    else
+	max_fence = FENCE_NR;
+
+    for (fence_nr = 0; fence_nr < max_fence; fence_nr++) {
+	if (!pI830->fence_used[fence_nr])
+	    break;
+    }
+    if (fence_nr == max_fence)
+	FatalError("Ran out of fence registers at %d\n", fence_nr);
+
+    pI830->fence_used[fence_nr] = 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;
-	}
+	uint32_t fence_start, fence_end;
 
 	switch (tile_format) {
 	case TILE_XMAJOR:
-            pI830->fence[nr] = (((pitch / 128) - 1) << 2) | offset | 1;
-	    pI830->fence[nr] |= I965_FENCE_X_MAJOR;
+	    fence_start = (((pitch / 128) - 1) << 2) | offset | 1;
+	    fence_start |= I965_FENCE_X_MAJOR;
             break;
 	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 TILE_NONE:
+	    fence_start = (((pitch / 128) - 1) << 2) | offset | 1;
+	    fence_start |= I965_FENCE_Y_MAJOR;
             break;
+	default:
+	    return -1;
 	}
 
 	/* The end marker is the address of the last page in the allocation. */
-	pI830->fence[FENCE_NEW_NR + nr] = offset + size - 4096;
-	return;
-    }
-
-    if (nr < 0 || nr >= FENCE_NR) {
-	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		   "i830_set_fence(): fence %d out of range\n",nr);
-	return;
-    }
-
-    pI830->fence[nr] = 0;
-
-    if (IS_I9XX(pI830))
-   	fence_mask = ~I915G_FENCE_START_MASK;
-    else
-   	fence_mask = ~I830_FENCE_START_MASK;
+	fence_end = offset + size - 4096;
 
-    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;
-    }
+	OUTREG(FENCE_NEW + fence_nr * 8, fence_start);
+	OUTREG(FENCE_NEW + fence_nr * 8 + 4, fence_end);
+    } else {
+	if (IS_I9XX(pI830))
+	    fence_mask = ~I915G_FENCE_START_MASK;
+	else
+	    fence_mask = ~I830_FENCE_START_MASK;
 
-    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 (offset & fence_mask) {
+	    FatalError("i830_set_tiling(): %d: offset (0x%08x) is not %s "
+		       "aligned\n",
+		       fence_nr, offset, (IS_I9XX(pI830)) ? "1MB" : "512k");
+	}
 
-    if (pitch & 127) {
-	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		   "i830_set_fence(): %d: pitch (%d) not a multiple of 128 "
-		   "bytes\n",
-		   nr, pitch);
-	return;
-    }
+	if (offset % size) {
+	    FatalError("i830_set_tiling(): %d: offset (0x%08x) is not "
+		       "size (%dk) aligned\n",
+		       fence_nr, offset, size / 1024);
+	}
 
-    val = offset | FENCE_VALID;
+	if (pitch & 127) {
+	    FatalError("i830_set_tiling(): %d: pitch (%d) not a multiple of "
+		       "128 bytes\n",
+		       fence_nr, pitch);
+	}
 
-    switch (tile_format) {
-    case TILE_XMAJOR:
-	val |= FENCE_X_MAJOR;
-	break;
-    case TILE_YMAJOR:
-	val |= FENCE_Y_MAJOR;
-	break;
-    case TILE_NONE:
-	break;
-    }
+	val = offset | FENCE_VALID;
 
-    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;
+	switch (tile_format) {
+	case TILE_XMAJOR:
+	    val |= FENCE_X_MAJOR;
 	    break;
-	case MB(64):
-	    val |= I915G_FENCE_SIZE_64M;
+	case TILE_YMAJOR:
+	    val |= FENCE_Y_MAJOR;
 	    break;
-	default:
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		       "i830_set_fence(): %d: illegal size (%d kByte)\n",
-		       nr, size / 1024);
-	    return;
-   	}
-    } else {
-   	switch (size) {
-	case KB(512):
-	    val |= FENCE_SIZE_512K;
+	case TILE_NONE:
 	    break;
-	case MB(1):
-	    val |= FENCE_SIZE_1M;
+	}
+
+	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:
+		FatalError("i830_set_tiling(): %d: illegal size (%d kByte)\n",
+			   fence_nr, size / 1024);
+	    }
+	} 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:
+		FatalError("i830_set_tiling(): %d: illegal size (%d kByte)\n",
+			   fence_nr, size / 1024);
+	    }
+	}
+
+	if ((IS_I945G(pI830) || IS_I945GM(pI830) || IS_G33CLASS(pI830)) &&
+	    tile_format == TILE_YMAJOR)
+	    fence_pitch = pitch / 128;
+	else if (IS_I9XX(pI830))
+	    fence_pitch = pitch / 512;
+	else
+	    fence_pitch = pitch / 128;
+
+	switch (fence_pitch) {
+	case 1:
+	    val |= FENCE_PITCH_1;
 	    break;
-	case MB(2):
-	    val |= FENCE_SIZE_2M;
+	case 2:
+	    val |= FENCE_PITCH_2;
 	    break;
-	case MB(4):
-	    val |= FENCE_SIZE_4M;
+	case 4:
+	    val |= FENCE_PITCH_4;
 	    break;
-	case MB(8):
-	    val |= FENCE_SIZE_8M;
+	case 8:
+	    val |= FENCE_PITCH_8;
 	    break;
-	case MB(16):
-	    val |= FENCE_SIZE_16M;
+	case 16:
+	    val |= FENCE_PITCH_16;
 	    break;
-	case MB(32):
-	    val |= FENCE_SIZE_32M;
+	case 32:
+	    val |= FENCE_PITCH_32;
 	    break;
-	case MB(64):
-	    val |= FENCE_SIZE_64M;
+	case 64:
+	    val |= FENCE_PITCH_64;
 	    break;
 	default:
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		       "i830_set_fence(): %d: illegal size (%d kByte)\n",
-		       nr, size / 1024);
-	    return;
-   	}
-    }
+	    FatalError("i830_set_tiling(): %d: illegal pitch (%d)\n",
+		       fence_nr, pitch);
+	}
 
-    if ((IS_I945G(pI830) || IS_I945GM(pI830) || IS_G33CLASS(pI830))
-	    && tile_format == TILE_YMAJOR)
-	fence_pitch = pitch / 128;
-    else if (IS_I9XX(pI830))
-	fence_pitch = pitch / 512;
-    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_ERROR,
-		   "i830_set_fence(): %d: illegal pitch (%d)\n", nr, pitch);
-	return;
+	OUTREG(FENCE + fence_nr * 4, val);
     }
 
-    pI830->fence[nr] = val;
+    return fence_nr;
+}
+
+static void
+i830_clear_tiling(ScrnInfoPtr pScrn, unsigned int fence_nr)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    if (IS_I965G(pI830)) {
+	OUTREG(FENCE_NEW + fence_nr * 8, 0);
+	OUTREG(FENCE_NEW + fence_nr * 8 + 4, 0);
+    } else {
+	OUTREG(FENCE + fence_nr * 4, 0);
+    }
+    pI830->fence_used[fence_nr] = FALSE;
 }
 
 /**
commit a6dc81a0864f9ab2f6fc1aa31002c0191f674ceb
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Oct 5 12:37:19 2007 -0700

    Allow front/back/depth to move over the lifetime of the server.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index abe70d7..339fe25 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -777,12 +777,8 @@ I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
    }
 }
 
-#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)
+i830_update_front_offset(ScrnInfoPtr pScrn)
 {
    ScreenPtr pScreen = pScrn->pScreen;
    I830Ptr pI830 = I830PTR(pScrn);
@@ -820,11 +816,10 @@ i830CreateScreenResources(ScreenPtr pScreen)
    if (!(*pScreen->CreateScreenResources)(pScreen))
       return FALSE;
 
-   i830UpdateFrontOffset(pScrn);
+   i830_update_front_offset(pScrn);
 
    return TRUE;
 }
-#endif
 
 int
 i830_output_clones (ScrnInfoPtr pScrn, int type_mask)
@@ -2867,10 +2862,8 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
    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;
@@ -3035,9 +3028,8 @@ I830EnterVT(int scrnIndex, int flags)
 
    i830_describe_allocations(pScrn, 1, "");
 
-#if 0
-   i830UpdateFrontOffset(pScrn);
-#endif
+   /* Update the screen pixmap in case the buffer moved */
+   i830_update_front_offset(pScrn);
 
    if (i830_check_error_state(pScrn)) {
       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 2ff1a0c..4d55ca7 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -1087,11 +1087,7 @@ i830_allocate_framebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox,
     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;
+    flags = ALLOW_SHARING;
 
     /* Clear everything first. */
     memset(FbMemBox, 0, sizeof(*FbMemBox));
@@ -1488,7 +1484,6 @@ i830_allocate_backbuffer(ScrnInfoPtr pScrn, i830_memory **buffer,
 	*buffer = i830_allocate_memory_tiled(pScrn, name, size, pitch,
 					     GTT_PAGE_SIZE,
 					     ALIGN_BOTH_ENDS |
-					     NEED_LIFETIME_FIXED |
 					     ALLOW_SHARING,
 					     TILE_XMAJOR);
     }
@@ -1500,7 +1495,6 @@ i830_allocate_backbuffer(ScrnInfoPtr pScrn, i830_memory **buffer,
 	size = ROUND_TO_PAGE(pitch * height);
 	*buffer = i830_allocate_memory(pScrn, name, size, GTT_PAGE_SIZE,
 				       ALIGN_BOTH_ENDS |
-				       NEED_LIFETIME_FIXED |
 				       ALLOW_SHARING);
     }
 
@@ -1543,7 +1537,6 @@ i830_allocate_depthbuffer(ScrnInfoPtr pScrn)
 	    i830_allocate_memory_tiled(pScrn, "depth buffer", size, pitch,
 				       GTT_PAGE_SIZE,
 				       ALIGN_BOTH_ENDS |
-				       NEED_LIFETIME_FIXED |
 				       ALLOW_SHARING,
 				       tile_format);
     }
@@ -1555,7 +1548,7 @@ i830_allocate_depthbuffer(ScrnInfoPtr pScrn)
 	size = ROUND_TO_PAGE(pitch * height);
 	pI830->depth_buffer =
 	    i830_allocate_memory(pScrn, "depth buffer", size, GTT_PAGE_SIZE,
-				 ALLOW_SHARING | NEED_LIFETIME_FIXED);
+				 ALLOW_SHARING);
     }
 
     if (pI830->depth_buffer == NULL) {
commit 132dce7565feeea1055899f8c1627766fe84c88c
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Oct 5 12:12:06 2007 -0700

    Delay SAREA and mapping setup until EnterVT when using the memory manager.
    
    Otherwise, we would use uninitialized offsets in the early setup.

diff --git a/src/i830_dri.c b/src/i830_dri.c
index 0466410..4d3458f 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -833,12 +833,19 @@ I830DRIDoMappings(ScreenPtr pScreen)
    pScrn->pScreen->width = pScrn->virtualX;
    pScrn->pScreen->height = pScrn->virtualY;
 
-   if (!i830_update_dri_buffers(pScrn)) {
-      /* screen mappings probably failed */
-      xf86DrvMsg(pScreen->myNum, X_ERROR,
-		 "[drm] drmAddMap(screen mappings) failed. Disabling DRI\n");
-      DRICloseScreen(pScreen);
-      return FALSE;
+   /* If we are using the kernel memory manager, we have to delay SAREA and
+    * mapping setup until our buffers are pinned at EnterVT, losing the
+    * opportunity to fail cleanly early on.
+    */
+   if (pI830->memory_manager == NULL) {
+      if (!i830_update_dri_buffers(pScrn)) {
+	 /* screen mappings probably failed */
+	 xf86DrvMsg(pScreen->myNum, X_ERROR,
+		    "[drm] drmAddMap(screen mappings) failed. "
+		    "Disabling DRI\n");
+	 DRICloseScreen(pScreen);
+	 return FALSE;
+      }
    }
 
    if (pI830->allocate_classic_textures)
diff --git a/src/i830_driver.c b/src/i830_driver.c
index d24c408..abe70d7 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3070,6 +3070,11 @@ I830EnterVT(int scrnIndex, int flags)
 
 #ifdef XF86DRI
    if (pI830->directRenderingEnabled) {
+      /* Update buffer offsets in sarea and mappings, since buffer offsets
+       * may have changed.
+       */
+      if (!i830_update_dri_buffers(pScrn))
+	 FatalError("i830_update_dri_buffers() failed\n");
 
       I830DRISetVBlankInterrupt (pScrn, TRUE);
 
@@ -3088,12 +3093,6 @@ I830EnterVT(int scrnIndex, int flags)
 	 for(i = 0; i < I830_NR_TEX_REGIONS+1 ; i++)
 	    sarea->texList[i].age = sarea->texAge;
 
-	 /* Update buffer offsets in sarea and mappings, since buffer offsets
-	  * may have changed.
-	  */
-	 if (!i830_update_dri_buffers(pScrn))
-	    FatalError("i830_update_dri_buffers() failed\n");
-
 	 DPRINTF(PFX, "calling dri unlock\n");
 	 DRIUnlock(screenInfo.screens[pScrn->scrnIndex]);
       }
commit 4ca3550fb7d488741f8dc1ba3c8722393277c3b8
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Oct 4 17:02:15 2007 -0700

    Rework DRI buffer mappings and sarea setup to allow for moving buffers.
    
    While this has been a desired feature for some time, to allow for reallocation
    of the front buffer, it was made more necessary by the desire to avoid
    requiring a NO_MOVE buffer type in TTM because buffer objects may not be left
    pinned over VT switch.  This is a step towards making those buffers
    movable and resizable.

diff --git a/src/i830.h b/src/i830.h
index df95fb5..a34be61 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -635,12 +635,10 @@ extern Bool I830DRIDoMappings(ScreenPtr pScreen);
 extern Bool I830DRIResume(ScreenPtr pScreen);
 extern void I830DRICloseScreen(ScreenPtr pScreen);
 extern Bool I830DRIFinishScreenInit(ScreenPtr pScreen);
-extern Bool I830UpdateDRIBuffers(ScrnInfoPtr pScrn, drmI830Sarea *sarea);
-extern void I830DRIUnmapScreenRegions(ScrnInfoPtr pScrn, drmI830Sarea *sarea);
-extern Bool I830DRIMapScreenRegions(ScrnInfoPtr pScrn, drmI830Sarea *sarea);
 extern void I830DRIUnlock(ScrnInfoPtr pScrn);
 extern Bool I830DRILock(ScrnInfoPtr pScrn);
 extern Bool I830DRISetVBlankInterrupt (ScrnInfoPtr pScrn, Bool on);
+Bool i830_update_dri_buffers(ScrnInfoPtr pScrn);
 #endif
 
 unsigned long intel_get_pixmap_offset(PixmapPtr pPix);
diff --git a/src/i830_common.h b/src/i830_common.h
index a4c3b5a..f3a7ea0 100644
--- a/src/i830_common.h
+++ b/src/i830_common.h
@@ -74,7 +74,7 @@ typedef struct {
    unsigned int depth_offset;
    unsigned int w;
    unsigned int h;
-   unsigned int pitch;
+   unsigned int pitch; /* Pitch of front buffer in units of pixels */
    unsigned int pitch_bits;
    unsigned int back_pitch;
    unsigned int depth_pitch;
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 4cddf3b..0466410 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -640,7 +640,7 @@ I830DRIScreenInit(ScreenPtr pScreen)
    /* Now, nuke dri.c's dummy frontbuffer map setup if we did that. */
    if (pDRIInfo->frameBufferSize != 0) {
        int tmp;
-       unsigned int fb_handle;
+       drm_handle_t fb_handle;
        void *ptmp;
 
        /* With the compat method, it will continue to report
@@ -743,149 +743,38 @@ I830DRIScreenInit(ScreenPtr pScreen)
    return TRUE;
 }
 
-Bool
-I830DRIMapScreenRegions(ScrnInfoPtr pScrn, drmI830Sarea *sarea)
-{
-   ScreenPtr pScreen = pScrn->pScreen;
-   I830Ptr pI830 = I830PTR(pScrn);
-   drm_handle_t front_handle;
-
-   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");
-   if (drmAddMap(pI830->drmSubFD,
-		 (drm_handle_t)(sarea->front_offset + pI830->LinearAddr),
-		 sarea->front_size,
-		 DRM_AGP,
-		 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);
-
-   if (drmAddMap(pI830->drmSubFD,
-                 (drm_handle_t)(sarea->back_offset + pI830->LinearAddr),
-                 sarea->back_size, DRM_AGP, 0,
-                 (drmAddress) &sarea->back_handle) < 0) {
-      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-                 "[drm] drmAddMap(back_handle) failed. Disabling DRI\n");
-      DRICloseScreen(pScreen);
-      return FALSE;
-   }
-   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Back Buffer = 0x%08x\n",
-              (int)sarea->back_handle);
-
-   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. Triple buffering "
-		    "inactive\n");
-	 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);
-   }
-
-   if (drmAddMap(pI830->drmSubFD,
-                 (drm_handle_t)sarea->depth_offset + pI830->LinearAddr,
-                 sarea->depth_size, DRM_AGP, 0,
-                 (drmAddress) &sarea->depth_handle) < 0) {
-      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-                 "[drm] drmAddMap(depth_handle) failed. Disabling DRI\n");
-      DRICloseScreen(pScreen);
-      return FALSE;
-   }
-   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Depth Buffer = 0x%08x\n",
-              (int)sarea->depth_handle);
-
-   if (pI830->allocate_classic_textures) {
-      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;
-}
-
-
-void
-I830DRIUnmapScreenRegions(ScrnInfoPtr pScrn, drmI830Sarea *sarea)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-
-   if (sarea->front_handle) {
-      drmRmMap(pI830->drmSubFD, sarea->front_handle);
-      sarea->front_handle = 0;
-   }
-   if (sarea->back_handle) {
-      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;
-   }
-   if (sarea->tex_handle) {
-      drmRmMap(pI830->drmSubFD, sarea->tex_handle);
-      sarea->tex_handle = 0;
-   }
-}
-
 static void
-I830InitTextureHeap(ScrnInfoPtr pScrn, drmI830Sarea *sarea)
+I830InitTextureHeap(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
 
+   if (pI830->textures == NULL)
+       return;
+
    /* Start up the simple memory manager for agp space */
    drmI830MemInitHeap drmHeap;
    drmHeap.region = I830_MEM_REGION_AGP;
    drmHeap.start  = 0;
-   drmHeap.size   = sarea->tex_size;
-      
+   drmHeap.size   = pI830->textures->size;
+
    if (drmCommandWrite(pI830->drmSubFD, DRM_I830_INIT_HEAP,
 			  &drmHeap, sizeof(drmHeap))) {
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		    "[drm] Failed to initialized agp heap manager\n");
    } else {
       xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		    "[drm] Initialized kernel agp heap manager, %d\n",
-		    sarea->tex_size);
+		    "[drm] Initialized kernel agp heap manager, %ld\n",
+		    pI830->textures->size);
 
       I830SetParam(pScrn, I830_SETPARAM_TEX_LRU_LOG_GRANULARITY, 
-		      sarea->log_tex_granularity);
+		   pI830->TexGranularity);
    }
 }
 
+/**
+ * Sets up mappings for static, lifetime-fixed allocations, and inital SAREA
+ * setup.
+ */
 Bool
 I830DRIDoMappings(ScreenPtr pScreen)
 {
@@ -944,14 +833,17 @@ I830DRIDoMappings(ScreenPtr pScreen)
    pScrn->pScreen->width = pScrn->virtualX;
    pScrn->pScreen->height = pScrn->virtualY;
 
-   /* this will map the screen regions */
-   if (!I830UpdateDRIBuffers(pScrn, sarea)) {
+   if (!i830_update_dri_buffers(pScrn)) {
       /* screen mappings probably failed */
       xf86DrvMsg(pScreen->myNum, X_ERROR,
 		 "[drm] drmAddMap(screen mappings) failed. Disabling DRI\n");
+      DRICloseScreen(pScreen);
       return FALSE;
    }
 
+   if (pI830->allocate_classic_textures)
+      I830InitTextureHeap(pScrn);
+
    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 );
@@ -1639,17 +1531,24 @@ I830DRIClipNotify(ScreenPtr pScreen, WindowPtr *ppWin, int num)
 #endif /* DRI_SUPPORTS_CLIP_NOTIFY */
 
 /**
- * Update the SAREA fields with the most recent values.
- * This gets called after the screen orientation/rotation changes.
+ * Update the SAREA fields with current buffer information.
+ *
+ * Most of the SAREA fields are already updated by i830_do_addmap().
+ *
+ * This does include other SAREA initialization which will actually be constant
+ * over the lifetime of the server.
  */
-Bool
-I830UpdateDRIBuffers(ScrnInfoPtr pScrn, drmI830Sarea *sarea)
+static void
+i830_update_sarea(ScrnInfoPtr pScrn, drmI830Sarea *sarea)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
    ScreenPtr pScreen = pScrn->pScreen;
-   Bool success;
+   I830Ptr pI830 = I830PTR(pScrn);
 
-   I830DRIUnmapScreenRegions(pScrn, sarea);
+   sarea->width = pScreen->width;
+   sarea->height = pScreen->height;
+   sarea->pitch = pScrn->displayWidth;
+   sarea->virtualX = pScrn->virtualX;
+   sarea->virtualY = pScrn->virtualY;
 
    sarea->front_tiled = (pI830->front_buffer->tiling != TILE_NONE);
    sarea->back_tiled = (pI830->back_buffer->tiling != TILE_NONE);
@@ -1660,42 +1559,7 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, drmI830Sarea *sarea)
    sarea->depth_tiled = (pI830->depth_buffer->tiling != TILE_NONE);
    sarea->rotated_tiled = FALSE;
 
-   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 = 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",
-              pScreen->width, pScreen->height,pScrn->displayWidth);
-
-   sarea->width = pScreen->width;
-   sarea->height = pScreen->height;
-   sarea->back_offset = pI830->back_buffer->offset;
-   sarea->back_size = pI830->back_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) {
-      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;
-   sarea->virtualY = pScrn->virtualY;
 
    sarea->front_bo_handle = -1;
    sarea->back_bo_handle = -1;
@@ -1719,13 +1583,149 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, drmI830Sarea *sarea)
    sarea->rotated_offset = -1;
    sarea->rotated_size = 0;
    sarea->rotated_pitch = pScrn->displayWidth;
+}
+
+/**
+ * Updates the DRI mapping for the given i830_memory struct, with the given
+ * flags.
+ */
+static int
+i830_do_addmap(ScrnInfoPtr pScrn, i830_memory *mem,
+	       drm_handle_t *sarea_handle, int *sarea_size, int *sarea_offset)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    int size = mem->size;
+
+    if (mem == pI830->front_buffer) {
+	/* Workaround for XAA pixmap cache: Don't use front_buffer->size
+	 * and instead, calculate the visible frontbuffer size and round to
+	 * avoid irritating the assertions of older DRI drivers.
+	 */
+	size = ROUND_TO_PAGE(pScrn->displayWidth * pScrn->virtualY *
+			     pI830->cpp);
+    }
+
+    if (*sarea_handle != 0 &&
+	(*sarea_size != size || *sarea_offset != mem->offset))
+    {
+	drmRmMap(pI830->drmSubFD, *sarea_handle);
+	*sarea_handle = 0;
+	*sarea_size = 0;
+	*sarea_offset = 0;
+    }
+
+    if (*sarea_handle == 0) {
+	int ret;
+
+	ret = drmAddMap(pI830->drmSubFD,
+			(drm_handle_t)(mem->offset + pI830->LinearAddr),
+			size, DRM_AGP, 0,
+			(drmAddress) sarea_handle);
+	if (ret == 0) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		       "[drm] mapped %s at 0x%08lx, handle = 0x%08x\n",
+		       mem->name, mem->offset + pI830->LinearAddr,
+		       (int)*sarea_handle);
+	    *sarea_size = size;
+	    *sarea_offset = mem->offset;
+	} else {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "[drm] failed to map %s at 0x%08lx\n",
+		       mem->name, mem->offset + pI830->LinearAddr);
+	    return FALSE;
+	}
+    }
+
+    return TRUE;
+}
+
+/**
+ * Updates the DRM mappings with the current buffer information.
+ *
+ * Some old DRI drivers may be unprepared for buffers actually moving at
+ * runtime, which would likely result in bus errors on software fallbacks or
+ * hangs or misrendering on hardware rendering.
+ */
+static Bool
+i830_update_dri_mappings(ScrnInfoPtr pScrn, drmI830Sarea *sarea)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+
+   if (!i830_do_addmap(pScrn, pI830->front_buffer, &sarea->front_handle,
+		       &sarea->front_size, &sarea->front_offset)) {
+       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling DRI.\n");
+       return FALSE;
+   }
+
+   if (!i830_do_addmap(pScrn, pI830->back_buffer, &sarea->back_handle,
+		       &sarea->back_size, &sarea->back_offset)) {
+       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling DRI.\n");
+       return FALSE;
+   }
+
+   if (pI830->third_buffer) {
+       if (!i830_do_addmap(pScrn, pI830->third_buffer, &sarea->third_handle,
+			   &sarea->third_size, &sarea->third_offset)) {
+	   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling DRI.\n");
+	   return FALSE;
+       }
+   } else {
+       sarea->third_handle = 0;
+       sarea->third_offset = 0;
+       sarea->third_size = 0;
+   }
+
+   if (!i830_do_addmap(pScrn, pI830->depth_buffer, &sarea->depth_handle,
+		       &sarea->depth_size, &sarea->depth_offset)) {
+       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling DRI.\n");
+       return FALSE;
+   }
+
+   if (pI830->allocate_classic_textures) {
+       if (!i830_do_addmap(pScrn, pI830->textures, &sarea->tex_handle,
+			   &sarea->tex_size, &sarea->tex_offset)) {
+	   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling DRI.\n");
+	   return FALSE;
+       }
+   }
+
+   return TRUE;
+}
+
+static void
+i830_update_screen_private(ScrnInfoPtr pScrn, drmI830Sarea *sarea)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
 
-   success = I830DRIMapScreenRegions(pScrn, sarea);
+   pI830->pDRIInfo->frameBufferPhysicalAddress = (char *) pI830->LinearAddr;
+   pI830->pDRIInfo->frameBufferStride = pScrn->displayWidth * pI830->cpp;
+   pI830->pDRIInfo->frameBufferSize = sarea->front_size;
+#if DRI_DRIVER_FRAMEBUFFER_MAP
+   pI830->pDRIInfo->hFrameBuffer = sarea->front_handle;
+#endif
+}
 
-   if (success && pI830->allocate_classic_textures)
-      I830InitTextureHeap(pScrn, sarea);
+/**
+ * Update the SAREA fields, DRI mappings, and screen info passed through the
+ * protocol.
+ *
+ * This gets called both at startup and after any of the buffers might have
+ * been relocated.
+ */
+Bool
+i830_update_dri_buffers(ScrnInfoPtr pScrn)
+{
+   ScreenPtr pScreen = pScrn->pScreen;
+   drmI830Sarea *sarea = (drmI830Sarea *) DRIGetSAREAPrivate(pScreen);
+   Bool success;
+
+   success = i830_update_dri_mappings(pScrn, sarea);
+   if (!success)
+       return FALSE;
+   i830_update_sarea(pScrn, sarea);
+   i830_update_screen_private(pScrn, sarea);
 
-   return success;
+   return TRUE;
 }
 
 Bool
diff --git a/src/i830_driver.c b/src/i830_driver.c
index b3edb61..d24c408 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3018,6 +3018,17 @@ I830EnterVT(int scrnIndex, int flags)
 
    pI830->leaving = FALSE;
 
+#ifdef XF86DRI_MM
+   if (pI830->directRenderingEnabled) {
+      /* Unlock the memory manager first of all so that we can pin our
+       * buffer objects
+       */
+      if (pI830->memory_manager != NULL) {
+	 drmMMUnlock(pI830->drmSubFD, DRM_BO_MEM_TT);
+      }
+   }
+#endif /* XF86DRI_MM */
+
    if (I830IsPrimary(pScrn))
       if (!i830_bind_all_memory(pScrn))
          return FALSE;
@@ -3077,11 +3088,11 @@ 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->memory_manager != NULL) {
-	    drmMMUnlock(pI830->drmSubFD, DRM_BO_MEM_TT);
-	 }
-#endif /* XF86DRI_MM */
+	 /* Update buffer offsets in sarea and mappings, since buffer offsets
+	  * may have changed.
+	  */
+	 if (!i830_update_dri_buffers(pScrn))
+	    FatalError("i830_update_dri_buffers() failed\n");
 
 	 DPRINTF(PFX, "calling dri unlock\n");
 	 DRIUnlock(screenInfo.screens[pScrn->scrnIndex]);
commit f393a12d21eed668cf4771f022beded9a4c547c7
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Oct 4 13:03:14 2007 -0700

    Move drmMMLock to after we have unbound our (pinned) buffers.
    
    There are still issues due to the fact that we're allocating
    NEED_LIFETIME_FIXED memory as buffer objects, which we refuse to unpin because
    we have no way of pinning it back in the same location.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index ce84bce..b3edb61 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2959,13 +2959,8 @@ I830LeaveVT(int scrnIndex, int flags)
 #ifdef XF86DRI
    if (pI830->directRenderingOpen) {
       DRILock(screenInfo.screens[pScrn->scrnIndex], 0);
-#ifdef XF86DRI_MM
-      if (pI830->memory_manager != NULL) {
-	 drmMMLock(pI830->drmSubFD, DRM_BO_MEM_TT);
-      }
-#endif /* XF86DRI_MM */
+
       I830DRISetVBlankInterrupt (pScrn, FALSE);
-      
       drmCtlUninstHandler(pI830->drmSubFD);
    }
 #endif
@@ -2983,6 +2978,18 @@ I830LeaveVT(int scrnIndex, int flags)
 
    if (I830IsPrimary(pScrn))
       i830_unbind_all_memory(pScrn);
+
+   /* Tell the kernel to evict all buffer objects and block new buffer
+    * allocations until we relese the lock.
+    */
+#ifdef XF86DRI_MM
+   if (pI830->directRenderingOpen) {
+      if (pI830->memory_manager != NULL) {
+	 drmMMLock(pI830->drmSubFD, DRM_BO_MEM_TT);
+      }
+   }
+#endif /* XF86DRI_MM */
+
    if (pI830->AccelInfoRec)
       pI830->AccelInfoRec->NeedToSync = FALSE;
 }
commit 8fc4e3078210f726c7c375faa2f2fd8d05017c09
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Oct 5 11:51:55 2007 -0700

    Refuse to allocate LIFETIME_FIXED objects in buffer objects.
    
    We can't guarantee the offset will stay the same using the current DRM
    interface, but the correct solution is fixing our code to allow these objects
    to move.  Breaks TTM mode of the DRI driver for now.

diff --git a/src/i830_memory.c b/src/i830_memory.c
index 85a78f5..2ff1a0c 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -758,7 +758,9 @@ i830_allocate_memory(ScrnInfoPtr pScrn, const char *name,
     I830Ptr pI830 = I830PTR(pScrn);
     i830_memory *mem;
 
-    if (pI830->memory_manager && !(flags & NEED_PHYSICAL_ADDR)) {
+    if (pI830->memory_manager && !(flags & NEED_PHYSICAL_ADDR) &&
+	!(flags & NEED_LIFETIME_FIXED))
+    {
 	return i830_allocate_memory_bo(pScrn, name, size, alignment, flags);
     } else {
 	mem = i830_allocate_aperture(pScrn, name, size, alignment, flags);
commit 0de747f7d219a56434dad49a8a6d1d9d4c251ca7
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Oct 11 10:36:01 2007 -0700

    In i830_allocate_memory_bo, bind if we control the VT, not on lifetime-fixed.

diff --git a/src/i830_memory.c b/src/i830_memory.c
index cdb7c47..85a78f5 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -709,14 +709,17 @@ i830_allocate_memory_bo(ScrnInfoPtr pScrn, const char *name,
     mem->offset = -1;
     mem->end = -1;
     mem->size = size;
-    if (flags & NEED_LIFETIME_FIXED) {
+    if (flags & NEED_LIFETIME_FIXED)
+	mem->lifetime_fixed_offset = TRUE;
+
+    /* Bind it if we currently control the VT */
+    if (pScrn->vtSema) {
 	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 */
commit 0040bb95445e800af80ca9fa1b92f5db33f1b4ac
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Oct 10 16:48:12 2007 -0700

    Fix potential use-after-free in XV overlay code on video stop.

diff --git a/src/i830_video.c b/src/i830_video.c
index beec03e..8c2d804 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -1016,6 +1016,7 @@ I830StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
 	 */
 	I830Sync(pScrn);
 	i830_free_memory(pScrn, pPriv->buf);
+	pPriv->buf = NULL;
 	pPriv->videoStatus = 0;
     } else {
 	if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
commit 56ae767180da4a8bd4b7a4c35b92e019ab67d753
Author: Zhenyu Wang <zhenyu.z.wang at intel.com>
Date:   Thu Oct 11 10:09:29 2007 +0800

    Revert "Fix G33 GTT stolen mem range"
    
    This reverts commit 2a8592f2ebcba86b1127aa889155d58a3dc186ca.
    
    This causes compat issue between ddx and kernel apggart version.
    Revert it as it shouldn't hurt normal people's default GTT size,
    but if you change it to 1MB in bios, it's supposed to be broken now.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 0d55609..ce84bce 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -481,9 +481,6 @@ 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);
commit 5faee02e97b7543b41bb1f8e3751558c48802833
Author: Zhenyu Wang <zhenyu.z.wang at intel.com>
Date:   Wed Oct 10 13:55:30 2007 +0800

    EXA: fix tiled dest rendering on i8XX chips

diff --git a/src/i830_render.c b/src/i830_render.c
index 90b884f..22e09c8 100644
--- a/src/i830_render.c
+++ b/src/i830_render.c
@@ -425,7 +425,8 @@ i830_prepare_composite(int op, PicturePtr pSrcPicture,
 
 	/* color buffer */
 	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(MI_NOOP);
 
commit 5bbe9f09fda1238da04e6b584813d40fc646f49d
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Wed Oct 3 00:18:25 2007 -0700

    Include xf86mm.h if using XF86DRI_MM
    
    This header file doesn't appear to be getting automatically included for
    some reason.

diff --git a/src/i830.h b/src/i830.h
index a04f937..df95fb5 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -68,6 +68,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #ifdef XF86DRI
 #include "xf86drm.h"
+#ifdef XF86DRI_MM
+#include "xf86mm.h"
+#endif
 #include "sarea.h"
 #define _XF86DRI_SERVER_
 #include "dri.h"
commit 41dacf97ec1d4ba6f54057f4fcc7bb76033a454e
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Wed Oct 3 00:17:41 2007 -0700

    Quirk for Samsung Q35 which has no TV output.

diff --git a/src/i830_quirks.c b/src/i830_quirks.c
index 8e4ec97..9ae250c 100644
--- a/src/i830_quirks.c
+++ b/src/i830_quirks.c
@@ -79,6 +79,8 @@ static i830_quirk i830_quirk_list[] = {
     /* Panasonic Toughbook CF-Y7 has no TV output */
     { PCI_CHIP_I965_GM, 0x10f7, 0x8338, quirk_ignore_tv },
     
+    /* Samsung Q35 has no TV output */
+    { PCI_CHIP_I945_GM, 0x144d, 0xc504, quirk_ignore_tv },
     { 0, 0, 0, NULL },
 };
 
commit 9e770bf69edaa8944048049e11266dbe1ef145e5
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Oct 4 14:31:37 2007 -0700

    Replace setting of LIFETIME_FIXED on cursors with just updating the offsets.

diff --git a/src/i830.h b/src/i830.h
index 0a4b4a7..a04f937 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -583,6 +583,7 @@ extern void IntelEmitInvarientState(ScrnInfoPtr pScrn);
 extern void I830EmitInvarientState(ScrnInfoPtr pScrn);
 extern void I915EmitInvarientState(ScrnInfoPtr pScrn);
 extern void I830SelectBuffer(ScrnInfoPtr pScrn, int buffer);
+void i830_update_cursor_offsets(ScrnInfoPtr pScrn);
 
 /* CRTC-based cursor functions */
 void
diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index 667b0a6..52eb266 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -1,4 +1,4 @@
-/* -*- c-basic-offset: 3 -*- */
+/* -*- c-basic-offset: 4 -*- */
 /**************************************************************************
 
 Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
@@ -275,3 +275,59 @@ i830_crtc_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg)
     OUTREG(pal0 +  8, fg & 0x00ffffff);
     OUTREG(pal0 + 12, bg & 0x00ffffff);
 }
+
+void
+i830_update_cursor_offsets (ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int i;
+
+    if (pI830->cursor_mem) {
+	unsigned long cursor_offset_base = pI830->cursor_mem->offset;
+	unsigned long cursor_addr_base, offset = 0;
+
+	/* Single memory buffer for cursors */
+	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;
+
+	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;
+	}
+    } else {
+	/* Separate allocations per cursor */
+	for (i = 0; i < xf86_config->num_crtc; i++) {
+	    xf86CrtcPtr crtc = xf86_config->crtc[i];
+	    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+
+	    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;
+	}
+    }
+}
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 23d5e0c..cdb7c47 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -1197,7 +1197,7 @@ i830_allocate_cursor_buffers(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-    int flags = pI830->CursorNeedsPhysical ? NEED_PHYSICAL_ADDR : NEED_LIFETIME_FIXED;
+    int flags = pI830->CursorNeedsPhysical ? NEED_PHYSICAL_ADDR : 0;
     int i;
     long size;
 
@@ -1211,35 +1211,8 @@ i830_allocate_cursor_buffers(ScrnInfoPtr pScrn)
     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 (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. */
-	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;
-	}
-
+    if (pI830->cursor_mem != NULL)
 	return TRUE;
-    }
 
     /*
      * Allocate four separate buffers when the kernel doesn't support
@@ -1265,21 +1238,6 @@ i830_allocate_cursor_buffers(ScrnInfoPtr pScrn)
 	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;
 }
@@ -1935,6 +1893,7 @@ i830_bind_all_memory(ScrnInfoPtr pScrn)
 	}
 #endif
     }
+    i830_update_cursor_offsets(pScrn);
 
     return TRUE;
 }
commit c9d6e90c2523096c45d330552f471e6bf1752704
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Oct 4 14:27:07 2007 -0700

    Don't set overlay registers LIFETIME_FIXED. It always uses the current offset.

diff --git a/src/i830_memory.c b/src/i830_memory.c
index 7671b5b..23d5e0c 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -993,20 +993,16 @@ static Bool
 i830_allocate_overlay(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    int flags = NEED_PHYSICAL_ADDR | NEED_LIFETIME_FIXED;
+    int flags = 0;
 
     /* Only allocate if overlay is going to be enabled. */
     if (!pI830->XvEnabled)
 	return TRUE;
 
-    if (OVERLAY_NOPHYSICAL(pI830))
-	flags &= ~NEED_PHYSICAL_ADDR;
+    if (!OVERLAY_NOPHYSICAL(pI830))
+	flags |= NEED_PHYSICAL_ADDR;
 
     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);
commit 1cc6bec4628a4ca04a68919a84148a1e6312072f
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Oct 4 14:23:48 2007 -0700

    Revert setting of exa_965_state as LIFETIME_FIXED.
    
    The current offset is used every time in render setup.

diff --git a/src/i830_memory.c b/src/i830_memory.c
index d2aa327..7671b5b 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -1389,7 +1389,7 @@ i830_allocate_2d_memory(ScrnInfoPtr pScrn)
     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, NEED_LIFETIME_FIXED);
+		    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");
commit dfa22df8ce7713b491c4766ce6ce652db91b5f90
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Oct 5 12:53:07 2007 -0700

    Don't leak buffer object allocations in i830_reset_allocations().

diff --git a/src/i830_memory.c b/src/i830_memory.c
index c850033..d2aa327 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -272,6 +272,14 @@ i830_reset_allocations(ScrnInfoPtr pScrn)
     while (pI830->memory_list->next->next != NULL)
 	i830_free_memory(pScrn, pI830->memory_list->next);
 
+    /* Free any allocations in buffer objects */
+#ifdef XF86DRI_MM
+    if (pI830->memory_manager) {
+	while (pI830->bo_list != NULL)
+	    i830_free_memory(pScrn, pI830->bo_list);
+    }
+#endif
+
     /* 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.
      */
commit 7db9d706a1bc9da7afc4823cee92b23e96ae55b8
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Oct 5 12:40:48 2007 -0700

    Warning cleanup.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index dc27170..0d55609 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2270,7 +2270,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
    Bool allocation_done = FALSE;
    MessageType from;
 #ifdef XF86DRI
-   Bool driDisabled;
    xf86CrtcConfigPtr config;
 #endif
 
commit bf33c4e2d91172efd08690fadda7b3743dd3de62
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Oct 5 12:40:37 2007 -0700

    Fix formatting of error message.

diff --git a/src/i830_memory.c b/src/i830_memory.c
index 7ae2332..c850033 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -1434,7 +1434,7 @@ i830_allocate_2d_memory(ScrnInfoPtr pScrn)
 				     size, 1, NEED_LIFETIME_FIXED);
 	    if (pI830->exa_offscreen == NULL) {
 		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-			   "Failed to allocate EXA offscreen memory.");
+			   "Failed to allocate EXA offscreen memory.\n");
 		return FALSE;
 	    }
 	}
commit 04e936935f0b0045600241424f1d04a6721a2432
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Oct 1 17:29:35 2007 -0700

    Bring the CH7017 driver closer to spec.
    
    This is also closer to what my hardware is programmed with, except for some
    very confusing off-by-one bugs in an unexpected direction.

diff --git a/src/ch7017/ch7017.c b/src/ch7017/ch7017.c
index ceb8a2a..f8e2b31 100644
--- a/src/ch7017/ch7017.c
+++ b/src/ch7017/ch7017.c
@@ -50,6 +50,7 @@ struct ch7017_priv {
     CARD8 save_hapi;
     CARD8 save_vali;
     CARD8 save_valo;
+    CARD8 save_ailo;
     CARD8 save_lvds_pll_vco;
     CARD8 save_feedback_div;
     CARD8 save_lvds_control_2;
@@ -157,31 +158,34 @@ ch7017_mode_set(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode)
     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 */
+    if (mode->Clock < 100000) {
+	outputs_enable = CH7017_LVDS_CHANNEL_A | CH7017_CHARGE_PUMP_LOW;
+	lvds_pll_feedback_div = CH7017_LVDS_PLL_FEEDBACK_DEFAULT_RESERVED |
+	    (2 << CH7017_LVDS_PLL_FEED_BACK_DIVIDER_SHIFT) |
+	    (13 << CH7017_LVDS_PLL_FEED_FORWARD_DIVIDER_SHIFT);
+	lvds_pll_vco_control = CH7017_LVDS_PLL_VCO_DEFAULT_RESERVED |
+	    (2 << CH7017_LVDS_PLL_VCO_SHIFT) |
+	    (3 << CH7017_LVDS_PLL_POST_SCALE_DIV_SHIFT);
 	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) {
+    } else {
+	outputs_enable = CH7017_LVDS_CHANNEL_A | CH7017_CHARGE_PUMP_HIGH;
+	lvds_pll_feedback_div = CH7017_LVDS_PLL_FEEDBACK_DEFAULT_RESERVED |
+	    (2 << CH7017_LVDS_PLL_FEED_BACK_DIVIDER_SHIFT) |
+	    (3 << CH7017_LVDS_PLL_FEED_FORWARD_DIVIDER_SHIFT);
 	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);
+	if (1) { /* XXX: dual channel panel detection.  Assume yes for now. */
+	    outputs_enable |= CH7017_LVDS_CHANNEL_B;
+	    lvds_pll_vco_control = CH7017_LVDS_PLL_VCO_DEFAULT_RESERVED |
+		(2 << CH7017_LVDS_PLL_VCO_SHIFT) |
+		(13 << CH7017_LVDS_PLL_POST_SCALE_DIV_SHIFT);
 	} else {
-	    lvds_pll_vco_control = (1 << 4) | (13 << 0);
+	    lvds_pll_vco_control = CH7017_LVDS_PLL_VCO_DEFAULT_RESERVED |
+		(1 << CH7017_LVDS_PLL_VCO_SHIFT) |
+		(13 << CH7017_LVDS_PLL_POST_SCALE_DIV_SHIFT);
 	}
-    } else {
-	FatalError("Invalid mode clock (%.1fMHz)\n",
-		   (float)mode->Clock / 1000.0);
     }
 
     horizontal_active_pixel_input = mode->HDisplay & 0x00ff;
@@ -189,10 +193,11 @@ ch7017_mode_set(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode)
     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);
+    active_input_line_output = ((mode->HDisplay & 0x0700) >> 8) |
+	(((mode->VDisplay & 0x0700) >> 8) << 3);
 
-    lvds_power_down = (mode->HDisplay & 0x0f00) >> 8;
+    lvds_power_down = CH7017_LVDS_POWER_DOWN_DEFAULT_RESERVED |
+	(mode->HDisplay & 0x0700) >> 8;
 
     ch7017_dpms(d, DPMSModeOff);
     ch7017_write(priv, CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT,
@@ -201,6 +206,8 @@ ch7017_mode_set(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode)
 		    horizontal_active_pixel_output);
     ch7017_write(priv, CH7017_VERTICAL_ACTIVE_LINE_OUTPUT,
 		    vertical_active_line_output);
+    ch7017_write(priv, CH7017_ACTIVE_INPUT_LINE_OUTPUT,
+		 active_input_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);
@@ -261,6 +268,7 @@ do {							\
     DUMP(CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT);
     DUMP(CH7017_HORIZONTAL_ACTIVE_PIXEL_OUTPUT);
     DUMP(CH7017_VERTICAL_ACTIVE_LINE_OUTPUT);
+    DUMP(CH7017_ACTIVE_INPUT_LINE_OUTPUT);
     DUMP(CH7017_LVDS_PLL_VCO_CONTROL);
     DUMP(CH7017_LVDS_PLL_FEEDBACK_DIV);
     DUMP(CH7017_LVDS_CONTROL_2);
@@ -275,6 +283,7 @@ ch7017_save(I2CDevPtr d)
 
     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_ACTIVE_INPUT_LINE_OUTPUT, &priv->save_ailo);
     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);
@@ -293,6 +302,7 @@ ch7017_restore(I2CDevPtr d)
 
     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_ACTIVE_INPUT_LINE_OUTPUT, priv->save_ailo);
     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);
diff --git a/src/ch7017/ch7017_reg.h b/src/ch7017/ch7017_reg.h
index 89f81cc..3344c4e 100644
--- a/src/ch7017/ch7017_reg.h
+++ b/src/ch7017/ch7017_reg.h
@@ -99,11 +99,12 @@
 
 #define CH7017_LVDS_POWER_DOWN		0x63
 /** High bits of horizontal active pixel output */
-#define CH7017_LVDS_HAP_HIGH_MASK	(0xf << 0)
+#define CH7017_LVDS_HAP_HIGH_MASK	(0x7 << 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_POWER_DOWN_DEFAULT_RESERVED 0x08
 
 #define CH7017_LVDS_ENCODING		0x64
 #define CH7017_LVDS_DITHER_2D		(1 << 2)
@@ -127,10 +128,20 @@
 #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_FEED_BACK_DIVIDER_SHIFT 4
+# define CH7017_LVDS_PLL_FEED_FORWARD_DIVIDER_SHIFT 0
+# define CH7017_LVDS_PLL_FEEDBACK_DEFAULT_RESERVED 0x80
+
 #define CH7017_LVDS_PLL_VCO_CONTROL	0x72
+# define CH7017_LVDS_PLL_VCO_DEFAULT_RESERVED 0x80
+# define CH7017_LVDS_PLL_VCO_SHIFT	4
+# define CH7017_LVDS_PLL_POST_SCALE_DIV_SHIFT 0
 
 #define CH7017_OUTPUTS_ENABLE		0x73
+# define CH7017_CHARGE_PUMP_LOW		0x0
+# define CH7017_CHARGE_PUMP_HIGH	0x3
 # define CH7017_LVDS_CHANNEL_A		(1 << 3)
 # define CH7017_LVDS_CHANNEL_B		(1 << 4)
 # define CH7017_TV_DAC_A		(1 << 5)
commit 263d48ad93a0fb7100729d0c6e0443797c20c80a
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Oct 1 16:23:30 2007 -0700

    Fix probing of the sample CH7017 device I found by allowing GPIO overrides.
    
    It may be that the LVDS chips need to be DVOA and GPIOB only on mobility
    devices with them, and DVOC/GPIOE on non-mobility like this 845.  But until
    more examples are found, just make this one device probe.

diff --git a/src/i830.h b/src/i830.h
index b1f1f68..0a4b4a7 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -221,6 +221,7 @@ struct _I830DVODriver {
    char *modulename;
    char *fntablename;
    unsigned int dvo_reg;
+   uint32_t gpio;
    int address;
    const char **symbols;
    I830I2CVidOutputRec *vid_rec;
diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index 8ba38bd..e6ff6af 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -99,9 +99,10 @@ struct _I830DVODriver i830_dvo_drivers[] =
 	.type = I830_OUTPUT_DVO_LVDS,
 	.modulename = "ch7017",
 	.fntablename = "ch7017_methods",
-	.dvo_reg = DVOA,
+	.dvo_reg = DVOC,
 	.address = 0xea,
 	.symbols = ch7017_symbols,
+	.gpio = GPIOE,
     }
 };
 
@@ -430,7 +431,12 @@ i830_dvo_init(ScrnInfoPtr pScrn)
 	ret_ptr = NULL;
 	drv->vid_rec = LoaderSymbol(drv->fntablename);
 
-	if (drv->type == I830_OUTPUT_DVO_LVDS)
+	/* Allow the I2C driver info to specify the GPIO to be used in
+	 * special cases, but otherwise default to what's defined in the spec.
+	 */
+	if (drv->gpio != 0)
+	    gpio = drv->gpio;
+	else if (drv->type == I830_OUTPUT_DVO_LVDS)
 	    gpio = GPIOB;
 	else
 	    gpio = GPIOE;
commit 219354af212c7b68c20df689692c55331e36a705
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Oct 1 16:09:13 2007 -0700

    Restore building of pciaccess-based tools even if the server doesn't use it.

diff --git a/configure.ac b/configure.ac
index 1c7ad04..e5a7cf6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -116,9 +116,15 @@ CFLAGS="$save_CFLAGS"
 
 if test x$XSERVER_LIBPCIACCESS = xyes; then
 	PKG_CHECK_MODULES([PCIACCESS], [pciaccess >= 0.8.0])
+else
+	PKG_CHECK_MODULES([PCIACCESS], [pciaccess >= 0.5.0],
+				       have_libpciaccess=yes,
+				       have_libpciaccess=no)
 fi
-
+have_libpciaccess=no
 AM_CONDITIONAL(XSERVER_LIBPCIACCESS, test "x$XSERVER_LIBPCIACCESS" = xyes)
+AM_CONDITIONAL(LIBPCIACCESS,
+	test "x$XSERVER_LIBPCIACCESS" = xyes -o "x$have_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 13cbf91..118d4b1 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 XSERVER_LIBPCIACCESS
+if LIBPCIACCESS
 REGDUMPER = reg_dumper
 endif
 
diff --git a/src/bios_reader/Makefile.am b/src/bios_reader/Makefile.am
index a4adecb..76ad15f 100644
--- a/src/bios_reader/Makefile.am
+++ b/src/bios_reader/Makefile.am
@@ -2,7 +2,7 @@ AM_CFLAGS = @WARN_CFLAGS@ @XORG_CFLAGS@ @XMODES_CFLAGS@
 
 noinst_PROGRAMS = bios_reader  $(BIOS_DUMPER)
 
-if XSERVER_LIBPCIACCESS
+if LIBPCIACCESS
 BIOS_DUMPER = bios_dumper
 
 bios_dumper_SOURCES = bios_dumper.c
commit 1b83e5e589105d05c1b78032fa47eecee478cb99
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Oct 1 14:32:28 2007 -0700

    Remove more DVO probing noise.

diff --git a/src/ch7017/ch7017.c b/src/ch7017/ch7017.c
index 4c9b4c6..ceb8a2a 100644
--- a/src/ch7017/ch7017.c
+++ b/src/ch7017/ch7017.c
@@ -94,8 +94,6 @@ 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;
diff --git a/src/sil164/sil164.c b/src/sil164/sil164.c
index c774a56..12fe8e2 100644
--- a/src/sil164/sil164.c
+++ b/src/sil164/sil164.c
@@ -81,8 +81,6 @@ sil164_init(I2CBusPtr b, I2CSlaveAddr addr)
     SIL164Ptr sil;
     unsigned char ch;
 
-    xf86DrvMsg(b->scrnIndex, X_ERROR, "detecting sil164\n");
-
     sil = xcalloc(1, sizeof(SIL164Rec));
     if (sil == NULL)
 	return NULL;
diff --git a/src/tfp410/tfp410.c b/src/tfp410/tfp410.c
index bc0ad74..b79fd2a 100644
--- a/src/tfp410/tfp410.c
+++ b/src/tfp410/tfp410.c
@@ -93,8 +93,6 @@ tfp410_init(I2CBusPtr b, I2CSlaveAddr addr)
     TFP410Ptr tfp;
     int id;
 
-    xf86DrvMsg(b->scrnIndex, X_INFO, "detecting tfp410\n");
-
     tfp = xcalloc(1, sizeof(TFP410Rec));
     if (tfp == NULL)
 	return NULL;
@@ -110,9 +108,11 @@ tfp410_init(I2CBusPtr b, I2CSlaveAddr addr)
     tfp->quiet = TRUE;
 
     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);
+	if (id != 0xffffffff) {
+	    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;
     }
 
commit 29d3188ee9676f697f6fcb859c7f680f5df30318
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Oct 1 13:45:09 2007 -0700

    Suppress I2C failure error messages during DVO device detection.
    
    Otherwise, errors would be printed for every chip probed which wasn't present
    on the system.

diff --git a/src/ch7xxx/ch7xxx.c b/src/ch7xxx/ch7xxx.c
index 3ef9612..3c58165 100644
--- a/src/ch7xxx/ch7xxx.c
+++ b/src/ch7xxx/ch7xxx.c
@@ -67,6 +67,8 @@ struct ch7xxx_reg_state {
 
 struct ch7xxx_priv {
     I2CDevRec d;
+    Bool quiet;
+
     struct ch7xxx_reg_state SavedReg;
     struct ch7xxx_reg_state ModeReg;
     CARD8 save_TCTL, save_TPCP, save_TPD, save_TPVT;
@@ -92,9 +94,11 @@ static Bool
 ch7xxx_read(struct ch7xxx_priv *dev_priv, int addr, unsigned char *ch)
 {
     if (!xf86I2CReadByte(&dev_priv->d, addr, ch)) {
-	xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex,
-		   X_ERROR, "Unable to read from %s Slave %d.\n",
-		   dev_priv->d.pI2CBus->BusName, dev_priv->d.SlaveAddr);
+	if (!dev_priv->quiet) {
+	    xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex,
+		       X_ERROR, "Unable to read from %s Slave %d.\n",
+		       dev_priv->d.pI2CBus->BusName, dev_priv->d.SlaveAddr);
+	}
 	return FALSE;
     }
 
@@ -106,9 +110,11 @@ static Bool
 ch7xxx_write(struct ch7xxx_priv *dev_priv, int addr, unsigned char ch)
 {
     if (!xf86I2CWriteByte(&dev_priv->d, addr, ch)) {
-	xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex, X_ERROR,
-		   "Unable to write to %s Slave %d.\n",
-		   dev_priv->d.pI2CBus->BusName, dev_priv->d.SlaveAddr);
+	if (!dev_priv->quiet) {
+	    xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex, X_ERROR,
+		       "Unable to write to %s Slave %d.\n",
+		       dev_priv->d.pI2CBus->BusName, dev_priv->d.SlaveAddr);
+	}
 	return FALSE;
     }
 
@@ -136,6 +142,7 @@ ch7xxx_init(I2CBusPtr b, I2CSlaveAddr addr)
     dev_priv->d.ByteTimeout = b->ByteTimeout;
     dev_priv->d.DriverPrivate.ptr = dev_priv;
 
+    dev_priv->quiet = TRUE;
     if (!ch7xxx_read(dev_priv, CH7xxx_REG_VID, &vendor))
 	goto out;
 
@@ -159,9 +166,11 @@ ch7xxx_init(I2CBusPtr b, I2CSlaveAddr addr)
 		   dev_priv->d.SlaveAddr);
 	goto out;
     }
-	xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex, X_INFO,
-		   "Detected %s chipset, vendor/device ID 0x%02x/0x%02x\n",
-		   name, vendor, device);
+    dev_priv->quiet = FALSE;
+
+    xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex, X_INFO,
+	       "Detected %s chipset, vendor/device ID 0x%02x/0x%02x\n",
+	       name, vendor, device);
 
     if (!xf86I2CDevInit(&dev_priv->d)) {
 	goto out;
diff --git a/src/ivch/ivch.c b/src/ivch/ivch.c
index bd11dd4..ac57ff3 100644
--- a/src/ivch/ivch.c
+++ b/src/ivch/ivch.c
@@ -48,6 +48,7 @@ struct ivch_priv {
     I2CDevRec	    d;
 
     xf86OutputPtr   output;
+    Bool quiet;
 
     CARD16    	    width;
     CARD16    	    height;
@@ -105,9 +106,11 @@ ivch_read(struct ivch_priv *priv, int addr, CARD16 *data)
     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);
+    if (!priv->quiet) {
+	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;
@@ -140,9 +143,12 @@ ivch_write(struct ivch_priv *priv, int addr, CARD16 data)
 
  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);
+
+    if (!priv->quiet) {
+	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;
 }
@@ -167,9 +173,11 @@ ivch_init(I2CBusPtr b, I2CSlaveAddr addr)
     priv->d.AcknTimeout = b->AcknTimeout;
     priv->d.ByteTimeout = b->ByteTimeout;
     priv->d.DriverPrivate.ptr = priv;
+    priv->quiet = TRUE;
 
     if (!ivch_read(priv, VR00, &temp))
 	goto out;
+    priv->quiet = FALSE;
 
     /* Since the identification bits are probably zeroes, which doesn't seem
      * very unique, check that the value in the base address field matches
diff --git a/src/sil164/sil164.c b/src/sil164/sil164.c
index 60a03e2..c774a56 100644
--- a/src/sil164/sil164.c
+++ b/src/sil164/sil164.c
@@ -49,9 +49,11 @@ static Bool
 sil164ReadByte(SIL164Ptr sil, int addr, CARD8 *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);
+	if (!sil->quiet) {
+	    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;
@@ -61,9 +63,11 @@ static Bool
 sil164WriteByte(SIL164Ptr sil, int addr, CARD8 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);
+	if (!sil->quiet) {
+	    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;
@@ -91,6 +95,7 @@ sil164_init(I2CBusPtr b, I2CSlaveAddr addr)
     sil->d.AcknTimeout = b->AcknTimeout;
     sil->d.ByteTimeout = b->ByteTimeout;
     sil->d.DriverPrivate.ptr = sil;
+    sil->quiet = TRUE;
 
     if (!sil164ReadByte(sil, SIL164_VID_LO, &ch))
 	goto out;
@@ -111,6 +116,7 @@ sil164_init(I2CBusPtr b, I2CSlaveAddr addr)
 		   ch, sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
 	goto out;
     }
+    sil->quiet = FALSE;
 
     if (!xf86I2CDevInit(&(sil->d))) {
 	goto out;
diff --git a/src/sil164/sil164_reg.h b/src/sil164/sil164_reg.h
index ebfcb8c..734e55d 100644
--- a/src/sil164/sil164_reg.h
+++ b/src/sil164/sil164_reg.h
@@ -65,6 +65,7 @@ typedef struct _Sil164SaveRec {
 
 typedef struct {
     I2CDevRec d;
+    Bool quiet;
     SIL164SaveRec SavedReg;
     SIL164SaveRec ModeReg;
 } SIL164Rec, *SIL164Ptr;
diff --git a/src/tfp410/tfp410.c b/src/tfp410/tfp410.c
index fecb64c..bc0ad74 100644
--- a/src/tfp410/tfp410.c
+++ b/src/tfp410/tfp410.c
@@ -48,9 +48,11 @@ 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);
+	if (!tfp->quiet) {
+	    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;
@@ -60,9 +62,11 @@ 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);
+	if (!tfp->quiet) {
+	    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;
@@ -103,6 +107,7 @@ tfp410_init(I2CBusPtr b, I2CSlaveAddr addr)
     tfp->d.AcknTimeout = b->AcknTimeout;
     tfp->d.ByteTimeout = b->ByteTimeout;
     tfp->d.DriverPrivate.ptr = tfp;
+    tfp->quiet = TRUE;
 
     if ((id = tfp410GetID(tfp, TFP410_VID_LO)) != TFP410_VID) {
 	xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_ERROR,
@@ -117,6 +122,7 @@ tfp410_init(I2CBusPtr b, I2CSlaveAddr addr)
 		   id, tfp->d.pI2CBus->BusName, tfp->d.SlaveAddr);
 	goto out;
     }
+    tfp->quiet = FALSE;
 
     if (!xf86I2CDevInit(&(tfp->d))) {
 	goto out;
diff --git a/src/tfp410/tfp410_reg.h b/src/tfp410/tfp410_reg.h
index 45afa9b..c555b97 100644
--- a/src/tfp410/tfp410_reg.h
+++ b/src/tfp410/tfp410_reg.h
@@ -95,6 +95,8 @@ typedef struct _TFP410SaveRec {
 
 typedef struct {
     I2CDevRec d;
+    Bool quiet;
+
     TFP410SaveRec SavedReg;
     TFP410SaveRec ModeReg;
 } TFP410Rec, *TFP410Ptr;
commit 6dd8228a386334d05836353672aae9f8c456e435
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Oct 1 12:07:22 2007 -0700

    Enable CH7017/7018 DVO driver by default.
    
    On hardware containing one of these chips (generally single pipe with an LVDS
    connected), it's probably better to try to enable it and fail in some cases
    than to not probe the output at all.

diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index cb461d7..8ba38bd 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -55,12 +55,10 @@ static const char *ivch_symbols[] = {
     NULL
 };
 
-#if 0
 static const char *ch7017_symbols[] = {
     "ch7017_methods",
     NULL
 };
-#endif
 
 /* driver list */
 struct _I830DVODriver i830_dvo_drivers[] =
@@ -97,10 +95,14 @@ struct _I830DVODriver i830_dvo_drivers[] =
 	.address = (TFP410_ADDR_1<<1),
 	.symbols = TFP410Symbols
     },
-    /*
-    { I830_OUTPUT_DVO_LVDS, "ch7017", "ch7017_methods",
-      0xea, ch7017_symbols, NULL, NULL, NULL }
-    */
+    {
+	.type = I830_OUTPUT_DVO_LVDS,
+	.modulename = "ch7017",
+	.fntablename = "ch7017_methods",
+	.dvo_reg = DVOA,
+	.address = 0xea,
+	.symbols = ch7017_symbols,
+    }
 };
 
 #define I830_NUM_DVO_DRIVERS (sizeof(i830_dvo_drivers)/sizeof(struct _I830DVODriver))
commit 994ee6721d9f1650ad37e21198b86848352b73af
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Oct 1 12:01:16 2007 -0700

    Disable TV/VGA output on the CH7017/7018 devices.
    
    We don't support those outputs on this chip yet, so turn them off if the BIOS
    had set them on.

diff --git a/src/ch7017/ch7017.c b/src/ch7017/ch7017.c
index 8e3a6ef..4c9b4c6 100644
--- a/src/ch7017/ch7017.c
+++ b/src/ch7017/ch7017.c
@@ -55,6 +55,7 @@ struct ch7017_priv {
     CARD8 save_lvds_control_2;
     CARD8 save_outputs_enable;
     CARD8 save_lvds_power_down;
+    CARD8 save_power_management;
 };
 
 static void
@@ -224,12 +225,20 @@ ch7017_dpms(I2CDevPtr d, int mode)
 
     ch7017_read(priv, CH7017_LVDS_POWER_DOWN, &val);
 
+    /* Turn off TV/VGA, and never turn it on since we don't support it. */
+    ch7017_write(priv, CH7017_POWER_MANAGEMENT,
+		 CH7017_DAC0_POWER_DOWN |
+		 CH7017_DAC1_POWER_DOWN |
+		 CH7017_DAC2_POWER_DOWN |
+		 CH7017_DAC3_POWER_DOWN |
+		 CH7017_TV_POWER_DOWN_EN);
+
     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 */
+	/* Turn off the LVDS */
 	ch7017_write(priv, CH7017_LVDS_POWER_DOWN,
 			val | CH7017_LVDS_POWER_DOWN_EN);
     }
@@ -273,6 +282,7 @@ ch7017_save(I2CDevPtr d)
     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);
+    ch7017_read(priv, CH7017_POWER_MANAGEMENT, &priv->save_power_management);
 }
 
 static void
@@ -290,6 +300,7 @@ ch7017_restore(I2CDevPtr d)
     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);
+    ch7017_write(priv, CH7017_POWER_MANAGEMENT, priv->save_power_management);
 }
 
 I830I2CVidOutputRec ch7017_methods = {
commit 0e5574e842eeaac75271ccd50027d3e54c57722d
Author: Regis Prevot <regis at myrix.net>
Date:   Sat Sep 29 16:21:08 2007 +0200

    Ignore detection of TV output on Panasonic CF-Y7

diff --git a/src/i830_quirks.c b/src/i830_quirks.c
index 6667545..8e4ec97 100644
--- a/src/i830_quirks.c
+++ b/src/i830_quirks.c
@@ -76,6 +76,8 @@ static i830_quirk i830_quirk_list[] = {
     
     /* Panasonic Toughbook CF-Y4 has no TV output */
     { PCI_CHIP_I915_GM, 0x10f7, 0x8338, quirk_ignore_tv },
+    /* Panasonic Toughbook CF-Y7 has no TV output */
+    { PCI_CHIP_I965_GM, 0x10f7, 0x8338, quirk_ignore_tv },
     
     { 0, 0, 0, NULL },
 };
commit 1845e7c6e9caf7a9ad7f46a8fbfa321ddec69a1e
Author: Jesse Barnes <jesse.barnes at intel.com>
Date:   Fri Sep 28 10:12:11 2007 -0700

    Go back to using old drm_i915_flip_t field name
    
    This field shouldn't have been renamed in the first place.  Go back to using
    the old name so that the tree is backward and forward compatible again.

diff --git a/src/i830_dri.c b/src/i830_dri.c
index 6fe75e5..4cddf3b 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 planes;
+   int pipes;
 } drm_i915_flip_t;
 
 #undef DRM_IOCTL_I915_FLIP
@@ -1256,20 +1256,20 @@ I830DRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
 #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 = { .planes = 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.planes |= 0x2;
+	    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.planes |= 0x1;
+	    flip.pipes |= 0x1;
 	 }
 
 	 drmCommandWrite(pI830->drmSubFD, DRM_I915_FLIP, &flip, sizeof(flip));
commit 97117171531af71816c5dd561abea38afa29150e
Author: Alan Hourihane <alanh at tungstengraphics.com>
Date:   Fri Sep 28 16:41:44 2007 +0100

    include "xf86mm.h"

diff --git a/src/i830.h b/src/i830.h
index 21618d8..ac4f2fb 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -56,6 +56,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "xf86Cursor.h"
 #include "xf86xv.h"
 #include "xf86int10.h"
+#include "xf86mm.h"
 #include "vbe.h"
 #include "vgaHW.h"
 #include "xf86Crtc.h"
commit f3d92ab474de11babe507b0e3c15aca146b6cb66
Author: Kyle McMartin <kyle at freedesktop.org>
Date:   Fri Sep 28 10:17:55 2007 -0400

    Dell XPS 1330 has no TV out

diff --git a/src/i830_quirks.c b/src/i830_quirks.c
index 28b8ff9..6667545 100644
--- a/src/i830_quirks.c
+++ b/src/i830_quirks.c
@@ -64,6 +64,8 @@ static i830_quirk i830_quirk_list[] = {
     
     /* Dell Latitude X1 */
     { PCI_CHIP_I945_GM, 0x1028, 0x01a3, quirk_ignore_tv },
+    /* Dell XPS 1330 */
+    { PCI_CHIP_I965_GM, 0x1028, 0x0209, quirk_ignore_tv },
     
     /* Lenovo X60s has no TV output */
     { PCI_CHIP_I945_GM, 0x17aa, 0x201a, quirk_ignore_tv },
commit bbf69c7446aa9748dacecccfe0b63d803f865b00
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, unsigned long offset, unsigned long 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) {
-		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 pScrn)
 {
     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 pScrn)
     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");


More information about the xorg-commit mailing list