msm_fb: display: change mdp clock while mdp is idle
Mdp clock need to be adjusted at run time base on the
performance level. However mdp clock can only be changed
when mdp blending/dma engine is idle.
Signed-off-by: Kuogee Hsieh <khsieh@codeaurora.org>
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index 8e89b16..6f7d59c 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -452,6 +452,8 @@
void mdp4_dma_s_done_mddi(void);
void mdp4_dma_p_done_mddi(void);
void mdp4_dma_p_done_dsi(struct mdp_dma_data *dma);
+void mdp4_dma_p_done_dsi_video(void);
+void mdp4_dma_p_done_lcdc(void);
void mdp4_overlay1_done_dtv(void);
void mdp4_overlay1_done_atv(void);
void mdp4_primary_vsync_lcdc(void);
@@ -460,6 +462,8 @@
void mdp4_overlay_lcdc_wait4vsync(struct msm_fb_data_type *mfd);
void mdp4_overlay_lcdc_vsync_push(struct msm_fb_data_type *mfd,
struct mdp4_overlay_pipe *pipe);
+
+void mdp4_set_perf_level(void);
void mdp4_mddi_overlay_dmas_restore(void);
void mdp4_mddi_dma_busy_wait(struct msm_fb_data_type *mfd);
void mdp4_mddi_overlay_kickoff(struct msm_fb_data_type *mfd,
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index 954f9f9..e8d6eef 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -98,7 +98,7 @@
};
static struct mdp4_overlay_ctrl *ctrl = &mdp4_overlay_db;
-static uint32 perf_level;
+static uint32 new_perf_level;
static uint32 mdp4_del_res_rel;
/* static array with index 0 for unset status and 1 for set status */
static bool overlay_status[MDP4_OVERLAY_TYPE_MAX];
@@ -1873,10 +1873,20 @@
return OVERLAY_PERF_LEVEL1;
}
+void mdp4_set_perf_level(void)
+{
+ static int old_perf_level;
+
+ if (old_perf_level != new_perf_level) {
+ mdp_set_core_clk(new_perf_level);
+ old_perf_level = new_perf_level;
+ }
+}
+
int mdp4_overlay_set(struct fb_info *info, struct mdp_overlay *req)
{
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
- int ret, mixer;
+ int ret, mixer, perf_level;
struct mdp4_overlay_pipe *pipe;
if (mfd == NULL) {
@@ -1964,7 +1974,8 @@
mdp4_del_res_rel = 0;
mutex_unlock(&mfd->dma->ov_mutex);
- mdp_set_core_clk(perf_level);
+
+ new_perf_level = perf_level;
#ifdef CONFIG_MSM_BUS_SCALING
if (pipe->mixer_num == MDP4_MIXER0) {
@@ -1976,14 +1987,6 @@
return 0;
}
-void mdp4_overlay_resource_release(void)
-{
- if (mdp4_del_res_rel) {
- mdp_set_core_clk(OVERLAY_PERF_LEVEL4);
- mdp4_del_res_rel = 0;
- }
-}
-
int mdp4_overlay_unset(struct fb_info *info, int ndx)
{
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
@@ -2069,7 +2072,7 @@
if (!(ctrl->ov_pipe[OVERLAY_PIPE_VG1].ref_cnt +
ctrl->ov_pipe[OVERLAY_PIPE_VG2].ref_cnt))
- mdp4_del_res_rel = 1;
+ new_perf_level = OVERLAY_PERF_LEVEL4;
mutex_unlock(&mfd->dma->ov_mutex);
diff --git a/drivers/video/msm/mdp4_overlay_atv.c b/drivers/video/msm/mdp4_overlay_atv.c
index 8dcdec0..420a9bc 100644
--- a/drivers/video/msm/mdp4_overlay_atv.c
+++ b/drivers/video/msm/mdp4_overlay_atv.c
@@ -183,7 +183,9 @@
wait_for_completion_killable(&atv_pipe->comp);
mdp_disable_irq(MDP_OVERLAY1_TERM);
+ /* change mdp clk while mdp is idle` */
+ mdp4_set_perf_level();
+
mdp4_stat.kickoff_atv++;
- mdp4_overlay_resource_release();
mutex_unlock(&mfd->dma->ov_mutex);
}
diff --git a/drivers/video/msm/mdp4_overlay_dsi_cmd.c b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
index a440ddf..9d00d80 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_cmd.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
@@ -629,6 +629,9 @@
unsigned long flag;
+ /* change mdp clk */
+ mdp4_set_perf_level();
+
mdp4_overlay_dsi_state_set(ST_DSI_PLAYING);
spin_lock_irqsave(&mdp_spin_lock, flag);
@@ -669,6 +672,5 @@
complete(&mfd->pan_comp);
}
}
- mdp4_overlay_resource_release();
mutex_unlock(&mfd->dma->ov_mutex);
}
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index 6d8a43f..0d2264f 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -419,16 +419,20 @@
}
#endif
-void mdp4_overlay_dsi_video_wait4vsync(struct msm_fb_data_type *mfd)
+static void mdp4_overlay_dsi_video_wait4event(struct msm_fb_data_type *mfd,
+ int dmap)
{
unsigned long flag;
- /* enable irq */
+ /* enable irq */
spin_lock_irqsave(&mdp_spin_lock, flag);
if (wait4vsync_cnt == 0) {
INIT_COMPLETION(dsi_pipe->comp);
mfd->dma->waiting = TRUE;
- mdp_intr_mask |= INTR_PRIMARY_VSYNC;
+ if (dmap)
+ mdp_intr_mask |= INTR_DMA_P_DONE;
+ else
+ mdp_intr_mask |= INTR_PRIMARY_VSYNC;
outp32(MDP_INTR_ENABLE, mdp_intr_mask);
mdp_enable_irq(MDP_DMA2_TERM); /* enable intr */
}
@@ -449,7 +453,10 @@
if (pipe->flags & MDP_OV_PLAY_NOWAIT)
return;
- mdp4_overlay_dsi_video_wait4vsync(mfd);
+ mdp4_overlay_dsi_video_wait4event(mfd, 1);
+
+ /* change mdp clk while mdp is idle */
+ mdp4_set_perf_level();
}
/*
@@ -460,6 +467,15 @@
complete_all(&dsi_pipe->comp);
}
+ /*
+ * mdp4_dma_p_done_dsi_video: called from isr
+ */
+void mdp4_dma_p_done_dsi_video(void)
+{
+ complete_all(&dsi_pipe->comp);
+}
+
+
/*
* mdp4_overlay1_done_dsi: called from isr
*/
@@ -494,5 +510,4 @@
mutex_unlock(&mfd->dma->ov_mutex);
mdp4_overlay_dsi_video_vsync_push(mfd, pipe);
mdp4_stat.kickoff_dsi++;
- mdp4_overlay_resource_release();
}
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index 71b460c..e6ba15e 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -319,6 +319,9 @@
return;
mdp4_overlay_dtv_wait4vsync(mfd);
+
+ /* change mdp clk while mdp is idle` */
+ mdp4_set_perf_level();
}
static void mdp4_overlay_dtv_wait4_ov_done(struct msm_fb_data_type *mfd)
@@ -347,6 +350,9 @@
return;
mdp4_overlay_dtv_wait4_ov_done(mfd);
+
+ /* change mdp clk while mdp is idle` */
+ mdp4_set_perf_level();
}
void mdp4_external_vsync_dtv()
@@ -399,6 +405,5 @@
mdp_disable_irq(MDP_OVERLAY1_TERM);
mdp4_stat.kickoff_dtv++;
- mdp4_overlay_resource_release();
mutex_unlock(&mfd->dma->ov_mutex);
}
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index 811c51d..0ac990b 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -324,7 +324,7 @@
}
#endif
-void mdp4_overlay_lcdc_wait4vsync(struct msm_fb_data_type *mfd)
+static void mdp4_overlay_lcdc_wait4event(struct msm_fb_data_type *mfd, int dmap)
{
unsigned long flag;
@@ -333,7 +333,10 @@
if (wait4vsync_cnt == 0) {
INIT_COMPLETION(lcdc_comp);
mfd->dma->waiting = TRUE;
- mdp_intr_mask |= INTR_PRIMARY_VSYNC;
+ if (dmap)
+ mdp_intr_mask |= INTR_DMA_P_DONE;
+ else
+ mdp_intr_mask |= INTR_PRIMARY_VSYNC;
outp32(MDP_INTR_ENABLE, mdp_intr_mask);
mdp_enable_irq(MDP_DMA2_TERM); /* enable intr */
}
@@ -353,7 +356,10 @@
if (pipe->flags & MDP_OV_PLAY_NOWAIT)
return;
- mdp4_overlay_lcdc_wait4vsync(mfd);
+ mdp4_overlay_lcdc_wait4event(mfd, 1);
+
+ /* change mdp clk while mdp is idle` */
+ mdp4_set_perf_level();
}
/*
@@ -365,6 +371,14 @@
}
/*
+ * mdp4_dma_p_done_lcdc: called from isr
+ */
+void mdp4_dma_p_done_lcdc(void)
+{
+ complete_all(&lcdc_comp);
+}
+
+/*
* mdp4_overlay0_done_lcdc: called from isr
*/
void mdp4_overlay0_done_lcdc(void)
@@ -397,5 +411,4 @@
mutex_unlock(&mfd->dma->ov_mutex);
mdp4_overlay_lcdc_vsync_push(mfd, pipe);
mdp4_stat.kickoff_lcdc++;
- mdp4_overlay_resource_release();
}
diff --git a/drivers/video/msm/mdp4_overlay_mddi.c b/drivers/video/msm/mdp4_overlay_mddi.c
index 2bf9faf..bd94c56 100644
--- a/drivers/video/msm/mdp4_overlay_mddi.c
+++ b/drivers/video/msm/mdp4_overlay_mddi.c
@@ -447,6 +447,9 @@
void mdp4_mddi_overlay_kickoff(struct msm_fb_data_type *mfd,
struct mdp4_overlay_pipe *pipe)
{
+ /* change mdp clk while mdp is idle` */
+ mdp4_set_perf_level();
+
if (mdp_hw_revision == MDP4_REVISION_V2_1) {
if (mdp4_overlay_status_read(MDP4_OVERLAY_TYPE_UNSET)) {
uint32 data;
@@ -546,6 +549,9 @@
void mdp4_mddi_dma_s_kickoff(struct msm_fb_data_type *mfd,
struct mdp4_overlay_pipe *pipe)
{
+ /* change mdp clk while mdp is idle` */
+ mdp4_set_perf_level();
+
mdp_enable_irq(MDP_DMA_S_TERM);
mfd->dma->busy = TRUE;
mfd->ibuf_flushed = TRUE;
@@ -595,7 +601,6 @@
complete(&mfd->pan_comp);
}
}
- mdp4_overlay_resource_release();
mutex_unlock(&mfd->dma->ov_mutex);
}
diff --git a/drivers/video/msm/mdp4_util.c b/drivers/video/msm/mdp4_util.c
index 0d4f4fc..a700caa 100644
--- a/drivers/video/msm/mdp4_util.c
+++ b/drivers/video/msm/mdp4_util.c
@@ -433,24 +433,37 @@
mdp_intr_mask &= ~INTR_DMA_P_DONE;
outp32(MDP_INTR_ENABLE, mdp_intr_mask);
dma->waiting = FALSE;
+ mdp4_dma_p_done_lcdc();
spin_unlock(&mdp_spin_lock);
- } else { /* MDDI */
+ }
#ifdef CONFIG_FB_MSM_OVERLAY
#ifdef CONFIG_FB_MSM_MIPI_DSI
+ else if (panel & MDP4_PANEL_DSI_VIDEO) {
+ /* disable LCDC interrupt */
+ spin_lock(&mdp_spin_lock);
+ mdp_intr_mask &= ~INTR_DMA_P_DONE;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ dma->waiting = FALSE;
+ mdp4_dma_p_done_dsi_video();
+ spin_unlock(&mdp_spin_lock);
+ } else if (panel & MDP4_PANEL_DSI_CMD) {
mdp4_dma_p_done_dsi(dma);
+ }
#else
+ else { /* MDDI */
mdp4_dma_p_done_mddi();
mdp_pipe_ctrl(MDP_DMA2_BLOCK,
MDP_BLOCK_POWER_OFF, TRUE);
+ complete(&dma->comp);
+ }
#endif
#else
+ else {
spin_lock(&mdp_spin_lock);
dma->busy = FALSE;
spin_unlock(&mdp_spin_lock);
-#endif
+ complete(&dma->comp);
}
-#ifndef CONFIG_FB_MSM_MIPI_DSI
- complete(&dma->comp);
#endif
}
if (isr & INTR_DMA_S_DONE) {