diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
index 53e495223ea0..f5bea3890807 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -1653,8 +1653,10 @@ static int vb2_start_streaming(struct vb2_queue *q)
 	return ret;
 }
 
-int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb,
-		  struct media_request *req)
+static int
+vb2_core_qbuf_common(struct vb2_queue *q, unsigned int index,
+		     struct v4l2_buffer *pb, struct v4l2_ext_buffer *eb,
+		     struct media_request *req)
 {
 	struct vb2_buffer *vb;
 	enum vb2_buffer_state orig_state;
@@ -1727,6 +1729,9 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb,
 		if (pb) {
 			call_void_bufop(q, copy_timestamp, vb, pb);
 			call_void_bufop(q, fill_user_buffer, vb, pb);
+		} else if (eb) {
+			call_void_bufop(q, copy_timestamp_ext, vb, eb);
+			call_void_bufop(q, fill_user_ext_buffer, vb, eb);
 		}
 
 		dprintk(q, 2, "qbuf of buffer %d succeeded\n", vb->index);
@@ -1766,6 +1771,8 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb,
 
 	if (pb)
 		call_void_bufop(q, copy_timestamp, vb, pb);
+	else if (eb)
+		call_void_bufop(q, copy_timestamp_ext, vb, eb);
 
 	trace_vb2_qbuf(q, vb);
 
@@ -1779,6 +1786,8 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb,
 	/* Fill buffer information for the userspace */
 	if (pb)
 		call_void_bufop(q, fill_user_buffer, vb, pb);
+	else if (eb)
+		call_void_bufop(q, fill_user_ext_buffer, vb, eb);
 
 	/*
 	 * If streamon has been called, and we haven't yet called
@@ -1805,8 +1814,21 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb,
 	dprintk(q, 2, "qbuf of buffer %d succeeded\n", vb->index);
 	return 0;
 }
+
+int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb,
+		  struct media_request *req)
+{
+	return vb2_core_qbuf_common(q, index, pb, NULL, req);
+}
 EXPORT_SYMBOL_GPL(vb2_core_qbuf);
 
+int vb2_core_ext_qbuf(struct vb2_queue *q, unsigned int index, void *pb,
+		      struct media_request *req)
+{
+	return vb2_core_qbuf_common(q, index, NULL, pb, req);
+}
+EXPORT_SYMBOL_GPL(vb2_core_ext_qbuf);
+
 /*
  * __vb2_wait_for_done_vb() - wait for a buffer to become available
  * for dequeuing
@@ -1956,8 +1978,10 @@ static void __vb2_dqbuf(struct vb2_buffer *vb)
 	call_void_bufop(q, init_buffer, vb);
 }
 
-int vb2_core_dqbuf(struct vb2_queue *q, unsigned int *pindex, void *pb,
-		   bool nonblocking)
+static int
+vb2_core_dqbuf_common(struct vb2_queue *q, unsigned int *pindex,
+		      struct v4l2_buffer *pb, struct v4l2_ext_buffer *eb,
+		      bool nonblocking)
 {
 	struct vb2_buffer *vb = NULL;
 	int ret;
@@ -1988,6 +2012,8 @@ int vb2_core_dqbuf(struct vb2_queue *q, unsigned int *pindex, void *pb,
 	/* Fill buffer information for the userspace */
 	if (pb)
 		call_void_bufop(q, fill_user_buffer, vb, pb);
+	else if (eb)
+		call_void_bufop(q, fill_user_ext_buffer, vb, eb);
 
 	/* Remove from vb2 queue */
 	list_del(&vb->queued_entry);
@@ -2010,10 +2036,22 @@ int vb2_core_dqbuf(struct vb2_queue *q, unsigned int *pindex, void *pb,
 		vb->index, vb2_state_name(vb->state));
 
 	return 0;
+}
 
+int vb2_core_dqbuf(struct vb2_queue *q, unsigned int *pindex, void *pb,
+		   bool nonblocking)
+{
+	return vb2_core_dqbuf_common(q, pindex, pb, NULL, nonblocking);
 }
 EXPORT_SYMBOL_GPL(vb2_core_dqbuf);
 
+int vb2_core_ext_dqbuf(struct vb2_queue *q, unsigned int *pindex, void *pb,
+		   bool nonblocking)
+{
+	return vb2_core_dqbuf_common(q, pindex, NULL, pb, nonblocking);
+}
+EXPORT_SYMBOL_GPL(vb2_core_ext_dqbuf);
+
 /*
  * __vb2_queue_cancel() - cancel and stop (pause) streaming
  *
diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index eb158de7d14a..01541140f902 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -157,6 +157,23 @@ static void __copy_timestamp(struct vb2_buffer *vb, const void *pb)
 	}
 };
 
+static void __copy_timestamp_ext(struct vb2_buffer *vb, const void *pb)
+{
+	const struct v4l2_ext_buffer *eb = pb;
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct vb2_queue *q = vb->vb2_queue;
+
+	if (q->is_output) {
+		/*
+		 * For output buffers copy the timestamp if needed,
+		 * and the timecode field and flag if needed.
+		 */
+		if (q->copy_timestamp)
+			vb->timestamp = eb->timestamp;
+		vbuf->flags |= eb->flags & V4L2_BUF_FLAG_TIMECODE;
+	}
+};
+
 static void vb2_warn_zero_bytesused(struct vb2_buffer *vb)
 {
 	static bool check_once;
@@ -210,6 +227,68 @@ vb2_fill_vb2_v4l2_buffer_flags(struct vb2_buffer *vb,
 	}
 }
 
+static int vb2_fill_vb2_v4l2_buffer_ext(struct vb2_buffer *vb,
+					const struct v4l2_ext_buffer *eb)
+{
+	struct vb2_queue *q = vb->vb2_queue;
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct vb2_plane *planes = vbuf->planes;
+	unsigned int i;
+
+	if (eb->field == V4L2_FIELD_ALTERNATE && q->is_output) {
+		/*
+		 * If the format's field is ALTERNATE, then the buffer's field
+		 * should be either TOP or BOTTOM, not ALTERNATE since that
+		 * makes no sense. The driver has to know whether the
+		 * buffer represents a top or a bottom field in order to
+		 * program any DMA correctly. Using ALTERNATE is wrong, since
+		 * that just says that it is either a top or a bottom field,
+		 * but not which of the two it is.
+		 */
+		dprintk(q, 1, "the field is incorrectly set to ALTERNATE for an output buffer\n");
+		return -EINVAL;
+	}
+	vbuf->sequence = 0;
+	vbuf->request_fd = -1;
+	vbuf->is_held = false;
+
+	for (i = 0; i < VIDEO_MAX_PLANES && eb->planes[i].m.userptr; i++) {
+		if (eb->memory == VB2_MEMORY_MMAP) {
+			planes[i].m.userptr = vb->planes[i].m.userptr;
+			planes[i].length = vb->planes[i].length;
+			planes[i].mem_offset = vb->planes[i].mem_offset;
+		} else {
+			planes[i].m.userptr = eb->planes[i].m.userptr;
+			/*
+			 * TODO: get dmabuf/mmap length, assing to max only for
+			 * userptr, that we assume userspace passed the right
+			 * size (can we assume that?)
+			 */
+			planes[i].length = UINT_MAX;
+			planes[i].mem_offset = eb->planes[i].offset;
+		}
+
+		planes[i].data_offset = 0;
+		if (V4L2_TYPE_IS_OUTPUT(eb->type)) {
+			if (eb->planes[i].bytesused == 0)
+				vb2_warn_zero_bytesused(vb);
+
+			if (vb->vb2_queue->allow_zero_bytesused)
+				planes[i].bytesused = eb->planes[i].bytesused;
+			else
+				planes[i].bytesused = eb->planes[i].bytesused ?
+						      eb->planes[i].bytesused :
+						      planes[i].length;
+		} else {
+			planes[i].bytesused = 0;
+		}
+	}
+
+	vb2_fill_vb2_v4l2_buffer_flags(vb, eb->type, eb->field, eb->flags);
+
+	return 0;
+}
+
 static int vb2_fill_vb2_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
 {
 	struct vb2_queue *q = vb->vb2_queue;
@@ -373,8 +452,35 @@ static void set_buffer_cache_hints(struct vb2_queue *q,
 		vb->skip_cache_sync_on_prepare = 1;
 }
 
-static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *mdev,
-				    struct v4l2_buffer *b, bool is_prepare,
+static enum v4l2_buf_type vb2_ext_to_queue_type(unsigned int type,
+						bool is_multiplanar)
+{
+	if (!is_multiplanar)
+		return type;
+
+	if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+	else if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+		return V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+
+	return type;
+}
+
+static enum v4l2_buf_type vb2_queue_to_ext_type(unsigned int type)
+{
+	if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+		return V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	else if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+		return V4L2_BUF_TYPE_VIDEO_OUTPUT;
+
+	return type;
+}
+
+static int vb2_queue_or_prepare_buf(struct vb2_queue *q,
+				    struct media_device *mdev,
+				    struct v4l2_buffer *b,
+				    struct v4l2_ext_buffer *eb,
+				    bool is_prepare,
 				    struct media_request **p_req)
 {
 	const char *opname = is_prepare ? "prepare_buf" : "qbuf";
@@ -382,46 +488,68 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md
 	struct vb2_v4l2_buffer *vbuf;
 	struct vb2_buffer *vb;
 	int ret;
+	u32 index, memory, type, request_fd;
+	u32 *flags;
+
+	/* TODO: see how to improve this */
+	if (eb) {
+		index = eb->index;
+		type = vb2_ext_to_queue_type(eb->type, q->is_multiplanar);
+		memory = eb->memory;
+		flags = (u32*)&eb->flags;
+		request_fd = eb->request_fd;
+	} else {
+		index = b->index;
+		type = b->type;
+		memory = b->memory;
+		flags = &b->flags;
+		request_fd = b->request_fd;
+	}
 
-	if (b->type != q->type) {
+	if (type != q->type) {
 		dprintk(q, 1, "%s: invalid buffer type\n", opname);
 		return -EINVAL;
 	}
 
-	if (b->index >= q->num_buffers) {
+	if (index >= q->num_buffers) {
 		dprintk(q, 1, "%s: buffer index out of range\n", opname);
 		return -EINVAL;
 	}
 
-	if (q->bufs[b->index] == NULL) {
+	if (q->bufs[index] == NULL) {
 		/* Should never happen */
 		dprintk(q, 1, "%s: buffer is NULL\n", opname);
 		return -EINVAL;
 	}
 
-	if (b->memory != q->memory) {
+	if (memory != q->memory) {
 		dprintk(q, 1, "%s: invalid memory type\n", opname);
 		return -EINVAL;
 	}
 
-	vb = q->bufs[b->index];
+	vb = q->bufs[index];
 	vbuf = to_vb2_v4l2_buffer(vb);
-	ret = __verify_planes_array(vb, b);
-	if (ret)
-		return ret;
+	if (b) {
+		ret = __verify_planes_array(vb, b);
+		if (ret)
+			return ret;
+	}
 
-	if (!is_prepare && (b->flags & V4L2_BUF_FLAG_REQUEST_FD) &&
+	if (!is_prepare && (*flags & V4L2_BUF_FLAG_REQUEST_FD) &&
 	    vb->state != VB2_BUF_STATE_DEQUEUED) {
 		dprintk(q, 1, "%s: buffer is not in dequeued state\n", opname);
 		return -EINVAL;
 	}
 
 	if (!vb->prepared) {
-		set_buffer_cache_hints(q, vb, &b->flags);
+		set_buffer_cache_hints(q, vb, flags);
 		/* Copy relevant information provided by the userspace */
 		memset(vbuf->planes, 0,
 		       sizeof(vbuf->planes[0]) * vb->num_planes);
-		ret = vb2_fill_vb2_v4l2_buffer(vb, b);
+		if (b)
+			ret = vb2_fill_vb2_v4l2_buffer(vb, b);
+		else
+			ret = vb2_fill_vb2_v4l2_buffer_ext(vb, eb);
 		if (ret)
 			return ret;
 	}
@@ -429,7 +557,7 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md
 	if (is_prepare)
 		return 0;
 
-	if (!(b->flags & V4L2_BUF_FLAG_REQUEST_FD)) {
+	if (!(*flags & V4L2_BUF_FLAG_REQUEST_FD)) {
 		if (q->requires_requests) {
 			dprintk(q, 1, "%s: queue requires requests\n", opname);
 			return -EBADR;
@@ -472,7 +600,7 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md
 		    !q->ops->buf_out_validate))
 		return -EINVAL;
 
-	req = media_request_get_by_fd(mdev, b->request_fd);
+	req = media_request_get_by_fd(mdev, request_fd);
 	if (IS_ERR(req)) {
 		dprintk(q, 1, "%s: invalid request_fd\n", opname);
 		return PTR_ERR(req);
@@ -490,7 +618,7 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md
 	}
 
 	*p_req = req;
-	vbuf->request_fd = b->request_fd;
+	vbuf->request_fd = request_fd;
 
 	return 0;
 }
@@ -547,6 +675,91 @@ static void v4l2_clear_buffer_flags(struct vb2_buffer *vb, u32 *flags,
 	}
 }
 
+/*
+ * v4l2_decompose_planes - decompose format into color components
+ *
+ * @eplanes: pointer to struct v4l2_ext_plane to fill.
+ * @sizeimage: size of the image when using a single plane.
+ * @pixelformat: forcc to consider when decomposing @sizeimage.
+ * @data_offset: offset of data in buffer
+ * @membuf: buffer to fill in eplanes[i].m
+ *
+ * Fill out @eplanes, dividing @sizeimage according to @pixelformat, where
+ * @sizeimage is the size of all planes in a contiguous manner.
+ */
+static int v4l2_decompose_planes(struct v4l2_ext_plane *eplanes,
+				 unsigned int sizeimage,
+				 const struct v4l2_format_info *info,
+				 unsigned int data_offset, u64 membuf)
+{
+	unsigned int i, y_plane_size, chroma_plane_size;
+
+	/*
+	 * Considering:
+	 * sizeimage = Y_plane_size + (comp_planes - 1) * chroma_plane_size
+	 * Y_plane_size = chroma_plane_size * (hdiv*vdiv)
+	 * Then:
+	 * chroma_plane_size = sizeimage / (hdiv*vdiv + comp_planes - 1)
+	 */
+	chroma_plane_size = sizeimage /
+			((info->hdiv * info->vdiv) + info->comp_planes - 1);
+	y_plane_size = chroma_plane_size * info->hdiv * info->vdiv;
+	eplanes[0].m.userptr = membuf;
+	eplanes[0].bytesused = y_plane_size;
+	eplanes[0].offset = data_offset;
+
+	for (i = 1; i < info->comp_planes; i++) {
+		eplanes[i].m.userptr = membuf;
+		eplanes[i] = eplanes[0];
+		eplanes[i].offset = data_offset + y_plane_size +
+				    chroma_plane_size * (i - 1);
+		eplanes[i].bytesused = chroma_plane_size;
+	}
+	return 0;
+}
+
+/*
+ * __fill_v4l2_ext_buffer() - fill in a struct v4l2_ext_buffer with information to be
+ * returned to userspace
+ */
+static void __fill_v4l2_ext_buffer(struct vb2_buffer *vb, void *pb)
+{
+	const struct v4l2_format_info *pix_info =
+					v4l2_format_info(vb->pixelformat);
+	struct v4l2_ext_buffer *eb = pb;
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct vb2_queue *q = vb->vb2_queue;
+	unsigned int i;
+
+	memset(eb, 0, sizeof(*eb));
+
+	/* Copy back data such as timestamp, flags, etc. */
+	eb->index = vb->index;
+	eb->type = vb2_queue_to_ext_type(vb->type);
+	eb->flags = vbuf->flags;
+	eb->field = vbuf->field;
+	eb->timestamp = vb->timestamp;
+	eb->sequence = vbuf->sequence;
+	eb->request_fd = 0;
+	eb->memory = vb->memory;
+
+	if (vb->num_planes == 1 && pix_info)
+		v4l2_decompose_planes(eb->planes,
+			vb->planes[0].bytesused - vb->planes[0].data_offset,
+			pix_info, vb->planes[i].data_offset,
+			vb->planes[0].m.userptr);
+	else
+		for (i = 0; i < vb->num_planes; i++) {
+			eb->planes[i].m.userptr = vb->planes[i].m.userptr;
+			eb->planes[i].bytesused = vb->planes[i].bytesused -
+						  vb->planes[i].data_offset;
+			eb->planes[i].offset = vb->planes[i].mem_offset +
+					       vb->planes[i].data_offset;
+		}
+
+	v4l2_clear_buffer_flags(vb, (u32*)&eb->flags, q, vbuf, &eb->request_fd);
+}
+
 /*
  * __fill_v4l2_buffer() - fill in a struct v4l2_buffer with information to be
  * returned to userspace
@@ -639,8 +852,10 @@ static const struct vb2_buf_ops v4l2_buf_ops = {
 	.verify_planes_array	= __verify_planes_array_core,
 	.init_buffer		= __init_vb2_v4l2_buffer,
 	.fill_user_buffer	= __fill_v4l2_buffer,
+	.fill_user_ext_buffer	= __fill_v4l2_ext_buffer,
 	.fill_vb2_buffer	= __fill_vb2_buffer,
 	.copy_timestamp		= __copy_timestamp,
+	.copy_timestamp_ext	= __copy_timestamp_ext,
 };
 
 struct vb2_buffer *vb2_find_buffer(struct vb2_queue *q, u64 timestamp)
@@ -751,7 +966,7 @@ int vb2_prepare_buf(struct vb2_queue *q, struct media_device *mdev,
 	if (b->flags & V4L2_BUF_FLAG_REQUEST_FD)
 		return -EINVAL;
 
-	ret = vb2_queue_or_prepare_buf(q, mdev, b, true, NULL);
+	ret = vb2_queue_or_prepare_buf(q, mdev, b, NULL, true, NULL);
 
 	return ret ? ret : vb2_core_prepare_buf(q, b->index, b);
 }
@@ -828,7 +1043,7 @@ int vb2_qbuf(struct vb2_queue *q, struct media_device *mdev,
 		return -EBUSY;
 	}
 
-	ret = vb2_queue_or_prepare_buf(q, mdev, b, false, &req);
+	ret = vb2_queue_or_prepare_buf(q, mdev, b, NULL, false, &req);
 	if (ret)
 		return ret;
 	ret = vb2_core_qbuf(q, b->index, b, req);
@@ -838,6 +1053,27 @@ int vb2_qbuf(struct vb2_queue *q, struct media_device *mdev,
 }
 EXPORT_SYMBOL_GPL(vb2_qbuf);
 
+int vb2_ext_qbuf(struct vb2_queue *q, struct media_device *mdev,
+		 struct v4l2_ext_buffer *eb)
+{
+	struct media_request *req = NULL;
+	int ret;
+
+	if (vb2_fileio_is_active(q)) {
+		dprintk(q, 1, "file io in progress\n");
+		return -EBUSY;
+	}
+
+	ret = vb2_queue_or_prepare_buf(q, mdev, NULL, eb, false, &req);
+	if (ret)
+		return ret;
+	ret = vb2_core_ext_qbuf(q, eb->index, eb, req);
+	if (req)
+		media_request_put(req);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(vb2_ext_qbuf);
+
 int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
 {
 	int ret;
@@ -869,6 +1105,38 @@ int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
 }
 EXPORT_SYMBOL_GPL(vb2_dqbuf);
 
+int
+vb2_ext_dqbuf(struct vb2_queue *q, struct v4l2_ext_buffer *eb, bool nonblocking)
+{
+	int ret;
+
+	if (vb2_fileio_is_active(q)) {
+		dprintk(q, 1, "file io in progress\n");
+		return -EBUSY;
+	}
+
+	if (vb2_ext_to_queue_type(eb->type, q->is_multiplanar) != q->type) {
+		dprintk(q, 1, "invalid buffer type\n");
+		return -EINVAL;
+	}
+
+	ret = vb2_core_ext_dqbuf(q, NULL, eb, nonblocking);
+
+	if (!q->is_output &&
+	    eb->flags & V4L2_BUF_FLAG_DONE &&
+	    eb->flags & V4L2_BUF_FLAG_LAST)
+		q->last_buffer_dequeued = true;
+
+	/*
+	 *  After calling the VIDIOC_DQBUF V4L2_BUF_FLAG_DONE must be
+	 *  cleared.
+	 */
+	eb->flags &= ~V4L2_BUF_FLAG_DONE;
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(vb2_ext_dqbuf);
+
 int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
 {
 	if (vb2_fileio_is_active(q)) {
@@ -1077,6 +1345,16 @@ int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
 }
 EXPORT_SYMBOL_GPL(vb2_ioctl_qbuf);
 
+int vb2_ioctl_ext_qbuf(struct file *file, void *priv, struct v4l2_ext_buffer *p)
+{
+	struct video_device *vdev = video_devdata(file);
+
+	if (vb2_queue_is_busy(vdev->queue, file))
+		return -EBUSY;
+	return vb2_ext_qbuf(vdev->queue, vdev->v4l2_dev->mdev, p);
+}
+EXPORT_SYMBOL_GPL(vb2_ioctl_ext_qbuf);
+
 int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
 {
 	struct video_device *vdev = video_devdata(file);
@@ -1087,6 +1365,17 @@ int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
 }
 EXPORT_SYMBOL_GPL(vb2_ioctl_dqbuf);
 
+int
+vb2_ioctl_ext_dqbuf(struct file *file, void *priv, struct v4l2_ext_buffer *p)
+{
+	struct video_device *vdev = video_devdata(file);
+
+	if (vb2_queue_is_busy(vdev->queue, file))
+		return -EBUSY;
+	return vb2_ext_dqbuf(vdev->queue, p, file->f_flags & O_NONBLOCK);
+}
+EXPORT_SYMBOL_GPL(vb2_ioctl_ext_dqbuf);
+
 int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
 {
 	struct video_device *vdev = video_devdata(file);
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 4b6a9d2ea372..27dd4279e68b 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -169,8 +169,12 @@ struct vb2_mem_ops {
  *		pointing to this plane.
  * @m.fd:	when memory is %VB2_MEMORY_DMABUF, a userspace file
  *		descriptor associated with this plane.
+ * @mem_offset:	offset where the plane starts. Usually 0, unless the buffer
+ *		is shared by all planes of a multi-planar format.
  * @data_offset:	offset in the plane to the start of data; usually 0,
- *		unless there is a header in front of the data.
+ *		unless there is a header in front of the data. In Ext API, this
+ *		is used by the driver to update the offset value from
+ *		v4l2_ext_buffer accordinly.
  *
  * Should contain enough information to be able to cover all the fields
  * of &struct v4l2_plane at videodev2.h.
@@ -187,6 +191,7 @@ struct vb2_plane {
 		unsigned long	userptr;
 		int		fd;
 	} m;
+	unsigned int		mem_offset;
 	unsigned int		data_offset;
 };
 
@@ -239,12 +244,14 @@ struct vb2_queue;
  * @index:		id number of the buffer.
  * @type:		buffer type.
  * @memory:		the method, in which the actual data is passed.
- * @num_planes:		number of planes in the buffer
+ * @num_planes:		number of memory planes in the buffer
  *			on an internal driver queue.
  * @timestamp:		frame timestamp in ns.
  * @request:		the request this buffer is associated with.
  * @req_obj:		used to bind this buffer to a request. This
  *			request object has a refcount.
+ * @pixelformat		pixelformat so vb2 can calculate the number of color
+ *			planes.
  */
 struct vb2_buffer {
 	struct vb2_queue	*vb2_queue;
@@ -255,6 +262,7 @@ struct vb2_buffer {
 	u64			timestamp;
 	struct media_request	*request;
 	struct media_request_object	req_obj;
+	u32			pixelformat;
 
 	/* private: internal use only
 	 *
@@ -463,18 +471,24 @@ struct vb2_ops {
  *			For V4L2 this is a &struct vb2_v4l2_buffer.
  * @fill_user_buffer:	given a &vb2_buffer fill in the userspace structure.
  *			For V4L2 this is a &struct v4l2_buffer.
+ * @fill_user_ext_buffer:given a &vb2_buffer fill in the userspace structure.
+ *			For V4L2 this is a &struct v4l2_ext_buffer.
  * @fill_vb2_buffer:	given a userspace structure, fill in the &vb2_buffer.
  *			If the userspace structure is invalid, then this op
  *			will return an error.
  * @copy_timestamp:	copy the timestamp from a userspace structure to
  *			the &struct vb2_buffer.
+ * @copy_timestamp_ext:	copy the timestamp from a userspace structure to
+ *			the &struct vb2_buffer.
  */
 struct vb2_buf_ops {
 	int (*verify_planes_array)(struct vb2_buffer *vb, const void *pb);
 	void (*init_buffer)(struct vb2_buffer *vb);
 	void (*fill_user_buffer)(struct vb2_buffer *vb, void *pb);
+	void (*fill_user_ext_buffer)(struct vb2_buffer *vb, void *pb);
 	int (*fill_vb2_buffer)(struct vb2_buffer *vb, struct vb2_plane *planes);
 	void (*copy_timestamp)(struct vb2_buffer *vb, const void *pb);
+	void (*copy_timestamp_ext)(struct vb2_buffer *vb, const void *eb);
 };
 
 /**
@@ -869,6 +883,8 @@ int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb);
  */
 int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb,
 		  struct media_request *req);
+int vb2_core_ext_qbuf(struct vb2_queue *q, unsigned int index, void *pb,
+		      struct media_request *req);
 
 /**
  * vb2_core_dqbuf() - Dequeue a buffer to the userspace
@@ -895,6 +911,8 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb,
  */
 int vb2_core_dqbuf(struct vb2_queue *q, unsigned int *pindex, void *pb,
 		   bool nonblocking);
+int vb2_core_ext_dqbuf(struct vb2_queue *q, unsigned int *pindex, void *pb,
+		       bool nonblocking);
 
 /**
  * vb2_core_streamon() - Implements VB2 stream ON logic
@@ -1180,6 +1198,17 @@ static inline void vb2_set_plane_payload(struct vb2_buffer *vb,
 	}
 }
 
+/**
+ * vb2_set_pixelformat() - set pixelformat for the buffer
+ * @vb:			pointer to &struct vb2_buffer.
+ * @pixelformat:	pixelformat to associate with the buffer.
+ */
+static inline void vb2_set_pixelformat(struct vb2_buffer *vb,
+				       u32 pixelformat)
+{
+	vb->pixelformat = pixelformat;
+}
+
 /**
  * vb2_get_plane_payload() - get bytesused for the plane plane_no
  * @vb:		pointer to &struct vb2_buffer to which the plane in
diff --git a/include/media/videobuf2-v4l2.h b/include/media/videobuf2-v4l2.h
index 5a845887850b..fe07f4378400 100644
--- a/include/media/videobuf2-v4l2.h
+++ b/include/media/videobuf2-v4l2.h
@@ -39,7 +39,7 @@ struct video_device;
  * @planes:	plane information (userptr/fd, length, bytesused, data_offset).
  *
  * Should contain enough information to be able to cover all the fields
- * of &struct v4l2_buffer at ``videodev2.h``.
+ * of &struct v4l2_buffer and &struct v4l2_ext_buffer at ``videodev2.h``.
  */
 struct vb2_v4l2_buffer {
 	struct vb2_buffer	vb2_buf;
@@ -144,6 +144,8 @@ int vb2_prepare_buf(struct vb2_queue *q, struct media_device *mdev,
  */
 int vb2_qbuf(struct vb2_queue *q, struct media_device *mdev,
 	     struct v4l2_buffer *b);
+int vb2_ext_qbuf(struct vb2_queue *q, struct media_device *mdev,
+		 struct v4l2_ext_buffer *b);
 
 /**
  * vb2_expbuf() - Export a buffer as a file descriptor
@@ -181,6 +183,8 @@ int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb);
  * from &v4l2_ioctl_ops->vidioc_dqbuf handler in driver.
  */
 int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking);
+int vb2_ext_dqbuf(struct vb2_queue *q, struct v4l2_ext_buffer *b,
+		  bool nonblocking);
 
 /**
  * vb2_streamon - start streaming
@@ -329,7 +333,9 @@ int vb2_ioctl_prepare_buf(struct file *file, void *priv,
 			  struct v4l2_buffer *p);
 int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p);
 int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p);
+int vb2_ioctl_ext_qbuf(struct file *file, void *priv, struct v4l2_ext_buffer *p);
 int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p);
+int vb2_ioctl_ext_dqbuf(struct file *file, void *priv, struct v4l2_ext_buffer *p);
 int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i);
 int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i);
 int vb2_ioctl_expbuf(struct file *file, void *priv,
