Am 07.04.2014 10:37, schrieb Thierry Reding:
From: Thierry Reding treding@nvidia.com
Certain types of I2C-over-AUX transactions require that only the address is transferred. Detect this by looking at the AUX message's size and set the address-only bit appropriately.
Signed-off-by: Thierry Reding treding@nvidia.com
Hi Alex,
This patch is required to make eDP work properly on Tegra with your I2C- over-AUX patch series applied. Would you consider carrying this in your series so that bisectability can be maintained? It would need to be applied prior to the core change (patch 2/4 in the latest series) to do so.
Hi Thierry,
do you already have this patch in drm-next or should I send it do Dave together with the pull request for the dp aux helper changes?
Regards, Christian.
Thanks, Thierry
drivers/gpu/drm/tegra/dpaux.c | 44 ++++++++++++++++++++++++++++++------------- drivers/gpu/drm/tegra/dpaux.h | 1 + 2 files changed, 32 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/tegra/dpaux.c b/drivers/gpu/drm/tegra/dpaux.c index d536ed381fbd..005c19bd92df 100644 --- a/drivers/gpu/drm/tegra/dpaux.c +++ b/drivers/gpu/drm/tegra/dpaux.c @@ -99,55 +99,73 @@ static void tegra_dpaux_read_fifo(struct tegra_dpaux *dpaux, u8 *buffer, static ssize_t tegra_dpaux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) {
- unsigned long value = DPAUX_DP_AUXCTL_TRANSACTREQ; unsigned long timeout = msecs_to_jiffies(250); struct tegra_dpaux *dpaux = to_dpaux(aux); unsigned long status; ssize_t ret = 0;
- u32 value;
- if (msg->size < 1 || msg->size > 16)
- /* Tegra has 4x4 byte DP AUX transmit and receive FIFOs. */
- if (msg->size > 16) return -EINVAL;
- tegra_dpaux_writel(dpaux, msg->address, DPAUX_DP_AUXADDR);
/*
* Allow zero-sized messages only for I2C, in which case they specify
* address-only transactions.
*/
if (msg->size < 1) {
switch (msg->request & ~DP_AUX_I2C_MOT) {
case DP_AUX_I2C_WRITE:
case DP_AUX_I2C_READ:
value = DPAUX_DP_AUXCTL_CMD_ADDRESS_ONLY;
break;
default:
return -EINVAL;
}
} else {
/* For non-zero-sized messages, set the CMDLEN field. */
value = DPAUX_DP_AUXCTL_CMDLEN(msg->size - 1);
}
switch (msg->request & ~DP_AUX_I2C_MOT) { case DP_AUX_I2C_WRITE: if (msg->request & DP_AUX_I2C_MOT)
value = DPAUX_DP_AUXCTL_CMD_MOT_WR;
elsevalue |= DPAUX_DP_AUXCTL_CMD_MOT_WR;
value = DPAUX_DP_AUXCTL_CMD_I2C_WR;
value |= DPAUX_DP_AUXCTL_CMD_I2C_WR;
break;
case DP_AUX_I2C_READ: if (msg->request & DP_AUX_I2C_MOT)
value = DPAUX_DP_AUXCTL_CMD_MOT_RD;
elsevalue |= DPAUX_DP_AUXCTL_CMD_MOT_RD;
value = DPAUX_DP_AUXCTL_CMD_I2C_RD;
value |= DPAUX_DP_AUXCTL_CMD_I2C_RD;
break;
case DP_AUX_I2C_STATUS: if (msg->request & DP_AUX_I2C_MOT)
value = DPAUX_DP_AUXCTL_CMD_MOT_RQ;
elsevalue |= DPAUX_DP_AUXCTL_CMD_MOT_RQ;
value = DPAUX_DP_AUXCTL_CMD_I2C_RQ;
value |= DPAUX_DP_AUXCTL_CMD_I2C_RQ;
break;
case DP_AUX_NATIVE_WRITE:
value = DPAUX_DP_AUXCTL_CMD_AUX_WR;
value |= DPAUX_DP_AUXCTL_CMD_AUX_WR;
break;
case DP_AUX_NATIVE_READ:
value = DPAUX_DP_AUXCTL_CMD_AUX_RD;
value |= DPAUX_DP_AUXCTL_CMD_AUX_RD;
break;
default: return -EINVAL; }
- value |= DPAUX_DP_AUXCTL_CMDLEN(msg->size - 1);
tegra_dpaux_writel(dpaux, msg->address, DPAUX_DP_AUXADDR); tegra_dpaux_writel(dpaux, value, DPAUX_DP_AUXCTL);
if ((msg->request & DP_AUX_I2C_READ) == 0) {
@@ -198,7 +216,7 @@ static ssize_t tegra_dpaux_transfer(struct drm_dp_aux *aux, break; }
- if (msg->reply == DP_AUX_NATIVE_REPLY_ACK) {
- if ((msg->size > 0) && (msg->reply == DP_AUX_NATIVE_REPLY_ACK)) { if (msg->request & DP_AUX_I2C_READ) { size_t count = value & DPAUX_DP_AUXSTAT_REPLY_MASK;
diff --git a/drivers/gpu/drm/tegra/dpaux.h b/drivers/gpu/drm/tegra/dpaux.h index 4f5bf10fdff9..806e245ca787 100644 --- a/drivers/gpu/drm/tegra/dpaux.h +++ b/drivers/gpu/drm/tegra/dpaux.h @@ -32,6 +32,7 @@ #define DPAUX_DP_AUXCTL_CMD_I2C_RQ (2 << 12) #define DPAUX_DP_AUXCTL_CMD_I2C_RD (1 << 12) #define DPAUX_DP_AUXCTL_CMD_I2C_WR (0 << 12) +#define DPAUX_DP_AUXCTL_CMD_ADDRESS_ONLY (1 << 8) #define DPAUX_DP_AUXCTL_CMDLEN(x) ((x) & 0xff)
#define DPAUX_DP_AUXSTAT 0x31