Skip to content

Commit

Permalink
drm/mcde: Fix DSI transfers
Browse files Browse the repository at this point in the history
There were bugs in the DSI transfer (read and write) function
as it was only tested with displays ever needing a single byte
to be written. Fixed it up and tested so we can now write
messages of up to 16 bytes and read up to 4 bytes from the
display.

Tested with a Sony ACX424AKP display: this display now self-
identifies and can control backlight in command mode.

Reported-by: kbuild test robot <lkp@intel.com>
Fixes: 5fc537b ("drm/mcde: Add new driver for ST-Ericsson MCDE")
Reviewed-by: Stephan Gerhold <stephan@gerhold.net>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20190903170804.17053-1-linus.walleij@linaro.org
  • Loading branch information
Linus Walleij committed Sep 4, 2019
1 parent 45d0dbd commit 88537dd
Showing 1 changed file with 47 additions and 23 deletions.
70 changes: 47 additions & 23 deletions drivers/gpu/drm/mcde/mcde_dsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,22 +178,26 @@ static ssize_t mcde_dsi_host_transfer(struct mipi_dsi_host *host,
const u32 loop_delay_us = 10; /* us */
const u8 *tx = msg->tx_buf;
u32 loop_counter;
size_t txlen;
size_t txlen = msg->tx_len;
size_t rxlen = msg->rx_len;
u32 val;
int ret;
int i;

txlen = msg->tx_len;
if (txlen > 12) {
if (txlen > 16) {
dev_err(d->dev,
"dunno how to write more than 12 bytes yet\n");
"dunno how to write more than 16 bytes yet\n");
return -EIO;
}
if (rxlen > 4) {
dev_err(d->dev,
"dunno how to read more than 4 bytes yet\n");
return -EIO;
}

dev_dbg(d->dev,
"message to channel %d, %zd bytes",
msg->channel,
txlen);
"message to channel %d, write %zd bytes read %zd bytes\n",
msg->channel, txlen, rxlen);

/* Command "nature" */
if (MCDE_DSI_HOST_IS_READ(msg->type))
Expand All @@ -210,9 +214,7 @@ static ssize_t mcde_dsi_host_transfer(struct mipi_dsi_host *host,
if (mipi_dsi_packet_format_is_long(msg->type))
val |= DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LONGNOTSHORT;
val |= 0 << DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_ID_SHIFT;
/* Add one to the length for the MIPI DCS command */
val |= txlen
<< DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_SIZE_SHIFT;
val |= txlen << DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_SIZE_SHIFT;
val |= DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LP_EN;
val |= msg->type << DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_SHIFT;
writel(val, d->regs + DSI_DIRECT_CMD_MAIN_SETTINGS);
Expand Down Expand Up @@ -249,17 +251,36 @@ static ssize_t mcde_dsi_host_transfer(struct mipi_dsi_host *host,
writel(1, d->regs + DSI_DIRECT_CMD_SEND);

loop_counter = 1000 * 1000 / loop_delay_us;
while (!(readl(d->regs + DSI_DIRECT_CMD_STS) &
DSI_DIRECT_CMD_STS_WRITE_COMPLETED)
&& --loop_counter)
usleep_range(loop_delay_us, (loop_delay_us * 3) / 2);

if (!loop_counter) {
dev_err(d->dev, "DSI write timeout!\n");
return -ETIME;
if (MCDE_DSI_HOST_IS_READ(msg->type)) {
/* Read command */
while (!(readl(d->regs + DSI_DIRECT_CMD_STS) &
(DSI_DIRECT_CMD_STS_READ_COMPLETED |
DSI_DIRECT_CMD_STS_READ_COMPLETED_WITH_ERR))
&& --loop_counter)
usleep_range(loop_delay_us, (loop_delay_us * 3) / 2);
if (!loop_counter) {
dev_err(d->dev, "DSI read timeout!\n");
return -ETIME;
}
} else {
/* Writing only */
while (!(readl(d->regs + DSI_DIRECT_CMD_STS) &
DSI_DIRECT_CMD_STS_WRITE_COMPLETED)
&& --loop_counter)
usleep_range(loop_delay_us, (loop_delay_us * 3) / 2);

if (!loop_counter) {
dev_err(d->dev, "DSI write timeout!\n");
return -ETIME;
}
}

val = readl(d->regs + DSI_DIRECT_CMD_STS);
if (val & DSI_DIRECT_CMD_STS_READ_COMPLETED_WITH_ERR) {
dev_err(d->dev, "read completed with error\n");
writel(1, d->regs + DSI_DIRECT_CMD_RD_INIT);
return -EIO;
}
if (val & DSI_DIRECT_CMD_STS_ACKNOWLEDGE_WITH_ERR_RECEIVED) {
val >>= DSI_DIRECT_CMD_STS_ACK_VAL_SHIFT;
dev_err(d->dev, "error during transmission: %04x\n",
Expand All @@ -269,10 +290,7 @@ static ssize_t mcde_dsi_host_transfer(struct mipi_dsi_host *host,

if (!MCDE_DSI_HOST_IS_READ(msg->type)) {
/* Return number of bytes written */
if (mipi_dsi_packet_format_is_long(msg->type))
ret = 4 + txlen;
else
ret = 4;
ret = txlen;
} else {
/* OK this is a read command, get the response */
u32 rdsz;
Expand All @@ -282,7 +300,13 @@ static ssize_t mcde_dsi_host_transfer(struct mipi_dsi_host *host,
rdsz = readl(d->regs + DSI_DIRECT_CMD_RD_PROPERTY);
rdsz &= DSI_DIRECT_CMD_RD_PROPERTY_RD_SIZE_MASK;
rddat = readl(d->regs + DSI_DIRECT_CMD_RDDAT);
for (i = 0; i < 4 && i < rdsz; i++)
if (rdsz < rxlen) {
dev_err(d->dev, "read error, requested %zd got %d\n",
rxlen, rdsz);
return -EIO;
}
/* FIXME: read more than 4 bytes */
for (i = 0; i < 4 && i < rxlen; i++)
rx[i] = (rddat >> (i * 8)) & 0xff;
ret = rdsz;
}
Expand Down

0 comments on commit 88537dd

Please sign in to comment.