diff options
Diffstat (limited to 'src/i830_display.c')
-rw-r--r-- | src/i830_display.c | 212 |
1 files changed, 191 insertions, 21 deletions
diff --git a/src/i830_display.c b/src/i830_display.c index febcf5a4..dd26d8f0 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -1367,6 +1367,124 @@ static void ironlake_fdi_link_train(xf86CrtcPtr crtc) ErrorF("FDI train done\n"); } +static const int snb_b_fdi_train_param [] = { + FDI_LINK_TRAIN_400MV_0DB_SNB_B, + FDI_LINK_TRAIN_400MV_6DB_SNB_B, + FDI_LINK_TRAIN_600MV_3_5DB_SNB_B, + FDI_LINK_TRAIN_800MV_0DB_SNB_B, +}; + +static void gen6_fdi_link_train(xf86CrtcPtr crtc) +{ + ScrnInfoPtr scrn = crtc->scrn; + intel_screen_private *intel = intel_get_screen_private(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, i = 0; + + /* 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); + + /* 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; + temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; + /* SNB-B */ + temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B; + OUTREG(fdi_tx_reg, temp); + INREG(fdi_tx_reg); + + temp = INREG(fdi_rx_reg); + if (1) { // XXX HAS_PCH_CPT(dev)) { + temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; + temp |= FDI_LINK_TRAIN_PATTERN_1_CPT; + } else { + 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); + + for (i = 0; i < 4; i++) { + temp = INREG(fdi_tx_reg); + temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; + temp |= snb_b_fdi_train_param[i]; + OUTREG(fdi_tx_reg, temp); + INREG(fdi_tx_reg); + + 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; + } + } + if (i == 4) + ErrorF("FDI train 1 fail!\n"); + + /* Train 2 */ + temp = INREG(fdi_tx_reg); + temp &= ~FDI_LINK_TRAIN_NONE; + temp |= FDI_LINK_TRAIN_PATTERN_2; + if (IS_GEN6(intel)) { + temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; + /* SNB-B */ + temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B; + } + OUTREG(fdi_tx_reg, temp); + + temp = INREG(fdi_rx_reg); + if (1) { // XXX HAS_PCH_CPT(dev)) { + temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; + temp |= FDI_LINK_TRAIN_PATTERN_2_CPT; + } else { + temp &= ~FDI_LINK_TRAIN_NONE; + temp |= FDI_LINK_TRAIN_PATTERN_2; + } + OUTREG(fdi_rx_reg, temp); + usleep(150); + + for (i = 0; i < 4; i++) { + temp = INREG(fdi_tx_reg); + temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; + temp |= snb_b_fdi_train_param[i]; + OUTREG(fdi_tx_reg, temp); + INREG(fdi_tx_reg); + + temp = INREG(fdi_rx_iir_reg); + ErrorF("FDI_RX_IIR 0x%x\n", temp); + + if ((temp & FDI_RX_SYMBOL_LOCK)) { + ErrorF("FDI train 2 done.\n"); + OUTREG(fdi_rx_iir_reg, + temp | FDI_RX_SYMBOL_LOCK); + break; + } + } + if (i == 4) + ErrorF("FDI train 2 fail!\n"); + + ErrorF("FDI train done\n"); +} + static void ironlake_crtc_enable(xf86CrtcPtr crtc) { @@ -1404,7 +1522,10 @@ ironlake_crtc_enable(xf86CrtcPtr crtc) /* XXX no LVDS port force */ if (i830PipeHasType(crtc, I830_OUTPUT_LVDS)) { + ErrorF("LVDS port force on\n"); temp = INREG(PCH_LVDS); + OUTREG(PCH_LVDS, temp | LVDS_PORT_EN); + INREG(PCH_LVDS); if ((temp & LVDS_PORT_EN) == 0) { OUTREG(PCH_LVDS, temp | LVDS_PORT_EN); INREG(PCH_LVDS); @@ -1422,6 +1543,7 @@ ironlake_crtc_enable(xf86CrtcPtr crtc) INREG(fdi_rx_reg); usleep(200); + /* Switch from Rawclk to PCDclk */ temp = INREG(fdi_rx_reg); OUTREG(fdi_rx_reg, temp | FDI_SEL_PCDCLK); temp = INREG(fdi_rx_reg); @@ -1435,8 +1557,10 @@ ironlake_crtc_enable(xf86CrtcPtr crtc) usleep(100); } + i830WaitForVblank(scrn); + /* Enable panel fitting for LVDS */ #define PF_FILTER_MASK (3<<23) #define PF_FILTER_MED_3x3 (1<<23) if (i830PipeHasType(crtc, I830_OUTPUT_LVDS)) { @@ -1471,7 +1595,10 @@ ironlake_crtc_enable(xf86CrtcPtr crtc) OUTREG(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE); /* Train FDI. */ - ironlake_fdi_link_train(crtc); + if (IS_GEN6(intel)) + gen6_fdi_link_train(crtc); + else + ironlake_fdi_link_train(crtc); /* enable PCH DPLL */ temp = INREG(pch_dpll_reg); @@ -1481,6 +1608,16 @@ ironlake_crtc_enable(xf86CrtcPtr crtc) } usleep(200); + if (1) { // XXX HAS_PCH_CPT + /* Be sure PCH DPLL SEL is set */ + temp = INREG(PCH_DPLL_SEL); + if (pipe == 0 && (temp & TRANSA_DPLL_ENABLE) == 0) + temp |= (TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL); + else if (pipe == 1 && (temp & TRANSB_DPLL_ENABLE) == 0) + temp |= (TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL); + OUTREG(PCH_DPLL_SEL, temp); + } + /* set transcoder timing */ OUTREG(trans_htot_reg, INREG(cpu_htot_reg)); OUTREG(trans_hblank_reg, INREG(cpu_hblank_reg)); @@ -1490,7 +1627,7 @@ ironlake_crtc_enable(xf86CrtcPtr crtc) OUTREG(trans_vblank_reg, INREG(cpu_vblank_reg)); OUTREG(trans_vsync_reg, INREG(cpu_vsync_reg)); - /* enable normal */ + /* enable normal train */ ErrorF("FDI TX link normal\n"); temp = INREG(fdi_tx_reg); @@ -1500,15 +1637,18 @@ ironlake_crtc_enable(xf86CrtcPtr crtc) INREG(fdi_tx_reg); temp = INREG(fdi_rx_reg); - temp &= ~FDI_LINK_TRAIN_NONE; - temp |= FDI_LINK_TRAIN_NONE; - - OUTREG(fdi_rx_reg, temp | FDI_LINK_TRAIN_NONE); + if (1) { //HAS_PCH_CPT(dev)) { + temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; + temp |= FDI_LINK_TRAIN_NORMAL_CPT; + } else { + temp &= ~FDI_LINK_TRAIN_NONE; + temp |= FDI_LINK_TRAIN_NONE; + } + OUTREG(fdi_rx_reg, temp | FDI_RX_ENHANCE_FRAME_ENABLE); INREG(fdi_rx_reg); usleep(100); - ErrorF("transcoder enable\n"); /* enable transcoder */ temp = INREG(transconf_reg); temp &= ~PIPE_BPC_MASK; @@ -1519,7 +1659,6 @@ ironlake_crtc_enable(xf86CrtcPtr crtc) while ((INREG(transconf_reg) & TRANS_STATE_ENABLE) == 0) ; - ErrorF("LUT load\n"); i830_crtc_load_lut(crtc); ErrorF("DPMS on done\n"); @@ -1618,15 +1757,20 @@ ironlake_crtc_disable(xf86CrtcPtr crtc) ErrorF("FDI RX train 1 preload\n"); temp = INREG(fdi_rx_reg); - temp &= ~FDI_LINK_TRAIN_NONE; - temp |= FDI_LINK_TRAIN_PATTERN_1; + if (1) { // XXX HAS_PCH_CPT(dev) + temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; + temp |= FDI_LINK_TRAIN_PATTERN_1_CPT; + } else { + 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)) { + ErrorF("LVDS port force off\n"); while ((temp = INREG(PCH_LVDS)) & PORT_ENABLE) { OUTREG(PCH_LVDS, temp & ~LVDS_PORT_EN); INREG(PCH_LVDS); @@ -1661,13 +1805,16 @@ ironlake_crtc_disable(xf86CrtcPtr crtc) INREG(transconf_reg); usleep(100); - ErrorF("PCH DPLL disable\n"); - /* disable PCH DPLL */ - temp = INREG(pch_dpll_reg); - OUTREG(pch_dpll_reg, temp & ~DPLL_VCO_ENABLE); - INREG(pch_dpll_reg); + if (1) { // XXX HAS_PCH_CPT(dev) + ErrorF("PCH DPLL disable\n"); + /* disable PCH DPLL */ + temp = INREG(pch_dpll_reg); + OUTREG(pch_dpll_reg, temp & ~DPLL_VCO_ENABLE); + INREG(pch_dpll_reg); + } ErrorF("FDI RX PLL PCD disable\n"); + /* Switch from PCDclk to Rawclk */ temp = INREG(fdi_rx_reg); temp &= ~FDI_SEL_PCDCLK; OUTREG(fdi_rx_reg, temp); @@ -2384,10 +2531,18 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, lvds = INREG(lvds_reg); lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP; - if (IS_IGDNG(intel)) - lvds |= (pipe == 1) ? LVDS_PIPEB_SELECT : 0; - else - lvds |= LVDS_PIPEB_SELECT; + if (pipe == 1) { + if (IS_IGDNG(intel)) + lvds |= PORT_TRANS_B_SEL_CPT; + else + lvds |= LVDS_PIPEB_SELECT; + } else { + if (IS_IGDNG(intel)) + lvds &= ~PORT_TRANS_SEL_MASK; + else + lvds &= ~LVDS_PIPEB_SELECT; + } + /* Set the B0-B3 data pairs corresponding to whether we're going to * set the DPLLs for dual-channel mode or not. */ @@ -2427,6 +2582,21 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, POSTING_READ(lvds_reg); } + if (IS_IGDNG(intel)) { + /* For non-DP output, clear any trans DP clock recovery setting.*/ + if (pipe == 0) { + OUTREG(TRANSA_DATA_M1, 0); + OUTREG(TRANSA_DATA_N1, 0); + OUTREG(TRANSA_DP_LINK_M1, 0); + OUTREG(TRANSA_DP_LINK_N1, 0); + } else { + OUTREG(TRANSB_DATA_M1, 0); + OUTREG(TRANSB_DATA_N1, 0); + OUTREG(TRANSB_DP_LINK_M1, 0); + OUTREG(TRANSB_DP_LINK_N1, 0); + } + } + OUTREG(fp_reg, fp); /* OUTREG(fp_reg + 4, fp); RHEL had this... wtf? */ OUTREG(dpll_reg, dpll); @@ -2497,7 +2667,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, POSTING_READ(pipeconf_reg); i830WaitForVblank(scrn); - if (IS_IGDNG(intel)) { + if (IS_IGDNG(intel) && !IS_GEN6(intel)) { /* enable address swizzle for tiling buffer */ temp = INREG(DISP_ARB_CTL); OUTREG(DISP_ARB_CTL, temp | DISP_TILE_SURFACE_SWIZZLING); |