xf86-video-intel: Branch 'modesetting' - src/i830_display.c src/i830_randr.c

Keith Packard keithp at kemper.freedesktop.org
Sun Dec 3 08:58:45 EET 2006


 src/i830_display.c |  417 +++++++++++++++++++++++++++++++++--------------------
 src/i830_randr.c   |    2 
 2 files changed, 265 insertions(+), 154 deletions(-)

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

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

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



More information about the xorg-commit mailing list