aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2011-01-05 17:45:24 -0500
committerChris Wilson <chris@chris-wilson.co.uk>2011-01-11 15:22:23 -0500
commit37f809755845cc3e18e8216c04525bdb885fa13b (patch)
tree6665530a9bf156653ffcfa8a3de7f07741ec3947
parent858bc21f0637c407601a05626854ae58b242f75d (diff)
drm/i915: make DP training try a little harder
When trying to do channel equalization, we need to make sure we still have clock recovery on all lanes while training. We also need to try clock recovery again if we lose the clock or if channel eq fails 5 times. We'll try clock recovery up to 5 more times before giving up entirely. Gets suspend/resume working on my Vaio again and brings us back into compliance with the DP training sequence spec. Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-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);