aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_dp.c
diff options
context:
space:
mode:
authorJani Nikula <jani.nikula@intel.com>2013-09-27 08:10:44 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-10-01 01:45:47 -0400
commit70aff66c953054334bf0569696901c13e206ade6 (patch)
tree26d9196727d91301e14b0f83ac08bdcd8226572b /drivers/gpu/drm/i915/intel_dp.c
parent58c67ce9f0a0d9f016cded91b652642e2aca9e07 (diff)
drm/i915/dp: do not write DP_TRAINING_PATTERN_SET all the time
Neither the DP spec nor the compliance test spec state or imply that we should write the DP_TRAINING_PATTERN_SET at every voltage swing and pre-emphasis change. Indeed we probably shouldn't. So don't. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=49402 Signed-off-by: Jani Nikula <jani.nikula@intel.com> Smoke-tested-by: Paulo Zanoni <paulo.r.zanoni@intel.com> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_dp.c')
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c129
1 files changed, 87 insertions, 42 deletions
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 5b02f9d069c3..2d790d019725 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2318,7 +2318,7 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP)
2318 2318
2319static bool 2319static bool
2320intel_dp_set_link_train(struct intel_dp *intel_dp, 2320intel_dp_set_link_train(struct intel_dp *intel_dp,
2321 uint32_t dp_reg_value, 2321 uint32_t *DP,
2322 uint8_t dp_train_pat) 2322 uint8_t dp_train_pat)
2323{ 2323{
2324 struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); 2324 struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
@@ -2354,50 +2354,51 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
2354 I915_WRITE(DP_TP_CTL(port), temp); 2354 I915_WRITE(DP_TP_CTL(port), temp);
2355 2355
2356 } else if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || port != PORT_A)) { 2356 } else if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || port != PORT_A)) {
2357 dp_reg_value &= ~DP_LINK_TRAIN_MASK_CPT; 2357 *DP &= ~DP_LINK_TRAIN_MASK_CPT;
2358 2358
2359 switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) { 2359 switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
2360 case DP_TRAINING_PATTERN_DISABLE: 2360 case DP_TRAINING_PATTERN_DISABLE:
2361 dp_reg_value |= DP_LINK_TRAIN_OFF_CPT; 2361 *DP |= DP_LINK_TRAIN_OFF_CPT;
2362 break; 2362 break;
2363 case DP_TRAINING_PATTERN_1: 2363 case DP_TRAINING_PATTERN_1:
2364 dp_reg_value |= DP_LINK_TRAIN_PAT_1_CPT; 2364 *DP |= DP_LINK_TRAIN_PAT_1_CPT;
2365 break; 2365 break;
2366 case DP_TRAINING_PATTERN_2: 2366 case DP_TRAINING_PATTERN_2:
2367 dp_reg_value |= DP_LINK_TRAIN_PAT_2_CPT; 2367 *DP |= DP_LINK_TRAIN_PAT_2_CPT;
2368 break; 2368 break;
2369 case DP_TRAINING_PATTERN_3: 2369 case DP_TRAINING_PATTERN_3:
2370 DRM_ERROR("DP training pattern 3 not supported\n"); 2370 DRM_ERROR("DP training pattern 3 not supported\n");
2371 dp_reg_value |= DP_LINK_TRAIN_PAT_2_CPT; 2371 *DP |= DP_LINK_TRAIN_PAT_2_CPT;
2372 break; 2372 break;
2373 } 2373 }
2374 2374
2375 } else { 2375 } else {
2376 dp_reg_value &= ~DP_LINK_TRAIN_MASK; 2376 *DP &= ~DP_LINK_TRAIN_MASK;
2377 2377
2378 switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) { 2378 switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
2379 case DP_TRAINING_PATTERN_DISABLE: 2379 case DP_TRAINING_PATTERN_DISABLE:
2380 dp_reg_value |= DP_LINK_TRAIN_OFF; 2380 *DP |= DP_LINK_TRAIN_OFF;
2381 break; 2381 break;
2382 case DP_TRAINING_PATTERN_1: 2382 case DP_TRAINING_PATTERN_1:
2383 dp_reg_value |= DP_LINK_TRAIN_PAT_1; 2383 *DP |= DP_LINK_TRAIN_PAT_1;
2384 break; 2384 break;
2385 case DP_TRAINING_PATTERN_2: 2385 case DP_TRAINING_PATTERN_2:
2386 dp_reg_value |= DP_LINK_TRAIN_PAT_2; 2386 *DP |= DP_LINK_TRAIN_PAT_2;
2387 break; 2387 break;
2388 case DP_TRAINING_PATTERN_3: 2388 case DP_TRAINING_PATTERN_3:
2389 DRM_ERROR("DP training pattern 3 not supported\n"); 2389 DRM_ERROR("DP training pattern 3 not supported\n");
2390 dp_reg_value |= DP_LINK_TRAIN_PAT_2; 2390 *DP |= DP_LINK_TRAIN_PAT_2;
2391 break; 2391 break;
2392 } 2392 }
2393 } 2393 }
2394 2394
2395 I915_WRITE(intel_dp->output_reg, dp_reg_value); 2395 I915_WRITE(intel_dp->output_reg, *DP);
2396 POSTING_READ(intel_dp->output_reg); 2396 POSTING_READ(intel_dp->output_reg);
2397 2397
2398 intel_dp_aux_native_write_1(intel_dp, 2398 ret = intel_dp_aux_native_write_1(intel_dp, DP_TRAINING_PATTERN_SET,
2399 DP_TRAINING_PATTERN_SET, 2399 dp_train_pat);
2400 dp_train_pat); 2400 if (ret != 1)
2401 return false;
2401 2402
2402 if ((dp_train_pat & DP_TRAINING_PATTERN_MASK) != 2403 if ((dp_train_pat & DP_TRAINING_PATTERN_MASK) !=
2403 DP_TRAINING_PATTERN_DISABLE) { 2404 DP_TRAINING_PATTERN_DISABLE) {
@@ -2412,6 +2413,37 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
2412 return true; 2413 return true;
2413} 2414}
2414 2415
2416static bool
2417intel_dp_reset_link_train(struct intel_dp *intel_dp, uint32_t *DP,
2418 uint8_t dp_train_pat)
2419{
2420 memset(intel_dp->train_set, 0, 4);
2421 intel_dp_set_signal_levels(intel_dp, DP);
2422 return intel_dp_set_link_train(intel_dp, DP, dp_train_pat);
2423}
2424
2425static bool
2426intel_dp_update_link_train(struct intel_dp *intel_dp, uint32_t *DP,
2427 uint8_t link_status[DP_LINK_STATUS_SIZE])
2428{
2429 struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
2430 struct drm_device *dev = intel_dig_port->base.base.dev;
2431 struct drm_i915_private *dev_priv = dev->dev_private;
2432 int ret;
2433
2434 intel_get_adjust_train(intel_dp, link_status);
2435 intel_dp_set_signal_levels(intel_dp, DP);
2436
2437 I915_WRITE(intel_dp->output_reg, *DP);
2438 POSTING_READ(intel_dp->output_reg);
2439
2440 ret = intel_dp_aux_native_write(intel_dp, DP_TRAINING_LANE0_SET,
2441 intel_dp->train_set,
2442 intel_dp->lane_count);
2443
2444 return ret == intel_dp->lane_count;
2445}
2446
2415static void intel_dp_set_idle_link_train(struct intel_dp *intel_dp) 2447static void intel_dp_set_idle_link_train(struct intel_dp *intel_dp)
2416{ 2448{
2417 struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); 2449 struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
@@ -2464,21 +2496,19 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
2464 2496
2465 DP |= DP_PORT_EN; 2497 DP |= DP_PORT_EN;
2466 2498
2467 memset(intel_dp->train_set, 0, 4); 2499 /* clock recovery */
2500 if (!intel_dp_reset_link_train(intel_dp, &DP,
2501 DP_TRAINING_PATTERN_1 |
2502 DP_LINK_SCRAMBLING_DISABLE)) {
2503 DRM_ERROR("failed to enable link training\n");
2504 return;
2505 }
2506
2468 voltage = 0xff; 2507 voltage = 0xff;
2469 voltage_tries = 0; 2508 voltage_tries = 0;
2470 loop_tries = 0; 2509 loop_tries = 0;
2471 for (;;) { 2510 for (;;) {
2472 /* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */ 2511 uint8_t link_status[DP_LINK_STATUS_SIZE];
2473 uint8_t link_status[DP_LINK_STATUS_SIZE];
2474
2475 intel_dp_set_signal_levels(intel_dp, &DP);
2476
2477 /* Set training pattern 1 */
2478 if (!intel_dp_set_link_train(intel_dp, DP,
2479 DP_TRAINING_PATTERN_1 |
2480 DP_LINK_SCRAMBLING_DISABLE))
2481 break;
2482 2512
2483 drm_dp_link_train_clock_recovery_delay(intel_dp->dpcd); 2513 drm_dp_link_train_clock_recovery_delay(intel_dp->dpcd);
2484 if (!intel_dp_get_link_status(intel_dp, link_status)) { 2514 if (!intel_dp_get_link_status(intel_dp, link_status)) {
@@ -2501,7 +2531,9 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
2501 DRM_DEBUG_KMS("too many full retries, give up\n"); 2531 DRM_DEBUG_KMS("too many full retries, give up\n");
2502 break; 2532 break;
2503 } 2533 }
2504 memset(intel_dp->train_set, 0, 4); 2534 intel_dp_reset_link_train(intel_dp, &DP,
2535 DP_TRAINING_PATTERN_1 |
2536 DP_LINK_SCRAMBLING_DISABLE);
2505 voltage_tries = 0; 2537 voltage_tries = 0;
2506 continue; 2538 continue;
2507 } 2539 }
@@ -2517,8 +2549,11 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
2517 voltage_tries = 0; 2549 voltage_tries = 0;
2518 voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; 2550 voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
2519 2551
2520 /* Compute new intel_dp->train_set as requested by target */ 2552 /* Update training set as requested by target */
2521 intel_get_adjust_train(intel_dp, link_status); 2553 if (!intel_dp_update_link_train(intel_dp, &DP, link_status)) {
2554 DRM_ERROR("failed to update link training\n");
2555 break;
2556 }
2522 } 2557 }
2523 2558
2524 intel_dp->DP = DP; 2559 intel_dp->DP = DP;
@@ -2532,11 +2567,18 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
2532 uint32_t DP = intel_dp->DP; 2567 uint32_t DP = intel_dp->DP;
2533 2568
2534 /* channel equalization */ 2569 /* channel equalization */
2570 if (!intel_dp_set_link_train(intel_dp, &DP,
2571 DP_TRAINING_PATTERN_2 |
2572 DP_LINK_SCRAMBLING_DISABLE)) {
2573 DRM_ERROR("failed to start channel equalization\n");
2574 return;
2575 }
2576
2535 tries = 0; 2577 tries = 0;
2536 cr_tries = 0; 2578 cr_tries = 0;
2537 channel_eq = false; 2579 channel_eq = false;
2538 for (;;) { 2580 for (;;) {
2539 uint8_t link_status[DP_LINK_STATUS_SIZE]; 2581 uint8_t link_status[DP_LINK_STATUS_SIZE];
2540 2582
2541 if (cr_tries > 5) { 2583 if (cr_tries > 5) {
2542 DRM_ERROR("failed to train DP, aborting\n"); 2584 DRM_ERROR("failed to train DP, aborting\n");
@@ -2544,21 +2586,18 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
2544 break; 2586 break;
2545 } 2587 }
2546 2588
2547 intel_dp_set_signal_levels(intel_dp, &DP);
2548
2549 /* channel eq pattern */
2550 if (!intel_dp_set_link_train(intel_dp, DP,
2551 DP_TRAINING_PATTERN_2 |
2552 DP_LINK_SCRAMBLING_DISABLE))
2553 break;
2554
2555 drm_dp_link_train_channel_eq_delay(intel_dp->dpcd); 2589 drm_dp_link_train_channel_eq_delay(intel_dp->dpcd);
2556 if (!intel_dp_get_link_status(intel_dp, link_status)) 2590 if (!intel_dp_get_link_status(intel_dp, link_status)) {
2591 DRM_ERROR("failed to get link status\n");
2557 break; 2592 break;
2593 }
2558 2594
2559 /* Make sure clock is still ok */ 2595 /* Make sure clock is still ok */
2560 if (!drm_dp_clock_recovery_ok(link_status, intel_dp->lane_count)) { 2596 if (!drm_dp_clock_recovery_ok(link_status, intel_dp->lane_count)) {
2561 intel_dp_start_link_train(intel_dp); 2597 intel_dp_start_link_train(intel_dp);
2598 intel_dp_set_link_train(intel_dp, &DP,
2599 DP_TRAINING_PATTERN_2 |
2600 DP_LINK_SCRAMBLING_DISABLE);
2562 cr_tries++; 2601 cr_tries++;
2563 continue; 2602 continue;
2564 } 2603 }
@@ -2572,13 +2611,19 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
2572 if (tries > 5) { 2611 if (tries > 5) {
2573 intel_dp_link_down(intel_dp); 2612 intel_dp_link_down(intel_dp);
2574 intel_dp_start_link_train(intel_dp); 2613 intel_dp_start_link_train(intel_dp);
2614 intel_dp_set_link_train(intel_dp, &DP,
2615 DP_TRAINING_PATTERN_2 |
2616 DP_LINK_SCRAMBLING_DISABLE);
2575 tries = 0; 2617 tries = 0;
2576 cr_tries++; 2618 cr_tries++;
2577 continue; 2619 continue;
2578 } 2620 }
2579 2621
2580 /* Compute new intel_dp->train_set as requested by target */ 2622 /* Update training set as requested by target */
2581 intel_get_adjust_train(intel_dp, link_status); 2623 if (!intel_dp_update_link_train(intel_dp, &DP, link_status)) {
2624 DRM_ERROR("failed to update link training\n");
2625 break;
2626 }
2582 ++tries; 2627 ++tries;
2583 } 2628 }
2584 2629
@@ -2593,7 +2638,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
2593 2638
2594void intel_dp_stop_link_train(struct intel_dp *intel_dp) 2639void intel_dp_stop_link_train(struct intel_dp *intel_dp)
2595{ 2640{
2596 intel_dp_set_link_train(intel_dp, intel_dp->DP, 2641 intel_dp_set_link_train(intel_dp, &intel_dp->DP,
2597 DP_TRAINING_PATTERN_DISABLE); 2642 DP_TRAINING_PATTERN_DISABLE);
2598} 2643}
2599 2644