drm/msm/dsi: Reset both PHYs before clock operation for dual DSI
authorArchit Taneja <architt@codeaurora.org>
Wed, 29 Jul 2015 16:14:12 +0000 (12:14 -0400)
committerRob Clark <robdclark@gmail.com>
Mon, 6 Feb 2017 16:28:45 +0000 (11:28 -0500)
In case of dual DSI, some registers in PHY1 have been programmed
during PLL0 clock's set_rate. The PHY1 reset called by host1 later
will silently reset those PHY1 registers. This change is to reset
and enable both PHYs before any PLL clock operation.

[Originally worked on by Hai Li <hali@codeaurora.org>. Fixed up
by Archit Taneja <architt@codeaurora.org>]

Signed-off-by: Archit Taneja <architt@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
drivers/gpu/drm/msm/dsi/dsi.h
drivers/gpu/drm/msm/dsi/dsi_host.c
drivers/gpu/drm/msm/dsi/dsi_manager.c

index d516fe296b7861e743c5b80db25aa543212b2367..9407a682d04540d23bcb4091bb3e1410d5bf3a87 100644 (file)
@@ -166,6 +166,7 @@ int msm_dsi_host_register(struct mipi_dsi_host *host, bool check_defer);
 void msm_dsi_host_unregister(struct mipi_dsi_host *host);
 int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host,
                        struct msm_dsi_pll *src_pll);
+void msm_dsi_host_reset_phy(struct mipi_dsi_host *host);
 void msm_dsi_host_destroy(struct mipi_dsi_host *host);
 int msm_dsi_host_modeset_init(struct mipi_dsi_host *host,
                                        struct drm_device *dev);
index 8e75e001ad02b21e99d27ae7f00bfb07321221a3..1d2c9b46737d53a861acb57cb5b978f809e161d1 100644 (file)
@@ -691,17 +691,6 @@ static int dsi_calc_clk_rate(struct msm_dsi_host *msm_host)
        return 0;
 }
 
-static void dsi_phy_sw_reset(struct msm_dsi_host *msm_host)
-{
-       DBG("");
-       dsi_write(msm_host, REG_DSI_PHY_RESET, DSI_PHY_RESET_RESET);
-       /* Make sure fully reset */
-       wmb();
-       udelay(1000);
-       dsi_write(msm_host, REG_DSI_PHY_RESET, 0);
-       udelay(100);
-}
-
 static void dsi_intr_ctrl(struct msm_dsi_host *msm_host, u32 mask, int enable)
 {
        u32 intr;
@@ -2126,6 +2115,19 @@ exit:
        return ret;
 }
 
+void msm_dsi_host_reset_phy(struct mipi_dsi_host *host)
+{
+       struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
+
+       DBG("");
+       dsi_write(msm_host, REG_DSI_PHY_RESET, DSI_PHY_RESET_RESET);
+       /* Make sure fully reset */
+       wmb();
+       udelay(1000);
+       dsi_write(msm_host, REG_DSI_PHY_RESET, 0);
+       udelay(100);
+}
+
 int msm_dsi_host_enable(struct mipi_dsi_host *host)
 {
        struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
@@ -2206,7 +2208,6 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host)
                goto fail_disable_reg;
        }
 
-       dsi_phy_sw_reset(msm_host);
        ret = msm_dsi_manager_phy_enable(msm_host->id,
                                        msm_host->byte_clk_rate * 8,
                                        msm_host->esc_clk_rate,
index c040830f59001007e9627c412bc15ebcdb652441..cb67e78d775b487a856af05f15dfb4a0b30d9c97 100644 (file)
@@ -669,13 +669,39 @@ int msm_dsi_manager_phy_enable(int id,
                struct msm_dsi_phy_shared_timings *shared_timings)
 {
        struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
+       struct msm_dsi *mdsi = dsi_mgr_get_dsi(DSI_CLOCK_MASTER);
+       struct msm_dsi *sdsi = dsi_mgr_get_dsi(DSI_CLOCK_SLAVE);
        struct msm_dsi_phy *phy = msm_dsi->phy;
        int src_pll_id = IS_DUAL_DSI() ? DSI_CLOCK_MASTER : id;
        int ret;
 
-       ret = msm_dsi_phy_enable(phy, src_pll_id, bit_rate, esc_rate);
-       if (ret)
-               return ret;
+       /* In case of dual DSI, some registers in PHY1 have been programmed
+        * during PLL0 clock's set_rate. The PHY1 reset called by host1 here
+        * will silently reset those PHY1 registers. Therefore we need to reset
+        * and enable both PHYs before any PLL clock operation.
+        */
+       if (IS_DUAL_DSI() && mdsi && sdsi) {
+               if (!mdsi->phy_enabled && !sdsi->phy_enabled) {
+                       msm_dsi_host_reset_phy(mdsi->host);
+                       msm_dsi_host_reset_phy(sdsi->host);
+                       ret = msm_dsi_phy_enable(mdsi->phy, src_pll_id,
+                                                bit_rate, esc_rate);
+                       if (ret)
+                               return ret;
+                       ret = msm_dsi_phy_enable(sdsi->phy, src_pll_id,
+                                                bit_rate, esc_rate);
+                       if (ret) {
+                               msm_dsi_phy_disable(mdsi->phy);
+                               return ret;
+                       }
+               }
+       } else {
+               msm_dsi_host_reset_phy(msm_dsi->host);
+               ret = msm_dsi_phy_enable(msm_dsi->phy, src_pll_id, bit_rate,
+                                                               esc_rate);
+               if (ret)
+                       return ret;
+       }
 
        msm_dsi->phy_enabled = true;
        msm_dsi_phy_get_shared_timings(phy, shared_timings);