diff options
author | Archit Taneja <architt@codeaurora.org> | 2015-07-29 12:14:12 -0400 |
---|---|---|
committer | Rob Clark <robdclark@gmail.com> | 2017-02-06 11:28:45 -0500 |
commit | 34d9545b9f769c6553e31a6820c9cb51f5e93099 (patch) | |
tree | 7f6bfe43053230360044c2a69119713a3f058fa8 /drivers | |
parent | 57bf433893370c069a0c34842f35a3bb8aa130fc (diff) |
drm/msm/dsi: Reset both PHYs before clock operation for dual DSI
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/msm/dsi/dsi.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/dsi/dsi_host.c | 25 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/dsi/dsi_manager.c | 32 |
3 files changed, 43 insertions, 15 deletions
diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index d516fe296b78..9407a682d045 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -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); diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 8e75e001ad02..1d2c9b46737d 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -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, diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index c040830f5900..cb67e78d775b 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -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); |