From b6099984cc4a12bb23fd90a53d17d3eb89c173c3 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 23 Sep 2013 16:28:57 +0300 Subject: [PATCH] drm/i915: don't write training pattern set if it doesn't change Organization: Intel Finland Oy - BIC 0357606-4 - Westendinkatu 7, 02160 Espoo Cc: Jani Nikula Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_dp.c | 42 ++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 5a937fc..03ab756 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -2113,9 +2113,10 @@ static uint32_t intel_vlv_signal_levels(struct intel_dp *intel_dp) return 0; } -static void +static bool intel_get_adjust_train(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE]) { + bool changed = false; uint8_t v = 0; uint8_t p = 0; int lane; @@ -2140,8 +2141,14 @@ intel_get_adjust_train(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_ST if (p >= preemph_max) p = preemph_max | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; - for (lane = 0; lane < 4; lane++) - intel_dp->train_set[lane] = v | p; + for (lane = 0; lane < 4; lane++) { + if (intel_dp->train_set[lane] != (v | p)) { + intel_dp->train_set[lane] = v | p; + changed = true; + } + } + + return changed; } static uint32_t @@ -2310,7 +2317,8 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP) static bool intel_dp_set_link_train(struct intel_dp *intel_dp, uint32_t dp_reg_value, - uint8_t dp_train_pat) + uint8_t dp_train_pat, + bool init) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = intel_dig_port->base.base.dev; @@ -2386,6 +2394,9 @@ intel_dp_set_link_train(struct intel_dp *intel_dp, I915_WRITE(intel_dp->output_reg, dp_reg_value); POSTING_READ(intel_dp->output_reg); + if (!init) + return true; + intel_dp_aux_native_write_1(intel_dp, DP_TRAINING_PATTERN_SET, dp_train_pat); @@ -2444,6 +2455,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) uint8_t voltage; int voltage_tries, loop_tries; uint32_t DP = intel_dp->DP; + bool changed = true; if (HAS_DDI(dev)) intel_ddi_prepare_link_retrain(encoder); @@ -2468,7 +2480,8 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) /* Set training pattern 1 */ if (!intel_dp_set_link_train(intel_dp, DP, DP_TRAINING_PATTERN_1 | - DP_LINK_SCRAMBLING_DISABLE)) + DP_LINK_SCRAMBLING_DISABLE, + changed)) break; drm_dp_link_train_clock_recovery_delay(intel_dp->dpcd); @@ -2494,22 +2507,23 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) } memset(intel_dp->train_set, 0, 4); voltage_tries = 0; + changed = true; continue; } /* Check to see if we've tried the same voltage 5 times */ - if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { + if (!changed) { ++voltage_tries; if (voltage_tries == 5) { DRM_DEBUG_KMS("too many voltage retries, give up\n"); break; } - } else + } else { voltage_tries = 0; - voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; + } /* Compute new intel_dp->train_set as requested by target */ - intel_get_adjust_train(intel_dp, link_status); + changed = intel_get_adjust_train(intel_dp, link_status); } intel_dp->DP = DP; @@ -2521,6 +2535,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) bool channel_eq = false; int tries, cr_tries; uint32_t DP = intel_dp->DP; + bool changed = true; /* channel equalization */ tries = 0; @@ -2540,7 +2555,8 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) /* channel eq pattern */ if (!intel_dp_set_link_train(intel_dp, DP, DP_TRAINING_PATTERN_2 | - DP_LINK_SCRAMBLING_DISABLE)) + DP_LINK_SCRAMBLING_DISABLE, + changed)) break; drm_dp_link_train_channel_eq_delay(intel_dp->dpcd); @@ -2551,6 +2567,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) if (!drm_dp_clock_recovery_ok(link_status, intel_dp->lane_count)) { intel_dp_start_link_train(intel_dp); cr_tries++; + changed = true; continue; } @@ -2564,12 +2581,13 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) intel_dp_link_down(intel_dp); intel_dp_start_link_train(intel_dp); tries = 0; + changed = true; cr_tries++; continue; } /* Compute new intel_dp->train_set as requested by target */ - intel_get_adjust_train(intel_dp, link_status); + changed = intel_get_adjust_train(intel_dp, link_status); ++tries; } @@ -2585,7 +2603,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) void intel_dp_stop_link_train(struct intel_dp *intel_dp) { intel_dp_set_link_train(intel_dp, intel_dp->DP, - DP_TRAINING_PATTERN_DISABLE); + DP_TRAINING_PATTERN_DISABLE, true); } static void -- 1.7.9.5