diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-28 09:35:11 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-28 09:35:11 -0700 |
commit | 0851668fdd97e526b2a41f794b785c204dd3d3e0 (patch) | |
tree | 4ef7c20a8be8393006c6fe9627eb29dd30877d61 /drivers/media/video/uvc/uvc_video.c | |
parent | 00ebb6382b8d9c7c15b5f8ad230670d8161d38dd (diff) | |
parent | 7655e594945289b418af39f6669fea4666a7b520 (diff) |
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (505 commits)
[media] af9015: Fix max I2C message size when used with tda18271
[media] IR: initialize ir_raw_event in few more drivers
[media] Guard a divide in v4l1 compat layer
[media] imon: fix nomouse modprobe option
[media] imon: remove redundant change_protocol call
[media] imon: fix my egregious brown paper bag w/rdev/idev split
[media] cafe_ccic: Configure ov7670 correctly
[media] ov7670: allow configuration of image size, clock speed, and I/O method
[media] af9015: support for DigitalNow TinyTwin v3 [1f4d:9016]
[media] af9015: map DigitalNow TinyTwin v2 remote
[media] DigitalNow TinyTwin remote controller
[media] af9015: RC fixes and improvements
videodev2.h.xml: Update to reflect the latest changes at videodev2.h
[media] v4l: document new Bayer and monochrome pixel formats
[media] DocBook/v4l: Add missing formats used on gspca cpia1 and sn9c2028
[media] firedtv: add parameter to fake ca_system_ids in CA_INFO
[media] tm6000: fix a macro coding style issue
tm6000: Remove some ugly debug code
[media] Nova-S-Plus audio line input
[media] [RFC,1/1] V4L2: Use new CAP bits in existing RDS capable drivers
...
Diffstat (limited to 'drivers/media/video/uvc/uvc_video.c')
-rw-r--r-- | drivers/media/video/uvc/uvc_video.c | 52 |
1 files changed, 47 insertions, 5 deletions
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index e27cf0d3b6d..5555f010283 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c @@ -1,8 +1,8 @@ /* * uvc_video.c -- USB Video Class driver - Video handling * - * Copyright (C) 2005-2009 - * Laurent Pinchart (laurent.pinchart@skynet.be) + * Copyright (C) 2005-2010 + * Laurent Pinchart (laurent.pinchart@ideasonboard.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -45,6 +45,30 @@ static int __uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, unit << 8 | intfnum, data, size, timeout); } +static const char *uvc_query_name(__u8 query) +{ + switch (query) { + case UVC_SET_CUR: + return "SET_CUR"; + case UVC_GET_CUR: + return "GET_CUR"; + case UVC_GET_MIN: + return "GET_MIN"; + case UVC_GET_MAX: + return "GET_MAX"; + case UVC_GET_RES: + return "GET_RES"; + case UVC_GET_LEN: + return "GET_LEN"; + case UVC_GET_INFO: + return "GET_INFO"; + case UVC_GET_DEF: + return "GET_DEF"; + default: + return "<invalid>"; + } +} + int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, __u8 intfnum, __u8 cs, void *data, __u16 size) { @@ -53,9 +77,9 @@ int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, ret = __uvc_query_ctrl(dev, query, unit, intfnum, cs, data, size, UVC_CTRL_CONTROL_TIMEOUT); if (ret != size) { - uvc_printk(KERN_ERR, "Failed to query (%u) UVC control %u " - "(unit %u) : %d (exp. %u).\n", query, cs, unit, ret, - size); + uvc_printk(KERN_ERR, "Failed to query (%s) UVC control %u on " + "unit %u: %d (exp. %u).\n", uvc_query_name(query), cs, + unit, ret, size); return -EIO; } @@ -114,6 +138,15 @@ static void uvc_fixup_video_ctrl(struct uvc_streaming *stream, bandwidth /= 8; bandwidth += 12; + /* The bandwidth estimate is too low for many cameras. Don't use + * maximum packet sizes lower than 1024 bytes to try and work + * around the problem. According to measurements done on two + * different camera models, the value is high enough to get most + * resolutions working while not preventing two simultaneous + * VGA streams at 15 fps. + */ + bandwidth = max_t(u32, bandwidth, 1024); + ctrl->dwMaxPayloadTransferSize = bandwidth; } } @@ -394,6 +427,12 @@ static int uvc_video_decode_start(struct uvc_streaming *stream, fid = data[1] & UVC_STREAM_FID; + /* Increase the sequence number regardless of any buffer states, so + * that discontinuous sequence numbers always indicate lost frames. + */ + if (stream->last_fid != fid) + stream->sequence++; + /* Store the payload FID bit and return immediately when the buffer is * NULL. */ @@ -427,6 +466,7 @@ static int uvc_video_decode_start(struct uvc_streaming *stream, else ktime_get_real_ts(&ts); + buf->buf.sequence = stream->sequence; buf->buf.timestamp.tv_sec = ts.tv_sec; buf->buf.timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC; @@ -688,6 +728,7 @@ static void uvc_video_encode_bulk(struct urb *urb, struct uvc_streaming *stream, if (buf->buf.bytesused == stream->queue.buf_used) { stream->queue.buf_used = 0; buf->state = UVC_BUF_STATE_READY; + buf->buf.sequence = ++stream->sequence; uvc_queue_next_buffer(&stream->queue, buf); stream->last_fid ^= UVC_STREAM_FID; } @@ -946,6 +987,7 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) unsigned int i; int ret; + stream->sequence = -1; stream->last_fid = -1; stream->bulk.header_size = 0; stream->bulk.skip_payload = 0; |