aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Farnsworth <simon.farnsworth@onelan.co.uk>2015-02-10 13:38:08 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2015-03-11 17:04:56 -0400
commit1d002fa720738bcd0bddb9178e9ea0773288e1dd (patch)
tree4a01b874d3b25afd098209c5983e23f50b6b3bc2
parent967667fd6d96a16fd4a216251eee112a214207ec (diff)
drm/dp: Use large transactions for I2C over AUX
Older DisplayPort to DVI-D Dual Link adapters designed by Bizlink have bugs in their I2C over AUX implementation (fixed in newer revisions). They work fine with Windows, but fail with Linux. It turns out that they cannot keep an I2C transaction open unless the previous read was 16 bytes; shorter reads can only be followed by a zero byte transfer ending the I2C transaction. Copy Windows's behaviour, and read 16 bytes at a time. If we get a short reply, assume that there's a hardware bottleneck, and shrink our read size to match. For this purpose, use the algorithm in the DisplayPort 1.2 spec, in the hopes that it'll be closest to what Windows does. Also provide an unsafe module parameter for testing smaller transfer sizes, in case there are sinks out there that cannot work with Windows. Note also that despite the previous comment in drm_dp_i2c_xfer, this speeds up native DP EDID reads; Ville Syrjälä <ville.syrjala@linux.intel.com> found the following changes in his testing: Device under test: old -> with this patch DP->DVI (OUI 001cf8): 40ms -> 35ms DP->VGA (OUI 0022b9): 45ms -> 38ms Zotac DP->2xHDMI: 25ms -> 4ms Asus PB278 monitor: 22ms -> 3ms A back of the envelope calculation shows that peak theoretical transfer rate for 1 byte reads is around 60 kbit/s; with 16 byte reads, this increases to around 500 kbit/s, which explains the increase in speed. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=55228 Tested-by: Aidan Marks <aidanamarks@gmail.com> (v3) Signed-off-by: Simon Farnsworth <simon.farnsworth@onelan.co.uk> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/drm_dp_helper.c76
-rw-r--r--include/drm/drm_dp_helper.h5
2 files changed, 63 insertions, 18 deletions
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index f1283878ff6d..d5368ea56a0f 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -427,11 +427,13 @@ static u32 drm_dp_i2c_functionality(struct i2c_adapter *adapter)
427 * retrying the transaction as appropriate. It is assumed that the 427 * retrying the transaction as appropriate. It is assumed that the
428 * aux->transfer function does not modify anything in the msg other than the 428 * aux->transfer function does not modify anything in the msg other than the
429 * reply field. 429 * reply field.
430 *
431 * Returns bytes transferred on success, or a negative error code on failure.
430 */ 432 */
431static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) 433static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
432{ 434{
433 unsigned int retry; 435 unsigned int retry;
434 int err; 436 int ret;
435 437
436 /* 438 /*
437 * DP1.2 sections 2.7.7.1.5.6.1 and 2.7.7.1.6.6.1: A DP Source device 439 * DP1.2 sections 2.7.7.1.5.6.1 and 2.7.7.1.6.6.1: A DP Source device
@@ -440,14 +442,14 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
440 */ 442 */
441 for (retry = 0; retry < 7; retry++) { 443 for (retry = 0; retry < 7; retry++) {
442 mutex_lock(&aux->hw_mutex); 444 mutex_lock(&aux->hw_mutex);
443 err = aux->transfer(aux, msg); 445 ret = aux->transfer(aux, msg);
444 mutex_unlock(&aux->hw_mutex); 446 mutex_unlock(&aux->hw_mutex);
445 if (err < 0) { 447 if (ret < 0) {
446 if (err == -EBUSY) 448 if (ret == -EBUSY)
447 continue; 449 continue;
448 450
449 DRM_DEBUG_KMS("transaction failed: %d\n", err); 451 DRM_DEBUG_KMS("transaction failed: %d\n", ret);
450 return err; 452 return ret;
451 } 453 }
452 454
453 455
@@ -488,9 +490,7 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
488 * Both native ACK and I2C ACK replies received. We 490 * Both native ACK and I2C ACK replies received. We
489 * can assume the transfer was successful. 491 * can assume the transfer was successful.
490 */ 492 */
491 if (err < msg->size) 493 return ret;
492 return -EPROTO;
493 return 0;
494 494
495 case DP_AUX_I2C_REPLY_NACK: 495 case DP_AUX_I2C_REPLY_NACK:
496 DRM_DEBUG_KMS("I2C nack\n"); 496 DRM_DEBUG_KMS("I2C nack\n");
@@ -513,14 +513,55 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
513 return -EREMOTEIO; 513 return -EREMOTEIO;
514} 514}
515 515
516/*
517 * Keep retrying drm_dp_i2c_do_msg until all data has been transferred.
518 *
519 * Returns an error code on failure, or a recommended transfer size on success.
520 */
521static int drm_dp_i2c_drain_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *orig_msg)
522{
523 int err, ret = orig_msg->size;
524 struct drm_dp_aux_msg msg = *orig_msg;
525
526 while (msg.size > 0) {
527 err = drm_dp_i2c_do_msg(aux, &msg);
528 if (err <= 0)
529 return err == 0 ? -EPROTO : err;
530
531 if (err < msg.size && err < ret) {
532 DRM_DEBUG_KMS("Partial I2C reply: requested %zu bytes got %d bytes\n",
533 msg.size, err);
534 ret = err;
535 }
536
537 msg.size -= err;
538 msg.buffer += err;
539 }
540
541 return ret;
542}
543
544/*
545 * Bizlink designed DP->DVI-D Dual Link adapters require the I2C over AUX
546 * packets to be as large as possible. If not, the I2C transactions never
547 * succeed. Hence the default is maximum.
548 */
549static int dp_aux_i2c_transfer_size __read_mostly = DP_AUX_MAX_PAYLOAD_BYTES;
550module_param_unsafe(dp_aux_i2c_transfer_size, int, 0644);
551MODULE_PARM_DESC(dp_aux_i2c_transfer_size,
552 "Number of bytes to transfer in a single I2C over DP AUX CH message, (1-16, default 16)");
553
516static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, 554static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
517 int num) 555 int num)
518{ 556{
519 struct drm_dp_aux *aux = adapter->algo_data; 557 struct drm_dp_aux *aux = adapter->algo_data;
520 unsigned int i, j; 558 unsigned int i, j;
559 unsigned transfer_size;
521 struct drm_dp_aux_msg msg; 560 struct drm_dp_aux_msg msg;
522 int err = 0; 561 int err = 0;
523 562
563 dp_aux_i2c_transfer_size = clamp(dp_aux_i2c_transfer_size, 1, DP_AUX_MAX_PAYLOAD_BYTES);
564
524 memset(&msg, 0, sizeof(msg)); 565 memset(&msg, 0, sizeof(msg));
525 566
526 for (i = 0; i < num; i++) { 567 for (i = 0; i < num; i++) {
@@ -538,20 +579,19 @@ static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
538 err = drm_dp_i2c_do_msg(aux, &msg); 579 err = drm_dp_i2c_do_msg(aux, &msg);
539 if (err < 0) 580 if (err < 0)
540 break; 581 break;
541 /* 582 /* We want each transaction to be as large as possible, but
542 * Many hardware implementations support FIFOs larger than a 583 * we'll go to smaller sizes if the hardware gives us a
543 * single byte, but it has been empirically determined that 584 * short reply.
544 * transferring data in larger chunks can actually lead to
545 * decreased performance. Therefore each message is simply
546 * transferred byte-by-byte.
547 */ 585 */
548 for (j = 0; j < msgs[i].len; j++) { 586 transfer_size = dp_aux_i2c_transfer_size;
587 for (j = 0; j < msgs[i].len; j += msg.size) {
549 msg.buffer = msgs[i].buf + j; 588 msg.buffer = msgs[i].buf + j;
550 msg.size = 1; 589 msg.size = min(transfer_size, msgs[i].len - j);
551 590
552 err = drm_dp_i2c_do_msg(aux, &msg); 591 err = drm_dp_i2c_drain_msg(aux, &msg);
553 if (err < 0) 592 if (err < 0)
554 break; 593 break;
594 transfer_size = err;
555 } 595 }
556 if (err < 0) 596 if (err < 0)
557 break; 597 break;
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index c5fdc2d3ca97..523f04c90dea 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -42,6 +42,8 @@
42 * 1.2 formally includes both eDP and DPI definitions. 42 * 1.2 formally includes both eDP and DPI definitions.
43 */ 43 */
44 44
45#define DP_AUX_MAX_PAYLOAD_BYTES 16
46
45#define DP_AUX_I2C_WRITE 0x0 47#define DP_AUX_I2C_WRITE 0x0
46#define DP_AUX_I2C_READ 0x1 48#define DP_AUX_I2C_READ 0x1
47#define DP_AUX_I2C_STATUS 0x2 49#define DP_AUX_I2C_STATUS 0x2
@@ -680,6 +682,9 @@ struct drm_dp_aux_msg {
680 * transactions. The drm_dp_aux_register_i2c_bus() function registers an 682 * transactions. The drm_dp_aux_register_i2c_bus() function registers an
681 * I2C adapter that can be passed to drm_probe_ddc(). Upon removal, drivers 683 * I2C adapter that can be passed to drm_probe_ddc(). Upon removal, drivers
682 * should call drm_dp_aux_unregister_i2c_bus() to remove the I2C adapter. 684 * should call drm_dp_aux_unregister_i2c_bus() to remove the I2C adapter.
685 * The I2C adapter uses long transfers by default; if a partial response is
686 * received, the adapter will drop down to the size given by the partial
687 * response for this transaction only.
683 * 688 *
684 * Note that the aux helper code assumes that the .transfer() function 689 * Note that the aux helper code assumes that the .transfer() function
685 * only modifies the reply field of the drm_dp_aux_msg structure. The 690 * only modifies the reply field of the drm_dp_aux_msg structure. The