aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2010-10-07 19:01:22 -0400
committerChris Wilson <chris@chris-wilson.co.uk>2010-10-08 05:28:26 -0400
commit869184a675662bddcdf76c5b95665272facff2b8 (patch)
tree6c11929082b43d378405bb657cfaf699e9bb6b6b /drivers/gpu/drm/i915
parent896673836b8c55b75e7d7d2741aaaadff0c6a038 (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.c146
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
1090static uint32_t 1088static uint32_t
1091intel_dp_signal_levels(uint8_t train_set, int lane_count) 1089intel_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
1196static bool 1204static bool
1205intel_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
1216static bool
1197intel_dp_set_link_train(struct intel_dp *intel_dp, 1217intel_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