xf86-video-intel: Branch 'display-port' - 3 commits - src/i810_reg.h src/i830_debug.c src/i830_display.c src/i830_dp.c

Keith Packard keithp at kemper.freedesktop.org
Thu Mar 19 01:07:18 PDT 2009


 src/i810_reg.h     |   42 +++++++++++++++++
 src/i830_debug.c   |    8 +++
 src/i830_display.c |   14 +++--
 src/i830_dp.c      |  129 +++++++++++++++++++++++++++++++----------------------
 4 files changed, 135 insertions(+), 58 deletions(-)

New commits:
commit d12cc0d84812dd0ad11c59e1c10d016e1c084953
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Mar 19 01:07:13 2009 -0700

    Add DP link and GMCH M and N registers

diff --git a/src/i810_reg.h b/src/i810_reg.h
index e99d010..3af027d 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -2289,6 +2289,43 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define PIPE_PIXEL_MASK		0x00ffffff
 #define PIPE_PIXEL_SHIFT	0
 
+/*
+ * Computing GMCH M and N values.
+ *
+ * GMCH M/N = dot clock * bytes per pixel / ls_clk * # of lanes
+ *
+ * ls_clk (we assume) is the DP link clock (1.62 or 2.7 GHz)
+ *
+ * The GMCH value is used internally
+ */
+#define PIPEA_GMCH_DATA_M	0x70050
+
+/* Transfer unit size for display port - 1, default is 0x3f (for TU size 64) */
+#define PIPE_GMCH_DATA_M_TU_SIZE_MASK	(0x3f << 25)
+#define PIPE_GMCH_DATA_M_TU_SIZE_SHIFT	25
+
+#define PIPE_GMCH_DATA_M_MASK		(0xffffff)
+
+#define PIPEA_GMCH_DATA_N	0x70054
+#define PIPE_GMCH_DATA_N_MASK		(0xffffff)
+
+/*
+ * Computing Link M and N values.
+ *
+ * Link M / N = pixel_clock / ls_clk
+ *
+ * (the DP spec calls pixel_clock the 'strm_clk')
+ *
+ * The Link value is transmitted in the Main Stream
+ * Attributes and VB-ID.
+ */
+
+#define PIPEA_DP_LINK_M		0x70060
+#define PIPEA_DP_LINK_M_MASK	(0xffffff)
+
+#define PIPEA_DP_LINK_N		0x70064
+#define PIPEA_DP_LINK_N_MASK	(0xffffff)
+
 #define PIPEB_DSL		0x71000
 
 #define PIPEBCONF 0x71008
@@ -2306,6 +2343,11 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define PIPEBFRAMEHIGH		0x71040
 #define PIPEBFRAMEPIXEL		0x71044
 
+#define PIPEB_GMCH_DATA_M	0x71050
+#define PIPEB_GMCH_DATA_N	0x71054
+#define PIPEB_DP_LINK_M		0x71060
+#define PIPEB_DP_LINK_N		0x71064
+
 #define DSPACNTR		0x70180
 #define DSPBCNTR		0x71180
 #define DISPLAY_PLANE_ENABLE 			(1<<31)
diff --git a/src/i830_debug.c b/src/i830_debug.c
index cf30dd5..96bd317 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -706,6 +706,10 @@ static struct i830SnapshotRec {
     DEFINEREG2(PIPEACONF, i830_debug_pipeconf),
     DEFINEREG2(PIPEASRC, i830_debug_yxminus1),
     DEFINEREG2(PIPEASTAT, i830_debug_pipestat),
+    DEFINEREG(PIPEA_GMCH_DATA_M),
+    DEFINEREG(PIPEA_GMCH_DATA_N),
+    DEFINEREG(PIPEA_DP_LINK_M),
+    DEFINEREG(PIPEA_DP_LINK_N),
 
     DEFINEREG2(FPA0, i830_debug_fp),
     DEFINEREG2(FPA1, i830_debug_fp),
@@ -730,6 +734,10 @@ static struct i830SnapshotRec {
     DEFINEREG2(PIPEBCONF, i830_debug_pipeconf),
     DEFINEREG2(PIPEBSRC, i830_debug_yxminus1),
     DEFINEREG2(PIPEBSTAT, i830_debug_pipestat),
+    DEFINEREG(PIPEB_GMCH_DATA_M),
+    DEFINEREG(PIPEB_GMCH_DATA_N),
+    DEFINEREG(PIPEB_DP_LINK_M),
+    DEFINEREG(PIPEB_DP_LINK_N),
 
     DEFINEREG2(FPB0, i830_debug_fp),
     DEFINEREG2(FPB1, i830_debug_fp),
commit 69dde0f9b3a20140a46bc80352b6b5a7389619e2
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Mar 19 01:06:53 2009 -0700

    Clean up dp_link_train to avoid hitting DP register twice

diff --git a/src/i830_dp.c b/src/i830_dp.c
index 8dd5722..0e2fc3f 100644
--- a/src/i830_dp.c
+++ b/src/i830_dp.c
@@ -461,10 +461,9 @@ i830_dp_link_train(xf86OutputPtr output, uint32_t DP)
 
     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 	       "i830_dp_link_train dp 0x%08x\n", DP);
-    OUTREG(dev_priv->output_reg, DP);
-    POSTING_READ(dev_priv->output_reg);
-
     if ((DP & DP_PORT_EN) == 0) {
+	OUTREG(dev_priv->output_reg, DP);
+	POSTING_READ(dev_priv->output_reg);
 	return;
     }
     DP &= ~DP_LINK_TRAIN_MASK;
commit b4badbf0e4ef6d73e2fdd6f93c875d30f77bd454
Author: Keith Packard <keithp at keithp.com>
Date:   Wed Mar 18 23:26:11 2009 -0700

    DP lights up a mode at 162kHz pixel clock

diff --git a/src/i830_display.c b/src/i830_display.c
index 55a20be..95ceb56 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -1303,7 +1303,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
     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;
 
     /* Set up some convenient bools for what outputs are connected to
@@ -1323,7 +1323,6 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
 	    break;
 	case I830_OUTPUT_SDVO:
 	case I830_OUTPUT_HDMI:
-	case I830_OUTPUT_DISPLAYPORT:
 	    is_sdvo = TRUE;
 	    if (intel_output->needs_tv_clock)
 		is_tv = TRUE;
@@ -1339,6 +1338,9 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
 	case I830_OUTPUT_ANALOG:
 	    is_crt = TRUE;
 	    break;
+	case I830_OUTPUT_DISPLAYPORT:
+	    is_dp = TRUE;
+	    break;
 	}
 
 	num_outputs++;
@@ -1401,7 +1403,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
 	    dpll |= DPLLB_MODE_LVDS;
 	else
 	    dpll |= DPLLB_MODE_DAC_SERIAL;
-	if (is_sdvo)
+	if (is_sdvo || is_dp)
 	{
 	    dpll |= DPLL_DVO_HIGH_SPEED;
 	    if ((IS_I945G(pI830) || IS_I945GM(pI830) || IS_G33CLASS(pI830)))
@@ -1430,7 +1432,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
 	    dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
 	    break;
 	}
-	if (IS_I965G(pI830) && !IS_GM45(pI830))
+	if (IS_I965G(pI830) /* && !IS_GM45(pI830) */)
 	    dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT);
     } else {
 	if (is_lvds) {
@@ -1591,8 +1593,10 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
     
     if (IS_I965G(pI830)) {
 	int sdvo_pixel_multiply = adjusted_mode->Clock / mode->Clock;
+/*	OUTREG(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) |
+	       ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT)); */
 	OUTREG(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) |
-	       ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT));
+	       ((sdvo_pixel_multiply - 1) << 0));
     } else {
 	/* write it again -- the BIOS does, after all */
 	OUTREG(dpll_reg, dpll);
diff --git a/src/i830_dp.c b/src/i830_dp.c
index fc1ddff..8dd5722 100644
--- a/src/i830_dp.c
+++ b/src/i830_dp.c
@@ -39,7 +39,7 @@
 struct i830_dp_priv {
     uint32_t output_reg;
     uint32_t save_DP;
-    uint8_t  save_link_configuration[0x10];
+    uint8_t  save_link_configuration[0x9];
     Bool has_audio;
     uint16_t i2c_address;
     Bool i2c_running;
@@ -60,13 +60,25 @@ i830_dp_mode_valid(xf86OutputPtr output, DisplayModePtr mode)
     return MODE_OK;
 }
 
+static int
+i830_dp_get_pixel_multiplier(DisplayModePtr pMode)
+{
+    if (pMode->Clock >= 100000)
+	return 1;
+    else if (pMode->Clock >= 50000)
+	return 2;
+    else
+	return 4;
+}
+
 static Bool
 i830_dp_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
 		     DisplayModePtr adjusted_mode)
 {
-    /* The DP output doesn't need the pixel multiplication that SDVO does,
-     * so no fixup.
+    /* Make the CRTC code factor in the SDVO pixel multiplier.  The SDVO
+     * device will be told of the multiplier during mode_set.
      */
+    adjusted_mode->Clock *= i830_dp_get_pixel_multiplier(mode);
     return TRUE;
 }
 
@@ -288,6 +300,8 @@ i830_dp_aux_i2c_transaction(ScrnInfoPtr pScrn, uint32_t output_reg,
 
     switch (mode) {
     case aux_i2c_start:
+    case aux_i2c_stop:
+    default:
         msg_bytes = 3;
         reply_bytes = 1;
 	break;
@@ -302,10 +316,6 @@ i830_dp_aux_i2c_transaction(ScrnInfoPtr pScrn, uint32_t output_reg,
 	msg_bytes = 4;
 	reply_bytes = 2;
 	break;
-    case aux_i2c_stop:
-        msg_bytes = 3;
-        reply_bytes = 1;
-	break;
     }
 
     for (;;) {
@@ -317,11 +327,8 @@ i830_dp_aux_i2c_transaction(ScrnInfoPtr pScrn, uint32_t output_reg,
 	    return -1;
 	}
 	if ((reply[0] & AUX_I2C_REPLY_MASK) == AUX_I2C_REPLY_ACK) {
-	    if (mode == aux_i2c_read) {
-		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-			   "i2c_read: %02x\n", reply[1]);
+	    if (mode == aux_i2c_read)
 		*read_byte = reply[1];
-	    }
 	    return reply_bytes - 1;
 	}
 	else if ((reply[0] & AUX_I2C_REPLY_MASK) == AUX_I2C_REPLY_DEFER)
@@ -346,8 +353,7 @@ i830_dp_mode_set(xf86OutputPtr output, DisplayModePtr mode,
     I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
     uint32_t dp;
 
-    dp = (DP_PORT_EN |
-	  DP_LINK_TRAIN_OFF |
+    dp = (DP_LINK_TRAIN_OFF |
 	  DP_VOLTAGE_0_4 |
 	  DP_PRE_EMPHASIS_0 |
 	  DP_PORT_WIDTH_4 |
@@ -365,6 +371,8 @@ i830_dp_mode_set(xf86OutputPtr output, DisplayModePtr mode,
     POSTING_READ(dev_priv->output_reg);
 }
 
+#include "i830_debug.h"
+
 static void
 i830_dp_dpms(xf86OutputPtr output, int mode)
 {
@@ -380,6 +388,12 @@ i830_dp_dpms(xf86OutputPtr output, int mode)
     } else {
 	temp = INREG(dev_priv->output_reg);
 	temp |= DP_PORT_EN;
+
+	i830_dp_aux_native_write(pScrn, dev_priv->output_reg, 0x100,
+				 dev_priv->save_link_configuration, sizeof (dev_priv->save_link_configuration));
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		   "%s: i830_dp_link_train\n", __func__);
+	i830DumpRegs(pScrn);
 	i830_dp_link_train(output, temp);
     }
 }
@@ -414,7 +428,7 @@ i830_dp_save(xf86OutputPtr output)
     i830_dp_aux_native_read(pScrn, dev_priv->output_reg, 0x100,
 		     dev_priv->save_link_configuration, sizeof (dev_priv->save_link_configuration));
     xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-	       "link configuration: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+	       "link configuration: %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
 	       dev_priv->save_link_configuration[0],
 	       dev_priv->save_link_configuration[1],
 	       dev_priv->save_link_configuration[2],
@@ -423,14 +437,7 @@ i830_dp_save(xf86OutputPtr output)
 	       dev_priv->save_link_configuration[5],
 	       dev_priv->save_link_configuration[6],
 	       dev_priv->save_link_configuration[7],
-	       dev_priv->save_link_configuration[8],
-	       dev_priv->save_link_configuration[9],
-	       dev_priv->save_link_configuration[10],
-	       dev_priv->save_link_configuration[11],
-	       dev_priv->save_link_configuration[12],
-	       dev_priv->save_link_configuration[13],
-	       dev_priv->save_link_configuration[14],
-	       dev_priv->save_link_configuration[15]);
+	       dev_priv->save_link_configuration[8]);
 
     i830_dp_lane_status(output, lane_status);
 }
@@ -447,17 +454,23 @@ i830_dp_link_train(xf86OutputPtr output, uint32_t DP)
     uint8_t lane_status[3];
     uint8_t adjust_request[10];
     int ret;
-    int tries;
     int i;
+    int voltage;
+    int pre_emphasis;
+    Bool clock_recovery = FALSE;
 
-    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 	       "i830_dp_link_train dp 0x%08x\n", DP);
+    OUTREG(dev_priv->output_reg, DP);
+    POSTING_READ(dev_priv->output_reg);
+
     if ((DP & DP_PORT_EN) == 0) {
-	OUTREG(dev_priv->output_reg, DP);
 	return;
     }
     DP &= ~DP_LINK_TRAIN_MASK;
 
+    usleep (20*1000);
+
     ret = i830_dp_aux_native_read(pScrn, dev_priv->output_reg,
 			   0x206, adjust_request, 2);
     xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
@@ -475,37 +488,46 @@ i830_dp_link_train(xf86OutputPtr output, uint32_t DP)
 			   training, 1);
     xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 	       "training pattern 1: %02x\n", training[0]);
-    memset(train_set, '\0', sizeof (train_set));
-    train_set[0] = (3 << 3) | (0 << 0);
-    train_set[1] = (3 << 3) | (0 << 0);
-    train_set[2] = (3 << 3) | (0 << 0);
-    train_set[3] = (3 << 3) | (0 << 0);
     /* clock recovery pattern */
-    tries = 0;
-    for (i = 0; i < 4; i++) {
-
-	ret = i830_dp_aux_native_write(pScrn, dev_priv->output_reg,
-				DP_TRAINING_LANE0_SET, train_set, 4);
-	if (ret != 4) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		       "voltage swing set failed\n");
-	    break;
+    for (voltage = 0; voltage < 4; voltage++) {
+	for (pre_emphasis = 0; pre_emphasis < 4; pre_emphasis++) {
+	    memset(train_set, (voltage << 0) | (pre_emphasis << 3), 4);
+	    ret = i830_dp_aux_native_write(pScrn, dev_priv->output_reg,
+					   DP_TRAINING_LANE0_SET, train_set, 4);
+	    if (ret != 4) {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			   "voltage %d pre_emphasis %d set failed\n",
+			   voltage, pre_emphasis);
+		continue;
+	    }
+	    for (i = 0; i < 4; i++) {
+		usleep (15*1000);
+		ret = i830_dp_lane_status(output, lane_status);
+		if (ret != 3)
+		    continue;
+		if ((lane_status[0] & DP_LANE_CR_DONE) &&
+		    (lane_status[0] & (DP_LANE_CR_DONE << 4)) &&
+		    (lane_status[1] & DP_LANE_CR_DONE) &&
+		    (lane_status[1] & (DP_LANE_CR_DONE << 4)))
+		{
+		    clock_recovery = TRUE;
+		}
+		if (clock_recovery)
+		    break;
+	    }
+	    if (clock_recovery)
+		break;
 	}
-
-	usleep (15*1000);
-	ret = i830_dp_lane_status(output, lane_status);
-	if (ret != 3)
-	    break;
-	if ((lane_status[0] & DP_LANE_CR_DONE) &&
-	    (lane_status[0] & (DP_LANE_CR_DONE << 4)) &&
-	    (lane_status[1] & DP_LANE_CR_DONE) &&
-	    (lane_status[1] & (DP_LANE_CR_DONE << 4)))
-	    break;
-	if (i == 3) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		       "clock recovery failed\n");
+	if (clock_recovery)
 	    break;
-	}
+    }
+    if (!clock_recovery) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "clock recovery failed\n");
+    } else {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "clock recovery at voltage %d pre_emphasis %d\n",
+		   voltage, pre_emphasis);
     }
     /* channel eq pattern */
     OUTREG(dev_priv->output_reg, DP | DP_LINK_TRAIN_PAT_2);
@@ -631,7 +653,6 @@ i830_dp_i2c_get_byte(I2CDevPtr dev, I2CByte *byte_ret, Bool last)
     struct i830_dp_priv *dev_priv = intel_output->dev_priv;
     ScrnInfoPtr scrn = output->scrn;
 
-    xf86DrvMsg(scrn->scrnIndex, X_ERROR, "i2c_get_byte %d\n", last);
     return i830_dp_aux_i2c_transaction(scrn, dev_priv->output_reg,
 				       dev_priv->i2c_address,
 				       aux_i2c_read, 0, byte_ret) == 1;
@@ -686,6 +707,9 @@ i830_dp_restore(xf86OutputPtr output)
 
     i830_dp_aux_native_write(pScrn, dev_priv->output_reg, 0x100,
 		     dev_priv->save_link_configuration, sizeof (dev_priv->save_link_configuration));
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+	       "%s: i830_dp_link_train\n", __func__);
+    i830DumpRegs(pScrn);
     i830_dp_link_train(output, dev_priv->save_DP);
 }
 


More information about the xorg-commit mailing list