From 088ead25524583e2200aa99111bea2f66a86545a Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 6 Dec 2017 10:15:40 -0500 Subject: media: uvcvideo: Add a metadata device node Some UVC video cameras contain metadata in their payload headers. This patch extracts that data, adding more clock synchronisation information, on both bulk and isochronous endpoints and makes it available to the user space on a separate video node, using the V4L2_CAP_META_CAPTURE capability and the V4L2_BUF_TYPE_META_CAPTURE buffer queue type. By default, only the V4L2_META_FMT_UVC pixel format is available from those nodes. However, cameras can be added to the device ID table to additionally specify their own metadata format, in which case that format will also become available from the metadata node. [Use put_unaligned instead of __put_unaligned_cpu64] [Use put_unaligned for the sof field as well] Signed-off-by: Guennadi Liakhovetski Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/uvc/uvc_queue.c | 44 ++++++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 7 deletions(-) (limited to 'drivers/media/usb/uvc/uvc_queue.c') diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c index c8d78b2f3de4..cd2ea5a23086 100644 --- a/drivers/media/usb/uvc/uvc_queue.c +++ b/drivers/media/usb/uvc/uvc_queue.c @@ -79,8 +79,19 @@ static int uvc_queue_setup(struct vb2_queue *vq, unsigned int sizes[], struct device *alloc_devs[]) { struct uvc_video_queue *queue = vb2_get_drv_priv(vq); - struct uvc_streaming *stream = uvc_queue_to_stream(queue); - unsigned size = stream->ctrl.dwMaxVideoFrameSize; + struct uvc_streaming *stream; + unsigned int size; + + switch (vq->type) { + case V4L2_BUF_TYPE_META_CAPTURE: + size = UVC_METATADA_BUF_SIZE; + break; + + default: + stream = uvc_queue_to_stream(queue); + size = stream->ctrl.dwMaxVideoFrameSize; + break; + } /* * When called with plane sizes, validate them. The driver supports @@ -114,7 +125,7 @@ static int uvc_buffer_prepare(struct vb2_buffer *vb) buf->error = 0; buf->mem = vb2_plane_vaddr(vb, 0); buf->length = vb2_plane_size(vb, 0); - if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + if (vb->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) buf->bytesused = 0; else buf->bytesused = vb2_get_plane_payload(vb, 0); @@ -177,10 +188,10 @@ static int uvc_start_streaming(struct vb2_queue *vq, unsigned int count) static void uvc_stop_streaming(struct vb2_queue *vq) { struct uvc_video_queue *queue = vb2_get_drv_priv(vq); - struct uvc_streaming *stream = uvc_queue_to_stream(queue); unsigned long flags; - uvc_video_enable(stream, 0); + if (vq->type != V4L2_BUF_TYPE_META_CAPTURE) + uvc_video_enable(uvc_queue_to_stream(queue), 0); spin_lock_irqsave(&queue->irqlock, flags); uvc_queue_return_buffers(queue, UVC_BUF_STATE_ERROR); @@ -198,20 +209,39 @@ static const struct vb2_ops uvc_queue_qops = { .stop_streaming = uvc_stop_streaming, }; +static const struct vb2_ops uvc_meta_queue_qops = { + .queue_setup = uvc_queue_setup, + .buf_prepare = uvc_buffer_prepare, + .buf_queue = uvc_buffer_queue, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, + .stop_streaming = uvc_stop_streaming, +}; + int uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type, int drop_corrupted) { int ret; queue->queue.type = type; - queue->queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; + queue->queue.io_modes = VB2_MMAP | VB2_USERPTR; 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.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC | V4L2_BUF_FLAG_TSTAMP_SRC_SOE; queue->queue.lock = &queue->mutex; + + switch (type) { + case V4L2_BUF_TYPE_META_CAPTURE: + queue->queue.ops = &uvc_meta_queue_qops; + break; + default: + queue->queue.io_modes |= VB2_DMABUF; + queue->queue.ops = &uvc_queue_qops; + break; + } + ret = vb2_queue_init(&queue->queue); if (ret) return ret; -- cgit