summaryrefslogtreecommitdiff
path: root/drivers/media/usb/uvc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/usb/uvc')
-rw-r--r--drivers/media/usb/uvc/uvc_ctrl.c3
-rw-r--r--drivers/media/usb/uvc/uvc_driver.c14
-rw-r--r--drivers/media/usb/uvc/uvc_entity.c38
-rw-r--r--drivers/media/usb/uvc/uvc_queue.c14
-rw-r--r--drivers/media/usb/uvc/uvc_v4l2.c20
-rw-r--r--drivers/media/usb/uvc/uvc_video.c17
6 files changed, 62 insertions, 44 deletions
diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c
index 3e59b288b..c2ee6e39f 100644
--- a/drivers/media/usb/uvc/uvc_ctrl.c
+++ b/drivers/media/usb/uvc/uvc_ctrl.c
@@ -227,7 +227,8 @@ static struct uvc_control_info uvc_ctrls[] = {
.size = 4,
.flags = UVC_CTRL_FLAG_SET_CUR
| UVC_CTRL_FLAG_GET_RANGE
- | UVC_CTRL_FLAG_RESTORE,
+ | UVC_CTRL_FLAG_RESTORE
+ | UVC_CTRL_FLAG_AUTO_UPDATE,
},
{
.entity = UVC_GUID_UVC_CAMERA,
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index d11fd6ac2..4e7148815 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -1656,6 +1656,7 @@ static void uvc_delete(struct uvc_device *dev)
#ifdef CONFIG_MEDIA_CONTROLLER
if (media_devnode_is_registered(&dev->mdev.devnode))
media_device_unregister(&dev->mdev);
+ media_device_cleanup(&dev->mdev);
#endif
list_for_each_safe(p, n, &dev->chains) {
@@ -1906,7 +1907,7 @@ static int uvc_probe(struct usb_interface *intf,
"linux-uvc-devel mailing list.\n");
}
- /* Register the media and V4L2 devices. */
+ /* Initialize the media device and register the V4L2 device. */
#ifdef CONFIG_MEDIA_CONTROLLER
dev->mdev.dev = &intf->dev;
strlcpy(dev->mdev.model, dev->name, sizeof(dev->mdev.model));
@@ -1916,8 +1917,7 @@ static int uvc_probe(struct usb_interface *intf,
strcpy(dev->mdev.bus_info, udev->devpath);
dev->mdev.hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
dev->mdev.driver_version = LINUX_VERSION_CODE;
- if (media_device_register(&dev->mdev) < 0)
- goto error;
+ media_device_init(&dev->mdev);
dev->vdev.mdev = &dev->mdev;
#endif
@@ -1936,6 +1936,11 @@ static int uvc_probe(struct usb_interface *intf,
if (uvc_register_chains(dev) < 0)
goto error;
+#ifdef CONFIG_MEDIA_CONTROLLER
+ /* Register the media device node */
+ if (media_device_register(&dev->mdev) < 0)
+ goto error;
+#endif
/* Save our data pointer in the interface data. */
usb_set_intfdata(intf, dev);
@@ -2540,7 +2545,8 @@ static struct usb_device_id uvc_ids[] = {
.bInterfaceProtocol = 0,
.driver_info = UVC_QUIRK_FORCE_Y8 },
/* Generic USB Video Class */
- { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) },
+ { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_UNDEFINED) },
+ { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_15) },
{}
};
diff --git a/drivers/media/usb/uvc/uvc_entity.c b/drivers/media/usb/uvc/uvc_entity.c
index dc56a59ec..ac386bb54 100644
--- a/drivers/media/usb/uvc/uvc_entity.c
+++ b/drivers/media/usb/uvc/uvc_entity.c
@@ -19,12 +19,8 @@
#include "uvcvideo.h"
-/* ------------------------------------------------------------------------
- * Video subdevices registration and unregistration
- */
-
-static int uvc_mc_register_entity(struct uvc_video_chain *chain,
- struct uvc_entity *entity)
+static int uvc_mc_create_links(struct uvc_video_chain *chain,
+ struct uvc_entity *entity)
{
const u32 flags = MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE;
struct media_entity *sink;
@@ -56,16 +52,13 @@ static int uvc_mc_register_entity(struct uvc_video_chain *chain,
continue;
remote_pad = remote->num_pads - 1;
- ret = media_entity_create_link(source, remote_pad,
+ ret = media_create_pad_link(source, remote_pad,
sink, i, flags);
if (ret < 0)
return ret;
}
- if (UVC_ENTITY_TYPE(entity) == UVC_TT_STREAMING)
- return 0;
-
- return v4l2_device_register_subdev(&chain->dev->vdev, &entity->subdev);
+ return 0;
}
static struct v4l2_subdev_ops uvc_subdev_ops = {
@@ -79,7 +72,8 @@ void uvc_mc_cleanup_entity(struct uvc_entity *entity)
media_entity_cleanup(&entity->vdev->entity);
}
-static int uvc_mc_init_entity(struct uvc_entity *entity)
+static int uvc_mc_init_entity(struct uvc_video_chain *chain,
+ struct uvc_entity *entity)
{
int ret;
@@ -88,11 +82,17 @@ static int uvc_mc_init_entity(struct uvc_entity *entity)
strlcpy(entity->subdev.name, entity->name,
sizeof(entity->subdev.name));
- ret = media_entity_init(&entity->subdev.entity,
- entity->num_pads, entity->pads, 0);
+ ret = media_entity_pads_init(&entity->subdev.entity,
+ entity->num_pads, entity->pads);
+
+ if (ret < 0)
+ return ret;
+
+ ret = v4l2_device_register_subdev(&chain->dev->vdev,
+ &entity->subdev);
} else if (entity->vdev != NULL) {
- ret = media_entity_init(&entity->vdev->entity,
- entity->num_pads, entity->pads, 0);
+ ret = media_entity_pads_init(&entity->vdev->entity,
+ entity->num_pads, entity->pads);
if (entity->flags & UVC_ENTITY_FLAG_DEFAULT)
entity->vdev->entity.flags |= MEDIA_ENT_FL_DEFAULT;
} else
@@ -107,7 +107,7 @@ int uvc_mc_register_entities(struct uvc_video_chain *chain)
int ret;
list_for_each_entry(entity, &chain->entities, chain) {
- ret = uvc_mc_init_entity(entity);
+ ret = uvc_mc_init_entity(chain, entity);
if (ret < 0) {
uvc_printk(KERN_INFO, "Failed to initialize entity for "
"entity %u\n", entity->id);
@@ -116,9 +116,9 @@ int uvc_mc_register_entities(struct uvc_video_chain *chain)
}
list_for_each_entry(entity, &chain->entities, chain) {
- ret = uvc_mc_register_entity(chain, entity);
+ ret = uvc_mc_create_links(chain, entity);
if (ret < 0) {
- uvc_printk(KERN_INFO, "Failed to register entity for "
+ uvc_printk(KERN_INFO, "Failed to create links for "
"entity %u\n", entity->id);
return ret;
}
diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c
index cfb868a48..543947227 100644
--- a/drivers/media/usb/uvc/uvc_queue.c
+++ b/drivers/media/usb/uvc/uvc_queue.c
@@ -69,23 +69,19 @@ static void uvc_queue_return_buffers(struct uvc_video_queue *queue,
* videobuf2 queue operations
*/
-static int uvc_queue_setup(struct vb2_queue *vq, const void *parg,
+static int uvc_queue_setup(struct vb2_queue *vq,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
- const struct v4l2_format *fmt = parg;
struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
struct uvc_streaming *stream = uvc_queue_to_stream(queue);
+ unsigned size = stream->ctrl.dwMaxVideoFrameSize;
/* Make sure the image size is large enough. */
- if (fmt && fmt->fmt.pix.sizeimage < stream->ctrl.dwMaxVideoFrameSize)
- return -EINVAL;
-
+ if (*nplanes)
+ return sizes[0] < size ? -EINVAL : 0;
*nplanes = 1;
-
- sizes[0] = fmt ? fmt->fmt.pix.sizeimage
- : stream->ctrl.dwMaxVideoFrameSize;
-
+ sizes[0] = size;
return 0;
}
diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c
index 2764f4360..d7723ce77 100644
--- a/drivers/media/usb/uvc/uvc_v4l2.c
+++ b/drivers/media/usb/uvc/uvc_v4l2.c
@@ -983,6 +983,22 @@ static int uvc_ioctl_g_ext_ctrls(struct file *file, void *fh,
unsigned int i;
int ret;
+ if (ctrls->which == V4L2_CTRL_WHICH_DEF_VAL) {
+ for (i = 0; i < ctrls->count; ++ctrl, ++i) {
+ struct v4l2_queryctrl qc = { .id = ctrl->id };
+
+ ret = uvc_query_v4l2_ctrl(chain, &qc);
+ if (ret < 0) {
+ ctrls->error_idx = i;
+ return ret;
+ }
+
+ ctrl->value = qc.default_value;
+ }
+
+ return 0;
+ }
+
ret = uvc_ctrl_begin(chain);
if (ret < 0)
return ret;
@@ -1010,6 +1026,10 @@ static int uvc_ioctl_s_try_ext_ctrls(struct uvc_fh *handle,
unsigned int i;
int ret;
+ /* Default value cannot be changed */
+ if (ctrls->which == V4L2_CTRL_WHICH_DEF_VAL)
+ return -EINVAL;
+
ret = uvc_ctrl_begin(chain);
if (ret < 0)
return ret;
diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
index 2b276ab77..075a0fe77 100644
--- a/drivers/media/usb/uvc/uvc_video.c
+++ b/drivers/media/usb/uvc/uvc_video.c
@@ -694,22 +694,19 @@ void uvc_video_clock_update(struct uvc_streaming *stream,
ts.tv_nsec -= NSEC_PER_SEC;
}
- uvc_trace(UVC_TRACE_CLOCK, "%s: SOF %u.%06llu y %llu ts %lu.%06lu "
- "buf ts %lu.%06lu (x1 %u/%u/%u x2 %u/%u/%u y1 %u y2 %u)\n",
+ uvc_trace(UVC_TRACE_CLOCK, "%s: SOF %u.%06llu y %llu ts %llu "
+ "buf ts %llu (x1 %u/%u/%u x2 %u/%u/%u y1 %u y2 %u)\n",
stream->dev->name,
sof >> 16, div_u64(((u64)sof & 0xffff) * 1000000LLU, 65536),
- y, ts.tv_sec, ts.tv_nsec / NSEC_PER_USEC,
- vbuf->timestamp.tv_sec,
- (unsigned long)vbuf->timestamp.tv_usec,
+ y, timespec_to_ns(&ts), vbuf->vb2_buf.timestamp,
x1, first->host_sof, first->dev_sof,
x2, last->host_sof, last->dev_sof, y1, y2);
/* Update the V4L2 buffer. */
- vbuf->timestamp.tv_sec = ts.tv_sec;
- vbuf->timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
+ vbuf->vb2_buf.timestamp = timespec_to_ns(&ts);
done:
- spin_unlock_irqrestore(&stream->clock.lock, flags);
+ spin_unlock_irqrestore(&clock->lock, flags);
}
/* ------------------------------------------------------------------------
@@ -1034,9 +1031,7 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
buf->buf.field = V4L2_FIELD_NONE;
buf->buf.sequence = stream->sequence;
- buf->buf.timestamp.tv_sec = ts.tv_sec;
- buf->buf.timestamp.tv_usec =
- ts.tv_nsec / NSEC_PER_USEC;
+ buf->buf.vb2_buf.timestamp = timespec_to_ns(&ts);
/* TODO: Handle PTS and SCR. */
buf->state = UVC_BUF_STATE_ACTIVE;