diff options
author | Jani Nikula <jani.nikula@intel.com> | 2013-09-27 08:10:44 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2013-10-01 01:45:47 -0400 |
commit | 70aff66c953054334bf0569696901c13e206ade6 (patch) | |
tree | 26d9196727d91301e14b0f83ac08bdcd8226572b /drivers/gpu/drm/i915/intel_dp.c | |
parent | 58c67ce9f0a0d9f016cded91b652642e2aca9e07 (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.c | 129 |
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 | ||
2319 | static bool | 2319 | static bool |
2320 | intel_dp_set_link_train(struct intel_dp *intel_dp, | 2320 | intel_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 | ||
2416 | static bool | ||
2417 | intel_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 | |||
2425 | static bool | ||
2426 | intel_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 | |||
2415 | static void intel_dp_set_idle_link_train(struct intel_dp *intel_dp) | 2447 | static 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 | ||
2594 | void intel_dp_stop_link_train(struct intel_dp *intel_dp) | 2639 | void 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 | ||