Use physically contiguous lower 3G memory for UVC cameras.

On i.MX this is required for the hardware encoder (VPU) to be
able to encode camera frames. The encoder only takes one bus
address (plus length) to a frame to encode so the entire frame
must be in physically contiguous memory.

Further, this is also needed to take the frame buffers exported
as dma-buf and feed to the GPU, which can't handle buffers in
memory over 3GB.

Bug: 148406831
Bug: 161286409

Change-Id: I3b36162322c174531c92a2726fe19d680899ec8d
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index 064d882..116db1c 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -1882,7 +1882,7 @@
 	int ret;
 
 	/* Initialize the video buffers queue. */
-	ret = uvc_queue_init(&stream->queue, stream->type, !uvc_no_drop_param);
+	ret = uvc_queue_init(&vdev->dev, &stream->queue, stream->type, !uvc_no_drop_param);
 	if (ret)
 		return ret;
 
diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c
index c8d78b2..85ad145 100644
--- a/drivers/media/usb/uvc/uvc_queue.c
+++ b/drivers/media/usb/uvc/uvc_queue.c
@@ -21,7 +21,7 @@
 #include <linux/vmalloc.h>
 #include <linux/wait.h>
 #include <media/videobuf2-v4l2.h>
-#include <media/videobuf2-vmalloc.h>
+#include <media/videobuf2-dma-contig.h>
 
 #include "uvcvideo.h"
 
@@ -198,8 +198,8 @@
 	.stop_streaming = uvc_stop_streaming,
 };
 
-int uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,
-		    int drop_corrupted)
+int uvc_queue_init(struct device *dev, struct uvc_video_queue *queue,
+			enum v4l2_buf_type type, int drop_corrupted)
 {
 	int ret;
 
@@ -208,7 +208,8 @@
 	queue->queue.drv_priv = queue;
 	queue->queue.buf_struct_size = sizeof(struct uvc_buffer);
 	queue->queue.ops = &uvc_queue_qops;
-	queue->queue.mem_ops = &vb2_vmalloc_memops;
+	queue->queue.mem_ops = &vb2_dma_contig_memops;
+	queue->queue.dev = dev;
 	queue->queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC
 		| V4L2_BUF_FLAG_TSTAMP_SRC_SOE;
 	queue->queue.lock = &queue->mutex;
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
index 0539878..3d959da 100644
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -654,7 +654,7 @@
 extern struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id);
 
 /* Video buffers queue management. */
-extern int uvc_queue_init(struct uvc_video_queue *queue,
+extern int uvc_queue_init(struct device *dev, struct uvc_video_queue *queue,
 		enum v4l2_buf_type type, int drop_corrupted);
 extern void uvc_queue_release(struct uvc_video_queue *queue);
 extern int uvc_request_buffers(struct uvc_video_queue *queue,
diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
index 6351ddc..f6131d4 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -26,6 +26,7 @@
 #include <linux/kmod.h>
 #include <linux/slab.h>
 #include <linux/uaccess.h>
+#include <linux/dma-mapping.h>
 
 #include <media/v4l2-common.h>
 #include <media/v4l2-device.h>
@@ -1020,6 +1021,10 @@
 	/* Part 6: Activate this minor. The char device can now be used. */
 	set_bit(V4L2_FL_REGISTERED, &vdev->flags);
 
+	/* Use physically contiguous memory for DMA. No-op if DMA is
+	   already configured */
+	arch_setup_dma_ops(&vdev->dev, 0, 0, NULL, false);
+
 	return 0;
 
 cleanup: