diff options
-rw-r--r-- | drivers/gpu/drm/i915/intel_ddi.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 59 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 1 |
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 | ||
1792 | static 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 */ |
1805 | void | 1824 | void |
1806 | intel_dp_start_link_train(struct intel_dp *intel_dp) | 1825 | intel_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 | |||
1974 | void 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 | ||
1952 | static void | 1980 | static 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, | |||
499 | extern void intel_dp_init_link_config(struct intel_dp *intel_dp); | 499 | extern void intel_dp_init_link_config(struct intel_dp *intel_dp); |
500 | extern void intel_dp_start_link_train(struct intel_dp *intel_dp); | 500 | extern void intel_dp_start_link_train(struct intel_dp *intel_dp); |
501 | extern void intel_dp_complete_link_train(struct intel_dp *intel_dp); | 501 | extern void intel_dp_complete_link_train(struct intel_dp *intel_dp); |
502 | extern void intel_dp_stop_link_train(struct intel_dp *intel_dp); | ||
502 | extern void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode); | 503 | extern void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode); |
503 | extern void intel_dp_encoder_destroy(struct drm_encoder *encoder); | 504 | extern void intel_dp_encoder_destroy(struct drm_encoder *encoder); |
504 | extern void intel_dp_check_link_status(struct intel_dp *intel_dp); | 505 | extern void intel_dp_check_link_status(struct intel_dp *intel_dp); |