diff options
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 e27cf0d3b6d9..5555f0102838 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * uvc_video.c -- USB Video Class driver - Video handling | 2 | * uvc_video.c -- USB Video Class driver - Video handling |
3 | * | 3 | * |
4 | * Copyright (C) 2005-2009 | 4 | * Copyright (C) 2005-2010 |
5 | * Laurent Pinchart (laurent.pinchart@skynet.be) | 5 | * Laurent Pinchart (laurent.pinchart@ideasonboard.com) |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by | 8 | * 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, | |||
45 | unit << 8 | intfnum, data, size, timeout); | 45 | unit << 8 | intfnum, data, size, timeout); |
46 | } | 46 | } |
47 | 47 | ||
48 | static const char *uvc_query_name(__u8 query) | ||
49 | { | ||
50 | switch (query) { | ||
51 | case UVC_SET_CUR: | ||
52 | return "SET_CUR"; | ||
53 | case UVC_GET_CUR: | ||
54 | return "GET_CUR"; | ||
55 | case UVC_GET_MIN: | ||
56 | return "GET_MIN"; | ||
57 | case UVC_GET_MAX: | ||
58 | return "GET_MAX"; | ||
59 | case UVC_GET_RES: | ||
60 | return "GET_RES"; | ||
61 | case UVC_GET_LEN: | ||
62 | return "GET_LEN"; | ||
63 | case UVC_GET_INFO: | ||
64 | return "GET_INFO"; | ||
65 | case UVC_GET_DEF: | ||
66 | return "GET_DEF"; | ||
67 | default: | ||
68 | return "<invalid>"; | ||
69 | } | ||
70 | } | ||
71 | |||
48 | int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, | 72 | int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, |
49 | __u8 intfnum, __u8 cs, void *data, __u16 size) | 73 | __u8 intfnum, __u8 cs, void *data, __u16 size) |
50 | { | 74 | { |
@@ -53,9 +77,9 @@ int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, | |||
53 | ret = __uvc_query_ctrl(dev, query, unit, intfnum, cs, data, size, | 77 | ret = __uvc_query_ctrl(dev, query, unit, intfnum, cs, data, size, |
54 | UVC_CTRL_CONTROL_TIMEOUT); | 78 | UVC_CTRL_CONTROL_TIMEOUT); |
55 | if (ret != size) { | 79 | if (ret != size) { |
56 | uvc_printk(KERN_ERR, "Failed to query (%u) UVC control %u " | 80 | uvc_printk(KERN_ERR, "Failed to query (%s) UVC control %u on " |
57 | "(unit %u) : %d (exp. %u).\n", query, cs, unit, ret, | 81 | "unit %u: %d (exp. %u).\n", uvc_query_name(query), cs, |
58 | size); | 82 | unit, ret, size); |
59 | return -EIO; | 83 | return -EIO; |
60 | } | 84 | } |
61 | 85 | ||
@@ -114,6 +138,15 @@ static void uvc_fixup_video_ctrl(struct uvc_streaming *stream, | |||
114 | bandwidth /= 8; | 138 | bandwidth /= 8; |
115 | bandwidth += 12; | 139 | bandwidth += 12; |
116 | 140 | ||
141 | /* The bandwidth estimate is too low for many cameras. Don't use | ||
142 | * maximum packet sizes lower than 1024 bytes to try and work | ||
143 | * around the problem. According to measurements done on two | ||
144 | * different camera models, the value is high enough to get most | ||
145 | * resolutions working while not preventing two simultaneous | ||
146 | * VGA streams at 15 fps. | ||
147 | */ | ||
148 | bandwidth = max_t(u32, bandwidth, 1024); | ||
149 | |||
117 | ctrl->dwMaxPayloadTransferSize = bandwidth; | 150 | ctrl->dwMaxPayloadTransferSize = bandwidth; |
118 | } | 151 | } |
119 | } | 152 | } |
@@ -394,6 +427,12 @@ static int uvc_video_decode_start(struct uvc_streaming *stream, | |||
394 | 427 | ||
395 | fid = data[1] & UVC_STREAM_FID; | 428 | fid = data[1] & UVC_STREAM_FID; |
396 | 429 | ||
430 | /* Increase the sequence number regardless of any buffer states, so | ||
431 | * that discontinuous sequence numbers always indicate lost frames. | ||
432 | */ | ||
433 | if (stream->last_fid != fid) | ||
434 | stream->sequence++; | ||
435 | |||
397 | /* Store the payload FID bit and return immediately when the buffer is | 436 | /* Store the payload FID bit and return immediately when the buffer is |
398 | * NULL. | 437 | * NULL. |
399 | */ | 438 | */ |
@@ -427,6 +466,7 @@ static int uvc_video_decode_start(struct uvc_streaming *stream, | |||
427 | else | 466 | else |
428 | ktime_get_real_ts(&ts); | 467 | ktime_get_real_ts(&ts); |
429 | 468 | ||
469 | buf->buf.sequence = stream->sequence; | ||
430 | buf->buf.timestamp.tv_sec = ts.tv_sec; | 470 | buf->buf.timestamp.tv_sec = ts.tv_sec; |
431 | buf->buf.timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC; | 471 | buf->buf.timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC; |
432 | 472 | ||
@@ -688,6 +728,7 @@ static void uvc_video_encode_bulk(struct urb *urb, struct uvc_streaming *stream, | |||
688 | if (buf->buf.bytesused == stream->queue.buf_used) { | 728 | if (buf->buf.bytesused == stream->queue.buf_used) { |
689 | stream->queue.buf_used = 0; | 729 | stream->queue.buf_used = 0; |
690 | buf->state = UVC_BUF_STATE_READY; | 730 | buf->state = UVC_BUF_STATE_READY; |
731 | buf->buf.sequence = ++stream->sequence; | ||
691 | uvc_queue_next_buffer(&stream->queue, buf); | 732 | uvc_queue_next_buffer(&stream->queue, buf); |
692 | stream->last_fid ^= UVC_STREAM_FID; | 733 | stream->last_fid ^= UVC_STREAM_FID; |
693 | } | 734 | } |
@@ -946,6 +987,7 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) | |||
946 | unsigned int i; | 987 | unsigned int i; |
947 | int ret; | 988 | int ret; |
948 | 989 | ||
990 | stream->sequence = -1; | ||
949 | stream->last_fid = -1; | 991 | stream->last_fid = -1; |
950 | stream->bulk.header_size = 0; | 992 | stream->bulk.header_size = 0; |
951 | stream->bulk.skip_payload = 0; | 993 | stream->bulk.skip_payload = 0; |