msm camera: snapshot wavelet denoise support

Signed-off-by: Mingcheng Zhu <mingchen@codeaurora.org>
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index 1babb9e..6dca569 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -193,7 +193,7 @@
 }
 
 /*send open command to server*/
-static int msm_send_open_server(void)
+static int msm_send_open_server(int vnode_id)
 {
 	int rc = 0;
 	struct msm_ctrl_cmd ctrlcmd;
@@ -202,6 +202,7 @@
 	ctrlcmd.timeout_ms = 10000;
 	ctrlcmd.length	 = 0;
 	ctrlcmd.value    = NULL;
+	ctrlcmd.vnode_id = vnode_id;
 
 	/* send command to config thread in usersspace, and get return value */
 	rc = msm_server_control(&g_server_dev, &ctrlcmd);
@@ -209,7 +210,7 @@
 	return rc;
 }
 
-static int msm_send_close_server(void)
+static int msm_send_close_server(int vnode_id)
 {
 	int rc = 0;
 	struct msm_ctrl_cmd ctrlcmd;
@@ -218,6 +219,7 @@
 	ctrlcmd.timeout_ms = 10000;
 	ctrlcmd.length	 = 0;
 	ctrlcmd.value    = NULL;
+	ctrlcmd.vnode_id = vnode_id;
 
 	/* send command to config thread in usersspace, and get return value */
 	rc = msm_server_control(&g_server_dev, &ctrlcmd);
@@ -253,6 +255,7 @@
 	ctrlcmd.length     = MSM_V4L2_DIMENSION_SIZE;
 	ctrlcmd.value      = (void *)pfmt->fmt.pix.priv;
 	ctrlcmd.timeout_ms = 10000;
+	ctrlcmd.vnode_id   = pcam->vnode_id;
 
 	/* send command to config thread in usersspace, and get return value */
 	rc = msm_server_control(&g_server_dev, &ctrlcmd);
@@ -591,13 +594,38 @@
 {
 	int rc = 0;
 	struct msm_cam_v4l2_device *pcam  = video_drvdata(f);
+	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	pcam_inst = container_of(f->private_data,
+		struct msm_cam_v4l2_dev_inst, eventHandle);
 
 	D("%s\n", __func__);
+
 	WARN_ON(pctx != f->private_data);
 	mutex_lock(&pcam->vid_lock);
-	if (ctrl->id == MSM_V4L2_PID_CAM_MODE)
-		pcam->op_mode = ctrl->value;
-	rc = msm_server_s_ctrl(pcam, ctrl);
+	switch (ctrl->id) {
+	case MSM_V4L2_PID_MMAP_INST:
+		pr_err("%s: mmap_inst=(0x%p, %d)\n",
+			 __func__, pcam_inst, pcam->remap_index);
+		pcam->remap_index = pcam_inst->my_index;
+		break;
+	case MSM_V4L2_PID_MMAP_ENTRY:
+		if (copy_from_user(&pcam->mmap_entry,
+						(void *)ctrl->value,
+						sizeof(pcam->mmap_entry))) {
+			rc = -EFAULT;
+		} else
+			pr_err("%s:mmap entry:phy=0x%x,image_mode=%d,op_mode=%d\n",
+				__func__, pcam->mmap_entry.phy_addr,
+				pcam->mmap_entry.image_mode,
+				pcam->mmap_entry.op_mode);
+
+		break;
+	default:
+		if (ctrl->id == MSM_V4L2_PID_CAM_MODE)
+			pcam->op_mode = ctrl->value;
+		rc = msm_server_s_ctrl(pcam, ctrl);
+		break;
+	}
 	mutex_unlock(&pcam->vid_lock);
 
 	return rc;
@@ -1311,7 +1339,7 @@
 
 
 	if (pcam->use_count == 1) {
-		rc = msm_send_open_server();
+		rc = msm_send_open_server(pcam->vnode_id);
 		if (rc < 0) {
 			mutex_unlock(&pcam->vid_lock);
 			pr_err("%s failed\n", __func__);
@@ -1323,6 +1351,37 @@
 	return rc;
 }
 
+static int msm_addr_remap(struct msm_cam_v4l2_dev_inst *pcam_inst,
+						  struct vm_area_struct *vma,
+						  struct msm_mmap_entry *entry)
+{
+	int phyaddr;
+	int retval;
+	unsigned long size;
+
+	phyaddr = (int)entry->phy_addr;
+	pr_err("%s: phy_addr=0x%x\n", __func__, (uint32_t)phyaddr);
+	size = vma->vm_end - vma->vm_start;
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+	retval = remap_pfn_range(vma, vma->vm_start,
+			phyaddr >> PAGE_SHIFT,
+			size, vma->vm_page_prot);
+	if (retval) {
+		pr_err("%s:mmap: remap failed with error %d. ",
+			   __func__, retval);
+		goto error;
+	}
+	pr_err("%s:mmap: phy_addr=0x%x: %08lx-%08lx, pgoff %08lx\n",
+		   __func__, (uint32_t)phyaddr,
+		   vma->vm_start, vma->vm_end, vma->vm_pgoff);
+	memset(entry, 0, sizeof(struct msm_mmap_entry));
+	return 0;
+error:
+	pr_err("%s:ret=%d\n", __func__, retval);
+	memset(entry, 0, sizeof(struct msm_mmap_entry));
+	return -ENOMEM;
+}
+
 static int msm_mmap(struct file *f, struct vm_area_struct *vma)
 {
 	int rc = 0;
@@ -1332,7 +1391,17 @@
 
 	D("mmap called, vma=0x%08lx\n", (unsigned long)vma);
 
-	rc = vb2_mmap(&pcam_inst->vid_bufq, vma);
+	if (pcam_inst->pcam->remap_index ==
+		pcam_inst->my_index &&
+		pcam_inst->pcam->mmap_entry.phy_addr) {
+		pr_err("%s: ioremap called, vma=0x%08lx\n",
+			 __func__, (unsigned long)vma);
+		rc = msm_addr_remap(pcam_inst, vma,
+						  &pcam_inst->pcam->mmap_entry);
+		pr_err("%s: msm_addr_remap ret=%d\n", __func__, rc);
+		return rc;
+	} else
+		rc = vb2_mmap(&pcam_inst->vid_bufq, vma);
 	D("vma start=0x%08lx, size=%ld, ret=%d\n",
 		(unsigned long)vma->vm_start,
 		(unsigned long)vma->vm_end - (unsigned long)vma->vm_start,
@@ -1358,6 +1427,11 @@
 
 	mutex_lock(&pcam->vid_lock);
 	pcam->use_count--;
+	if (pcam_inst->pcam->remap_index ==
+		pcam_inst->my_index) {
+		pcam_inst->pcam->remap_index = 0;
+		memset(&pcam->mmap_entry, 0, sizeof(pcam->mmap_entry));
+	}
 	pcam->dev_inst_map[pcam_inst->image_mode] = NULL;
 	vb2_queue_release(&pcam_inst->vid_bufq);
 	pcam->dev_inst[pcam_inst->my_index] = NULL;
@@ -1381,7 +1455,7 @@
 		if (rc < 0)
 			pr_err("msm_cam_server_close_session fails %d\n", rc);
 
-		rc = msm_send_close_server();
+		rc = msm_send_close_server(pcam->vnode_id);
 		if (rc < 0)
 			pr_err("msm_send_close_server failed %d\n", rc);
 
@@ -1689,7 +1763,8 @@
 		if (copy_from_user(&ev, (void __user *)arg,
 				sizeof(struct v4l2_event)))
 			break;
-		u_isp_event = (struct msm_isp_stats_event_ctrl *)ev.u.data;
+		u_isp_event =
+			(struct msm_isp_stats_event_ctrl *)ev.u.data;
 		u_msg_value = u_isp_event->isp_data.isp_msg.data;
 
 		rc = v4l2_event_dequeue(
@@ -1699,21 +1774,24 @@
 			pr_err("no pending events?");
 			break;
 		}
-
-		k_isp_event = (struct msm_isp_stats_event_ctrl *)ev.u.data;
-		if (ev.type ==
-			V4L2_EVENT_PRIVATE_START+MSM_CAM_RESP_STAT_EVT_MSG &&
-			k_isp_event->isp_data.isp_msg.len > 0) {
-			void *k_msg_value = k_isp_event->isp_data.isp_msg.data;
-			if (copy_to_user(u_msg_value, k_msg_value,
-				k_isp_event->isp_data.isp_msg.len)) {
-				rc = -EINVAL;
-				break;
+		if (ev.type != (V4L2_EVENT_PRIVATE_START +
+				MSM_CAM_RESP_DIV_FRAME_EVT_MSG)) {
+			k_isp_event =
+			(struct msm_isp_stats_event_ctrl *)ev.u.data;
+			if (ev.type == (V4L2_EVENT_PRIVATE_START +
+				MSM_CAM_RESP_STAT_EVT_MSG) &&
+				k_isp_event->isp_data.isp_msg.len > 0) {
+				void *k_msg_value =
+					k_isp_event->isp_data.isp_msg.data;
+				if (copy_to_user(u_msg_value, k_msg_value,
+					k_isp_event->isp_data.isp_msg.len)) {
+					rc = -EINVAL;
+					break;
+				}
+				kfree(k_msg_value);
 			}
-			kfree(k_msg_value);
+			k_isp_event->isp_data.isp_msg.data = u_msg_value;
 		}
-		k_isp_event->isp_data.isp_msg.data = u_msg_value;
-
 		if (copy_to_user((void __user *)arg, &ev,
 				sizeof(struct v4l2_event))) {
 			rc = -EINVAL;
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index 15ed7fe..60172fc 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -94,6 +94,7 @@
 
 struct msm_cam_v4l2_device;
 struct msm_cam_v4l2_dev_inst;
+#define MSM_MAX_IMG_MODE                8
 
 /* buffer for one video frame */
 struct msm_frame_buffer {
@@ -139,6 +140,19 @@
 
 extern int msm_ispif_init_module(struct msm_ispif_ops *p_ispif);
 
+struct msm_free_buf {
+	uint32_t paddr;
+	uint32_t y_off;
+	uint32_t cbcr_off;
+};
+
+struct msm_mctl_pp_info {
+	spinlock_t lock;
+	uint32_t cnt;
+	uint32_t pp_key;
+	uint32_t cur_frame_id[MSM_MAX_IMG_MODE];
+	struct msm_free_buf div_frame[MSM_MAX_IMG_MODE];
+};
 /* "Media Controller" represents a camera steaming session,
  * which consists of a "sensor" device and an "isp" device
  * (such as VFE, if needed), connected via an "IO" device,
@@ -179,7 +193,7 @@
 	struct msm_ispif_fns *ispif_fns;
 
 	struct pm_qos_request_list pm_qos_req_list;
-	uint32_t pp_key;
+	struct msm_mctl_pp_info pp_info;
 };
 
 /* abstract camera device represents a VFE and connected sensor */
@@ -206,11 +220,7 @@
 	unsigned long buffer;
 	int fd;
 };
-struct msm_free_buf {
-	uint32_t paddr;
-	uint32_t y_off;
-	uint32_t cbcr_off;
-};
+
 #define MSM_DEV_INST_MAX                    16
 struct msm_cam_v4l2_dev_inst {
 	struct v4l2_fh  eventHandle;
@@ -230,7 +240,6 @@
 	struct v4l2_crop crop;
 	int streamon;
 };
-#define MSM_MAX_IMG_MODE                5
 /* abstract camera device for each sensor successfully probed*/
 struct msm_cam_v4l2_device {
 	/* standard device interfaces */
@@ -287,6 +296,8 @@
 	uint8_t ctrl_data[max_control_command_size];
 	struct msm_ctrl_cmd ctrl;
 	uint32_t event_mask;
+	struct msm_mmap_entry mmap_entry;
+	int remap_index;
 };
 static inline struct msm_cam_v4l2_device *to_pcam(
 	struct v4l2_device *v4l2_dev)
@@ -359,9 +370,7 @@
 int msm_mctl_buf_done(struct msm_cam_media_controller *pmctl,
 			int msg_type, uint32_t y_phy, uint32_t frame_id);
 int msm_mctl_buf_done_pp(struct msm_cam_media_controller *pmctl,
-					int msg_type, uint32_t y_phy,
-					uint32_t frame_id,
-					struct timeval *timestamp);
+			int msg_type, struct msm_free_buf *frame, int dirty);
 int msm_mctl_reserve_free_buf(struct msm_cam_media_controller *pmctl,
 				int path, struct msm_free_buf *free_buf);
 int msm_mctl_release_free_buf(struct msm_cam_media_controller *pmctl,
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index 739d027..05b1742 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -204,40 +204,67 @@
 static int msm_mctl_set_pp_key(struct msm_cam_media_controller *p_mctl,
 				void __user *arg)
 {
-	if (copy_from_user(&p_mctl->pp_key, arg, sizeof(p_mctl->pp_key)))
-		return -EFAULT;
-	return 0;
+	int rc = 0;
+	unsigned long flags;
+	spin_lock_irqsave(&p_mctl->pp_info.lock, flags);
+	if (copy_from_user(&p_mctl->pp_info.pp_key,
+			arg, sizeof(p_mctl->pp_info.pp_key)))
+		rc = -EFAULT;
+	else
+		D("%s: mctl=0x%p, pp_key_setting=0x%x",
+			__func__, p_mctl, p_mctl->pp_info.pp_key);
+
+	spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
+	return rc;
 }
 
 static int msm_mctl_pp_done(struct msm_cam_media_controller *p_mctl,
 				void __user *arg)
 {
-	struct msm_buffer buf;
-	int msg_type;
+	struct msm_frame frame;
+	int msg_type, image_mode, rc = 0;
+	int dirty = 0;
+	struct msm_free_buf buf;
+	unsigned long flags;
 
-	if (copy_from_user(&buf, arg, sizeof(struct msm_buffer)))
+	if (copy_from_user(&frame, arg, sizeof(frame)))
 		return -EFAULT;
-
-	switch (buf.path) {
+	spin_lock_irqsave(&p_mctl->pp_info.lock, flags);
+	switch (frame.path) {
 	case OUTPUT_TYPE_P:
-		if (!(p_mctl->pp_key & PP_PREV))
-			return -EFAULT;
+		if (!(p_mctl->pp_info.pp_key & PP_PREV)) {
+			rc = -EFAULT;
+			goto err;
+		}
 		msg_type = VFE_MSG_OUTPUT_P;
+		image_mode = MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW;
 		break;
 	case OUTPUT_TYPE_S:
-		if (!(p_mctl->pp_key & (PP_SNAP|PP_RAW_SNAP)))
+		if (!(p_mctl->pp_info.pp_key & PP_SNAP))
 			return -EFAULT;
 		msg_type = VFE_MSG_OUTPUT_S;
+		image_mode = MSM_V4L2_EXT_CAPTURE_MODE_MAIN;
 		break;
 	case OUTPUT_TYPE_T:
 	case OUTPUT_TYPE_V:
 	default:
-		return -EFAULT;
+		rc = -EFAULT;
+		goto err;
 	}
+	memcpy(&buf, &p_mctl->pp_info.div_frame[image_mode], sizeof(buf));
+	memset(&p_mctl->pp_info.div_frame[image_mode], 0, sizeof(buf));
+	if (p_mctl->pp_info.cur_frame_id[image_mode] !=
+					frame.frame_id) {
+		/* dirty frame. should not pass to app */
+		dirty = 1;
+	}
+	spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
 	/* here buf.addr is phy_addr */
-	return msm_mctl_buf_done_pp(p_mctl, msg_type,
-					buf.planes[0].addr,
-					buf.frame_id, &buf.timestamp);
+	rc = msm_mctl_buf_done_pp(p_mctl, msg_type, &buf, dirty);
+	return rc;
+err:
+	spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
+	return rc;
 }
 
 /* called by the server or the config nodes to handle user space
@@ -479,6 +506,8 @@
 	pmctl->plat_dev = pcam->pdev;
 	/* init mctl buf */
 	msm_mctl_buf_init(pcam);
+	memset(&pmctl->pp_info, 0, sizeof(pmctl->pp_info));
+	spin_lock_init(&pmctl->pp_info.lock);
 	/* init sub device*/
 	v4l2_subdev_init(&(pmctl->mctl_sdev), &mctl_subdev_ops);
 	v4l2_set_subdevdata(&(pmctl->mctl_sdev), pmctl);
diff --git a/drivers/media/video/msm/msm_mctl_buf.c b/drivers/media/video/msm/msm_mctl_buf.c
index 1694ff7..361b612 100644
--- a/drivers/media/video/msm/msm_mctl_buf.c
+++ b/drivers/media/video/msm/msm_mctl_buf.c
@@ -429,7 +429,7 @@
 		struct msm_cam_media_controller *pmctl,
 		struct msm_cam_v4l2_dev_inst *pcam_inst,
 		int msg_type, uint32_t y_phy,
-		uint32_t frame_id, struct timeval *timestamp)
+		uint32_t *frame_id, int gen_timestamp)
 {
 	struct msm_frame_buffer *buf = NULL;
 	int del_buf = 1;
@@ -441,11 +441,12 @@
 			__func__, y_phy);
 		return -EINVAL;
 	}
-	if (!timestamp)
+	if (gen_timestamp) {
+		if (frame_id)
+			buf->vidbuf.v4l2_buf.sequence = *frame_id;
 		msm_mctl_gettimeofday(
 			&buf->vidbuf.v4l2_buf.timestamp);
-	else
-		buf->vidbuf.v4l2_buf.timestamp = *timestamp;
+	}
 	vb2_buffer_done(&buf->vidbuf, VB2_BUF_STATE_DONE);
 	return 0;
 }
@@ -453,31 +454,25 @@
 static int msm_mctl_buf_divert(
 			struct msm_cam_media_controller *pmctl,
 			struct msm_cam_v4l2_dev_inst *pcam_inst,
-			struct msm_buffer **buf)
+			struct msm_cam_evt_divert_frame *div)
 {
 	struct v4l2_event v4l2_evt;
-	struct msm_isp_stats_event_ctrl *isp_event;
-
+	struct msm_cam_evt_divert_frame *tmp;
 	memset(&v4l2_evt, 0, sizeof(v4l2_evt));
-	isp_event =
-		(struct msm_isp_stats_event_ctrl *)v4l2_evt.u.data;
-	D("%s inst = %p, image_mode = %d, frame_id=%d\n",
-	__func__, pcam_inst, pcam_inst->image_mode, (*buf)->frame_id);
 	v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
-			  MSM_CAM_RESP_DIV_FRAME_EVT_MSG;
-	isp_event->resptype = MSM_CAM_RESP_DIV_FRAME_EVT_MSG;
-	isp_event->isp_data.div_frame.image_mode = pcam_inst->image_mode;
-	isp_event->isp_data.div_frame.op_mode = pcam_inst->pcam->op_mode;
-	isp_event->isp_data.div_frame.node_idx = pcam_inst->pcam->vnode_id;
-	isp_event->isp_data.div_frame.inst_idx = pcam_inst->my_index;
-	isp_event->isp_data.div_frame.len = sizeof(struct msm_buffer);
-	isp_event->isp_data.div_frame.data = *buf;
-	*buf = NULL;
-	/* now queue the event */
-	v4l2_event_queue(pmctl->config_device->config_stat_event_queue.pvdev,
-					&v4l2_evt);
+			MSM_CAM_RESP_DIV_FRAME_EVT_MSG;
+	memcpy(&v4l2_evt.u.data[0], div,
+			sizeof(struct msm_cam_evt_divert_frame));
+	D("%s inst=%p, img_mode=%d, frame_id=%d,phy=0x%x,len=%d\n",
+		__func__, pcam_inst, pcam_inst->image_mode, div->frame_id,
+		(uint32_t)div->phy_addr, div->length);
+	tmp = (struct msm_cam_evt_divert_frame *)&v4l2_evt.u.data[0];
+	v4l2_event_queue(
+		pmctl->config_device->config_stat_event_queue.pvdev,
+		&v4l2_evt);
 	return 0;
 }
+
 int msm_mctl_buf_done(struct msm_cam_media_controller *p_mctl,
 			int msg_type, uint32_t y_phy, uint32_t frame_id)
 {
@@ -485,80 +480,84 @@
 	struct msm_cam_v4l2_dev_inst *pcam_inst;
 	int idx;
 	int del_buf = 0;
+	int image_mode = MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT;
+	unsigned long flags;
+	int path = 0;
+
 
 	idx = msm_mctl_out_type_to_inst_index(
 					p_mctl->sync.pcam_sync, msg_type);
 	pcam_inst = p_mctl->sync.pcam_sync->dev_inst[idx];
-
 	switch (msg_type) {
 	case VFE_MSG_OUTPUT_P:
 		pp_key = PP_PREV;
+		image_mode = MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW;
+		path = OUTPUT_TYPE_P;
 		break;
 	case VFE_MSG_OUTPUT_S:
 		pp_key = PP_SNAP;
+		image_mode = MSM_V4L2_EXT_CAPTURE_MODE_MAIN;
+		path = OUTPUT_TYPE_S;
 		break;
 	case VFE_MSG_OUTPUT_T:
-		pp_key = OUTPUT_TYPE_T;
-		break;
 	default:
+	  path = OUTPUT_TYPE_T;
 		break;
 	}
-	if (p_mctl->pp_key & pp_key) {
-		/* need divert to pp */
-		struct msm_buffer *buf;
+	spin_lock_irqsave(&p_mctl->pp_info.lock, flags);
+	if (p_mctl->pp_info.pp_key & pp_key) {
+		int rc = 0;
+		struct msm_cam_evt_divert_frame div;
 		struct msm_frame_buffer *vb = NULL;
 		struct videobuf2_contig_pmem *mem;
 
-		buf = kmalloc(sizeof(struct msm_buffer), GFP_ATOMIC);
-		if (!buf) {
-			pr_err("%s:no mem\n", __func__);
-			return -ENOMEM;
+		p_mctl->pp_info.cur_frame_id[image_mode]++;
+		if (!p_mctl->pp_info.cur_frame_id[image_mode])
+			p_mctl->pp_info.cur_frame_id[image_mode] = 1;
+		if (!p_mctl->pp_info.div_frame[image_mode].paddr) {
+			/* no frame in postproc. good to divert the frame up */
+			memset(&div, 0, sizeof(div));
+			vb = msm_mctl_buf_find(p_mctl, pcam_inst,
+					del_buf, msg_type, y_phy);
+			if (!vb) {
+				spin_unlock_irqrestore(&p_mctl->pp_info.lock,
+					flags);
+				return -EINVAL;
+			}
+			vb->vidbuf.v4l2_buf.sequence = frame_id;
+			mem = vb2_plane_cookie(&vb->vidbuf, 0);
+			div.image_mode = pcam_inst->image_mode;
+			div.op_mode    = pcam_inst->pcam->op_mode;
+			div.inst_idx   = pcam_inst->my_index;
+			div.node_idx   = pcam_inst->pcam->vnode_id;
+			div.phy_addr   =
+				videobuf2_to_pmem_contig(&vb->vidbuf, 0);
+			div.phy_offset = mem->addr_offset;
+			div.y_off      = mem->y_off;
+			div.cbcr_off   = mem->cbcr_off;
+			div.fd         = (int)mem->vaddr;
+			div.frame_id   =
+				p_mctl->pp_info.cur_frame_id[image_mode];
+			div.path       = path;
+			div.length     = mem->size;
+			msm_mctl_gettimeofday(&div.timestamp);
+			vb->vidbuf.v4l2_buf.timestamp = div.timestamp;
+			p_mctl->pp_info.div_frame[image_mode].paddr =
+				div.phy_addr;
+			p_mctl->pp_info.div_frame[image_mode].y_off =
+				div.y_off;
+			p_mctl->pp_info.div_frame[image_mode].cbcr_off =
+				div.cbcr_off;
+			rc = msm_mctl_buf_divert(p_mctl, pcam_inst, &div);
+			spin_unlock_irqrestore(&p_mctl->pp_info.lock,
+				flags);
+			return rc;
 		}
-		vb = msm_mctl_buf_find(p_mctl, pcam_inst,
-				del_buf, msg_type, y_phy);
-		if (!vb)
-			return -EINVAL;
-		mem = vb2_plane_cookie(&vb->vidbuf, 0);
-		msm_mctl_gettimeofday(&buf->timestamp);
-		buf->frame_id = frame_id;
-		buf->path = mem->buffer_type;
-		buf->num = 2;
-		buf->memory_type = mem->is_userptr;
-		buf->planes[0].type = MSM_PLANE_Y;
-		buf->planes[0].offset = mem->y_off;
-		buf->planes[0].length = mem->cbcr_off;
-		buf->planes[0].addr =
-			(unsigned long)videobuf2_to_pmem_contig(&vb->vidbuf, 0);
-		buf->planes[0].addr_offset = mem->addr_offset;
-		buf->planes[0].fd = (int)mem->vaddr;
-		buf->planes[1].type = MSM_PLANE_UV;
-		buf->planes[1].offset = mem->cbcr_off;
-		/* this is a hack for single plane case.
-			need cleanup when moving to rael multi-planner */
-		buf->planes[1].length = mem->size;
-		buf->planes[1].addr =
-			(unsigned long)videobuf2_to_pmem_contig(&vb->vidbuf, 0);
-		buf->planes[1].addr_offset = mem->addr_offset;
-		buf->planes[1].fd = (int)mem->vaddr;
-		return msm_mctl_buf_divert(p_mctl, pcam_inst, &buf);
-	} else
-		return msm_mctl_buf_done_proc(p_mctl, pcam_inst,
+	}
+	spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
+	return msm_mctl_buf_done_proc(p_mctl, pcam_inst,
 							msg_type, y_phy,
-							frame_id, NULL);
-}
-
-int msm_mctl_buf_done_pp(struct msm_cam_media_controller *pmctl,
-				int msg_type, uint32_t y_phy,
-				uint32_t frame_id, struct timeval *timestamp)
-{
-	struct msm_cam_v4l2_dev_inst *pcam_inst;
-	int idx;
-
-	idx = msm_mctl_out_type_to_inst_index(
-		pmctl->sync.pcam_sync, msg_type);
-	pcam_inst = pmctl->sync.pcam_sync->dev_inst[idx];
-	return msm_mctl_buf_done_proc(pmctl, pcam_inst,
-			msg_type, y_phy, frame_id, timestamp);
+							&frame_id, 1);
 }
 
 int msm_mctl_buf_init(struct msm_cam_v4l2_device *pcam)
@@ -582,10 +581,12 @@
 		return rc;
 	}
 	memset(free_buf, 0, sizeof(struct msm_free_buf));
-	idx = msm_mctl_out_type_to_inst_index(pmctl->sync.pcam_sync, msg_type);
+	idx = msm_mctl_out_type_to_inst_index(pmctl->sync.pcam_sync,
+		msg_type);
 	pcam_inst = pmctl->sync.pcam_sync->dev_inst[idx];
 	if (!pcam_inst->streamon) {
-		pr_err("%s: stream 0x%p is off\n", __func__, pcam_inst);
+		pr_err("%s: stream 0x%p is off\n",
+			__func__, pcam_inst);
 		return rc;
 	}
 	spin_lock_irqsave(&pcam_inst->vq_irqlock, flags);
@@ -653,3 +654,24 @@
 	return rc;
 }
 
+int msm_mctl_buf_done_pp(
+		struct msm_cam_media_controller *pmctl,
+		int msg_type, struct msm_free_buf *frame, int dirty)
+{
+	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	int idx, rc = 0;
+
+	idx = msm_mctl_out_type_to_inst_index(
+		pmctl->sync.pcam_sync, msg_type);
+	pcam_inst = pmctl->sync.pcam_sync->dev_inst[idx];
+	D("%s:inst=0x%p, paddr=0x%x, dirty=%d",
+		__func__, pcam_inst, frame->paddr, dirty);
+	if (dirty)
+		/* the frame is dirty, not going to disptach to app */
+		rc = msm_mctl_release_free_buf(pmctl, msg_type, frame);
+	else
+		rc = msm_mctl_buf_done_proc(pmctl, pcam_inst,
+			msg_type, frame->paddr, NULL, 0);
+	return rc;
+}
+
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index a5d4b06..0bd42f7 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -190,12 +190,19 @@
 };
 
 struct msm_cam_evt_divert_frame {
-	uint32_t image_mode;
-	uint32_t op_mode;
+	unsigned short image_mode;
+	unsigned short op_mode;
 	unsigned short inst_idx;
 	unsigned short node_idx;
-	unsigned int len;
-	void *data;
+	unsigned long  phy_addr;
+	uint32_t       phy_offset;
+	uint32_t       y_off;
+	uint32_t       cbcr_off;
+	int32_t        fd;
+	uint32_t       frame_id;
+	int            path;
+	uint32_t       length;
+	struct timeval timestamp;
 };
 
 struct msm_isp_stats_event_ctrl {
@@ -203,7 +210,6 @@
 	union {
 		struct msm_cam_evt_msg isp_msg;
 		struct msm_ctrl_cmd ctrl;
-		struct msm_cam_evt_divert_frame div_frame;
 	} isp_data;
 };
 
@@ -465,6 +471,14 @@
 	int info_len;
 };
 
+struct msm_mmap_entry {
+	uint32_t image_mode;/* extended mode */
+	uint32_t op_mode;	/* operation mode, video, capture */
+	uint32_t vnode_idx;	/* dev node idx */
+	uint32_t phy_addr;	/* phy address: TBD: to be dropped */
+	uint32_t idx;		/* v4l2 buffer index */
+};
+
 #define MSM_MEM_MMAP		0
 #define MSM_MEM_USERPTR		1
 #define MSM_PLANE_MAX		8
@@ -595,8 +609,10 @@
 #define MSM_V4L2_PID_SNOW_DETECTION         (V4L2_CID_PRIVATE_BASE+12)
 #define MSM_V4L2_PID_CTRL_CMD               (V4L2_CID_PRIVATE_BASE+13)
 #define MSM_V4L2_PID_EVT_SUB_INFO           (V4L2_CID_PRIVATE_BASE+14)
-#define MSM_V4L2_PID_STROBE_FLASH	    (V4L2_CID_PRIVATE_BASE+15)
-#define MSM_V4L2_PID_MAX                    MSM_V4L2_PID_STROBE_FLASH
+#define MSM_V4L2_PID_STROBE_FLASH           (V4L2_CID_PRIVATE_BASE+15)
+#define MSM_V4L2_PID_MMAP_ENTRY             (V4L2_CID_PRIVATE_BASE+16)
+#define MSM_V4L2_PID_MMAP_INST              (V4L2_CID_PRIVATE_BASE+17)
+#define MSM_V4L2_PID_MAX                    MSM_V4L2_PID_MMAP_INST
 
 /* camera operation mode for video recording - two frame output queues */
 #define MSM_V4L2_CAM_OP_DEFAULT         0