xf86-video-intel: Branch '2.7' - 8 commits - man/intel.man src/i810_reg.h src/i830_display.c src/i830_driver.c src/i830_exa.c src/i830_sdvo.c src/i830_video.c

Carl Worth cworth at kemper.freedesktop.org
Mon Apr 6 14:08:04 PDT 2009


 man/intel.man      |    9 -
 src/i810_reg.h     |   19 ++-
 src/i830_display.c |  279 ++++++++++++++++++++++++++++++++++++++++++++++++++---
 src/i830_driver.c  |    3 
 src/i830_exa.c     |    3 
 src/i830_sdvo.c    |   10 +
 src/i830_video.c   |   58 ++++-------
 7 files changed, 322 insertions(+), 59 deletions(-)

New commits:
commit 3e5586cace98f73a9f8403a6446d380899ecbce9
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Apr 6 14:02:08 2009 -0700

    Fix new video sync-to-blank code for multi-head
    
    We need to account for a non-zero Y offset for the CRTC. Without
    this, we don't sync to the correct region, so tearing becomes
    visible again.
    (cherry picked from commit 5d9d9a2e466474a0508a15b294a91507ccb3ccc1)

diff --git a/src/i830_video.c b/src/i830_video.c
index 3331dd3..13f3ab1 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -2517,6 +2517,7 @@ I830PutImage(ScrnInfoPtr pScrn,
 
         if (sync) {
 	    BoxPtr box;
+	    int y1, y2;
             int event, pipe;
 	    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
 
@@ -2529,14 +2530,16 @@ I830PutImage(ScrnInfoPtr pScrn,
 	    }
 
 	    box = REGION_EXTENTS(unused, clipBoxes);
+	    y1 = box->y1 - crtc->y;
+	    y2 = box->y2 - crtc->y;
 
             BEGIN_BATCH(5);
 	    /* The documentation says that the LOAD_SCAN_LINES command
 	     * always comes in pairs. Don't ask me why. */
 	    OUT_BATCH(MI_LOAD_SCAN_LINES_INCL | pipe);
-	    OUT_BATCH((box->y1 << 16) | box->y2);
+	    OUT_BATCH((y1 << 16) | y2);
 	    OUT_BATCH(MI_LOAD_SCAN_LINES_INCL | pipe);
-	    OUT_BATCH((box->y1 << 16) | box->y2);
+	    OUT_BATCH((y1 << 16) | y2);
             OUT_BATCH(MI_WAIT_FOR_EVENT | event);
             ADVANCE_BATCH();
         }
commit 4e9b75175be791c6098ef79be8e04a8c3baa40f9
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>
    (cherry picked from commit 7c94227dd4fa2164bebb36234958053bf1d26c12)

diff --git a/src/i830_display.c b/src/i830_display.c
index c280d26..dd1310f 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)
 {
@@ -1513,6 +1586,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.
@@ -1565,7 +1639,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 3428e2fd4be337359278f7ab1dc0d9945d6fee34
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>
    (cherry picked from commit 48db5bde9298f1126dfb42f4be8a3d61166abfd8)

diff --git a/src/i830_display.c b/src/i830_display.c
index 43ea4d4..c280d26 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
commit 3b29eb99259ea7b84bd41bff623b027dbe28ffba
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Apr 6 11:31:20 2009 -0700

    Remove support for 'auto'(-1) value of XV_SYNC_TO_VBLANK
    
    We previously had a heurstic here where we would only sync to vblank
    for windows that covered more than 25% of the screen. We don't need
    this anymore since the new approach to sync, (WAIT_FOR_SCANLINE_WINDOW),
    is not excessively costly for small windows.
    (cherry picked from commit 3d4ee3cac1d63dfdf7b54c8ba577f3b77637499f)

diff --git a/man/intel.man b/man/intel.man
index ffe69a1..6ccacda 100644
--- a/man/intel.man
+++ b/man/intel.man
@@ -451,10 +451,11 @@ You can use the "xvattr" tool to query/set those attributes at runtime.
 
 .SS "XV_SYNC_TO_VBLANK"
 XV_SYNC_TO_VBLANK is used to control whether textured adapter synchronizes 
-the screen update to the vblank to eliminate tearing. It has three 
-values 'auto'(-1), 'off'(0) and 'on(1). 'off' means never sync, 'on' means 
-always sync, no matter what size, and 'auto' means sync if the Xv image is 
-more than quarter of the pixels on the screen. The default is 'auto'(-1).
+the screen update to the vblank to eliminate tearing. It is a Boolean
+attribute with values of 0 (never sync) or 1 (always sync). An historic
+value of -1 (sync for large windows only) will now be interpreted as 1,
+(since the current approach for sync is not costly even with small
+video windows).
 
 .SS "XV_BRIGHTNESS"
         
diff --git a/src/i830_video.c b/src/i830_video.c
index 3dde5b4..3331dd3 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -1019,7 +1019,7 @@ I830SetupImageVideoTextured(ScreenPtr pScreen)
 	pPriv->doubleBuffer = 0;
 
 	pPriv->rotation = RR_Rotate_0;
-	pPriv->SyncToVblank = -1;
+	pPriv->SyncToVblank = 1;
 
 	/* gotta uninit this someplace, XXX: shouldn't be necessary for textured */
 	REGION_NULL(pScreen, &pPriv->clip);
@@ -2513,23 +2513,6 @@ I830PutImage(ScrnInfoPtr pScrn,
             sync = FALSE;
         } else if (pPriv->SyncToVblank == 0) {
             sync = FALSE;
-        } else if (pPriv->SyncToVblank == -1) {
-            BoxRec crtc_box;
-            BoxPtr pbox;
-            int nbox, crtc_area, coverage = 0;
-
-            i830_crtc_box(crtc, &crtc_box);
-            crtc_area = i830_box_area(&crtc_box);
-            pbox = REGION_RECTS(clipBoxes);
-            nbox = REGION_NUM_RECTS(clipBoxes);
-            
-            while (nbox--) {
-                coverage += i830_box_area(pbox);
-                pbox++;
-            }
-
-            if ((coverage << 2) < crtc_area)
-                sync = FALSE;
         }
 
         if (sync) {
commit 5dd2777ce836bdf55b53ed763728705d4d686673
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Apr 6 11:16:40 2009 -0700

    Use WAIT_FOR_SCAN_LINE instead of WAIT_FOR_VBLANK
    
    Either way, the goal is tear-free video playing. But waiting for
    a scan-line window not only has the advantage of being cheaper
    for small windows, but also avoids hanging the GPU in the case
    of the pipe getting turned off, (by screensaver, for example),
    while a batch is waiting for a VBLANK that will never occur.
    
    This fixes that GPU hang.
    (cherry picked from commit bc3312fd7c03d09a231dfebfe390fe668ad15d1e)

diff --git a/src/i810_reg.h b/src/i810_reg.h
index 3114b42..c964569 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -2435,12 +2435,19 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define MI_OVERLAY_FLIP_OFF		(2<<21)
 
 /* Wait for Events */
-#define MI_WAIT_FOR_EVENT		(0x03<<23)
-#define MI_WAIT_FOR_PIPEB_SVBLANK	(1<<18)
-#define MI_WAIT_FOR_PIPEA_SVBLANK	(1<<17)
-#define MI_WAIT_FOR_OVERLAY_FLIP	(1<<16)
-#define MI_WAIT_FOR_PIPEB_VBLANK	(1<<7)
-#define MI_WAIT_FOR_PIPEA_VBLANK	(1<<3)
+#define MI_WAIT_FOR_EVENT			(0x03<<23)
+#define MI_WAIT_FOR_PIPEB_SVBLANK		(1<<18)
+#define MI_WAIT_FOR_PIPEA_SVBLANK		(1<<17)
+#define MI_WAIT_FOR_OVERLAY_FLIP		(1<<16)
+#define MI_WAIT_FOR_PIPEB_VBLANK		(1<<7)
+#define MI_WAIT_FOR_PIPEB_SCAN_LINE_WINDOW	(1<<5)
+#define MI_WAIT_FOR_PIPEA_VBLANK		(1<<3)
+#define MI_WAIT_FOR_PIPEA_SCAN_LINE_WINDOW	(1<<2)
+
+/* Set the scan line for MI_WAIT_FOR_PIPE?_SCAN_LINE_WINDOW */
+#define MI_LOAD_SCAN_LINES_INCL			(0x12<<23)
+#define MI_LOAD_SCAN_LINES_DISPLAY_PIPEA	(0)
+#define MI_LOAD_SCAN_LINES_DISPLAY_PIPEB	(0x1<<20)
 
 /* Flush */
 #define MI_FLUSH			(0x04<<23)
diff --git a/src/i830_video.c b/src/i830_video.c
index 3f3aaac..3dde5b4 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -2533,24 +2533,28 @@ I830PutImage(ScrnInfoPtr pScrn,
         }
 
         if (sync) {
-            I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
-            int event;
-
-            if (IS_I965G(pI830)) {
-                if (intel_crtc->pipe == 0)
-                    event = MI_WAIT_FOR_PIPEA_SVBLANK;
-                else
-                    event = MI_WAIT_FOR_PIPEB_SVBLANK;
-            } else {
-                if (intel_crtc->pipe == 0)
-                    event = MI_WAIT_FOR_PIPEA_VBLANK;
-                else
-                    event = MI_WAIT_FOR_PIPEB_VBLANK;
-            }
+	    BoxPtr box;
+            int event, pipe;
+	    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+
+	    if (intel_crtc->pipe == 0) {
+		event = MI_WAIT_FOR_PIPEA_SCAN_LINE_WINDOW;
+		pipe = MI_LOAD_SCAN_LINES_DISPLAY_PIPEA;
+	    } else {
+		event = MI_WAIT_FOR_PIPEB_SCAN_LINE_WINDOW;
+		pipe = MI_LOAD_SCAN_LINES_DISPLAY_PIPEB;
+	    }
+
+	    box = REGION_EXTENTS(unused, clipBoxes);
 
-            BEGIN_BATCH(2);
+            BEGIN_BATCH(5);
+	    /* The documentation says that the LOAD_SCAN_LINES command
+	     * always comes in pairs. Don't ask me why. */
+	    OUT_BATCH(MI_LOAD_SCAN_LINES_INCL | pipe);
+	    OUT_BATCH((box->y1 << 16) | box->y2);
+	    OUT_BATCH(MI_LOAD_SCAN_LINES_INCL | pipe);
+	    OUT_BATCH((box->y1 << 16) | box->y2);
             OUT_BATCH(MI_WAIT_FOR_EVENT | event);
-            OUT_BATCH(MI_NOOP);
             ADVANCE_BATCH();
         }
 
commit 5944f5e32511984b11decc0df6074600e1989934
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>
    (cherry picked from commit 6cd914ef315036ce8e91c7b6492994353e8ed2d8)

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 633c24bc20ed96b1f9ef954bfd722e3ab504ea93
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>
    (cherry picked from commit fad714c40078d22fff82dc0692a344f66ddf9680)

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 6501f8e5e91f3f87348d590e42a4860fea2cfddc
Author: Hugo Jacques <hugo.jacques at verint.com>
Date:   Wed Apr 1 10:10:05 2009 +0800

    SDVO: add composite TV out support
    (cherry picked from commit 00de1757dd5776962bdd4c8968181878c2ebf4c9)

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;


More information about the xorg-commit mailing list