diff options
author | Jesse Barnes <jbarnes@virtuousgeek.org> | 2010-10-07 19:01:22 -0400 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-10-08 05:28:26 -0400 |
commit | 869184a675662bddcdf76c5b95665272facff2b8 (patch) | |
tree | 6c11929082b43d378405bb657cfaf699e9bb6b6b /drivers/gpu/drm/i915 | |
parent | 896673836b8c55b75e7d7d2741aaaadff0c6a038 (diff) |
drm/i915/dp: use VBT provided eDP params if available
We can skip most of the link training step if we use the VBT provided
values.
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'drivers/gpu/drm/i915')
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 146 |
1 files changed, 89 insertions, 57 deletions
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 7fa828275e4a..d4ef20598da8 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
@@ -581,6 +581,17 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, | |||
581 | mode->clock = dev_priv->panel_fixed_mode->clock; | 581 | mode->clock = dev_priv->panel_fixed_mode->clock; |
582 | } | 582 | } |
583 | 583 | ||
584 | /* Just use VBT values for eDP */ | ||
585 | if (is_edp(intel_dp)) { | ||
586 | intel_dp->lane_count = dev_priv->edp.lanes; | ||
587 | intel_dp->link_bw = dev_priv->edp.rate; | ||
588 | adjusted_mode->clock = intel_dp_link_clock(intel_dp->link_bw); | ||
589 | DRM_DEBUG_KMS("eDP link bw %02x lane count %d clock %d\n", | ||
590 | intel_dp->link_bw, intel_dp->lane_count, | ||
591 | adjusted_mode->clock); | ||
592 | return true; | ||
593 | } | ||
594 | |||
584 | for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { | 595 | for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { |
585 | for (clock = 0; clock <= max_clock; clock++) { | 596 | for (clock = 0; clock <= max_clock; clock++) { |
586 | int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count); | 597 | int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count); |
@@ -599,19 +610,6 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, | |||
599 | } | 610 | } |
600 | } | 611 | } |
601 | 612 | ||
602 | if (is_edp(intel_dp)) { | ||
603 | /* okay we failed just pick the highest */ | ||
604 | intel_dp->lane_count = max_lane_count; | ||
605 | intel_dp->link_bw = bws[max_clock]; | ||
606 | adjusted_mode->clock = intel_dp_link_clock(intel_dp->link_bw); | ||
607 | DRM_DEBUG_KMS("Force picking display port link bw %02x lane " | ||
608 | "count %d clock %d\n", | ||
609 | intel_dp->link_bw, intel_dp->lane_count, | ||
610 | adjusted_mode->clock); | ||
611 | |||
612 | return true; | ||
613 | } | ||
614 | |||
615 | return false; | 613 | return false; |
616 | } | 614 | } |
617 | 615 | ||
@@ -1088,11 +1086,21 @@ intel_get_adjust_train(struct intel_dp *intel_dp) | |||
1088 | } | 1086 | } |
1089 | 1087 | ||
1090 | static uint32_t | 1088 | static uint32_t |
1091 | intel_dp_signal_levels(uint8_t train_set, int lane_count) | 1089 | intel_dp_signal_levels(struct intel_dp *intel_dp) |
1092 | { | 1090 | { |
1093 | uint32_t signal_levels = 0; | 1091 | struct drm_device *dev = intel_dp->base.base.dev; |
1092 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
1093 | uint32_t signal_levels = 0; | ||
1094 | u8 train_set = intel_dp->train_set[0]; | ||
1095 | u32 vswing = train_set & DP_TRAIN_VOLTAGE_SWING_MASK; | ||
1096 | u32 preemphasis = train_set & DP_TRAIN_PRE_EMPHASIS_MASK; | ||
1094 | 1097 | ||
1095 | switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) { | 1098 | if (is_edp(intel_dp)) { |
1099 | vswing = dev_priv->edp.vswing; | ||
1100 | preemphasis = dev_priv->edp.preemphasis; | ||
1101 | } | ||
1102 | |||
1103 | switch (vswing) { | ||
1096 | case DP_TRAIN_VOLTAGE_SWING_400: | 1104 | case DP_TRAIN_VOLTAGE_SWING_400: |
1097 | default: | 1105 | default: |
1098 | signal_levels |= DP_VOLTAGE_0_4; | 1106 | signal_levels |= DP_VOLTAGE_0_4; |
@@ -1107,7 +1115,7 @@ intel_dp_signal_levels(uint8_t train_set, int lane_count) | |||
1107 | signal_levels |= DP_VOLTAGE_1_2; | 1115 | signal_levels |= DP_VOLTAGE_1_2; |
1108 | break; | 1116 | break; |
1109 | } | 1117 | } |
1110 | switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) { | 1118 | switch (preemphasis) { |
1111 | case DP_TRAIN_PRE_EMPHASIS_0: | 1119 | case DP_TRAIN_PRE_EMPHASIS_0: |
1112 | default: | 1120 | default: |
1113 | signal_levels |= DP_PRE_EMPHASIS_0; | 1121 | signal_levels |= DP_PRE_EMPHASIS_0; |
@@ -1194,6 +1202,18 @@ intel_channel_eq_ok(struct intel_dp *intel_dp) | |||
1194 | } | 1202 | } |
1195 | 1203 | ||
1196 | static bool | 1204 | static bool |
1205 | intel_dp_aux_handshake_required(struct intel_dp *intel_dp) | ||
1206 | { | ||
1207 | struct drm_device *dev = intel_dp->base.base.dev; | ||
1208 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
1209 | |||
1210 | if (is_edp(intel_dp) && dev_priv->no_aux_handshake) | ||
1211 | return false; | ||
1212 | |||
1213 | return true; | ||
1214 | } | ||
1215 | |||
1216 | static bool | ||
1197 | intel_dp_set_link_train(struct intel_dp *intel_dp, | 1217 | intel_dp_set_link_train(struct intel_dp *intel_dp, |
1198 | uint32_t dp_reg_value, | 1218 | uint32_t dp_reg_value, |
1199 | uint8_t dp_train_pat) | 1219 | uint8_t dp_train_pat) |
@@ -1205,6 +1225,9 @@ intel_dp_set_link_train(struct intel_dp *intel_dp, | |||
1205 | I915_WRITE(intel_dp->output_reg, dp_reg_value); | 1225 | I915_WRITE(intel_dp->output_reg, dp_reg_value); |
1206 | POSTING_READ(intel_dp->output_reg); | 1226 | POSTING_READ(intel_dp->output_reg); |
1207 | 1227 | ||
1228 | if (!intel_dp_aux_handshake_required(intel_dp)) | ||
1229 | return true; | ||
1230 | |||
1208 | intel_dp_aux_native_write_1(intel_dp, | 1231 | intel_dp_aux_native_write_1(intel_dp, |
1209 | DP_TRAINING_PATTERN_SET, | 1232 | DP_TRAINING_PATTERN_SET, |
1210 | dp_train_pat); | 1233 | dp_train_pat); |
@@ -1237,10 +1260,11 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) | |||
1237 | POSTING_READ(intel_dp->output_reg); | 1260 | POSTING_READ(intel_dp->output_reg); |
1238 | intel_wait_for_vblank(dev, intel_crtc->pipe); | 1261 | intel_wait_for_vblank(dev, intel_crtc->pipe); |
1239 | 1262 | ||
1240 | /* Write the link configuration data */ | 1263 | if (intel_dp_aux_handshake_required(intel_dp)) |
1241 | intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET, | 1264 | /* Write the link configuration data */ |
1242 | intel_dp->link_configuration, | 1265 | intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET, |
1243 | DP_LINK_CONFIGURATION_SIZE); | 1266 | intel_dp->link_configuration, |
1267 | DP_LINK_CONFIGURATION_SIZE); | ||
1244 | 1268 | ||
1245 | DP |= DP_PORT_EN; | 1269 | DP |= DP_PORT_EN; |
1246 | if (HAS_PCH_CPT(dev) && !is_edp(intel_dp)) | 1270 | if (HAS_PCH_CPT(dev) && !is_edp(intel_dp)) |
@@ -1258,7 +1282,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) | |||
1258 | signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]); | 1282 | signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]); |
1259 | DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; | 1283 | DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; |
1260 | } else { | 1284 | } else { |
1261 | signal_levels = intel_dp_signal_levels(intel_dp->train_set[0], intel_dp->lane_count); | 1285 | signal_levels = intel_dp_signal_levels(intel_dp); |
1262 | DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; | 1286 | DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; |
1263 | } | 1287 | } |
1264 | 1288 | ||
@@ -1272,33 +1296,37 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) | |||
1272 | break; | 1296 | break; |
1273 | /* Set training pattern 1 */ | 1297 | /* Set training pattern 1 */ |
1274 | 1298 | ||
1275 | udelay(100); | 1299 | udelay(500); |
1276 | if (!intel_dp_get_link_status(intel_dp)) | 1300 | if (intel_dp_aux_handshake_required(intel_dp)) { |
1277 | break; | 1301 | break; |
1302 | } else { | ||
1303 | if (!intel_dp_get_link_status(intel_dp)) | ||
1304 | break; | ||
1278 | 1305 | ||
1279 | if (intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) { | 1306 | if (intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) { |
1280 | clock_recovery = true; | 1307 | clock_recovery = true; |
1281 | break; | ||
1282 | } | ||
1283 | |||
1284 | /* Check to see if we've tried the max voltage */ | ||
1285 | for (i = 0; i < intel_dp->lane_count; i++) | ||
1286 | if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) | ||
1287 | break; | 1308 | break; |
1288 | if (i == intel_dp->lane_count) | 1309 | } |
1289 | break; | ||
1290 | 1310 | ||
1291 | /* Check to see if we've tried the same voltage 5 times */ | 1311 | /* Check to see if we've tried the max voltage */ |
1292 | if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { | 1312 | for (i = 0; i < intel_dp->lane_count; i++) |
1293 | ++tries; | 1313 | if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) |
1294 | if (tries == 5) | 1314 | break; |
1315 | if (i == intel_dp->lane_count) | ||
1295 | break; | 1316 | break; |
1296 | } else | ||
1297 | tries = 0; | ||
1298 | voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; | ||
1299 | 1317 | ||
1300 | /* Compute new intel_dp->train_set as requested by target */ | 1318 | /* Check to see if we've tried the same voltage 5 times */ |
1301 | intel_get_adjust_train(intel_dp); | 1319 | if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { |
1320 | ++tries; | ||
1321 | if (tries == 5) | ||
1322 | break; | ||
1323 | } else | ||
1324 | tries = 0; | ||
1325 | voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; | ||
1326 | |||
1327 | /* Compute new intel_dp->train_set as requested by target */ | ||
1328 | intel_get_adjust_train(intel_dp); | ||
1329 | } | ||
1302 | } | 1330 | } |
1303 | 1331 | ||
1304 | intel_dp->DP = DP; | 1332 | intel_dp->DP = DP; |
@@ -1325,7 +1353,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) | |||
1325 | signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]); | 1353 | signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]); |
1326 | DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; | 1354 | DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; |
1327 | } else { | 1355 | } else { |
1328 | signal_levels = intel_dp_signal_levels(intel_dp->train_set[0], intel_dp->lane_count); | 1356 | signal_levels = intel_dp_signal_levels(intel_dp); |
1329 | DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; | 1357 | DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; |
1330 | } | 1358 | } |
1331 | 1359 | ||
@@ -1339,24 +1367,28 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) | |||
1339 | DP_TRAINING_PATTERN_2)) | 1367 | DP_TRAINING_PATTERN_2)) |
1340 | break; | 1368 | break; |
1341 | 1369 | ||
1342 | udelay(400); | 1370 | udelay(500); |
1343 | if (!intel_dp_get_link_status(intel_dp)) | ||
1344 | break; | ||
1345 | 1371 | ||
1346 | if (intel_channel_eq_ok(intel_dp)) { | 1372 | if (!intel_dp_aux_handshake_required(intel_dp)) { |
1347 | channel_eq = true; | ||
1348 | break; | 1373 | break; |
1349 | } | 1374 | } else { |
1375 | if (!intel_dp_get_link_status(intel_dp)) | ||
1376 | break; | ||
1350 | 1377 | ||
1351 | /* Try 5 times */ | 1378 | if (intel_channel_eq_ok(intel_dp)) { |
1352 | if (tries > 5) | 1379 | channel_eq = true; |
1353 | break; | 1380 | break; |
1381 | } | ||
1354 | 1382 | ||
1355 | /* Compute new intel_dp->train_set as requested by target */ | 1383 | /* Try 5 times */ |
1356 | intel_get_adjust_train(intel_dp); | 1384 | if (tries > 5) |
1357 | ++tries; | 1385 | break; |
1358 | } | ||
1359 | 1386 | ||
1387 | /* Compute new intel_dp->train_set as requested by target */ | ||
1388 | intel_get_adjust_train(intel_dp); | ||
1389 | ++tries; | ||
1390 | } | ||
1391 | } | ||
1360 | if (HAS_PCH_CPT(dev) && !is_edp(intel_dp)) | 1392 | if (HAS_PCH_CPT(dev) && !is_edp(intel_dp)) |
1361 | reg = DP | DP_LINK_TRAIN_OFF_CPT; | 1393 | reg = DP | DP_LINK_TRAIN_OFF_CPT; |
1362 | else | 1394 | else |