diff options
| -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 | ||
