aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorImre Deak <imre.deak@intel.com>2013-05-03 05:57:41 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-05-04 04:24:56 -0400
commit3ab9c63705cb7b1b9f83ddce725d8bd9ef7c66a9 (patch)
tree991dc789a5355b487ec8a44d05b0e3a54f34d9de
parent657445fe8660100ad174600ebfa61536392b7624 (diff)
drm/i915: hsw: fix link training for eDP on port-A
According to BSpec the link training sequence for eDP on HSW port-A should be as follows: 1. link training: clock recovery 2. link training: equalization 3. link training: set idle transmission mode 4. display pipe enable 5. link training: disable (set normal mode) Contrary to this at the moment we don't do step 3. and we do step 5. before step 4. Fix this by setting idle transmission mode for eDP at the end of intel_dp_complete_link_train and adding a new intel_dp_stop_link_training function to disable link training. With these changes we'll end up with the following functions corresponding to the above steps: intel_dp_start_link_train -> step 1. intel_dp_complete_link_train -> step 2., step 3. intel_dp_stop_link_train -> step 5. For port-A we'll call intel_dp_stop_link_train only after enabling the pipe, for everything else we'll call it right after intel_dp_complete_link_train to preserve the current behavior. Tested on HSW/HSW-ULT. In v2: - Due to a HW issue we must set idle transmission mode for port-A too before enabling the pipe. Thanks for Arthur Runyan for explaining this. - Update the patch subject to make it clear that it's an eDP fix, DP is not affected. v3: - rename intel_dp_link_train() to intel_dp_set_link_train(), use 'val' instead 'l' as var name. (Paulo) Signed-off-by: Imre Deak <imre.deak@intel.com> Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com> Tested-by: Paulo Zanoni <paulo.r.zanoni@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/i915/intel_ddi.c5
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c59
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h1
3 files changed, 50 insertions, 15 deletions
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 26a0a570f92e..fb961bb81903 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1265,6 +1265,8 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
1265 intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); 1265 intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
1266 intel_dp_start_link_train(intel_dp); 1266 intel_dp_start_link_train(intel_dp);
1267 intel_dp_complete_link_train(intel_dp); 1267 intel_dp_complete_link_train(intel_dp);
1268 if (port != PORT_A)
1269 intel_dp_stop_link_train(intel_dp);
1268 } 1270 }
1269} 1271}
1270 1272
@@ -1326,6 +1328,9 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder)
1326 } else if (type == INTEL_OUTPUT_EDP) { 1328 } else if (type == INTEL_OUTPUT_EDP) {
1327 struct intel_dp *intel_dp = enc_to_intel_dp(encoder); 1329 struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
1328 1330
1331 if (port == PORT_A)
1332 intel_dp_stop_link_train(intel_dp);
1333
1329 ironlake_edp_backlight_on(intel_dp); 1334 ironlake_edp_backlight_on(intel_dp);
1330 } 1335 }
1331 1336
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 0ab9813a79b5..93694da7f717 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1379,6 +1379,7 @@ static void intel_enable_dp(struct intel_encoder *encoder)
1379 ironlake_edp_panel_on(intel_dp); 1379 ironlake_edp_panel_on(intel_dp);
1380 ironlake_edp_panel_vdd_off(intel_dp, true); 1380 ironlake_edp_panel_vdd_off(intel_dp, true);
1381 intel_dp_complete_link_train(intel_dp); 1381 intel_dp_complete_link_train(intel_dp);
1382 intel_dp_stop_link_train(intel_dp);
1382 ironlake_edp_backlight_on(intel_dp); 1383 ironlake_edp_backlight_on(intel_dp);
1383} 1384}
1384 1385
@@ -1701,10 +1702,9 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
1701 struct drm_i915_private *dev_priv = dev->dev_private; 1702 struct drm_i915_private *dev_priv = dev->dev_private;
1702 enum port port = intel_dig_port->port; 1703 enum port port = intel_dig_port->port;
1703 int ret; 1704 int ret;
1704 uint32_t temp;
1705 1705
1706 if (HAS_DDI(dev)) { 1706 if (HAS_DDI(dev)) {
1707 temp = I915_READ(DP_TP_CTL(port)); 1707 uint32_t temp = I915_READ(DP_TP_CTL(port));
1708 1708
1709 if (dp_train_pat & DP_LINK_SCRAMBLING_DISABLE) 1709 if (dp_train_pat & DP_LINK_SCRAMBLING_DISABLE)
1710 temp |= DP_TP_CTL_SCRAMBLE_DISABLE; 1710 temp |= DP_TP_CTL_SCRAMBLE_DISABLE;
@@ -1714,18 +1714,6 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
1714 temp &= ~DP_TP_CTL_LINK_TRAIN_MASK; 1714 temp &= ~DP_TP_CTL_LINK_TRAIN_MASK;
1715 switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) { 1715 switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
1716 case DP_TRAINING_PATTERN_DISABLE: 1716 case DP_TRAINING_PATTERN_DISABLE:
1717
1718 if (port != PORT_A) {
1719 temp |= DP_TP_CTL_LINK_TRAIN_IDLE;
1720 I915_WRITE(DP_TP_CTL(port), temp);
1721
1722 if (wait_for((I915_READ(DP_TP_STATUS(port)) &
1723 DP_TP_STATUS_IDLE_DONE), 1))
1724 DRM_ERROR("Timed out waiting for DP idle patterns\n");
1725
1726 temp &= ~DP_TP_CTL_LINK_TRAIN_MASK;
1727 }
1728
1729 temp |= DP_TP_CTL_LINK_TRAIN_NORMAL; 1717 temp |= DP_TP_CTL_LINK_TRAIN_NORMAL;
1730 1718
1731 break; 1719 break;
@@ -1801,6 +1789,37 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
1801 return true; 1789 return true;
1802} 1790}
1803 1791
1792static void intel_dp_set_idle_link_train(struct intel_dp *intel_dp)
1793{
1794 struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
1795 struct drm_device *dev = intel_dig_port->base.base.dev;
1796 struct drm_i915_private *dev_priv = dev->dev_private;
1797 enum port port = intel_dig_port->port;
1798 uint32_t val;
1799
1800 if (!HAS_DDI(dev))
1801 return;
1802
1803 val = I915_READ(DP_TP_CTL(port));
1804 val &= ~DP_TP_CTL_LINK_TRAIN_MASK;
1805 val |= DP_TP_CTL_LINK_TRAIN_IDLE;
1806 I915_WRITE(DP_TP_CTL(port), val);
1807
1808 /*
1809 * On PORT_A we can have only eDP in SST mode. There the only reason
1810 * we need to set idle transmission mode is to work around a HW issue
1811 * where we enable the pipe while not in idle link-training mode.
1812 * In this case there is requirement to wait for a minimum number of
1813 * idle patterns to be sent.
1814 */
1815 if (port == PORT_A)
1816 return;
1817
1818 if (wait_for((I915_READ(DP_TP_STATUS(port)) & DP_TP_STATUS_IDLE_DONE),
1819 1))
1820 DRM_ERROR("Timed out waiting for DP idle patterns\n");
1821}
1822
1804/* Enable corresponding port and start training pattern 1 */ 1823/* Enable corresponding port and start training pattern 1 */
1805void 1824void
1806intel_dp_start_link_train(struct intel_dp *intel_dp) 1825intel_dp_start_link_train(struct intel_dp *intel_dp)
@@ -1943,10 +1962,19 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
1943 ++tries; 1962 ++tries;
1944 } 1963 }
1945 1964
1965 intel_dp_set_idle_link_train(intel_dp);
1966
1967 intel_dp->DP = DP;
1968
1946 if (channel_eq) 1969 if (channel_eq)
1947 DRM_DEBUG_KMS("Channel EQ done. DP Training successfull\n"); 1970 DRM_DEBUG_KMS("Channel EQ done. DP Training successfull\n");
1948 1971
1949 intel_dp_set_link_train(intel_dp, DP, DP_TRAINING_PATTERN_DISABLE); 1972}
1973
1974void intel_dp_stop_link_train(struct intel_dp *intel_dp)
1975{
1976 intel_dp_set_link_train(intel_dp, intel_dp->DP,
1977 DP_TRAINING_PATTERN_DISABLE);
1950} 1978}
1951 1979
1952static void 1980static void
@@ -2154,6 +2182,7 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)
2154 drm_get_encoder_name(&intel_encoder->base)); 2182 drm_get_encoder_name(&intel_encoder->base));
2155 intel_dp_start_link_train(intel_dp); 2183 intel_dp_start_link_train(intel_dp);
2156 intel_dp_complete_link_train(intel_dp); 2184 intel_dp_complete_link_train(intel_dp);
2185 intel_dp_stop_link_train(intel_dp);
2157 } 2186 }
2158} 2187}
2159 2188
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index b5b6d19e6dd3..624a9e6b8d71 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -499,6 +499,7 @@ extern void intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
499extern void intel_dp_init_link_config(struct intel_dp *intel_dp); 499extern void intel_dp_init_link_config(struct intel_dp *intel_dp);
500extern void intel_dp_start_link_train(struct intel_dp *intel_dp); 500extern void intel_dp_start_link_train(struct intel_dp *intel_dp);
501extern void intel_dp_complete_link_train(struct intel_dp *intel_dp); 501extern void intel_dp_complete_link_train(struct intel_dp *intel_dp);
502extern void intel_dp_stop_link_train(struct intel_dp *intel_dp);
502extern void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode); 503extern void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode);
503extern void intel_dp_encoder_destroy(struct drm_encoder *encoder); 504extern void intel_dp_encoder_destroy(struct drm_encoder *encoder);
504extern void intel_dp_check_link_status(struct intel_dp *intel_dp); 505extern void intel_dp_check_link_status(struct intel_dp *intel_dp);