aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c27
1 files changed, 23 insertions, 4 deletions
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 1dc60408d5b8..c768e30e5e85 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1334,17 +1334,24 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
1334 struct drm_device *dev = intel_dp->base.base.dev; 1334 struct drm_device *dev = intel_dp->base.base.dev;
1335 struct drm_i915_private *dev_priv = dev->dev_private; 1335 struct drm_i915_private *dev_priv = dev->dev_private;
1336 bool channel_eq = false; 1336 bool channel_eq = false;
1337 int tries; 1337 int tries, cr_tries;
1338 u32 reg; 1338 u32 reg;
1339 uint32_t DP = intel_dp->DP; 1339 uint32_t DP = intel_dp->DP;
1340 1340
1341 /* channel equalization */ 1341 /* channel equalization */
1342 tries = 0; 1342 tries = 0;
1343 cr_tries = 0;
1343 channel_eq = false; 1344 channel_eq = false;
1344 for (;;) { 1345 for (;;) {
1345 /* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */ 1346 /* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */
1346 uint32_t signal_levels; 1347 uint32_t signal_levels;
1347 1348
1349 if (cr_tries > 5) {
1350 DRM_ERROR("failed to train DP, aborting\n");
1351 intel_dp_link_down(intel_dp);
1352 break;
1353 }
1354
1348 if (IS_GEN6(dev) && is_edp(intel_dp)) { 1355 if (IS_GEN6(dev) && is_edp(intel_dp)) {
1349 signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]); 1356 signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]);
1350 DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; 1357 DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;
@@ -1367,14 +1374,26 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
1367 if (!intel_dp_get_link_status(intel_dp)) 1374 if (!intel_dp_get_link_status(intel_dp))
1368 break; 1375 break;
1369 1376
1377 /* Make sure clock is still ok */
1378 if (!intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) {
1379 intel_dp_start_link_train(intel_dp);
1380 cr_tries++;
1381 continue;
1382 }
1383
1370 if (intel_channel_eq_ok(intel_dp)) { 1384 if (intel_channel_eq_ok(intel_dp)) {
1371 channel_eq = true; 1385 channel_eq = true;
1372 break; 1386 break;
1373 } 1387 }
1374 1388
1375 /* Try 5 times */ 1389 /* Try 5 times, then try clock recovery if that fails */
1376 if (tries > 5) 1390 if (tries > 5) {
1377 break; 1391 intel_dp_link_down(intel_dp);
1392 intel_dp_start_link_train(intel_dp);
1393 tries = 0;
1394 cr_tries++;
1395 continue;
1396 }
1378 1397
1379 /* Compute new intel_dp->train_set as requested by target */ 1398 /* Compute new intel_dp->train_set as requested by target */
1380 intel_get_adjust_train(intel_dp); 1399 intel_get_adjust_train(intel_dp);