aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-03-30 11:20:43 -0400
committerChris Wilson <chris@chris-wilson.co.uk>2011-03-31 04:37:01 -0400
commit7f58aabc369014fda3a4a33604ba0a1b63b941ac (patch)
treeaeb82491f30b9565752d97a26b2292963c895185 /drivers
parent9f01b25048ad12b5d71f4f7d3b62ef737639a08d (diff)
drm/i915: Reset GMBUS controller after NAK
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. v2: Add some comments as suggested by Keith Packard. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=35781 Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Keith Packard <keithp@keithp.com> Tested-by: Jesse Barnes <jbarnes@virtuousgeek.org> Tested-by: "Mengmeng Meng" <mengmeng.meng@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/i915/intel_i2c.c25
1 files changed, 21 insertions, 4 deletions
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c
index 82d04c5899d2..d3b903bce7c5 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,
259 if (wait_for(I915_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_RDY), 50)) 259 if (wait_for(I915_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_RDY), 50))
260 goto timeout; 260 goto timeout;
261 if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER) 261 if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER)
262 return 0; 262 goto clear_err;
263 263
264 val = I915_READ(GMBUS3 + reg_offset); 264 val = I915_READ(GMBUS3 + reg_offset);
265 do { 265 do {
@@ -287,7 +287,7 @@ gmbus_xfer(struct i2c_adapter *adapter,
287 if (wait_for(I915_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_RDY), 50)) 287 if (wait_for(I915_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_RDY), 50))
288 goto timeout; 288 goto timeout;
289 if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER) 289 if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER)
290 return 0; 290 goto clear_err;
291 291
292 val = loop = 0; 292 val = loop = 0;
293 do { 293 do {
@@ -302,14 +302,31 @@ gmbus_xfer(struct i2c_adapter *adapter,
302 if (i + 1 < num && wait_for(I915_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_WAIT_PHASE), 50)) 302 if (i + 1 < num && wait_for(I915_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_WAIT_PHASE), 50))
303 goto timeout; 303 goto timeout;
304 if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER) 304 if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER)
305 return 0; 305 goto clear_err;
306 } 306 }
307 307
308 return num; 308 goto done;
309
310clear_err:
311 /* Toggle the Software Clear Interrupt bit. This has the effect
312 * of resetting the GMBUS controller and so clearing the
313 * BUS_ERROR raised by the slave's NAK.
314 */
315 I915_WRITE(GMBUS1 + reg_offset, GMBUS_SW_CLR_INT);
316 I915_WRITE(GMBUS1 + reg_offset, 0);
317
318done:
319 /* Mark the GMBUS interface as disabled. We will re-enable it at the
320 * start of the next xfer, till then let it sleep.
321 */
322 I915_WRITE(GMBUS0 + reg_offset, 0);
323 return i;
309 324
310timeout: 325timeout:
311 DRM_INFO("GMBUS timed out, falling back to bit banging on pin %d [%s]\n", 326 DRM_INFO("GMBUS timed out, falling back to bit banging on pin %d [%s]\n",
312 bus->reg0 & 0xff, bus->adapter.name); 327 bus->reg0 & 0xff, bus->adapter.name);
328 I915_WRITE(GMBUS0 + reg_offset, 0);
329
313 /* Hardware may not support GMBUS over these pins? Try GPIO bitbanging instead. */ 330 /* Hardware may not support GMBUS over these pins? Try GPIO bitbanging instead. */
314 bus->force_bit = intel_gpio_create(dev_priv, bus->reg0 & 0xff); 331 bus->force_bit = intel_gpio_create(dev_priv, bus->reg0 & 0xff);
315 if (!bus->force_bit) 332 if (!bus->force_bit)