diff options
| author | Aravind Venkateswaran <aravindh@codeaurora.org> | 2016-04-12 18:20:10 -0700 |
|---|---|---|
| committer | Jeevan Shriram <jshriram@codeaurora.org> | 2016-04-22 15:00:04 -0700 |
| commit | 7dcf51415ceaf2061413c08868bf998fdcfa3ee7 (patch) | |
| tree | bf5bcca27ea73f7bc9bf6ac6001786e4a9f710ab /drivers/video/fbdev | |
| parent | de2f55c7c0e8f93186a855c9acae3a1b11a15c10 (diff) | |
msm: mdss: modify DSI phy init sequence for split-DSI config
For split-DSI hardware configuration, both the DSI controller clocks are
sourced from a single PLL (clock-master). In such cases, it is important
to initialize both DSI0 PHY and DSI1 PHY prior to enabling the PLL.
This is due to the fact that for certain HW versions, PLL programming
for the clock-master may require configure some PLL registers on the
clock-slave. If the PHY init sequence for the clock-slave is called
after PLL is programmed, it could reset those PLL registers leading to
unexpected behavior. Fix this by ensuring that PHY init sequence is done
for both controllers at the same time for split display usecases.
CRs-Fixed: 1000724
Change-Id: I09fb8097d31cd0390cea5c32bb7aabceeff2c37e
Signed-off-by: Aravind Venkateswaran <aravindh@codeaurora.org>
Diffstat (limited to 'drivers/video/fbdev')
| -rw-r--r-- | drivers/video/fbdev/msm/msm_mdss_io_8974.c | 60 |
1 files changed, 58 insertions, 2 deletions
diff --git a/drivers/video/fbdev/msm/msm_mdss_io_8974.c b/drivers/video/fbdev/msm/msm_mdss_io_8974.c index 619c671650ea..805f58d65e62 100644 --- a/drivers/video/fbdev/msm/msm_mdss_io_8974.c +++ b/drivers/video/fbdev/msm/msm_mdss_io_8974.c @@ -427,7 +427,7 @@ static void mdss_dsi_ctrl_phy_reset(struct mdss_dsi_ctrl_pdata *ctrl) wmb(); /* maek sure reset cleared */ } -void mdss_dsi_phy_sw_reset(struct mdss_dsi_ctrl_pdata *ctrl) +static void mdss_dsi_phy_sw_reset_sub(struct mdss_dsi_ctrl_pdata *ctrl) { struct mdss_dsi_ctrl_pdata *sctrl = NULL; struct dsi_shared_data *sdata; @@ -484,7 +484,39 @@ void mdss_dsi_phy_sw_reset(struct mdss_dsi_ctrl_pdata *ctrl) } mutex_unlock(&sdata->phy_reg_lock); +} + +void mdss_dsi_phy_sw_reset(struct mdss_dsi_ctrl_pdata *ctrl) +{ + struct mdss_dsi_ctrl_pdata *sctrl = NULL; + struct dsi_shared_data *sdata; + + if (ctrl == NULL) { + pr_err("%s: Invalid input data\n", __func__); + return; + } + + sdata = ctrl->shared_data; + + /* + * When operating in split display mode, make sure that the PHY reset + * is only done from the clock master. This will ensure that the PLL is + * off when PHY reset is called. + */ + if (mdss_dsi_is_ctrl_clk_slave(ctrl)) + return; + + mdss_dsi_phy_sw_reset_sub(ctrl); + if (mdss_dsi_is_ctrl_clk_master(ctrl)) { + sctrl = mdss_dsi_get_ctrl_clk_slave(); + if (sctrl) + mdss_dsi_phy_sw_reset_sub(sctrl); + else + pr_warn("%s: unable to get slave ctrl\n", __func__); + } + + /* All other quirks go here */ if ((sdata->hw_rev == MDSS_DSI_HW_REV_103) && !mdss_dsi_is_hw_config_dual(sdata) && mdss_dsi_is_right_ctrl(ctrl)) { @@ -1179,12 +1211,36 @@ void mdss_dsi_phy_disable(struct mdss_dsi_ctrl_pdata *ctrl) wmb(); } -void mdss_dsi_phy_init(struct mdss_dsi_ctrl_pdata *ctrl) +static void mdss_dsi_phy_init_sub(struct mdss_dsi_ctrl_pdata *ctrl) { mdss_dsi_phy_regulator_ctrl(ctrl, true); mdss_dsi_phy_ctrl(ctrl, true); } +void mdss_dsi_phy_init(struct mdss_dsi_ctrl_pdata *ctrl) +{ + struct mdss_dsi_ctrl_pdata *sctrl = NULL; + + /* + * When operating in split display mode, make sure that both the PHY + * blocks are initialized together prior to the PLL being enabled. This + * is achieved by calling the phy_init function for the clk_slave from + * the clock_master. + */ + if (mdss_dsi_is_ctrl_clk_slave(ctrl)) + return; + + mdss_dsi_phy_init_sub(ctrl); + + if (mdss_dsi_is_ctrl_clk_master(ctrl)) { + sctrl = mdss_dsi_get_ctrl_clk_slave(); + if (sctrl) + mdss_dsi_phy_init_sub(sctrl); + else + pr_warn("%s: unable to get slave ctrl\n", __func__); + } +} + void mdss_dsi_core_clk_deinit(struct device *dev, struct dsi_shared_data *sdata) { if (sdata->mmss_misc_ahb_clk) |
