diff options
Diffstat (limited to 'drivers/gpu/drm/drm_dp_helper.c')
-rw-r--r-- | drivers/gpu/drm/drm_dp_helper.c | 55 |
1 files changed, 35 insertions, 20 deletions
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 27671489477d..4b6e6f3ba0a1 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c | |||
@@ -577,7 +577,9 @@ static u32 drm_dp_i2c_functionality(struct i2c_adapter *adapter) | |||
577 | 577 | ||
578 | /* | 578 | /* |
579 | * Transfer a single I2C-over-AUX message and handle various error conditions, | 579 | * Transfer a single I2C-over-AUX message and handle various error conditions, |
580 | * retrying the transaction as appropriate. | 580 | * retrying the transaction as appropriate. It is assumed that the |
581 | * aux->transfer function does not modify anything in the msg other than the | ||
582 | * reply field. | ||
581 | */ | 583 | */ |
582 | static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) | 584 | static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) |
583 | { | 585 | { |
@@ -665,11 +667,26 @@ static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, | |||
665 | { | 667 | { |
666 | struct drm_dp_aux *aux = adapter->algo_data; | 668 | struct drm_dp_aux *aux = adapter->algo_data; |
667 | unsigned int i, j; | 669 | unsigned int i, j; |
670 | struct drm_dp_aux_msg msg; | ||
671 | int err = 0; | ||
668 | 672 | ||
669 | for (i = 0; i < num; i++) { | 673 | memset(&msg, 0, sizeof(msg)); |
670 | struct drm_dp_aux_msg msg; | ||
671 | int err; | ||
672 | 674 | ||
675 | for (i = 0; i < num; i++) { | ||
676 | msg.address = msgs[i].addr; | ||
677 | msg.request = (msgs[i].flags & I2C_M_RD) ? | ||
678 | DP_AUX_I2C_READ : | ||
679 | DP_AUX_I2C_WRITE; | ||
680 | msg.request |= DP_AUX_I2C_MOT; | ||
681 | /* Send a bare address packet to start the transaction. | ||
682 | * Zero sized messages specify an address only (bare | ||
683 | * address) transaction. | ||
684 | */ | ||
685 | msg.buffer = NULL; | ||
686 | msg.size = 0; | ||
687 | err = drm_dp_i2c_do_msg(aux, &msg); | ||
688 | if (err < 0) | ||
689 | break; | ||
673 | /* | 690 | /* |
674 | * Many hardware implementations support FIFOs larger than a | 691 | * Many hardware implementations support FIFOs larger than a |
675 | * single byte, but it has been empirically determined that | 692 | * single byte, but it has been empirically determined that |
@@ -678,30 +695,28 @@ static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, | |||
678 | * transferred byte-by-byte. | 695 | * transferred byte-by-byte. |
679 | */ | 696 | */ |
680 | for (j = 0; j < msgs[i].len; j++) { | 697 | for (j = 0; j < msgs[i].len; j++) { |
681 | memset(&msg, 0, sizeof(msg)); | ||
682 | msg.address = msgs[i].addr; | ||
683 | |||
684 | msg.request = (msgs[i].flags & I2C_M_RD) ? | ||
685 | DP_AUX_I2C_READ : | ||
686 | DP_AUX_I2C_WRITE; | ||
687 | |||
688 | /* | ||
689 | * All messages except the last one are middle-of- | ||
690 | * transfer messages. | ||
691 | */ | ||
692 | if ((i < num - 1) || (j < msgs[i].len - 1)) | ||
693 | msg.request |= DP_AUX_I2C_MOT; | ||
694 | |||
695 | msg.buffer = msgs[i].buf + j; | 698 | msg.buffer = msgs[i].buf + j; |
696 | msg.size = 1; | 699 | msg.size = 1; |
697 | 700 | ||
698 | err = drm_dp_i2c_do_msg(aux, &msg); | 701 | err = drm_dp_i2c_do_msg(aux, &msg); |
699 | if (err < 0) | 702 | if (err < 0) |
700 | return err; | 703 | break; |
701 | } | 704 | } |
705 | if (err < 0) | ||
706 | break; | ||
702 | } | 707 | } |
708 | if (err >= 0) | ||
709 | err = num; | ||
710 | /* Send a bare address packet to close out the transaction. | ||
711 | * Zero sized messages specify an address only (bare | ||
712 | * address) transaction. | ||
713 | */ | ||
714 | msg.request &= ~DP_AUX_I2C_MOT; | ||
715 | msg.buffer = NULL; | ||
716 | msg.size = 0; | ||
717 | (void)drm_dp_i2c_do_msg(aux, &msg); | ||
703 | 718 | ||
704 | return num; | 719 | return err; |
705 | } | 720 | } |
706 | 721 | ||
707 | static const struct i2c_algorithm drm_dp_i2c_algo = { | 722 | static const struct i2c_algorithm drm_dp_i2c_algo = { |