159,6 → 159,8 |
} |
EXPORT_SYMBOL(drm_dp_bw_code_to_link_rate); |
|
#define AUX_RETRY_INTERVAL 500 /* us */ |
|
/** |
* DOC: dp helpers |
* |
354,6 → 356,37 |
EXPORT_SYMBOL(drm_dp_link_power_up); |
|
/** |
* drm_dp_link_power_down() - power down a DisplayPort link |
* @aux: DisplayPort AUX channel |
* @link: pointer to a structure containing the link configuration |
* |
* Returns 0 on success or a negative error code on failure. |
*/ |
int drm_dp_link_power_down(struct drm_dp_aux *aux, struct drm_dp_link *link) |
{ |
u8 value; |
int err; |
|
/* DP_SET_POWER register is only available on DPCD v1.1 and later */ |
if (link->revision < 0x11) |
return 0; |
|
err = drm_dp_dpcd_readb(aux, DP_SET_POWER, &value); |
if (err < 0) |
return err; |
|
value &= ~DP_SET_POWER_MASK; |
value |= DP_SET_POWER_D3; |
|
err = drm_dp_dpcd_writeb(aux, DP_SET_POWER, value); |
if (err < 0) |
return err; |
|
return 0; |
} |
EXPORT_SYMBOL(drm_dp_link_power_down); |
|
/** |
* drm_dp_link_configure() - configure a DisplayPort link |
* @aux: DisplayPort AUX channel |
* @link: pointer to a structure containing the link configuration |
391,32 → 424,134 |
I2C_FUNC_10BIT_ADDR; |
} |
|
static void drm_dp_i2c_msg_write_status_update(struct drm_dp_aux_msg *msg) |
{ |
/* |
* In case of i2c defer or short i2c ack reply to a write, |
* we need to switch to WRITE_STATUS_UPDATE to drain the |
* rest of the message |
*/ |
if ((msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_I2C_WRITE) { |
msg->request &= DP_AUX_I2C_MOT; |
msg->request |= DP_AUX_I2C_WRITE_STATUS_UPDATE; |
} |
} |
|
#define AUX_PRECHARGE_LEN 10 /* 10 to 16 */ |
#define AUX_SYNC_LEN (16 + 4) /* preamble + AUX_SYNC_END */ |
#define AUX_STOP_LEN 4 |
#define AUX_CMD_LEN 4 |
#define AUX_ADDRESS_LEN 20 |
#define AUX_REPLY_PAD_LEN 4 |
#define AUX_LENGTH_LEN 8 |
|
/* |
* Calculate the duration of the AUX request/reply in usec. Gives the |
* "best" case estimate, ie. successful while as short as possible. |
*/ |
static int drm_dp_aux_req_duration(const struct drm_dp_aux_msg *msg) |
{ |
int len = AUX_PRECHARGE_LEN + AUX_SYNC_LEN + AUX_STOP_LEN + |
AUX_CMD_LEN + AUX_ADDRESS_LEN + AUX_LENGTH_LEN; |
|
if ((msg->request & DP_AUX_I2C_READ) == 0) |
len += msg->size * 8; |
|
return len; |
} |
|
static int drm_dp_aux_reply_duration(const struct drm_dp_aux_msg *msg) |
{ |
int len = AUX_PRECHARGE_LEN + AUX_SYNC_LEN + AUX_STOP_LEN + |
AUX_CMD_LEN + AUX_REPLY_PAD_LEN; |
|
/* |
* For read we expect what was asked. For writes there will |
* be 0 or 1 data bytes. Assume 0 for the "best" case. |
*/ |
if (msg->request & DP_AUX_I2C_READ) |
len += msg->size * 8; |
|
return len; |
} |
|
#define I2C_START_LEN 1 |
#define I2C_STOP_LEN 1 |
#define I2C_ADDR_LEN 9 /* ADDRESS + R/W + ACK/NACK */ |
#define I2C_DATA_LEN 9 /* DATA + ACK/NACK */ |
|
/* |
* Calculate the length of the i2c transfer in usec, assuming |
* the i2c bus speed is as specified. Gives the the "worst" |
* case estimate, ie. successful while as long as possible. |
* Doesn't account the the "MOT" bit, and instead assumes each |
* message includes a START, ADDRESS and STOP. Neither does it |
* account for additional random variables such as clock stretching. |
*/ |
static int drm_dp_i2c_msg_duration(const struct drm_dp_aux_msg *msg, |
int i2c_speed_khz) |
{ |
/* AUX bitrate is 1MHz, i2c bitrate as specified */ |
return DIV_ROUND_UP((I2C_START_LEN + I2C_ADDR_LEN + |
msg->size * I2C_DATA_LEN + |
I2C_STOP_LEN) * 1000, i2c_speed_khz); |
} |
|
/* |
* Deterine how many retries should be attempted to successfully transfer |
* the specified message, based on the estimated durations of the |
* i2c and AUX transfers. |
*/ |
static int drm_dp_i2c_retry_count(const struct drm_dp_aux_msg *msg, |
int i2c_speed_khz) |
{ |
int aux_time_us = drm_dp_aux_req_duration(msg) + |
drm_dp_aux_reply_duration(msg); |
int i2c_time_us = drm_dp_i2c_msg_duration(msg, i2c_speed_khz); |
|
return DIV_ROUND_UP(i2c_time_us, aux_time_us + AUX_RETRY_INTERVAL); |
} |
|
/* |
* FIXME currently assumes 10 kHz as some real world devices seem |
* to require it. We should query/set the speed via DPCD if supported. |
*/ |
static int dp_aux_i2c_speed_khz __read_mostly = 10; |
module_param_unsafe(dp_aux_i2c_speed_khz, int, 0644); |
MODULE_PARM_DESC(dp_aux_i2c_speed_khz, |
"Assumed speed of the i2c bus in kHz, (1-400, default 10)"); |
|
/* |
* Transfer a single I2C-over-AUX message and handle various error conditions, |
* retrying the transaction as appropriate. It is assumed that the |
* aux->transfer function does not modify anything in the msg other than the |
* reply field. |
* |
* Returns bytes transferred on success, or a negative error code on failure. |
*/ |
static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) |
{ |
unsigned int retry; |
int err; |
|
unsigned int retry, defer_i2c; |
int ret; |
/* |
* DP1.2 sections 2.7.7.1.5.6.1 and 2.7.7.1.6.6.1: A DP Source device |
* is required to retry at least seven times upon receiving AUX_DEFER |
* before giving up the AUX transaction. |
* |
* We also try to account for the i2c bus speed. |
*/ |
for (retry = 0; retry < 7; retry++) { |
int max_retries = max(7, drm_dp_i2c_retry_count(msg, dp_aux_i2c_speed_khz)); |
|
for (retry = 0, defer_i2c = 0; retry < (max_retries + defer_i2c); retry++) { |
mutex_lock(&aux->hw_mutex); |
err = aux->transfer(aux, msg); |
ret = aux->transfer(aux, msg); |
mutex_unlock(&aux->hw_mutex); |
if (err < 0) { |
if (err == -EBUSY) |
if (ret < 0) { |
if (ret == -EBUSY) |
continue; |
|
DRM_DEBUG_KMS("transaction failed: %d\n", err); |
return err; |
DRM_DEBUG_KMS("transaction failed: %d\n", ret); |
return ret; |
} |
|
|
429,11 → 564,11 |
break; |
|
case DP_AUX_NATIVE_REPLY_NACK: |
DRM_DEBUG_KMS("native nack\n"); |
DRM_DEBUG_KMS("native nack (result=%d, size=%zu)\n", ret, msg->size); |
return -EREMOTEIO; |
|
case DP_AUX_NATIVE_REPLY_DEFER: |
DRM_DEBUG_KMS("native defer"); |
DRM_DEBUG_KMS("native defer\n"); |
/* |
* We could check for I2C bit rate capabilities and if |
* available adjust this interval. We could also be |
457,17 → 592,27 |
* Both native ACK and I2C ACK replies received. We |
* can assume the transfer was successful. |
*/ |
if (err < msg->size) |
return -EPROTO; |
return 0; |
if (ret != msg->size) |
drm_dp_i2c_msg_write_status_update(msg); |
return ret; |
|
case DP_AUX_I2C_REPLY_NACK: |
DRM_DEBUG_KMS("I2C nack\n"); |
DRM_DEBUG_KMS("I2C nack (result=%d, size=%zu\n", ret, msg->size); |
aux->i2c_nack_count++; |
return -EREMOTEIO; |
|
case DP_AUX_I2C_REPLY_DEFER: |
DRM_DEBUG_KMS("I2C defer\n"); |
/* DP Compliance Test 4.2.2.5 Requirement: |
* Must have at least 7 retries for I2C defers on the |
* transaction to pass this test |
*/ |
aux->i2c_defer_count++; |
if (defer_i2c < 7) |
defer_i2c++; |
usleep_range(400, 500); |
drm_dp_i2c_msg_write_status_update(msg); |
|
continue; |
|
default: |
480,22 → 625,68 |
return -EREMOTEIO; |
} |
|
static void drm_dp_i2c_msg_set_request(struct drm_dp_aux_msg *msg, |
const struct i2c_msg *i2c_msg) |
{ |
msg->request = (i2c_msg->flags & I2C_M_RD) ? |
DP_AUX_I2C_READ : DP_AUX_I2C_WRITE; |
msg->request |= DP_AUX_I2C_MOT; |
} |
|
/* |
* Keep retrying drm_dp_i2c_do_msg until all data has been transferred. |
* |
* Returns an error code on failure, or a recommended transfer size on success. |
*/ |
static int drm_dp_i2c_drain_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *orig_msg) |
{ |
int err, ret = orig_msg->size; |
struct drm_dp_aux_msg msg = *orig_msg; |
|
while (msg.size > 0) { |
err = drm_dp_i2c_do_msg(aux, &msg); |
if (err <= 0) |
return err == 0 ? -EPROTO : err; |
|
if (err < msg.size && err < ret) { |
DRM_DEBUG_KMS("Partial I2C reply: requested %zu bytes got %d bytes\n", |
msg.size, err); |
ret = err; |
} |
|
msg.size -= err; |
msg.buffer += err; |
} |
|
return ret; |
} |
|
/* |
* Bizlink designed DP->DVI-D Dual Link adapters require the I2C over AUX |
* packets to be as large as possible. If not, the I2C transactions never |
* succeed. Hence the default is maximum. |
*/ |
static int dp_aux_i2c_transfer_size __read_mostly = DP_AUX_MAX_PAYLOAD_BYTES; |
module_param_unsafe(dp_aux_i2c_transfer_size, int, 0644); |
MODULE_PARM_DESC(dp_aux_i2c_transfer_size, |
"Number of bytes to transfer in a single I2C over DP AUX CH message, (1-16, default 16)"); |
|
static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, |
int num) |
{ |
struct drm_dp_aux *aux = adapter->algo_data; |
unsigned int i, j; |
unsigned transfer_size; |
struct drm_dp_aux_msg msg; |
int err = 0; |
|
dp_aux_i2c_transfer_size = clamp(dp_aux_i2c_transfer_size, 1, DP_AUX_MAX_PAYLOAD_BYTES); |
|
memset(&msg, 0, sizeof(msg)); |
|
for (i = 0; i < num; i++) { |
msg.address = msgs[i].addr; |
msg.request = (msgs[i].flags & I2C_M_RD) ? |
DP_AUX_I2C_READ : |
DP_AUX_I2C_WRITE; |
msg.request |= DP_AUX_I2C_MOT; |
drm_dp_i2c_msg_set_request(&msg, &msgs[i]); |
/* Send a bare address packet to start the transaction. |
* Zero sized messages specify an address only (bare |
* address) transaction. |
503,22 → 694,35 |
msg.buffer = NULL; |
msg.size = 0; |
err = drm_dp_i2c_do_msg(aux, &msg); |
|
/* |
* Reset msg.request in case in case it got |
* changed into a WRITE_STATUS_UPDATE. |
*/ |
drm_dp_i2c_msg_set_request(&msg, &msgs[i]); |
|
if (err < 0) |
break; |
/* |
* Many hardware implementations support FIFOs larger than a |
* single byte, but it has been empirically determined that |
* transferring data in larger chunks can actually lead to |
* decreased performance. Therefore each message is simply |
* transferred byte-by-byte. |
/* We want each transaction to be as large as possible, but |
* we'll go to smaller sizes if the hardware gives us a |
* short reply. |
*/ |
for (j = 0; j < msgs[i].len; j++) { |
transfer_size = dp_aux_i2c_transfer_size; |
for (j = 0; j < msgs[i].len; j += msg.size) { |
msg.buffer = msgs[i].buf + j; |
msg.size = 1; |
msg.size = min(transfer_size, msgs[i].len - j); |
|
err = drm_dp_i2c_do_msg(aux, &msg); |
err = drm_dp_i2c_drain_msg(aux, &msg); |
|
/* |
* Reset msg.request in case in case it got |
* changed into a WRITE_STATUS_UPDATE. |
*/ |
drm_dp_i2c_msg_set_request(&msg, &msgs[i]); |
|
if (err < 0) |
break; |
transfer_size = err; |
} |
if (err < 0) |
break; |