summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAravind Venkateswaran <aravindh@codeaurora.org>2014-03-12 14:49:32 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 20:28:17 -0700
commit9344504e2e6bfdc324e5b3738d133ecd7dec35ea (patch)
tree55e69f567b432a8016f7fd1ddce77ebcbc0927a2
parentec96ea593c2170207e6c64a02c03afd5890dee64 (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.h5
-rw-r--r--drivers/video/fbdev/msm/msm_mdss_io_8974.c140
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)