Merge "msm_fb: display:  free writeback buffer at correct time" into msm-3.4
diff --git a/drivers/video/msm/mdp.h b/drivers/video/msm/mdp.h
index e91209b..2411dca 100644
--- a/drivers/video/msm/mdp.h
+++ b/drivers/video/msm/mdp.h
@@ -283,10 +283,10 @@
 #define MDP_PRIM_RDPTR_TERM 0x400
 #endif
 #define MDP_OVERLAY2_TERM 0x80
-#define MDP_HISTOGRAM_TERM_DMA_P 0x100
-#define MDP_HISTOGRAM_TERM_DMA_S 0x200
-#define MDP_HISTOGRAM_TERM_VG_1 0x400
-#define MDP_HISTOGRAM_TERM_VG_2 0x800
+#define MDP_HISTOGRAM_TERM_DMA_P 0x10000
+#define MDP_HISTOGRAM_TERM_DMA_S 0x20000
+#define MDP_HISTOGRAM_TERM_VG_1 0x40000
+#define MDP_HISTOGRAM_TERM_VG_2 0x80000
 
 #define ACTIVE_START_X_EN BIT(31)
 #define ACTIVE_START_Y_EN BIT(31)
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index 71315e6..eee114a 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -2064,7 +2064,7 @@
 	iom_pipe_info = &mdp_iommu[pipe->mixer_num][pipe->pipe_ndx - 1];
 	iom_pipe_info->mark_unmap = 1;
 
-	mdp4_overlay_iommu_pipe_free(pipe->pipe_ndx, 1);
+	mdp4_overlay_iommu_pipe_free(pipe->pipe_ndx, 0);
 
 	memset(pipe, 0, sizeof(*pipe));
 
@@ -2886,16 +2886,11 @@
 
 		mfd->use_ov0_blt &= ~(1 << (pipe->pipe_ndx-1));
 		mdp4_overlay_update_blt_mode(mfd);
-		if (!mfd->use_ov0_blt)
-			mdp4_free_writeback_buf(mfd, MDP4_MIXER0);
 	} else {	/* mixer1, DTV, ATV */
 		if (ctrl->panel_mode & MDP4_PANEL_DTV) {
 			mdp4_overlay_dtv_unset(mfd, pipe);
 			mfd->use_ov1_blt &= ~(1 << (pipe->pipe_ndx-1));
 			mdp4_overlay1_update_blt_mode(mfd);
-			if (!mfd->use_ov1_blt)
-				mdp4_free_writeback_buf(mfd,
-								MDP4_MIXER1);
 		}
 	}
 
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index 28b5cd5..398b1e6 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -49,16 +49,19 @@
 	struct device *dev;
 	int inited;
 	int update_ndx;
-	uint32 dmap_intr_cnt;
+	int ov_koff;
+	int ov_done;
 	atomic_t suspend;
-	int dmap_wait_cnt;
 	int wait_vsync_cnt;
 	int blt_change;
+	int blt_free;
 	int fake_vsync;
 	struct mutex update_lock;
+	struct completion ov_comp;
 	struct completion dmap_comp;
 	struct completion vsync_comp;
 	spinlock_t spin_lock;
+	struct msm_fb_data_type *mfd;
 	struct mdp4_overlay_pipe *base_pipe;
 	struct vsync_update vlist[2];
 	int vsync_irq_enabled;
@@ -145,8 +148,9 @@
 	mdp4_stat.overlay_play[pipe->mixer_num]++;
 }
 
-
 static void mdp4_dsi_video_blt_ov_update(struct mdp4_overlay_pipe *pipe);
+static void mdp4_dsi_video_wait4dmap(int cndx);
+static void mdp4_dsi_video_wait4ov(int cndx);
 
 int mdp4_dsi_video_pipe_commit(void)
 {
@@ -175,11 +179,37 @@
 	vctrl->update_ndx++;
 	vctrl->update_ndx &= 0x01;
 	vp->update_cnt = 0;     /* reset */
+	if (vctrl->blt_free) {
+		vctrl->blt_free--;
+		if (vctrl->blt_free == 0)
+			mdp4_free_writeback_buf(vctrl->mfd, mixer);
+	}
 	mutex_unlock(&vctrl->update_lock);
 
 	/* free previous committed iommu back to pool */
 	mdp4_overlay_iommu_unmap_freelist(mixer);
 
+	spin_lock_irqsave(&vctrl->spin_lock, flags);
+	if (vctrl->ov_koff != vctrl->ov_done) {
+		spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+		pr_err("%s: Error, frame dropped %d %d\n", __func__,
+				vctrl->ov_koff, vctrl->ov_done);
+		return 0;
+	}
+	spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+
+	if (vctrl->blt_change) {
+		pipe = vctrl->base_pipe;
+		spin_lock_irqsave(&vctrl->spin_lock, flags);
+		INIT_COMPLETION(vctrl->dmap_comp);
+		INIT_COMPLETION(vctrl->ov_comp);
+		vsync_irq_enable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
+		spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+		mdp4_dsi_video_wait4dmap(0);
+		if (pipe->ov_blt_addr)
+			mdp4_dsi_video_wait4ov(0);
+	}
+
 	pipe = vp->plist;
 	for (i = 0; i < OVERLAY_PIPE_MAX; i++, pipe++) {
 		if (pipe->pipe_used) {
@@ -200,16 +230,17 @@
 	spin_lock_irqsave(&vctrl->spin_lock, flags);
 	if (pipe->ov_blt_addr) {
 		mdp4_dsi_video_blt_ov_update(pipe);
-		pipe->blt_ov_done++;
+		pipe->ov_cnt++;
+		INIT_COMPLETION(vctrl->ov_comp);
 		vsync_irq_enable(INTR_OVERLAY0_DONE, MDP_OVERLAY0_TERM);
 		mb();
-		pipe->blt_ov_koff++;
+		vctrl->ov_koff++;
 		/* kickoff overlay engine */
 		mdp4_stat.kickoff_ov0++;
 		outpdw(MDP_BASE + 0x0004, 0);
-	} else if (vctrl->dmap_intr_cnt == 0) {
+	} else {
 		/* schedule second phase update  at dmap */
-		vctrl->dmap_intr_cnt++;
+		INIT_COMPLETION(vctrl->dmap_comp);
 		vsync_irq_enable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
 	}
 	spin_unlock_irqrestore(&vctrl->spin_lock, flags);
@@ -285,7 +316,6 @@
 
 static void mdp4_dsi_video_wait4dmap(int cndx)
 {
-	unsigned long flags;
 	struct vsycn_ctrl *vctrl;
 
 	if (cndx >= MAX_CONTROLLER) {
@@ -298,23 +328,26 @@
 	if (atomic_read(&vctrl->suspend) > 0)
 		return;
 
-	/* start timing generator & mmu if they are not started yet */
-	mdp4_overlay_dsi_video_start();
-
-	spin_lock_irqsave(&vctrl->spin_lock, flags);
-	if (vctrl->dmap_wait_cnt == 0) {
-		INIT_COMPLETION(vctrl->dmap_comp);
-		if (vctrl->dmap_intr_cnt == 0) {
-			vctrl->dmap_intr_cnt++;
-			vsync_irq_enable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
-		}
-	}
-	vctrl->dmap_wait_cnt++;
-	spin_unlock_irqrestore(&vctrl->spin_lock, flags);
-
 	wait_for_completion(&vctrl->dmap_comp);
 }
 
+static void mdp4_dsi_video_wait4ov(int cndx)
+{
+	struct vsycn_ctrl *vctrl;
+
+	if (cndx >= MAX_CONTROLLER) {
+		pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+		return;
+	}
+
+	vctrl = &vsync_ctrl_db[cndx];
+
+	if (atomic_read(&vctrl->suspend) > 0)
+		return;
+
+	wait_for_completion(&vctrl->ov_comp);
+}
+
 static void send_vsync_work(struct work_struct *work)
 {
 	struct vsycn_ctrl *vctrl =
@@ -349,6 +382,7 @@
 	mutex_init(&vctrl->update_lock);
 	init_completion(&vctrl->vsync_comp);
 	init_completion(&vctrl->dmap_comp);
+	init_completion(&vctrl->ov_comp);
 	atomic_set(&vctrl->suspend, 0);
 	spin_lock_init(&vctrl->spin_lock);
 	INIT_WORK(&vctrl->vsync_work, send_vsync_work);
@@ -413,14 +447,15 @@
 	vctrl = &vsync_ctrl_db[cndx];
 	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
 
-	vctrl->dev = mfd->fbi->dev;
-
 	if (!mfd)
 		return -ENODEV;
 
 	if (mfd->key != MFD_KEY)
 		return -EINVAL;
 
+	vctrl->mfd = mfd;
+	vctrl->dev = mfd->fbi->dev;
+
 	/* mdp clock on */
 	mdp_clk_ctrl(1);
 
@@ -728,18 +763,16 @@
 	int bpp;
 	char *overlay_base;
 
-
 	if (pipe->ov_blt_addr == 0)
 		return;
 
-
 #ifdef BLT_RGB565
 	bpp = 2; /* overlay ouput is RGB565 */
 #else
 	bpp = 3; /* overlay ouput is RGB888 */
 #endif
 	off = 0;
-	if (pipe->blt_ov_done & 0x01)
+	if (pipe->ov_cnt & 0x01)
 		off = pipe->src_height * pipe->src_width * bpp;
 	addr = pipe->ov_blt_addr + off;
 
@@ -764,7 +797,7 @@
 	bpp = 3; /* overlay ouput is RGB888 */
 #endif
 	off = 0;
-	if (pipe->blt_dmap_done & 0x01)
+	if (pipe->dmap_cnt & 0x01)
 		off = pipe->src_height * pipe->src_width * bpp;
 	addr = pipe->dma_blt_addr + off;
 
@@ -774,7 +807,6 @@
 
 void mdp4_overlay_dsi_video_set_perf(struct msm_fb_data_type *mfd)
 {
-	mdp4_dsi_video_wait4dmap(0);
 	/* change mdp clk while mdp is idle */
 	mdp4_set_perf_level();
 }
@@ -819,30 +851,26 @@
 	pipe = vctrl->base_pipe;
 
 	spin_lock(&vctrl->spin_lock);
+	vsync_irq_disable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
 	if (vctrl->blt_change) {
 		mdp4_overlayproc_cfg(pipe);
 		mdp4_overlay_dmap_xy(pipe);
 		if (pipe->ov_blt_addr) {
 			mdp4_dsi_video_blt_ov_update(pipe);
-			pipe->blt_ov_done++;
-
+			pipe->ov_cnt++;
 			/* Prefill one frame */
-			vsync_irq_enable(INTR_OVERLAY0_DONE, MDP_OVERLAY0_TERM);
+			vsync_irq_enable(INTR_OVERLAY0_DONE,
+						MDP_OVERLAY0_TERM);
 			/* kickoff overlay0 engine */
 			mdp4_stat.kickoff_ov0++;
+			vctrl->ov_koff++;	/* make up for prefill */
 			outpdw(MDP_BASE + 0x0004, 0);
 		}
 		vctrl->blt_change = 0;
 	}
 
-	vctrl->dmap_intr_cnt--;
-	if (vctrl->dmap_wait_cnt) {
-		complete_all(&vctrl->dmap_comp);
-		vctrl->dmap_wait_cnt = 0; /* reset */
-	} else  {
-		mdp4_overlay_dma_commit(cndx);
-	}
-	vsync_irq_disable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
+	complete_all(&vctrl->dmap_comp);
+	mdp4_overlay_dma_commit(cndx);
 	spin_unlock(&vctrl->spin_lock);
 }
 
@@ -858,14 +886,16 @@
 	pipe = vctrl->base_pipe;
 
 	spin_lock(&vctrl->spin_lock);
+	vsync_irq_disable(INTR_OVERLAY0_DONE, MDP_OVERLAY0_TERM);
+	vctrl->ov_done++;
+	complete_all(&vctrl->ov_comp);
 	if (pipe->ov_blt_addr == 0) {
 		spin_unlock(&vctrl->spin_lock);
 		return;
 	}
 
 	mdp4_dsi_video_blt_dmap_update(pipe);
-	pipe->blt_dmap_done++;
-	vsync_irq_disable(INTR_OVERLAY0_DONE, MDP_OVERLAY0_TERM);
+	pipe->dmap_cnt++;
 	spin_unlock(&vctrl->spin_lock);
 }
 
@@ -876,7 +906,6 @@
 static void mdp4_dsi_video_do_blt(struct msm_fb_data_type *mfd, int enable)
 {
 	unsigned long flag;
-	int data;
 	int cndx = 0;
 	struct vsycn_ctrl *vctrl;
 	struct mdp4_overlay_pipe *pipe;
@@ -895,16 +924,17 @@
 	if (enable && pipe->ov_blt_addr == 0) {
 		pipe->ov_blt_addr = mfd->ov0_wb_buf->write_addr;
 		pipe->dma_blt_addr = mfd->ov0_wb_buf->read_addr;
-		pipe->blt_cnt = 0;
 		pipe->ov_cnt = 0;
-		pipe->blt_dmap_done = 0;
-		pipe->blt_ov_koff = 0;
-		pipe->blt_ov_done = 0;
+		pipe->dmap_cnt = 0;
+		vctrl->ov_koff = 0;
+		vctrl->ov_done = 0;
+		vctrl->blt_free = 0;
 		mdp4_stat.blt_dsi_video++;
 		vctrl->blt_change++;
 	} else if (enable == 0 && pipe->ov_blt_addr) {
 		pipe->ov_blt_addr = 0;
 		pipe->dma_blt_addr =  0;
+		vctrl->blt_free = 4;	/* 4 commits to free wb buf */
 		vctrl->blt_change++;
 	}
 
@@ -917,11 +947,6 @@
 	}
 
 	spin_unlock_irqrestore(&vctrl->spin_lock, flag);
-
-	data = inpdw(MDP_BASE + DSI_VIDEO_BASE);
-	data &= 0x01;
-	if (data)	/* timing generator enabled */
-		mdp4_dsi_video_wait4dmap(0);
 }
 
 void mdp4_dsi_video_overlay_blt(struct msm_fb_data_type *mfd,
@@ -972,6 +997,10 @@
 	}
 
 	mdp4_dsi_video_pipe_commit();
-	mdp4_dsi_video_wait4dmap(0);
+
+	if (pipe->ov_blt_addr)
+		mdp4_dsi_video_wait4ov(0);
+	else
+		mdp4_dsi_video_wait4dmap(0);
 }
 
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index 57793fc..2da2052 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -50,16 +50,19 @@
 	struct device *dev;
 	int inited;
 	int update_ndx;
-	uint32 dmap_intr_cnt;
+	int ov_koff;
+	int ov_done;
 	atomic_t suspend;
-	int dmap_wait_cnt;
 	int wait_vsync_cnt;
 	int blt_change;
+	int blt_free;
 	int fake_vsync;
 	struct mutex update_lock;
+	struct completion ov_comp;
 	struct completion dmap_comp;
 	struct completion vsync_comp;
 	spinlock_t spin_lock;
+	struct msm_fb_data_type *mfd;
 	struct mdp4_overlay_pipe *base_pipe;
 	struct vsync_update vlist[2];
 	int vsync_irq_enabled;
@@ -150,8 +153,9 @@
 	mdp4_stat.overlay_play[pipe->mixer_num]++;
 }
 
-
 static void mdp4_lcdc_blt_ov_update(struct mdp4_overlay_pipe *pipe);
+static void mdp4_lcdc_wait4dmap(int cndx);
+static void mdp4_lcdc_wait4ov(int cndx);
 
 int mdp4_lcdc_pipe_commit(void)
 {
@@ -180,11 +184,37 @@
 	vctrl->update_ndx++;
 	vctrl->update_ndx &= 0x01;
 	vp->update_cnt = 0;     /* reset */
+	if (vctrl->blt_free) {
+		vctrl->blt_free--;
+		if (vctrl->blt_free == 0)
+			mdp4_free_writeback_buf(vctrl->mfd, mixer);
+	}
 	mutex_unlock(&vctrl->update_lock);
 
 	/* free previous committed iommu back to pool */
 	mdp4_overlay_iommu_unmap_freelist(mixer);
 
+	spin_lock_irqsave(&vctrl->spin_lock, flags);
+	if (vctrl->ov_koff != vctrl->ov_done) {
+		spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+		pr_err("%s: Error, frame dropped %d %d\n", __func__,
+			vctrl->ov_koff, vctrl->ov_done);
+		return 0;
+	}
+	spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+
+	if (vctrl->blt_change) {
+		pipe = vctrl->base_pipe;
+		spin_lock_irqsave(&vctrl->spin_lock, flags);
+		INIT_COMPLETION(vctrl->dmap_comp);
+		INIT_COMPLETION(vctrl->ov_comp);
+		vsync_irq_enable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
+		spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+		mdp4_lcdc_wait4dmap(0);
+		if (pipe->ov_blt_addr)
+			mdp4_lcdc_wait4ov(0);
+	}
+
 	pipe = vp->plist;
 	for (i = 0; i < OVERLAY_PIPE_MAX; i++, pipe++) {
 		if (pipe->pipe_used) {
@@ -205,15 +235,17 @@
 	spin_lock_irqsave(&vctrl->spin_lock, flags);
 	if (pipe->ov_blt_addr) {
 		mdp4_lcdc_blt_ov_update(pipe);
-		pipe->blt_ov_done++;
+		pipe->ov_cnt++;
+		INIT_COMPLETION(vctrl->ov_comp);
 		vsync_irq_enable(INTR_OVERLAY0_DONE, MDP_OVERLAY0_TERM);
 		mb();
-		pipe->blt_ov_koff++;
+		vctrl->ov_koff++;
 		/* kickoff overlay engine */
+		mdp4_stat.kickoff_ov0++;
 		outpdw(MDP_BASE + 0x0004, 0);
-	} else if (vctrl->dmap_intr_cnt == 0) {
+	} else {
 		/* schedule second phase update  at dmap */
-		vctrl->dmap_intr_cnt++;
+		INIT_COMPLETION(vctrl->dmap_comp);
 		vsync_irq_enable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
 	}
 	spin_unlock_irqrestore(&vctrl->spin_lock, flags);
@@ -289,7 +321,6 @@
 
 static void mdp4_lcdc_wait4dmap(int cndx)
 {
-	unsigned long flags;
 	struct vsycn_ctrl *vctrl;
 
 	if (cndx >= MAX_CONTROLLER) {
@@ -302,22 +333,24 @@
 	if (atomic_read(&vctrl->suspend) > 0)
 		return;
 
-	/* start timing generator & mmu if they are not started yet */
-	mdp4_overlay_lcdc_start();
-
-	spin_lock_irqsave(&vctrl->spin_lock, flags);
-	if (vctrl->dmap_wait_cnt == 0) {
-		INIT_COMPLETION(vctrl->dmap_comp);
-		if (vctrl->dmap_intr_cnt == 0) {
-			vctrl->dmap_intr_cnt++;
-			vsync_irq_enable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
-		}
-	}
-	vctrl->dmap_wait_cnt++;
-	spin_unlock_irqrestore(&vctrl->spin_lock, flags);
-
 	wait_for_completion(&vctrl->dmap_comp);
-	pr_debug("%s: pid=%d after wait\n", __func__, current->pid);
+}
+
+static void mdp4_lcdc_wait4ov(int cndx)
+{
+	struct vsycn_ctrl *vctrl;
+
+	if (cndx >= MAX_CONTROLLER) {
+		pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+		return;
+	}
+
+	vctrl = &vsync_ctrl_db[cndx];
+
+	if (atomic_read(&vctrl->suspend) > 0)
+		return;
+
+	wait_for_completion(&vctrl->ov_comp);
 }
 
 static void send_vsync_work(struct work_struct *work)
@@ -354,6 +387,7 @@
 	mutex_init(&vctrl->update_lock);
 	init_completion(&vctrl->vsync_comp);
 	init_completion(&vctrl->dmap_comp);
+	init_completion(&vctrl->ov_comp);
 	atomic_set(&vctrl->suspend, 0);
 	spin_lock_init(&vctrl->spin_lock);
 	INIT_WORK(&vctrl->vsync_work, send_vsync_work);
@@ -424,6 +458,7 @@
 	if (mfd->key != MFD_KEY)
 		return -EINVAL;
 
+	vctrl->mfd = mfd;
 	vctrl->dev = mfd->fbi->dev;
 
 	/* mdp clock on */
@@ -637,18 +672,16 @@
 	int bpp;
 	char *overlay_base;
 
-
 	if (pipe->ov_blt_addr == 0)
 		return;
 
-
 #ifdef BLT_RGB565
 	bpp = 2; /* overlay ouput is RGB565 */
 #else
 	bpp = 3; /* overlay ouput is RGB888 */
 #endif
 	off = 0;
-	if (pipe->blt_ov_done & 0x01)
+	if (pipe->ov_cnt & 0x01)
 		off = pipe->src_height * pipe->src_width * bpp;
 	addr = pipe->ov_blt_addr + off;
 
@@ -666,14 +699,13 @@
 	if (pipe->ov_blt_addr == 0)
 		return;
 
-
 #ifdef BLT_RGB565
 	bpp = 2; /* overlay ouput is RGB565 */
 #else
 	bpp = 3; /* overlay ouput is RGB888 */
 #endif
 	off = 0;
-	if (pipe->blt_dmap_done & 0x01)
+	if (pipe->dmap_cnt & 0x01)
 		off = pipe->src_height * pipe->src_width * bpp;
 	addr = pipe->dma_blt_addr + off;
 
@@ -683,7 +715,6 @@
 
 void mdp4_overlay_lcdc_set_perf(struct msm_fb_data_type *mfd)
 {
-	mdp4_lcdc_wait4dmap(0);
 	/* change mdp clk while mdp is idle */
 	mdp4_set_perf_level();
 }
@@ -727,29 +758,25 @@
 	pipe = vctrl->base_pipe;
 
 	spin_lock(&vctrl->spin_lock);
+	vsync_irq_disable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
 	if (vctrl->blt_change) {
 		mdp4_overlayproc_cfg(pipe);
 		mdp4_overlay_dmap_xy(pipe);
 		if (pipe->ov_blt_addr) {
 			mdp4_lcdc_blt_ov_update(pipe);
-			pipe->blt_ov_done++;
-
+			pipe->ov_cnt++;
 			/* Prefill one frame */
 			vsync_irq_enable(INTR_OVERLAY0_DONE, MDP_OVERLAY0_TERM);
 			/* kickoff overlay0 engine */
+			mdp4_stat.kickoff_ov0++;
+			vctrl->ov_koff++;       /* make up for prefill */
 			outpdw(MDP_BASE + 0x0004, 0);
 		}
 		vctrl->blt_change = 0;
 	}
 
-	vctrl->dmap_intr_cnt--;
-	if (vctrl->dmap_wait_cnt) {
-		complete_all(&vctrl->dmap_comp);
-		vctrl->dmap_wait_cnt = 0; /* reset */
-	} else  {
-		mdp4_overlay_dma_commit(cndx);
-	}
-	vsync_irq_disable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
+	complete_all(&vctrl->dmap_comp);
+	mdp4_overlay_dma_commit(cndx);
 	spin_unlock(&vctrl->spin_lock);
 }
 
@@ -765,21 +792,22 @@
 	pipe = vctrl->base_pipe;
 
 	spin_lock(&vctrl->spin_lock);
+	vsync_irq_disable(INTR_OVERLAY0_DONE, MDP_OVERLAY0_TERM);
+	vctrl->ov_done++;
+	complete_all(&vctrl->ov_comp);
 	if (pipe->ov_blt_addr == 0) {
 		spin_unlock(&vctrl->spin_lock);
 		return;
 	}
 
 	mdp4_lcdc_blt_dmap_update(pipe);
-	pipe->blt_dmap_done++;
-	mdp_disable_irq_nosync(MDP_OVERLAY0_TERM);
+	pipe->dmap_cnt++;
 	spin_unlock(&vctrl->spin_lock);
 }
 
 static void mdp4_lcdc_do_blt(struct msm_fb_data_type *mfd, int enable)
 {
 	unsigned long flag;
-	int data;
 	int cndx = 0;
 	struct vsycn_ctrl *vctrl;
 	struct mdp4_overlay_pipe *pipe;
@@ -798,16 +826,17 @@
 	if (enable && pipe->ov_blt_addr == 0) {
 		pipe->ov_blt_addr = mfd->ov0_wb_buf->write_addr;
 		pipe->dma_blt_addr = mfd->ov0_wb_buf->read_addr;
-		pipe->blt_cnt = 0;
 		pipe->ov_cnt = 0;
-		pipe->blt_dmap_done = 0;
-		pipe->blt_ov_koff = 0;
-		pipe->blt_ov_done = 0;
+		pipe->dmap_cnt = 0;
+		vctrl->ov_koff = 0;
+		vctrl->ov_done = 0;
+		vctrl->blt_free = 0;
 		mdp4_stat.blt_lcdc++;
 		vctrl->blt_change++;
 	} else if (enable == 0 && pipe->ov_blt_addr) {
 		pipe->ov_blt_addr = 0;
 		pipe->dma_blt_addr = 0;
+		vctrl->blt_free = 4;    /* 4 commits to free wb buf */
 		vctrl->blt_change++;
 	}
 
@@ -820,11 +849,6 @@
 	}
 
 	spin_unlock_irqrestore(&vctrl->spin_lock, flag);
-
-	data = inpdw(MDP_BASE + LCDC_BASE);
-	data &= 0x01;
-	if (data)       /* timing generator enabled */
-		mdp4_lcdc_wait4dmap(0);
 }
 
 void mdp4_lcdc_overlay_blt(struct msm_fb_data_type *mfd,
@@ -876,5 +900,9 @@
 	}
 
 	mdp4_lcdc_pipe_commit();
-	mdp4_lcdc_wait4dmap(0);
+
+	if (pipe->ov_blt_addr)
+		mdp4_lcdc_wait4ov(0);
+	else
+		mdp4_lcdc_wait4dmap(0);
 }
diff --git a/drivers/video/msm/mdp4_util.c b/drivers/video/msm/mdp4_util.c
index 573e317..e76b8ba 100644
--- a/drivers/video/msm/mdp4_util.c
+++ b/drivers/video/msm/mdp4_util.c
@@ -462,11 +462,6 @@
 		dma = &dma2_data;
 		if (panel & (MDP4_PANEL_LCDC | MDP4_PANEL_DSI_VIDEO)) {
 			/* disable LCDC interrupt */
-			spin_lock(&mdp_spin_lock);
-			mdp_intr_mask &= ~INTR_OVERLAY0_DONE;
-			outp32(MDP_INTR_ENABLE, mdp_intr_mask);
-			dma->waiting = FALSE;
-			spin_unlock(&mdp_spin_lock);
 			if (panel & MDP4_PANEL_LCDC)
 				mdp4_overlay0_done_lcdc(0);
 #ifdef CONFIG_FB_MSM_MIPI_DSI