msm_fb: display: add spinlock to synchronize mdp irq enable/disable

To improve performance, UI push thread release mutex before blocked at
waiting for vsync to allow Video thread to be updated at same vsycn.
This also cause contention to enable/disable mdp irq.
Add spinlock to synchronize both threads and irq context.

Signed-off-by: Kuogee Hsieh <khsieh@codeaurora.org>
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index cc3bd1b..251e55d 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -2255,11 +2255,15 @@
 	} else {
 		/* primary interface */
 		ctrl->mixer0_played++;
-		if (ctrl->panel_mode & MDP4_PANEL_LCDC)
+		if (ctrl->panel_mode & MDP4_PANEL_LCDC) {
+			mdp4_overlay_reg_flush(pipe, 1);
 			mdp4_overlay_lcdc_vsync_push(mfd, pipe);
+		}
 #ifdef CONFIG_FB_MSM_MIPI_DSI
-		else if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO)
+		else if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO) {
+			mdp4_overlay_reg_flush(pipe, 1);
 			mdp4_overlay_dsi_video_vsync_push(mfd, pipe);
+		}
 #endif
 		else {
 			/* mddi & mipi dsi cmd mode */
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index 88b81e7..f7ceaac 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -37,6 +37,7 @@
 static int first_pixel_start_y;
 
 static int writeback_offset;
+static int wait4vsync_cnt;
 
 static struct mdp4_overlay_pipe *dsi_pipe;
 
@@ -337,22 +338,27 @@
 
 	 /* enable irq */
 	spin_lock_irqsave(&mdp_spin_lock, flag);
-	mdp_enable_irq(MDP_DMA2_TERM);	/* enable intr */
-	INIT_COMPLETION(dsi_pipe->comp);
-	mfd->dma->waiting = TRUE;
-	outp32(MDP_INTR_CLEAR, INTR_PRIMARY_VSYNC);
-	mdp_intr_mask |= INTR_PRIMARY_VSYNC;
-	outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+	if (wait4vsync_cnt == 0) {
+		INIT_COMPLETION(dsi_pipe->comp);
+		mfd->dma->waiting = TRUE;
+		mdp_intr_mask |= INTR_PRIMARY_VSYNC;
+		outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+		mdp_enable_irq(MDP_DMA2_TERM);	/* enable intr */
+	}
+	wait4vsync_cnt++;
 	spin_unlock_irqrestore(&mdp_spin_lock, flag);
 	wait_for_completion_killable(&dsi_pipe->comp);
-	mdp_disable_irq(MDP_DMA2_TERM);
+	spin_lock(&mdp_spin_lock);
+	wait4vsync_cnt--;
+	if (wait4vsync_cnt == 0)
+		mdp_disable_irq(MDP_DMA2_TERM);
+	spin_unlock(&mdp_spin_lock);
 }
 
 void mdp4_overlay_dsi_video_vsync_push(struct msm_fb_data_type *mfd,
 			struct mdp4_overlay_pipe *pipe)
 {
 
-	mdp4_overlay_reg_flush(pipe, 1);
 	if (pipe->flags & MDP_OV_PLAY_NOWAIT)
 		return;
 
@@ -397,6 +403,7 @@
 	pipe = dsi_pipe;
 	pipe->srcp0_addr = (uint32) buf;
 	mdp4_overlay_rgb_setup(pipe);
+	mdp4_overlay_reg_flush(pipe, 1);
 	mutex_unlock(&mfd->dma->ov_mutex);
 	mdp4_overlay_dsi_video_vsync_push(mfd, pipe);
 	mdp4_stat.kickoff_dsi++;
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index ed44d54..811c51d 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -46,6 +46,7 @@
 
 static struct mdp4_overlay_pipe *lcdc_pipe;
 static struct completion lcdc_comp;
+static int wait4vsync_cnt;
 
 int mdp_lcdc_on(struct platform_device *pdev)
 {
@@ -329,22 +330,26 @@
 
 	 /* enable irq */
 	spin_lock_irqsave(&mdp_spin_lock, flag);
-	mdp_enable_irq(MDP_DMA2_TERM);	/* enable intr */
-	INIT_COMPLETION(lcdc_comp);
-	mfd->dma->waiting = TRUE;
-	outp32(MDP_INTR_CLEAR, INTR_PRIMARY_VSYNC);
-	mdp_intr_mask |= INTR_PRIMARY_VSYNC;
-	outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+	if (wait4vsync_cnt == 0) {
+		INIT_COMPLETION(lcdc_comp);
+		mfd->dma->waiting = TRUE;
+		mdp_intr_mask |= INTR_PRIMARY_VSYNC;
+		outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+		mdp_enable_irq(MDP_DMA2_TERM);	/* enable intr */
+	}
+	wait4vsync_cnt++;
 	spin_unlock_irqrestore(&mdp_spin_lock, flag);
-	wait_for_completion_killable(&lcdc_comp);
-	mdp_disable_irq(MDP_DMA2_TERM);
+	wait_for_completion(&lcdc_comp);
+	spin_lock(&mdp_spin_lock);
+	wait4vsync_cnt--;
+	if (wait4vsync_cnt == 0)
+		mdp_disable_irq(MDP_DMA2_TERM);
+	spin_unlock(&mdp_spin_lock);
 }
 
 void mdp4_overlay_lcdc_vsync_push(struct msm_fb_data_type *mfd,
 			struct mdp4_overlay_pipe *pipe)
 {
-
-	mdp4_overlay_reg_flush(pipe, 1);
 	if (pipe->flags & MDP_OV_PLAY_NOWAIT)
 		return;
 
@@ -388,6 +393,7 @@
 	pipe = lcdc_pipe;
 	pipe->srcp0_addr = (uint32) buf;
 	mdp4_overlay_rgb_setup(pipe);
+	mdp4_overlay_reg_flush(pipe, 1);
 	mutex_unlock(&mfd->dma->ov_mutex);
 	mdp4_overlay_lcdc_vsync_push(mfd, pipe);
 	mdp4_stat.kickoff_lcdc++;
diff --git a/drivers/video/msm/mdp4_util.c b/drivers/video/msm/mdp4_util.c
index 52e4a82..0d4f4fc 100644
--- a/drivers/video/msm/mdp4_util.c
+++ b/drivers/video/msm/mdp4_util.c
@@ -404,13 +404,13 @@
 		mdp_intr_mask &= ~INTR_PRIMARY_VSYNC;
 		outp32(MDP_INTR_ENABLE, mdp_intr_mask);
 		dma->waiting = FALSE;
-		spin_unlock(&mdp_spin_lock);
 		if (panel & MDP4_PANEL_LCDC)
 			mdp4_primary_vsync_lcdc();
 #ifdef CONFIG_FB_MSM_MIPI_DSI
 		else if (panel & MDP4_PANEL_DSI_VIDEO)
 			mdp4_primary_vsync_dsi_video();
 #endif
+		spin_unlock(&mdp_spin_lock);
 	}
 #ifdef CONFIG_FB_MSM_DTV
 	if (isr & INTR_EXTERNAL_VSYNC) {
@@ -419,9 +419,9 @@
 		mdp_intr_mask &= ~INTR_EXTERNAL_VSYNC;
 		outp32(MDP_INTR_ENABLE, mdp_intr_mask);
 		dma->waiting = FALSE;
-		spin_unlock(&mdp_spin_lock);
 		if (panel & MDP4_PANEL_DTV)
 			mdp4_external_vsync_dtv();
+		spin_unlock(&mdp_spin_lock);
 	}
 #endif
 	if (isr & INTR_DMA_P_DONE) {