Hi Stephen On Fri, 6 Jan 2023 at 03:01, Stephen Boyd <swboyd@xxxxxxxxxxxx> wrote: > > The unprepare sequence has started to fail after moving to panel bridge > code in the msm drm driver (commit 007ac0262b0d ("drm/msm/dsi: switch to > DRM_PANEL_BRIDGE")). You'll see messages like this in the kernel logs: > > panel-boe-tv101wum-nl6 ae94000.dsi.0: failed to set panel off: -22 > > This is because boe_panel_enter_sleep_mode() needs an operating DSI link > to set the panel into sleep mode. Performing those writes in the > unprepare phase of bridge ops is too late, because the link has already > been torn down by the DSI controller in post_disable, i.e. the PHY has > been disabled, etc. See dsi_mgr_bridge_post_disable() for more details > on the DSI . > > Split the unprepare function into a disable part and an unprepare part. > For now, just the DSI writes to enter sleep mode are put in the disable > function. This fixes the panel off routine and keeps the panel happy. It is documented that the mipi_dsi_host_ops transfer function should be called with the host in any state [1], so the host driver is failing there. This sounds like the same issue I was addressing in adding the prepare_prev_first flag to drm_panel, and pre_enable_prev_first to drm_bridge via [2]. Defining prepare_prev_first for your panel would result in the host pre_enable being called before the panel prepare, and therefore the transfer calls from boe_panel_init_dcs_cmd boe_panel_prepare won't be relying on the DSI host powering up early. It will also call the panel unprepare before the DSI host bridge post_disable is called, and therefore the DSI host will still be powered up and the transfer won't fail. Actually I've just noted the comment at [3]. [2] is that framework fix that means that the magic workaround isn't required, but it will require this panel to opt in to the ordering change. Cheers. Dave [1] https://www.kernel.org/doc/html/latest/gpu/drm-kms-helpers.html#c.mipi_dsi_host_ops [2] https://patchwork.freedesktop.org/series/100252/ [3] https://github.com/torvalds/linux/blob/master/drivers/gpu/drm/msm/dsi/dsi_manager.c#L47 > My Wormdingler has an integrated touchscreen that stops responding to > touch if the panel is only half disabled too. This patch fixes it. And > finally, this saves power when the screen is off because without this > fix the regulators for the panel are left enabled when nothing is being > displayed on the screen. > > Fixes: 007ac0262b0d ("drm/msm/dsi: switch to DRM_PANEL_BRIDGE") > Fixes: a869b9db7adf ("drm/panel: support for boe tv101wum-nl6 wuxga dsi video mode panel") > Cc: yangcong <yangcong5@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx> > Cc: Douglas Anderson <dianders@xxxxxxxxxxxx> > Cc: Jitao Shi <jitao.shi@xxxxxxxxxxxx> > Cc: Sam Ravnborg <sam@xxxxxxxxxxxx> > Cc: Rob Clark <robdclark@xxxxxxxxxxxx> > Cc: Dmitry Baryshkov <dmitry.baryshkov@xxxxxxxxxx> > Signed-off-by: Stephen Boyd <swboyd@xxxxxxxxxxxx> > --- > drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c | 16 ++++++++++++---- > 1 file changed, 12 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c > index 857a2f0420d7..c924f1124ebc 100644 > --- a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c > +++ b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c > @@ -1193,14 +1193,11 @@ static int boe_panel_enter_sleep_mode(struct boe_panel *boe) > return 0; > } > > -static int boe_panel_unprepare(struct drm_panel *panel) > +static int boe_panel_disable(struct drm_panel *panel) > { > struct boe_panel *boe = to_boe_panel(panel); > int ret; > > - if (!boe->prepared) > - return 0; > - > ret = boe_panel_enter_sleep_mode(boe); > if (ret < 0) { > dev_err(panel->dev, "failed to set panel off: %d\n", ret); > @@ -1209,6 +1206,16 @@ static int boe_panel_unprepare(struct drm_panel *panel) > > msleep(150); > > + return 0; > +} > + > +static int boe_panel_unprepare(struct drm_panel *panel) > +{ > + struct boe_panel *boe = to_boe_panel(panel); > + > + if (!boe->prepared) > + return 0; > + > if (boe->desc->discharge_on_disable) { > regulator_disable(boe->avee); > regulator_disable(boe->avdd); > @@ -1528,6 +1535,7 @@ static enum drm_panel_orientation boe_panel_get_orientation(struct drm_panel *pa > } > > static const struct drm_panel_funcs boe_panel_funcs = { > + .disable = boe_panel_disable, > .unprepare = boe_panel_unprepare, > .prepare = boe_panel_prepare, > .enable = boe_panel_enable, > > base-commit: 1b929c02afd37871d5afb9d498426f83432e71c2 > -- > https://chromeos.dev >