@@ -166,6 +166,7 @@ struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host,
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);
@@ -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 @@ int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host,
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,
@@ -660,13 +660,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);
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> --- drivers/gpu/drm/msm/dsi/dsi.h | 1 + drivers/gpu/drm/msm/dsi/dsi_host.c | 25 +++++++++++++------------ drivers/gpu/drm/msm/dsi/dsi_manager.c | 32 +++++++++++++++++++++++++++++--- 3 files changed, 43 insertions(+), 15 deletions(-)