aboutsummaryrefslogtreecommitdiff
path: root/src/drivers/intel/gma
diff options
context:
space:
mode:
Diffstat (limited to 'src/drivers/intel/gma')
-rw-r--r--src/drivers/intel/gma/i915.h5
-rw-r--r--src/drivers/intel/gma/intel_ddi.c52
-rw-r--r--src/drivers/intel/gma/intel_dp.c20
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