Merge "display: flush fences on dma stop" into android-msm-ray-3.18
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index ff361f4..1e4f584 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -153,10 +153,32 @@
 	return blocking_notifier_call_chain(&ses->notifier_head, event, ses);
 }
 
+static void __mdp3_dispatch_dma_done(struct mdp3_session_data *session)
+{
+	int cnt;
+
+	cnt = atomic_read(&session->dma_done_cnt);
+	MDSS_XLOG(cnt);
+	while (cnt > 0) {
+		mdp3_ctrl_notify(session, MDP_NOTIFY_FRAME_DONE);
+		atomic_dec(&session->dma_done_cnt);
+		cnt--;
+	}
+}
+
+void mdp3_flush_dma_done(struct mdp3_session_data *session)
+{
+	if (!session)
+		return;
+
+	pr_debug("%s\n", __func__);
+
+	__mdp3_dispatch_dma_done(session);
+}
+
 static void mdp3_dispatch_dma_done(struct kthread_work *work)
 {
 	struct mdp3_session_data *session;
-	int cnt = 0;
 
 	pr_debug("%s\n", __func__);
 	session = container_of(work, struct mdp3_session_data,
@@ -164,14 +186,7 @@
 	if (!session)
 		return;
 
-	cnt = atomic_read(&session->dma_done_cnt);
-	MDSS_XLOG(cnt);
-	while (cnt > 0) {
-		mdp3_ctrl_notify(session, MDP_NOTIFY_FRAME_DONE);
-		atomic_dec(&session->dma_done_cnt);
-		mdp3_ctrl_notify(session, MDP_NOTIFY_FRAME_CTX_DONE);
-		cnt--;
-	}
+	__mdp3_dispatch_dma_done(session);
 }
 
 static void mdp3_dispatch_clk_off(struct work_struct *work)
@@ -3202,7 +3217,8 @@
 		pr_err("fail to init dma\n");
 		goto init_done;
 	}
-
+	mdp3_session->dma->session = mdp3_session;
+	
 	intf_type = mdp3_ctrl_get_intf_type(mfd);
 	mdp3_session->intf = mdp3_get_display_intf(intf_type);
 	if (!mdp3_session->intf) {
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.h b/drivers/video/msm/mdss/mdp3_ctrl.h
index 38766c9..ad6e46f 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.h
+++ b/drivers/video/msm/mdss/mdp3_ctrl.h
@@ -90,6 +90,7 @@
 
 void mdp3_bufq_deinit(struct mdp3_buffer_queue *bufq, int client);
 int mdp3_ctrl_init(struct msm_fb_data_type *mfd);
+void mdp3_flush_dma_done(struct mdp3_session_data *mdp3_session);
 int mdp3_bufq_push(struct mdp3_buffer_queue *bufq,
 			struct mdp3_img_data *data);
 int mdp3_ctrl_get_source_format(u32 imgType);
diff --git a/drivers/video/msm/mdss/mdp3_dma.c b/drivers/video/msm/mdss/mdp3_dma.c
index eb37e71..a6a5ad4 100644
--- a/drivers/video/msm/mdss/mdp3_dma.c
+++ b/drivers/video/msm/mdss/mdp3_dma.c
@@ -1146,6 +1146,16 @@
 
 	reinit_completion(&dma->dma_comp);
 	dma->vsync_client.handler = NULL;
+
+	/*
+	 * Interrupts are disabled.
+	 * Check for blocked dma done interrupt.
+	 * Flush items waiting for dma done interrupt.
+	 */
+	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD &&
+		atomic_read(&dma->session->dma_done_cnt))
+		mdp3_flush_dma_done(dma->session);
+
 	return ret;
 }
 
diff --git a/drivers/video/msm/mdss/mdp3_dma.h b/drivers/video/msm/mdss/mdp3_dma.h
index c0391e3..60b4abd 100644
--- a/drivers/video/msm/mdss/mdp3_dma.h
+++ b/drivers/video/msm/mdss/mdp3_dma.h
@@ -292,6 +292,8 @@
 	struct fb_cmap *gc_cmap;
 	struct fb_cmap *hist_cmap;
 
+	struct mdp3_session_data *session;
+
 	bool (*busy)(void);
 
 	int (*dma_config)(struct mdp3_dma *dma,
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index 35319b82..db1d13d 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -1929,7 +1929,7 @@
 	ret = mfd->mdp.off_fnc(mfd);
 	if (ret)
 		mfd->panel_power_state = cur_power_state;
-	else if (mdss_panel_is_power_off(req_power_state))
+	else if (!mdss_panel_is_power_on_interactive(req_power_state))
 		mdss_fb_release_fences(mfd);
 	mfd->op_enable = true;
 	complete(&mfd->power_off_comp);