xf86-video-intel: Branch 'display-port' - 24 commits - configure.ac man/Makefile.am src/drmmode_display.c src/i810_driver.c src/i810.h src/i830_bios.c src/i830_display.c src/i830_display.h src/i830_driver.c src/i830_exa.c src/i830_lvds.c src/i830_memory.c src/i830_sdvo.c src/i830_video.c src/Makefile.am src/reg_dumper/.gitignore src/reg_dumper/lid.c src/reg_dumper/Makefile.am

Keith Packard keithp at kemper.freedesktop.org
Fri Apr 3 17:47:29 PDT 2009


 configure.ac               |    2 
 man/Makefile.am            |   20 -
 src/Makefile.am            |    6 
 src/drmmode_display.c      |  186 ++++++++++++++++
 src/i810.h                 |    1 
 src/i810_driver.c          |   19 -
 src/i830_bios.c            |    8 
 src/i830_display.c         |  508 +++++++++++++++++++++++++++++++++++----------
 src/i830_display.h         |    2 
 src/i830_driver.c          |   51 +++-
 src/i830_exa.c             |   50 ++--
 src/i830_lvds.c            |    7 
 src/i830_memory.c          |   16 -
 src/i830_sdvo.c            |   10 
 src/i830_video.c           |   13 -
 src/reg_dumper/.gitignore  |    1 
 src/reg_dumper/Makefile.am |    9 
 src/reg_dumper/lid.c       |  146 ++++++++++++
 18 files changed, 855 insertions(+), 200 deletions(-)

New commits:
commit 43da57d30d26a878534f2cc50044d9bbc0cf484a
Merge: 922fe23... 6cd914e...
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Apr 3 17:47:22 2009 -0700

    Merge commit 'origin/master' into display-port

diff --cc src/i830_display.c
index 7d2cc4c,dd1310f..9c32884
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@@ -1303,8 -1584,9 +1584,9 @@@ i830_crtc_mode_set(xf86CrtcPtr crtc, Di
      int refclk;
      intel_clock_t clock;
      uint32_t dpll = 0, fp = 0, dspcntr, pipeconf, lvds_bits = 0;
 -    Bool ok, is_sdvo = FALSE, is_dvo = FALSE;
 +    Bool ok, is_sdvo = FALSE, is_dvo = FALSE, is_dp = FALSE;
      Bool is_crt = FALSE, is_lvds = FALSE, is_tv = FALSE;
+     const intel_limit_t *limit;
  
      /* Set up some convenient bools for what outputs are connected to
       * our pipe, used in DPLL setup.
commit 6cd914ef315036ce8e91c7b6492994353e8ed2d8
Author: Jesse Barnes <jbarnes at virtuousgeek.org>
Date:   Fri Apr 3 11:15:18 2009 -0700

    Fix offset in begin_gtt_access case
    
    Don't use bo->virtual in the begin_gtt_access case, use the framebuffer
    mapping and bo offset instead.
    
    Reviewed-by: Eric Anholt <eric at anholt.net>
    Signed-off-by: Jesse Barnes <jbarnes at virtuousgeek.org>

diff --git a/src/i830_driver.c b/src/i830_driver.c
index d7ee615..32ca6c9 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -846,11 +846,12 @@ i830_update_front_offset(ScrnInfoPtr pScrn)
 	      if (drm_intel_gem_bo_map_gtt(bo))
 		  xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "%s: bo map failed\n",
 			     __FUNCTION__);
+	      data = bo->virtual;
 	  } else {
 	      /* Will already be pinned by bind_all_memory in this case */
 	      drm_intel_gem_bo_start_gtt_access(bo, 1);
+	      data = pI830->FbBase + bo->offset;
 	  }
-	  data = bo->virtual;
       }
    }
    if (!pScreen->ModifyPixmapHeader(pScreen->GetScreenPixmap(pScreen),
diff --git a/src/i830_exa.c b/src/i830_exa.c
index fc4e66c..39011bc 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -867,12 +867,13 @@ i830_uxa_prepare_access (PixmapPtr pixmap, uxa_access_t access)
 			   __FUNCTION__);
 		return FALSE;
 	    }
+	    pixmap->devPrivate.ptr = bo->virtual;
 	} else { /* or not... */
 	    if (drm_intel_bo_pin(bo, 4096) != 0)
 		return FALSE;
 	    drm_intel_gem_bo_start_gtt_access(bo, access == UXA_ACCESS_RW);
+	    pixmap->devPrivate.ptr = i830->FbBase + bo->offset;
 	}
-	pixmap->devPrivate.ptr = bo->virtual;
     }
     return TRUE;
 }
commit fad714c40078d22fff82dc0692a344f66ddf9680
Author: Zhenyu Wang <zhenyu.z.wang at intel.com>
Date:   Wed Apr 1 10:11:35 2009 +0800

    SDVO: fix output flag dumping for unknown type
    
    Found by Hugo Jacques <hugo.jacques at verint.com>

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 79d49d9..a7b5171 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -1605,7 +1605,7 @@ i830_sdvo_output_setup (xf86OutputPtr output, uint16_t flag)
 	xf86DrvMsg(intel_output->pI2CBus->scrnIndex, X_WARNING,
 		   "%s: Unknown SDVO output type (0x%02x%02x)\n",
 		   SDVO_NAME(dev_priv),
-		   bytes[0], bytes[1]);
+		   bytes[1], bytes[0]);
 	name_prefix="Unknown";
     }
 
commit 00de1757dd5776962bdd4c8968181878c2ebf4c9
Author: Hugo Jacques <hugo.jacques at verint.com>
Date:   Wed Apr 1 10:10:05 2009 +0800

    SDVO: add composite TV out support

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 254b866..79d49d9 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -1570,6 +1570,14 @@ i830_sdvo_output_setup (xf86OutputPtr output, uint16_t flag)
 	dev_priv->is_tv = TRUE;
 	intel_output->needs_tv_clock = TRUE;
     }
+    else if (flag & SDVO_OUTPUT_CVBS0)
+    {
+	dev_priv->controlled_output = SDVO_OUTPUT_CVBS0;
+	output->subpixel_order = SubPixelHorizontalRGB; /* XXX */
+	name_prefix="TV";
+	dev_priv->is_tv = TRUE;
+	intel_output->needs_tv_clock = TRUE;
+    }
     else if (flag & SDVO_OUTPUT_RGB0)
     {
 	dev_priv->controlled_output = SDVO_OUTPUT_RGB0;
commit 087f72e1f5d7d11b8795ba80a842874f5a9bb01d
Author: Jesse Barnes <jbarnes at virtuousgeek.org>
Date:   Tue Mar 31 07:50:10 2009 -0700

    Match GTT unmap with map in KMS rotation case
    
    Missed this when the GTT unmap call was added.  If we don't do this we
    trigger an assertion in libdrm, since the buffer has never been mapped
    normally.
    
    Fixes bug #20943.
    
    Signed-off-by: Jesse Barnes <jbarnes at virtuousgeek.org>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 0cbcde7..7b97a64 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -382,7 +382,7 @@ drmmode_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *dat
 		 * unbound. */
 		drmModeRmFB(drmmode->fd, drmmode_crtc->rotate_fb_id);
 		drmmode_crtc->rotate_fb_id = 0;
-		drm_intel_bo_unmap(drmmode_crtc->rotate_bo);
+		drm_intel_gem_bo_unmap_gtt(drmmode_crtc->rotate_bo);
 		dri_bo_unreference(drmmode_crtc->rotate_bo);
 		drmmode_crtc->rotate_bo = NULL;
 	}
commit 4f046af760b92c07f59664359453933fb5358e3d
Author: Zhenyu Wang <zhenyu.z.wang at intel.com>
Date:   Tue Mar 31 13:49:44 2009 +0800

    Disable LVDS detect methods
    
    Both methods ACPI lid and SWF bit have issues in LVDS detect from
    wider testing. Fallback to origin code.

diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index 7569e99..7fc0bce 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -881,6 +881,13 @@ i830_lvds_mode_set(xf86OutputPtr output, DisplayModePtr mode,
 static xf86OutputStatus
 i830_lvds_detect(xf86OutputPtr output)
 {
+    /* Fallback to origin, mark LVDS always connected.
+     * From wider tests, we have seen both broken cases with
+     * ACPI lid and SWF bit. So disable them for now until we
+     * get a reliable way for LVDS detect.
+     */
+    return XF86OutputStatusConnected;
+
     enum lid_status lid;
 
     lid = i830_lvds_acpi_lid_open(output);
commit e964d4e53af3a47de6d09c884be1cc0044d03bea
Author: Albert Damen <albrt at gmx.net>
Date:   Mon Mar 30 11:38:02 2009 -0700

    Non-GEM allocations incorrectly force TILE_NONE (bug 20797)
    
    With -intel 2.6.3 performance was very bad when using a non gem enabled kernel
    (2.6.27) and EXA. For example sauerbraten ran with 4 fps and screensaver GLBlur
    with 1 fps. With -intel 2.6.1 performance was good using the same kernel.
    
    Git bisecting led me to commit f1ed73c1ef3e3daa9f695194dcc813167cbcb53d (in 2.6
    branch) "Make i830_allocate_memory take tiling parameters" as first bad commit.
    
    Using gdb I found tiling was set exactly the same in 2.6.3 as in 2.6.1, so that
    was good (TILE_XMAJOR for front, back and depth buffers).
    Looking further I found the line mem->tiling = TILE_NONE; (line 961 in
    src/i830_memory.c) at the end of i830_allocate_memory suspicious, as
    mem->tiling now already gets set via i830_allocate_aperture and some buffers do
    have tiling. Removing that line indeed fixed the performance issue. Now
    sauerbraten runs with 30+ fps and GLBlur runs smoothly.

diff --git a/src/i830_memory.c b/src/i830_memory.c
index 052d906..e3314c5 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -958,8 +958,6 @@ i830_allocate_memory(ScrnInfoPtr pScrn, const char *name,
 	}
     }
 
-    mem->tiling = TILE_NONE;
-
     return mem;
 }
 
commit 51cf8a453c2bc2e8604bfc41a649e971c1ba5026
Author: Jesse Barnes <jbarnes at virtuousgeek.org>
Date:   Mon Mar 30 11:27:56 2009 -0700

    Require libdrm 2.4.6 for GTT unmap support
    
    Need the new functions available.

diff --git a/configure.ac b/configure.ac
index 88059bf..ae134af 100644
--- a/configure.ac
+++ b/configure.ac
@@ -211,7 +211,7 @@ if test "x$GCC" = "xyes"; then
 	-Wnested-externs -fno-strict-aliasing"
 fi
 
-PKG_CHECK_MODULES(DRM, [libdrm >= 2.4.5])
+PKG_CHECK_MODULES(DRM, [libdrm >= 2.4.6])
 AM_CONDITIONAL(DRI, test x$DRI = xyes)
 if test "$DRI" = yes; then
         PKG_CHECK_MODULES(DRI, [xf86driproto glproto])
commit 8dabcc40747bfd478f296728741240241698f165
Author: Jesse Barnes <jbarnes at virtuousgeek.org>
Date:   Mon Mar 30 09:53:40 2009 -0700

    Tiling fixes, third set
    
    Hopefully this concludes the fixes necessary to deal with the various
    combinations of kernel and user level tiling.  We have several cases to
    handle:
      1) KMS (kernel handles all tiling)
      2) UMS w/memory management + kexec fencing (kernel handles all tiling)
      3) UMS w/memory mangement but no kexec fencing (userland handles tiling)
      4) UMS w/o memory management (userland handles tiling)
    
    For cases (1) & (2) we can use GTT mapping, which will give us good
    performance and take care of allocating fence registers as needed.  It's
    important *not* to have userland set up fence regs in this case, since
    the kernel will be using all of them.
    
    For case (3), we use the begin/end GTT map functions provided by libdrm,
    in combination with pinning and fence register setup in i830_memory.c to
    deal with tiled surfaces.  This also gives us good performance and
    correctness.
    
    For case (4) we use the old style virtual mapping + offset for dealing
    with surfaces; note that UXA doesn't seem to work in this configuration
    regardless of these fixes.
    
    Fixes bug #20803.
    
    Reviewed-by: Eric Anholt <eric at anholt.net>
    Signed-off-by: Jesse Barnes <jbarnes at virtuousgeek.org>

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 7502d30..d7ee615 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -823,22 +823,40 @@ i830_update_front_offset(ScrnInfoPtr pScrn)
    ScreenPtr pScreen = pScrn->pScreen;
    I830Ptr pI830 = I830PTR(pScrn);
    int pitch = pScrn->displayWidth * pI830->cpp;
+   pointer data = NULL;
 
    /* Update buffer locations, which may have changed as a result of
     * i830_bind_all_memory().
     */
    pScrn->fbOffset = pI830->front_buffer->offset;
 
+   if (pI830->starting || pI830->accel == ACCEL_UXA)
+       return;
+
    /* 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 && pI830->accel != ACCEL_UXA) {
-      if (!pScreen->ModifyPixmapHeader(pScreen->GetScreenPixmap(pScreen),
+   if (!pI830->memory_manager) {
+       data = pI830->FbBase + pScrn->fbOffset; /* default to legacy */
+   } else {
+      dri_bo *bo = pI830->front_buffer->bo;
+
+      if (bo) {
+	  if (pI830->kernel_exec_fencing) {
+	      if (drm_intel_gem_bo_map_gtt(bo))
+		  xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "%s: bo map failed\n",
+			     __FUNCTION__);
+	  } else {
+	      /* Will already be pinned by bind_all_memory in this case */
+	      drm_intel_gem_bo_start_gtt_access(bo, 1);
+	  }
+	  data = bo->virtual;
+      }
+   }
+   if (!pScreen->ModifyPixmapHeader(pScreen->GetScreenPixmap(pScreen),
 				       pScrn->virtualX, pScrn->virtualY, -1, -1,
-				       pitch, (pointer)(pI830->FbBase +
-							pScrn->fbOffset)))
+				       pitch, data))
        FatalError("Couldn't adjust screen pixmap\n");
-   }
 }
 
 /**
diff --git a/src/i830_exa.c b/src/i830_exa.c
index 0a22486..fc4e66c 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -37,6 +37,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "i810_reg.h"
 #include "i915_drm.h"
 #include <string.h>
+#include <sys/mman.h>
 
 #define ALWAYS_SYNC		0
 #define ALWAYS_FLUSH		0
@@ -837,8 +838,6 @@ i830_uxa_set_pixmap_bo (PixmapPtr pixmap, dri_bo *bo)
 static Bool
 i830_uxa_prepare_access (PixmapPtr pixmap, uxa_access_t access)
 {
-    ScrnInfoPtr pScrn = xf86Screens[pixmap->drawable.pScreen->myNum];
-    I830Ptr pI830 = I830PTR(pScrn);
     dri_bo *bo = i830_get_pixmap_bo (pixmap);
 
     if (bo) {
@@ -853,16 +852,27 @@ i830_uxa_prepare_access (PixmapPtr pixmap, uxa_access_t access)
 	    i830->need_sync = FALSE;
 	}
 
-	if (pScrn->vtSema && !pI830->use_drm_mode && pI830->memory_manager) {
-	    if (drm_intel_bo_pin(bo, 4096) != 0)
-		return FALSE;
-	    drm_intel_gem_bo_start_gtt_access(bo, access == UXA_ACCESS_RW);
-	    pixmap->devPrivate.ptr = pI830->FbBase + bo->offset;
-	} else {
+	/* No VT sema or GEM?  No GTT mapping. */
+	if (!scrn->vtSema || !i830->memory_manager) {
 	    if (dri_bo_map(bo, access == UXA_ACCESS_RW) != 0)
 		return FALSE;
 	    pixmap->devPrivate.ptr = bo->virtual;
+	    return TRUE;
+	}
+
+	/* Kernel manages fences at GTT map/fault time */
+	if (i830->kernel_exec_fencing) {
+	    if (drm_intel_gem_bo_map_gtt(bo)) {
+		xf86DrvMsg(scrn->scrnIndex, X_WARNING, "%s: bo map failed\n",
+			   __FUNCTION__);
+		return FALSE;
+	    }
+	} else { /* or not... */
+	    if (drm_intel_bo_pin(bo, 4096) != 0)
+		return FALSE;
+	    drm_intel_gem_bo_start_gtt_access(bo, access == UXA_ACCESS_RW);
 	}
+	pixmap->devPrivate.ptr = bo->virtual;
     }
     return TRUE;
 }
@@ -870,8 +880,6 @@ i830_uxa_prepare_access (PixmapPtr pixmap, uxa_access_t access)
 static void
 i830_uxa_finish_access (PixmapPtr pixmap)
 {
-    ScrnInfoPtr pScrn = xf86Screens[pixmap->drawable.pScreen->myNum];
-    I830Ptr pI830 = I830PTR(pScrn);
     dri_bo *bo = i830_get_pixmap_bo (pixmap);
 
     if (bo) {
@@ -879,14 +887,20 @@ i830_uxa_finish_access (PixmapPtr pixmap)
 	ScrnInfoPtr scrn = xf86Screens[screen->myNum];
 	I830Ptr i830 = I830PTR(scrn);
 
-	if (pScrn->vtSema && !pI830->use_drm_mode && pI830->memory_manager)
-	    drm_intel_bo_unpin(bo);
-	else
+	if (bo == i830->front_buffer->bo)
+	    i830->need_flush = TRUE;
+
+	if (!scrn->vtSema || !i830->memory_manager) {
 	    dri_bo_unmap(bo);
+	    pixmap->devPrivate.ptr = NULL;
+	    return;
+	}
 
+	if (i830->kernel_exec_fencing)
+	    drm_intel_gem_bo_unmap_gtt(bo);
+	else
+	    drm_intel_bo_unpin(bo);
 	pixmap->devPrivate.ptr = NULL;
-	if (bo == i830->front_buffer->bo)
-	    i830->need_flush = TRUE;
     }
 }
 
commit 375b2e40fcb17e94538a75392950e2533c1bb031
Author: Zhenyu Wang <zhenyu.z.wang at intel.com>
Date:   Wed Mar 25 11:13:52 2009 +0800

    Disable LVDS config parsing from VBT for now
    
    As wider tests showed that this doesn't work for all VBIOS, so
    disable it for now and reenable it after we get reliable method.

diff --git a/src/i830_bios.c b/src/i830_bios.c
index 9b13bf4..4f2355d 100644
--- a/src/i830_bios.c
+++ b/src/i830_bios.c
@@ -181,6 +181,12 @@ parse_driver_feature(I830Ptr pI830, struct bdb_header *bdb)
     if (!IS_I9XX(pI830))
 	return;
 
+    /* XXX Disable this parsing, as it looks doesn't work for all
+       VBIOS. Reenable it if we could find out the reliable VBT parsing
+       for LVDS config later. */
+    if (1)
+	return;
+
     feature = find_section(bdb, BDB_DRIVER_FEATURES);
     if (!feature)
 	return;
commit 69c84f2c8204771b68f40ed64e64657237b54546
Author: Zhenyu Wang <zhenyu.z.wang at intel.com>
Date:   Thu Mar 26 13:52:05 2009 +0800

    gitignore intel_lid

diff --git a/src/reg_dumper/.gitignore b/src/reg_dumper/.gitignore
index 5aac542..60a9a4f 100644
--- a/src/reg_dumper/.gitignore
+++ b/src/reg_dumper/.gitignore
@@ -4,3 +4,4 @@ intel_idle
 intel_reg_dumper
 intel_stepping
 intel_statuspage
+intel_lid
commit b5b377806422c9538fa9f846819ad253c1a50846
Author: Ma, Ling <ling.ma at intel.com>
Date:   Wed Mar 25 14:39:46 2009 +0800

    disable center mode for 965GM and G4X platform
    
    When disabling VGA mode, usually we don't need to touch VGA center mode.
    However because of hardware reason, for Cresline, Cantiga & Eaglelake platform,
    we have to disable center mode as well. The patch fixed bug- TV Out strobing regression,
    reported by Robert Lowery in intel-gfx at lists.freedesktop.org mailing list.
    
    Signed-off-by: Ma Ling <ling.ma at intel.com>

diff --git a/src/i830_display.c b/src/i830_display.c
index a44143f..dd1310f 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -1113,6 +1113,9 @@ i830_disable_vga_plane (xf86CrtcPtr crtc)
     sr01 = INREG8(SRX + 1);
     OUTREG8(SRX + 1, sr01 | (1 << 5));
     usleep(30);
+    /* disable center mode on 965GM and G4X platform */
+    if (IS_I965GM(pI830) || IS_G4X(pI830))
+        vgacntrl &= ~(3 << 24);
 
     vgacntrl |= VGA_DISP_DISABLE;
 
commit e6af995b24767815ab30364385768867e80605c2
Author: Zhenyu Wang <zhenyu.z.wang at intel.com>
Date:   Mon Mar 23 19:19:58 2009 +0800

    KMS: hook up output properties for randr
    
    This gets output properties from kernel, then hook them up
    for randr. So we can control output properties through randr
    like in UMS.
    
    Signed-off-by: Zhenyu Wang <zhenyu.z.wang at intel.com>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index e485256..0cbcde7 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -35,6 +35,7 @@
 #include "i830.h"
 #include "intel_bufmgr.h"
 #include "xf86drmMode.h"
+#include "X11/Xatom.h"
 
 typedef struct {
     int fd;
@@ -52,11 +53,20 @@ typedef struct {
 } drmmode_crtc_private_rec, *drmmode_crtc_private_ptr;
 
 typedef struct {
+    drmModePropertyPtr mode_prop;
+    uint64_t value;
+    int num_atoms; /* if range prop, num_atoms == 1; if enum prop, num_atoms == num_enums + 1 */
+    Atom *atoms;
+} drmmode_prop_rec, *drmmode_prop_ptr;
+
+typedef struct {
     drmmode_ptr drmmode;
     int output_id;
     drmModeConnectorPtr mode_output;
     drmModeEncoderPtr mode_encoder;
     drmModePropertyBlobPtr edid_blob;
+    int num_props;
+    drmmode_prop_ptr props;
 } drmmode_output_private_rec, *drmmode_output_private_ptr;
 
 static void
@@ -508,9 +518,15 @@ static void
 drmmode_output_destroy(xf86OutputPtr output)
 {
 	drmmode_output_private_ptr drmmode_output = output->driver_private;
+	int i;
 
 	if (drmmode_output->edid_blob)
 		drmModeFreePropertyBlob(drmmode_output->edid_blob);
+	for (i = 0; i < drmmode_output->num_props; i++) {
+	    drmModeFreeProperty(drmmode_output->props[i].mode_prop);
+	    xfree(drmmode_output->props[i].atoms);
+	}
+	xfree(drmmode_output->props);
 	drmModeFreeConnector(drmmode_output->mode_output);
 	xfree(drmmode_output);
 	output->driver_private = NULL;
@@ -542,7 +558,162 @@ drmmode_output_dpms(xf86OutputPtr output, int mode)
 	}
 }
 
+static Bool
+drmmode_property_ignore(drmModePropertyPtr prop)
+{
+    if (!prop)
+	return TRUE;
+    /* ignore blob prop */
+    if (prop->flags & DRM_MODE_PROP_BLOB)
+	return TRUE;
+    /* ignore standard property */
+    if (!strcmp(prop->name, "EDID") ||
+	    !strcmp(prop->name, "DPMS"))
+	return TRUE;
+
+    return FALSE;
+}
+
+static void
+drmmode_output_create_resources(xf86OutputPtr output)
+{
+    drmmode_output_private_ptr drmmode_output = output->driver_private;
+    drmModeConnectorPtr mode_output = drmmode_output->mode_output;
+    drmmode_ptr drmmode = drmmode_output->drmmode;
+    drmModePropertyPtr drmmode_prop;
+    int i, j, err;
+
+    drmmode_output->props = xcalloc(mode_output->count_props, sizeof(drmmode_prop_rec));
+    if (!drmmode_output->props)
+	return;
+
+    drmmode_output->num_props = 0;
+    for (i = 0, j = 0; i < mode_output->count_props; i++) {
+	drmmode_prop = drmModeGetProperty(drmmode->fd, mode_output->props[i]);
+	if (drmmode_property_ignore(drmmode_prop)) {
+	    drmModeFreeProperty(drmmode_prop);
+	    continue;
+	}
+	drmmode_output->props[j].mode_prop = drmmode_prop;
+	drmmode_output->props[j].value = mode_output->prop_values[i];
+	drmmode_output->num_props++;
+	j++;
+    }
+
+    for (i = 0; i < drmmode_output->num_props; i++) {
+	drmmode_prop_ptr p = &drmmode_output->props[i];
+	drmmode_prop = p->mode_prop;
+
+	if (drmmode_prop->flags & DRM_MODE_PROP_RANGE) {
+	    INT32 range[2];
+
+	    p->num_atoms = 1;
+	    p->atoms = xcalloc(p->num_atoms, sizeof(Atom));
+	    if (!p->atoms)
+		continue;
+	    p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
+	    range[0] = drmmode_prop->values[0];
+	    range[1] = drmmode_prop->values[1];
+	    err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
+		    FALSE, TRUE,
+		    drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
+		    2, range);
+	    if (err != 0) {
+		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
+			"RRConfigureOutputProperty error, %d\n", err);
+	    }
+	    err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
+		    XA_INTEGER, 32, PropModeReplace, 1, &p->value, FALSE, TRUE);
+	    if (err != 0) {
+		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
+			"RRChangeOutputProperty error, %d\n", err);
+	    }
+	} else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM) {
+	    p->num_atoms = drmmode_prop->count_enums + 1;
+	    p->atoms = xcalloc(p->num_atoms, sizeof(Atom));
+	    if (!p->atoms)
+		continue;
+	    p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
+	    for (j = 1; j <= drmmode_prop->count_enums; j++) {
+		struct drm_mode_property_enum *e = &drmmode_prop->enums[j-1];
+		p->atoms[j] = MakeAtom(e->name, strlen(e->name), TRUE);
+	    }
+	    err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
+		    FALSE, FALSE,
+		    drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
+		    p->num_atoms - 1, (INT32 *)&p->atoms[1]);
+	    if (err != 0) {
+		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
+			"RRConfigureOutputProperty error, %d\n", err);
+	    }
+	    for (j = 0; j < drmmode_prop->count_enums; j++)
+		if (drmmode_prop->enums[j].value == p->value)
+		    break;
+	    /* there's always a matching value */
+	    err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
+		    XA_ATOM, 32, PropModeReplace, 1, &p->atoms[j+1], FALSE, TRUE);
+	    if (err != 0) {
+		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
+			"RRChangeOutputProperty error, %d\n", err);
+	    }
+	}
+    }
+}
+
+static Bool
+drmmode_output_set_property(xf86OutputPtr output, Atom property,
+		RRPropertyValuePtr value)
+{
+    drmmode_output_private_ptr drmmode_output = output->driver_private;
+    drmmode_ptr drmmode = drmmode_output->drmmode;
+    int i;
+
+    for (i = 0; i < drmmode_output->num_props; i++) {
+	drmmode_prop_ptr p = &drmmode_output->props[i];
+
+	if (p->atoms[0] != property)
+	    continue;
+
+	if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) {
+	    uint32_t val;
+
+	    if (value->type != XA_INTEGER || value->format != 32 ||
+		    value->size != 1)
+		return FALSE;
+	    val = *(uint32_t *)value->data;
+
+	    drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id,
+		    p->mode_prop->prop_id, (uint64_t)val);
+	    return TRUE;
+	} else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) {
+	    Atom	atom;
+	    const char	*name;
+	    int		j;
+
+	    if (value->type != XA_ATOM || value->format != 32 || value->size != 1)
+		return FALSE;
+	    memcpy(&atom, value->data, 4);
+	    name = NameForAtom(atom);
+
+	    /* search for matching name string, then set its value down */
+	    for (j = 0; j < p->mode_prop->count_enums; j++) {
+		if (!strcmp(p->mode_prop->enums[j].name, name)) {
+		    drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id,
+			    p->mode_prop->prop_id, p->mode_prop->enums[j].value);
+		    return TRUE;
+		}
+	    }
+	}
+    }
+    /* no property found? */
+    return FALSE;
+}
+
 static const xf86OutputFuncsRec drmmode_output_funcs = {
+	.create_resources = drmmode_output_create_resources,
+#ifdef RANDR_12_INTERFACE
+	.set_property = drmmode_output_set_property,
+#endif
 	.dpms = drmmode_output_dpms,
 #if 0
 
commit 74d0713e002a9781ed00fdd10eb6f75907ae796c
Author: Kalev Lember <kalev at smartlink.ee>
Date:   Fri Mar 20 02:21:41 2009 +0200

    Fix VT switch with XV overlay video enabled.
    
    drm_intel_bo_unpin() was called with NULL argument.
    
    Signed-off-by: Kalev Lember <kalev at smartlink.ee>

diff --git a/src/i830_video.c b/src/i830_video.c
index 3c6fbf3..3f3aaac 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -1048,11 +1048,14 @@ I830StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
 	if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
 	    i830_overlay_off(pScrn);
 	}
-	if (!pPriv->textured)
-	    drm_intel_bo_unpin(pPriv->buf);
-	drm_intel_bo_unreference(pPriv->buf);
-	pPriv->buf = NULL;
-	pPriv->videoStatus = 0;
+
+	if (pPriv->buf) {
+	    if (!pPriv->textured)
+		drm_intel_bo_unpin(pPriv->buf);
+	    drm_intel_bo_unreference(pPriv->buf);
+	    pPriv->buf = NULL;
+	    pPriv->videoStatus = 0;
+	}
     } else {
 	if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
 	    pPriv->videoStatus |= OFF_TIMER;
commit b345b4e6adf00f8b2626e5c2563fc159e2295cc5
Author: Rémi Cardona <remi at gentoo.org>
Date:   Fri Nov 14 13:55:52 2008 +0100

    clean up man page generation and remove all traces of the i810 driver
    
    The i810 compatibility symlink has been broken since libpciaccess, so just
    let it die.

diff --git a/man/Makefile.am b/man/Makefile.am
index 7432d5a..ac08621 100644
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -25,21 +25,12 @@
 # 
 
 drivermandir = $(DRIVER_MAN_DIR)
+driverman_DATA = $(DRIVER_NAME).$(DRIVER_MAN_SUFFIX)
 
-DRIVER_MAN_DIR_SUFFIX = $(DRIVER_MAN_DIR:@mandir@/man%=%)
-
-driverman_PRE = @DRIVER_NAME at .man
-
-driverman_DATA = \
-	$(driverman_PRE:man=@DRIVER_MAN_SUFFIX@) \
-	i810. at DRIVER_MAN_SUFFIX@
-
-EXTRA_DIST = @DRIVER_NAME at .man
+EXTRA_DIST = $(DRIVER_NAME).man
 
 CLEANFILES = $(driverman_DATA)
 
-SED = sed
-
 # Strings to replace in man pages
 XORGRELSTRING = @PACKAGE_STRING@
   XORGMANNAME = X Version 11
@@ -60,10 +51,3 @@ SUFFIXES = .$(DRIVER_MAN_SUFFIX) .man
 
 .man.$(DRIVER_MAN_SUFFIX):
 	sed $(MAN_SUBSTS) < $< > $@
-
-BUILT_SOURCES = shadows.DONE
-
-shadows.DONE:
-	-rm -f i810. at DRIVER_MAN_SUFFIX@
-	echo .so man$(DRIVER_MAN_DIR_SUFFIX)/intel.$(DRIVER_MAN_SUFFIX) > \
-		i810. at DRIVER_MAN_SUFFIX@
diff --git a/src/Makefile.am b/src/Makefile.am
index e05dbab..ad87afc 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -220,9 +220,3 @@ if XVMC
 intel_drv_la_SOURCES += \
 	$(INTEL_XVMC_SRCS)
 endif
-
-install-data-local: install-intel_drv_laLTLIBRARIES
-	(cd $(DESTDIR)$(intel_drv_ladir) && rm -f i810_drv.so && ln -s intel_drv.so i810_drv.so)
-
-uninstall-local:
-	(cd $(DESTDIR)$(intel_drv_ladir) && rm -f i810_drv.so)
diff --git a/src/i810.h b/src/i810.h
index 7ea2043..c88771e 100644
--- a/src/i810.h
+++ b/src/i810.h
@@ -70,7 +70,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define I810_VERSION 4000
 #define I810_NAME "intel"
 #define I810_DRIVER_NAME "intel"
-#define I810_LEGACY_DRIVER_NAME "i810"
 
 #define INTEL_VERSION_MAJOR PACKAGE_VERSION_MAJOR
 #define INTEL_VERSION_MINOR PACKAGE_VERSION_MINOR
diff --git a/src/i810_driver.c b/src/i810_driver.c
index 6ae388d..fe4bd62 100644
--- a/src/i810_driver.c
+++ b/src/i810_driver.c
@@ -472,21 +472,6 @@ static XF86ModuleVersionInfo intelVersRec = {
 
 _X_EXPORT XF86ModuleData intelModuleData = { &intelVersRec, i810Setup, NULL };
 
-static XF86ModuleVersionInfo i810VersRec = {
-   "i810",
-   MODULEVENDORSTRING,
-   MODINFOSTRING1,
-   MODINFOSTRING2,
-   XORG_VERSION_CURRENT,
-   INTEL_VERSION_MAJOR, INTEL_VERSION_MINOR, INTEL_VERSION_PATCH,
-   ABI_CLASS_VIDEODRV,
-   ABI_VIDEODRV_VERSION,
-   MOD_CLASS_VIDEODRV,
-   {0, 0, 0, 0}
-};
-
-_X_EXPORT XF86ModuleData i810ModuleData = { &i810VersRec, i810Setup, NULL };
-
 static pointer
 i810Setup(pointer module, pointer opts, int *errmaj, int *errmin)
 {
@@ -681,9 +666,7 @@ I810Probe(DriverPtr drv, int flags)
     * driver, and return if there are none.
     */
    if ((numDevSections =
-	xf86MatchDevice(I810_DRIVER_NAME, &devSections)) <= 0 &&
-       (numDevSections =
-	xf86MatchDevice(I810_LEGACY_DRIVER_NAME, &devSections)) <= 0) {
+	xf86MatchDevice(I810_DRIVER_NAME, &devSections)) <= 0 ) {
       return FALSE;
    }
 
commit 48b91e066878db63a1558e4cd3e6d12ff9c49197
Author: Jesse Barnes <jbarnes at virtuousgeek.org>
Date:   Fri Mar 20 12:33:22 2009 -0700

    Don't manage fences part two
    
    Don't try to clear fences that were never installed.  Missed this bit in
    the last fix for #20265.

diff --git a/src/i830_memory.c b/src/i830_memory.c
index 36dab11..052d906 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -270,7 +270,8 @@ i830_unbind_memory(ScrnInfoPtr pScrn, i830_memory *mem)
     if (mem == NULL || !mem->bound)
 	return TRUE;
 
-    if (mem->tiling != TILE_NONE && !pI830->use_drm_mode)
+    if (mem->tiling != TILE_NONE && !pI830->use_drm_mode &&
+	!pI830->kernel_exec_fencing)
 	i830_clear_tiling(pScrn, mem->fence_nr);
 
 #ifdef XF86DRI
commit 28319d60aa2d793c209043c1ce2d38b14c66a4be
Author: Zhenyu Wang <zhenyu.z.wang at intel.com>
Date:   Fri Mar 20 13:14:15 2009 +0800

    Add a lid status test program "intel_lid"

diff --git a/src/reg_dumper/Makefile.am b/src/reg_dumper/Makefile.am
index b04395a..fa2defd 100644
--- a/src/reg_dumper/Makefile.am
+++ b/src/reg_dumper/Makefile.am
@@ -3,7 +3,8 @@ noinst_PROGRAMS = intel_reg_dumper \
 	intel_idle \
 	intel_stepping \
 	intel_statuspage \
-	intel_hotplug
+	intel_hotplug \
+	intel_lid
 
 intel_reg_dumper_SOURCES = \
 	main.c \
@@ -36,12 +37,18 @@ intel_statuspage_SOURCES = \
 	reg_dumper.h \
 	util.c
 
+intel_lid_SOURCES = \
+	lid.c \
+	reg_dumper.h \
+	util.c
+
 intel_hotplug_LDADD = $(PCIACCESS_LIBS)
 intel_reg_dumper_LDADD = $(PCIACCESS_LIBS)
 intel_gtt_LDADD = $(PCIACCESS_LIBS)
 intel_idle_LDADD = $(PCIACCESS_LIBS)
 intel_stepping_LDADD = $(PCIACCESS_LIBS)
 intel_statuspage_LDADD = $(PCIACCESS_LIBS)
+intel_lid_LDADD = $(PCIACCESS_LIBS)
 
 AM_CFLAGS = $(PCIACCESS_CFLAGS) $(WARN_CFLAGS) \
 	-I$(srcdir)/.. -DREG_DUMPER
diff --git a/src/reg_dumper/lid.c b/src/reg_dumper/lid.c
new file mode 100644
index 0000000..771d67d
--- /dev/null
+++ b/src/reg_dumper/lid.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Zhenyu Wang <zhenyu.z.wang at intel.com>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <pciaccess.h>
+#include <err.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "reg_dumper.h"
+#include "../i810_reg.h"
+#include "../i830_bios.h"
+
+enum lid_status {
+    LID_UNKNOWN = -1,
+    LID_OPEN,
+    LID_CLOSE,
+};
+
+#define ACPI_BUTTON "/proc/acpi/button/"
+#define ACPI_LID "/proc/acpi/button/lid/"
+
+static int
+i830_lvds_acpi_lid_state(void)
+{
+    int fd;
+    DIR *button_dir;
+    DIR *lid_dir;
+    struct dirent *lid_dent;
+    char *state_name;
+    char state[64];
+    enum lid_status ret = LID_UNKNOWN;
+
+    button_dir = opendir(ACPI_BUTTON);
+    /* If acpi button driver is not loaded, bypass ACPI check method */
+    if (button_dir == NULL)
+	goto out;
+    closedir(button_dir);
+
+    lid_dir = opendir(ACPI_LID);
+
+    /* no acpi lid object found */
+    if (lid_dir == NULL)
+	goto out;
+
+    while (1) {
+	lid_dent = readdir(lid_dir);
+	if (lid_dent == NULL) {
+	    /* no LID object */
+	    closedir(lid_dir);
+	    goto out;
+	}
+	if (strcmp(lid_dent->d_name, ".") &&
+		strcmp(lid_dent->d_name, "..")) {
+	    break;
+	}
+    }
+    state_name = malloc(strlen(ACPI_LID) + strlen(lid_dent->d_name) + 7);
+    memset(state_name, 0, sizeof(state_name));
+    strcat(state_name, ACPI_LID);
+    strcat(state_name, lid_dent->d_name);
+    strcat(state_name, "/state");
+
+    closedir(lid_dir);
+
+    if ((fd = open(state_name, O_RDONLY)) == -1) {
+	free(state_name);
+	goto out;
+    }
+    free(state_name);
+    if (read(fd, state, 64) == -1) {
+	close(fd);
+	goto out;
+    }
+    close(fd);
+    if (strstr(state, "open"))
+	ret = LID_OPEN;
+    else if (strstr(state, "closed"))
+	ret = LID_CLOSE;
+    else /* "unsupported" */
+	ret = LID_UNKNOWN;
+
+out:
+    return ret;
+}
+
+int main(int argc, char **argv)
+{
+    I830Rec i830;
+    I830Ptr pI830 = &i830;
+    int swf14, acpi_lid;
+
+    intel_i830rec_init(pI830);
+
+    while (1) {
+	swf14 = INREG(SWF14);
+
+	printf("Intel LVDS Lid status:\n");
+	printf("\tSWF14(0x%x) : %s\n", swf14, swf14 & SWF14_LID_SWITCH_EN ? "close" : "open");
+
+	acpi_lid = i830_lvds_acpi_lid_state();
+	switch (acpi_lid) {
+	    case LID_UNKNOWN:
+		printf("\tACPI Lid state : unknown\n");
+		break;
+	    case LID_OPEN:
+		printf("\tACPI Lid state : open\n");
+		break;
+	    case LID_CLOSE:
+		printf("\tACPI Lid state : close\n");
+		break;
+	}
+	sleep(2);
+    }
+    return 0;
+}
commit 636d252f3b1eac687f7b11952e949c383cb86ed4
Author: Jesse Barnes <jbarnes at nietzche.localdomain>
Date:   Thu Mar 19 13:25:29 2009 -0700

    Don't install fences if the kernel is managing them
    
    If execbuffer is setting up fences, it also means that the kernel is
    managing them at pin time, so installing one in the 2D driver in that
    case is an error.  The fence should stick around as long as the buffer
    is pinned (the kernel won't steal these), though it will be freed at
    leavevt and re-allocated at entervt.
    
    On 965+ chips, the pin ioctl will *not* install a fence reg, but that's
    also ok because all 965+ operations include tiling bits, and sw
    fallbacks will be protected by prepare/finish access hooks, which will
    either access the backing store or use the GTT, which will ensure proper
    fencing at fault time.
    
    Fixes #20265.
    
    Acked-by: Eric Anholt <eric at anholt.net>

diff --git a/src/i830_memory.c b/src/i830_memory.c
index 96e1763..36dab11 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -253,7 +253,8 @@ i830_bind_memory(ScrnInfoPtr pScrn, i830_memory *mem)
 	mem->bound = TRUE;
     }
 
-    if (mem->tiling != TILE_NONE && !pI830->use_drm_mode) {
+    if (mem->tiling != TILE_NONE && !pI830->use_drm_mode &&
+	!pI830->kernel_exec_fencing) {
 	mem->fence_nr = i830_set_tiling(pScrn, mem->offset, mem->pitch,
 					mem->allocated_size, mem->tiling);
     }
@@ -532,12 +533,8 @@ i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset, unsigned long size)
 		int ret;
 
 		sp.param = I915_SETPARAM_NUM_USED_FENCES;
-		if (pI830->use_drm_mode)
-		    sp.value = 0; /* kernel gets them all */
-		else if (pI830->directRenderingType == DRI_XF86DRI)
-		    sp.value = 3; /* front/back/depth */
-		else
-		    sp.value = 2; /* just front for DRI2 (both old & new though) */
+		sp.value = 0; /* kernel gets them all */
+
 		ret = drmCommandWrite(pI830->drmSubFD, DRM_I915_SETPARAM, &sp,
 				      sizeof(sp));
 		if (ret == 0)
commit d92e6158c86d7da873913461ef7e828bd411d8c4
Author: Carl Worth <cworth at cworth.org>
Date:   Thu Mar 19 10:06:03 2009 -0700

    Revert the rest of the EXA_VERSION_MAJOR bump
    
    This was mistakenly added in the unrelated change in revision
    fe08b81d0f5d6f96e0124e6286bd24aba6e140ad
    and wasn't completely reverted in the later revision
    78a60e1b66fe2e8449702dd43d9b062d279af8f1

diff --git a/src/i830_exa.c b/src/i830_exa.c
index 18d8cde..0a22486 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -675,10 +675,6 @@ I830EXAInit(ScreenPtr pScreen)
     memset(pI830->EXADriverPtr, 0, sizeof(*pI830->EXADriverPtr));
 
     pI830->bufferOffset = 0;
-#if EXA_VERSION_MAJOR > 2
-    pI830->EXADriverPtr->exa_major = 3;
-    pI830->EXADriverPtr->exa_minor = 0;
-#else
     pI830->EXADriverPtr->exa_major = 2;
     /* If compiled against EXA 2.2, require 2.2 so we can use the
      * PixmapIsOffscreen hook.
@@ -691,7 +687,6 @@ I830EXAInit(ScreenPtr pScreen)
 	       "EXA compatibility mode.  Output rotation rendering "
 	       "performance may suffer\n");
 #endif
-#endif
     if (!pI830->use_drm_mode) {
 	pI830->EXADriverPtr->memoryBase = pI830->FbBase;
 	if (pI830->exa_offscreen) {
commit 85e6b528582c2397ee9eb2132cd0d05ce12eb43d
Author: Ma Ling <ling.ma at intel.com>
Date:   Thu Mar 19 09:10:19 2009 -0700

    Set SSC frequency for 8xx chips correctly
    
    All 8xx class chips have the 66/48 split, not just 855.
    
    Fixes #18358.

diff --git a/src/i830_bios.c b/src/i830_bios.c
index 7f20553..9b13bf4 100644
--- a/src/i830_bios.c
+++ b/src/i830_bios.c
@@ -161,7 +161,7 @@ parse_general_features(I830Ptr pI830, struct bdb_header *bdb)
     pI830->tv_present = general->int_tv_support;
     pI830->lvds_use_ssc = general->enable_ssc;
     if (pI830->lvds_use_ssc) {
-	if (IS_I855(pI830))
+	if (IS_I85X(pI830))
 	    pI830->lvds_ssc_freq = general->ssc_freq ? 66 : 48;
 	else
 	    pI830->lvds_ssc_freq = general->ssc_freq ? 100 : 96;
commit bedc894a565ce3c7a50990e3f78953fc2432ad40
Author: Jesse Barnes <jbarnes at nietzche.localdomain>
Date:   Wed Mar 18 20:19:44 2009 -0700

    Re-enable disabled outputs after rotation
    
    The server may have made a DPMS call before doing rotation, so after we
    do the mode set with the rotated framebuffer, we need to re-enable the
    corresponding output(s).
    
    Fixes bug #20573.

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 141c027..e485256 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -60,6 +60,9 @@ typedef struct {
 } drmmode_output_private_rec, *drmmode_output_private_ptr;
 
 static void
+drmmode_output_dpms(xf86OutputPtr output, int mode);
+
+static void
 drmmode_ConvertFromKMode(ScrnInfoPtr scrn,
 			 drmModeModeInfoPtr kmode,
 			 DisplayModePtr	mode)
@@ -210,6 +213,16 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 	else
 		ret = TRUE;
 
+	/* Turn on any outputs on this crtc that may have been disabled */
+	for (i = 0; i < xf86_config->num_output; i++) {
+		xf86OutputPtr output = xf86_config->output[i];
+
+		if (output->crtc != crtc)
+			continue;
+
+		drmmode_output_dpms(output, DPMSModeOn);
+	}
+
 done:
 	if (!ret) {
 		crtc->x = saved_x;
commit 6deb26ae7bd796e88a5dd90df5f6c35fbc44e798
Author: Jesse Barnes <jbarnes at virtuousgeek.org>
Date:   Wed Mar 18 09:36:58 2009 -0700

    Create known output configuration at EnterVT time
    
    Since we added the pipe A force quirk (leaving pipe A on all the time),
    DPMS calls to disable it have silently returned, leaving the pipe on.
    If another driver (like vesafb) has enabled it, we may end up with a bad
    configuration, leading to hangs or blank screens at VT switch time.
    
    Fixes bug #19603.

diff --git a/src/i830_display.c b/src/i830_display.c
index e6fdff9..a44143f 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -1121,14 +1121,8 @@ i830_disable_vga_plane (xf86CrtcPtr crtc)
 
 }
 
-/**
- * Sets the power management mode of the pipe and plane.
- *
- * This code should probably grow support for turning the cursor off and back
- * on appropriately at the same time as we're turning the pipe off/on.
- */
-static void
-i830_crtc_dpms(xf86CrtcPtr crtc, int mode)
+void
+i830_crtc_enable(xf86CrtcPtr crtc)
 {
     ScrnInfoPtr pScrn = crtc->scrn;
     I830Ptr pI830 = I830PTR(pScrn);
@@ -1141,112 +1135,148 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mode)
     int dspbase_reg = (plane == 0) ? DSPABASE : DSPBBASE;
     uint32_t temp;
 
-    /* XXX: When our outputs are all unaware of DPMS modes other than off and
-     * on, we should map those modes to DPMSModeOff in the CRTC.
-     */
-    switch (mode) {
-    case DPMSModeOn:
-    case DPMSModeStandby:
-    case DPMSModeSuspend:
-	/* Enable the DPLL */
-	temp = INREG(dpll_reg);
-	if ((temp & DPLL_VCO_ENABLE) == 0)
-	{
-	    OUTREG(dpll_reg, temp);
-	    POSTING_READ(dpll_reg);
-	    /* Wait for the clocks to stabilize. */
-	    usleep(150);
-	    OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE);
-	    POSTING_READ(dpll_reg);
-	    /* Wait for the clocks to stabilize. */
-	    usleep(150);
-	    OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE);
-	    POSTING_READ(dpll_reg);
-	    /* Wait for the clocks to stabilize. */
-	    usleep(150);
-	}
+    /* Enable the DPLL */
+    temp = INREG(dpll_reg);
+    if ((temp & DPLL_VCO_ENABLE) == 0)
+    {
+	OUTREG(dpll_reg, temp);
+	POSTING_READ(dpll_reg);
+	/* Wait for the clocks to stabilize. */
+	usleep(150);
+	OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE);
+	POSTING_READ(dpll_reg);
+	/* Wait for the clocks to stabilize. */
+	usleep(150);
+	OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE);
+	POSTING_READ(dpll_reg);
+	/* Wait for the clocks to stabilize. */
+	usleep(150);
+    }
 
-	/* Enable the pipe */
-	temp = INREG(pipeconf_reg);
-	if ((temp & PIPEACONF_ENABLE) == 0)
-	    OUTREG(pipeconf_reg, temp | PIPEACONF_ENABLE);
+    /* Enable the pipe */
+    temp = INREG(pipeconf_reg);
+    if ((temp & PIPEACONF_ENABLE) == 0)
+	OUTREG(pipeconf_reg, temp | PIPEACONF_ENABLE);
 
-	/* Enable the plane */
-	temp = INREG(dspcntr_reg);
-	if ((temp & DISPLAY_PLANE_ENABLE) == 0)
-	{
-	    OUTREG(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE);
-	    /* Flush the plane changes */
-	    OUTREG(dspbase_reg, INREG(dspbase_reg));
-	}
+    /* Enable the plane */
+    temp = INREG(dspcntr_reg);
+    if ((temp & DISPLAY_PLANE_ENABLE) == 0)
+    {
+	OUTREG(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE);
+	/* Flush the plane changes */
+	OUTREG(dspbase_reg, INREG(dspbase_reg));
+    }
 
-	i830_crtc_load_lut(crtc);
+    i830_crtc_load_lut(crtc);
 
-	/* Give the overlay scaler a chance to enable if it's on this pipe */
-	i830_crtc_dpms_video(crtc, TRUE);
+    /* Give the overlay scaler a chance to enable if it's on this pipe */
+    i830_crtc_dpms_video(crtc, TRUE);
 
-	/* Reenable compression if needed */
-	if (i830_use_fb_compression(crtc))
-	    i830_enable_fb_compression(crtc);
-	i830_modeset_ctl(crtc, 0);
-	break;
-    case DPMSModeOff:
-	i830_modeset_ctl(crtc, 1);
-	/* Shut off compression if in use */
-	if (i830_use_fb_compression(crtc))
-	    i830_disable_fb_compression(crtc);
+    /* Reenable compression if needed */
+    if (i830_use_fb_compression(crtc))
+	i830_enable_fb_compression(crtc);
+    i830_modeset_ctl(crtc, 0);
+}
 
-	/* Give the overlay scaler a chance to disable if it's on this pipe */
-	i830_crtc_dpms_video(crtc, FALSE);
+void
+i830_crtc_disable(xf86CrtcPtr crtc, Bool disable_pipe)
+{
+    ScrnInfoPtr pScrn = crtc->scrn;
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+    int pipe = intel_crtc->pipe;
+    int plane = intel_crtc->plane;
+    int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
+    int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
+    int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
+    int dspbase_reg = (plane == 0) ? DSPABASE : DSPBBASE;
+    uint32_t temp;
 
-	/* 
-	 * The documentation says :
-	 * - Disable planes (VGA or hires)
-	 * - Disable pipe
-	 * - Disable VGA display
-	 */
+    i830_modeset_ctl(crtc, 1);
+    /* Shut off compression if in use */
+    if (i830_use_fb_compression(crtc))
+	i830_disable_fb_compression(crtc);
 
-	/* Disable display plane */
-	temp = INREG(dspcntr_reg);
-	if ((temp & DISPLAY_PLANE_ENABLE) != 0)
-	{
-	    OUTREG(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
-	    /* Flush the plane changes */
-	    OUTREG(dspbase_reg, INREG(dspbase_reg));
-	    POSTING_READ(dspbase_reg);
-	}
+    /* Give the overlay scaler a chance to disable if it's on this pipe */
+    i830_crtc_dpms_video(crtc, FALSE);
 
-	if (!IS_I9XX(pI830)) {
-	    /* Wait for vblank for the disable to take effect */
-	    i830WaitForVblank(pScrn);
-	}
+    /* 
+     * The documentation says :
+     * - Disable planes (VGA or hires)
+     * - Disable pipe
+     * - Disable VGA display
+     */
 
-	/* May need to leave pipe A on */
-	if ((pipe != 0) || !(pI830->quirk_flag & QUIRK_PIPEA_FORCE))
-	{
-		/* Next, disable display pipes */
-		temp = INREG(pipeconf_reg);
-		if ((temp & PIPEACONF_ENABLE) != 0) {
-		    OUTREG(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
-		    POSTING_READ(pipeconf_reg);
-		}
+    /* Disable display plane */
+    temp = INREG(dspcntr_reg);
+    if ((temp & DISPLAY_PLANE_ENABLE) != 0)
+    {
+	OUTREG(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
+	/* Flush the plane changes */
+	OUTREG(dspbase_reg, INREG(dspbase_reg));
+	POSTING_READ(dspbase_reg);
+    }
 
-		/* Wait for vblank for the disable to take effect. */
-		i830WaitForVblank(pScrn);
+    if (!IS_I9XX(pI830)) {
+	/* Wait for vblank for the disable to take effect */
+	i830WaitForVblank(pScrn);
+    }
 
-		temp = INREG(dpll_reg);
-		if ((temp & DPLL_VCO_ENABLE) != 0) {
-		    OUTREG(dpll_reg, temp & ~DPLL_VCO_ENABLE);
-		    POSTING_READ(dpll_reg);
-		}
+    /* May need to leave pipe A on */
+    if (disable_pipe)
+    {
+	/* Next, disable display pipes */
+	temp = INREG(pipeconf_reg);
+	if ((temp & PIPEACONF_ENABLE) != 0) {
+	    OUTREG(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
+	    POSTING_READ(pipeconf_reg);
+	}
 
-		/* Wait for the clocks to turn off. */
-		usleep(150);
+	/* Wait for vblank for the disable to take effect. */
+	i830WaitForVblank(pScrn);
+
+	temp = INREG(dpll_reg);
+	if ((temp & DPLL_VCO_ENABLE) != 0) {
+	    OUTREG(dpll_reg, temp & ~DPLL_VCO_ENABLE);
+	    POSTING_READ(dpll_reg);
 	}
 
-	/* Disable the VGA plane that we never use. */
-	i830_disable_vga_plane (crtc);
+	/* Wait for the clocks to turn off. */
+	usleep(150);
+    }
 
+    /* Disable the VGA plane that we never use. */
+    i830_disable_vga_plane (crtc);
+}
+
+/**
+ * Sets the power management mode of the pipe and plane.
+ *
+ * This code should probably grow support for turning the cursor off and back
+ * on appropriately at the same time as we're turning the pipe off/on.
+ */
+static void
+i830_crtc_dpms(xf86CrtcPtr crtc, int mode)
+{
+    ScrnInfoPtr pScrn = crtc->scrn;
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+    int pipe = intel_crtc->pipe;
+    Bool disable_pipe = TRUE;
+
+    /* XXX: When our outputs are all unaware of DPMS modes other than off and
+     * on, we should map those modes to DPMSModeOff in the CRTC.
+     */
+    switch (mode) {
+    case DPMSModeOn:
+    case DPMSModeStandby:
+    case DPMSModeSuspend:
+	i830_crtc_enable(crtc);
+	break;
+    case DPMSModeOff:
+	if ((pipe == 0) && (pI830->quirk_flag & QUIRK_PIPEA_FORCE))
+	    disable_pipe = FALSE;
+	i830_crtc_disable(crtc, disable_pipe);
 	break;
     }
 
diff --git a/src/i830_display.h b/src/i830_display.h
index 8d767b1..0ba196d 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -32,6 +32,8 @@ void i830PipeSetBase(xf86CrtcPtr crtc, int x, int y);
 void i830WaitForVblank(ScrnInfoPtr pScrn);
 void i830DescribeOutputConfiguration(ScrnInfoPtr pScrn);
 void i830_set_new_crtc_bo(ScrnInfoPtr pScrn);
+void i830_crtc_disable(xf86CrtcPtr crtc, Bool disable_pipe);
+void i830_crtc_enable(xf86CrtcPtr crtc);
 
 xf86CrtcPtr i830GetLoadDetectPipe(xf86OutputPtr output, DisplayModePtr mode, int *dpms_mode);
 void i830ReleaseLoadDetectPipe(xf86OutputPtr output, int dpms_mode);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index c19fcc6..7502d30 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2275,7 +2275,7 @@ RestoreHWState(ScrnInfoPtr pScrn)
    /* Disable pipes */
    for (i = 0; i < xf86_config->num_crtc; i++) {
       xf86CrtcPtr crtc = xf86_config->crtc[i];
-      crtc->funcs->dpms(crtc, DPMSModeOff);
+      i830_crtc_disable(crtc, TRUE);
    }
    i830WaitForVblank(pScrn);
 
@@ -3460,8 +3460,9 @@ static Bool
 I830EnterVT(int scrnIndex, int flags)
 {
    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+   xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
    I830Ptr  pI830 = I830PTR(pScrn);
-   int ret;
+   int i, ret;
 
    DPRINTF(PFX, "Enter VT\n");
 
@@ -3482,6 +3483,23 @@ I830EnterVT(int scrnIndex, int flags)
 	  SaveHWState(pScrn);
    }
 
+   /* Get the hardware into a known state if needed */
+   if (!pI830->use_drm_mode) {
+       /* Disable outputs */
+       for (i = 0; i < xf86_config->num_output; i++) {
+	   xf86OutputPtr   output = xf86_config->output[i];
+	   output->funcs->dpms(output, DPMSModeOff);
+       }
+       i830WaitForVblank(pScrn);
+
+       /* Disable pipes */
+       for (i = 0; i < xf86_config->num_crtc; i++) {
+	   xf86CrtcPtr crtc = xf86_config->crtc[i];
+	   i830_crtc_disable(crtc, TRUE);
+       }
+       i830WaitForVblank(pScrn);
+   }
+
    pI830->leaving = FALSE;
 
    if (!pI830->use_drm_mode)
commit 7c94227dd4fa2164bebb36234958053bf1d26c12
Author: Ma Ling <ling.ma at intel.com>
Date:   Tue Mar 17 10:33:15 2009 +0800

    Use best PLL timing values for G4X platform
    
    construct function to find precise parameters from internal spreadsheet
    table on G4X platform.
    
    Signed-off-by: Ma Ling <ling.ma at intel.com>

diff --git a/src/i830_display.c b/src/i830_display.c
index fb48a4d..e6fdff9 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -67,10 +67,13 @@ typedef struct {
 
 #define INTEL_P2_NUM		      2
 
-typedef struct {
+typedef struct intel_limit intel_limit_t;
+struct intel_limit {
     intel_range_t   dot, vco, n, m, m1, m2, p, p1;
     intel_p2_t	    p2;
-} intel_limit_t;
+    Bool (* find_pll)(const intel_limit_t *, xf86CrtcPtr,
+                      int, int, intel_clock_t *);
+};
 
 #define I8XX_DOT_MIN		  25000
 #define I8XX_DOT_MAX		 350000
@@ -236,6 +239,13 @@ typedef struct {
 #define G4X_P2_DUAL_LVDS_FAST           7
 #define G4X_P2_DUAL_LVDS_LIMIT          0
 
+static Bool
+intel_find_pll_i8xx_and_i9xx(const intel_limit_t *, xf86CrtcPtr,
+                             int, int, intel_clock_t *);
+static Bool
+intel_find_pll_g4x(const intel_limit_t *, xf86CrtcPtr,
+                   int, int, intel_clock_t *);
+
 static const intel_limit_t intel_limits[] = {
     { /* INTEL_LIMIT_I8XX_DVO_DAC */
         .dot = { .min = I8XX_DOT_MIN,		.max = I8XX_DOT_MAX },
@@ -248,6 +258,7 @@ static const intel_limit_t intel_limits[] = {
         .p1  = { .min = I8XX_P1_MIN,		.max = I8XX_P1_MAX },
 	.p2  = { .dot_limit = I8XX_P2_SLOW_LIMIT,
 		 .p2_slow = I8XX_P2_SLOW,	.p2_fast = I8XX_P2_FAST },
+        .find_pll = intel_find_pll_i8xx_and_i9xx,
     },
     { /* INTEL_LIMIT_I8XX_LVDS */
         .dot = { .min = I8XX_DOT_MIN,		.max = I8XX_DOT_MAX },
@@ -260,6 +271,7 @@ static const intel_limit_t intel_limits[] = {
         .p1  = { .min = I8XX_P1_LVDS_MIN,	.max = I8XX_P1_LVDS_MAX },
 	.p2  = { .dot_limit = I8XX_P2_SLOW_LIMIT,
 		 .p2_slow = I8XX_P2_LVDS_SLOW,	.p2_fast = I8XX_P2_LVDS_FAST },
+        .find_pll = intel_find_pll_i8xx_and_i9xx,
     },
     { /* INTEL_LIMIT_I9XX_SDVO_DAC */
         .dot = { .min = I9XX_DOT_MIN,		.max = I9XX_DOT_MAX },
@@ -272,6 +284,7 @@ static const intel_limit_t intel_limits[] = {
         .p1  = { .min = I9XX_P1_MIN,		.max = I9XX_P1_MAX },
 	.p2  = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT,
 		 .p2_slow = I9XX_P2_SDVO_DAC_SLOW,	.p2_fast = I9XX_P2_SDVO_DAC_FAST },
+        .find_pll = intel_find_pll_i8xx_and_i9xx,
     },
     { /* INTEL_LIMIT_I9XX_LVDS */
         .dot = { .min = I9XX_DOT_MIN,		.max = I9XX_DOT_MAX },
@@ -287,6 +300,7 @@ static const intel_limit_t intel_limits[] = {
 	 */
 	.p2  = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
 		 .p2_slow = I9XX_P2_LVDS_SLOW,	.p2_fast = I9XX_P2_LVDS_FAST },
+        .find_pll = intel_find_pll_i8xx_and_i9xx,
     },
     { /* INTEL_LIMIT_IGD_SDVO */
         .dot = { .min = I9XX_DOT_MIN,		.max = I9XX_DOT_MAX},
@@ -299,6 +313,7 @@ static const intel_limit_t intel_limits[] = {
         .p1  = { .min = I9XX_P1_MIN,		.max = I9XX_P1_MAX },
 	.p2  = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT,
 		 .p2_slow = I9XX_P2_SDVO_DAC_SLOW,	.p2_fast = I9XX_P2_SDVO_DAC_FAST },
+        .find_pll = intel_find_pll_i8xx_and_i9xx,
     },
     { /* INTEL_LIMIT_IGD_LVDS */
         .dot = { .min = I9XX_DOT_MIN,		.max = I9XX_DOT_MAX },
@@ -312,6 +327,7 @@ static const intel_limit_t intel_limits[] = {
 	/* IGD only supports single-channel mode. */
 	.p2  = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
 		 .p2_slow = I9XX_P2_LVDS_SLOW,	.p2_fast = I9XX_P2_LVDS_SLOW },
+        .find_pll = intel_find_pll_i8xx_and_i9xx,
     },
     /* below parameter and function is for G4X Chipset Family*/
     {   /* INTEL_LIMIT_G4X_SDVO */
@@ -326,6 +342,7 @@ static const intel_limit_t intel_limits[] = {
         .p2  = { .dot_limit = G4X_P2_SDVO_LIMIT,
                  .p2_slow = G4X_P2_SDVO_SLOW,
                  .p2_fast = G4X_P2_SDVO_FAST },
+        .find_pll = intel_find_pll_g4x,
     },
     {   /* INTEL_LIMIT_G4X_HDMI_DAC */
         .dot = { .min = G4X_DOT_HDMI_DAC_MIN,	.max = G4X_DOT_HDMI_DAC_MAX },
@@ -339,6 +356,7 @@ static const intel_limit_t intel_limits[] = {
         .p2  = { .dot_limit = G4X_P2_HDMI_DAC_LIMIT,
                  .p2_slow = G4X_P2_HDMI_DAC_SLOW,
                  .p2_fast = G4X_P2_HDMI_DAC_FAST },
+        .find_pll = intel_find_pll_g4x,
     },
     {   /* INTEL_LIMIT_G4X_SINGLE_LVDS */
         .dot = { .min = G4X_DOT_SINGLE_LVDS_MIN,
@@ -360,6 +378,7 @@ static const intel_limit_t intel_limits[] = {
         .p2  = { .dot_limit = G4X_P2_SINGLE_LVDS_LIMIT,
                  .p2_slow = G4X_P2_SINGLE_LVDS_SLOW,
                  .p2_fast = G4X_P2_SINGLE_LVDS_FAST },
+        .find_pll = intel_find_pll_g4x,
     },
     {   /* INTEL_LIMIT_G4X_DUAL_LVDS */
         .dot = { .min = G4X_DOT_DUAL_LVDS_MIN,
@@ -381,6 +400,7 @@ static const intel_limit_t intel_limits[] = {
         .p2  = { .dot_limit = G4X_P2_DUAL_LVDS_LIMIT,
                  .p2_slow = G4X_P2_DUAL_LVDS_SLOW,
                  .p2_fast = G4X_P2_DUAL_LVDS_FAST },
+        .find_pll = intel_find_pll_g4x,
     },
 };
 
@@ -547,18 +567,13 @@ i830PllIsValid(xf86CrtcPtr crtc, intel_clock_t *clock)
     return TRUE;
 }
 
-/**
- * Returns a set of divisors for the desired target clock with the given
- * refclk, or FALSE.  The returned values represent the clock equation:
- * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
- */
 static Bool
-i830FindBestPLL(xf86CrtcPtr crtc, int target, int refclk, intel_clock_t *best_clock)
+intel_find_pll_i8xx_and_i9xx(const intel_limit_t * limit, xf86CrtcPtr crtc,
+	                     int target, int refclk, intel_clock_t *best_clock)
 {
     ScrnInfoPtr pScrn = crtc->scrn;
     I830Ptr pI830 = I830PTR(pScrn);
-    intel_clock_t   clock;
-    const intel_limit_t   *limit = intel_limit (crtc);
+    intel_clock_t clock;
     int err = target;
 
     if (i830PipeHasType(crtc, I830_OUTPUT_LVDS))
@@ -610,6 +625,64 @@ i830FindBestPLL(xf86CrtcPtr crtc, int target, int refclk, intel_clock_t *best_cl
     return (err != target);
 }
 
+static Bool
+intel_find_pll_g4x(const intel_limit_t * limit, xf86CrtcPtr crtc,
+                   int target, int refclk, intel_clock_t *best_clock)
+{
+    ScrnInfoPtr pScrn = crtc->scrn;
+    I830Ptr pI830 = I830PTR(pScrn);
+    intel_clock_t clock;
+    int  max_n;
+    Bool found = FALSE;
+    int err_most = target * 0.0048;
+
+    if (i830PipeHasType(crtc, I830_OUTPUT_LVDS))
+    {
+        /* For LVDS, if the panel is on, just rely on its current settings for
+         * dual-channel.  We haven't figured out how to reliably set up
+         * different single/dual channel state, if we even can.
+         */
+        if ((INREG(LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP)
+            clock.p2 = limit->p2.p2_fast;
+        else
+            clock.p2 = limit->p2.p2_slow;
+    } else {
+        if (target < limit->p2.dot_limit)
+            clock.p2 = limit->p2.p2_slow;
+        else
+            clock.p2 = limit->p2.p2_fast;
+    }
+
+    max_n = limit->n.max;
+    /* based on hardware requirement prefer smaller n to precision */
+    for (clock.n = limit->n.min; clock.n <= max_n; clock.n++) {
+        /* based on hardware requirement prefere larger m1,m2, p1*/
+        for (clock.m1 = limit->m1.max;
+            clock.m1 >= limit->m1.min; clock.m1--) {
+            for (clock.m2 = limit->m2.max;
+                clock.m2 >= limit->m2.min; clock.m2--) {
+                for (clock.p1 = limit->p1.max;
+                    clock.p1 >= limit->p1.min; clock.p1--) {
+                    int this_err;
+
+                    intel_clock (pI830, refclk, &clock);
+                    if (!i830PllIsValid(crtc, &clock))
+                        continue;
+                    this_err = abs(clock.dot - target) ;
+                    if (this_err < err_most) {
+                        memcpy(best_clock, &clock, sizeof(intel_clock_t));
+                        err_most = this_err;
+                        /* prefer smaller n to precision */
+                        max_n = clock.n;
+                        found = TRUE;
+                    }
+                }
+            }
+        }
+    }
+    return found;
+}
+
 void
 i830WaitForVblank(ScrnInfoPtr pScreen)
 {
@@ -1480,6 +1553,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
     uint32_t dpll = 0, fp = 0, dspcntr, pipeconf, lvds_bits = 0;
     Bool ok, is_sdvo = FALSE, is_dvo = FALSE;
     Bool is_crt = FALSE, is_lvds = FALSE, is_tv = FALSE;
+    const intel_limit_t *limit;
 
     /* Set up some convenient bools for what outputs are connected to
      * our pipe, used in DPLL setup.
@@ -1532,7 +1606,13 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
 	refclk = 48000;
     }
 
-    ok = i830FindBestPLL(crtc, adjusted_mode->Clock, refclk, &clock);
+    /*
+     * Returns a set of divisors for the desired target clock with the given
+     * refclk, or FALSE.  The returned values represent the clock equation:
+     * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
+     */
+    limit = intel_limit (crtc);
+    ok = limit->find_pll(limit, crtc, adjusted_mode->Clock, refclk, &clock);
     if (!ok)
 	FatalError("Couldn't find PLL settings for mode!\n");
 
commit 48db5bde9298f1126dfb42f4be8a3d61166abfd8
Author: Ma Ling <ling.ma at intel.com>
Date:   Tue Mar 17 10:41:02 2009 +0800

    Define documented PLL timing limits for G4X platform
    
    These timings on G4X platform were specified by internal spreadsheet from the chipset group.
    
    Signed-off-by: Ma Ling <ling.ma at intel.com>

diff --git a/src/i830_display.c b/src/i830_display.c
index ca55906..fb48a4d 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -153,6 +153,88 @@ typedef struct {
 #define INTEL_LIMIT_I9XX_LVDS	    3
 #define INTEL_LIMIT_IGD_SDVO_DAC    4
 #define INTEL_LIMIT_IGD_LVDS	    5
+#define INTEL_LIMIT_G4X_SDVO	    6
+#define INTEL_LIMIT_G4X_HDMI_DAC    7
+#define INTEL_LIMIT_G4X_SINGLE_LVDS 8
+#define INTEL_LIMIT_G4X_DUAL_LVDS   9
+
+/*The parameter is for SDVO on G4x platform*/
+#define G4X_VCO_MIN                1750000
+#define G4X_VCO_MAX                3500000
+#define G4X_DOT_SDVO_MIN           25000
+#define G4X_DOT_SDVO_MAX           270000
+#define G4X_N_SDVO_MIN             1
+#define G4X_N_SDVO_MAX             4
+#define G4X_M_SDVO_MIN             104
+#define G4X_M_SDVO_MAX             138
+#define G4X_M1_SDVO_MIN            17
+#define G4X_M1_SDVO_MAX            23
+#define G4X_M2_SDVO_MIN            5
+#define G4X_M2_SDVO_MAX            11
+#define G4X_P_SDVO_MIN             10
+#define G4X_P_SDVO_MAX             30
+#define G4X_P1_SDVO_MIN            1
+#define G4X_P1_SDVO_MAX            3
+#define G4X_P2_SDVO_SLOW           10
+#define G4X_P2_SDVO_FAST           10
+#define G4X_P2_SDVO_LIMIT          270000
+
+/*The parameter is for HDMI_DAC on G4x platform*/
+#define G4X_DOT_HDMI_DAC_MIN           22000
+#define G4X_DOT_HDMI_DAC_MAX           400000
+#define G4X_N_HDMI_DAC_MIN             1
+#define G4X_N_HDMI_DAC_MAX             4
+#define G4X_M_HDMI_DAC_MIN             104
+#define G4X_M_HDMI_DAC_MAX             138
+#define G4X_M1_HDMI_DAC_MIN            16
+#define G4X_M1_HDMI_DAC_MAX            23
+#define G4X_M2_HDMI_DAC_MIN            5
+#define G4X_M2_HDMI_DAC_MAX            11
+#define G4X_P_HDMI_DAC_MIN             5
+#define G4X_P_HDMI_DAC_MAX             80
+#define G4X_P1_HDMI_DAC_MIN            1
+#define G4X_P1_HDMI_DAC_MAX            8
+#define G4X_P2_HDMI_DAC_SLOW           10
+#define G4X_P2_HDMI_DAC_FAST           5
+#define G4X_P2_HDMI_DAC_LIMIT          165000
+
+/*The parameter is for SINGLE_LVDS on G4x platform*/
+#define G4X_DOT_SINGLE_LVDS_MIN           20000
+#define G4X_DOT_SINGLE_LVDS_MAX           115000
+#define G4X_N_SINGLE_LVDS_MIN             1
+#define G4X_N_SINGLE_LVDS_MAX             3
+#define G4X_M_SINGLE_LVDS_MIN             104
+#define G4X_M_SINGLE_LVDS_MAX             138
+#define G4X_M1_SINGLE_LVDS_MIN            17
+#define G4X_M1_SINGLE_LVDS_MAX            23
+#define G4X_M2_SINGLE_LVDS_MIN            5
+#define G4X_M2_SINGLE_LVDS_MAX            11
+#define G4X_P_SINGLE_LVDS_MIN             28
+#define G4X_P_SINGLE_LVDS_MAX             112
+#define G4X_P1_SINGLE_LVDS_MIN            2
+#define G4X_P1_SINGLE_LVDS_MAX            8
+#define G4X_P2_SINGLE_LVDS_SLOW           14
+#define G4X_P2_SINGLE_LVDS_FAST           14
+#define G4X_P2_SINGLE_LVDS_LIMIT          0
+
+/*The parameter is for DUAL_LVDS on G4x platform*/
+#define G4X_DOT_DUAL_LVDS_MIN           80000
+#define G4X_DOT_DUAL_LVDS_MAX           224000
+#define G4X_N_DUAL_LVDS_MIN             1
+#define G4X_N_DUAL_LVDS_MAX             3
+#define G4X_M_DUAL_LVDS_MIN             104
+#define G4X_M_DUAL_LVDS_MAX             138
+#define G4X_M1_DUAL_LVDS_MIN            17
+#define G4X_M1_DUAL_LVDS_MAX            23
+#define G4X_M2_DUAL_LVDS_MIN            5
+#define G4X_M2_DUAL_LVDS_MAX            11
+#define G4X_P_DUAL_LVDS_MIN             14
+#define G4X_P_DUAL_LVDS_MAX             42
+#define G4X_P1_DUAL_LVDS_MIN            2
+#define G4X_P1_DUAL_LVDS_MAX            6
+#define G4X_P2_DUAL_LVDS_SLOW           7
+#define G4X_P2_DUAL_LVDS_FAST           7
+#define G4X_P2_DUAL_LVDS_LIMIT          0
 
 static const intel_limit_t intel_limits[] = {
     { /* INTEL_LIMIT_I8XX_DVO_DAC */
@@ -231,15 +313,108 @@ static const intel_limit_t intel_limits[] = {
 	.p2  = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
 		 .p2_slow = I9XX_P2_LVDS_SLOW,	.p2_fast = I9XX_P2_LVDS_SLOW },
     },
+    /* below parameter and function is for G4X Chipset Family*/
+    {   /* INTEL_LIMIT_G4X_SDVO */
+        .dot = { .min = G4X_DOT_SDVO_MIN,       .max = G4X_DOT_SDVO_MAX },
+        .vco = { .min = G4X_VCO_MIN,            .max = G4X_VCO_MAX},
+        .n   = { .min = G4X_N_SDVO_MIN,         .max = G4X_N_SDVO_MAX },
+        .m   = { .min = G4X_M_SDVO_MIN,         .max = G4X_M_SDVO_MAX },
+        .m1  = { .min = G4X_M1_SDVO_MIN,        .max = G4X_M1_SDVO_MAX },
+        .m2  = { .min = G4X_M2_SDVO_MIN,        .max = G4X_M2_SDVO_MAX },
+        .p   = { .min = G4X_P_SDVO_MIN,         .max = G4X_P_SDVO_MAX },
+        .p1  = { .min = G4X_P1_SDVO_MIN,        .max = G4X_P1_SDVO_MAX},
+        .p2  = { .dot_limit = G4X_P2_SDVO_LIMIT,
+                 .p2_slow = G4X_P2_SDVO_SLOW,
+                 .p2_fast = G4X_P2_SDVO_FAST },
+    },
+    {   /* INTEL_LIMIT_G4X_HDMI_DAC */
+        .dot = { .min = G4X_DOT_HDMI_DAC_MIN,	.max = G4X_DOT_HDMI_DAC_MAX },
+        .vco = { .min = G4X_VCO_MIN,	        .max = G4X_VCO_MAX},
+        .n   = { .min = G4X_N_HDMI_DAC_MIN,	.max = G4X_N_HDMI_DAC_MAX },
+        .m   = { .min = G4X_M_HDMI_DAC_MIN,	.max = G4X_M_HDMI_DAC_MAX },
+        .m1  = { .min = G4X_M1_HDMI_DAC_MIN,	.max = G4X_M1_HDMI_DAC_MAX },
+        .m2  = { .min = G4X_M2_HDMI_DAC_MIN,	.max = G4X_M2_HDMI_DAC_MAX },
+        .p   = { .min = G4X_P_HDMI_DAC_MIN,	.max = G4X_P_HDMI_DAC_MAX },
+        .p1  = { .min = G4X_P1_HDMI_DAC_MIN,	.max = G4X_P1_HDMI_DAC_MAX},
+        .p2  = { .dot_limit = G4X_P2_HDMI_DAC_LIMIT,
+                 .p2_slow = G4X_P2_HDMI_DAC_SLOW,
+                 .p2_fast = G4X_P2_HDMI_DAC_FAST },
+    },
+    {   /* INTEL_LIMIT_G4X_SINGLE_LVDS */
+        .dot = { .min = G4X_DOT_SINGLE_LVDS_MIN,
+                 .max = G4X_DOT_SINGLE_LVDS_MAX },
+        .vco = { .min = G4X_VCO_MIN,
+                 .max = G4X_VCO_MAX },
+        .n   = { .min = G4X_N_SINGLE_LVDS_MIN,
+                 .max = G4X_N_SINGLE_LVDS_MAX },
+        .m   = { .min = G4X_M_SINGLE_LVDS_MIN,
+                 .max = G4X_M_SINGLE_LVDS_MAX },
+        .m1  = { .min = G4X_M1_SINGLE_LVDS_MIN,
+                 .max = G4X_M1_SINGLE_LVDS_MAX },
+        .m2  = { .min = G4X_M2_SINGLE_LVDS_MIN,
+                 .max = G4X_M2_SINGLE_LVDS_MAX },
+        .p   = { .min = G4X_P_SINGLE_LVDS_MIN,
+                 .max = G4X_P_SINGLE_LVDS_MAX },
+        .p1  = { .min = G4X_P1_SINGLE_LVDS_MIN,
+                 .max = G4X_P1_SINGLE_LVDS_MAX },
+        .p2  = { .dot_limit = G4X_P2_SINGLE_LVDS_LIMIT,
+                 .p2_slow = G4X_P2_SINGLE_LVDS_SLOW,
+                 .p2_fast = G4X_P2_SINGLE_LVDS_FAST },
+    },
+    {   /* INTEL_LIMIT_G4X_DUAL_LVDS */
+        .dot = { .min = G4X_DOT_DUAL_LVDS_MIN,
+                 .max = G4X_DOT_DUAL_LVDS_MAX },
+        .vco = { .min = G4X_VCO_MIN,
+                 .max = G4X_VCO_MAX},
+        .n   = { .min = G4X_N_DUAL_LVDS_MIN,
+                 .max = G4X_N_DUAL_LVDS_MAX },
+        .m   = { .min = G4X_M_DUAL_LVDS_MIN,
+                 .max = G4X_M_DUAL_LVDS_MAX },
+        .m1  = { .min = G4X_M1_DUAL_LVDS_MIN,
+                 .max = G4X_M1_DUAL_LVDS_MAX },
+        .m2  = { .min = G4X_M2_DUAL_LVDS_MIN,
+                 .max = G4X_M2_DUAL_LVDS_MAX },
+        .p   = { .min = G4X_P_DUAL_LVDS_MIN,
+                 .max = G4X_P_DUAL_LVDS_MAX },
+        .p1  = { .min = G4X_P1_DUAL_LVDS_MIN,
+                 .max = G4X_P1_DUAL_LVDS_MAX},
+        .p2  = { .dot_limit = G4X_P2_DUAL_LVDS_LIMIT,
+                 .p2_slow = G4X_P2_DUAL_LVDS_SLOW,
+                 .p2_fast = G4X_P2_DUAL_LVDS_FAST },
+    },
 };
 
+static const intel_limit_t *intel_limit_g4x (xf86CrtcPtr crtc)
+{
+    ScrnInfoPtr	pScrn = crtc->scrn;
+    I830Ptr	pI830 = I830PTR(pScrn);
+    const intel_limit_t *limit;
+
+    if (i830PipeHasType (crtc, I830_OUTPUT_LVDS)) {
+        if ((INREG(LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP) {
+            /* LVDS with dual channel */
+            limit = &intel_limits[INTEL_LIMIT_G4X_DUAL_LVDS];
+        } else /* LVDS with single channel */
+            limit = &intel_limits[INTEL_LIMIT_G4X_SINGLE_LVDS];
+    } else if (i830PipeHasType (crtc, I830_OUTPUT_HDMI) ||
+               i830PipeHasType (crtc, I830_OUTPUT_ANALOG)) {
+        limit = &intel_limits[INTEL_LIMIT_G4X_HDMI_DAC];
+    } else if (i830PipeHasType (crtc, I830_OUTPUT_SDVO)) {
+        limit = &intel_limits[INTEL_LIMIT_G4X_SDVO];
+    } else /* The option is for other outputs */
+        limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC];
+    return limit;
+}
+
 static const intel_limit_t *intel_limit (xf86CrtcPtr crtc)
 {
     ScrnInfoPtr	pScrn = crtc->scrn;
     I830Ptr	pI830 = I830PTR(pScrn);
     const intel_limit_t *limit;
 
-    if (IS_I9XX(pI830) && !IS_IGD(pI830)) {
+    if (IS_G4X(pI830)) {
+        limit = intel_limit_g4x(crtc);
+    } else if (IS_I9XX(pI830) && !IS_IGD(pI830)) {
 	if (i830PipeHasType (crtc, I830_OUTPUT_LVDS))
 	    limit = &intel_limits[INTEL_LIMIT_I9XX_LVDS];
 	else


More information about the xorg-commit mailing list