summaryrefslogtreecommitdiff
path: root/src/i830_display.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/i830_display.c')
-rw-r--r--src/i830_display.c212
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);