diff options
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 27 |
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); |