diff options
author | Owain G. Ainsworth <oga@openbsd.org> | 2010-05-29 16:43:01 +0100 |
---|---|---|
committer | Owain G. Ainsworth <oga@openbsd.org> | 2010-05-29 16:43:01 +0100 |
commit | 893bd522245c4e809d6912972f8baf581e052f94 (patch) | |
tree | b2343107110a594a795572f0b81580f30a9c9510 | |
parent | 7585b82894a80e9deab0c22935f11e5839154c2a (diff) |
port over ironlake fdi/dpms code from 2.6.34 kernel
(cherry picked from commit 00e824b7cd59000e118dad55f563823b65148e01)
Conflicts:
src/i830_display.c
src/i830_lvds.c
from RHEL5 ironlake branch, courtesy of airlied.
-rw-r--r-- | src/i830_display.c | 351 | ||||
-rw-r--r-- | src/i830_lvds.c | 41 |
2 files changed, 201 insertions, 191 deletions
diff --git a/src/i830_display.c b/src/i830_display.c index bdf0191e..fa2d94e8 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -1487,6 +1487,100 @@ i830_crtc_disable(xf86CrtcPtr crtc, Bool disable_pipe) i830_disable_vga_plane (crtc); } +static void ironlake_fdi_link_train(xf86CrtcPtr crtc) +{ + ScrnInfoPtr scrn = crtc->scrn; + intel_screen_private *intel = intel_get_screen_private(scrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + 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 scrn = crtc->scrn; @@ -1538,38 +1632,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); } @@ -1589,7 +1680,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); @@ -1597,7 +1689,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)); @@ -1607,80 +1700,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(scrn->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); + /* enable 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); } + usleep(200); - 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); - } - if (j == tries) - xf86DrvMsg(scrn->scrnIndex, X_WARNING, "train 2 failed\n"); - - usleep(500); - - ErrorF("transcoder timing\n"); /* set transcoder timing */ OUTREG(trans_htot_reg, INREG(cpu_htot_reg)); OUTREG(trans_hblank_reg, INREG(cpu_hblank_reg)); @@ -1693,41 +1722,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); @@ -1738,14 +1757,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"); @@ -1759,7 +1778,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"); @@ -1768,26 +1787,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); @@ -1797,19 +1818,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); } } @@ -1834,32 +1858,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 34b3cbce..8f7044d9 100644 --- a/src/i830_lvds.c +++ b/src/i830_lvds.c @@ -510,68 +510,49 @@ i830SetLVDSPanelPower(xf86OutputPtr output, Bool on) struct i830_lvds_priv *dev_priv = intel_output->dev_priv; ScrnInfoPtr scrn = output->scrn; intel_screen_private *intel = intel_get_screen_private(scrn); - uint32_t pp_status, ctl_reg, status_reg; + uint32_t pp_status, ctl_reg, status_reg, lvds_reg; if (IS_IGDNG(intel)) { 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(intel)) { - 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 on->on, be aware to current level. */ - if ((INREG(ctl_reg) & POWER_TARGET_ON) && !dev_priv->dpmsoff) - dev_priv->backlight_duty_cycle = dev_priv->get_backlight(output); + OUTREG(lvds_reg, INREG(lvds_reg) | LVDS_PORT_EN); + INREG(lvds_reg); - /* - * 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. - */ if (!(INREG(ctl_reg) & POWER_TARGET_ON) && dev_priv->backlight_duty_cycle == 0 && intel->backlight_control_method < BCM_KERNEL) 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); dev_priv->dpmsoff = FALSE; } else { - /* - * Only save the current backlight value if we're going from - * on to off. - */ if ((INREG(ctl_reg) & POWER_TARGET_ON) && !dev_priv->dpmsoff) 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); dev_priv->dpmsoff = TRUE; } } |