msm: camera: Add support for instance handle based buffer lookup.

Currently when VFE requests for a free buffer, we search based
on the image mode sent from VFE. In some cases, there can be
multiple instances with the same image mode. This means the
buffer lookup logic has to take into consideration other
parameters like current usecase, vfe operation mode etc.
To ease this, add support for buffer lookup based on
the instance handle. The instance handle contains information
about where to get the buffer from. So the buffer lookup
logic does not have to know about other details. The instance
handle is decided when the user sets the format for a particular
instance. It is passed on to the VFE during AXI configuration.
VFE stores this and sends it whenever it requests for a free
buffer for a particular output.
Keep the current image_mode based buffer lookup logic for
legacy targets.

Change-Id: I78c3db77ac4014365c9866ff780ec71ac4c7ff87
Signed-off-by: Kiran Kumar H N <hurlisal@codeaurora.org>
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index d9ede7a..eb8acb8 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -92,6 +92,33 @@
 	return rc;
 }
 
+static int msm_camera_v4l2_private_g_ctrl(struct file *f, void *pctx,
+	struct msm_camera_v4l2_ioctl_t *ioctl_ptr)
+{
+	int rc = -EINVAL;
+	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);
+
+	WARN_ON(pctx != f->private_data);
+
+	mutex_lock(&pcam->vid_lock);
+	switch (ioctl_ptr->id) {
+	case MSM_V4L2_PID_INST_HANDLE:
+		COPY_TO_USER(rc, (void __user *)ioctl_ptr->ioctl_ptr,
+			(void *)&pcam_inst->inst_handle, sizeof(uint32_t));
+		if (rc)
+			ERR_COPY_TO_USER();
+		break;
+	default:
+		pr_err("%s Unsupported ioctl %d ", __func__, ioctl_ptr->id);
+		break;
+	}
+	mutex_unlock(&pcam->vid_lock);
+	return rc;
+}
+
 static int msm_camera_v4l2_g_ctrl(struct file *f, void *pctx,
 					struct v4l2_control *c)
 {
@@ -686,7 +713,9 @@
 	struct msm_cam_v4l2_dev_inst *pcam_inst;
 	pcam_inst = container_of(f->private_data,
 		struct msm_cam_v4l2_dev_inst, eventHandle);
-	pcam_inst->image_mode = a->parm.capture.extendedmode;
+	pcam_inst->image_mode = (a->parm.capture.extendedmode & 0x7F);
+	SET_IMG_MODE(pcam_inst->inst_handle, pcam_inst->image_mode);
+	SET_VIDEO_INST_IDX(pcam_inst->inst_handle, pcam_inst->my_index);
 	pcam_inst->pcam->dev_inst_map[pcam_inst->image_mode] = pcam_inst;
 	pcam_inst->path = msm_vidbuf_get_path(pcam_inst->image_mode);
 	D("%spath=%d,rc=%d\n", __func__,
@@ -745,6 +774,12 @@
 	case MSM_CAM_V4L2_IOCTL_PRIVATE_S_CTRL:
 		rc = msm_camera_v4l2_private_s_ctrl(file, fh, ioctl_ptr);
 		break;
+	case MSM_CAM_V4L2_IOCTL_PRIVATE_G_CTRL:
+		rc = msm_camera_v4l2_private_g_ctrl(file, fh, ioctl_ptr);
+		break;
+	default:
+		pr_err("%s Unsupported ioctl cmd %d ", __func__, cmd);
+		break;
 	}
 	return rc;
 }
@@ -1055,6 +1090,8 @@
 		v4l2_fh_del(&pcam_inst->eventHandle);
 		v4l2_fh_exit(&pcam_inst->eventHandle);
 	}
+	CLR_VIDEO_INST_IDX(pcam_inst->inst_handle);
+	CLR_IMG_MODE(pcam_inst->inst_handle);
 	mutex_unlock(&pcam_inst->inst_lock);
 	mutex_destroy(&pcam_inst->inst_lock);
 	kfree(pcam_inst);
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index 5fc2f68..6cd60d3 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -122,7 +122,7 @@
 
 struct msm_free_buf {
 	uint8_t num_planes;
-	int32_t image_mode;
+	uint32_t inst_handle;
 	uint32_t ch_paddr[VIDEO_MAX_PLANES];
 	uint32_t vb;
 };
@@ -323,7 +323,7 @@
 	enum v4l2_mbus_pixelcode sensor_pxlcode;
 	struct msm_cam_v4l2_device *pcam;
 	int my_index;
-	int image_mode;
+	uint32_t image_mode;
 	int path;
 	int buf_count;
 	/* buffer offsets, if any */
@@ -335,6 +335,7 @@
 	struct img_plane_info plane_info;
 	int vbqueue_initialized;
 	struct mutex inst_lock;
+	uint32_t inst_handle;
 };
 
 struct msm_cam_mctl_node {
@@ -547,6 +548,18 @@
 	struct msm_cam_server_irqmap_entry hw_irqmap[CAMERA_SS_IRQ_MAX];
 };
 
+enum msm_cam_buf_lookup_type {
+	BUF_LOOKUP_INVALID,
+	BUF_LOOKUP_BY_IMG_MODE,
+	BUF_LOOKUP_BY_INST_HANDLE,
+};
+
+struct msm_cam_buf_handle {
+	uint16_t buf_lookup_type;
+	uint32_t image_mode;
+	uint32_t inst_handle;
+};
+
 /* ISP related functions */
 void msm_isp_vfe_dev_init(struct v4l2_subdev *vd);
 /*
@@ -562,33 +575,34 @@
 int msm_mctl_buf_init(struct msm_cam_v4l2_device *pcam);
 int msm_mctl_init_user_formats(struct msm_cam_v4l2_device *pcam);
 int msm_mctl_buf_done(struct msm_cam_media_controller *pmctl,
-			int msg_type, struct msm_free_buf *buf,
-			uint32_t frame_id);
+	struct msm_cam_buf_handle *buf_handle,
+	struct msm_free_buf *buf,
+	uint32_t frame_id);
 int msm_mctl_buf_done_pp(struct msm_cam_media_controller *pmctl,
-	int msg_type, struct msm_free_buf *frame, int dirty, int node_type);
+	struct msm_cam_buf_handle *buf_handle,
+	struct msm_free_buf *frame, int dirty, int node_type);
 int msm_mctl_reserve_free_buf(struct msm_cam_media_controller *pmctl,
-				struct msm_cam_v4l2_dev_inst *pcam_inst,
-				int path, struct msm_free_buf *free_buf);
+	struct msm_cam_v4l2_dev_inst *pcam_inst,
+	struct msm_cam_buf_handle *buf_handle,
+	struct msm_free_buf *free_buf);
 int msm_mctl_release_free_buf(struct msm_cam_media_controller *pmctl,
-				struct msm_cam_v4l2_dev_inst *pcam_inst,
-				int path, struct msm_free_buf *free_buf);
+	struct msm_cam_v4l2_dev_inst *pcam_inst,
+	struct msm_free_buf *free_buf);
 /*Memory(PMEM) functions*/
 int msm_register_pmem(struct hlist_head *ptype, void __user *arg,
-				struct ion_client *client);
+	struct ion_client *client);
 int msm_pmem_table_del(struct hlist_head *ptype, void __user *arg,
-				struct ion_client *client);
+	struct ion_client *client);
 int msm_pmem_region_get_phy_addr(struct hlist_head *ptype,
 	struct msm_mem_map_info *mem_map, int32_t *phyaddr);
 uint8_t msm_pmem_region_lookup(struct hlist_head *ptype,
 	int pmem_type, struct msm_pmem_region *reg, uint8_t maxcount);
 uint8_t msm_pmem_region_lookup_2(struct hlist_head *ptype,
-					int pmem_type,
-					struct msm_pmem_region *reg,
-					uint8_t maxcount);
+	int pmem_type, struct msm_pmem_region *reg,
+	uint8_t maxcount);
 unsigned long msm_pmem_stats_vtop_lookup(
-				struct msm_cam_media_controller *mctl,
-				unsigned long buffer,
-				int fd);
+	struct msm_cam_media_controller *mctl,
+	unsigned long buffer, int fd);
 unsigned long msm_pmem_stats_ptov_lookup(
 	struct msm_cam_media_controller *mctl,
 	unsigned long addr, int *fd);
@@ -605,33 +619,25 @@
 int msm_mctl_is_pp_msg_type(struct msm_cam_media_controller *p_mctl,
 	int msg_type);
 int msm_mctl_do_pp(struct msm_cam_media_controller *p_mctl,
-			int msg_type, uint32_t y_phy, uint32_t frame_id);
+	int msg_type, uint32_t y_phy, uint32_t frame_id);
 int msm_mctl_pp_ioctl(struct msm_cam_media_controller *p_mctl,
-			unsigned int cmd, unsigned long arg);
+	unsigned int cmd, unsigned long arg);
 int msm_mctl_pp_notify(struct msm_cam_media_controller *pmctl,
-			struct msm_mctl_pp_frame_info *pp_frame_info);
+	struct msm_mctl_pp_frame_info *pp_frame_info);
 int msm_mctl_img_mode_to_inst_index(struct msm_cam_media_controller *pmctl,
-					int out_type, int node_type);
+	int out_type, int node_type);
 struct msm_frame_buffer *msm_mctl_buf_find(
 	struct msm_cam_media_controller *pmctl,
 	struct msm_cam_v4l2_dev_inst *pcam_inst, int del_buf,
-	int msg_type, struct msm_free_buf *fbuf);
+	struct msm_free_buf *fbuf);
 void msm_mctl_gettimeofday(struct timeval *tv);
-struct msm_frame_buffer *msm_mctl_get_free_buf(
-		struct msm_cam_media_controller *pmctl,
-		int msg_type);
-int msm_mctl_put_free_buf(
-		struct msm_cam_media_controller *pmctl,
-		int msg_type, struct msm_frame_buffer *buf);
 int msm_mctl_check_pp(struct msm_cam_media_controller *p_mctl,
-		int msg_type, int *pp_divert_type, int *pp_type);
+	int msg_type, int *pp_divert_type, int *pp_type);
 int msm_mctl_do_pp_divert(
 	struct msm_cam_media_controller *p_mctl,
-	int msg_type, struct msm_free_buf *fbuf,
+	struct msm_cam_buf_handle *buf_handle,
+	struct msm_free_buf *fbuf,
 	uint32_t frame_id, int pp_type);
-int msm_mctl_buf_del(struct msm_cam_media_controller *pmctl,
-	int msg_type,
-	struct msm_frame_buffer *my_buf);
 int msm_mctl_pp_release_free_frame(
 	struct msm_cam_media_controller *p_mctl,
 	void __user *arg);
@@ -639,7 +645,7 @@
 	struct msm_cam_media_controller *p_mctl,
 	void __user *arg);
 int msm_mctl_set_pp_key(struct msm_cam_media_controller *p_mctl,
-				void __user *arg);
+	void __user *arg);
 int msm_mctl_pp_done(
 	struct msm_cam_media_controller *p_mctl,
 	void __user *arg);
@@ -647,15 +653,15 @@
 	struct msm_cam_media_controller *p_mctl,
 	void __user *arg);
 int msm_setup_v4l2_event_queue(struct v4l2_fh *eventHandle,
-					struct video_device *pvdev);
+	struct video_device *pvdev);
 int msm_setup_mctl_node(struct msm_cam_v4l2_device *pcam);
 struct msm_cam_v4l2_dev_inst *msm_mctl_get_pcam_inst(
-		struct msm_cam_media_controller *pmctl,
-		int image_mode);
+	struct msm_cam_media_controller *pmctl,
+	struct msm_cam_buf_handle *buf_handle);
 int msm_mctl_buf_return_buf(struct msm_cam_media_controller *pmctl,
-			int image_mode, struct msm_frame_buffer *buf);
+	int image_mode, struct msm_frame_buffer *buf);
 int msm_mctl_pp_mctl_divert_done(struct msm_cam_media_controller *p_mctl,
-					void __user *arg);
+	void __user *arg);
 void msm_release_ion_client(struct kref *ref);
 int msm_cam_register_subdev_node(struct v4l2_subdev *sd,
 	struct msm_cam_subdev_info *sd_info);
@@ -668,7 +674,7 @@
 	int *p_active);
 int msm_cam_server_close_mctl_session(struct msm_cam_v4l2_device *pcam);
 long msm_v4l2_evt_notify(struct msm_cam_media_controller *mctl,
-		unsigned int cmd, unsigned long evt);
+	unsigned int cmd, unsigned long evt);
 int msm_mctl_pp_get_vpe_buf_info(struct msm_mctl_pp_frame_info *zoom);
 void msm_queue_init(struct msm_device_queue *queue, const char *name);
 void msm_enqueue(struct msm_device_queue *queue, struct list_head *entry);
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index 9e1d9c1..67e7c02 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -168,7 +168,9 @@
 	struct msm_cam_v4l2_device *pcam = pmctl->pcam_ptr;
 	struct msm_frame_info *frame_info =
 		(struct msm_frame_info *)vdata->evt_msg.data;
-	uint32_t vfe_id, image_mode;
+	uint32_t vfe_id;
+	struct msm_cam_buf_handle buf_handle;
+
 	if (!pcam) {
 		pr_debug("%s pcam is null. return\n", __func__);
 		msm_isp_sync_free(vdata);
@@ -176,10 +178,13 @@
 	}
 	if (frame_info) {
 		vfe_id = frame_info->path;
-		image_mode = frame_info->image_mode;
+		buf_handle.buf_lookup_type = BUF_LOOKUP_BY_INST_HANDLE;
+		buf_handle.inst_handle = frame_info->inst_handle;
 	} else {
 		vfe_id = vdata->evt_msg.msg_id;
-		image_mode = msm_isp_vfe_msg_to_img_mode(pmctl, vfe_id);
+		buf_handle.buf_lookup_type = BUF_LOOKUP_BY_IMG_MODE;
+		buf_handle.image_mode =
+			msm_isp_vfe_msg_to_img_mode(pmctl, vfe_id);
 	}
 
 	switch (vdata->type) {
@@ -189,14 +194,14 @@
 		D("%s Got V32_START_*: Getting ping addr id = %d",
 						__func__, vfe_id);
 		msm_mctl_reserve_free_buf(pmctl, NULL,
-					image_mode, &free_buf);
+					&buf_handle, &free_buf);
 		cfgcmd.cmd_type = CMD_CONFIG_PING_ADDR;
 		cfgcmd.value = &vfe_id;
 		vfe_params.vfe_cfg = &cfgcmd;
 		vfe_params.data = (void *)&free_buf;
 		rc = v4l2_subdev_call(sd, core, ioctl, 0, &vfe_params);
 		msm_mctl_reserve_free_buf(pmctl, NULL,
-					image_mode, &free_buf);
+					&buf_handle, &free_buf);
 		cfgcmd.cmd_type = CMD_CONFIG_PONG_ADDR;
 		cfgcmd.value = &vfe_id;
 		vfe_params.vfe_cfg = &cfgcmd;
@@ -208,7 +213,7 @@
 		pr_debug("%s Got V32_CAPTURE: getting buffer for id = %d",
 						__func__, vfe_id);
 		msm_mctl_reserve_free_buf(pmctl, NULL,
-					image_mode, &free_buf);
+					&buf_handle, &free_buf);
 		cfgcmd.cmd_type = CMD_CONFIG_PING_ADDR;
 		cfgcmd.value = &vfe_id;
 		vfe_params.vfe_cfg = &cfgcmd;
@@ -216,7 +221,7 @@
 		rc = v4l2_subdev_call(sd, core, ioctl, 0, &vfe_params);
 		temp_free_buf = free_buf;
 		if (msm_mctl_reserve_free_buf(pmctl, NULL,
-					image_mode, &free_buf)) {
+					&buf_handle, &free_buf)) {
 			/* Write the same buffer into PONG */
 			free_buf = temp_free_buf;
 		}
@@ -254,7 +259,7 @@
 		D("%s Got OUTPUT_IRQ: Getting free buf id = %d",
 						__func__, vfe_id);
 		msm_mctl_reserve_free_buf(pmctl, NULL,
-					image_mode, &free_buf);
+					&buf_handle, &free_buf);
 		cfgcmd.cmd_type = CMD_CONFIG_FREE_BUF_ADDR;
 		cfgcmd.value = &vfe_id;
 		vfe_params.vfe_cfg = &cfgcmd;
@@ -320,10 +325,10 @@
 	}
 	case NOTIFY_VFE_MSG_OUT: {
 		uint8_t msgid;
-		int32_t image_mode = -1;
+		struct msm_cam_buf_handle buf_handle;
 		struct isp_msg_output *isp_output =
 				(struct isp_msg_output *)arg;
-		if (isp_output->buf.image_mode < 0) {
+		if (!isp_output->buf.inst_handle) {
 			switch (isp_output->output_id) {
 			case MSG_ID_OUTPUT_P:
 				msgid = VFE_MSG_OUTPUT_P;
@@ -356,19 +361,22 @@
 				rc = -EINVAL;
 				break;
 			}
-			if (!rc)
-				image_mode =
+			if (!rc) {
+				buf_handle.buf_lookup_type =
+					BUF_LOOKUP_BY_IMG_MODE;
+				buf_handle.image_mode =
 				msm_isp_vfe_msg_to_img_mode(pmctl, msgid);
+			}
 		} else {
-			image_mode = isp_output->buf.image_mode;
+			buf_handle.buf_lookup_type = BUF_LOOKUP_BY_INST_HANDLE;
+			buf_handle.inst_handle = isp_output->buf.inst_handle;
 		}
 		isp_event->isp_data.isp_msg.msg_id =
 			isp_output->output_id;
 		isp_event->isp_data.isp_msg.frame_id =
 			isp_output->frameCounter;
 		buf = isp_output->buf;
-		BUG_ON(image_mode < 0);
-		msm_mctl_buf_done(pmctl, image_mode,
+		msm_mctl_buf_done(pmctl, &buf_handle,
 			&buf, isp_output->frameCounter);
 		}
 		break;
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index 0a61b69..edc8899 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -882,6 +882,8 @@
 	pcam->mctl_node.dev_inst[pcam_inst->my_index] = NULL;
 	v4l2_fh_del(&pcam_inst->eventHandle);
 	v4l2_fh_exit(&pcam_inst->eventHandle);
+	CLR_MCTLPP_INST_IDX(pcam_inst->inst_handle);
+	CLR_IMG_MODE(pcam_inst->inst_handle);
 	mutex_destroy(&pcam_inst->inst_lock);
 
 	kfree(pcam_inst);
@@ -1454,7 +1456,9 @@
 	struct msm_cam_v4l2_dev_inst *pcam_inst;
 	pcam_inst = container_of(f->private_data,
 		struct msm_cam_v4l2_dev_inst, eventHandle);
-	pcam_inst->image_mode = a->parm.capture.extendedmode;
+	pcam_inst->image_mode = (a->parm.capture.extendedmode & 0x7F);
+	SET_IMG_MODE(pcam_inst->inst_handle, pcam_inst->image_mode);
+	SET_MCTLPP_INST_IDX(pcam_inst->inst_handle, pcam_inst->my_index);
 	pcam_inst->pcam->mctl_node.dev_inst_map[pcam_inst->image_mode] =
 		pcam_inst;
 	pcam_inst->path = msm_mctl_vidbuf_get_path(pcam_inst->image_mode);
@@ -1499,6 +1503,51 @@
 	return rc;
 }
 
+static int msm_mctl_v4l2_private_g_ctrl(struct file *f, void *pctx,
+	struct msm_camera_v4l2_ioctl_t *ioctl_ptr)
+{
+	int rc = -EINVAL;
+	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);
+
+	WARN_ON(pctx != f->private_data);
+
+	mutex_lock(&pcam->mctl_node.dev_lock);
+	switch (ioctl_ptr->id) {
+	case MSM_V4L2_PID_INST_HANDLE:
+		COPY_TO_USER(rc, (void __user *)ioctl_ptr->ioctl_ptr,
+			(void *)&pcam_inst->inst_handle, sizeof(uint32_t));
+		if (rc)
+			ERR_COPY_TO_USER();
+		break;
+	default:
+		pr_err("%s Unsupported ioctl %d ", __func__, ioctl_ptr->id);
+		break;
+	}
+	mutex_unlock(&pcam->mctl_node.dev_lock);
+	return rc;
+}
+
+static long msm_mctl_v4l2_private_ioctl(struct file *file, void *fh,
+	  bool valid_prio, int cmd, void *arg)
+{
+	int rc = -EINVAL;
+	struct msm_camera_v4l2_ioctl_t *ioctl_ptr = arg;
+	D("%s: cmd %d\n", __func__, _IOC_NR(cmd));
+
+	switch (cmd) {
+	case MSM_CAM_V4L2_IOCTL_PRIVATE_G_CTRL:
+		rc = msm_mctl_v4l2_private_g_ctrl(file, fh, ioctl_ptr);
+		break;
+	default:
+		pr_err("%s Unsupported ioctl cmd %d ", __func__, cmd);
+		break;
+	}
+	return rc;
+}
+
 /* mctl node v4l2_ioctl_ops */
 static const struct v4l2_ioctl_ops g_msm_mctl_ioctl_ops = {
 	.vidioc_querycap = msm_mctl_v4l2_querycap,
@@ -1538,6 +1587,7 @@
 	/* event subscribe/unsubscribe */
 	.vidioc_subscribe_event = msm_mctl_v4l2_subscribe_event,
 	.vidioc_unsubscribe_event = msm_mctl_v4l2_unsubscribe_event,
+	.vidioc_default = msm_mctl_v4l2_private_ioctl,
 };
 
 int msm_setup_mctl_node(struct msm_cam_v4l2_device *pcam)
diff --git a/drivers/media/video/msm/msm_mctl_buf.c b/drivers/media/video/msm/msm_mctl_buf.c
index cd86a80..befd213 100644
--- a/drivers/media/video/msm/msm_mctl_buf.c
+++ b/drivers/media/video/msm/msm_mctl_buf.c
@@ -368,7 +368,7 @@
 struct msm_frame_buffer *msm_mctl_buf_find(
 	struct msm_cam_media_controller *pmctl,
 	struct msm_cam_v4l2_dev_inst *pcam_inst, int del_buf,
-	int image_mode, struct msm_free_buf *fbuf)
+	struct msm_free_buf *fbuf)
 {
 	struct msm_frame_buffer *buf = NULL, *tmp;
 	uint32_t buf_phyaddr = 0;
@@ -409,14 +409,13 @@
 int msm_mctl_buf_done_proc(
 		struct msm_cam_media_controller *pmctl,
 		struct msm_cam_v4l2_dev_inst *pcam_inst,
-		int image_mode, struct msm_free_buf *fbuf,
+		struct msm_free_buf *fbuf,
 		uint32_t *frame_id, int gen_timestamp)
 {
 	struct msm_frame_buffer *buf = NULL;
 	int del_buf = 1;
 
-	buf = msm_mctl_buf_find(pmctl, pcam_inst, del_buf,
-					image_mode, fbuf);
+	buf = msm_mctl_buf_find(pmctl, pcam_inst, del_buf, fbuf);
 	if (!buf) {
 		pr_err("%s: buf=0x%x not found\n",
 			__func__, fbuf->ch_paddr[0]);
@@ -434,48 +433,81 @@
 
 
 int msm_mctl_buf_done(struct msm_cam_media_controller *p_mctl,
-			int image_mode, struct msm_free_buf *fbuf,
-			uint32_t frame_id)
+	struct msm_cam_buf_handle *buf_handle,
+	struct msm_free_buf *fbuf,
+	uint32_t frame_id)
 {
 	struct msm_cam_v4l2_dev_inst *pcam_inst;
 	int idx, rc;
 	int pp_divert_type = 0, pp_type = 0;
+	uint32_t image_mode;
+
+	if (!p_mctl || !buf_handle || !fbuf) {
+		pr_err("%s Invalid argument. ", __func__);
+		return -EINVAL;
+	}
+	if (buf_handle->buf_lookup_type == BUF_LOOKUP_BY_IMG_MODE)
+		image_mode = buf_handle->image_mode;
+	else
+		image_mode = GET_IMG_MODE(buf_handle->inst_handle);
+
+	if (image_mode > MSM_V4L2_EXT_CAPTURE_MODE_MAX) {
+		pr_err("%s Invalid image mode %d ", __func__, image_mode);
+		return -EINVAL;
+	}
 
 	msm_mctl_check_pp(p_mctl, image_mode, &pp_divert_type, &pp_type);
 	D("%s: pp_type=%d, pp_divert_type = %d, frame_id = 0x%x image_mode %d",
 		__func__, pp_type, pp_divert_type, frame_id, image_mode);
-	if (pp_type || pp_divert_type)
-		rc = msm_mctl_do_pp_divert(p_mctl,
-		image_mode, fbuf, frame_id, pp_type);
-	else {
-		idx = msm_mctl_img_mode_to_inst_index(
-				p_mctl, image_mode, 0);
-		if (idx < 0) {
-			/* check mctl node */
-			if ((image_mode >= 0) &&
-				p_mctl->pcam_ptr->mctl_node.
-					dev_inst_map[image_mode]) {
-				int index = p_mctl->pcam_ptr->mctl_node.
-					   dev_inst_map[image_mode]->my_index;
-				pcam_inst = p_mctl->pcam_ptr->mctl_node.
-					dev_inst[index];
-				D("%s: Mctl node index %d inst %p",
-					__func__, index, pcam_inst);
-				rc = msm_mctl_buf_done_proc(p_mctl, pcam_inst,
-					image_mode, fbuf,
-					&frame_id, 1);
-				D("%s mctl node buf done %d\n", __func__, 0);
-				return rc;
+	if (pp_type || pp_divert_type) {
+		rc = msm_mctl_do_pp_divert(p_mctl, buf_handle,
+			fbuf, frame_id, pp_type);
+	} else {
+		/* Find the instance on which vb2_buffer_done() needs to be
+		 * called, so that the user can get the buffer.
+		 * If the lookup type is
+		 * - By instance handle:
+		 *    Either mctl_pp inst idx or video inst idx should be set.
+		 *    Try to get the MCTL_PP inst idx first, if its not set,
+		 *    fall back to video inst idx. Once we get the inst idx,
+		 *    get the pcam_inst from the corresponding dev_inst[] map.
+		 *    If neither are set, its a serious error, trigger a BUG_ON.
+		 * - By image mode:
+		 *    Legacy usecase. Use the image mode and get the pcam_inst
+		 *    from the video node.
+		 */
+		if (buf_handle->buf_lookup_type == BUF_LOOKUP_BY_INST_HANDLE) {
+			idx = GET_MCTLPP_INST_IDX(buf_handle->inst_handle);
+			if (idx > MSM_DEV_INST_MAX) {
+				idx = GET_VIDEO_INST_IDX(
+					buf_handle->inst_handle);
+				BUG_ON(idx > MSM_DEV_INST_MAX);
+				pcam_inst = p_mctl->pcam_ptr->dev_inst[idx];
 			} else {
-			  pr_err("%s Invalid instance, dropping buffer\n",
-				  __func__);
-			  return idx;
+				pcam_inst = p_mctl->pcam_ptr->mctl_node.
+					dev_inst[idx];
 			}
+		} else if (buf_handle->buf_lookup_type ==
+				BUF_LOOKUP_BY_IMG_MODE) {
+			idx = msm_mctl_img_mode_to_inst_index(p_mctl,
+				buf_handle->image_mode, 0);
+			if (idx < 0) {
+				pr_err("%s Invalid idx %d ", __func__, idx);
+				return -EINVAL;
+			}
+			pcam_inst = p_mctl->pcam_ptr->dev_inst[idx];
+		} else {
+			pr_err("%s Invalid buffer lookup type %d", __func__,
+				buf_handle->buf_lookup_type);
+			return -EINVAL;
 		}
-		pcam_inst = p_mctl->pcam_ptr->dev_inst[idx];
+		if (!pcam_inst) {
+			pr_err("%s Invalid instance, Dropping buffer. ",
+				__func__);
+			return -EINVAL;
+		}
 		rc = msm_mctl_buf_done_proc(p_mctl, pcam_inst,
-				image_mode, fbuf,
-				&frame_id, 1);
+			fbuf, &frame_id, 1);
 	}
 	return rc;
 }
@@ -508,58 +540,99 @@
 	return ret;
 }
 
-struct msm_cam_v4l2_dev_inst *msm_mctl_get_pcam_inst(
-				struct msm_cam_media_controller *pmctl,
-				int image_mode)
+struct msm_cam_v4l2_dev_inst *msm_mctl_get_inst_by_img_mode(
+	struct msm_cam_media_controller *pmctl, uint32_t img_mode)
 {
 	struct msm_cam_v4l2_dev_inst *pcam_inst = NULL;
 	struct msm_cam_v4l2_device *pcam = pmctl->pcam_ptr;
 	int idx;
 
-	if (image_mode >= 0) {
-		/* Valid image mode. Search the mctl node first.
-		 * If mctl node doesnt have the instance, then
-		 * search in the user's video node */
-		if (pmctl->vfe_output_mode == VFE_OUTPUTS_MAIN_AND_THUMB
+	/* Valid image mode. Search the mctl node first.
+	 * If mctl node doesnt have the instance, then
+	 * search in the user's video node */
+	if (pmctl->vfe_output_mode == VFE_OUTPUTS_MAIN_AND_THUMB
 		|| pmctl->vfe_output_mode == VFE_OUTPUTS_THUMB_AND_MAIN) {
-			if (pcam->mctl_node.dev_inst_map[image_mode]
-			&& is_buffer_queued(pcam, image_mode)) {
-				idx =
-				pcam->mctl_node.dev_inst_map[image_mode]
-				->my_index;
-				pcam_inst = pcam->mctl_node.dev_inst[idx];
-				D("%s Found instance %p in mctl node device\n",
-				  __func__, pcam_inst);
-			} else if (pcam->dev_inst_map[image_mode]) {
-				idx = pcam->dev_inst_map[image_mode]->my_index;
-				pcam_inst = pcam->dev_inst[idx];
-				D("%s Found instance %p in video device\n",
+		if (pcam->mctl_node.dev_inst_map[img_mode]
+		&& is_buffer_queued(pcam, img_mode)) {
+			idx = pcam->mctl_node.dev_inst_map[img_mode]->my_index;
+			pcam_inst = pcam->mctl_node.dev_inst[idx];
+			D("%s Found instance %p in mctl node device\n",
 				__func__, pcam_inst);
-			}
-		} else {
-			if (pcam->mctl_node.dev_inst_map[image_mode]) {
-				idx = pcam->mctl_node.dev_inst_map[image_mode]
-				->my_index;
-				pcam_inst = pcam->mctl_node.dev_inst[idx];
-				D("%s Found instance %p in mctl node device\n",
+		} else if (pcam->dev_inst_map[img_mode]) {
+			idx = pcam->dev_inst_map[img_mode]->my_index;
+			pcam_inst = pcam->dev_inst[idx];
+			D("%s Found instance %p in video device\n",
 				__func__, pcam_inst);
-			} else if (pcam->dev_inst_map[image_mode]) {
-				idx = pcam->dev_inst_map[image_mode]->my_index;
-				pcam_inst = pcam->dev_inst[idx];
-				D("%s Found instance %p in video device\n",
-				__func__, pcam_inst);
-			}
 		}
-	} else
-		pr_err("%s Invalid image mode %d. Return NULL\n",
-			__func__, image_mode);
+	} else {
+		if (pcam->mctl_node.dev_inst_map[img_mode]) {
+			idx = pcam->mctl_node.dev_inst_map[img_mode]->my_index;
+			pcam_inst = pcam->mctl_node.dev_inst[idx];
+			D("%s Found instance %p in mctl node device\n",
+				__func__, pcam_inst);
+		} else if (pcam->dev_inst_map[img_mode]) {
+			idx = pcam->dev_inst_map[img_mode]->my_index;
+			pcam_inst = pcam->dev_inst[idx];
+			D("%s Found instance %p in video device\n",
+				__func__, pcam_inst);
+		}
+	}
+	return pcam_inst;
+}
+
+struct msm_cam_v4l2_dev_inst *msm_mctl_get_pcam_inst(
+				struct msm_cam_media_controller *pmctl,
+				struct msm_cam_buf_handle *buf_handle)
+{
+	struct msm_cam_v4l2_dev_inst *pcam_inst = NULL;
+	struct msm_cam_v4l2_device *pcam = pmctl->pcam_ptr;
+	int idx;
+
+	/* Get the pcam instance on based on the following rules:
+	 * If the lookup type is
+	 * - By instance handle:
+	 *    Either mctl_pp inst idx or video inst idx should be set.
+	 *    Try to get the MCTL_PP inst idx first, if its not set,
+	 *    fall back to video inst idx. Once we get the inst idx,
+	 *    get the pcam_inst from the corresponding dev_inst[] map.
+	 *    If neither are set, its a serious error, trigger a BUG_ON.
+	 * - By image mode:(Legacy usecase)
+	 *    If vfe is in configured in snapshot mode, first check if
+	 *    mctl pp node has a instance created for this image mode
+	 *    and if there is a buffer queued for that instance.
+	 *    If so, return that instance, otherwise get the pcam instance
+	 *    for this image_mode from the video instance.
+	 *    If the vfe is configured in any other mode, then first check
+	 *    if mctl pp node has a instance created for this image mode,
+	 *    otherwise get the pcam instance for this image mode from the
+	 *    video instance.
+	 */
+	if (buf_handle->buf_lookup_type == BUF_LOOKUP_BY_INST_HANDLE) {
+		idx = GET_MCTLPP_INST_IDX(buf_handle->inst_handle);
+		if (idx > MSM_DEV_INST_MAX) {
+			idx = GET_VIDEO_INST_IDX(buf_handle->inst_handle);
+			BUG_ON(idx > MSM_DEV_INST_MAX);
+			pcam_inst = pcam->dev_inst[idx];
+		} else {
+			pcam_inst = pcam->mctl_node.dev_inst[idx];
+		}
+	} else if ((buf_handle->buf_lookup_type == BUF_LOOKUP_BY_IMG_MODE)
+		&& (buf_handle->image_mode >= 0 &&
+		buf_handle->image_mode < MSM_V4L2_EXT_CAPTURE_MODE_MAX)) {
+		pcam_inst = msm_mctl_get_inst_by_img_mode(pmctl,
+				buf_handle->image_mode);
+	} else {
+		pr_err("%s Invalid buffer lookup type %d", __func__,
+			buf_handle->buf_lookup_type);
+	}
 	return pcam_inst;
 }
 
 int msm_mctl_reserve_free_buf(
-		struct msm_cam_media_controller *pmctl,
-		struct msm_cam_v4l2_dev_inst *pref_pcam_inst,
-		int image_mode, struct msm_free_buf *free_buf)
+	struct msm_cam_media_controller *pmctl,
+	struct msm_cam_v4l2_dev_inst *pref_pcam_inst,
+	struct msm_cam_buf_handle *buf_handle,
+	struct msm_free_buf *free_buf)
 {
 	struct msm_cam_v4l2_dev_inst *pcam_inst = pref_pcam_inst;
 	unsigned long flags = 0;
@@ -568,8 +641,8 @@
 	int rc = -EINVAL, i;
 	uint32_t buf_idx, plane_offset = 0;
 
-	if (!free_buf || !pmctl) {
-		pr_err("%s: free_buf/pmctl is null\n", __func__);
+	if (!free_buf || !pmctl || !buf_handle) {
+		pr_err("%s: Invalid argument passed\n", __func__);
 		return rc;
 	}
 	memset(free_buf, 0, sizeof(struct msm_free_buf));
@@ -579,7 +652,7 @@
 	 * If the preferred camera instance is NULL, get the
 	 * camera instance using the image mode passed */
 	if (!pcam_inst)
-		pcam_inst = msm_mctl_get_pcam_inst(pmctl, image_mode);
+		pcam_inst = msm_mctl_get_pcam_inst(pmctl, buf_handle);
 
 	if (!pcam_inst || !pcam_inst->streamon) {
 		pr_err("%s: stream is turned off\n", __func__);
@@ -641,7 +714,7 @@
 
 int msm_mctl_release_free_buf(struct msm_cam_media_controller *pmctl,
 				struct msm_cam_v4l2_dev_inst *pcam_inst,
-				int image_mode, struct msm_free_buf *free_buf)
+				struct msm_free_buf *free_buf)
 {
 	unsigned long flags = 0;
 	struct msm_frame_buffer *buf = NULL;
@@ -677,20 +750,39 @@
 }
 
 int msm_mctl_buf_done_pp(struct msm_cam_media_controller *pmctl,
-	int image_mode, struct msm_free_buf *frame, int dirty, int node_type)
+	struct msm_cam_buf_handle *buf_handle,
+	struct msm_free_buf *frame, int dirty, int node_type)
 {
-	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	struct msm_cam_v4l2_dev_inst *pcam_inst = NULL;
 	int rc = 0, idx;
 
-	idx = msm_mctl_img_mode_to_inst_index(pmctl, image_mode, node_type);
-	if (idx < 0) {
-		pr_err("%s Invalid instance, buffer not released\n", __func__);
-		return idx;
+	if (!pmctl || !buf_handle) {
+		pr_err("%s Invalid argument ", __func__);
+		return -EINVAL;
 	}
-	if (node_type)
-		pcam_inst = pmctl->pcam_ptr->mctl_node.dev_inst[idx];
-	else
-		pcam_inst = pmctl->pcam_ptr->dev_inst[idx];
+
+	if (buf_handle->buf_lookup_type == BUF_LOOKUP_BY_INST_HANDLE) {
+		idx = GET_MCTLPP_INST_IDX(buf_handle->inst_handle);
+		if (idx > MSM_DEV_INST_MAX) {
+			idx = GET_VIDEO_INST_IDX(buf_handle->inst_handle);
+			BUG_ON(idx > MSM_DEV_INST_MAX);
+			pcam_inst = pmctl->pcam_ptr->dev_inst[idx];
+		} else {
+			pcam_inst = pmctl->pcam_ptr->mctl_node.dev_inst[idx];
+		}
+	} else if (buf_handle->buf_lookup_type == BUF_LOOKUP_BY_IMG_MODE) {
+		idx = msm_mctl_img_mode_to_inst_index(pmctl,
+			buf_handle->image_mode, node_type);
+		if (idx < 0) {
+			pr_err("%s Invalid instance, buffer not released\n",
+				__func__);
+			return idx;
+		}
+		if (node_type)
+			pcam_inst = pmctl->pcam_ptr->mctl_node.dev_inst[idx];
+		else
+			pcam_inst = pmctl->pcam_ptr->dev_inst[idx];
+	}
 	if (!pcam_inst) {
 		pr_err("%s Invalid instance, cannot send buf to user",
 			__func__);
@@ -701,121 +793,12 @@
 		__func__, pcam_inst, frame->ch_paddr[0], dirty);
 	if (dirty)
 		/* the frame is dirty, not going to disptach to app */
-		rc = msm_mctl_release_free_buf(pmctl, pcam_inst,
-						image_mode, frame);
+		rc = msm_mctl_release_free_buf(pmctl, pcam_inst, frame);
 	else
-		rc = msm_mctl_buf_done_proc(pmctl, pcam_inst,
-			image_mode, frame, NULL, 0);
+		rc = msm_mctl_buf_done_proc(pmctl, pcam_inst, frame, NULL, 0);
 	return rc;
 }
 
-struct msm_frame_buffer *msm_mctl_get_free_buf(
-		struct msm_cam_media_controller *pmctl,
-		int image_mode)
-{
-	struct msm_cam_v4l2_dev_inst *pcam_inst;
-	unsigned long flags = 0;
-	struct msm_frame_buffer *buf = NULL;
-	int rc = -EINVAL, idx;
-
-	idx = msm_mctl_img_mode_to_inst_index(pmctl,
-		image_mode, 0);
-	if (idx < 0) {
-		pr_err("%s Invalid instance, cant get buffer\n", __func__);
-		return NULL;
-	}
-	pcam_inst = pmctl->pcam_ptr->dev_inst[idx];
-	if (!pcam_inst->streamon) {
-		D("%s: stream 0x%p is off\n", __func__, pcam_inst);
-		return NULL;
-	}
-	spin_lock_irqsave(&pcam_inst->vq_irqlock, flags);
-	if (!list_empty(&pcam_inst->free_vq)) {
-		list_for_each_entry(buf, &pcam_inst->free_vq, list) {
-			if (buf->state == MSM_BUFFER_STATE_QUEUED) {
-				buf->state = MSM_BUFFER_STATE_RESERVED;
-				rc = 0;
-				break;
-			}
-		}
-	}
-	if (rc != 0) {
-		D("%s:No free buffer available: inst = 0x%p ",
-				__func__, pcam_inst);
-		buf = NULL;
-	}
-	spin_unlock_irqrestore(&pcam_inst->vq_irqlock, flags);
-	return buf;
-}
-
-int msm_mctl_put_free_buf(
-		struct msm_cam_media_controller *pmctl,
-		int image_mode, struct msm_frame_buffer *my_buf)
-{
-	struct msm_cam_v4l2_dev_inst *pcam_inst;
-	unsigned long flags = 0;
-	int rc = 0, idx;
-	struct msm_frame_buffer *buf = NULL;
-
-	idx = msm_mctl_img_mode_to_inst_index(pmctl,
-		image_mode, 0);
-	if (idx < 0) {
-		pr_err("%s Invalid instance, cant put buffer\n", __func__);
-		return idx;
-	}
-	pcam_inst = pmctl->pcam_ptr->dev_inst[idx];
-	if (!pcam_inst->streamon) {
-		D("%s: stream 0x%p is off\n", __func__, pcam_inst);
-		return rc;
-	}
-	spin_lock_irqsave(&pcam_inst->vq_irqlock, flags);
-	if (!list_empty(&pcam_inst->free_vq)) {
-		list_for_each_entry(buf, &pcam_inst->free_vq, list) {
-			if (my_buf == buf) {
-				buf->state = MSM_BUFFER_STATE_QUEUED;
-				spin_unlock_irqrestore(&pcam_inst->vq_irqlock,
-					flags);
-				return 0;
-			}
-		}
-	}
-	spin_unlock_irqrestore(&pcam_inst->vq_irqlock, flags);
-	return rc;
-}
-
-int msm_mctl_buf_del(struct msm_cam_media_controller *pmctl,
-	int image_mode,
-	struct msm_frame_buffer *my_buf)
-{
-	struct msm_cam_v4l2_dev_inst *pcam_inst;
-	struct msm_frame_buffer *buf = NULL;
-	unsigned long flags = 0;
-	int idx;
-
-	idx = msm_mctl_img_mode_to_inst_index(pmctl,
-		image_mode, 0);
-	if (idx < 0) {
-		pr_err("%s Invalid instance, cant delete buffer\n", __func__);
-		return idx;
-	}
-	pcam_inst = pmctl->pcam_ptr->dev_inst[idx];
-	D("%s: idx = %d, pinst=0x%p", __func__, idx, pcam_inst);
-	spin_lock_irqsave(&pcam_inst->vq_irqlock, flags);
-	if (!list_empty(&pcam_inst->free_vq)) {
-		list_for_each_entry(buf, &pcam_inst->free_vq, list) {
-			if (my_buf == buf) {
-				list_del_init(&buf->list);
-				spin_unlock_irqrestore(&pcam_inst->vq_irqlock,
-					flags);
-				return 0;
-			}
-		}
-	}
-	spin_unlock_irqrestore(&pcam_inst->vq_irqlock, flags);
-	pr_err("%s: buf 0x%p not found", __func__, my_buf);
-	return -EINVAL;
-}
-
 int msm_mctl_buf_return_buf(struct msm_cam_media_controller *pmctl,
 			int image_mode, struct msm_frame_buffer *rbuf)
 {
diff --git a/drivers/media/video/msm/msm_mctl_pp.c b/drivers/media/video/msm/msm_mctl_pp.c
index abcee4b..dcb7c51 100644
--- a/drivers/media/video/msm/msm_mctl_pp.c
+++ b/drivers/media/video/msm/msm_mctl_pp.c
@@ -153,61 +153,96 @@
 	spin_unlock_irqrestore(&pcam_inst->vq_irqlock, flags);
 	return 0;
 }
+
 static struct msm_cam_v4l2_dev_inst *msm_mctl_get_pcam_inst_for_divert(
-		struct msm_cam_media_controller *pmctl,
-		int image_mode, struct msm_free_buf *fbuf, int *node_type)
+	struct msm_cam_media_controller *pmctl,
+	struct msm_cam_buf_handle *buf_handle,
+	struct msm_free_buf *fbuf, int *node_type)
 {
 	struct msm_cam_v4l2_dev_inst *pcam_inst = NULL;
 	struct msm_cam_v4l2_device *pcam = pmctl->pcam_ptr;
 	int idx;
+	uint32_t img_mode;
 
-	if (image_mode >= 0) {
-		/* Valid image mode. Search the mctl node first.
-		 * If mctl node doesnt have the instance, then
-		 * search in the user's video node */
-		if (pcam->mctl_node.dev_inst_map[image_mode]
-		&& is_buf_in_queue(pcam, fbuf, image_mode)) {
-			idx =
-			pcam->mctl_node.dev_inst_map[image_mode]->my_index;
-			pcam_inst = pcam->mctl_node.dev_inst[idx];
-			*node_type = MCTL_NODE;
-			D("%s Found instance %p in mctl node device\n",
-				__func__, pcam_inst);
-		} else if (pcam->dev_inst_map[image_mode]) {
-			idx = pcam->dev_inst_map[image_mode]->my_index;
+	if (buf_handle->buf_lookup_type == BUF_LOOKUP_BY_INST_HANDLE) {
+		idx = GET_MCTLPP_INST_IDX(buf_handle->inst_handle);
+		if (idx > MSM_DEV_INST_MAX) {
+			idx = GET_VIDEO_INST_IDX(buf_handle->inst_handle);
+			BUG_ON(idx > MSM_DEV_INST_MAX);
 			pcam_inst = pcam->dev_inst[idx];
 			*node_type = VIDEO_NODE;
-			D("%s Found instance %p in video device",
-				__func__, pcam_inst);
-		} else
+		} else {
+			pcam_inst = pcam->mctl_node.dev_inst[idx];
+			*node_type = MCTL_NODE;
+		}
+	} else if (buf_handle->buf_lookup_type == BUF_LOOKUP_BY_IMG_MODE) {
+		img_mode = buf_handle->image_mode;
+		if (img_mode >= 0 && img_mode < MSM_V4L2_EXT_CAPTURE_MODE_MAX) {
+			/* Valid image mode. Search the mctl node first.
+			 * If mctl node doesnt have the instance, then
+			 * search in the user's video node */
+			if (pcam->mctl_node.dev_inst_map[img_mode]
+				&& is_buf_in_queue(pcam, fbuf, img_mode)) {
+				idx = pcam->mctl_node.
+					dev_inst_map[img_mode]->my_index;
+				pcam_inst = pcam->mctl_node.dev_inst[idx];
+				*node_type = MCTL_NODE;
+				D("%s Found instance %p in mctl node device\n",
+					__func__, pcam_inst);
+			} else if (pcam->dev_inst_map[img_mode]) {
+				idx = pcam->dev_inst_map[img_mode]->my_index;
+				pcam_inst = pcam->dev_inst[idx];
+				*node_type = VIDEO_NODE;
+				D("%s Found instance %p in video device",
+					__func__, pcam_inst);
+			} else {
+				pr_err("%s Cannot find instance for %d.\n",
+					__func__, img_mode);
+			}
+		} else {
 			pr_err("%s Invalid image mode %d. Return NULL\n",
-				   __func__, image_mode);
+				__func__, buf_handle->image_mode);
+		}
+	} else {
+		pr_err("%s Invalid buffer lookup type ", __func__);
 	}
-		return pcam_inst;
+	return pcam_inst;
 }
 
 int msm_mctl_do_pp_divert(
 	struct msm_cam_media_controller *p_mctl,
-	int image_mode, struct msm_free_buf *fbuf,
+	struct msm_cam_buf_handle *buf_handle,
+	struct msm_free_buf *fbuf,
 	uint32_t frame_id, int pp_type)
 {
 	struct msm_cam_v4l2_dev_inst *pcam_inst;
-	int rc = 0, i, buf_idx;
+	int rc = 0, i, buf_idx, node;
 	int del_buf = 0; /* delete from free queue */
 	struct msm_cam_evt_divert_frame div;
 	struct msm_frame_buffer *vb = NULL;
 	struct videobuf2_contig_pmem *mem;
-	int node;
+	uint32_t image_mode;
 
-	pcam_inst = msm_mctl_get_pcam_inst_for_divert
-		(p_mctl, image_mode, fbuf, &node);
+	if (buf_handle->buf_lookup_type == BUF_LOOKUP_BY_IMG_MODE) {
+		image_mode = buf_handle->image_mode;
+		div.frame.inst_handle = 0;
+	} else if (buf_handle->buf_lookup_type == BUF_LOOKUP_BY_INST_HANDLE) {
+		image_mode = GET_IMG_MODE(buf_handle->inst_handle);
+		div.frame.inst_handle = buf_handle->inst_handle;
+	} else {
+		pr_err("%s Invalid buffer lookup type %d ", __func__,
+			buf_handle->buf_lookup_type);
+		return -EINVAL;
+	}
+
+	pcam_inst = msm_mctl_get_pcam_inst_for_divert(p_mctl,
+			buf_handle, fbuf, &node);
 	if (!pcam_inst) {
 		pr_err("%s Invalid instance. Cannot divert frame.\n",
 			__func__);
 		return -EINVAL;
 	}
-	vb = msm_mctl_buf_find(p_mctl, pcam_inst,
-		  del_buf, image_mode, fbuf);
+	vb = msm_mctl_buf_find(p_mctl, pcam_inst, del_buf, fbuf);
 	if (!vb)
 		return -EINVAL;
 
@@ -392,50 +427,16 @@
 			struct msm_mctl_pp_cmd *pp_cmd)
 {
 	int rc = 0;
-	struct msm_mctl_pp_frame_buffer pp_buffer;
-	struct msm_frame_buffer *buf = NULL;
-	void __user *argp = (void __user *)pp_cmd->value;
-	int img_mode;
 	unsigned long flags;
 
 	switch (pp_cmd->id) {
-	case MCTL_CMD_GET_FRAME_BUFFER: {
-		if (copy_from_user(&pp_buffer, pp_cmd->value,
-				sizeof(pp_buffer)))
-			return -EFAULT;
-		img_mode = msm_mctl_pp_path_to_img_mode(pp_buffer.path);
-		if (img_mode < 0) {
-			pr_err("%s Invalid image mode\n", __func__);
-			return img_mode;
-		}
-		buf = msm_mctl_get_free_buf(p_mctl, img_mode);
-		pp_buffer.buf_handle = (uint32_t)buf;
-		if (copy_to_user((void *)argp,
-			&pp_buffer,
-			sizeof(struct msm_mctl_pp_frame_buffer))) {
-			ERR_COPY_TO_USER();
-			rc = -EFAULT;
-		}
-		break;
-	}
-	case MCTL_CMD_PUT_FRAME_BUFFER: {
-		if (copy_from_user(&pp_buffer, pp_cmd->value,
-				sizeof(pp_buffer)))
-			return -EFAULT;
-		img_mode = msm_mctl_pp_path_to_img_mode(pp_buffer.path);
-		if (img_mode < 0) {
-			pr_err("%s Invalid image mode\n", __func__);
-			return img_mode;
-		}
-		buf = (struct msm_frame_buffer *)pp_buffer.buf_handle;
-		msm_mctl_put_free_buf(p_mctl, img_mode, buf);
-		break;
-	}
 	case MCTL_CMD_DIVERT_FRAME_PP_PATH: {
 		struct msm_mctl_pp_divert_pp divert_pp;
 		if (copy_from_user(&divert_pp, pp_cmd->value,
-				sizeof(divert_pp)))
+				sizeof(divert_pp))) {
+			ERR_COPY_FROM_USER();
 			return -EFAULT;
+		}
 		D("%s: PP_PATH, path=%d",
 			__func__, divert_pp.path);
 		spin_lock_irqsave(&p_mctl->pp_info.lock, flags);
@@ -490,17 +491,20 @@
 	struct msm_cam_media_controller *p_mctl,
 	void __user *arg)
 {
-	struct msm_cam_evt_divert_frame frame;
+	struct msm_cam_evt_divert_frame div_frame;
 	int image_mode, rc = 0;
 	struct msm_free_buf free_buf;
 	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	struct msm_cam_buf_handle buf_handle;
 
 	memset(&free_buf, 0, sizeof(struct msm_free_buf));
-	if (copy_from_user(&frame, arg,
-		sizeof(struct msm_cam_evt_divert_frame)))
+	if (copy_from_user(&div_frame, arg,
+		sizeof(struct msm_cam_evt_divert_frame))) {
+		ERR_COPY_FROM_USER();
 		return -EFAULT;
+	}
 
-	image_mode = frame.image_mode;
+	image_mode = div_frame.image_mode;
 	if (image_mode <= 0) {
 		pr_err("%s Invalid image mode %d", __func__, image_mode);
 		return -EINVAL;
@@ -511,17 +515,25 @@
 		pr_err("%s Instance already closed ", __func__);
 		return -EINVAL;
 	}
+	if (div_frame.frame.inst_handle) {
+		buf_handle.buf_lookup_type = BUF_LOOKUP_BY_INST_HANDLE;
+		buf_handle.inst_handle = div_frame.frame.inst_handle;
+	} else {
+		buf_handle.buf_lookup_type = BUF_LOOKUP_BY_IMG_MODE;
+		buf_handle.image_mode = image_mode;
+	}
 	rc = msm_mctl_reserve_free_buf(p_mctl, pcam_inst,
-					image_mode, &free_buf);
+					&buf_handle, &free_buf);
 	if (rc == 0) {
-		msm_mctl_pp_get_phy_addr(pcam_inst, free_buf.vb, &frame.frame);
-		if (copy_to_user((void *)arg, &frame, sizeof(frame))) {
+		msm_mctl_pp_get_phy_addr(pcam_inst,
+			free_buf.vb, &div_frame.frame);
+		if (copy_to_user((void *)arg, &div_frame, sizeof(div_frame))) {
 			ERR_COPY_TO_USER();
 			rc = -EFAULT;
 		}
 	}
 	D("%s: reserve free buf got buffer %d from %p rc = %d, phy = 0x%x",
-		__func__, frame.frame.buf_idx,
+		__func__, div_frame.frame.buf_idx,
 		pcam_inst, rc, free_buf.ch_paddr[0]);
 	return rc;
 }
@@ -535,10 +547,13 @@
 	struct msm_pp_frame *frame;
 	int image_mode, rc = 0;
 	struct msm_free_buf free_buf;
+	struct msm_cam_buf_handle buf_handle;
 
 	if (copy_from_user(&div_frame, arg,
-		sizeof(struct msm_cam_evt_divert_frame)))
+		sizeof(struct msm_cam_evt_divert_frame))) {
+		ERR_COPY_FROM_USER();
 		return -EFAULT;
+	}
 
 	image_mode = div_frame.image_mode;
 	if (image_mode < 0) {
@@ -551,15 +566,21 @@
 	else
 		free_buf.ch_paddr[0] = frame->sp.phy_addr;
 
-	pcam_inst = msm_mctl_get_pcam_inst(p_mctl, image_mode);
+	if (div_frame.frame.inst_handle) {
+		buf_handle.buf_lookup_type = BUF_LOOKUP_BY_INST_HANDLE;
+		buf_handle.inst_handle = div_frame.frame.inst_handle;
+	} else {
+		buf_handle.buf_lookup_type = BUF_LOOKUP_BY_IMG_MODE;
+		buf_handle.image_mode = image_mode;
+	}
+	pcam_inst = msm_mctl_get_pcam_inst(p_mctl, &buf_handle);
 	if (!pcam_inst) {
 		pr_err("%s Invalid instance. Cannot release frame.\n",
 			__func__);
 		return -EINVAL;
 	}
 
-	rc = msm_mctl_release_free_buf(p_mctl, pcam_inst,
-					image_mode, &free_buf);
+	rc = msm_mctl_release_free_buf(p_mctl, pcam_inst, &free_buf);
 	D("%s: release free buf, rc = %d, phy = 0x%x",
 		__func__, rc, free_buf.ch_paddr[0]);
 
@@ -573,11 +594,13 @@
 	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)))
+			arg, sizeof(p_mctl->pp_info.pp_key))) {
+		ERR_COPY_FROM_USER();
 		rc = -EFAULT;
-	else
+	} 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;
 }
@@ -591,12 +614,24 @@
 	int dirty = 0;
 	struct msm_free_buf buf;
 	unsigned long flags;
+	struct msm_cam_buf_handle buf_handle;
 
-	if (copy_from_user(&frame, arg, sizeof(frame)))
+	if (copy_from_user(&frame, arg, sizeof(frame))) {
+		ERR_COPY_FROM_USER();
 		return -EFAULT;
+	}
 
 	spin_lock_irqsave(&p_mctl->pp_info.lock, flags);
-	image_mode = msm_mctl_pp_path_to_img_mode(frame.path);
+	if (frame.inst_handle) {
+		buf_handle.buf_lookup_type = BUF_LOOKUP_BY_INST_HANDLE;
+		buf_handle.inst_handle = frame.inst_handle;
+		image_mode = GET_IMG_MODE(frame.inst_handle);
+	} else {
+		buf_handle.buf_lookup_type = BUF_LOOKUP_BY_IMG_MODE;
+		buf_handle.image_mode =
+			msm_mctl_pp_path_to_img_mode(frame.path);
+		image_mode = buf_handle.image_mode;
+	}
 	if (image_mode < 0) {
 		pr_err("%s Invalid image mode\n", __func__);
 		return image_mode;
@@ -622,8 +657,7 @@
 			buf.ch_paddr[0] = frame.sp.phy_addr + frame.sp.y_off;
 	}
 	spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
-	/* here buf.addr is phy_addr */
-	rc = msm_mctl_buf_done_pp(p_mctl, image_mode, &buf, dirty, 0);
+	rc = msm_mctl_buf_done_pp(p_mctl, &buf_handle, &buf, dirty, 0);
 	return rc;
 }
 
@@ -636,10 +670,14 @@
 	int dirty = 0;
 	struct msm_free_buf buf;
 	unsigned long flags;
+	struct msm_cam_buf_handle buf_handle;
+
 	D("%s enter\n", __func__);
 
-	if (copy_from_user(&frame, arg, sizeof(frame)))
+	if (copy_from_user(&frame, arg, sizeof(frame))) {
+		ERR_COPY_FROM_USER();
 		return -EFAULT;
+	}
 
 	spin_lock_irqsave(&p_mctl->pp_info.lock, flags);
 	D("%s Frame path: %d\n", __func__, frame.path);
@@ -665,6 +703,14 @@
 		goto err;
 	}
 
+	if (frame.inst_handle) {
+		buf_handle.buf_lookup_type = BUF_LOOKUP_BY_INST_HANDLE;
+		buf_handle.inst_handle = frame.inst_handle;
+	} else {
+		buf_handle.buf_lookup_type = BUF_LOOKUP_BY_IMG_MODE;
+		buf_handle.image_mode = image_mode;
+	}
+
 	if (frame.num_planes > 1)
 		buf.ch_paddr[0] = frame.mp[0].phy_addr +
 					frame.mp[0].data_offset;
@@ -673,7 +719,7 @@
 
 	spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
 	D("%s Frame done id: %d\n", __func__, frame.frame_id);
-	rc = msm_mctl_buf_done_pp(p_mctl, image_mode,
+	rc = msm_mctl_buf_done_pp(p_mctl, &buf_handle,
 		&buf, dirty, frame.node_type);
 	return rc;
 err:
diff --git a/drivers/media/video/msm/msm_vfe31_v4l2.c b/drivers/media/video/msm/msm_vfe31_v4l2.c
index 71bce67..18168ee 100644
--- a/drivers/media/video/msm/msm_vfe31_v4l2.c
+++ b/drivers/media/video/msm/msm_vfe31_v4l2.c
@@ -643,7 +643,7 @@
 		vfe31_ctrl->vfebase + VFE_GLOBAL_RESET);
 }
 
-static void vfe31_subdev_notify(int id, int path, int image_mode)
+static void vfe31_subdev_notify(int id, int path, uint32_t inst_handle)
 {
 	struct msm_vfe_resp rp;
 	struct msm_frame_info frame_info;
@@ -652,7 +652,7 @@
 	memset(&rp, 0, sizeof(struct msm_vfe_resp));
 	CDBG("vfe31_subdev_notify : msgId = %d\n", id);
 	rp.evt_msg.type   = MSM_CAMERA_MSG;
-	frame_info.image_mode = image_mode;
+	frame_info.inst_handle = inst_handle;
 	frame_info.path = path;
 	rp.evt_msg.data = &frame_info;
 	rp.type	   = id;
@@ -663,20 +663,21 @@
 static int vfe31_config_axi(int mode, uint32_t *ao)
 {
 	uint32_t *ch_info;
-	uint32_t *axi_cfg = ao+V31_AXI_RESERVED;
+	uint32_t *axi_cfg = ao + V31_AXI_RESERVED;
 	/* Update the corresponding write masters for each output*/
 	ch_info = axi_cfg + V31_AXI_CFG_LEN;
 	vfe31_ctrl->outpath.out0.ch0 = 0x0000FFFF & *ch_info;
 	vfe31_ctrl->outpath.out0.ch1 = 0x0000FFFF & (*ch_info++ >> 16);
-	vfe31_ctrl->outpath.out0.ch2 = 0x0000FFFF & *ch_info;
-	vfe31_ctrl->outpath.out0.image_mode = 0x0000FFFF & (*ch_info++ >> 16);
+	vfe31_ctrl->outpath.out0.ch2 = 0x0000FFFF & *ch_info++;
+	vfe31_ctrl->outpath.out0.inst_handle = *ch_info++;
 	vfe31_ctrl->outpath.out1.ch0 = 0x0000FFFF & *ch_info;
 	vfe31_ctrl->outpath.out1.ch1 = 0x0000FFFF & (*ch_info++ >> 16);
-	vfe31_ctrl->outpath.out1.ch2 = 0x0000FFFF & *ch_info;
-	vfe31_ctrl->outpath.out1.image_mode = 0x0000FFFF & (*ch_info++ >> 16);
+	vfe31_ctrl->outpath.out1.ch2 = 0x0000FFFF & *ch_info++;
+	vfe31_ctrl->outpath.out1.inst_handle = *ch_info++;
 	vfe31_ctrl->outpath.out2.ch0 = 0x0000FFFF & *ch_info;
 	vfe31_ctrl->outpath.out2.ch1 = 0x0000FFFF & (*ch_info++ >> 16);
 	vfe31_ctrl->outpath.out2.ch2 = 0x0000FFFF & *ch_info++;
+	vfe31_ctrl->outpath.out2.inst_handle = *ch_info++;
 
 	switch (mode) {
 	case OUTPUT_PRIM:
@@ -713,7 +714,7 @@
 	msm_camera_io_memcpy(vfe31_ctrl->vfebase +
 		vfe31_cmd[VFE_CMD_AXI_OUT_CFG].offset, axi_cfg,
 		vfe31_cmd[VFE_CMD_AXI_OUT_CFG].length - V31_AXI_CH_INF_LEN -
-			V31_AXI_RESERVED);
+			V31_AXI_RESERVED_LEN);
 	return 0;
 }
 
@@ -1301,14 +1302,14 @@
 {
 	struct vfe31_output_ch *outch = NULL;
 	struct msm_free_buf *b = NULL;
-	uint32_t image_mode = 0;
+	uint32_t inst_handle = 0;
 
 	if (path == VFE_MSG_OUTPUT_PRIMARY)
-		image_mode = vfe31_ctrl->outpath.out0.image_mode;
+		inst_handle = vfe31_ctrl->outpath.out0.inst_handle;
 	else
-		image_mode = vfe31_ctrl->outpath.out1.image_mode;
+		inst_handle = vfe31_ctrl->outpath.out1.inst_handle;
 
-	vfe31_subdev_notify(id, path, image_mode);
+	vfe31_subdev_notify(id, path, inst_handle);
 	outch = vfe31_get_ch(path);
 	if (outch->free_buf.ch_paddr[0])
 		b = &outch->free_buf;
@@ -1318,14 +1319,14 @@
 {
 	struct vfe31_output_ch *outch = NULL;
 	int rc = 0;
-	uint32_t image_mode = 0;
+	uint32_t inst_handle = 0;
 
 	if (path == VFE_MSG_OUTPUT_PRIMARY)
-		image_mode = vfe31_ctrl->outpath.out0.image_mode;
+		inst_handle = vfe31_ctrl->outpath.out0.inst_handle;
 	else
-		image_mode = vfe31_ctrl->outpath.out1.image_mode;
+		inst_handle = vfe31_ctrl->outpath.out1.inst_handle;
 
-	vfe31_subdev_notify(id, path, image_mode);
+	vfe31_subdev_notify(id, path, inst_handle);
 	outch = vfe31_get_ch(path);
 	if (outch->ping.ch_paddr[0] && outch->pong.ch_paddr[0]) {
 		/* Configure Preview Ping Pong */
@@ -1477,16 +1478,26 @@
 	case VFE_CMD_START_RECORDING:
 		pr_info("vfe31_proc_general: cmdID = %s\n",
 			vfe31_general_cmd[cmd->id]);
+		if (copy_from_user(&temp1, (void __user *)(cmd->value),
+				sizeof(uint32_t))) {
+			pr_err("%s Error copying inst_handle for recording\n",
+				__func__);
+			rc = -EFAULT;
+			goto proc_general_done;
+		}
 		if (vfe31_ctrl->operation_mode ==
-			VFE_OUTPUTS_PREVIEW_AND_VIDEO)
+			VFE_OUTPUTS_PREVIEW_AND_VIDEO) {
+			vfe31_ctrl->outpath.out1.inst_handle = temp1;
 			rc = vfe31_configure_pingpong_buffers(
 				VFE_MSG_V31_START_RECORDING,
 				VFE_MSG_OUTPUT_SECONDARY);
-		else if (vfe31_ctrl->operation_mode ==
-			VFE_OUTPUTS_VIDEO_AND_PREVIEW)
+		} else if (vfe31_ctrl->operation_mode ==
+			VFE_OUTPUTS_VIDEO_AND_PREVIEW) {
+			vfe31_ctrl->outpath.out0.inst_handle = temp1;
 			rc = vfe31_configure_pingpong_buffers(
 				VFE_MSG_V31_START_RECORDING,
 				VFE_MSG_OUTPUT_PRIMARY);
+		}
 		if (rc < 0) {
 			pr_err("%s error configuring pingpong buffers"
 				" for video", __func__);
@@ -1916,6 +1927,14 @@
 		break;
 
 	case VFE_CMD_LIVESHOT:
+		if (copy_from_user(&temp1, (void __user *)(cmd->value),
+				sizeof(uint32_t))) {
+			pr_err("%s Error copying inst_handle for liveshot ",
+				__func__);
+			rc = -EFAULT;
+			goto proc_general_done;
+		}
+		vfe31_ctrl->outpath.out0.inst_handle = temp1;
 		/* Configure primary channel */
 		rc = vfe31_configure_pingpong_buffers(VFE_MSG_V31_CAPTURE,
 			VFE_MSG_OUTPUT_PRIMARY);
@@ -2715,12 +2734,12 @@
 }
 static void vfe_send_outmsg(struct v4l2_subdev *sd, uint8_t msgid,
 	uint32_t ch0_paddr, uint32_t ch1_paddr,
-	uint32_t ch2_paddr, uint32_t image_mode)
+	uint32_t ch2_paddr, uint32_t inst_handle)
 {
 	struct isp_msg_output msg;
 
 	msg.output_id		= msgid;
-	msg.buf.image_mode	= image_mode;
+	msg.buf.inst_handle	= inst_handle;
 	msg.buf.ch_paddr[0]	= ch0_paddr;
 	msg.buf.ch_paddr[1]	= ch1_paddr;
 	msg.buf.ch_paddr[2]	= ch2_paddr;
@@ -2803,7 +2822,7 @@
 		vfe_send_outmsg(&vfe31_ctrl->subdev,
 			MSG_ID_OUTPUT_PRIMARY, ch0_paddr,
 			ch1_paddr, ch2_paddr,
-			vfe31_ctrl->outpath.out0.image_mode);
+			vfe31_ctrl->outpath.out0.inst_handle);
 
 		if (vfe31_ctrl->liveshot_state == VFE_STATE_STOPPED)
 			vfe31_ctrl->liveshot_state = VFE_STATE_IDLE;
@@ -2876,7 +2895,7 @@
 		vfe_send_outmsg(&vfe31_ctrl->subdev,
 			MSG_ID_OUTPUT_SECONDARY, ch0_paddr,
 			ch1_paddr, ch2_paddr,
-			vfe31_ctrl->outpath.out1.image_mode);
+			vfe31_ctrl->outpath.out1.inst_handle);
 	} else {
 		vfe31_ctrl->outpath.out1.frame_drop_cnt++;
 		CDBG("path_irq_1 - no free buffer!\n");
diff --git a/drivers/media/video/msm/msm_vfe31_v4l2.h b/drivers/media/video/msm/msm_vfe31_v4l2.h
index 2cba995..6396966 100644
--- a/drivers/media/video/msm/msm_vfe31_v4l2.h
+++ b/drivers/media/video/msm/msm_vfe31_v4l2.h
@@ -217,10 +217,11 @@
 #define V31_OPERATION_CFG_LEN     32
 
 #define V31_AXI_OUT_OFF           0x00000038
-#define V31_AXI_OUT_LEN           212
-#define V31_AXI_CH_INF_LEN        24
+#define V31_AXI_OUT_LEN           240
+#define V31_AXI_CH_INF_LEN        48
 #define V31_AXI_CFG_LEN           47
 #define V31_AXI_RESERVED            1
+#define V31_AXI_RESERVED_LEN        4
 
 #define V31_FRAME_SKIP_OFF        0x00000504
 #define V31_FRAME_SKIP_LEN        32
@@ -696,7 +697,7 @@
 struct vfe31_output_ch {
 	struct list_head free_buf_queue;
 	spinlock_t free_buf_lock;
-	uint16_t image_mode;
+	uint32_t inst_handle;
 	int8_t ch0;
 	int8_t ch1;
 	int8_t ch2;
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index cbe1f15..38179e6 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.c
@@ -393,7 +393,7 @@
 		vfe32_ctrl->share_ctrl->vfebase + VFE_CAMIF_COMMAND);
 }
 
-static void vfe32_subdev_notify(int id, int path, int image_mode,
+static void vfe32_subdev_notify(int id, int path, uint32_t inst_handle,
 	struct v4l2_subdev *sd, struct vfe_share_ctrl_t *share_ctrl)
 {
 	struct msm_vfe_resp rp;
@@ -403,7 +403,7 @@
 	CDBG("vfe32_subdev_notify : msgId = %d\n", id);
 	memset(&rp, 0, sizeof(struct msm_vfe_resp));
 	rp.evt_msg.type   = MSM_CAMERA_MSG;
-	frame_info.image_mode = image_mode;
+	frame_info.inst_handle = inst_handle;
 	frame_info.path = path;
 	rp.evt_msg.data = &frame_info;
 	rp.type	   = id;
@@ -423,27 +423,27 @@
 	axi_ctrl->share_ctrl->outpath.out0.ch0 = 0x0000FFFF & *ch_info;
 	axi_ctrl->share_ctrl->outpath.out0.ch1 =
 		0x0000FFFF & (*ch_info++ >> 16);
-	axi_ctrl->share_ctrl->outpath.out0.ch2 = 0x0000FFFF & *ch_info;
-	axi_ctrl->share_ctrl->outpath.out0.image_mode =
-		0x0000FFFF & (*ch_info++ >> 16);
+	axi_ctrl->share_ctrl->outpath.out0.ch2 = 0x0000FFFF & *ch_info++;
+	axi_ctrl->share_ctrl->outpath.out0.inst_handle = *ch_info++;
+
 	axi_ctrl->share_ctrl->outpath.out1.ch0 = 0x0000FFFF & *ch_info;
 	axi_ctrl->share_ctrl->outpath.out1.ch1 =
 		0x0000FFFF & (*ch_info++ >> 16);
-	axi_ctrl->share_ctrl->outpath.out1.ch2 = 0x0000FFFF & *ch_info;
-	axi_ctrl->share_ctrl->outpath.out1.image_mode =
-		0x0000FFFF & (*ch_info++ >> 16);
+	axi_ctrl->share_ctrl->outpath.out1.ch2 = 0x0000FFFF & *ch_info++;
+	axi_ctrl->share_ctrl->outpath.out1.inst_handle = *ch_info++;
+
 	axi_ctrl->share_ctrl->outpath.out2.ch0 = 0x0000FFFF & *ch_info;
 	axi_ctrl->share_ctrl->outpath.out2.ch1 =
 		0x0000FFFF & (*ch_info++ >> 16);
-	axi_ctrl->share_ctrl->outpath.out2.ch2 = 0x0000FFFF & *ch_info;
-	axi_ctrl->share_ctrl->outpath.out2.image_mode =
-		0x0000FFFF & (*ch_info++ >> 16);
+	axi_ctrl->share_ctrl->outpath.out2.ch2 = 0x0000FFFF & *ch_info++;
+	axi_ctrl->share_ctrl->outpath.out2.inst_handle = *ch_info++;
+
 	axi_ctrl->share_ctrl->outpath.out3.ch0 = 0x0000FFFF & *ch_info;
 	axi_ctrl->share_ctrl->outpath.out3.ch1 =
 		0x0000FFFF & (*ch_info++ >> 16);
-	axi_ctrl->share_ctrl->outpath.out3.ch2 = 0x0000FFFF & *ch_info;
-	axi_ctrl->share_ctrl->outpath.out3.image_mode =
-		0x0000FFFF & (*ch_info++ >> 16);
+	axi_ctrl->share_ctrl->outpath.out3.ch2 = 0x0000FFFF & *ch_info++;
+	axi_ctrl->share_ctrl->outpath.out3.inst_handle = *ch_info++;
+
 	axi_ctrl->share_ctrl->outpath.output_mode = 0;
 
 	if (mode & OUTPUT_TERT1)
@@ -1468,18 +1468,18 @@
 {
 	struct vfe32_output_ch *outch = NULL;
 	struct msm_free_buf *b = NULL;
-	uint32_t image_mode = 0;
+	uint32_t inst_handle = 0;
 
 	if (path == VFE_MSG_OUTPUT_PRIMARY)
-		image_mode = axi_ctrl->share_ctrl->outpath.out0.image_mode;
+		inst_handle = axi_ctrl->share_ctrl->outpath.out0.inst_handle;
 	else if (path == VFE_MSG_OUTPUT_SECONDARY)
-		image_mode = axi_ctrl->share_ctrl->outpath.out1.image_mode;
+		inst_handle = axi_ctrl->share_ctrl->outpath.out1.inst_handle;
 	else if (path == VFE_MSG_OUTPUT_TERTIARY1)
-		image_mode = axi_ctrl->share_ctrl->outpath.out2.image_mode;
+		inst_handle = axi_ctrl->share_ctrl->outpath.out2.inst_handle;
 	else if (path == VFE_MSG_OUTPUT_TERTIARY2)
-		image_mode = axi_ctrl->share_ctrl->outpath.out3.image_mode;
+		inst_handle = axi_ctrl->share_ctrl->outpath.out3.inst_handle;
 
-	vfe32_subdev_notify(id, path, image_mode,
+	vfe32_subdev_notify(id, path, inst_handle,
 		&axi_ctrl->subdev, axi_ctrl->share_ctrl);
 	outch = vfe32_get_ch(path, axi_ctrl->share_ctrl);
 	if (outch->free_buf.ch_paddr[0])
@@ -1491,17 +1491,17 @@
 {
 	struct vfe32_output_ch *outch = NULL;
 	int rc = 0;
-	uint32_t image_mode = 0;
+	uint32_t inst_handle = 0;
 	if (path == VFE_MSG_OUTPUT_PRIMARY)
-		image_mode = vfe32_ctrl->share_ctrl->outpath.out0.image_mode;
+		inst_handle = vfe32_ctrl->share_ctrl->outpath.out0.inst_handle;
 	else if (path == VFE_MSG_OUTPUT_SECONDARY)
-		image_mode = vfe32_ctrl->share_ctrl->outpath.out1.image_mode;
+		inst_handle = vfe32_ctrl->share_ctrl->outpath.out1.inst_handle;
 	else if (path == VFE_MSG_OUTPUT_TERTIARY1)
-		image_mode = vfe32_ctrl->share_ctrl->outpath.out2.image_mode;
+		inst_handle = vfe32_ctrl->share_ctrl->outpath.out2.inst_handle;
 	else if (path == VFE_MSG_OUTPUT_TERTIARY2)
-		image_mode = vfe32_ctrl->share_ctrl->outpath.out3.image_mode;
+		inst_handle = vfe32_ctrl->share_ctrl->outpath.out3.inst_handle;
 
-	vfe32_subdev_notify(id, path, image_mode,
+	vfe32_subdev_notify(id, path, inst_handle,
 		&vfe32_ctrl->subdev, vfe32_ctrl->share_ctrl);
 	outch = vfe32_get_ch(path, vfe32_ctrl->share_ctrl);
 	if (outch->ping.ch_paddr[0] && outch->pong.ch_paddr[0]) {
@@ -1708,18 +1708,30 @@
 	case VFE_CMD_START_RECORDING:
 		pr_info("vfe32_proc_general: cmdID = %s\n",
 			vfe32_general_cmd[cmd->id]);
+		if (copy_from_user(&temp1, (void __user *)(cmd->value),
+				sizeof(uint32_t))) {
+			pr_err("%s Error copying inst_handle for recording\n",
+				__func__);
+			rc = -EFAULT;
+			goto proc_general_done;
+		}
 		if (vfe32_ctrl->share_ctrl->operation_mode &
-			VFE_OUTPUTS_PREVIEW_AND_VIDEO)
+			VFE_OUTPUTS_PREVIEW_AND_VIDEO) {
+			vfe32_ctrl->share_ctrl->outpath.out1.inst_handle =
+				temp1;
 			rc = vfe32_configure_pingpong_buffers(
 				VFE_MSG_V32_START_RECORDING,
 				VFE_MSG_OUTPUT_SECONDARY,
 				vfe32_ctrl);
-		else if (vfe32_ctrl->share_ctrl->operation_mode &
-			VFE_OUTPUTS_VIDEO_AND_PREVIEW)
+		} else if (vfe32_ctrl->share_ctrl->operation_mode &
+			VFE_OUTPUTS_VIDEO_AND_PREVIEW) {
+			vfe32_ctrl->share_ctrl->outpath.out0.inst_handle =
+				temp1;
 			rc = vfe32_configure_pingpong_buffers(
 				VFE_MSG_V32_START_RECORDING,
 				VFE_MSG_OUTPUT_PRIMARY,
 				vfe32_ctrl);
+		}
 		if (rc < 0) {
 			pr_err("%s error configuring pingpong buffers"
 				" for video", __func__);
@@ -2191,6 +2203,14 @@
 		break;
 
 	case VFE_CMD_LIVESHOT:
+		if (copy_from_user(&temp1, (void __user *)(cmd->value),
+				sizeof(uint32_t))) {
+			pr_err("%s Error copying inst_handle for liveshot ",
+				__func__);
+			rc = -EFAULT;
+			goto proc_general_done;
+		}
+		vfe32_ctrl->share_ctrl->outpath.out0.inst_handle = temp1;
 		/* Configure primary channel */
 		rc = vfe32_configure_pingpong_buffers(VFE_MSG_V32_CAPTURE,
 					VFE_MSG_OUTPUT_PRIMARY, vfe32_ctrl);
@@ -3456,12 +3476,12 @@
 static void vfe_send_outmsg(
 	struct axi_ctrl_t *axi_ctrl, uint8_t msgid,
 	uint32_t ch0_paddr, uint32_t ch1_paddr,
-	uint32_t ch2_paddr, uint32_t image_mode)
+	uint32_t ch2_paddr, uint32_t inst_handle)
 {
 	struct isp_msg_output msg;
 
 	msg.output_id = msgid;
-	msg.buf.image_mode = image_mode;
+	msg.buf.inst_handle = inst_handle;
 	msg.buf.ch_paddr[0]	= ch0_paddr;
 	msg.buf.ch_paddr[1]	= ch1_paddr;
 	msg.buf.ch_paddr[2]	= ch2_paddr;
@@ -3563,7 +3583,7 @@
 		vfe_send_outmsg(axi_ctrl,
 			MSG_ID_OUTPUT_PRIMARY, ch0_paddr,
 			ch1_paddr, ch2_paddr,
-			axi_ctrl->share_ctrl->outpath.out0.image_mode);
+			axi_ctrl->share_ctrl->outpath.out0.inst_handle);
 
 	} else {
 		axi_ctrl->share_ctrl->outpath.out0.frame_drop_cnt++;
@@ -3641,7 +3661,7 @@
 		vfe_send_outmsg(axi_ctrl,
 			MSG_ID_OUTPUT_SECONDARY, ch0_paddr,
 			ch1_paddr, ch2_paddr,
-			axi_ctrl->share_ctrl->outpath.out1.image_mode);
+			axi_ctrl->share_ctrl->outpath.out1.inst_handle);
 
 	} else {
 		axi_ctrl->share_ctrl->outpath.out1.frame_drop_cnt++;
@@ -3682,7 +3702,7 @@
 			vfe_send_outmsg(axi_ctrl,
 				MSG_ID_OUTPUT_TERTIARY1, ch0_paddr,
 				0, 0,
-				axi_ctrl->share_ctrl->outpath.out2.image_mode);
+				axi_ctrl->share_ctrl->outpath.out2.inst_handle);
 
 		} else {
 			axi_ctrl->share_ctrl->outpath.out2.frame_drop_cnt++;
@@ -3723,7 +3743,7 @@
 			vfe_send_outmsg(axi_ctrl,
 				MSG_ID_OUTPUT_TERTIARY2, ch0_paddr,
 				0, 0,
-				axi_ctrl->share_ctrl->outpath.out3.image_mode);
+				axi_ctrl->share_ctrl->outpath.out3.inst_handle);
 		} else {
 			axi_ctrl->share_ctrl->outpath.out3.frame_drop_cnt++;
 			pr_err("path_irq irq - no free buffer for rdi1!\n");
diff --git a/drivers/media/video/msm/msm_vfe32.h b/drivers/media/video/msm/msm_vfe32.h
index 3196eda..9336cfb 100644
--- a/drivers/media/video/msm/msm_vfe32.h
+++ b/drivers/media/video/msm/msm_vfe32.h
@@ -241,8 +241,8 @@
 #define V32_OPERATION_CFG_LEN     44
 
 #define V32_AXI_OUT_OFF           0x00000038
-#define V32_AXI_OUT_LEN           224
-#define V32_AXI_CH_INF_LEN        32
+#define V32_AXI_OUT_LEN           240
+#define V32_AXI_CH_INF_LEN        48
 #define V32_AXI_CFG_LEN           47
 #define V32_AXI_BUS_FMT_OFF    1
 #define V32_AXI_BUS_FMT_LEN    4
@@ -756,7 +756,7 @@
 struct vfe32_output_ch {
 	struct list_head free_buf_queue;
 	spinlock_t free_buf_lock;
-	uint16_t image_mode;
+	uint32_t inst_handle;
 	int8_t ch0;
 	int8_t ch1;
 	int8_t ch2;
diff --git a/drivers/media/video/msm/msm_vfe7x27a_v4l2.c b/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
index 3701331..64e0385 100644
--- a/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
+++ b/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
@@ -585,7 +585,7 @@
 	struct isp_msg_output msg;
 
 	msg.output_id = msgid;
-	msg.buf.image_mode = -1;
+	msg.buf.inst_handle = 0;
 	msg.buf.ch_paddr[0]     = ch0_paddr;
 	msg.buf.ch_paddr[1]     = ch1_paddr;
 	msg.frameCounter = vfe2x_ctrl->vfeFrameId;
diff --git a/drivers/media/video/msm/server/msm_cam_server.c b/drivers/media/video/msm/server/msm_cam_server.c
index 2dfdd7e..755ed9a 100644
--- a/drivers/media/video/msm/server/msm_cam_server.c
+++ b/drivers/media/video/msm/server/msm_cam_server.c
@@ -423,6 +423,7 @@
 	plane_info.buffer_type = pfmt->type;
 	plane_info.ext_mode = pcam->dev_inst[idx]->image_mode;
 	plane_info.num_planes = 1;
+	plane_info.inst_handle = pcam->dev_inst[idx]->inst_handle;
 	D("%s: %d, %d, 0x%x\n", __func__,
 		pfmt->fmt.pix.width, pfmt->fmt.pix.height,
 		pfmt->fmt.pix.pixelformat);
@@ -479,6 +480,8 @@
 	plane_info.buffer_type = pfmt->type;
 	plane_info.ext_mode = pcam->dev_inst[idx]->image_mode;
 	plane_info.num_planes = pix_mp->num_planes;
+	plane_info.inst_handle = pcam->dev_inst[idx]->inst_handle;
+
 	if (plane_info.num_planes <= 0 ||
 		plane_info.num_planes > VIDEO_MAX_PLANES) {
 		pr_err("%s Invalid number of planes set %d", __func__,
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index 80e1bf8..ae81dcd 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -210,6 +210,9 @@
 #define MSM_CAM_IOCTL_UNSET_MCTL_SDEV \
 	_IOW(MSM_CAM_IOCTL_MAGIC, 59, struct msm_mctl_set_sdev_data *)
 
+#define MSM_CAM_IOCTL_GET_INST_HANDLE \
+	_IOR(MSM_CAM_IOCTL_MAGIC, 60, uint32_t *)
+
 struct msm_stats_reqbuf {
 	int num_buf;		/* how many buffers requested */
 	int stats_type;	/* stats type */
@@ -340,6 +343,7 @@
 		struct msm_pp_frame_mp mp[MAX_PLANES];
 	};
 	int node_type;
+	uint32_t inst_handle;
 };
 
 struct msm_cam_evt_divert_frame {
@@ -773,7 +777,7 @@
 #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_MMAP_ENTRY             (V4L2_CID_PRIVATE_BASE+16)
+#define MSM_V4L2_PID_INST_HANDLE            (V4L2_CID_PRIVATE_BASE+16)
 #define MSM_V4L2_PID_MMAP_INST              (V4L2_CID_PRIVATE_BASE+17)
 #define MSM_V4L2_PID_PP_PLANE_INFO          (V4L2_CID_PRIVATE_BASE+18)
 #define MSM_V4L2_PID_MAX                    MSM_V4L2_PID_PP_PLANE_INFO
@@ -1629,7 +1633,7 @@
 	uint8_t num_planes;
 	struct plane_data plane[MAX_PLANES];
 	uint32_t sp_y_offset;
-	uint8_t vpe_can_use;
+	uint32_t inst_handle;
 };
 
 #define QCAMERA_NAME "qcamera"
@@ -1682,6 +1686,9 @@
 #define MSM_CAM_V4L2_IOCTL_PRIVATE_S_CTRL \
 	_IOWR('V', BASE_VIDIOC_PRIVATE + 8, struct msm_camera_v4l2_ioctl_t)
 
+#define MSM_CAM_V4L2_IOCTL_PRIVATE_G_CTRL \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 9, struct msm_camera_v4l2_ioctl_t)
+
 #define VIDIOC_MSM_VPE_INIT \
 	_IO('V', BASE_VIDIOC_PRIVATE + 15)
 
@@ -1862,4 +1869,38 @@
 
 #define V4L2_EVENT_CPP_FRAME_DONE  (V4L2_EVENT_PRIVATE_START + 0)
 
+/* Instance Handle - inst_handle
+ * Data bundle containing the information about where
+ * to get a buffer for a particular camera instance.
+ * This is a bitmask containing the following data:
+ * Buffer Handle Bitmask:
+ *      ------------------------------------
+ *      Bits    :  Purpose
+ *      ------------------------------------
+ *      31 - 24 :  Reserved.
+ *      23      :  is Image mode valid?
+ *      22 - 16 :  Image mode.
+ *      15      :  is MCTL PP inst idx valid?
+ *      14 - 8  :  MCTL PP inst idx.
+ *      7       :  is Video inst idx valid?
+ *      6 - 0   :  Video inst idx.
+ */
+#define CLR_IMG_MODE(handle)	(handle &= 0xFF00FFFF)
+#define SET_IMG_MODE(handle, data)	\
+	(handle |= ((0x1 << 23) | ((data & 0x7F) << 16)))
+#define GET_IMG_MODE(handle)	\
+	((handle & 0x800000) ? ((handle & 0x7F0000) >> 16) : 0xFF)
+
+#define CLR_MCTLPP_INST_IDX(handle)	(handle &= 0xFFFF00FF)
+#define SET_MCTLPP_INST_IDX(handle, data)	\
+	(handle |= ((0x1 << 15) | ((data & 0x7F) << 8)))
+#define GET_MCTLPP_INST_IDX(handle)	\
+	((handle & 0x8000) ? ((handle & 0x7F00) >> 8) : 0xFF)
+
+#define CLR_VIDEO_INST_IDX(handle)	(handle &= 0xFFFFFF00)
+#define GET_VIDEO_INST_IDX(handle)	\
+	((handle & 0x80) ? (handle & 0x7F) : 0xFF)
+#define SET_VIDEO_INST_IDX(handle, data)	\
+	(handle |= (0x1 << 7) | (data & 0x7F))
+
 #endif /* __LINUX_MSM_CAMERA_H */
diff --git a/include/media/msm_isp.h b/include/media/msm_isp.h
index 1f3527b..3df6ded 100644
--- a/include/media/msm_isp.h
+++ b/include/media/msm_isp.h
@@ -336,7 +336,7 @@
 #define VFE_OUTPUTS_RDI1                BIT(12)
 
 struct msm_frame_info {
-	uint32_t image_mode;
+	uint32_t inst_handle;
 	uint32_t path;
 };