diff options
Diffstat (limited to 'drivers/gpu/drm/i915')
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_i2c.c | 66 |
2 files changed, 57 insertions, 10 deletions
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index b522eb6e59a4..3da1af46625c 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
@@ -1807,6 +1807,7 @@ enum skl_disp_power_wells { | |||
1807 | #define GMBUS_CYCLE_INDEX (2<<25) | 1807 | #define GMBUS_CYCLE_INDEX (2<<25) |
1808 | #define GMBUS_CYCLE_STOP (4<<25) | 1808 | #define GMBUS_CYCLE_STOP (4<<25) |
1809 | #define GMBUS_BYTE_COUNT_SHIFT 16 | 1809 | #define GMBUS_BYTE_COUNT_SHIFT 16 |
1810 | #define GMBUS_BYTE_COUNT_MAX 256U | ||
1810 | #define GMBUS_SLAVE_INDEX_SHIFT 8 | 1811 | #define GMBUS_SLAVE_INDEX_SHIFT 8 |
1811 | #define GMBUS_SLAVE_ADDR_SHIFT 1 | 1812 | #define GMBUS_SLAVE_ADDR_SHIFT 1 |
1812 | #define GMBUS_SLAVE_READ (1<<0) | 1813 | #define GMBUS_SLAVE_READ (1<<0) |
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index b31088a551f2..56e437e31580 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c | |||
@@ -270,18 +270,17 @@ gmbus_wait_idle(struct drm_i915_private *dev_priv) | |||
270 | } | 270 | } |
271 | 271 | ||
272 | static int | 272 | static int |
273 | gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg, | 273 | gmbus_xfer_read_chunk(struct drm_i915_private *dev_priv, |
274 | u32 gmbus1_index) | 274 | unsigned short addr, u8 *buf, unsigned int len, |
275 | u32 gmbus1_index) | ||
275 | { | 276 | { |
276 | int reg_offset = dev_priv->gpio_mmio_base; | 277 | int reg_offset = dev_priv->gpio_mmio_base; |
277 | u16 len = msg->len; | ||
278 | u8 *buf = msg->buf; | ||
279 | 278 | ||
280 | I915_WRITE(GMBUS1 + reg_offset, | 279 | I915_WRITE(GMBUS1 + reg_offset, |
281 | gmbus1_index | | 280 | gmbus1_index | |
282 | GMBUS_CYCLE_WAIT | | 281 | GMBUS_CYCLE_WAIT | |
283 | (len << GMBUS_BYTE_COUNT_SHIFT) | | 282 | (len << GMBUS_BYTE_COUNT_SHIFT) | |
284 | (msg->addr << GMBUS_SLAVE_ADDR_SHIFT) | | 283 | (addr << GMBUS_SLAVE_ADDR_SHIFT) | |
285 | GMBUS_SLAVE_READ | GMBUS_SW_RDY); | 284 | GMBUS_SLAVE_READ | GMBUS_SW_RDY); |
286 | while (len) { | 285 | while (len) { |
287 | int ret; | 286 | int ret; |
@@ -303,11 +302,35 @@ gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg, | |||
303 | } | 302 | } |
304 | 303 | ||
305 | static int | 304 | static int |
306 | gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg) | 305 | gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg, |
306 | u32 gmbus1_index) | ||
307 | { | 307 | { |
308 | int reg_offset = dev_priv->gpio_mmio_base; | ||
309 | u16 len = msg->len; | ||
310 | u8 *buf = msg->buf; | 308 | u8 *buf = msg->buf; |
309 | unsigned int rx_size = msg->len; | ||
310 | unsigned int len; | ||
311 | int ret; | ||
312 | |||
313 | do { | ||
314 | len = min(rx_size, GMBUS_BYTE_COUNT_MAX); | ||
315 | |||
316 | ret = gmbus_xfer_read_chunk(dev_priv, msg->addr, | ||
317 | buf, len, gmbus1_index); | ||
318 | if (ret) | ||
319 | return ret; | ||
320 | |||
321 | rx_size -= len; | ||
322 | buf += len; | ||
323 | } while (rx_size != 0); | ||
324 | |||
325 | return 0; | ||
326 | } | ||
327 | |||
328 | static int | ||
329 | gmbus_xfer_write_chunk(struct drm_i915_private *dev_priv, | ||
330 | unsigned short addr, u8 *buf, unsigned int len) | ||
331 | { | ||
332 | int reg_offset = dev_priv->gpio_mmio_base; | ||
333 | unsigned int chunk_size = len; | ||
311 | u32 val, loop; | 334 | u32 val, loop; |
312 | 335 | ||
313 | val = loop = 0; | 336 | val = loop = 0; |
@@ -319,8 +342,8 @@ gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg) | |||
319 | I915_WRITE(GMBUS3 + reg_offset, val); | 342 | I915_WRITE(GMBUS3 + reg_offset, val); |
320 | I915_WRITE(GMBUS1 + reg_offset, | 343 | I915_WRITE(GMBUS1 + reg_offset, |
321 | GMBUS_CYCLE_WAIT | | 344 | GMBUS_CYCLE_WAIT | |
322 | (msg->len << GMBUS_BYTE_COUNT_SHIFT) | | 345 | (chunk_size << GMBUS_BYTE_COUNT_SHIFT) | |
323 | (msg->addr << GMBUS_SLAVE_ADDR_SHIFT) | | 346 | (addr << GMBUS_SLAVE_ADDR_SHIFT) | |
324 | GMBUS_SLAVE_WRITE | GMBUS_SW_RDY); | 347 | GMBUS_SLAVE_WRITE | GMBUS_SW_RDY); |
325 | while (len) { | 348 | while (len) { |
326 | int ret; | 349 | int ret; |
@@ -337,6 +360,29 @@ gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg) | |||
337 | if (ret) | 360 | if (ret) |
338 | return ret; | 361 | return ret; |
339 | } | 362 | } |
363 | |||
364 | return 0; | ||
365 | } | ||
366 | |||
367 | static int | ||
368 | gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg) | ||
369 | { | ||
370 | u8 *buf = msg->buf; | ||
371 | unsigned int tx_size = msg->len; | ||
372 | unsigned int len; | ||
373 | int ret; | ||
374 | |||
375 | do { | ||
376 | len = min(tx_size, GMBUS_BYTE_COUNT_MAX); | ||
377 | |||
378 | ret = gmbus_xfer_write_chunk(dev_priv, msg->addr, buf, len); | ||
379 | if (ret) | ||
380 | return ret; | ||
381 | |||
382 | buf += len; | ||
383 | tx_size -= len; | ||
384 | } while (tx_size != 0); | ||
385 | |||
340 | return 0; | 386 | return 0; |
341 | } | 387 | } |
342 | 388 | ||