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

From: Tomi Valkeinen

Date: Fri Mar 27 2026 - 06:56:16 EST


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@xxxxxxxxxxxxxxxx>
---
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