xf86-video-intel: Branch 'fbc' - 6 commits - configure.ac .gitignore man/intel.man src/i830_crt.c src/i830_debug.c src/i830_display.c src/i830_driver.c src/i830_dvo.c src/i830.h src/i830_memory.c src/i830_tv.c

Jesse Barnes jbarnes at kemper.freedesktop.org
Mon Jul 2 09:35:33 PDT 2007


 .gitignore         |    1 
 configure.ac       |    1 
 man/intel.man      |    7 +++
 src/i830.h         |    3 +
 src/i830_crt.c     |   36 ++++++++++++----
 src/i830_debug.c   |  116 +++++++++++++++++++++++++++++++++++++--------------
 src/i830_display.c |  119 ++++++++++++++++++++++++++++++++++++++++++++++++++---
 src/i830_driver.c  |    7 +++
 src/i830_dvo.c     |    4 -
 src/i830_memory.c  |   57 ++++++++++++++++++++++++-
 src/i830_tv.c      |    7 ++-
 11 files changed, 306 insertions(+), 52 deletions(-)

New commits:
diff-tree b384c608978dcd3d2ea6c0018179673cb4735f4c (from 1e2e301348b4168aeed38b3fdc6b0e43d5678a86)
Author: Jesse Barnes <jbarnes at nietzche.virtuousgeek.org>
Date:   Mon Jul 2 09:32:28 2007 -0700

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

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

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

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

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

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

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

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

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

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

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

diff --git a/src/i830_debug.c b/src/i830_debug.c
index bda263c..055ca93 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -571,39 +571,91 @@ void i830DumpRegs (ScrnInfoPtr pScrn)
     {
 	fp = INREG(pipe == 0 ? FPA0 : FPB0);
 	dpll = INREG(pipe == 0 ? DPLL_A : DPLL_B);
-	switch ((dpll >> 24) & 0x3) {
-	case 0:
-	    p2 = 10;
-	    break;
-	case 1:
-	    p2 = 5;
-	    break;
-	default:
-	    p2 = 1;
-	    xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "p2 out of range\n");
-	    break;
+	if (IS_I9XX(pI830)) 
+	{
+	    CARD32  lvds = INREG(LVDS);
+	    if ((lvds & LVDS_PORT_EN) &&
+		(lvds & LVDS_PIPEB_SELECT) == (pipe << 30))
+	    {
+		if ((lvds & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP)
+		    p2 = 7;
+		else
+		    p2 = 14;
+	    }
+	    else
+	    {
+		switch ((dpll >> 24) & 0x3) {
+		case 0:
+		    p2 = 10;
+		    break;
+		case 1:
+		    p2 = 5;
+		    break;
+		default:
+		    p2 = 1;
+		    xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "p2 out of range\n");
+		    break;
+		}
+	    }
+	    switch ((dpll >> 16) & 0xff) {
+	    case 1:
+		p1 = 1; break;
+	    case 2:
+		p1 = 2; break;
+	    case 4:
+		p1 = 3; break;
+	    case 8:
+		p1 = 4; break;
+	    case 16:
+		p1 = 5; break;
+	    case 32:
+		p1 = 6; break;
+	    case 64:
+		p1 = 7; break;
+	    case 128:
+		p1 = 8; break;
+	    default:
+		p1 = 1;
+		xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "p1 out of range\n");
+		break;
+	    }
 	}
-	switch ((dpll >> 16) & 0xff) {
-	case 1:
-	    p1 = 1; break;
-	case 2:
-	    p1 = 2; break;
-	case 4:
-	    p1 = 3; break;
-	case 8:
-	    p1 = 4; break;
-	case 16:
-	    p1 = 5; break;
-	case 32:
-	    p1 = 6; break;
-	case 64:
-	    p1 = 7; break;
-	case 128:
-	    p1 = 8; break;
-	default:
-	    p1 = 1;
-	    xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "p1 out of range\n");
-	    break;
+	else
+	{
+	    CARD32  lvds = INREG(LVDS);
+	    if (IS_I85X (pI830) && 
+		(lvds & LVDS_PORT_EN) &&
+		(lvds & LVDS_PIPEB_SELECT) == (pipe << 30))
+	    {
+		if ((lvds & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP)
+		    p2 = 7;
+		else
+		    p2 = 14;
+		switch ((dpll >> 16) & 0x3f) {
+		case 0x01:  p1 = 1; break;
+		case 0x02:  p1 = 2; break;
+		case 0x04:  p1 = 3; break;
+		case 0x08:  p1 = 4; break;
+		case 0x10:  p1 = 5; break;
+		case 0x20:  p1 = 6; break;
+		default:
+		    p1 = 1;
+		    xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "LVDS P1 0x%x invalid encoding\n",
+				(dpll >> 16) & 0x3f);
+		    break;
+		}
+	    }
+	    else
+	    {
+		if (dpll & (1 << 23))
+		    p2 = 4;
+		else
+		    p2 = 2;
+		if (dpll & PLL_P1_DIVIDE_BY_TWO)
+		    p1 = 2;
+		else
+		    p1 = ((dpll >> 16) & 0x3f) + 2;
+	    }
 	}
 	switch ((dpll >> 13) & 0x3) {
 	case 0:


More information about the xorg-commit mailing list