diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_dp.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 72 |
1 files changed, 66 insertions, 6 deletions
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index d83447557f9b..63424d5db9c6 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
@@ -33,7 +33,7 @@ | |||
33 | #include "intel_drv.h" | 33 | #include "intel_drv.h" |
34 | #include "i915_drm.h" | 34 | #include "i915_drm.h" |
35 | #include "i915_drv.h" | 35 | #include "i915_drv.h" |
36 | #include "intel_dp.h" | 36 | #include "drm_dp_helper.h" |
37 | 37 | ||
38 | #define DP_LINK_STATUS_SIZE 6 | 38 | #define DP_LINK_STATUS_SIZE 6 |
39 | #define DP_LINK_CHECK_TIMEOUT (10 * 1000) | 39 | #define DP_LINK_CHECK_TIMEOUT (10 * 1000) |
@@ -382,17 +382,77 @@ intel_dp_aux_native_read(struct intel_output *intel_output, | |||
382 | } | 382 | } |
383 | 383 | ||
384 | static int | 384 | static int |
385 | intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, | 385 | intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, |
386 | uint8_t *send, int send_bytes, | 386 | uint8_t write_byte, uint8_t *read_byte) |
387 | uint8_t *recv, int recv_bytes) | ||
388 | { | 387 | { |
388 | struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; | ||
389 | struct intel_dp_priv *dp_priv = container_of(adapter, | 389 | struct intel_dp_priv *dp_priv = container_of(adapter, |
390 | struct intel_dp_priv, | 390 | struct intel_dp_priv, |
391 | adapter); | 391 | adapter); |
392 | struct intel_output *intel_output = dp_priv->intel_output; | 392 | struct intel_output *intel_output = dp_priv->intel_output; |
393 | uint16_t address = algo_data->address; | ||
394 | uint8_t msg[5]; | ||
395 | uint8_t reply[2]; | ||
396 | int msg_bytes; | ||
397 | int reply_bytes; | ||
398 | int ret; | ||
399 | |||
400 | /* Set up the command byte */ | ||
401 | if (mode & MODE_I2C_READ) | ||
402 | msg[0] = AUX_I2C_READ << 4; | ||
403 | else | ||
404 | msg[0] = AUX_I2C_WRITE << 4; | ||
405 | |||
406 | if (!(mode & MODE_I2C_STOP)) | ||
407 | msg[0] |= AUX_I2C_MOT << 4; | ||
408 | |||
409 | msg[1] = address >> 8; | ||
410 | msg[2] = address; | ||
411 | |||
412 | switch (mode) { | ||
413 | case MODE_I2C_WRITE: | ||
414 | msg[3] = 0; | ||
415 | msg[4] = write_byte; | ||
416 | msg_bytes = 5; | ||
417 | reply_bytes = 1; | ||
418 | break; | ||
419 | case MODE_I2C_READ: | ||
420 | msg[3] = 0; | ||
421 | msg_bytes = 4; | ||
422 | reply_bytes = 2; | ||
423 | break; | ||
424 | default: | ||
425 | msg_bytes = 3; | ||
426 | reply_bytes = 1; | ||
427 | break; | ||
428 | } | ||
393 | 429 | ||
394 | return intel_dp_aux_ch(intel_output, | 430 | for (;;) { |
395 | send, send_bytes, recv, recv_bytes); | 431 | ret = intel_dp_aux_ch(intel_output, |
432 | msg, msg_bytes, | ||
433 | reply, reply_bytes); | ||
434 | if (ret < 0) { | ||
435 | DRM_DEBUG("aux_ch failed %d\n", ret); | ||
436 | return ret; | ||
437 | } | ||
438 | switch (reply[0] & AUX_I2C_REPLY_MASK) { | ||
439 | case AUX_I2C_REPLY_ACK: | ||
440 | if (mode == MODE_I2C_READ) { | ||
441 | *read_byte = reply[1]; | ||
442 | } | ||
443 | return reply_bytes - 1; | ||
444 | case AUX_I2C_REPLY_NACK: | ||
445 | DRM_DEBUG("aux_ch nack\n"); | ||
446 | return -EREMOTEIO; | ||
447 | case AUX_I2C_REPLY_DEFER: | ||
448 | DRM_DEBUG("aux_ch defer\n"); | ||
449 | udelay(100); | ||
450 | break; | ||
451 | default: | ||
452 | DRM_ERROR("aux_ch invalid reply 0x%02x\n", reply[0]); | ||
453 | return -EREMOTEIO; | ||
454 | } | ||
455 | } | ||
396 | } | 456 | } |
397 | 457 | ||
398 | static int | 458 | static int |