diff options
Diffstat (limited to 'src/drivers/intel')
-rw-r--r-- | src/drivers/intel/gma/i915.h | 5 | ||||
-rw-r--r-- | src/drivers/intel/gma/intel_ddi.c | 52 | ||||
-rw-r--r-- | src/drivers/intel/gma/intel_dp.c | 20 |
3 files changed, 77 insertions, 0 deletions
diff --git a/src/drivers/intel/gma/i915.h b/src/drivers/intel/gma/i915.h index 37570649f9..e976f912cc 100644 --- a/src/drivers/intel/gma/i915.h +++ b/src/drivers/intel/gma/i915.h @@ -178,3 +178,8 @@ u8 drm_dp_get_adjust_request_pre_emphasis(u8 link_status[DP_LINK_STATUS_SIZE], int lane); +void intel_dp_wait_reg(unsigned long addr, + unsigned long val); + +void intel_dp_wait_panel_power_control(unsigned long val); + diff --git a/src/drivers/intel/gma/intel_ddi.c b/src/drivers/intel/gma/intel_ddi.c index 659d73ca04..220bd47100 100644 --- a/src/drivers/intel/gma/intel_ddi.c +++ b/src/drivers/intel/gma/intel_ddi.c @@ -105,3 +105,55 @@ void intel_prepare_ddi_buffers(int port, int use_fdi_mode) } } +static void intel_wait_ddi_buf_idle(int port) +{ + uint32_t reg = DDI_BUF_CTL(port); + int i; + + for (i = 0; i < 8; i++) { + udelay(1); + if (io_i915_read32(reg) & DDI_BUF_IS_IDLE){ + printk(BIOS_SPEW, "%s: buf is idle (success)\n", __func__); + return; + } + } + printk(BIOS_ERR, "Timeout waiting for DDI BUF %d idle bit\n", port); +} + + +void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp, int port) +{ + int wait; + uint32_t val; + + if (io_i915_read32(DP_TP_CTL(port)) & DP_TP_CTL_ENABLE) { + val = io_i915_read32(DDI_BUF_CTL(port)); + if (val & DDI_BUF_CTL_ENABLE) { + val &= ~DDI_BUF_CTL_ENABLE; + io_i915_write32(DDI_BUF_CTL(port), val); + wait = 1; + } + + val = io_i915_read32(DP_TP_CTL(port)); + val &= ~(DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_MASK); + val |= DP_TP_CTL_LINK_TRAIN_PAT1; + io_i915_write32(DP_TP_CTL(port), val); + //POSTING_READ(DP_TP_CTL(port)); + + if (wait) + intel_wait_ddi_buf_idle(port); + } + + val = DP_TP_CTL_ENABLE | DP_TP_CTL_MODE_SST | + DP_TP_CTL_LINK_TRAIN_PAT1 | DP_TP_CTL_SCRAMBLE_DISABLE; + if (intel_dp->link_configuration[1] & DP_LANE_COUNT_ENHANCED_FRAME_EN) + val |= DP_TP_CTL_ENHANCED_FRAME_ENABLE; + io_i915_write32(DP_TP_CTL(port), val); + //POSTING_READ(DP_TP_CTL(port)); + + intel_dp->DP |= DDI_BUF_CTL_ENABLE; + io_i915_write32(DDI_BUF_CTL(port), intel_dp->DP); + //POSTING_READ(DDI_BUF_CTL(port)); + + udelay(600); +} diff --git a/src/drivers/intel/gma/intel_dp.c b/src/drivers/intel/gma/intel_dp.c index 4b5f7c49c1..8097c6aca5 100644 --- a/src/drivers/intel/gma/intel_dp.c +++ b/src/drivers/intel/gma/intel_dp.c @@ -621,6 +621,26 @@ static void ironlake_wait_panel_power_cycle(struct intel_dp *intel_dp) ironlake_wait_panel_status(intel_dp, IDLE_CYCLE_MASK, IDLE_CYCLE_VALUE); } +void intel_dp_wait_reg(unsigned long addr, + unsigned long val) +{ + unsigned long newval; + int tries = 0; + + while ((newval = io_i915_read32(addr)) != val) { + udelay(1); + if (tries++ > 1000) { + printk(BIOS_ERR, "%s: Waiting on %08lx to be %08lx, got %08lx\n", + __func__, addr, val, newval); + break; + } + } +} + +void intel_dp_wait_panel_power_control(unsigned long val) +{ + intel_dp_wait_reg(PCH_PP_CONTROL, val); +} /* Read the current pp_control value, unlocking the register if it * is locked |