aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorBenson Leung <bleung@chromium.org>2012-02-09 15:03:17 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2012-02-29 14:10:36 -0500
commitcaae745a352377f48f6eb43b5040214d803a885f (patch)
treec8d02a2a3ac5162e31ac2b8ee9b971256ad03e11 /drivers/gpu
parent5d1333fcce84e77ec865f6b09006401ed3f564b5 (diff)
drm/i915: Fix single msg gmbus_xfers writes
gmbus_xfer with a single message (particularly a single message write) would set Bus Cycle Select to 100b, the Gen Stop cycle, instead of 101b, No Index, Stop cycle. This would not start single message i2c transactions. Also, gmbus_xfer done: will disable the interface without checking if it is idle. In the case of writes, there will be no wait on status or delay to ensure the write starts and completes before the interface is turned off. Fixed the former issue by using the same cycle selection as used in the I2C_M_RD for the write case. GMBUS_CYCLE_WAIT | (i + 1 == num ? GMBUS_CYCLE_STOP : 0) Fixed the latter by waiting on GMBUS_ACTIVE to deassert before disable. Note from the grumpy d-i-n maintainer: The first hunk that changes the gmbus read path is just cosmetics to align the code with the write path. I.e. the commit message above is slightly lying because the first issue is _only_ with writes (and not simply "particularly"). Signed-off-by: Benson Leung <bleung@chromium.org> Reviewed-by: Daniel Kurtz <djkurtz@chromium.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/i915/intel_i2c.c13
1 files changed, 9 insertions, 4 deletions
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c
index 068617f7256a..4e4ddd5d1f51 100644
--- a/drivers/gpu/drm/i915/intel_i2c.c
+++ b/drivers/gpu/drm/i915/intel_i2c.c
@@ -253,7 +253,8 @@ gmbus_xfer(struct i2c_adapter *adapter,
253 253
254 if (msgs[i].flags & I2C_M_RD) { 254 if (msgs[i].flags & I2C_M_RD) {
255 I915_WRITE(GMBUS1 + reg_offset, 255 I915_WRITE(GMBUS1 + reg_offset,
256 GMBUS_CYCLE_WAIT | (i + 1 == num ? GMBUS_CYCLE_STOP : 0) | 256 GMBUS_CYCLE_WAIT |
257 (i + 1 == num ? GMBUS_CYCLE_STOP : 0) |
257 (len << GMBUS_BYTE_COUNT_SHIFT) | 258 (len << GMBUS_BYTE_COUNT_SHIFT) |
258 (msgs[i].addr << GMBUS_SLAVE_ADDR_SHIFT) | 259 (msgs[i].addr << GMBUS_SLAVE_ADDR_SHIFT) |
259 GMBUS_SLAVE_READ | GMBUS_SW_RDY); 260 GMBUS_SLAVE_READ | GMBUS_SW_RDY);
@@ -282,7 +283,8 @@ gmbus_xfer(struct i2c_adapter *adapter,
282 283
283 I915_WRITE(GMBUS3 + reg_offset, val); 284 I915_WRITE(GMBUS3 + reg_offset, val);
284 I915_WRITE(GMBUS1 + reg_offset, 285 I915_WRITE(GMBUS1 + reg_offset,
285 (i + 1 == num ? GMBUS_CYCLE_STOP : GMBUS_CYCLE_WAIT) | 286 GMBUS_CYCLE_WAIT |
287 (i + 1 == num ? GMBUS_CYCLE_STOP : 0) |
286 (msgs[i].len << GMBUS_BYTE_COUNT_SHIFT) | 288 (msgs[i].len << GMBUS_BYTE_COUNT_SHIFT) |
287 (msgs[i].addr << GMBUS_SLAVE_ADDR_SHIFT) | 289 (msgs[i].addr << GMBUS_SLAVE_ADDR_SHIFT) |
288 GMBUS_SLAVE_WRITE | GMBUS_SW_RDY); 290 GMBUS_SLAVE_WRITE | GMBUS_SW_RDY);
@@ -321,9 +323,12 @@ clear_err:
321 I915_WRITE(GMBUS1 + reg_offset, 0); 323 I915_WRITE(GMBUS1 + reg_offset, 0);
322 324
323done: 325done:
324 /* Mark the GMBUS interface as disabled. We will re-enable it at the 326 /* Mark the GMBUS interface as disabled after waiting for idle.
325 * start of the next xfer, till then let it sleep. 327 * We will re-enable it at the start of the next xfer,
328 * till then let it sleep.
326 */ 329 */
330 if (wait_for((I915_READ(GMBUS2 + reg_offset) & GMBUS_ACTIVE) == 0, 10))
331 DRM_INFO("GMBUS timed out waiting for idle\n");
327 I915_WRITE(GMBUS0 + reg_offset, 0); 332 I915_WRITE(GMBUS0 + reg_offset, 0);
328 ret = i; 333 ret = i;
329 goto out; 334 goto out;