Re: [PATCH 1/2] drm/msm/dsi: move DSI host powerup to modeset time

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 18/01/2022 23:03, Dmitry Baryshkov wrote:
On Tue, 18 Jan 2022 at 22:29, Abhinav Kumar <quic_abhinavk@xxxxxxxxxxx> wrote:



On 12/7/2021 2:29 PM, Dmitry Baryshkov wrote:
The DSI subsystem does not fully fall into the pre-enable/enable system
of callbacks, since typically DSI device bridge drivers expect to be
able to communicate with DSI devices at the pre-enable() callback. The
reason is that for some DSI hosts enabling the video stream would
prevent other drivers from sending DSI commands. For example see the
panel-bridge driver, which does drm_panel_prepare() from the
pre_enable() callback (which would be called before our pre_enable()
callback, resulting in panel preparation failures as the link is not yet
ready).

Therewere several attempts to solve this issue, but currently the best
approach is to power up the DSI link from the mode_set() callback,
allowing next bridge/panel to use DSI transfers in the pre_enable()
time. Follow this approach.

Change looks okay. As per the programming guideline, we should set the
VIDEO_MODE_EN register in the DSI controller followed by enabling the
timing engine which will still happen even now because we will do it in
modeset instead of the pre_enable().
But, this can potentially increase the delay between VIDEO_MODE_EN
and TIMING_ENGINE_EN. I dont see anything in the programming guide
against this but since this is a change from the original flow, I would
like to do one test before acking this. Can you please try adding a huge
delay like 200-300ms between VIDEO_MODE_EN and timing engine enable to
make sure there are no issues? You can do that here:


Fine, I'll do the test as the time permits.

I did the tests, the display pipeline works as expected.

Let's get this in, it allows using other DSI-controlled bridges.



int msm_dsi_host_enable(struct mipi_dsi_host *host)
{
      struct msm_dsi_host *msm_host = to_msm_dsi_host(host);

      dsi_op_mode_config(msm_host,
          !!(msm_host->mode_flags & MIPI_DSI_MODE_VIDEO), true);

      msleep(300);
}


Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@xxxxxxxxxx>
---
   drivers/gpu/drm/msm/dsi/dsi_manager.c | 43 +++++++++++++++++++--------
   1 file changed, 31 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index 681ca74fe410..497719efb9e9 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -336,13 +336,12 @@ dsi_mgr_connector_best_encoder(struct drm_connector *connector)
       return msm_dsi_get_encoder(msm_dsi);
   }

-static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
+static void 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);
       struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1);
       struct mipi_dsi_host *host = msm_dsi->host;
-     struct drm_panel *panel = msm_dsi->panel;
       struct msm_dsi_phy_shared_timings phy_shared_timings[DSI_MAX];
       bool is_bonded_dsi = IS_BONDED_DSI();
       int ret;
@@ -383,6 +382,34 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
       if (is_bonded_dsi && msm_dsi1)
               msm_dsi_host_enable_irq(msm_dsi1->host);

+     return;
+
+host1_on_fail:
+     msm_dsi_host_power_off(host);
+host_on_fail:
+     dsi_mgr_phy_disable(id);
+phy_en_fail:
+     return;
+}
+
+static void dsi_mgr_bridge_pre_enable(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;
+     struct drm_panel *panel = msm_dsi->panel;
+     bool is_bonded_dsi = IS_BONDED_DSI();
+     int ret;
+
+     DBG("id=%d", id);
+     if (!msm_dsi_device_connected(msm_dsi))
+             return;
+
+     /* Do nothing with the host if it is slave-DSI in case of bonded DSI */
+     if (is_bonded_dsi && !IS_MASTER_DSI_LINK(id))
+             return;
+
       /* Always call panel functions once, because even for dual panels,
        * there is only one drm_panel instance.
        */
@@ -417,17 +444,7 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
       if (panel)
               drm_panel_unprepare(panel);
   panel_prep_fail:
-     msm_dsi_host_disable_irq(host);
-     if (is_bonded_dsi && msm_dsi1)
-             msm_dsi_host_disable_irq(msm_dsi1->host);

-     if (is_bonded_dsi && msm_dsi1)
-             msm_dsi_host_power_off(msm_dsi1->host);
-host1_on_fail:
-     msm_dsi_host_power_off(host);
-host_on_fail:
-     dsi_mgr_phy_disable(id);
-phy_en_fail:
       return;
   }

@@ -573,6 +590,8 @@ static void dsi_mgr_bridge_mode_set(struct drm_bridge *bridge,
       msm_dsi_host_set_display_mode(host, adjusted_mode);
       if (is_bonded_dsi && other_dsi)
               msm_dsi_host_set_display_mode(other_dsi->host, adjusted_mode);
+
+     dsi_mgr_bridge_power_on(bridge);
   }

   static const struct drm_connector_funcs dsi_mgr_connector_funcs = {





--
With best wishes
Dmitry



[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [Linux for Sparc]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux