Skip to content

Commit

Permalink
drm: vc4: dsi: enable video and then retry failed transfers
Browse files Browse the repository at this point in the history
The DSI block appears to be able to come up stuck in a condition where
it leaves the lanes in HS mode or just jabbering. This stops LP
transfers from completing as there is no LP time available. This is
signalled via the LP1 contention error.

Enabling video briefly clears that condition, so if we detect the
error condition, enable video mode and then retry.

Signed-off-by: Dave Stevenson <[email protected]>
  • Loading branch information
6by9 committed Sep 20, 2024
1 parent a6891c8 commit 44f0745
Showing 1 changed file with 40 additions and 8 deletions.
48 changes: 40 additions & 8 deletions drivers/gpu/drm/vc4/vc4_dsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,8 @@
DSI1_INT_PR_TO)

#define DSI0_STAT 0x2c
# define DSI0_STAT_ERR_CONT_LP1 BIT(6)
# define DSI0_STAT_ERR_CONT_LP0 BIT(5)
#define DSI0_HSTX_TO_CNT 0x30
#define DSI0_LPRX_TO_CNT 0x34
#define DSI0_TA_TO_CNT 0x38
Expand Down Expand Up @@ -1203,10 +1205,9 @@ static int vc4_dsi_bridge_attach(struct drm_bridge *bridge,
&dsi->bridge, flags);
}

static ssize_t vc4_dsi_host_transfer(struct mipi_dsi_host *host,
const struct mipi_dsi_msg *msg)
static ssize_t vc4_dsi_transfer(struct vc4_dsi *dsi,
const struct mipi_dsi_msg *msg, bool log_error)
{
struct vc4_dsi *dsi = host_to_dsi(host);
struct mipi_dsi_packet packet;
u32 pkth = 0, pktc = 0;
int i, ret;
Expand Down Expand Up @@ -1315,10 +1316,12 @@ static ssize_t vc4_dsi_host_transfer(struct mipi_dsi_host *host,
DSI_PORT_WRITE(TXPKT1C, pktc);

if (!wait_for_completion_timeout(&dsi->xfer_completion,
msecs_to_jiffies(1000))) {
dev_err(&dsi->pdev->dev, "transfer interrupt wait timeout");
dev_err(&dsi->pdev->dev, "instat: 0x%08x\n",
DSI_PORT_READ(INT_STAT));
msecs_to_jiffies(500))) {
if (log_error) {
dev_err(&dsi->pdev->dev, "transfer interrupt wait timeout");
dev_err(&dsi->pdev->dev, "instat: 0x%08x, stat: 0x%08x\n",
DSI_PORT_READ(INT_STAT), DSI_PORT_READ(INT_STAT));
}
ret = -ETIMEDOUT;
} else {
ret = dsi->xfer_result;
Expand Down Expand Up @@ -1361,7 +1364,8 @@ static ssize_t vc4_dsi_host_transfer(struct mipi_dsi_host *host,
return ret;

reset_fifo_and_return:
DRM_ERROR("DSI transfer failed, resetting: %d\n", ret);
if (log_error)
DRM_ERROR("DSI transfer failed, resetting: %d\n", ret);

DSI_PORT_WRITE(TXPKT1C, DSI_PORT_READ(TXPKT1C) & ~DSI_TXPKT1C_CMD_EN);
udelay(1);
Expand All @@ -1374,6 +1378,34 @@ static ssize_t vc4_dsi_host_transfer(struct mipi_dsi_host *host,
return ret;
}

static ssize_t vc4_dsi_host_transfer(struct mipi_dsi_host *host,
const struct mipi_dsi_msg *msg)
{
struct vc4_dsi *dsi = host_to_dsi(host);
u32 stat, disp0_ctrl;
int ret;

ret = vc4_dsi_transfer(dsi, msg, false);

if (ret == -ETIMEDOUT) {
stat = DSI_PORT_READ(STAT);
if (stat & DSI_PORT_BIT(STAT_ERR_CONT_LP1)) {
DSI_PORT_WRITE(STAT, DSI_PORT_BIT(STAT_ERR_CONT_LP1));

disp0_ctrl = DSI_PORT_READ(DISP0_CTRL);
disp0_ctrl |= DSI_DISP0_ENABLE;
DSI_PORT_WRITE(DISP0_CTRL, disp0_ctrl);
msleep(30);
disp0_ctrl &= ~DSI_DISP0_ENABLE;
DSI_PORT_WRITE(DISP0_CTRL, disp0_ctrl);
msleep(30);

ret = vc4_dsi_transfer(dsi, msg, true);
}
}
return ret;
}

static const struct component_ops vc4_dsi_ops;
static int vc4_dsi_host_attach(struct mipi_dsi_host *host,
struct mipi_dsi_device *device)
Expand Down

0 comments on commit 44f0745

Please sign in to comment.