Message ID | 1396859864-25955-1-git-send-email-thierry.reding@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
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; > + value |= DPAUX_DP_AUXCTL_CMD_MOT_WR; > else > - 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; > + value |= DPAUX_DP_AUXCTL_CMD_MOT_RD; > else > - 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; > + value |= DPAUX_DP_AUXCTL_CMD_MOT_RQ; > else > - 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
On Tue, Apr 8, 2014 at 4:06 PM, Christian König <deathsimple@vodafone.de> wrote: > 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? The patch is not in drm-next. To preserve bisectability it should be part of Alex' patch set and it needs to be applied before the patch that makes use of the bare address transactions (patch 2/4 in the series). Thierry
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; + value |= DPAUX_DP_AUXCTL_CMD_MOT_WR; else - 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; + value |= DPAUX_DP_AUXCTL_CMD_MOT_RD; else - 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; + value |= DPAUX_DP_AUXCTL_CMD_MOT_RQ; else - 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