Locking PLL requires the DSI HS clock to be running, which it might not be
in probe(), but should be in atomic_enable().

This resolves issues like this:

sn65dsi83 1-002c: failed to lock PLL, ret=-110
sn65dsi83 1-002c: Unexpected link status 0x01
sn65dsi83 1-002c: Unexpected link status 0x01
sn65dsi83 1-002c: reset the pipe

as seen with nwl-dsi bridge and others.

This is the same issue as addressed in the patch by Gary Bisson [1],
but changing the ti-sn65dsi83 driver instead, so we don't have to change
all other drivers that could potentially be used with this chip.

[1] https://lore.kernel.org/all/[email protected]/

Signed-off-by: Esben Haabendal <[email protected]>
---
 drivers/gpu/drm/bridge/ti-sn65dsi83.c | 30 ++++++++++++++----------------
 1 file changed, 14 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi83.c 
b/drivers/gpu/drm/bridge/ti-sn65dsi83.c
index 32e9eadd7452..e87bed3a6640 100644
--- a/drivers/gpu/drm/bridge/ti-sn65dsi83.c
+++ b/drivers/gpu/drm/bridge/ti-sn65dsi83.c
@@ -532,7 +532,6 @@ static void sn65dsi83_atomic_pre_enable(struct drm_bridge 
*bridge,
        bool test_pattern = sn65dsi83_test_pattern;
        bool lvds_format_24bpp;
        bool lvds_format_jeida;
-       unsigned int pval;
        __le16 le16val;
        u16 val;
        int ret;
@@ -682,26 +681,12 @@ static void sn65dsi83_atomic_pre_enable(struct drm_bridge 
*bridge,
        regmap_write(ctx->regmap, REG_VID_CHA_TEST_PATTERN,
                     test_pattern ? REG_VID_CHA_TEST_PATTERN_EN : 0);
 
-       /* Enable PLL */
-       regmap_write(ctx->regmap, REG_RC_PLL_EN, REG_RC_PLL_EN_PLL_EN);
-       usleep_range(3000, 4000);
-       ret = regmap_read_poll_timeout(ctx->regmap, REG_RC_LVDS_PLL, pval,
-                                      pval & REG_RC_LVDS_PLL_PLL_EN_STAT,
-                                      1000, 100000);
-       if (ret) {
-               dev_err(ctx->dev, "failed to lock PLL, ret=%i\n", ret);
-               /* On failure, disable PLL again and exit. */
-               regmap_write(ctx->regmap, REG_RC_PLL_EN, 0x00);
-               goto err_add_action;
-       }
-
        /* Trigger reset after CSR register update. */
        regmap_write(ctx->regmap, REG_RC_RESET, REG_RC_RESET_SOFT_RESET);
 
        /* Wait for 10ms after soft reset as specified in datasheet */
        usleep_range(10000, 12000);
 
-err_add_action:
        devm_add_action(ctx->dev, sn65dsi83_release_resources, ctx);
 err_exit:
        drm_bridge_exit(idx);
@@ -712,11 +697,24 @@ static void sn65dsi83_atomic_enable(struct drm_bridge 
*bridge,
 {
        struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);
        unsigned int pval;
-       int idx;
+       int idx, ret;
 
        if (!drm_bridge_enter(bridge, &idx))
                return;
 
+       /* Enable PLL */
+       regmap_write(ctx->regmap, REG_RC_PLL_EN, REG_RC_PLL_EN_PLL_EN);
+       usleep_range(3000, 4000);
+       ret = regmap_read_poll_timeout(ctx->regmap, REG_RC_LVDS_PLL, pval,
+                                      pval & REG_RC_LVDS_PLL_PLL_EN_STAT,
+                                      1000, 100000);
+       if (ret) {
+               dev_err(ctx->dev, "failed to lock PLL, ret=%i\n", ret);
+               /* On failure, disable PLL again and exit. */
+               regmap_write(ctx->regmap, REG_RC_PLL_EN, 0x00);
+               return;
+       }
+
        /* Clear all errors that got asserted during initialization. */
        regmap_read(ctx->regmap, REG_IRQ_STAT, &pval);
        regmap_write(ctx->regmap, REG_IRQ_STAT, pval);

-- 
2.55.0

Reply via email to