Once a NAK has been asserted by the slave, we need to reset the GMBUS
controller in order to continue. This is done by asserting the Software
Clear Interrupt bit and then clearing it again to restore operations.

If we don't clear the NAK, then all future GMBUS xfers will fail,
including DDC probes and EDID retrieval.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=35781
Signed-off-by: Chris Wilson <[email protected]>
---
 drivers/gpu/drm/i915/intel_i2c.c |   19 +++++++++++++++----
 1 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c
index 82d04c5..abdedd8 100644
--- a/drivers/gpu/drm/i915/intel_i2c.c
+++ b/drivers/gpu/drm/i915/intel_i2c.c
@@ -259,7 +259,7 @@ gmbus_xfer(struct i2c_adapter *adapter,
                                if (wait_for(I915_READ(GMBUS2 + reg_offset) & 
(GMBUS_SATOER | GMBUS_HW_RDY), 50))
                                        goto timeout;
                                if (I915_READ(GMBUS2 + reg_offset) & 
GMBUS_SATOER)
-                                       return 0;
+                                       goto clear_err;
 
                                val = I915_READ(GMBUS3 + reg_offset);
                                do {
@@ -287,7 +287,7 @@ gmbus_xfer(struct i2c_adapter *adapter,
                                if (wait_for(I915_READ(GMBUS2 + reg_offset) & 
(GMBUS_SATOER | GMBUS_HW_RDY), 50))
                                        goto timeout;
                                if (I915_READ(GMBUS2 + reg_offset) & 
GMBUS_SATOER)
-                                       return 0;
+                                       goto clear_err;
 
                                val = loop = 0;
                                do {
@@ -302,14 +302,25 @@ gmbus_xfer(struct i2c_adapter *adapter,
                if (i + 1 < num && wait_for(I915_READ(GMBUS2 + reg_offset) & 
(GMBUS_SATOER | GMBUS_HW_WAIT_PHASE), 50))
                        goto timeout;
                if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER)
-                       return 0;
+                       goto clear_err;
        }
 
-       return num;
+       goto done;
+
+clear_err:
+       I915_WRITE(GMBUS1 + reg_offset, GMBUS_SW_CLR_INT);
+       POSTING_READ(GMBUS1 + reg_offset);
+       I915_WRITE(GMBUS1 + reg_offset, 0);
+
+done:
+       I915_WRITE(GMBUS0 + reg_offset, 0);
+       return i;
 
 timeout:
        DRM_INFO("GMBUS timed out, falling back to bit banging on pin %d 
[%s]\n",
                 bus->reg0 & 0xff, bus->adapter.name);
+       I915_WRITE(GMBUS0 + reg_offset, 0);
+
        /* Hardware may not support GMBUS over these pins? Try GPIO bitbanging 
instead. */
        bus->force_bit = intel_gpio_create(dev_priv, bus->reg0 & 0xff);
        if (!bus->force_bit)
-- 
1.7.4.1

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to