diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_dp.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 50 |
1 files changed, 39 insertions, 11 deletions
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 1dc60408d5b..1f4242b682c 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
@@ -1153,18 +1153,27 @@ intel_dp_signal_levels(uint8_t train_set, int lane_count) | |||
1153 | static uint32_t | 1153 | static uint32_t |
1154 | intel_gen6_edp_signal_levels(uint8_t train_set) | 1154 | intel_gen6_edp_signal_levels(uint8_t train_set) |
1155 | { | 1155 | { |
1156 | switch (train_set & (DP_TRAIN_VOLTAGE_SWING_MASK|DP_TRAIN_PRE_EMPHASIS_MASK)) { | 1156 | int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK | |
1157 | DP_TRAIN_PRE_EMPHASIS_MASK); | ||
1158 | switch (signal_levels) { | ||
1157 | case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0: | 1159 | case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0: |
1158 | return EDP_LINK_TRAIN_400MV_0DB_SNB_B; | 1160 | case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_0: |
1161 | return EDP_LINK_TRAIN_400_600MV_0DB_SNB_B; | ||
1162 | case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_3_5: | ||
1163 | return EDP_LINK_TRAIN_400MV_3_5DB_SNB_B; | ||
1159 | case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_6: | 1164 | case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_6: |
1160 | return EDP_LINK_TRAIN_400MV_6DB_SNB_B; | 1165 | case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_6: |
1166 | return EDP_LINK_TRAIN_400_600MV_6DB_SNB_B; | ||
1161 | case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_3_5: | 1167 | case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_3_5: |
1162 | return EDP_LINK_TRAIN_600MV_3_5DB_SNB_B; | 1168 | case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_3_5: |
1169 | return EDP_LINK_TRAIN_600_800MV_3_5DB_SNB_B; | ||
1163 | case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_0: | 1170 | case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_0: |
1164 | return EDP_LINK_TRAIN_800MV_0DB_SNB_B; | 1171 | case DP_TRAIN_VOLTAGE_SWING_1200 | DP_TRAIN_PRE_EMPHASIS_0: |
1172 | return EDP_LINK_TRAIN_800_1200MV_0DB_SNB_B; | ||
1165 | default: | 1173 | default: |
1166 | DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level\n"); | 1174 | DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level:" |
1167 | return EDP_LINK_TRAIN_400MV_0DB_SNB_B; | 1175 | "0x%x\n", signal_levels); |
1176 | return EDP_LINK_TRAIN_400_600MV_0DB_SNB_B; | ||
1168 | } | 1177 | } |
1169 | } | 1178 | } |
1170 | 1179 | ||
@@ -1334,17 +1343,24 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) | |||
1334 | struct drm_device *dev = intel_dp->base.base.dev; | 1343 | struct drm_device *dev = intel_dp->base.base.dev; |
1335 | struct drm_i915_private *dev_priv = dev->dev_private; | 1344 | struct drm_i915_private *dev_priv = dev->dev_private; |
1336 | bool channel_eq = false; | 1345 | bool channel_eq = false; |
1337 | int tries; | 1346 | int tries, cr_tries; |
1338 | u32 reg; | 1347 | u32 reg; |
1339 | uint32_t DP = intel_dp->DP; | 1348 | uint32_t DP = intel_dp->DP; |
1340 | 1349 | ||
1341 | /* channel equalization */ | 1350 | /* channel equalization */ |
1342 | tries = 0; | 1351 | tries = 0; |
1352 | cr_tries = 0; | ||
1343 | channel_eq = false; | 1353 | channel_eq = false; |
1344 | for (;;) { | 1354 | for (;;) { |
1345 | /* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */ | 1355 | /* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */ |
1346 | uint32_t signal_levels; | 1356 | uint32_t signal_levels; |
1347 | 1357 | ||
1358 | if (cr_tries > 5) { | ||
1359 | DRM_ERROR("failed to train DP, aborting\n"); | ||
1360 | intel_dp_link_down(intel_dp); | ||
1361 | break; | ||
1362 | } | ||
1363 | |||
1348 | if (IS_GEN6(dev) && is_edp(intel_dp)) { | 1364 | if (IS_GEN6(dev) && is_edp(intel_dp)) { |
1349 | signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]); | 1365 | signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]); |
1350 | DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; | 1366 | DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; |
@@ -1367,14 +1383,26 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) | |||
1367 | if (!intel_dp_get_link_status(intel_dp)) | 1383 | if (!intel_dp_get_link_status(intel_dp)) |
1368 | break; | 1384 | break; |
1369 | 1385 | ||
1386 | /* Make sure clock is still ok */ | ||
1387 | if (!intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) { | ||
1388 | intel_dp_start_link_train(intel_dp); | ||
1389 | cr_tries++; | ||
1390 | continue; | ||
1391 | } | ||
1392 | |||
1370 | if (intel_channel_eq_ok(intel_dp)) { | 1393 | if (intel_channel_eq_ok(intel_dp)) { |
1371 | channel_eq = true; | 1394 | channel_eq = true; |
1372 | break; | 1395 | break; |
1373 | } | 1396 | } |
1374 | 1397 | ||
1375 | /* Try 5 times */ | 1398 | /* Try 5 times, then try clock recovery if that fails */ |
1376 | if (tries > 5) | 1399 | if (tries > 5) { |
1377 | break; | 1400 | intel_dp_link_down(intel_dp); |
1401 | intel_dp_start_link_train(intel_dp); | ||
1402 | tries = 0; | ||
1403 | cr_tries++; | ||
1404 | continue; | ||
1405 | } | ||
1378 | 1406 | ||
1379 | /* Compute new intel_dp->train_set as requested by target */ | 1407 | /* Compute new intel_dp->train_set as requested by target */ |
1380 | intel_get_adjust_train(intel_dp); | 1408 | intel_get_adjust_train(intel_dp); |