[PATCH 2/3] drm/bridge: cdns-dsi: Fix stop-state at enable time

Tomi Valkeinen posted 3 patches 6 days, 6 hours ago
[PATCH 2/3] drm/bridge: cdns-dsi: Fix stop-state at enable time
Posted by Tomi Valkeinen 6 days, 6 hours ago
When using continuous clock, the cdns dsi doesn't keep the clock lanes in
LP-11 long enough to signal a stop state, although the data lanes are
kept high long enough. The data lanes most likely stay in LP-11 until
there is data to send, so the LP-11 duration is not defined.

While some DSI peripherals seem to work fine without correct stop-state
on the clock lane, at least Xilinx D-PHY RX fails to initialize if it
does not observe correct stop-state.

Add explicit stop-state handling to the driver. This is not described in
the documentation, but observing the clk and data lanes with an
oscilloscope, the solution in this patch seems to work:

Set the FORCE_STOP flags for clock and data lanes before starting the
D-PHY power up and init sequence, and drop the FORCE_STOP flags after
the init has been done, and 100 us has passed.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
 drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index 2c86bf346fea..439d56c69be9 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -635,9 +635,16 @@ static void cdns_dsi_hs_init(struct cdns_dsi *dsi)
 {
 	struct cdns_dsi_output *output = &dsi->output;
 	u32 status;
+	u32 val;
 
 	if (dsi->phy_initialized)
 		return;
+
+	/* Set force stop state on all lanes */
+	val = readl(dsi->regs + MCTL_MAIN_EN);
+	val |= DATA_FORCE_STOP | CLK_FORCE_STOP;
+	writel(val, dsi->regs + MCTL_MAIN_EN);
+
 	/*
 	 * Power all internal DPHY blocks down and maintain their reset line
 	 * asserted before changing the DPHY config.
@@ -661,6 +668,13 @@ static void cdns_dsi_hs_init(struct cdns_dsi *dsi)
 	writel(DPHY_CMN_PSO | DPHY_ALL_D_PDN | DPHY_C_PDN | DPHY_CMN_PDN |
 	       DPHY_D_RSTB(output->dev->lanes) | DPHY_C_RSTB,
 	       dsi->regs + MCTL_DPHY_CFG0);
+
+	/* Keep stop state for at least 100 us */
+	usleep_range(100, 200);
+
+	val &= ~(DATA_FORCE_STOP | CLK_FORCE_STOP);
+	writel(val, dsi->regs + MCTL_MAIN_EN);
+
 	dsi->phy_initialized = true;
 }
 

-- 
2.43.0