summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/video/fbdev/msm/dsi_host_v2.c62
1 files changed, 52 insertions, 10 deletions
diff --git a/drivers/video/fbdev/msm/dsi_host_v2.c b/drivers/video/fbdev/msm/dsi_host_v2.c
index d6c3ee963c87..67bfdd96161e 100644
--- a/drivers/video/fbdev/msm/dsi_host_v2.c
+++ b/drivers/video/fbdev/msm/dsi_host_v2.c
@@ -41,11 +41,14 @@ struct dsi_host_v2_private {
unsigned char *dsi_base;
size_t dsi_reg_size;
struct device dis_dev;
+ int clk_count;
+ int dsi_on;
void (*debug_enable_clk)(int on);
};
static struct dsi_host_v2_private *dsi_host_private;
+static int msm_dsi_clk_ctrl(struct mdss_panel_data *pdata, int enable);
int msm_dsi_init(void)
{
@@ -883,6 +886,15 @@ void msm_dsi_cmdlist_rx(struct mdss_dsi_ctrl_pdata *ctrl,
void msm_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp)
{
struct dcs_cmd_req *req;
+ int dsi_on;
+
+ mutex_lock(&ctrl->mutex);
+ dsi_on = dsi_host_private->dsi_on;
+ mutex_unlock(&ctrl->mutex);
+ if (!dsi_on) {
+ pr_err("try to send DSI commands while dsi is off\n");
+ return;
+ }
mutex_lock(&ctrl->cmd_mutex);
req = mdss_dsi_cmdlist_get(ctrl);
@@ -892,6 +904,7 @@ void msm_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp)
return;
}
+ msm_dsi_clk_ctrl(&ctrl->panel_data, 1);
dsi_set_tx_power_mode(0);
if (req->flags & CMD_REQ_RX)
@@ -900,6 +913,7 @@ void msm_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp)
msm_dsi_cmdlist_tx(ctrl, req);
dsi_set_tx_power_mode(1);
+ msm_dsi_clk_ctrl(&ctrl->panel_data, 0);
mutex_unlock(&ctrl->cmd_mutex);
}
@@ -973,11 +987,14 @@ static int msm_dsi_on(struct mdss_panel_data *pdata)
ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
panel_data);
+ mutex_lock(&ctrl_pdata->mutex);
+
ret = msm_dss_enable_vreg(
ctrl_pdata->power_data.vreg_config,
ctrl_pdata->power_data.num_vreg, 1);
if (ret) {
pr_err("%s: DSI power on failed\n", __func__);
+ mutex_unlock(&ctrl_pdata->mutex);
return ret;
}
@@ -1065,6 +1082,9 @@ static int msm_dsi_on(struct mdss_panel_data *pdata)
msm_dsi_op_mode_config(mipi->mode, pdata);
msm_dsi_set_irq(ctrl_pdata, DSI_INTR_ERROR_MASK);
+ dsi_host_private->clk_count = 1;
+ dsi_host_private->dsi_on = 1;
+ mutex_unlock(&ctrl_pdata->mutex);
return ret;
}
@@ -1084,6 +1104,7 @@ static int msm_dsi_off(struct mdss_panel_data *pdata)
panel_data);
pr_debug("msm_dsi_off\n");
+ mutex_lock(&ctrl_pdata->mutex);
msm_dsi_clear_irq(ctrl_pdata, ctrl_pdata->dsi_irq_mask);
msm_dsi_controller_cfg(0);
msm_dsi_clk_set_rate(DSI_ESC_CLK_RATE, 0, 0, 0);
@@ -1097,8 +1118,11 @@ static int msm_dsi_off(struct mdss_panel_data *pdata)
ctrl_pdata->power_data.num_vreg, 0);
if (ret) {
pr_err("%s: Panel power off failed\n", __func__);
- return ret;
}
+ dsi_host_private->clk_count = 0;
+ dsi_host_private->dsi_on = 0;
+
+ mutex_unlock(&ctrl_pdata->mutex);
return ret;
}
@@ -1122,11 +1146,13 @@ static int msm_dsi_cont_on(struct mdss_panel_data *pdata)
panel_data);
pinfo = &pdata->panel_info;
+ mutex_lock(&ctrl_pdata->mutex);
ret = msm_dss_enable_vreg(
ctrl_pdata->power_data.vreg_config,
ctrl_pdata->power_data.num_vreg, 1);
if (ret) {
pr_err("%s: DSI power on failed\n", __func__);
+ mutex_unlock(&ctrl_pdata->mutex);
return ret;
}
@@ -1134,6 +1160,9 @@ static int msm_dsi_cont_on(struct mdss_panel_data *pdata)
msm_dsi_prepare_clocks();
msm_dsi_clk_enable();
msm_dsi_set_irq(ctrl_pdata, DSI_INTR_ERROR_MASK);
+ dsi_host_private->clk_count = 1;
+ dsi_host_private->dsi_on = 1;
+ mutex_unlock(&ctrl_pdata->mutex);
return 0;
}
@@ -1265,21 +1294,34 @@ static struct device_node *dsi_find_panel_of_node(
static int msm_dsi_clk_ctrl(struct mdss_panel_data *pdata, int enable)
{
u32 bitclk_rate = 0, byteclk_rate = 0, pclk_rate = 0, dsiclk_rate = 0;
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
pr_debug("%s:\n", __func__);
+ ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+ panel_data);
+
+ mutex_lock(&ctrl_pdata->mutex);
+
if (enable) {
- msm_dsi_ahb_ctrl(1);
- msm_dsi_cal_clk_rate(pdata, &bitclk_rate, &dsiclk_rate,
- &byteclk_rate, &pclk_rate);
- msm_dsi_clk_set_rate(DSI_ESC_CLK_RATE, dsiclk_rate,
- byteclk_rate, pclk_rate);
- msm_dsi_clk_enable();
+ dsi_host_private->clk_count++;
+ if (dsi_host_private->clk_count == 1) {
+ msm_dsi_ahb_ctrl(1);
+ msm_dsi_cal_clk_rate(pdata, &bitclk_rate, &dsiclk_rate,
+ &byteclk_rate, &pclk_rate);
+ msm_dsi_clk_set_rate(DSI_ESC_CLK_RATE, dsiclk_rate,
+ byteclk_rate, pclk_rate);
+ msm_dsi_clk_enable();
+ }
} else {
- msm_dsi_clk_set_rate(DSI_ESC_CLK_RATE, 0, 0, 0);
- msm_dsi_clk_disable();
- msm_dsi_ahb_ctrl(0);
+ dsi_host_private->clk_count--;
+ if (dsi_host_private->clk_count == 0) {
+ msm_dsi_clk_set_rate(DSI_ESC_CLK_RATE, 0, 0, 0);
+ msm_dsi_clk_disable();
+ msm_dsi_ahb_ctrl(0);
+ }
}
+ mutex_unlock(&ctrl_pdata->mutex);
return 0;
}