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.mur...@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp_aux.c | 36 ++++++++++++++-------
 1 file changed, 24 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux.c 
b/drivers/gpu/drm/i915/display/intel_dp_aux.c
index 197c6e81db14..14a0704fb4b4 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_aux.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_aux.c
@@ -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;
+                       }
                }
        }
 
-- 
2.25.1

Reply via email to