diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-05-31 10:23:08 +0200 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-05-31 10:23:08 +0200 |
commit | f69407950c6bef8b303faeebc36c5416605d4dee (patch) | |
tree | a86be5aa4d323d719c910faae118ad49d6eda298 | |
parent | 51700f84a50bb1eb5c6d7b944c489a0d28c717e7 (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.c | 13 |
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); |