@@ -37,7 +37,7 @@ static void intel_dp_aux_unpack(u32 src, u8 *dst, int dst_bytes)
}
static u32
-intel_dp_aux_wait_done(struct intel_dp *intel_dp)
+intel_dp_aux_wait_for(struct intel_dp *intel_dp, u32 mask, u32 val)
{
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
i915_reg_t ch_ctl = intel_dp->aux_ch_ctl_reg(intel_dp);
@@ -45,8 +45,7 @@ intel_dp_aux_wait_done(struct intel_dp *intel_dp)
u32 status;
int ret;
- ret = __intel_de_wait_for_register(i915, ch_ctl,
- DP_AUX_CH_CTL_SEND_BUSY, 0,
+ ret = __intel_de_wait_for_register(i915, ch_ctl, mask, val,
2, timeout_ms, &status);
if (ret == -ETIMEDOUT)
@@ -321,13 +320,8 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
/* Send the command and wait for it to complete */
intel_de_write(i915, ch_ctl, send_ctl);
- status = intel_dp_aux_wait_done(intel_dp);
-
- /* Clear done status and any errors */
- intel_de_write(i915, ch_ctl,
- status | DP_AUX_CH_CTL_DONE |
- DP_AUX_CH_CTL_TIME_OUT_ERROR |
- DP_AUX_CH_CTL_RECEIVE_ERROR);
+ status = intel_dp_aux_wait_for(intel_dp,
+ DP_AUX_CH_CTL_SEND_BUSY, 0);
/*
* DP CTS 1.2 Core Rev 1.1, 4.2.1.1 & 4.2.1.2
@@ -335,15 +329,33 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
* Timeout errors from the HW already meet this
* requirement so skip to next iteration
*/
- if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR)
+ if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) {
+ /* Clear the timeout error */
+ intel_de_rmw(i915, ch_ctl, DP_AUX_CH_CTL_TIME_OUT_ERROR, 0);
+
+ /* Clear all errors */
+ status = intel_de_read(i915, ch_ctl);
+ intel_de_write(i915, ch_ctl, status);
continue;
+ }
if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) {
+ /* Clear the reveive error */
+ intel_de_rmw(i915, ch_ctl, DP_AUX_CH_CTL_RECEIVE_ERROR, 0);
usleep_range(400, 500);
+ /* Clear all errors */
+ status = intel_de_read(i915, ch_ctl);
+ intel_de_write(i915, ch_ctl, status);
continue;
}
- if (status & DP_AUX_CH_CTL_DONE)
+ if (status & DP_AUX_CH_CTL_DONE) {
+ /* Clear aux done */
+ intel_de_rmw(i915, ch_ctl, DP_AUX_CH_CTL_DONE, 0);
+ /* Clear all errors */
+ status = intel_de_read(i915, ch_ctl);
+ intel_de_write(i915, ch_ctl, status);
goto done;
+ }
}
}
At the beginning of the aux transfer a check for aux control busy bit is done. Then as per the spec on aux transfer timeout, need to retry freshly for 3 times with a delay which is taken care by the control register. On each of these 3 trials a check for busy has to be done so as to start freshly. v2: updated the commit message v4: check for SEND_BUSY after write (Imre) v5: reverted the send_ctl to the while loop (Jani) v6: Fixed the BAT failure Signed-off-by: Arun R Murthy <arun.r.murthy@intel.com> --- drivers/gpu/drm/i915/display/intel_dp_aux.c | 36 ++++++++++++++------- 1 file changed, 24 insertions(+), 12 deletions(-)