summaryrefslogtreecommitdiff
path: root/drivers/media/usb/uvc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-04-04 09:50:07 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2014-04-04 09:50:07 -0700
commit3c83e61e67256e0bb08c46cc2db43b58fd617251 (patch)
tree0233e1e04e6449c60b01ff5dea8bea85bcf22f08 /drivers/media/usb/uvc
parent4a4389abdd9822fdf3cc2ac6ed87eb811fd43acc (diff)
parenta83b93a7480441a47856dc9104bea970e84cda87 (diff)
downloadlinux-3c83e61e67256e0bb08c46cc2db43b58fd617251.tar.gz
linux-3c83e61e67256e0bb08c46cc2db43b58fd617251.tar.bz2
linux-3c83e61e67256e0bb08c46cc2db43b58fd617251.zip
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab: "The main set of series of patches for media subsystem, including: - document RC sysfs class - added an API to setup scancode to allow waking up systems using the Remote Controller - add API for SDR devices. Drivers are still on staging - some API improvements for getting EDID data from media inputs/outputs - new DVB frontend driver for drx-j (ATSC) - one driver (it913x/it9137) got removed, in favor of an improvement on another driver (af9035) - added a skeleton V4L2 PCI driver at documentation - added a dual flash driver (lm3646) - added a new IR driver (img-ir) - added an IR scancode decoder for the Sharp protocol - some improvements at the usbtv driver, to allow its core to be reused. - added a new SDR driver (rtl2832u_sdr) - added a new tuner driver (msi001) - several improvements at em28xx driver to fix PM support, device removal and to split the V4L2 specific bits into a separate sub-driver - one driver got converted to videobuf2 (s2255drv) - the e4000 tuner driver now follows an improved binding model - some fixes at V4L2 compat32 code - several fixes and enhancements at videobuf2 code - some cleanups at V4L2 API documentation - usual driver enhancements, new board additions and misc fixups" [ NOTE! This merge effective drops commit 4329b93b283c ("of: Reduce indentation in of_graph_get_next_endpoint"). The of_graph_get_next_endpoint() function was moved and renamed by commit fd9fdb78a9bf ("[media] of: move graph helpers from drivers/media/v4l2-core to drivers/of"). It was originally called v4l2_of_get_next_endpoint() and lived in the file drivers/media/v4l2-core/v4l2-of.c. In that original location, it was then fixed to support empty port nodes by commit b9db140c1e46 ("[media] v4l: of: Support empty port nodes"), and that commit clashes badly with the dropped "Reduce intendation" commit. I had to choose one or the other, and decided that the "Support empty port nodes" commit was more important ] * 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (426 commits) [media] em28xx-dvb: fix PCTV 461e tuner I2C binding Revert "[media] em28xx-dvb: fix PCTV 461e tuner I2C binding" [media] em28xx: fix PCTV 290e LNA oops [media] em28xx-dvb: fix PCTV 461e tuner I2C binding [media] m88ds3103: fix bug on .set_tone() [media] saa7134: fix WARN_ON during resume [media] v4l2-dv-timings: add module name, description, license [media] videodev2.h: add parenthesis around macro arguments [media] saa6752hs: depends on CRC32 [media] si4713: fix Kconfig dependencies [media] Sensoray 2255 uses videobuf2 [media] adv7180: free an interrupt on failure paths in init_device() [media] e4000: make VIDEO_V4L2 dependency optional [media] af9033: Don't export functions for the hardware filter [media] af9035: use af9033 PID filters [media] af9033: implement PID filter [media] rtl2832_sdr: do not use dynamic stack allocation [media] e4000: fix 32-bit build error [media] em28xx-audio: make sure audio is unmuted on open() [media] DocBook media: v4l2_format_sdr was renamed to v4l2_sdr_format ...
Diffstat (limited to 'drivers/media/usb/uvc')
-rw-r--r--drivers/media/usb/uvc/uvc_driver.c24
-rw-r--r--drivers/media/usb/uvc/uvc_queue.c29
-rw-r--r--drivers/media/usb/uvc/uvc_v4l2.c11
-rw-r--r--drivers/media/usb/uvc/uvc_video.c23
-rw-r--r--drivers/media/usb/uvc/uvcvideo.h16
5 files changed, 91 insertions, 12 deletions
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index c3bb2502225b..ad47c5cb539a 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -108,11 +108,31 @@ static struct uvc_format_desc uvc_fmts[] = {
.fcc = V4L2_PIX_FMT_Y16,
},
{
- .name = "RGB Bayer",
+ .name = "BGGR Bayer (BY8 )",
.guid = UVC_GUID_FORMAT_BY8,
.fcc = V4L2_PIX_FMT_SBGGR8,
},
{
+ .name = "BGGR Bayer (BA81)",
+ .guid = UVC_GUID_FORMAT_BA81,
+ .fcc = V4L2_PIX_FMT_SBGGR8,
+ },
+ {
+ .name = "GBRG Bayer (GBRG)",
+ .guid = UVC_GUID_FORMAT_GBRG,
+ .fcc = V4L2_PIX_FMT_SGBRG8,
+ },
+ {
+ .name = "GRBG Bayer (GRBG)",
+ .guid = UVC_GUID_FORMAT_GRBG,
+ .fcc = V4L2_PIX_FMT_SGRBG8,
+ },
+ {
+ .name = "RGGB Bayer (RGGB)",
+ .guid = UVC_GUID_FORMAT_RGGB,
+ .fcc = V4L2_PIX_FMT_SRGGB8,
+ },
+ {
.name = "RGB565",
.guid = UVC_GUID_FORMAT_RGBP,
.fcc = V4L2_PIX_FMT_RGB565,
@@ -925,7 +945,7 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
case UVC_VC_HEADER:
n = buflen >= 12 ? buffer[11] : 0;
- if (buflen < 12 || buflen < 12 + n) {
+ if (buflen < 12 + n) {
uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
"interface %d HEADER error\n", udev->devnum,
alts->desc.bInterfaceNumber);
diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c
index cd962be860ca..6e92d2080255 100644
--- a/drivers/media/usb/uvc/uvc_queue.c
+++ b/drivers/media/usb/uvc/uvc_queue.c
@@ -48,12 +48,14 @@ static int uvc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
struct uvc_streaming *stream =
container_of(queue, struct uvc_streaming, queue);
- if (*nbuffers > UVC_MAX_VIDEO_BUFFERS)
- *nbuffers = UVC_MAX_VIDEO_BUFFERS;
+ /* Make sure the image size is large enough. */
+ if (fmt && fmt->fmt.pix.sizeimage < stream->ctrl.dwMaxVideoFrameSize)
+ return -EINVAL;
*nplanes = 1;
- sizes[0] = stream->ctrl.dwMaxVideoFrameSize;
+ sizes[0] = fmt ? fmt->fmt.pix.sizeimage
+ : stream->ctrl.dwMaxVideoFrameSize;
return 0;
}
@@ -104,15 +106,15 @@ static void uvc_buffer_queue(struct vb2_buffer *vb)
spin_unlock_irqrestore(&queue->irqlock, flags);
}
-static int uvc_buffer_finish(struct vb2_buffer *vb)
+static void uvc_buffer_finish(struct vb2_buffer *vb)
{
struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
struct uvc_streaming *stream =
container_of(queue, struct uvc_streaming, queue);
struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
- uvc_video_clock_update(stream, &vb->v4l2_buf, buf);
- return 0;
+ if (vb->state == VB2_BUF_STATE_DONE)
+ uvc_video_clock_update(stream, &vb->v4l2_buf, buf);
}
static void uvc_wait_prepare(struct vb2_queue *vq)
@@ -149,7 +151,8 @@ int uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,
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_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+ queue->queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC
+ | V4L2_BUF_FLAG_TSTAMP_SRC_SOE;
ret = vb2_queue_init(&queue->queue);
if (ret)
return ret;
@@ -196,6 +199,18 @@ int uvc_query_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf)
return ret;
}
+int uvc_create_buffers(struct uvc_video_queue *queue,
+ struct v4l2_create_buffers *cb)
+{
+ int ret;
+
+ mutex_lock(&queue->mutex);
+ ret = vb2_create_bufs(&queue->queue, cb);
+ mutex_unlock(&queue->mutex);
+
+ return ret;
+}
+
int uvc_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf)
{
int ret;
diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c
index 3afff92804d3..378ae02e593b 100644
--- a/drivers/media/usb/uvc/uvc_v4l2.c
+++ b/drivers/media/usb/uvc/uvc_v4l2.c
@@ -1000,6 +1000,17 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
return uvc_query_buffer(&stream->queue, buf);
}
+ case VIDIOC_CREATE_BUFS:
+ {
+ struct v4l2_create_buffers *cb = arg;
+
+ ret = uvc_acquire_privileges(handle);
+ if (ret < 0)
+ return ret;
+
+ return uvc_create_buffers(&stream->queue, cb);
+ }
+
case VIDIOC_QBUF:
if (!uvc_has_privileges(handle))
return -EBUSY;
diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
index 898c208889cd..8d52baf5952b 100644
--- a/drivers/media/usb/uvc/uvc_video.c
+++ b/drivers/media/usb/uvc/uvc_video.c
@@ -1453,6 +1453,9 @@ static unsigned int uvc_endpoint_max_bpi(struct usb_device *dev,
case USB_SPEED_HIGH:
psize = usb_endpoint_maxp(&ep->desc);
return (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
+ case USB_SPEED_WIRELESS:
+ psize = usb_endpoint_maxp(&ep->desc);
+ return psize;
default:
psize = usb_endpoint_maxp(&ep->desc);
return psize & 0x07ff;
@@ -1847,7 +1850,25 @@ int uvc_video_enable(struct uvc_streaming *stream, int enable)
if (!enable) {
uvc_uninit_video(stream, 1);
- usb_set_interface(stream->dev->udev, stream->intfnum, 0);
+ if (stream->intf->num_altsetting > 1) {
+ usb_set_interface(stream->dev->udev,
+ stream->intfnum, 0);
+ } else {
+ /* UVC doesn't specify how to inform a bulk-based device
+ * when the video stream is stopped. Windows sends a
+ * CLEAR_FEATURE(HALT) request to the video streaming
+ * bulk endpoint, mimic the same behaviour.
+ */
+ unsigned int epnum = stream->header.bEndpointAddress
+ & USB_ENDPOINT_NUMBER_MASK;
+ unsigned int dir = stream->header.bEndpointAddress
+ & USB_ENDPOINT_DIR_MASK;
+ unsigned int pipe;
+
+ pipe = usb_sndbulkpipe(stream->dev->udev, epnum) | dir;
+ usb_clear_halt(stream->dev->udev, pipe);
+ }
+
uvc_queue_enable(&stream->queue, 0);
uvc_video_clock_cleanup(stream);
return 0;
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
index 9e35982d099a..b1f69a6d4068 100644
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -94,6 +94,18 @@
#define UVC_GUID_FORMAT_BY8 \
{ 'B', 'Y', '8', ' ', 0x00, 0x00, 0x10, 0x00, \
0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_BA81 \
+ { 'B', 'A', '8', '1', 0x00, 0x00, 0x10, 0x00, \
+ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_GBRG \
+ { 'G', 'B', 'R', 'G', 0x00, 0x00, 0x10, 0x00, \
+ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_GRBG \
+ { 'G', 'R', 'B', 'G', 0x00, 0x00, 0x10, 0x00, \
+ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_RGGB \
+ { 'R', 'G', 'G', 'B', 0x00, 0x00, 0x10, 0x00, \
+ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
#define UVC_GUID_FORMAT_RGBP \
{ 'R', 'G', 'B', 'P', 0x00, 0x00, 0x10, 0x00, \
0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
@@ -115,8 +127,6 @@
#define UVC_URBS 5
/* Maximum number of packets per URB. */
#define UVC_MAX_PACKETS 32
-/* Maximum number of video buffers. */
-#define UVC_MAX_VIDEO_BUFFERS 32
/* Maximum status buffer size in bytes of interrupt URB. */
#define UVC_MAX_STATUS_SIZE 16
@@ -616,6 +626,8 @@ extern int uvc_alloc_buffers(struct uvc_video_queue *queue,
extern void uvc_free_buffers(struct uvc_video_queue *queue);
extern int uvc_query_buffer(struct uvc_video_queue *queue,
struct v4l2_buffer *v4l2_buf);
+extern int uvc_create_buffers(struct uvc_video_queue *queue,
+ struct v4l2_create_buffers *v4l2_cb);
extern int uvc_queue_buffer(struct uvc_video_queue *queue,
struct v4l2_buffer *v4l2_buf);
extern int uvc_dequeue_buffer(struct uvc_video_queue *queue,