summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2012-05-31 10:23:08 +0200
committerDaniel Vetter <daniel.vetter@ffwll.ch>2012-05-31 10:23:08 +0200
commitf69407950c6bef8b303faeebc36c5416605d4dee (patch)
treea86be5aa4d323d719c910faae118ad49d6eda298
parent51700f84a50bb1eb5c6d7b944c489a0d28c717e7 (diff)
drm/i915: retry gmbus transfers after first NAKhpd-mess
Paulo Zanoni has a machine with too many bogons. Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/i915/intel_i2c.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c
index 1991a4408cf9..ca0169d759a9 100644
--- a/drivers/gpu/drm/i915/intel_i2c.c
+++ b/drivers/gpu/drm/i915/intel_i2c.c
@@ -333,6 +333,7 @@ gmbus_xfer(struct i2c_adapter *adapter,
struct drm_i915_private *dev_priv = bus->dev_priv;
int i, reg_offset;
int ret = 0;
+ bool repeat = false;
mutex_lock(&dev_priv->gmbus_mutex);
@@ -343,6 +344,7 @@ gmbus_xfer(struct i2c_adapter *adapter,
reg_offset = dev_priv->gpio_mmio_base;
+repeat:
I915_WRITE(GMBUS0 + reg_offset, bus->reg0);
for (i = 0; i < num; i++) {
@@ -421,6 +423,17 @@ clear_err:
I915_WRITE(GMBUS1 + reg_offset, 0);
I915_WRITE(GMBUS0 + reg_offset, 0);
+ /*
+ * GMBUS is a fickle thing, and especially on wire pairs shared with
+ * other stuff (e.g. dp aux transfers) we need to clear bogons first
+ * before we can be sure that the NAK is real. So just retry once after
+ * resetting the bus.
+ */
+ if (!repeat) {
+ repeat = true;
+ goto repeat;
+ }
+
DRM_DEBUG_KMS("GMBUS [%s] NAK for addr: %04x %c(%d)\n",
adapter->name, msgs[i].addr,
(msgs[i].flags & I2C_M_RD) ? 'r' : 'w', msgs[i].len);