Commit f6e3be98 authored by Ville Syrjälä's avatar Ville Syrjälä

drm/i915: Fix DP clock recovery "voltage_tries" handling

The DP spec says:
"If the receiver keeps the same value in the ADJUST_REQUEST_LANEx_y
 register(s) while the LANEx_CR_DONE bits remain unset, the transmitter
 must loop four times with the same voltage swing. On the fifth time,
 the transmitter must down-shift to the lower bit rate and must repeat
 the CR-lock training sequence as described below."

Lets fix the code to follow that instead of terminating after five
times of transmitting the same signal levels. The text in spec feels
a little bit ambiguous still, but this is my best guess at its meaning.

As a bonus this also gets rid of the train_set[0] stuff which
would not work for per-lane drive settings anyway.

Cc: Imre Deak <imre.deak@intel.com>
CC: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20211001160826.17080-1-ville.syrjala@linux.intel.comReviewed-by: default avatarImre Deak <imre.deak@intel.com>
parent 7d4fed88
...@@ -511,6 +511,25 @@ static void intel_dp_link_training_clock_recovery_delay(struct intel_dp *intel_d ...@@ -511,6 +511,25 @@ static void intel_dp_link_training_clock_recovery_delay(struct intel_dp *intel_d
drm_dp_lttpr_link_train_clock_recovery_delay(); drm_dp_lttpr_link_train_clock_recovery_delay();
} }
static bool intel_dp_adjust_request_changed(int lane_count,
const u8 old_link_status[DP_LINK_STATUS_SIZE],
const u8 new_link_status[DP_LINK_STATUS_SIZE])
{
int lane;
for (lane = 0; lane < lane_count; lane++) {
u8 old = drm_dp_get_adjust_request_voltage(old_link_status, lane) |
drm_dp_get_adjust_request_pre_emphasis(old_link_status, lane);
u8 new = drm_dp_get_adjust_request_voltage(new_link_status, lane) |
drm_dp_get_adjust_request_pre_emphasis(new_link_status, lane);
if (old != new)
return true;
}
return false;
}
/* /*
* Perform the link training clock recovery phase on the given DP PHY using * Perform the link training clock recovery phase on the given DP PHY using
* training pattern 1. * training pattern 1.
...@@ -521,7 +540,7 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp, ...@@ -521,7 +540,7 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp,
enum drm_dp_phy dp_phy) enum drm_dp_phy dp_phy)
{ {
struct drm_i915_private *i915 = dp_to_i915(intel_dp); struct drm_i915_private *i915 = dp_to_i915(intel_dp);
u8 voltage; u8 old_link_status[DP_LINK_STATUS_SIZE] = {};
int voltage_tries, cr_tries, max_cr_tries; int voltage_tries, cr_tries, max_cr_tries;
bool max_vswing_reached = false; bool max_vswing_reached = false;
...@@ -574,8 +593,6 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp, ...@@ -574,8 +593,6 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp,
return false; return false;
} }
voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
/* Update training set as requested by target */ /* Update training set as requested by target */
intel_dp_get_adjust_train(intel_dp, crtc_state, dp_phy, intel_dp_get_adjust_train(intel_dp, crtc_state, dp_phy,
link_status); link_status);
...@@ -585,12 +602,14 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp, ...@@ -585,12 +602,14 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp,
return false; return false;
} }
if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == if (!intel_dp_adjust_request_changed(crtc_state->lane_count,
voltage) old_link_status, link_status))
++voltage_tries; ++voltage_tries;
else else
voltage_tries = 1; voltage_tries = 1;
memcpy(old_link_status, link_status, sizeof(link_status));
if (intel_dp_link_max_vswing_reached(intel_dp, crtc_state)) if (intel_dp_link_max_vswing_reached(intel_dp, crtc_state))
max_vswing_reached = true; max_vswing_reached = true;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment