Replace the delayed work with a delay and synchronous initialization in atomic_enable. This should fix all 5 issues sashiko flagged as high priority [1].
The next bridge or panel in the chain may depend on the LVDS signal being active after atomic_enable, so arbitrarily deferring bridge initialization is not an option. [1] https://sashiko.dev/#/patchset/20260719-add-lt9211c-bridge-v6-0-e56d22152586%40oss.qualcomm.com Signed-off-by: Philipp Zabel <[email protected]> --- drivers/gpu/drm/bridge/lontium-lt9211.c | 93 ++++++++----------------- 1 file changed, 30 insertions(+), 63 deletions(-) diff --git a/drivers/gpu/drm/bridge/lontium-lt9211.c b/drivers/gpu/drm/bridge/lontium-lt9211.c index ffd0f9f08e2d..1b5cb601adde 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9211.c +++ b/drivers/gpu/drm/bridge/lontium-lt9211.c @@ -62,14 +62,7 @@ struct lt9211 { struct regulator *vccio; bool lvds_dual_link; bool lvds_dual_link_even_odd_swap; - /* LT9211C specific fields */ enum lt9211_chip_type chip_type; - struct workqueue_struct *wq; - struct delayed_work lt9211_dw; - struct drm_display_mode mode; - bool bpp24; - bool jeida; - bool de; }; static const struct regmap_range lt9211_rw_ranges[] = { @@ -154,8 +147,6 @@ static const struct regmap_config lt9211c_regmap_config = { .max_register = 0xda00, }; -static void lt9211_delayed_work_func(struct work_struct *work); - static struct lt9211 *bridge_to_lt9211(struct drm_bridge *bridge) { return container_of(bridge, struct lt9211, bridge); @@ -896,8 +887,8 @@ static int lt9211c_configure_plls(struct lt9211 *ctx, return ret; } -static int lt9211c_configure_tx(struct lt9211 *ctx, - const struct drm_display_mode *mode) +static int lt9211c_configure_tx(struct lt9211 *ctx, bool jeida, bool bpp24, + bool de, const struct drm_display_mode *mode) { const struct reg_sequence lt9211c_tx_phy_off_seq[] = { { 0x8236, 0x00 }, @@ -949,10 +940,10 @@ static int lt9211c_configure_tx(struct lt9211 *ctx, { 0x8556, 0x20 }, { 0x8568, 0x00 }, - { 0x856e, 0x10 | (ctx->de ? BIT(6) : 0) }, - { 0x856f, 0x81 | (ctx->jeida ? BIT(6) : 0) | + { 0x856e, 0x10 | (de ? BIT(6) : 0) }, + { 0x856f, 0x81 | (jeida ? BIT(6) : 0) | (ctx->lvds_dual_link ? BIT(4) : 0) | - (ctx->bpp24 ? BIT(2) : 0) }, + (bpp24 ? BIT(2) : 0) }, }; const struct reg_sequence lt9211c_tx_ssc_seq[] = { @@ -995,7 +986,7 @@ static int lt9211c_configure_tx(struct lt9211 *ctx, dev_info(ctx->dev, "dual_link=%d,even_odd_swap=%d,bpp24=%d,jeida=%d,de=%d\n", ctx->lvds_dual_link, ctx->lvds_dual_link_even_odd_swap, - ctx->bpp24, ctx->jeida, ctx->de); + bpp24, jeida, de); ret = regmap_multi_reg_write(ctx->regmap, lt9211c_tx_phy_off_seq, ARRAY_SIZE(lt9211c_tx_phy_off_seq)); @@ -1138,39 +1129,6 @@ static int lt9211c_configure_tx(struct lt9211 *ctx, return 0; } -static void lt9211_delayed_work_func(struct work_struct *work) -{ - struct delayed_work *dw = to_delayed_work(work); - struct lt9211 *ctx = container_of(dw, struct lt9211, lt9211_dw); - const struct drm_display_mode *mode = &ctx->mode; - int ret; - - if (ctx->chip_type != LT9211C) { - dev_err(ctx->dev, "LT9211: Delayed work called for non-LT9211C chip\n"); - return; - } - - ret = lt9211c_configure_rx(ctx); - if (ret) - return; - - ret = lt9211c_autodetect_rx(ctx, mode); - if (ret) - return; - - ret = lt9211c_configure_timing(ctx, mode); - if (ret) - return; - - ret = lt9211c_configure_plls(ctx, mode); - if (ret) - return; - - ret = lt9211c_configure_tx(ctx, mode); - if (ret) - return; -} - static void lt9211_atomic_enable(struct drm_bridge *bridge, struct drm_atomic_commit *state) { @@ -1240,11 +1198,30 @@ static void lt9211_atomic_enable(struct drm_bridge *bridge, if (ret) return; - if (ctx->chip_type == LT9211C && ctx->wq) { - drm_mode_copy(&ctx->mode, mode); - /* LT9211C must enable after mipi clock enable */ - queue_delayed_work(ctx->wq, &ctx->lt9211_dw, - msecs_to_jiffies(100)); + if (ctx->chip_type == LT9211C) { + msleep(100); + + ret = lt9211c_configure_rx(ctx); + if (ret) + return; + + ret = lt9211c_autodetect_rx(ctx, mode); + if (ret) + return; + + ret = lt9211c_configure_timing(ctx, mode); + if (ret) + return; + + ret = lt9211c_configure_plls(ctx, mode); + if (ret) + return; + + ret = lt9211c_configure_tx(ctx, lvds_format_jeida, lvds_format_24bpp, + bus_flags & DRM_BUS_FLAG_DE_HIGH, mode); + if (ret) + return; + dev_dbg(ctx->dev, "LT9211C enabled.\n"); return; } @@ -1501,13 +1478,6 @@ static int lt9211_probe(struct i2c_client *client) if (IS_ERR(ctx->regmap)) return PTR_ERR(ctx->regmap); - if (ctx->chip_type == LT9211C) { - ctx->wq = create_workqueue("lt9211_work"); - if (!ctx->wq) - return -ENOMEM; - INIT_DELAYED_WORK(&ctx->lt9211_dw, lt9211_delayed_work_func); - } - dev_set_drvdata(dev, ctx); i2c_set_clientdata(client, ctx); @@ -1525,9 +1495,6 @@ static void lt9211_remove(struct i2c_client *client) { struct lt9211 *ctx = i2c_get_clientdata(client); - if (ctx->wq) - destroy_workqueue(ctx->wq); - drm_bridge_remove(&ctx->bridge); } -- 2.47.3
