msm camera: migrate to videobuf2 framework

add necessary changes in camera driver to
migrate to videobuf2 framework.

Signed-off-by: Kiran Kumar H N <hurlisal@codeaurora.org>
Signed-off-by: Mingcheng Zhu <mingchen@codeaurora.org>

Conflicts:

	drivers/media/video/Makefile
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index 724c7a3..c4b240f 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -10,8 +10,11 @@
 
 omap2cam-objs	:=	omap24xxcam.o omap24xxcam-dma.o
 
-videodev-objs	:=	v4l2-dev.o v4l2-ioctl.o v4l2-device.o   v4l2-fh.o \
-			v4l2-event.o v4l2-ctrls.o v4l2-subdev.o videobuf-core.o videobuf-msm-mem.o videobuf-dma-contig.o
+videodev-objs	:=	v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o \
+			v4l2-event.o v4l2-ctrls.o v4l2-subdev.o videobuf2-core.o \
+			videobuf2-memops.o videobuf2-msm-mem.o videobuf2-dma-contig.o \
+			videobuf2-vmalloc.o videobuf2-dma-sg.o
+
 
 # V4L2 core modules
 
diff --git a/drivers/media/video/msm/Makefile b/drivers/media/video/msm/Makefile
index 0e8054f..24fbcda 100644
--- a/drivers/media/video/msm/Makefile
+++ b/drivers/media/video/msm/Makefile
@@ -4,7 +4,7 @@
 endif
 
 ifeq ($(CONFIG_MSM_CAMERA_V4L2),y)
-  obj-$(CONFIG_MSM_CAMERA) += msm_isp.o msm.o msm_mem.o msm_mctl.o
+  obj-$(CONFIG_MSM_CAMERA) += msm_isp.o msm.o msm_mem.o msm_mctl.o msm_mctl_buf.o
 else
   obj-$(CONFIG_MSM_CAMERA) += msm_camera.o
 endif
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index c42f97b..6ded98b 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -265,7 +265,6 @@
 							pix->pixelformat;
 		pcam->dev_inst[idx]->vid_fmt.fmt.pix.bytesperline =
 							pix->bytesperline;
-		pcam->dev_inst[idx]->vid_bufq.field   = pix->field;
 		pcam->dev_inst[idx]->sensor_pxlcode
 					= pcam->usr_fmts[i].pxlcode;
 		D("%s:inst=0x%x,idx=%d,width=%d,heigth=%d\n",
@@ -608,36 +607,12 @@
 				struct v4l2_requestbuffers *pb)
 {
 	int rc = 0;
-	int i = 0;
-	/*struct msm_cam_v4l2_device *pcam  = video_drvdata(f);*/
-	struct msm_cam_v4l2_dev_inst *pcam_inst  = f->private_data;
-
+	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);
-
-	if (!pb->count) {
-		if (pcam_inst->vid_bufq.streaming)
-			videobuf_stop(&pcam_inst->vid_bufq);
-		else
-			videobuf_queue_cancel(&pcam_inst->vid_bufq);
-
-		/* free the queue: function name is ambiguous it frees all
-		types of buffers (mmap or userptr - it doesn't matter) */
-		rc = videobuf_mmap_free(&pcam_inst->vid_bufq);
-	} else {
-		rc = videobuf_reqbufs(&pcam_inst->vid_bufq, pb);
-		if (rc < 0)
-			return rc;
-		/* Now initialize the local msm_frame_buffer structure */
-		for (i = 0; i < pb->count; i++) {
-			struct msm_frame_buffer *buf = container_of(
-						pcam_inst->vid_bufq.bufs[i],
-						struct msm_frame_buffer,
-						vidbuf);
-			buf->inuse = 0;
-			INIT_LIST_HEAD(&buf->vidbuf.queue);
-		}
-	}
+	rc = vb2_reqbufs(&pcam_inst->vid_bufq, pb);
 	pcam_inst->buf_count = pb->count;
 	return rc;
 }
@@ -646,12 +621,13 @@
 					struct v4l2_buffer *pb)
 {
 	/* get the video device */
-	struct msm_cam_v4l2_dev_inst *pcam_inst  = f->private_data;
+	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);
-
-	return videobuf_querybuf(&pcam_inst->vid_bufq, pb);
+	return vb2_querybuf(&pcam_inst->vid_bufq, pb);
 }
 
 static int msm_camera_v4l2_qbuf(struct file *f, void *pctx,
@@ -659,12 +635,17 @@
 {
 	int rc = 0;
 	/* get the camera device */
-	struct msm_cam_v4l2_dev_inst *pcam_inst  = f->private_data;
+	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);
 
-	rc = videobuf_qbuf(&pcam_inst->vid_bufq, pb);
+	D("%s stored reserved info %d", __func__, pb->reserved);
+	pcam_inst->buf_offset[pb->index] = pb->reserved;
+
+	rc = vb2_qbuf(&pcam_inst->vid_bufq, pb);
 	D("%s, videobuf_qbuf returns %d\n", __func__, rc);
 
 	return rc;
@@ -675,12 +656,14 @@
 {
 	int rc = 0;
 	/* get the camera device */
-	struct msm_cam_v4l2_dev_inst *pcam_inst  = f->private_data;
+	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);
 
-	rc = videobuf_dqbuf(&pcam_inst->vid_bufq, pb, f->f_flags & O_NONBLOCK);
+	rc = vb2_dqbuf(&pcam_inst->vid_bufq, pb,  f->f_flags & O_NONBLOCK);
 	D("%s, videobuf_dqbuf returns %d\n", __func__, rc);
 
 	return rc;
@@ -690,18 +673,18 @@
 					enum v4l2_buf_type i)
 {
 	int rc = 0;
-	struct videobuf_buffer *buf;
-	int cnt = 0;
 	/* get the camera device */
 	struct msm_cam_v4l2_device *pcam  = video_drvdata(f);
-	struct msm_cam_v4l2_dev_inst *pcam_inst  = f->private_data;
+	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);
 
 	D("%s Calling videobuf_streamon", __func__);
 	/* if HW streaming on is successful, start buffer streaming */
-	rc = videobuf_streamon(&pcam_inst->vid_bufq);
+	rc = vb2_streamon(&pcam_inst->vid_bufq, V4L2_BUF_TYPE_VIDEO_CAPTURE);
 	D("%s, videobuf_streamon returns %d\n", __func__, rc);
 
 	mutex_lock(&pcam->vid_lock);
@@ -709,16 +692,8 @@
 	rc = msm_server_streamon(pcam, pcam_inst->my_index);
 	mutex_unlock(&pcam->vid_lock);
 	D("%s rc = %d\n", __func__, rc);
-	if (rc < 0) {
+	if (rc < 0)
 		pr_err("%s: hw failed to start streaming\n", __func__);
-		return rc;
-	}
-
-	list_for_each_entry(buf, &pcam_inst->vid_bufq.stream, stream) {
-		D("%s index %d, state %d\n", __func__, cnt, buf->state);
-		cnt++;
-	}
-
 	return rc;
 }
 
@@ -728,7 +703,9 @@
 	int rc = 0;
 	/* get the camera device */
 	struct msm_cam_v4l2_device *pcam  = video_drvdata(f);
-	struct msm_cam_v4l2_dev_inst *pcam_inst  = f->private_data;
+	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);
@@ -742,7 +719,7 @@
 		pr_err("%s: hw failed to stop streaming\n", __func__);
 
 	/* stop buffer streaming */
-	rc = videobuf_streamoff(&pcam_inst->vid_bufq);
+	rc = vb2_streamoff(&pcam_inst->vid_bufq, V4L2_BUF_TYPE_VIDEO_CAPTURE);
 	D("%s, videobuf_streamoff returns %d\n", __func__, rc);
 
 	return rc;
@@ -783,7 +760,9 @@
 	int rc = 0;
 	/* get the video device */
 	struct msm_cam_v4l2_device *pcam  = video_drvdata(f);
-	struct msm_cam_v4l2_dev_inst *pcam_inst  = f->private_data;
+	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);
@@ -829,7 +808,9 @@
 	void __user *uptr;
 	/* get the video device */
 	struct msm_cam_v4l2_device *pcam  = video_drvdata(f);
-	struct msm_cam_v4l2_dev_inst *pcam_inst  = f->private_data;
+	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__);
 	D("%s, inst=0x%x,idx=%d,priv = 0x%p\n",
@@ -950,7 +931,9 @@
 				struct v4l2_streamparm *a)
 {
 	int rc = 0;
-	struct msm_cam_v4l2_dev_inst *pcam_inst  = f->private_data;
+	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->pcam->dev_inst_map[pcam_inst->image_mode] = pcam_inst;
 	pcam_inst->path = msm_vidbuf_get_path(pcam_inst->image_mode);
@@ -1197,8 +1180,7 @@
 		return rc;
 	}
 
-
-	f->private_data = pcam_inst;
+	f->private_data = &pcam_inst->eventHandle;
 
 	D("f->private_data = 0x%x, pcam = 0x%x\n",
 		(u32)f->private_data, (u32)pcam_inst);
@@ -1220,12 +1202,13 @@
 static int msm_mmap(struct file *f, struct vm_area_struct *vma)
 {
 	int rc = 0;
-	struct msm_cam_v4l2_dev_inst *pcam_inst  = f->private_data;
+	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	pcam_inst = container_of(f->private_data,
+		struct msm_cam_v4l2_dev_inst, eventHandle);
 
 	D("mmap called, vma=0x%08lx\n", (unsigned long)vma);
 
-	rc = videobuf_mmap_mapper(&pcam_inst->vid_bufq, vma);
-
+	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,
@@ -1237,9 +1220,11 @@
 static int msm_close(struct file *f)
 {
 	int rc = 0;
-	struct msm_cam_v4l2_device *pcam  = video_drvdata(f);
-	struct msm_cam_v4l2_dev_inst *pcam_inst  = f->private_data;
-
+	struct msm_cam_v4l2_device *pcam;
+	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	pcam_inst = container_of(f->private_data,
+		struct msm_cam_v4l2_dev_inst, eventHandle);
+	pcam = pcam_inst->pcam;
 	D("%s\n", __func__);
 	if (!pcam) {
 		pr_err("%s NULL pointer of camera device!\n", __func__);
@@ -1250,12 +1235,7 @@
 	mutex_lock(&pcam->vid_lock);
 	pcam->use_count--;
 	pcam->dev_inst_map[pcam_inst->image_mode] = NULL;
-	videobuf_stop(&pcam_inst->vid_bufq);
-	/* free the queue: function name is ambiguous it frees all
-	types of buffers (mmap or userptr - it doesn't matter) */
-	rc = videobuf_mmap_free(&pcam_inst->vid_bufq);
-	if (rc  < 0)
-		pr_err("%s: unable to free buffers\n", __func__);
+	vb2_queue_release(&pcam_inst->vid_bufq);
 	pcam->dev_inst[pcam_inst->my_index] = NULL;
 	kfree(pcam_inst);
 	f->private_data = NULL;
@@ -1286,9 +1266,11 @@
 static unsigned int msm_poll(struct file *f, struct poll_table_struct *wait)
 {
 	int rc = 0;
-	struct msm_cam_v4l2_device *pcam  = video_drvdata(f);
-	struct msm_cam_v4l2_dev_inst *pcam_inst  = f->private_data;
-
+	struct msm_cam_v4l2_device *pcam;
+	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	pcam_inst = container_of(f->private_data,
+		struct msm_cam_v4l2_dev_inst, eventHandle);
+	pcam = pcam_inst->pcam;
 	D("%s\n", __func__);
 	if (!pcam) {
 		pr_err("%s NULL pointer of camera device!\n", __func__);
@@ -1301,7 +1283,7 @@
 		return -EINVAL;
 	}
 
-	rc |= videobuf_poll_stream(f, &pcam_inst->vid_bufq, wait);
+	rc |= vb2_poll(&pcam_inst->vid_bufq, f, wait);
 	D("%s returns, rc  = 0x%x\n", __func__, rc);
 
 	return rc;
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index 0049cc1..7390f10 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -26,8 +26,8 @@
 #include <media/v4l2-fh.h>
 #include <media/v4l2-event.h>
 #include <media/v4l2-mediabus.h>
-#include <media/videobuf-dma-contig.h>
-#include <media/videobuf-msm-mem.h>
+#include <media/videobuf2-dma-contig.h>
+#include <media/videobuf2-msm-mem.h>
 #include <mach/camera.h>
 
 #define MSM_V4L2_DIMENSION_SIZE 96
@@ -98,7 +98,8 @@
 /* buffer for one video frame */
 struct msm_frame_buffer {
 	/* common v4l buffer stuff -- must be first */
-	struct videobuf_buffer    vidbuf;
+	struct vb2_buffer         vidbuf;
+	struct list_head		  list;
 	enum v4l2_mbus_pixelcode  pxlcode;
 	int                       inuse;
 	int                       active;
@@ -138,11 +139,12 @@
 
 extern int msm_ispif_init_module(struct msm_ispif_ops *p_ispif);
 
-/*"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, (such as IPIF on 8960, or none on 8660)
-   plus other extra sub devices such as VPE and flash
-*/
+/* "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,
+ * (such as IPIF on 8960, or none on 8660) plus other extra
+ * sub devices such as VPE and flash.
+ */
 
 struct msm_cam_media_controller {
 
@@ -155,7 +157,7 @@
 					unsigned int cmd, unsigned long arg);
 	int (*mctl_release)(struct msm_cam_media_controller *p_mctl);
 	int (*mctl_vidbuf_init)(struct msm_cam_v4l2_dev_inst *pcam,
-						struct videobuf_queue *);
+						struct vb2_queue *q);
 	int (*mctl_ufmt_init)(struct msm_cam_media_controller *p_mctl);
 
 	struct v4l2_device v4l2_dev;
@@ -203,18 +205,27 @@
 	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 videobuf_queue vid_bufq;
-	spinlock_t vb_irqlock;
+	struct v4l2_fh  eventHandle;
+	struct vb2_queue vid_bufq;
+	spinlock_t vq_irqlock;
+	struct list_head free_vq;
 	struct v4l2_format vid_fmt;
-	/* senssor pixel code*/
+	/* sensor pixel code*/
 	enum v4l2_mbus_pixelcode sensor_pxlcode;
 	struct msm_cam_v4l2_device *pcam;
 	int my_index;
 	int image_mode;
 	int path;
 	int buf_count;
+	/* buffer offset, if any */
+	uint32_t buf_offset[VIDEO_MAX_FRAME];
 };
 #define MSM_MAX_IMG_MODE                5
 /* abstract camera device for each sensor successfully probed*/
@@ -339,9 +350,12 @@
 int msm_isp_init_module(int g_num_config_nodes);
 
 int msm_mctl_init_module(struct msm_cam_v4l2_device *pcam);
+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, uint32_t y_phy);
+int msm_mctl_fetch_free_buf(struct msm_cam_media_controller *pmctl,
+				int path, struct msm_free_buf *free_buf);
 /*Memory(PMEM) functions*/
 int msm_register_pmem(struct hlist_head *ptype, void __user *arg);
 int msm_pmem_table_del(struct hlist_head *ptype, void __user *arg);
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index 35cb68a..4875d6d 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -82,337 +82,6 @@
 	},
 
 };
-/* master controller instance counter
-static atomic_t mctl_instance = ATOMIC_INIT(0);
-*/
-
-static int buffer_size(int width, int height, int pixelformat)
-{
-	int size;
-
-	switch (pixelformat) {
-	case V4L2_PIX_FMT_NV21:
-	case V4L2_PIX_FMT_NV12:
-		size = width * height * 3/2;
-		break;
-	case V4L2_PIX_FMT_SBGGR10:
-	case V4L2_PIX_FMT_SGBRG10:
-	case V4L2_PIX_FMT_SGRBG10:
-	case V4L2_PIX_FMT_SRGGB10:
-		size = width * height;
-		break;
-	default:
-		pr_err("%s: pixelformat %d not supported.\n",
-			__func__, pixelformat);
-		size = -EINVAL;
-	}
-
-	return size;
-}
-/*
- *  Videobuf operations
- */
-
-static void free_buffer(struct videobuf_queue *vq,
-			struct msm_frame_buffer *buf)
-{
-	struct videobuf_buffer *vb = &buf->vidbuf;
-
-	BUG_ON(in_interrupt());
-
-	D("%s (vb=0x%p) 0x%08lx %d\n", __func__,
-			vb, vb->baddr, vb->bsize);
-
-	/* This waits until this buffer is out of danger, i.e.,
-	 * until it is no longer in STATE_QUEUED or STATE_ACTIVE */
-	videobuf_waiton(vq, vb, 0, 0);
-	videobuf_pmem_contig_free(vq, vb);
-	vb->state = VIDEOBUF_NEEDS_INIT;
-}
-
-/* Setup # of buffers and size of each buffer for the videobuf_queue.
-   This is called when videobuf_reqbufs() is called, so this function
-   should tell how many buffer should be used and how big the size is.
-
-   The caller will allocate the real buffers, either in user space or
-   in kernel */
-static int msm_vidbuf_setup(struct videobuf_queue *vq, unsigned int *count,
-							unsigned int *size)
-{
-	/* get the video device */
-	struct msm_cam_v4l2_dev_inst *pcam_inst = vq->priv_data;
-	struct msm_cam_v4l2_device *pcam = NULL;
-
-	pcam = pcam_inst->pcam;
-
-	D("%s\n", __func__);
-	if (!pcam || !count || !size) {
-		pr_err("%s error : invalid input\n", __func__);
-		return -EINVAL;
-	}
-
-	D("%s, inst=0x%x,idx=%d, width = %d\n", __func__,
-		(u32)pcam_inst, pcam_inst->my_index,
-		pcam_inst->vid_fmt.fmt.pix.width);
-	D("%s, inst=0x%x,idx=%d, height = %d\n", __func__,
-		(u32)pcam_inst, pcam_inst->my_index,
-		pcam_inst->vid_fmt.fmt.pix.height);
-	*size = buffer_size(pcam_inst->vid_fmt.fmt.pix.width,
-				pcam_inst->vid_fmt.fmt.pix.height,
-				pcam_inst->vid_fmt.fmt.pix.pixelformat);
-	D("%s:inst=0x%x,idx=%d,count=%d, size=%d\n", __func__,
-		(u32)pcam_inst, pcam_inst->my_index, *count, *size);
-	return 0;
-}
-
-/* Prepare the buffer before it is put into the videobuf_queue for streaming.
-   This is called when videobuf_qbuf() is called, so this function should
-   setup the video buffer to receieve the VFE output. */
-static int msm_vidbuf_prepare(struct videobuf_queue *vq,
-	struct videobuf_buffer *vb, enum v4l2_field field)
-{
-	int rc = 0;
-	/*struct msm_cam_v4l2_device *pcam = vq->priv_data;*/
-	struct msm_cam_v4l2_dev_inst *pcam_inst = NULL;
-	struct msm_cam_v4l2_device *pcam = NULL;
-	struct msm_frame_buffer *buf = NULL;
-
-	D("%s\n", __func__);
-	if (!vb || !vq) {
-		pr_err("%s error : input is NULL\n", __func__);
-		return -EINVAL;
-	}
-	pcam_inst = vq->priv_data;
-	pcam = pcam_inst->pcam;
-	buf = container_of(vb, struct msm_frame_buffer, vidbuf);
-
-	if (!pcam || !buf) {
-		pr_err("%s error : pointer is NULL\n", __func__);
-		return -EINVAL;
-	}
-
-	D("%s (vb=0x%p) 0x%08lx %d\n", __func__,
-		vb, vb->baddr, vb->bsize);
-
-	/* by this time vid_fmt should be already set */
-	/* return error if it is not */
-	if ((pcam_inst->vid_fmt.fmt.pix.width == 0) ||
-		(pcam_inst->vid_fmt.fmt.pix.height == 0)) {
-		pr_err("%s error : pcam vid_fmt is not set\n", __func__);
-		return -EINVAL;
-	}
-
-	buf->inuse = 1;
-
-	D("buf->pxlcode=%d, pcam->sensor_pxlcode=%d, vb->width=%d,"
-		"pcam->vid_fmt.fmt.pix.width = %d, vb->height = %d,"
-		"pcam->vid_fmt.fmt.pix.height=%d, vb->field=%d, field=%d\n",
-		buf->pxlcode, pcam_inst->sensor_pxlcode, vb->width,
-		pcam_inst->vid_fmt.fmt.pix.width, vb->height,
-		pcam_inst->vid_fmt.fmt.pix.height, vb->field, field);
-
-	if (buf->pxlcode != pcam_inst->sensor_pxlcode ||
-		vb->width   != pcam_inst->vid_fmt.fmt.pix.width ||
-		vb->height	!= pcam_inst->vid_fmt.fmt.pix.height ||
-		vb->field   != field) {
-		buf->pxlcode  = pcam_inst->sensor_pxlcode;
-		vb->width = pcam_inst->vid_fmt.fmt.pix.width;
-		vb->height  = pcam_inst->vid_fmt.fmt.pix.height;
-		vb->field = field;
-		vb->state = VIDEOBUF_NEEDS_INIT;
-		D("VIDEOBUF_NEEDS_INIT\n");
-	}
-
-	vb->size = buffer_size(pcam_inst->vid_fmt.fmt.pix.width, vb->height,
-				pcam_inst->vid_fmt.fmt.pix.pixelformat);
-
-	D("vb->size=%lu, vb->bsize=%u, vb->baddr=0x%x\n",
-		vb->size, vb->bsize, (uint32_t)vb->baddr);
-
-	if (0 != vb->baddr && vb->bsize < vb->size) {
-		pr_err("Something wrong vb->size=%lu, vb->bsize=%u,\
-					vb->baddr=0x%x\n",
-					vb->size, vb->bsize,
-					(uint32_t)vb->baddr);
-		rc = -EINVAL;
-		goto out;
-	}
-
-	if (vb->state == VIDEOBUF_NEEDS_INIT) {
-		rc = videobuf_iolock(vq, vb, NULL);
-		if (rc)
-			goto fail;
-		D("%s: setting buffer state to prepared\n", __func__);
-		vb->state = VIDEOBUF_PREPARED;
-	}
-
-	buf->inuse = 0;
-
-	/* finally if everything is oK, set the VIDEOBUF_PREPARED state*/
-	if (0 == rc)
-		vb->state = VIDEOBUF_PREPARED;
-	return rc;
-
-fail:
-	free_buffer(vq, buf);
-
-out:
-	buf->inuse = 0;
-	return rc;
-}
-
-/* Called under spin_lock_irqsave(q->irqlock, flags) in videobuf-core.c*/
-static void msm_vidbuf_queue(struct videobuf_queue *vq,
-				struct videobuf_buffer *vb)
-{
-	/*struct msm_cam_v4l2_device *pcam = vq->priv_data;*/
-	struct msm_cam_v4l2_dev_inst *pcam_inst = NULL;
-	struct msm_cam_v4l2_device *pcam = NULL;
-	unsigned long phyaddr = 0;
-	int rc;
-
-	D("%s\n", __func__);
-	if (!vb || !vq) {
-		pr_err("%s error : input is NULL\n", __func__);
-		return ;
-	}
-	pcam_inst = vq->priv_data;
-	pcam = pcam_inst->pcam;
-	if (!pcam) {
-		pr_err("%s error : pcam is NULL\n", __func__);
-		return;
-	}
-	D("%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize);
-
-
-	vb->state = VIDEOBUF_QUEUED;
-	if (vq->streaming) {
-		struct msm_frame frame;
-		struct msm_vfe_cfg_cmd cfgcmd;
-		/* we are returning a buffer to the queue */
-		struct videobuf_contig_pmem *mem = vb->priv;
-		/* get the physcial address of the buffer */
-		phyaddr = (unsigned long) videobuf_to_pmem_contig(vb);
-
-		D("%s buffer type is %d\n", __func__, mem->buffer_type);
-		frame.path = pcam_inst->path;
-		frame.buffer = 0;
-		frame.y_off = mem->y_off;
-		frame.cbcr_off = mem->cbcr_off;
-
-		/* now release frame to vfe */
-		cfgcmd.cmd_type = CMD_FRAME_BUF_RELEASE;
-		cfgcmd.value    = (void *)&frame;
-		/* yyan: later change to mctl APIs*/
-		rc = msm_isp_subdev_ioctl(&pcam->mctl.isp_sdev->sd,
-			&cfgcmd, &phyaddr);
-	}
-}
-
-/* This will be called when streamingoff is called. */
-static void msm_vidbuf_release(struct videobuf_queue *vq,
-				struct videobuf_buffer *vb)
-{
-	struct msm_cam_v4l2_dev_inst *pcam_inst = vq->priv_data;
-	struct msm_cam_v4l2_device *pcam = pcam_inst->pcam;
-	struct msm_frame_buffer *buf = container_of(vb, struct msm_frame_buffer,
-									vidbuf);
-
-	D("%s\n", __func__);
-	if (!pcam || !vb || !vq) {
-		pr_err("%s error : input is NULL\n", __func__);
-		return ;
-	}
-#ifdef DEBUG
-	D("%s (vb=0x%p) 0x%08lx %d\n", __func__,
-		vb, vb->baddr, vb->bsize);
-
-	switch (vb->state) {
-	case VIDEOBUF_ACTIVE:
-		D("%s (active)\n", __func__);
-		break;
-	case VIDEOBUF_QUEUED:
-		D("%s (queued)\n", __func__);
-		break;
-	case VIDEOBUF_PREPARED:
-		D("%s (prepared)\n", __func__);
-		break;
-	default:
-		D("%s (unknown) state = %d\n", __func__, vb->state);
-		break;
-	}
-#endif
-
-	/* free the buffer */
-	free_buffer(vq, buf);
-}
-
-
-static struct videobuf_queue_ops msm_vidbuf_ops = {
-	.buf_setup  = msm_vidbuf_setup,
-	.buf_prepare  = msm_vidbuf_prepare,
-	.buf_queue  = msm_vidbuf_queue,
-	.buf_release  = msm_vidbuf_release,
-};
-
-
-
-/* prepare a video buffer queue for a vl42 device*/
-static int msm_vidbuf_init(struct msm_cam_v4l2_dev_inst *pcam_inst,
-						   struct videobuf_queue *q)
-{
-	int rc = 0;
-	struct resource *res;
-	struct platform_device *pdev = NULL;
-	struct msm_cam_v4l2_device *pcam = pcam_inst->pcam;
-	D("%s\n", __func__);
-	if (!pcam || !q) {
-		pr_err("%s error : input is NULL\n", __func__);
-		return -EINVAL;
-	} else
-		pdev = pcam->mctl.sync.pdev;
-
-	if (!pdev) {
-		pr_err("%s error : pdev is NULL\n", __func__);
-		return -EINVAL;
-	}
-	if (pcam->use_count == 1) {
-		/* first check if we have resources */
-		res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-		if (res) {
-			D("res->start = 0x%x\n", (u32)res->start);
-			D("res->size = 0x%x\n", (u32)resource_size(res));
-			D("res->end = 0x%x\n", (u32)res->end);
-			rc = dma_declare_coherent_memory(&pdev->dev, res->start,
-				res->start,
-				resource_size(res),
-				DMA_MEMORY_MAP |
-				DMA_MEMORY_EXCLUSIVE);
-			if (!rc) {
-				pr_err("%s: Unable to declare coherent memory.\n",
-				 __func__);
-				rc = -ENXIO;
-				return rc;
-			}
-
-			/*pcam->memsize = resource_size(res);*/
-			D("%s: found DMA capable resource\n", __func__);
-		} else {
-			pr_err("%s: no DMA capable resource\n", __func__);
-			return -ENOMEM;
-		}
-	}
-	spin_lock_init(&pcam_inst->vb_irqlock);
-
-	videobuf_queue_pmem_contig_init(q, &msm_vidbuf_ops, &pdev->dev,
-		&pcam_inst->vb_irqlock,
-		V4L2_BUF_TYPE_VIDEO_CAPTURE,
-		V4L2_FIELD_NONE,
-		sizeof(struct msm_frame_buffer), pcam_inst, NULL);
-
-
-	return 0;
-}
 
 /*
  *  V4l2 subdevice operations
@@ -762,77 +431,13 @@
 	pmctl->mctl_open = msm_mctl_open;
 	pmctl->mctl_cmd = msm_mctl_cmd;
 	pmctl->mctl_notify = msm_mctl_notify;
-	pmctl->mctl_vidbuf_init = msm_vidbuf_init;
 	pmctl->mctl_release = msm_mctl_release;
-
 	pmctl->plat_dev = pcam->pdev;
+	/* init mctl buf */
+	msm_mctl_buf_init(pcam);
 	/* init sub device*/
 	v4l2_subdev_init(&(pmctl->mctl_sdev), &mctl_subdev_ops);
 	v4l2_set_subdevdata(&(pmctl->mctl_sdev), pmctl);
 
 	return 0;
 }
-static int msm_mctl_out_type_to_inst_index(struct msm_cam_v4l2_device *pcam,
-					int out_type)
-{
-	switch (out_type) {
-	case VFE_MSG_OUTPUT_P:
-		return pcam->dev_inst_map
-			[MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW]->my_index;
-	case VFE_MSG_OUTPUT_V:
-		return pcam->dev_inst_map
-			[MSM_V4L2_EXT_CAPTURE_MODE_VIDEO]->my_index;
-	case VFE_MSG_OUTPUT_S:
-		return pcam->dev_inst_map
-			[MSM_V4L2_EXT_CAPTURE_MODE_MAIN]->my_index;
-	case VFE_MSG_OUTPUT_T:
-		return pcam->dev_inst_map
-			[MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL]->my_index;
-	default:
-		return 0;
-	}
-	return 0;
-}
-
-int msm_mctl_buf_done(struct msm_cam_media_controller *pmctl,
-			int msg_type, uint32_t y_phy)
-{
-	struct videobuf_queue *q;
-	struct videobuf_buffer *buf = NULL;
-	uint32_t buf_phyaddr = 0;
-	int i, idx;
-	unsigned long flags = 0;
-
-	idx = msm_mctl_out_type_to_inst_index(pmctl->sync.pcam_sync, msg_type);
-	q = &(pmctl->sync.pcam_sync->dev_inst[idx]->vid_bufq);
-
-	D("q=0x%x\n", (u32)q);
-
-	/* find the videobuf which is done */
-	for (i = 0; i < VIDEO_MAX_FRAME; i++) {
-		if (NULL == q->bufs[i])
-			continue;
-		buf = q->bufs[i];
-		buf_phyaddr = videobuf_to_pmem_contig(buf);
-		D("buf_phyaddr=0x%x\n", (u32)buf_phyaddr);
-		D("data->phy.y_phy=0x%x\n",
-				y_phy);
-		D("buf = 0x%x\n", (u32)buf);
-		if (buf_phyaddr == y_phy) {
-			/* signal that buffer is done */
-			/* get the buf lock first */
-			spin_lock_irqsave(q->irqlock, flags);
-			buf->state = VIDEOBUF_DONE;
-			D("queuedequeue video_buffer 0x%x,"
-				"phyaddr = 0x%x\n",
-				(u32)buf, y_phy);
-
-			do_gettimeofday(&buf->ts);
-			buf->field_count++;
-			wake_up(&buf->done);
-			spin_unlock_irqrestore(q->irqlock, flags);
-			break;
-		}
-	}
-	return 0;
-}
diff --git a/drivers/media/video/msm/msm_mctl_buf.c b/drivers/media/video/msm/msm_mctl_buf.c
new file mode 100644
index 0000000..d084f9c
--- /dev/null
+++ b/drivers/media/video/msm/msm_mctl_buf.c
@@ -0,0 +1,471 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/ioctl.h>
+#include <linux/spinlock.h>
+#include <linux/videodev2.h>
+#include <linux/vmalloc.h>
+
+#include <media/v4l2-dev.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-device.h>
+
+#include <linux/android_pmem.h>
+
+#include "msm.h"
+#include "msm_ispif.h"
+
+#ifdef CONFIG_MSM_CAMERA_DEBUG
+#define D(fmt, args...) pr_debug("msm_mctl_buf: " fmt, ##args)
+#else
+#define D(fmt, args...) do {} while (0)
+#endif
+
+#define PAD_TO_WORD(a)	  (((a) + 3) & ~3)
+
+static int buffer_size(uint32_t *yoffset, uint32_t *cbcroffset,
+						int width, int height,
+						int pixelformat, int ext_mode)
+{
+	int size;
+
+	*yoffset = 0;
+	switch (pixelformat) {
+	case V4L2_PIX_FMT_NV21:
+	case V4L2_PIX_FMT_NV12:
+		if (ext_mode == MSM_V4L2_EXT_CAPTURE_MODE_VIDEO) {
+			size = PAD_TO_2K(width * height, 1)
+				+ PAD_TO_2K(width * height/2, 1);
+			*cbcroffset = PAD_TO_2K(width * height, 1);
+		} else {
+			size = PAD_TO_WORD(width * height)
+				+ PAD_TO_WORD(width * height/2);
+			*cbcroffset = PAD_TO_WORD(width * height);
+		}
+		break;
+	case V4L2_PIX_FMT_SBGGR10:
+	case V4L2_PIX_FMT_SGBRG10:
+	case V4L2_PIX_FMT_SGRBG10:
+	case V4L2_PIX_FMT_SRGGB10:
+		size = PAD_TO_WORD(width * height);
+		break;
+	default:
+		pr_err("%s: pixelformat %d not supported.\n",
+			__func__, pixelformat);
+		size = -EINVAL;
+	}
+	size = PAGE_ALIGN(size);
+	return size;
+}
+
+static int msm_vb2_ops_queue_setup(struct vb2_queue *vq,
+					unsigned int *num_buffers,
+					unsigned int *num_planes,
+					unsigned long sizes[],
+					void *alloc_ctxs[])
+{
+	/* get the video device */
+	struct msm_cam_v4l2_dev_inst *pcam_inst = vb2_get_drv_priv(vq);
+	struct msm_cam_v4l2_device *pcam = pcam_inst->pcam;
+	uint32_t yoffset, cbcroffset;
+
+	D("%s\n", __func__);
+	if (!pcam || !(*num_buffers)) {
+		pr_err("%s error : invalid input\n", __func__);
+		return -EINVAL;
+	}
+	/* TBD: need to set based on format */
+	*num_planes = 1;
+	D("%s, inst=0x%x,idx=%d, width = %d\n", __func__,
+		(u32)pcam_inst, pcam_inst->my_index,
+		pcam_inst->vid_fmt.fmt.pix.width);
+	D("%s, inst=0x%x,idx=%d, height = %d\n", __func__,
+		(u32)pcam_inst, pcam_inst->my_index,
+		pcam_inst->vid_fmt.fmt.pix.height);
+	sizes[0] = buffer_size(&yoffset, &cbcroffset,
+				pcam_inst->vid_fmt.fmt.pix.width,
+				pcam_inst->vid_fmt.fmt.pix.height,
+				pcam_inst->vid_fmt.fmt.pix.pixelformat,
+				pcam_inst->image_mode);
+	return 0;
+}
+
+static void msm_vb2_ops_wait_prepare(struct vb2_queue *q)
+{
+	/* we use polling so do not use this fn now */
+}
+static void msm_vb2_ops_wait_finish(struct vb2_queue *q)
+{
+	/* we use polling so do not use this fn now */
+}
+
+static int msm_vb2_ops_buf_init(struct vb2_buffer *vb)
+{
+	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	struct msm_cam_v4l2_device *pcam;
+	struct videobuf2_contig_pmem *mem;
+	struct vb2_queue	*vq;
+	uint32_t yoffset, cbcroffset;
+	int size, rc = 0;
+	vq = vb->vb2_queue;
+	pcam_inst = vb2_get_drv_priv(vq);
+	pcam = pcam_inst->pcam;
+	D("%s\n", __func__);
+	D("%s, inst=0x%x,idx=%d, width = %d\n", __func__,
+		(u32)pcam_inst, pcam_inst->my_index,
+		pcam_inst->vid_fmt.fmt.pix.width);
+	D("%s, inst=0x%x,idx=%d, height = %d\n", __func__,
+		(u32)pcam_inst, pcam_inst->my_index,
+		pcam_inst->vid_fmt.fmt.pix.height);
+	mem = vb2_plane_cookie(vb, 0);
+	size = buffer_size(&yoffset, &cbcroffset,
+				pcam_inst->vid_fmt.fmt.pix.width,
+				pcam_inst->vid_fmt.fmt.pix.height,
+				pcam_inst->vid_fmt.fmt.pix.pixelformat,
+				pcam_inst->image_mode);
+	if (size < 0)
+		return size;
+	if (vb->v4l2_buf.memory == V4L2_MEMORY_USERPTR)
+		rc = videobuf2_pmem_contig_user_get(mem, yoffset, cbcroffset,
+			pcam_inst->buf_offset[vb->v4l2_buf.index],
+			pcam_inst->path);
+	else
+		rc = videobuf2_pmem_contig_mmap_get(mem, yoffset, cbcroffset,
+			pcam_inst->path);
+
+	return rc;
+}
+
+static int msm_vb2_ops_buf_prepare(struct vb2_buffer *vb)
+{
+	int i, rc = 0;
+	uint32_t len;
+	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	struct msm_cam_v4l2_device *pcam;
+	struct msm_frame_buffer *buf;
+	struct vb2_queue	*vq = vb->vb2_queue;
+
+	D("%s\n", __func__);
+	if (!vb || !vq) {
+		pr_err("%s error : input is NULL\n", __func__);
+		return -EINVAL;
+	}
+	pcam_inst = vb2_get_drv_priv(vq);
+	pcam = pcam_inst->pcam;
+	buf = container_of(vb, struct msm_frame_buffer, vidbuf);
+
+	if (!pcam || !buf) {
+		pr_err("%s error : pointer is NULL\n", __func__);
+		return -EINVAL;
+	}
+	/* by this time vid_fmt should be already set.
+	 * return error if it is not. */
+	if ((pcam_inst->vid_fmt.fmt.pix.width == 0) ||
+		(pcam_inst->vid_fmt.fmt.pix.height == 0)) {
+		pr_err("%s error : pcam vid_fmt is not set\n", __func__);
+		return -EINVAL;
+	}
+	/* prefill in the byteused field */
+	for (i = 0; i < vb->num_planes; i++) {
+		len = vb2_plane_size(vb, i);
+		vb2_set_plane_payload(vb, i, len);
+	}
+	buf->inuse = 0;
+	return rc;
+}
+
+static int msm_vb2_ops_buf_finish(struct vb2_buffer *vb)
+{
+	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	struct msm_cam_v4l2_device *pcam;
+	struct msm_frame_buffer *buf;
+
+	pcam_inst = vb2_get_drv_priv(vb->vb2_queue);
+	pcam = pcam_inst->pcam;
+	buf = container_of(vb, struct msm_frame_buffer, vidbuf);
+	D("%s: inst=0x%x, buf=0x, %x, idx=%d\n", __func__,
+	(uint32_t)pcam_inst, (uint32_t)buf, vb->v4l2_buf.index);
+	return 0;
+}
+
+static void msm_vb2_ops_buf_cleanup(struct vb2_buffer *vb)
+{
+	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	struct msm_cam_v4l2_device *pcam;
+	struct videobuf2_contig_pmem *mem;
+	struct msm_frame_buffer *buf;
+	uint32_t i, vb_phyaddr = 0, buf_phyaddr = 0;
+	pcam_inst = vb2_get_drv_priv(vb->vb2_queue);
+	pcam = pcam_inst->pcam;
+	buf = container_of(vb, struct msm_frame_buffer, vidbuf);
+	D("%s: inst=0x%x, buf=0x%x, idx=%d\n", __func__,
+	(uint32_t)pcam_inst, (uint32_t)buf, vb->v4l2_buf.index);
+	vb_phyaddr = (unsigned long) videobuf2_to_pmem_contig(vb, 0);
+	list_for_each_entry(buf, &pcam_inst->free_vq, list) {
+		buf_phyaddr = (unsigned long)
+				videobuf2_to_pmem_contig(&buf->vidbuf, 0);
+		D("%s vb_idx=%d,vb_paddr=0x%x,phyaddr=0x%x\n",
+			__func__, buf->vidbuf.v4l2_buf.index,
+			buf_phyaddr, vb_phyaddr);
+		if (vb_phyaddr == buf_phyaddr) {
+			list_del(&buf->list);
+			break;
+		}
+	}
+	for (i = 0; i < vb->num_planes; i++) {
+		mem = vb2_plane_cookie(vb, i);
+		videobuf2_pmem_contig_user_put(mem);
+	}
+}
+
+static int msm_vb2_ops_start_streaming(struct vb2_queue *q)
+{
+	return 0;
+}
+
+static int msm_vb2_ops_stop_streaming(struct vb2_queue *q)
+{
+	return 0;
+}
+
+static void msm_vb2_ops_buf_queue(struct vb2_buffer *vb)
+{
+	struct msm_cam_v4l2_dev_inst *pcam_inst = NULL;
+	struct msm_cam_v4l2_device *pcam = NULL;
+	unsigned long phyaddr = 0;
+	unsigned long flags = 0;
+	int rc;
+	struct vb2_queue *vq = vb->vb2_queue;
+	struct msm_frame frame;
+	struct msm_vfe_cfg_cmd cfgcmd;
+	struct videobuf2_contig_pmem *mem;
+	struct msm_frame_buffer *buf;
+	D("%s\n", __func__);
+	if (!vb || !vq) {
+		pr_err("%s error : input is NULL\n", __func__);
+		return ;
+	}
+	pcam_inst = vb2_get_drv_priv(vq);
+	pcam = pcam_inst->pcam;
+	D("%s pcam_inst=%p,(vb=0x%p),idx=%d,len=%d\n", __func__, pcam_inst,
+	vb, vb->v4l2_buf.index, vb->v4l2_buf.length);
+	buf = container_of(vb, struct msm_frame_buffer, vidbuf);
+	/* we are returning a buffer to the queue */
+	mem = vb2_plane_cookie(vb, 0);
+	/* get the physcial address of the buffer */
+	phyaddr = (unsigned long) videobuf2_to_pmem_contig(vb, 0);
+	D("%s buffer type is %d\n", __func__, mem->buffer_type);
+	frame.path = pcam_inst->path;
+	frame.buffer = 0;
+	frame.y_off = mem->y_off;
+	frame.cbcr_off = mem->cbcr_off;
+	/* now release frame to vfe */
+	cfgcmd.cmd_type = CMD_FRAME_BUF_RELEASE;
+	cfgcmd.value    = (void *)&frame;
+	spin_lock_irqsave(&pcam_inst->vq_irqlock, flags);
+	list_add_tail(&buf->list, &pcam_inst->free_vq);
+	/* TBD: need to remove. VFE is going to call
+	   msm_mctl_fetch_free_buf to get free buf.
+	   Work with Shuzhen to hash out details tomorrow */
+	rc = msm_isp_subdev_ioctl(&pcam->mctl.isp_sdev->sd,
+			&cfgcmd, &phyaddr);
+	spin_unlock_irqrestore(&pcam_inst->vq_irqlock, flags);
+}
+
+static struct vb2_ops msm_vb2_ops = {
+	.queue_setup = msm_vb2_ops_queue_setup,
+	.wait_prepare = msm_vb2_ops_wait_prepare,
+	.wait_finish = msm_vb2_ops_wait_finish,
+	.buf_init = msm_vb2_ops_buf_init,
+	.buf_prepare = msm_vb2_ops_buf_prepare,
+	.buf_finish = msm_vb2_ops_buf_finish,
+	.buf_cleanup = msm_vb2_ops_buf_cleanup,
+	.start_streaming = msm_vb2_ops_start_streaming,
+	.stop_streaming = msm_vb2_ops_stop_streaming,
+	.buf_queue = msm_vb2_ops_buf_queue,
+};
+
+
+/* prepare a video buffer queue for a vl42 device*/
+static int msm_vidbuf_init(struct msm_cam_v4l2_dev_inst *pcam_inst,
+						struct vb2_queue *q)
+{
+	int rc = 0;
+	struct resource *res;
+	struct platform_device *pdev = NULL;
+	struct msm_cam_v4l2_device *pcam = NULL;
+
+	D("%s\n", __func__);
+	pcam = pcam_inst->pcam;
+	if (!pcam || !q) {
+		pr_err("%s error : input is NULL\n", __func__);
+		return -EINVAL;
+	} else
+		pdev = pcam->mctl.sync.pdev;
+
+	if (!pdev) {
+		pr_err("%s error : pdev is NULL\n", __func__);
+		return -EINVAL;
+	}
+	if (pcam->use_count == 1) {
+		/* first check if we have resources */
+		res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+		if (res) {
+			D("res->start = 0x%x\n", (u32)res->start);
+			D("res->size = 0x%x\n", (u32)resource_size(res));
+			D("res->end = 0x%x\n", (u32)res->end);
+			rc = dma_declare_coherent_memory(&pdev->dev, res->start,
+					res->start,
+					resource_size(res),
+					DMA_MEMORY_MAP |
+					DMA_MEMORY_EXCLUSIVE);
+			if (!rc) {
+				pr_err("%s: Unable to declare coherent memory.\n",
+				__func__);
+				rc = -ENXIO;
+				return rc;
+			}
+			D("%s: found DMA capable resource\n", __func__);
+		} else {
+			pr_err("%s: no DMA capable resource\n", __func__);
+			return -ENOMEM;
+		}
+	}
+	spin_lock_init(&pcam_inst->vq_irqlock);
+	INIT_LIST_HEAD(&pcam_inst->free_vq);
+	videobuf2_queue_pmem_contig_init(q, V4L2_BUF_TYPE_VIDEO_CAPTURE,
+						&msm_vb2_ops,
+						sizeof(struct msm_frame_buffer),
+						(void *)pcam_inst);
+	return 0;
+}
+
+static int msm_mctl_out_type_to_inst_index(struct msm_cam_v4l2_device *pcam,
+					int out_type)
+{
+	switch (out_type) {
+	case VFE_MSG_OUTPUT_P:
+		return pcam->dev_inst_map
+			[MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW]->my_index;
+	case VFE_MSG_OUTPUT_V:
+		return pcam->dev_inst_map
+			[MSM_V4L2_EXT_CAPTURE_MODE_VIDEO]->my_index;
+	case VFE_MSG_OUTPUT_S:
+		return pcam->dev_inst_map
+			[MSM_V4L2_EXT_CAPTURE_MODE_MAIN]->my_index;
+	case VFE_MSG_OUTPUT_T:
+		return pcam->dev_inst_map
+			[MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL]->my_index;
+	default:
+		return 0;
+	}
+	return 0;
+}
+
+static int msm_mctl_get_pcam_inst_idx(int out_put_type)
+{
+	switch (out_put_type) {
+	case OUTPUT_TYPE_T:
+		return MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL;
+	case OUTPUT_TYPE_S:
+		return MSM_V4L2_EXT_CAPTURE_MODE_MAIN;
+	case OUTPUT_TYPE_V:
+		return MSM_V4L2_EXT_CAPTURE_MODE_VIDEO;
+	case OUTPUT_TYPE_P:
+	  return MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW;
+	default:
+		return 0;
+	}
+}
+
+
+int msm_mctl_buf_done(struct msm_cam_media_controller *pmctl,
+					int msg_type, uint32_t y_phy)
+{
+	struct msm_frame_buffer *buf = NULL;
+	uint32_t buf_phyaddr = 0;
+	int idx, got = 0;
+	unsigned long flags = 0;
+	struct msm_cam_v4l2_dev_inst *pcam_inst;
+
+	idx = msm_mctl_out_type_to_inst_index(pmctl->sync.pcam_sync, msg_type);
+	pcam_inst = pmctl->sync.pcam_sync->dev_inst[idx];
+	/* we actually need a list, not a queue */
+	spin_lock_irqsave(&pcam_inst->vq_irqlock, flags);
+	list_for_each_entry(buf, &pcam_inst->free_vq, list) {
+		buf_phyaddr = (unsigned long)
+				videobuf2_to_pmem_contig(&buf->vidbuf, 0);
+		D("%s vb_idx=%d,vb_paddr=0x%x,y_phy=0x%x\n",
+			__func__, buf->vidbuf.v4l2_buf.index,
+			buf_phyaddr, y_phy);
+		if (y_phy == buf_phyaddr) {
+			got = 1;
+			break;
+		}
+	}
+	if (!got) {
+		spin_unlock_irqrestore(&pcam_inst->vq_irqlock, flags);
+		pr_err("%s: buf_done addr 0x%x != free buf queue head 0x%x\n",
+			__func__, (uint32_t)y_phy, (uint32_t)buf_phyaddr);
+		return -EINVAL;
+	}
+	list_del(&buf->list);
+	buf->vidbuf.v4l2_buf.sequence++;
+	spin_unlock_irqrestore(&pcam_inst->vq_irqlock, flags);
+	do_gettimeofday(&buf->vidbuf.v4l2_buf.timestamp);
+	vb2_buffer_done(&buf->vidbuf, VB2_BUF_STATE_DONE);
+	return 0;
+}
+
+int msm_mctl_buf_init(struct msm_cam_v4l2_device *pcam)
+{
+	pcam->mctl.mctl_vidbuf_init = msm_vidbuf_init;
+	return 0;
+}
+
+int msm_mctl_fetch_free_buf(struct msm_cam_media_controller *pmctl,
+				int path, struct msm_free_buf *free_buf)
+{
+	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	struct videobuf2_contig_pmem *mem;
+	int idx = msm_mctl_get_pcam_inst_idx(path);
+	unsigned long flags = 0;
+	struct msm_frame_buffer *buf = NULL;
+	int rc = -1;
+
+	pcam_inst = pmctl->sync.pcam_sync->dev_inst[idx];
+	spin_lock_irqsave(&pcam_inst->vq_irqlock, flags);
+	list_for_each_entry(buf, &pcam_inst->free_vq, list) {
+		if (buf->inuse == 0) {
+			mem = vb2_plane_cookie(&buf->vidbuf, 0);
+			free_buf->paddr =
+			(uint32_t) videobuf2_to_pmem_contig(&buf->vidbuf, 0);
+			free_buf->y_off = mem->y_off;
+			free_buf->cbcr_off = mem->cbcr_off;
+			D("%s path=%d,inst=0x%p,idx=%d,paddr=0x%x, "
+				"y_off=%d,cbcroff=%d\n", __func__, path,
+				pcam_inst, buf->vidbuf.v4l2_buf.index,
+				free_buf->paddr, free_buf->y_off,
+				free_buf->cbcr_off);
+			/* mark it used */
+			buf->inuse = 1;
+			rc = 0;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&pcam_inst->vq_irqlock, flags);
+	return rc;
+}
diff --git a/drivers/media/video/msm/msm_mem.c b/drivers/media/video/msm/msm_mem.c
index 5232f7c..b887f1e 100644
--- a/drivers/media/video/msm/msm_mem.c
+++ b/drivers/media/video/msm/msm_mem.c
@@ -303,37 +303,39 @@
 						struct msm_pmem_region *reg,
 						int mem_type)
 {
-	struct videobuf_contig_pmem *mem;
+	struct videobuf2_contig_pmem *mem;
+	struct vb2_queue *q = &pcam->dev_inst[idx]->vid_bufq;
+	int i;
 	uint8_t rc = 0;
-	struct videobuf_queue *q = &pcam->dev_inst[idx]->vid_bufq;
-	struct videobuf_buffer *buf = NULL;
 
-	videobuf_queue_lock(q);
-	list_for_each_entry(buf, &q->stream, stream) {
-		mem = buf->priv;
-		reg->paddr = mem->phyaddr;
-		D("%s paddr for buf %d is 0x%p\n", __func__,
-						buf->i,
-						(void *)reg->paddr);
-		reg->len = sizeof(struct msm_pmem_info);
-		reg->file = NULL;
-		reg->info.len = mem->size;
-
-		reg->info.vaddr =
-			(void *)(buf->baddr);
-
-		reg->info.type = mem_type;
-
-		reg->info.offset = 0;
-		reg->info.y_off = mem->y_off;
-		reg->info.cbcr_off = PAD_TO_WORD(mem->cbcr_off);
-		D("%s y_off = %d, cbcr_off = %d\n", __func__,
+	mutex_lock(&hlist_mut);
+	for (i = 0; i < pcam->dev_inst[idx]->buf_count ; i++) {
+		if (q->bufs[i] != NULL) {
+			mem = vb2_plane_cookie(q->bufs[i], 0);
+			if (!mem) {
+				pr_err("%s mem is null. Return ", __func__);
+				break;
+			}
+			reg->paddr = mem->phyaddr;
+			D("%s paddr for buf %d is 0x%p\n", __func__,
+							i,
+							(void *)reg->paddr);
+			reg->len = sizeof(struct msm_pmem_info);
+			reg->file = NULL;
+			reg->info.len = mem->size;
+			reg->info.vaddr = vb2_plane_vaddr(q->bufs[i], 0);
+			reg->info.type = mem_type;
+			reg->info.offset = 0;
+			reg->info.y_off = mem->y_off;
+			reg->info.cbcr_off = PAD_TO_WORD(mem->cbcr_off);
+			D("%s y_off = %d, cbcr_off = %d\n", __func__,
 			reg->info.y_off, reg->info.cbcr_off);
-		rc += 1;
-		reg++;
+			rc += 1;
+			reg++;
+		}
 	}
-	videobuf_queue_unlock(q);
-
+	mutex_unlock(&hlist_mut);
+	D("%s returning rc= %d\n", __func__, rc);
 	return rc;
 }
 
diff --git a/drivers/media/video/videobuf2-msm-mem.c b/drivers/media/video/videobuf2-msm-mem.c
new file mode 100644
index 0000000..13fbd1f
--- /dev/null
+++ b/drivers/media/video/videobuf2-msm-mem.c
@@ -0,0 +1,275 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * Based on videobuf-dma-contig.c,
+ * (c) 2008 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * helper functions for physically contiguous pmem capture buffers
+ * The functions support contiguous memory allocations using pmem
+ * kernel API.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/pagemap.h>
+#include <linux/sched.h>
+#include <linux/io.h>
+#include <linux/android_pmem.h>
+#include <linux/memory_alloc.h>
+#include <media/videobuf2-msm-mem.h>
+#include <media/msm_camera.h>
+#include <mach/memory.h>
+
+#include <media/videobuf2-core.h>
+
+#define MAGIC_PMEM 0x0733ac64
+#define MAGIC_CHECK(is, should)               \
+	if (unlikely((is) != (should))) {           \
+		pr_err("magic mismatch: %x expected %x\n", (is), (should)); \
+		BUG();                  \
+	}
+
+#ifdef CONFIG_MSM_CAMERA_DEBUG
+#define D(fmt, args...) pr_debug("videobuf-msm-mem: " fmt, ##args)
+#else
+#define D(fmt, args...) do {} while (0)
+#endif
+
+static int32_t msm_mem_allocate(const size_t size)
+{
+	int32_t phyaddr;
+	phyaddr = allocate_contiguous_ebi_nomap(size, SZ_4K);
+	return phyaddr;
+}
+
+static int32_t msm_mem_free(const int32_t phyaddr)
+{
+	int32_t rc = 0;
+	free_contiguous_memory_by_paddr(phyaddr);
+	return rc;
+}
+
+static void videobuf2_vm_close(struct vm_area_struct *vma)
+{
+	struct videobuf2_contig_pmem *mem = vma->vm_private_data;
+	D("vm_close %p [count=%u,vma=%08lx-%08lx]\n",
+		mem, mem->count, vma->vm_start, vma->vm_end);
+	mem->count--;
+}
+static void videobuf2_vm_open(struct vm_area_struct *vma)
+{
+	struct videobuf2_contig_pmem *mem = vma->vm_private_data;
+	D("vm_open %p [count=%u,vma=%08lx-%08lx]\n",
+		mem, mem->count, vma->vm_start, vma->vm_end);
+	mem->count++;
+}
+
+static const struct vm_operations_struct videobuf2_vm_ops = {
+	.open     = videobuf2_vm_open,
+	.close    = videobuf2_vm_close,
+};
+
+static void *msm_vb2_mem_ops_alloc(void *alloc_ctx, unsigned long size)
+{
+	struct videobuf2_contig_pmem *mem;
+	mem = kzalloc(sizeof(*mem), GFP_KERNEL);
+	if (!mem)
+		return ERR_PTR(-ENOMEM);
+
+	mem->magic = MAGIC_PMEM;
+	mem->size =  PAGE_ALIGN(size);
+	mem->alloc_ctx = alloc_ctx;
+	mem->is_userptr = 0;
+	mem->phyaddr = msm_mem_allocate(mem->size);
+	if (IS_ERR((void *)mem->phyaddr)) {
+		pr_err("%s : pmem memory allocation failed\n", __func__);
+		kfree(mem);
+		return ERR_PTR(-ENOMEM);
+	}
+	return mem;
+}
+static void msm_vb2_mem_ops_put(void *buf_priv)
+{
+	struct videobuf2_contig_pmem *mem = buf_priv;
+	if (!mem->is_userptr)
+		msm_mem_free(mem->phyaddr);
+	kfree(mem);
+}
+int videobuf2_pmem_contig_mmap_get(struct videobuf2_contig_pmem *mem,
+					uint32_t yoffset,
+					uint32_t cbcroffset, int path)
+{
+	mem->y_off = yoffset;
+	mem->cbcr_off = cbcroffset;
+	mem->buffer_type = path;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(videobuf2_pmem_contig_mmap_get);
+
+/**
+ * videobuf_pmem_contig_user_get() - setup user space memory pointer
+ * @mem: per-buffer private videobuf-contig-pmem data
+ * @vb: video buffer to map
+ *
+ * This function validates and sets up a pointer to user space memory.
+ * Only physically contiguous pfn-mapped memory is accepted.
+ *
+ * Returns 0 if successful.
+ */
+int videobuf2_pmem_contig_user_get(struct videobuf2_contig_pmem *mem,
+					uint32_t yoffset, uint32_t cbcroffset,
+					uint32_t addr_offset, int path)
+{
+	unsigned long kvstart;
+	unsigned long len;
+	int rc;
+
+	if (mem->phyaddr != 0)
+		return 0;
+
+	rc = get_pmem_file((int)mem->vaddr, (unsigned long *)&mem->phyaddr,
+					&kvstart, &len, &mem->file);
+	if (rc < 0) {
+		pr_err("%s: get_pmem_file fd %d error %d\n",
+					__func__, (int)mem->vaddr, rc);
+		return rc;
+	}
+	mem->phyaddr += addr_offset;
+	mem->y_off = yoffset;
+	mem->cbcr_off = cbcroffset;
+	mem->buffer_type = path;
+	return rc;
+}
+EXPORT_SYMBOL_GPL(videobuf2_pmem_contig_user_get);
+
+void videobuf2_pmem_contig_user_put(struct videobuf2_contig_pmem *mem)
+{
+	if (mem->is_userptr)
+		put_pmem_file(mem->file);
+	mem->is_userptr = 0;
+	mem->phyaddr = 0;
+	mem->size = 0;
+}
+EXPORT_SYMBOL_GPL(videobuf2_pmem_contig_user_put);
+
+static void *msm_vb2_mem_ops_get_userptr(void *alloc_ctx, unsigned long vaddr,
+					unsigned long size, int write)
+{
+	struct videobuf2_contig_pmem *mem;
+	mem = kzalloc(sizeof(*mem), GFP_KERNEL);
+	if (!mem)
+		return ERR_PTR(-ENOMEM);
+	mem->magic = MAGIC_PMEM;
+	mem->is_userptr = 1;
+	mem->vaddr = (void *)vaddr;
+	mem->size = size;
+	mem->alloc_ctx = alloc_ctx;
+	return mem;
+}
+static void msm_vb2_mem_ops_put_userptr(void *buf_priv)
+{
+	kfree(buf_priv);
+}
+
+static void *msm_vb2_mem_ops_vaddr(void *buf_priv)
+{
+	struct videobuf2_contig_pmem *mem = buf_priv;
+	return mem->vaddr;
+}
+static void *msm_vb2_mem_ops_cookie(void *buf_priv)
+{
+	return buf_priv;
+}
+static unsigned int msm_vb2_mem_ops_num_users(void *buf_priv)
+{
+	struct videobuf2_contig_pmem *mem = buf_priv;
+	MAGIC_CHECK(mem->magic, MAGIC_PMEM);
+	return mem->count;
+}
+static int msm_vb2_mem_ops_mmap(void *buf_priv, struct vm_area_struct *vma)
+{
+	struct videobuf2_contig_pmem *mem;
+	int retval;
+	unsigned long size;
+	D("%s\n", __func__);
+	mem = buf_priv;
+	D("mem = 0x%x\n", (u32)mem);
+	BUG_ON(!mem);
+	MAGIC_CHECK(mem->magic, MAGIC_PMEM);
+
+	/* Try to remap memory */
+	size = vma->vm_end - vma->vm_start;
+	size = (size < mem->size) ? size : mem->size;
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+	retval = remap_pfn_range(vma, vma->vm_start,
+			mem->phyaddr >> PAGE_SHIFT,
+			size, vma->vm_page_prot);
+	if (retval) {
+		pr_err("mmap: remap failed with error %d. ", retval);
+		goto error;
+	}
+	mem->vaddr = (void *)vma->vm_start;
+	vma->vm_ops = &videobuf2_vm_ops;
+	vma->vm_flags |= VM_DONTEXPAND;
+	vma->vm_private_data = mem;
+
+	D("mmap %p: %08lx-%08lx (%lx) pgoff %08lx\n",
+		map, vma->vm_start, vma->vm_end,
+		(long int)mem->bsize, vma->vm_pgoff);
+	videobuf2_vm_open(vma);
+	return 0;
+error:
+	return -ENOMEM;
+}
+
+static struct vb2_mem_ops msm_vb2_mem_ops = {
+	.alloc = msm_vb2_mem_ops_alloc,
+	.put = msm_vb2_mem_ops_put,
+	.get_userptr = msm_vb2_mem_ops_get_userptr,
+	.put_userptr = msm_vb2_mem_ops_put_userptr,
+	.vaddr = msm_vb2_mem_ops_vaddr,
+	.cookie = msm_vb2_mem_ops_cookie,
+	.num_users = msm_vb2_mem_ops_num_users,
+	.mmap = msm_vb2_mem_ops_mmap
+};
+
+void videobuf2_queue_pmem_contig_init(struct vb2_queue *q,
+					enum v4l2_buf_type type,
+					const struct vb2_ops *ops,
+					unsigned int size,
+					void *priv)
+{
+	memset(q, 0, sizeof(struct vb2_queue));
+	q->mem_ops = &msm_vb2_mem_ops;
+	q->ops = ops;
+	q->drv_priv = priv;
+	q->type = type;
+	q->io_modes = VB2_MMAP | VB2_USERPTR;
+	q->io_flags = 0;
+	q->buf_struct_size = size;
+	vb2_queue_init(q);
+}
+EXPORT_SYMBOL_GPL(videobuf2_queue_pmem_contig_init);
+
+int videobuf2_to_pmem_contig(struct vb2_buffer *vb, unsigned int plane_no)
+{
+	struct videobuf2_contig_pmem *mem;
+	mem = vb2_plane_cookie(vb, plane_no);
+	BUG_ON(!mem);
+	MAGIC_CHECK(mem->magic, MAGIC_PMEM);
+	return mem->phyaddr;
+}
+EXPORT_SYMBOL_GPL(videobuf2_to_pmem_contig);
+
+MODULE_DESCRIPTION("helper module to manage video4linux PMEM contig buffers");
+MODULE_LICENSE("GPL v2");