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