diff --git a/msm/dsi/dsi_ctrl.c b/msm/dsi/dsi_ctrl.c index 375119282e..ed7a21c2bc 100644 --- a/msm/dsi/dsi_ctrl.c +++ b/msm/dsi/dsi_ctrl.c @@ -719,6 +719,7 @@ static int dsi_ctrl_clocks_init(struct platform_device *pdev, struct dsi_link_lp_clk_info *lp_link = &ctrl->clk_info.lp_link_clks; struct dsi_link_hs_clk_info *hs_link = &ctrl->clk_info.hs_link_clks; struct dsi_clk_link_set *rcg = &ctrl->clk_info.rcg_clks; + struct dsi_clk_link_set *xo = &ctrl->clk_info.xo_clk; core->mdp_core_clk = devm_clk_get(&pdev->dev, "mdp_core_clk"); if (IS_ERR(core->mdp_core_clk)) { @@ -792,6 +793,14 @@ static int dsi_ctrl_clocks_init(struct platform_device *pdev, goto fail; } + xo->byte_clk = devm_clk_get(&pdev->dev, "xo"); + if (IS_ERR(xo->byte_clk)) { + xo->byte_clk = NULL; + DSI_CTRL_DEBUG(ctrl, "failed to get xo clk, rc=%d\n", rc); + } + + xo->pixel_clk = xo->byte_clk; + return 0; fail: dsi_ctrl_clocks_deinit(ctrl); diff --git a/msm/dsi/dsi_ctrl.h b/msm/dsi/dsi_ctrl.h index 6df95a15c4..e9d3fa5fdb 100644 --- a/msm/dsi/dsi_ctrl.h +++ b/msm/dsi/dsi_ctrl.h @@ -119,6 +119,7 @@ struct dsi_ctrl_power_info { * output of the PLL is set as parent for these root * clocks. These clocks are specific to controller * instance. + * @xo_clk: XO clocks used to park the DSI PLL before turning off. * @mux_clks: Mux clocks used for Dynamic refresh feature. * @ext_clks: External byte/pixel clocks from the MMSS block. These * clocks are set as parent to rcg clocks. @@ -131,6 +132,7 @@ struct dsi_ctrl_clk_info { struct dsi_link_hs_clk_info hs_link_clks; struct dsi_link_lp_clk_info lp_link_clks; struct dsi_clk_link_set rcg_clks; + struct dsi_clk_link_set xo_clk; /* Clocks set by DSI Manager */ struct dsi_clk_link_set mux_clks; diff --git a/msm/dsi/dsi_display.c b/msm/dsi/dsi_display.c index 7afa7407f3..3fa92cb9ef 100644 --- a/msm/dsi/dsi_display.c +++ b/msm/dsi/dsi_display.c @@ -2647,6 +2647,52 @@ error: return rc; } +static int dsi_display_set_clk_src(struct dsi_display *display, bool set_xo) +{ + int rc = 0; + int i; + struct dsi_display_ctrl *m_ctrl, *ctrl; + struct dsi_ctrl_clk_info *info; + + if (display->trusted_vm_env) + return 0; + /* + * In case of split DSI usecases, the clock for master controller should + * be enabled before the other controller. Master controller in the + * clock context refers to the controller that sources the clock. While turning off the + * clocks, the source is set to xo. + */ + m_ctrl = &display->ctrl[display->clk_master_idx]; + info = &m_ctrl->ctrl->clk_info; + + if (!set_xo) + rc = dsi_ctrl_set_clock_source(m_ctrl->ctrl, &display->clock_info.pll_clks); + else if ((info->xo_clk.byte_clk) && (info->xo_clk.pixel_clk)) + rc = dsi_ctrl_set_clock_source(m_ctrl->ctrl, &info->xo_clk); + if (rc) { + DSI_ERR("[%s] failed to set source clocks for master, rc=%d\n", display->name, rc); + return rc; + } + + /* Set source for the rest of the controllers */ + display_for_each_ctrl(i, display) { + ctrl = &display->ctrl[i]; + if (!ctrl->ctrl || (ctrl == m_ctrl)) + continue; + + info = &ctrl->ctrl->clk_info; + if (!set_xo) + rc = dsi_ctrl_set_clock_source(ctrl->ctrl, &display->clock_info.pll_clks); + else if ((info->xo_clk.byte_clk) && (info->xo_clk.pixel_clk)) + rc = dsi_ctrl_set_clock_source(ctrl->ctrl, &info->xo_clk); + if (rc) { + DSI_ERR("[%s] failed to set source clocks, rc=%d\n", display->name, rc); + return rc; + } + } + return 0; +} + int dsi_display_phy_pll_toggle(void *priv, bool prepare) { int rc = 0; @@ -2658,6 +2704,8 @@ int dsi_display_phy_pll_toggle(void *priv, bool prepare) return -EINVAL; } + rc = dsi_display_set_clk_src(display, !prepare); + m_ctrl = &display->ctrl[display->clk_master_idx]; if (!m_ctrl->phy) { DSI_ERR("[%s] PHY not found\n", display->name); @@ -2703,44 +2751,6 @@ int dsi_display_phy_configure(void *priv, bool commit) return rc; } -static int dsi_display_set_clk_src(struct dsi_display *display) -{ - int rc = 0; - int i; - struct dsi_display_ctrl *m_ctrl, *ctrl; - - /* - * In case of split DSI usecases, the clock for master controller should - * be enabled before the other controller. Master controller in the - * clock context refers to the controller that sources the clock. - */ - m_ctrl = &display->ctrl[display->clk_master_idx]; - - rc = dsi_ctrl_set_clock_source(m_ctrl->ctrl, - &display->clock_info.pll_clks); - if (rc) { - DSI_ERR("[%s] failed to set source clocks for master, rc=%d\n", - display->name, rc); - return rc; - } - - /* Turn on rest of the controllers */ - display_for_each_ctrl(i, display) { - ctrl = &display->ctrl[i]; - if (!ctrl->ctrl || (ctrl == m_ctrl)) - continue; - - rc = dsi_ctrl_set_clock_source(ctrl->ctrl, - &display->clock_info.pll_clks); - if (rc) { - DSI_ERR("[%s] failed to set source clocks, rc=%d\n", - display->name, rc); - return rc; - } - } - return 0; -} - static int dsi_display_phy_reset_config(struct dsi_display *display, bool enable) { @@ -7257,16 +7267,6 @@ static int dsi_display_pre_switch(struct dsi_display *display) goto error_ctrl_clk_off; } - if (!display->trusted_vm_env) { - rc = dsi_display_set_clk_src(display); - if (rc) { - DSI_ERR( - "[%s] failed to set DSI link clock source, rc=%d\n", - display->name, rc); - goto error_ctrl_deinit; - } - } - rc = dsi_display_clk_ctrl(display->dsi_clk_handle, DSI_LINK_CLK, DSI_CLK_ON); if (rc) { @@ -7666,16 +7666,6 @@ int dsi_display_prepare(struct dsi_display *display) } } - if (!display->trusted_vm_env) { - rc = dsi_display_set_clk_src(display); - if (rc) { - DSI_ERR( - "[%s] failed to set DSI link clock source, rc=%d\n", - display->name, rc); - goto error_phy_disable; - } - } - rc = dsi_display_ctrl_init(display); if (rc) { DSI_ERR("[%s] failed to setup DSI controller, rc=%d\n",