e39e3b58655bc5f096fbff9cce4a27c7242c9bb6
[openwrt/staging/linusw.git] /
1 From 6da70162dd1e729c04e2dc25472b39390868af79 Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.com>
3 Date: Fri, 20 Sep 2024 12:05:18 +0100
4 Subject: [PATCH 1272/1350] drm: vc4: dsi: enable video and then retry failed
5 transfers
6
7 The DSI block appears to be able to come up stuck in a condition where
8 it leaves the lanes in HS mode or just jabbering. This stops LP
9 transfers from completing as there is no LP time available. This is
10 signalled via the LP1 contention error.
11
12 Enabling video briefly clears that condition, so if we detect the
13 error condition, enable video mode and then retry.
14
15 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
16 ---
17 drivers/gpu/drm/vc4/vc4_dsi.c | 54 +++++++++++++++++++++++++++++------
18 1 file changed, 46 insertions(+), 8 deletions(-)
19
20 --- a/drivers/gpu/drm/vc4/vc4_dsi.c
21 +++ b/drivers/gpu/drm/vc4/vc4_dsi.c
22 @@ -286,6 +286,8 @@
23 DSI1_INT_PR_TO)
24
25 #define DSI0_STAT 0x2c
26 +# define DSI0_STAT_ERR_CONT_LP1 BIT(6)
27 +# define DSI0_STAT_ERR_CONT_LP0 BIT(5)
28 #define DSI0_HSTX_TO_CNT 0x30
29 #define DSI0_LPRX_TO_CNT 0x34
30 #define DSI0_TA_TO_CNT 0x38
31 @@ -1203,10 +1205,9 @@ static int vc4_dsi_bridge_attach(struct
32 &dsi->bridge, flags);
33 }
34
35 -static ssize_t vc4_dsi_host_transfer(struct mipi_dsi_host *host,
36 - const struct mipi_dsi_msg *msg)
37 +static ssize_t vc4_dsi_transfer(struct vc4_dsi *dsi,
38 + const struct mipi_dsi_msg *msg, bool log_error)
39 {
40 - struct vc4_dsi *dsi = host_to_dsi(host);
41 struct mipi_dsi_packet packet;
42 u32 pkth = 0, pktc = 0;
43 int i, ret;
44 @@ -1315,10 +1316,12 @@ static ssize_t vc4_dsi_host_transfer(str
45 DSI_PORT_WRITE(TXPKT1C, pktc);
46
47 if (!wait_for_completion_timeout(&dsi->xfer_completion,
48 - msecs_to_jiffies(1000))) {
49 - dev_err(&dsi->pdev->dev, "transfer interrupt wait timeout");
50 - dev_err(&dsi->pdev->dev, "instat: 0x%08x\n",
51 - DSI_PORT_READ(INT_STAT));
52 + msecs_to_jiffies(500))) {
53 + if (log_error) {
54 + dev_err(&dsi->pdev->dev, "transfer interrupt wait timeout");
55 + dev_err(&dsi->pdev->dev, "instat: 0x%08x, stat: 0x%08x\n",
56 + DSI_PORT_READ(INT_STAT), DSI_PORT_READ(INT_STAT));
57 + }
58 ret = -ETIMEDOUT;
59 } else {
60 ret = dsi->xfer_result;
61 @@ -1361,7 +1364,8 @@ static ssize_t vc4_dsi_host_transfer(str
62 return ret;
63
64 reset_fifo_and_return:
65 - DRM_ERROR("DSI transfer failed, resetting: %d\n", ret);
66 + if (log_error)
67 + DRM_ERROR("DSI transfer failed, resetting: %d\n", ret);
68
69 DSI_PORT_WRITE(TXPKT1C, DSI_PORT_READ(TXPKT1C) & ~DSI_TXPKT1C_CMD_EN);
70 udelay(1);
71 @@ -1374,6 +1378,40 @@ reset_fifo_and_return:
72 return ret;
73 }
74
75 +static ssize_t vc4_dsi_host_transfer(struct mipi_dsi_host *host,
76 + const struct mipi_dsi_msg *msg)
77 +{
78 + struct vc4_dsi *dsi = host_to_dsi(host);
79 + u32 stat, disp0_ctrl;
80 + int ret;
81 +
82 + ret = vc4_dsi_transfer(dsi, msg, false);
83 +
84 + if (ret == -ETIMEDOUT) {
85 + stat = DSI_PORT_READ(STAT);
86 + disp0_ctrl = DSI_PORT_READ(DISP0_CTRL);
87 +
88 + DSI_PORT_WRITE(STAT, DSI_PORT_BIT(STAT_ERR_CONT_LP1));
89 + if (!(disp0_ctrl & DSI_DISP0_ENABLE)) {
90 + /* If video mode not enabled, then try recovering by
91 + * enabling it briefly to clear FIFOs and the state.
92 + */
93 + disp0_ctrl |= DSI_DISP0_ENABLE;
94 + DSI_PORT_WRITE(DISP0_CTRL, disp0_ctrl);
95 + msleep(30);
96 + disp0_ctrl &= ~DSI_DISP0_ENABLE;
97 + DSI_PORT_WRITE(DISP0_CTRL, disp0_ctrl);
98 + msleep(30);
99 +
100 + ret = vc4_dsi_transfer(dsi, msg, true);
101 + } else {
102 + DRM_ERROR("DSI transfer failed whilst in HS mode stat: 0x%08x\n",
103 + stat);
104 + }
105 + }
106 + return ret;
107 +}
108 +
109 static const struct component_ops vc4_dsi_ops;
110 static int vc4_dsi_host_attach(struct mipi_dsi_host *host,
111 struct mipi_dsi_device *device)