diff options
| author | Aravind Venkateswaran <aravindh@codeaurora.org> | 2014-03-12 14:49:32 -0700 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 20:28:17 -0700 |
| commit | 9344504e2e6bfdc324e5b3738d133ecd7dec35ea (patch) | |
| tree | 55e69f567b432a8016f7fd1ddce77ebcbc0927a2 | |
| parent | ec96ea593c2170207e6c64a02c03afd5890dee64 (diff) | |
msm: mdss: cleanup dsi clock handling
Currently the DSI driver uses a two level reference counting for
the clocks used by the driver so as to ensure that the clocks are
correctly configured for dual-dsi use cases. However, this is not
necessary as the same can be achieved by using a single reference
count. Clean up the code to remove the sub-level ref counts and
add necessary error handling.
Change-Id: I6f1c1bfe83322dc0e1da3d757b6ca88cd629663e
Signed-off-by: Aravind Venkateswaran <aravindh@codeaurora.org>
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dsi.h | 5 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/msm_mdss_io_8974.c | 140 |
2 files changed, 89 insertions, 56 deletions
diff --git a/drivers/video/fbdev/msm/mdss_dsi.h b/drivers/video/fbdev/msm/mdss_dsi.h index 373e01e9a513..9838623baa2a 100644 --- a/drivers/video/fbdev/msm/mdss_dsi.h +++ b/drivers/video/fbdev/msm/mdss_dsi.h @@ -148,7 +148,6 @@ enum dsi_lane_map_type { #define DSI_CMD_TERM BIT(0) extern struct device dsi_dev; -extern int mdss_dsi_clk_on; extern u32 dsi_irq; extern struct mdss_dsi_ctrl_pdata *ctrl_list[]; @@ -249,7 +248,6 @@ struct mdss_dsi_ctrl_pdata { struct dss_io_data phy_io; int reg_size; u32 clk_cnt; - int clk_cnt_sub; u32 flags; struct clk *mdp_core_clk; struct clk *ahb_clk; @@ -261,7 +259,6 @@ struct mdss_dsi_ctrl_pdata { u8 ctrl_state; int panel_mode; int irq_cnt; - int mdss_dsi_clk_on; int rst_gpio; int disp_en_gpio; int disp_te_gpio; @@ -323,7 +320,7 @@ void mdp4_dsi_cmd_trigger(void); void mdss_dsi_cmd_mdp_start(struct mdss_dsi_ctrl_pdata *ctrl); void mdss_dsi_cmd_bta_sw_trigger(struct mdss_panel_data *pdata); void mdss_dsi_ack_err_status(struct mdss_dsi_ctrl_pdata *ctrl); -void mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int enable); +int mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int enable); int mdss_dsi_link_clk_start(struct mdss_dsi_ctrl_pdata *ctrl); void mdss_dsi_link_clk_stop(struct mdss_dsi_ctrl_pdata *ctrl); int mdss_dsi_bus_clk_start(struct mdss_dsi_ctrl_pdata *ctrl); diff --git a/drivers/video/fbdev/msm/msm_mdss_io_8974.c b/drivers/video/fbdev/msm/msm_mdss_io_8974.c index a349d69c741e..1d1c3036463c 100644 --- a/drivers/video/fbdev/msm/msm_mdss_io_8974.c +++ b/drivers/video/fbdev/msm/msm_mdss_io_8974.c @@ -408,11 +408,6 @@ static int mdss_dsi_link_clk_enable(struct mdss_dsi_ctrl_pdata *ctrl_pdata) pr_debug("%s: ndx=%d\n", __func__, ctrl_pdata->ndx); - if (ctrl_pdata->mdss_dsi_clk_on) { - pr_info("%s: mdss_dsi_clks already ON\n", __func__); - return 0; - } - rc = clk_enable(ctrl_pdata->esc_clk); if (rc) { pr_err("%s: Failed to enable dsi esc clk\n", __func__); @@ -431,8 +426,6 @@ static int mdss_dsi_link_clk_enable(struct mdss_dsi_ctrl_pdata *ctrl_pdata) goto pixel_clk_err; } - ctrl_pdata->mdss_dsi_clk_on = 1; - return rc; pixel_clk_err: @@ -452,16 +445,9 @@ static void mdss_dsi_link_clk_disable(struct mdss_dsi_ctrl_pdata *ctrl_pdata) pr_debug("%s: ndx=%d\n", __func__, ctrl_pdata->ndx); - if (ctrl_pdata->mdss_dsi_clk_on == 0) { - pr_info("%s: mdss_dsi_clks already OFF\n", __func__); - return; - } - clk_disable(ctrl_pdata->esc_clk); clk_disable(ctrl_pdata->pixel_clk); clk_disable(ctrl_pdata->byte_clk); - - ctrl_pdata->mdss_dsi_clk_on = 0; } int mdss_dsi_link_clk_start(struct mdss_dsi_ctrl_pdata *ctrl) @@ -500,35 +486,52 @@ void mdss_dsi_link_clk_stop(struct mdss_dsi_ctrl_pdata *ctrl) mdss_dsi_link_clk_unprepare(ctrl); } -static void mdss_dsi_clk_ctrl_sub(struct mdss_dsi_ctrl_pdata *ctrl, int enable) +static int __mdss_dsi_update_clk_cnt(u32 *clk_cnt, int enable) { int changed = 0; if (enable) { - if (ctrl->clk_cnt_sub == 0) + if (*clk_cnt == 0) changed++; - ctrl->clk_cnt_sub++; + (*clk_cnt)++; } else { - if (ctrl->clk_cnt_sub) { - ctrl->clk_cnt_sub--; - if (ctrl->clk_cnt_sub == 0) + if (*clk_cnt != 0) { + (*clk_cnt)--; + if (*clk_cnt == 0) changed++; } else { - pr_debug("%s: Can not be turned off\n", __func__); + pr_debug("%s: clk cnt already zero\n", __func__); } } - pr_debug("%s: ndx=%d clk_cnt_sub=%d changed=%d enable=%d\n", - __func__, ctrl->ndx, ctrl->clk_cnt_sub, changed, enable); - if (changed) { - if (enable) { - if (mdss_dsi_bus_clk_start(ctrl) == 0) - mdss_dsi_link_clk_start(ctrl); - } else { - mdss_dsi_link_clk_stop(ctrl); + return changed; +} + +static int mdss_dsi_clk_ctrl_sub(struct mdss_dsi_ctrl_pdata *ctrl, int enable) +{ + int rc = 0; + + pr_debug("%s: ndx=%d enable=%d\n", __func__, ctrl->ndx, enable); + + if (enable) { + rc = mdss_dsi_bus_clk_start(ctrl); + if (rc) { + pr_err("Failed to start bus clocks. rc=%d\n", rc); + goto error; + } + rc = mdss_dsi_link_clk_start(ctrl); + if (rc) { + pr_err("Failed to start link clocks. rc=%d\n", rc); mdss_dsi_bus_clk_stop(ctrl); + goto error; } + } else { + mdss_dsi_link_clk_stop(ctrl); + mdss_dsi_bus_clk_stop(ctrl); } + +error: + return rc; } static DEFINE_MUTEX(dsi_clk_lock); /* per system */ @@ -543,11 +546,17 @@ bool __mdss_dsi_clk_enabled(struct mdss_dsi_ctrl_pdata *ctrl) return enabled; } -void mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int enable) +int mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int enable) { - int changed = 0; + int rc = 0; + int changed = 0, m_changed = 0; struct mdss_dsi_ctrl_pdata *mctrl = NULL; + if (!ctrl) { + pr_err("%s: Invalid arg\n", __func__); + return -EINVAL; + } + /* * In broadcast mode, we need to enable clocks for the * master controller as well when enabling clocks for the @@ -559,34 +568,61 @@ void mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int enable) pr_warn("%s: Unable to get master control\n", __func__); } - mutex_lock(&dsi_clk_lock); - if (enable) { - if (ctrl->clk_cnt == 0) - changed++; - ctrl->clk_cnt++; - } else { - if (ctrl->clk_cnt) { - ctrl->clk_cnt--; - if (ctrl->clk_cnt == 0) - changed++; - } else { - pr_debug("%s: Can not be turned off\n", __func__); - } - } + pr_debug("%s++: ndx=%d clk_cnt=%d mctrl=%s m_clk_cnt=%d\n, enable=%d\n", + __func__, ctrl->ndx, ctrl->clk_cnt, + mctrl ? "yes" : "no", mctrl ? mctrl->clk_cnt : -1, enable); - pr_debug("%s: ndx=%d clk_cnt=%d changed=%d enable=%d\n", - __func__, ctrl->ndx, ctrl->clk_cnt, changed, enable); + mutex_lock(&dsi_clk_lock); + changed = __mdss_dsi_update_clk_cnt(&ctrl->clk_cnt, enable); + if (changed && mctrl) + m_changed = __mdss_dsi_update_clk_cnt(&mctrl->clk_cnt, enable); if (changed) { - if (enable && mctrl) - mdss_dsi_clk_ctrl_sub(mctrl, enable); + if (enable && m_changed) { + rc = mdss_dsi_clk_ctrl_sub(mctrl, enable); + if (rc) { + pr_err("Failed to start mctrl clocks. rc=%d\n", + rc); + goto error_mctrl_start; + } + } - mdss_dsi_clk_ctrl_sub(ctrl, enable); + rc = mdss_dsi_clk_ctrl_sub(ctrl, enable); + if (rc) { + pr_err("Failed to %s ctrl clocks. rc=%d\n", + (enable ? "start" : "stop"), rc); + goto error_ctrl; + } - if (!enable && mctrl) - mdss_dsi_clk_ctrl_sub(mctrl, enable); + if (!enable && m_changed) { + rc = mdss_dsi_clk_ctrl_sub(mctrl, enable); + if (rc) { + pr_err("Failed to stop mctrl clocks. rc=%d\n", + rc); + goto error_mctrl_stop; + } + } } + + goto no_error; + +error_mctrl_stop: + mdss_dsi_clk_ctrl_sub(ctrl, enable ? 0 : 1); +error_ctrl: + mdss_dsi_clk_ctrl_sub(mctrl, 0); +error_mctrl_start: + __mdss_dsi_update_clk_cnt(&mctrl->clk_cnt, enable ? 0 : 1); + __mdss_dsi_update_clk_cnt(&ctrl->clk_cnt, enable ? 0 : 1); + +no_error: mutex_unlock(&dsi_clk_lock); + pr_debug("%s--: ndx=%d clk_cnt=%d changed=%d mctrl=%s m_clk_cnt=%d\n", + __func__, ctrl->ndx, ctrl->clk_cnt, changed, + mctrl ? "yes" : "no", mctrl ? mctrl->clk_cnt : -1); + pr_debug("%s--: m_changed=%d enable=%d\n", __func__, + mctrl ? m_changed : -1, enable); + + return rc; } void mdss_dsi_phy_sw_reset(unsigned char *ctrl_base) |
