drm/msm/dsi: More properly handle errors in regards to dsi_mgr_bridge_power_on()
authorDouglas Anderson <dianders@chromium.org>
Tue, 31 Jan 2023 22:18:26 +0000 (14:18 -0800)
committerDmitry Baryshkov <dmitry.baryshkov@linaro.org>
Sat, 20 May 2023 23:18:32 +0000 (02:18 +0300)
In commit 7d8e9a90509f ("drm/msm/dsi: move DSI host powerup to modeset
time") the error handling with regards to dsi_mgr_bridge_power_on()
got a bit worse. Specifically if we failed to power the bridge on then
nothing would really notice. The modeset function couldn't return an
error and thus we'd blindly go forward and try to do the pre-enable.

In commit ec7981e6c614 ("drm/msm/dsi: don't powerup at modeset time
for parade-ps8640") we added a special case to move the powerup back
to pre-enable time for ps8640. When we did that, we didn't try to
recover the old/better error handling just for ps8640.

In the patch ("drm/msm/dsi: Stop unconditionally powering up DSI hosts
at modeset") we've now moved the powering up back to exclusively being
during pre-enable. That means we can add the better error handling
back in, so let's do it. To do so we'll add a new function
dsi_mgr_bridge_power_off() that's matches how errors were handled
prior to commit 7d8e9a90509f ("drm/msm/dsi: move DSI host powerup to
modeset time").

NOTE: Now that we have dsi_mgr_bridge_power_off(), it feels as if we
should be calling it in dsi_mgr_bridge_post_disable(). That would make
some sense, but doing so would change the current behavior and thus
should be a separate patch. Specifically:
* dsi_mgr_bridge_post_disable() always calls dsi_mgr_phy_disable()
  even in the slave-DSI case of bonded DSI. We'd need to add special
  handling for this if it's truly needed.
* dsi_mgr_bridge_post_disable() calls msm_dsi_phy_pll_save_state()
  midway through the poweroff.
* dsi_mgr_bridge_post_disable() has a different order of some of the
  poweroffs / IRQ disables.
For now we'll leave dsi_mgr_bridge_post_disable() alone.

Signed-off-by: Douglas Anderson <dianders@chromium.org>
Reviewed-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Patchwork: https://patchwork.freedesktop.org/patch/521059/
Link: https://lore.kernel.org/r/20230131141756.RFT.v2.3.I3c87b53c4ab61a7d5e05f601a4eb44c7e3809a01@changeid
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drivers/gpu/drm/msm/dsi/dsi_manager.c

index 2197a54..28b8012 100644 (file)
@@ -228,7 +228,7 @@ static void msm_dsi_manager_set_split_display(u8 id)
        }
 }
 
-static void dsi_mgr_bridge_power_on(struct drm_bridge *bridge)
+static int dsi_mgr_bridge_power_on(struct drm_bridge *bridge)
 {
        int id = dsi_mgr_bridge_get_id(bridge);
        struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
@@ -268,14 +268,31 @@ static void dsi_mgr_bridge_power_on(struct drm_bridge *bridge)
        if (is_bonded_dsi && msm_dsi1)
                msm_dsi_host_enable_irq(msm_dsi1->host);
 
-       return;
+       return 0;
 
 host1_on_fail:
        msm_dsi_host_power_off(host);
 host_on_fail:
        dsi_mgr_phy_disable(id);
 phy_en_fail:
-       return;
+       return ret;
+}
+
+static void dsi_mgr_bridge_power_off(struct drm_bridge *bridge)
+{
+       int id = dsi_mgr_bridge_get_id(bridge);
+       struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
+       struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1);
+       struct mipi_dsi_host *host = msm_dsi->host;
+       bool is_bonded_dsi = IS_BONDED_DSI();
+
+       msm_dsi_host_disable_irq(host);
+       if (is_bonded_dsi && msm_dsi1) {
+               msm_dsi_host_disable_irq(msm_dsi1->host);
+               msm_dsi_host_power_off(msm_dsi1->host);
+       }
+       msm_dsi_host_power_off(host);
+       dsi_mgr_phy_disable(id);
 }
 
 static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
@@ -295,7 +312,11 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
        if (is_bonded_dsi && !IS_MASTER_DSI_LINK(id))
                return;
 
-       dsi_mgr_bridge_power_on(bridge);
+       ret = dsi_mgr_bridge_power_on(bridge);
+       if (ret) {
+               dev_err(&msm_dsi->pdev->dev, "Power on failed: %d\n", ret);
+               return;
+       }
 
        ret = msm_dsi_host_enable(host);
        if (ret) {
@@ -316,8 +337,7 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
 host1_en_fail:
        msm_dsi_host_disable(host);
 host_en_fail:
-
-       return;
+       dsi_mgr_bridge_power_off(bridge);
 }
 
 void msm_dsi_manager_tpg_enable(void)