summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/i830_display.c352
-rw-r--r--src/i830_lvds.c38
2 files changed, 204 insertions, 186 deletions
diff --git a/src/i830_display.c b/src/i830_display.c
index 17549b9d..50440156 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -948,6 +948,102 @@ i830_disable_vga_plane (xf86CrtcPtr crtc)
}
}
+static void ironlake_fdi_link_train(xf86CrtcPtr crtc)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+ int pipe = intel_crtc->pipe;
+ int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL;
+ int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL;
+ int fdi_rx_iir_reg = (pipe == 0) ? FDI_RXA_IIR : FDI_RXB_IIR;
+ int fdi_rx_imr_reg = (pipe == 0) ? FDI_RXA_IMR : FDI_RXB_IMR;
+ uint32_t temp, tries = 0;
+
+ /* enable CPU FDI TX and PCH FDI RX */
+ temp = INREG(fdi_tx_reg);
+ temp |= FDI_TX_ENABLE;
+ temp &= ~(7 << 19);
+ temp |= /*(intel_crtc->fdi_lanes - 1)*/3 << 19;
+ temp &= ~FDI_LINK_TRAIN_NONE;
+ temp |= FDI_LINK_TRAIN_PATTERN_1;
+ OUTREG(fdi_tx_reg, temp);
+ INREG(fdi_tx_reg);
+
+ temp = INREG(fdi_rx_reg);
+ temp &= ~FDI_LINK_TRAIN_NONE;
+ temp |= FDI_LINK_TRAIN_PATTERN_1;
+ OUTREG(fdi_rx_reg, temp | FDI_RX_ENABLE);
+ INREG(fdi_rx_reg);
+ usleep(150);
+
+ /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit
+ for train result */
+ temp = INREG(fdi_rx_imr_reg);
+ temp &= ~FDI_RX_SYMBOL_LOCK;
+ temp &= ~FDI_RX_BIT_LOCK;
+ OUTREG(fdi_rx_imr_reg, temp);
+ INREG(fdi_rx_imr_reg);
+ usleep(150);
+
+ for (;;) {
+ temp = INREG(fdi_rx_iir_reg);
+ ErrorF("FDI_RX_IIR 0x%x\n", temp);
+
+ if ((temp & FDI_RX_BIT_LOCK)) {
+ ErrorF("FDI train 1 done.\n");
+ OUTREG(fdi_rx_iir_reg,
+ temp | FDI_RX_BIT_LOCK);
+ break;
+ }
+
+ tries++;
+
+ if (tries > 5) {
+ ErrorF("FDI train 1 fail!\n");
+ break;
+ }
+ }
+
+ /* Train 2 */
+ temp = INREG(fdi_tx_reg);
+ temp &= ~FDI_LINK_TRAIN_NONE;
+ temp |= FDI_LINK_TRAIN_PATTERN_2;
+ OUTREG(fdi_tx_reg, temp);
+
+ temp = INREG(fdi_rx_reg);
+ temp &= ~FDI_LINK_TRAIN_NONE;
+ temp |= FDI_LINK_TRAIN_PATTERN_2;
+ OUTREG(fdi_rx_reg, temp);
+ usleep(150);
+
+ tries = 0;
+
+ for (;;) {
+ temp = INREG(fdi_rx_iir_reg);
+ ErrorF("FDI_RX_IIR 0x%x\n", temp);
+
+ if (temp & FDI_RX_SYMBOL_LOCK) {
+ OUTREG(fdi_rx_iir_reg,
+ temp | FDI_RX_SYMBOL_LOCK);
+ ErrorF("FDI train 2 done.\n");
+ break;
+ }
+
+ tries++;
+
+ if (tries > 5) {
+ ErrorF("FDI train 2 fail!\n");
+ break;
+ }
+ }
+
+ ErrorF("FDI train done\n");
+}
+
+
+
static void igdng_crtc_dpms(xf86CrtcPtr crtc, int mode)
{
ScrnInfoPtr pScrn = crtc->scrn;
@@ -999,38 +1095,35 @@ static void igdng_crtc_dpms(xf86CrtcPtr crtc, int mode)
case DPMSModeSuspend:
/* XXX no LVDS port force */
-
- ErrorF("PCH DPLL enable\n");
- /* enable PCH DPLL */
- while (!((temp = INREG(pch_dpll_reg)) & DPLL_VCO_ENABLE)) {
- OUTREG(pch_dpll_reg, temp | DPLL_VCO_ENABLE);
- INREG(pch_dpll_reg);
- usleep(10);
+ if (i830PipeHasType(crtc, I830_OUTPUT_LVDS)) {
+ temp = INREG(PCH_LVDS);
+ if ((temp & LVDS_PORT_EN) == 0) {
+ OUTREG(PCH_LVDS, temp | LVDS_PORT_EN);
+ INREG(PCH_LVDS);
+ }
}
ErrorF("PCH FDI RX PLL enable\n");
temp = INREG(fdi_rx_reg);
-
temp &= ~(0x7 << 16);
temp |= (pipe_bpc << 11);
- temp &= ~(FDI_DP_PORT_WIDTH_MASK << 19);
+ temp &= ~(FDI_DP_PORT_WIDTH_MASK);
temp |= FDI_DP_PORT_WIDTH_X4;
- OUTREG(fdi_rx_reg, temp); /* default 4 lanes */
+ OUTREG(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE); /* default 4 lanes */
INREG(fdi_rx_reg);
usleep(200);
temp = INREG(fdi_rx_reg);
OUTREG(fdi_rx_reg, temp | FDI_SEL_PCDCLK);
- INREG(fdi_rx_reg);
+ temp = INREG(fdi_rx_reg);
usleep(200);
- ErrorF("PCH FDI TX PLL enable\n");
- /* Enable CPU FDI TX PLL, always on for IGDNG */
- while (!((temp = INREG(fdi_tx_reg)) & FDI_TX_PLL_ENABLE)) {
- temp &= (~FDI_DP_PORT_WIDTH_MASK);
- temp |= FDI_TX_PLL_ENABLE | FDI_DP_PORT_WIDTH_X4;
- OUTREG(fdi_tx_reg, temp);
+ ErrorF("PCH FDI TX PLL enable %08x\n", temp);
+ temp = INREG(fdi_tx_reg);
+ if ((temp & FDI_TX_PLL_ENABLE) == 0) {
+ OUTREG(fdi_tx_reg, temp | FDI_TX_PLL_ENABLE);
+ INREG(fdi_tx_reg);
usleep(100);
}
@@ -1063,7 +1156,8 @@ static void igdng_crtc_dpms(xf86CrtcPtr crtc, int mode)
ErrorF("Pipe enable\n");
/* Enable CPU pipe */
- while (!((temp = INREG(pipeconf_reg)) & PIPEACONF_ENABLE)) {
+ temp = INREG(pipeconf_reg);
+ if ((temp & PIPEACONF_ENABLE) == 0) {
OUTREG(pipeconf_reg, temp | PIPEACONF_ENABLE);
INREG(pipeconf_reg);
usleep(100);
@@ -1071,7 +1165,8 @@ static void igdng_crtc_dpms(xf86CrtcPtr crtc, int mode)
ErrorF("Plane enable\n");
/* configure and enable CPU plane */
- while (!((temp = INREG(dspcntr_reg)) & DISPLAY_PLANE_ENABLE)) {
+ temp = INREG(dspcntr_reg);
+ if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
OUTREG(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE);
/* Flush the plane changes */
OUTREG(dspbase_reg, INREG(dspbase_reg));
@@ -1081,79 +1176,16 @@ static void igdng_crtc_dpms(xf86CrtcPtr crtc, int mode)
OUTREG(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE);
/* Train FDI. */
+ ironlake_fdi_link_train(crtc);
- ErrorF("FDI TX enable\n");
- /* enable CPU FDI TX and PCH FDI RX */
- while (!((temp = INREG(fdi_tx_reg)) & FDI_TX_ENABLE)) {
- temp |= FDI_TX_ENABLE;
- temp |= FDI_DP_PORT_WIDTH_X4; /* default */
- temp &= ~FDI_LINK_TRAIN_NONE;
- temp |= FDI_LINK_TRAIN_PATTERN_1;
- OUTREG(fdi_tx_reg, temp);
- usleep(10);
- }
-
- ErrorF("FDI RX enable\n");
- while (!((temp = INREG(fdi_rx_reg)) & FDI_RX_ENABLE)) {
- temp &= ~FDI_LINK_TRAIN_NONE;
- temp |= FDI_LINK_TRAIN_PATTERN_1;
- OUTREG(fdi_rx_reg, temp | FDI_RX_ENABLE);
- usleep(10);
- }
-
- usleep(150);
-
- ErrorF("FDI link train 1 start\n");
- /* unmask FDI RX Interrupt symbol_lock and bit_lock bit
- for train result */
- while ((temp = INREG(fdi_rx_imr_reg)) &
- (FDI_RX_SYMBOL_LOCK|FDI_RX_BIT_LOCK)) {
- temp &= ~(FDI_RX_SYMBOL_LOCK | FDI_RX_BIT_LOCK);
- OUTREG(fdi_rx_imr_reg, temp);
- usleep(150);
- }
-
- ErrorF("FDI link train 1 wait\n");
- for (j = 0; j < tries; j++) {
- temp = INREG(fdi_rx_iir_reg);
- if (temp & FDI_RX_BIT_LOCK)
- break;
- usleep(200);
- }
- if (j == tries)
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "train 1 failed\n");
-
- ErrorF("FDI link train 2 start TX\n");
- while (!((temp = INREG(fdi_tx_reg)) & FDI_LINK_TRAIN_PATTERN_2)) {
- temp &= ~FDI_LINK_TRAIN_NONE;
- temp |= FDI_LINK_TRAIN_PATTERN_2;
- OUTREG(fdi_tx_reg, temp);
- usleep(10);
- }
-
- ErrorF("FDI link train 2 start TX\n");
- while (!((temp = INREG(fdi_rx_reg)) & FDI_LINK_TRAIN_PATTERN_2)) {
- temp &= ~FDI_LINK_TRAIN_NONE;
- temp |= FDI_LINK_TRAIN_PATTERN_2;
- OUTREG(fdi_rx_reg, temp);
- usleep(10);
- }
-
- usleep(500);
-
- ErrorF("FDI link train 2 wait\n");
- for (j = 0; j < tries; j++) {
- temp = INREG(fdi_rx_iir_reg);
- if (temp & FDI_RX_SYMBOL_LOCK)
- break;
- usleep(200);
+ /* enalbe PCH DPLL */
+ temp = INREG(pch_dpll_reg);
+ if ((temp & DPLL_VCO_ENABLE) == 0) {
+ OUTREG(pch_dpll_reg, temp | DPLL_VCO_ENABLE);
+ INREG(pch_dpll_reg);
}
- if (j == tries)
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "train 2 failed\n");
-
- usleep(500);
+ usleep(200);
- ErrorF("transcoder timing\n");
/* set transcoder timing */
OUTREG(trans_htot_reg, INREG(cpu_htot_reg));
OUTREG(trans_hblank_reg, INREG(cpu_hblank_reg));
@@ -1166,41 +1198,31 @@ static void igdng_crtc_dpms(xf86CrtcPtr crtc, int mode)
/* enable normal */
ErrorF("FDI TX link normal\n");
- while (((temp = INREG(fdi_tx_reg)) & FDI_LINK_TRAIN_NONE) != FDI_LINK_TRAIN_NONE) {
- temp &= ~FDI_LINK_TRAIN_NONE;
- OUTREG(fdi_tx_reg, temp | FDI_LINK_TRAIN_NONE |
- FDI_TX_ENHANCE_FRAME_ENABLE);
- usleep(10);
- }
+ temp = INREG(fdi_tx_reg);
+ temp &= ~FDI_LINK_TRAIN_NONE;
+ OUTREG(fdi_tx_reg, temp | FDI_LINK_TRAIN_NONE |
+ FDI_TX_ENHANCE_FRAME_ENABLE);
+ INREG(fdi_tx_reg);
- ErrorF("FDI RX link normal\n");
- while (((temp = INREG(fdi_rx_reg)) & FDI_LINK_TRAIN_NONE) != FDI_LINK_TRAIN_NONE) {
- temp &= ~FDI_LINK_TRAIN_NONE;
- OUTREG(fdi_rx_reg, temp | FDI_LINK_TRAIN_NONE |
- FDI_RX_ENHANCE_FRAME_ENABLE);
- usleep(10);
- }
+ temp = INREG(fdi_rx_reg);
+ temp &= ~FDI_LINK_TRAIN_NONE;
+ temp |= FDI_LINK_TRAIN_NONE;
+
+ OUTREG(fdi_rx_reg, temp | FDI_LINK_TRAIN_NONE);
+ INREG(fdi_rx_reg);
- usleep(500);
+ usleep(100);
ErrorF("transcoder enable\n");
/* enable transcoder */
- n = 0;
- while (!((temp = INREG(transconf_reg)) & TRANS_STATE_ENABLE)) {
- temp |= TRANS_ENABLE;
- temp &= ~PIPE_BPC_MASK;
- temp |= pipe_bpc;
- OUTREG(transconf_reg, temp | TRANS_ENABLE);
- n++;
- usleep(500);
- if (n > 20) {
- ErrorF("aborting transcoder %x enable\n", transconf_reg);
- break;
- }
- }
+ temp = INREG(transconf_reg);
+ temp &= ~PIPE_BPC_MASK;
+ temp |= pipe_bpc;
+ OUTREG(transconf_reg, temp | TRANS_ENABLE);
+ INREG(transconf_reg);
- /* wait one idle pattern time */
- usleep(100);
+ while ((INREG(transconf_reg) & TRANS_STATE_ENABLE) == 0)
+ ;
ErrorF("LUT load\n");
i830_crtc_load_lut(crtc);
@@ -1211,14 +1233,14 @@ static void igdng_crtc_dpms(xf86CrtcPtr crtc, int mode)
case DPMSModeOff:
ErrorF("Plane disable\n");
- /* Disable display plane */
- while ((temp = INREG(dspcntr_reg)) & DISPLAY_PLANE_ENABLE) {
- OUTREG(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
- /* Flush the plane changes */
- OUTREG(dspbase_reg, INREG(dspbase_reg));
- INREG(dspbase_reg);
- usleep(10);
+ temp = INREG(dspcntr_reg);
+ if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
+ OUTREG(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
+ /* flush plane changes */
+ OUTREG(dspbase_reg, INREG(dspbase_reg));
+ INREG(dspbase_reg);
}
+
i830_disable_vga_plane (crtc);
ErrorF("Pipe disable\n");
@@ -1232,7 +1254,7 @@ static void igdng_crtc_dpms(xf86CrtcPtr crtc, int mode)
while ((INREG(pipeconf_reg) & I965_PIPECONF_ACTIVE) != 0) {
n++;
if (n < 60) {
- usleep(5000);
+ usleep(500);
continue;
} else {
ErrorF("aborting pipeconf disable early\n");
@@ -1241,26 +1263,28 @@ static void igdng_crtc_dpms(xf86CrtcPtr crtc, int mode)
}
}
+ usleep(100);
+
ErrorF("PFIT disable\n");
- /* Disable PF */
- while ((temp = INREG(pf_ctl_reg)) & PF_ENABLE) {
- OUTREG(pf_ctl_reg, temp & ~PF_ENABLE);
- usleep(10);
+ temp = INREG(pf_ctl_reg);
+ if ((temp & PF_ENABLE) != 0) {
+ OUTREG(pf_ctl_reg, temp & ~PF_ENABLE);
+ INREG(pf_ctl_reg);
}
OUTREG(pf_win_size, 0);
+ INREG(pf_win_size);
ErrorF("FDI TX disable\n");
- /* disable CPU FDI tx and PCH FDI rx */
- while ((temp = INREG(fdi_tx_reg)) & FDI_TX_ENABLE) {
- OUTREG(fdi_tx_reg, temp & ~FDI_TX_ENABLE);
- usleep(10);
- }
+ temp = INREG(fdi_tx_reg);
+ OUTREG(fdi_tx_reg, temp & ~FDI_TX_ENABLE);
+ INREG(fdi_tx_reg);
ErrorF("FDI RX disable\n");
- while ((temp = INREG(fdi_rx_reg)) & FDI_RX_ENABLE) {
- OUTREG(fdi_rx_reg, temp & ~FDI_RX_ENABLE);
- usleep(10);
- }
+ temp = INREG(fdi_rx_reg);
+ temp &= ~(0x07 << 16);
+ temp |= pipe_bpc << 11;
+ OUTREG(fdi_rx_reg, temp & ~FDI_RX_ENABLE);
+ INREG(fdi_rx_reg);
usleep(100);
@@ -1270,19 +1294,22 @@ static void igdng_crtc_dpms(xf86CrtcPtr crtc, int mode)
temp &= ~FDI_LINK_TRAIN_NONE;
temp |= FDI_LINK_TRAIN_PATTERN_1;
OUTREG(fdi_tx_reg, temp);
+ INREG(fdi_tx_reg);
ErrorF("FDI RX train 1 preload\n");
temp = INREG(fdi_rx_reg);
temp &= ~FDI_LINK_TRAIN_NONE;
temp |= FDI_LINK_TRAIN_PATTERN_1;
OUTREG(fdi_rx_reg, temp);
+ INREG(fdi_rx_reg);
usleep(100);
ErrorF("LVDS port force off\n");
if (i830PipeHasType(crtc, I830_OUTPUT_LVDS)) {
while ((temp = INREG(PCH_LVDS)) & PORT_ENABLE) {
- OUTREG(PCH_LVDS, temp & ~PORT_ENABLE);
+ OUTREG(PCH_LVDS, temp & ~LVDS_PORT_EN);
+ INREG(PCH_LVDS);
usleep(100);
}
}
@@ -1307,32 +1334,37 @@ static void igdng_crtc_dpms(xf86CrtcPtr crtc, int mode)
}
}
+ temp = INREG(transconf_reg);
+ temp &= ~PIPE_BPC_MASK;
+ temp |= pipe_bpc;
+ OUTREG(transconf_reg, temp);
+ INREG(transconf_reg);
+ usleep(100);
+
ErrorF("PCH DPLL disable\n");
/* disable PCH DPLL */
- while ((temp = INREG(pch_dpll_reg)) & DPLL_VCO_ENABLE) {
- OUTREG(pch_dpll_reg, temp & ~DPLL_VCO_ENABLE);
- usleep(10);
- }
+ temp = INREG(pch_dpll_reg);
+ OUTREG(pch_dpll_reg, temp & ~DPLL_VCO_ENABLE);
+ INREG(pch_dpll_reg);
ErrorF("FDI RX PLL PCD disable\n");
- while ((temp = INREG(fdi_rx_reg)) & FDI_SEL_PCDCLK) {
- temp &= ~FDI_SEL_PCDCLK;
- OUTREG(fdi_rx_reg, temp);
- usleep(10);
- }
+ temp = INREG(fdi_rx_reg);
+ temp &= ~FDI_SEL_PCDCLK;
+ OUTREG(fdi_rx_reg, temp);
+ temp = INREG(fdi_rx_reg);
- ErrorF("FDI RX PLL disable\n");
- while ((temp = INREG(fdi_rx_reg)) & FDI_RX_PLL_ENABLE) {
- temp &= ~FDI_RX_PLL_ENABLE;
- OUTREG(fdi_rx_reg, temp);
- usleep(10);
- }
+ ErrorF("FDI TX PLL disable %08x\n", temp);
+ temp = INREG(fdi_tx_reg);
+ temp &= ~FDI_TX_PLL_ENABLE;
+ OUTREG(fdi_tx_reg, temp);
+ temp = INREG(fdi_tx_reg);
+ usleep(100);
- ErrorF("FDI TX PLL disable\n");
- while ((temp = INREG(fdi_tx_reg)) & FDI_RX_PLL_ENABLE) {
- OUTREG(fdi_tx_reg, temp & ~FDI_TX_PLL_ENABLE);
- usleep(10);
- }
+ ErrorF("FDI RX PLL disable %08x\n", temp);
+ temp = INREG(fdi_tx_reg);
+ OUTREG(fdi_tx_reg, temp & ~FDI_TX_PLL_ENABLE);
+ INREG(fdi_tx_reg);
+ usleep(100);
ErrorF("DPMS off done\n");
/* Wait for the clocks to turn off. */
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index 4d9cb6be..ce6910fd 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -404,61 +404,47 @@ i830SetLVDSPanelPower(xf86OutputPtr output, Bool on)
struct i830_lvds_priv *dev_priv = intel_output->dev_priv;
ScrnInfoPtr pScrn = output->scrn;
I830Ptr pI830 = I830PTR(pScrn);
- CARD32 pp_status, ctl_reg, status_reg;
+ CARD32 pp_status, ctl_reg, status_reg, lvds_reg;
if (IS_IGDNG(pI830)) {
ctl_reg = PCH_PP_CONTROL;
status_reg = PCH_PP_STATUS;
+ lvds_reg = PCH_LVDS;
} else {
ctl_reg = PP_CONTROL;
status_reg = PP_STATUS;
- }
-
- if (IS_IGDNG(pI830)) {
- CARD32 temp;
- if (on) {
- temp = INREG(PCH_LVDS);
- OUTREG(PCH_LVDS, temp | PORT_ENABLE);
- temp = INREG(PCH_LVDS);
- } else {
- temp = INREG(PCH_LVDS);
- OUTREG(PCH_LVDS, temp & ~PORT_ENABLE);
- temp = INREG(PCH_LVDS);
- }
- usleep(100);
+ lvds_reg = LVDS;
}
if (on) {
- /*
- * If we're going from off->on we may need to turn on the backlight.
- * We should use the saved value whenever possible, but on some
- * machines 0 is a valid backlight value (due to an external backlight
- * controller for example), so on them, when turning LVDS back on,
- * they'll always re-maximize the brightness.
- */
+ OUTREG(lvds_reg, INREG(lvds_reg) | LVDS_PORT_EN);
+ INREG(lvds_reg);
+
if (!(INREG(ctl_reg) & POWER_TARGET_ON) &&
dev_priv->backlight_duty_cycle == 0)
dev_priv->backlight_duty_cycle = dev_priv->backlight_max;
OUTREG(ctl_reg, INREG(ctl_reg) | POWER_TARGET_ON);
+ INREG(ctl_reg);
do {
pp_status = INREG(status_reg);
} while ((pp_status & PP_ON) == 0);
+ /* set backlight */
dev_priv->set_backlight(output, dev_priv->backlight_duty_cycle);
} else {
- /*
- * Only save the current backlight value if we're going from
- * on to off.
- */
if (INREG(ctl_reg) & POWER_TARGET_ON)
dev_priv->backlight_duty_cycle = dev_priv->get_backlight(output);
dev_priv->set_backlight(output, 0);
OUTREG(ctl_reg, INREG(ctl_reg) & ~POWER_TARGET_ON);
+ INREG(ctl_reg);
do {
pp_status = INREG(status_reg);
} while (pp_status & PP_ON);
+
+ OUTREG(lvds_reg, INREG(lvds_reg) & ~LVDS_PORT_EN);
+ INREG(lvds_reg);
}
}