diff options
author | Thierry MERLE <thierry.merle@free.fr> | 2006-12-04 06:31:14 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2006-12-10 06:05:45 -0500 |
commit | f2242ee5474f46d87a45cd4e214b5c3aa02ff293 (patch) | |
tree | 38d7eff61756058d6bec246b672effb0f0f0c04c /drivers/media | |
parent | 18d8a4540caddaa9a42fb4dbc04c75c4b806278b (diff) |
V4L/DVB (4927): Enhancements on usbvision driver
Enhance the buffer management of this driver + some corrections
- linux list.h usage for buffer management
- VIDIOC_ENUMSTD/VIDIOC_G_STD/VIDIOC_S_STD simplification (use of
v4l2_video_std_construct)
- create_sysfs : remove of warnings for video_device_create_file return code
- make the driver compatible with 2.6.19 kernel version (remove
slave_send and slave_recv in usbvision-i2c, change ctrlUrb_complete
function prototype)
- deactivated v4l2_read because this code was not the priority but
working on it :)
Signed-off-by: Thierry MERLE <thierry.merle@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/usbvision/usbvision-core.c | 651 | ||||
-rw-r--r-- | drivers/media/video/usbvision/usbvision-i2c.c | 8 | ||||
-rw-r--r-- | drivers/media/video/usbvision/usbvision.h | 91 |
3 files changed, 418 insertions, 332 deletions
diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c index f225701f16fd..06e8e67da362 100644 --- a/drivers/media/video/usbvision/usbvision-core.c +++ b/drivers/media/video/usbvision/usbvision-core.c | |||
@@ -437,6 +437,25 @@ static struct usbvision_v4l2_format_st usbvision_v4l2_format[] = { | |||
437 | { 1, 2, 16, V4L2_PIX_FMT_YUV422P , "YUV422P" } | 437 | { 1, 2, 16, V4L2_PIX_FMT_YUV422P , "YUV422P" } |
438 | }; | 438 | }; |
439 | 439 | ||
440 | /* supported tv norms */ | ||
441 | static struct usbvision_tvnorm tvnorms[] = { | ||
442 | { | ||
443 | .name = "PAL", | ||
444 | .id = V4L2_STD_PAL, | ||
445 | }, { | ||
446 | .name = "NTSC", | ||
447 | .id = V4L2_STD_NTSC, | ||
448 | }, { | ||
449 | .name = "SECAM", | ||
450 | .id = V4L2_STD_SECAM, | ||
451 | }, { | ||
452 | .name = "PAL-M", | ||
453 | .id = V4L2_STD_PAL_M, | ||
454 | } | ||
455 | }; | ||
456 | |||
457 | #define TVNORMS ARRAY_SIZE(tvnorms) | ||
458 | |||
440 | 459 | ||
441 | /* | 460 | /* |
442 | * The value of 'scratch_buf_size' affects quality of the picture | 461 | * The value of 'scratch_buf_size' affects quality of the picture |
@@ -451,7 +470,7 @@ static const int scratch_buf_size = DEFAULT_SCRATCH_BUF_SIZE; | |||
451 | // Function prototypes | 470 | // Function prototypes |
452 | static int usbvision_restart_isoc(struct usb_usbvision *usbvision); | 471 | static int usbvision_restart_isoc(struct usb_usbvision *usbvision); |
453 | static int usbvision_begin_streaming(struct usb_usbvision *usbvision); | 472 | static int usbvision_begin_streaming(struct usb_usbvision *usbvision); |
454 | static int usbvision_muxsel(struct usb_usbvision *usbvision, int channel, int norm); | 473 | static int usbvision_muxsel(struct usb_usbvision *usbvision, int channel); |
455 | static int usbvision_i2c_write(void *data, unsigned char addr, char *buf, short len); | 474 | static int usbvision_i2c_write(void *data, unsigned char addr, char *buf, short len); |
456 | static int usbvision_i2c_read(void *data, unsigned char addr, char *buf, short len); | 475 | static int usbvision_i2c_read(void *data, unsigned char addr, char *buf, short len); |
457 | static int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg); | 476 | static int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg); |
@@ -463,6 +482,8 @@ static int usbvision_measure_bandwidth (struct usb_usbvision *usbvision); | |||
463 | static void usbvision_release(struct usb_usbvision *usbvision); | 482 | static void usbvision_release(struct usb_usbvision *usbvision); |
464 | static int usbvision_set_input(struct usb_usbvision *usbvision); | 483 | static int usbvision_set_input(struct usb_usbvision *usbvision); |
465 | static int usbvision_set_output(struct usb_usbvision *usbvision, int width, int height); | 484 | static int usbvision_set_output(struct usb_usbvision *usbvision, int width, int height); |
485 | static void usbvision_empty_framequeues(struct usb_usbvision *dev); | ||
486 | static int usbvision_stream_interrupt(struct usb_usbvision *dev); | ||
466 | static void call_i2c_clients(struct usb_usbvision *usbvision, unsigned int cmd, void *arg); | 487 | static void call_i2c_clients(struct usb_usbvision *usbvision, unsigned int cmd, void *arg); |
467 | 488 | ||
468 | 489 | ||
@@ -609,7 +630,7 @@ static ssize_t show_streaming(struct class_device *class_dev, char *buf) | |||
609 | { | 630 | { |
610 | struct video_device *vdev = to_video_device(class_dev); | 631 | struct video_device *vdev = to_video_device(class_dev); |
611 | struct usb_usbvision *usbvision = video_get_drvdata(vdev); | 632 | struct usb_usbvision *usbvision = video_get_drvdata(vdev); |
612 | return sprintf(buf, "%s\n", YES_NO(usbvision->streaming)); | 633 | return sprintf(buf, "%s\n", YES_NO(usbvision->streaming==Stream_On?1:0)); |
613 | } | 634 | } |
614 | static CLASS_DEVICE_ATTR(streaming, S_IRUGO, show_streaming, NULL); | 635 | static CLASS_DEVICE_ATTR(streaming, S_IRUGO, show_streaming, NULL); |
615 | 636 | ||
@@ -639,17 +660,18 @@ static CLASS_DEVICE_ATTR(bridge, S_IRUGO, show_device_bridge, NULL); | |||
639 | 660 | ||
640 | static void usbvision_create_sysfs(struct video_device *vdev) | 661 | static void usbvision_create_sysfs(struct video_device *vdev) |
641 | { | 662 | { |
663 | int res; | ||
642 | if (vdev) { | 664 | if (vdev) { |
643 | video_device_create_file(vdev, &class_device_attr_version); | 665 | res=video_device_create_file(vdev, &class_device_attr_version); |
644 | video_device_create_file(vdev, &class_device_attr_model); | 666 | res=video_device_create_file(vdev, &class_device_attr_model); |
645 | video_device_create_file(vdev, &class_device_attr_hue); | 667 | res=video_device_create_file(vdev, &class_device_attr_hue); |
646 | video_device_create_file(vdev, &class_device_attr_contrast); | 668 | res=video_device_create_file(vdev, &class_device_attr_contrast); |
647 | video_device_create_file(vdev, &class_device_attr_brightness); | 669 | res=video_device_create_file(vdev, &class_device_attr_brightness); |
648 | video_device_create_file(vdev, &class_device_attr_saturation); | 670 | res=video_device_create_file(vdev, &class_device_attr_saturation); |
649 | video_device_create_file(vdev, &class_device_attr_streaming); | 671 | res=video_device_create_file(vdev, &class_device_attr_streaming); |
650 | video_device_create_file(vdev, &class_device_attr_overlay); | 672 | res=video_device_create_file(vdev, &class_device_attr_overlay); |
651 | video_device_create_file(vdev, &class_device_attr_compression); | 673 | res=video_device_create_file(vdev, &class_device_attr_compression); |
652 | video_device_create_file(vdev, &class_device_attr_bridge); | 674 | res=video_device_create_file(vdev, &class_device_attr_bridge); |
653 | } | 675 | } |
654 | } | 676 | } |
655 | 677 | ||
@@ -1209,15 +1231,13 @@ void usbvision_testpattern(struct usb_usbvision *usbvision, int fullframe, | |||
1209 | printk(KERN_ERR "%s: usbvision == NULL\n", proc); | 1231 | printk(KERN_ERR "%s: usbvision == NULL\n", proc); |
1210 | return; | 1232 | return; |
1211 | } | 1233 | } |
1212 | if ((usbvision->curFrameNum < 0) | 1234 | if (usbvision->curFrame == NULL) { |
1213 | || (usbvision->curFrameNum >= USBVISION_NUMFRAMES)) { | 1235 | printk(KERN_ERR "%s: usbvision->curFrame is NULL.\n", proc); |
1214 | printk(KERN_ERR "%s: usbvision->curFrameNum=%d.\n", proc, | ||
1215 | usbvision->curFrameNum); | ||
1216 | return; | 1236 | return; |
1217 | } | 1237 | } |
1218 | 1238 | ||
1219 | /* Grab the current frame */ | 1239 | /* Grab the current frame */ |
1220 | frame = &usbvision->frame[usbvision->curFrameNum]; | 1240 | frame = usbvision->curFrame; |
1221 | 1241 | ||
1222 | /* Optionally start at the beginning */ | 1242 | /* Optionally start at the beginning */ |
1223 | if (fullframe) { | 1243 | if (fullframe) { |
@@ -1290,7 +1310,7 @@ static enum ParseState usbvision_find_header(struct usb_usbvision *usbvision) | |||
1290 | frame = &usbvision->overlay_frame; | 1310 | frame = &usbvision->overlay_frame; |
1291 | } | 1311 | } |
1292 | else { | 1312 | else { |
1293 | frame = &usbvision->frame[usbvision->curFrameNum]; | 1313 | frame = usbvision->curFrame; |
1294 | } | 1314 | } |
1295 | 1315 | ||
1296 | while (scratch_get_header(usbvision, &frame->isocHeader) == USBVISION_HEADER_LENGTH) { | 1316 | while (scratch_get_header(usbvision, &frame->isocHeader) == USBVISION_HEADER_LENGTH) { |
@@ -1325,7 +1345,6 @@ static enum ParseState usbvision_find_header(struct usb_usbvision *usbvision) | |||
1325 | frame->frmwidth = frame->isocHeader.frameWidth * usbvision->stretch_width; | 1345 | frame->frmwidth = frame->isocHeader.frameWidth * usbvision->stretch_width; |
1326 | frame->frmheight = frame->isocHeader.frameHeight * usbvision->stretch_height; | 1346 | frame->frmheight = frame->isocHeader.frameHeight * usbvision->stretch_height; |
1327 | frame->v4l2_linesize = (frame->frmwidth * frame->v4l2_format.depth)>> 3; | 1347 | frame->v4l2_linesize = (frame->frmwidth * frame->v4l2_format.depth)>> 3; |
1328 | usbvision->curFrame = frame; | ||
1329 | } | 1348 | } |
1330 | else { // no header found | 1349 | else { // no header found |
1331 | PDEBUG(DBG_HEADER, "skipping scratch data, no header"); | 1350 | PDEBUG(DBG_HEADER, "skipping scratch data, no header"); |
@@ -1380,7 +1399,7 @@ static enum ParseState usbvision_parse_lines_422(struct usb_usbvision *usbvision | |||
1380 | usbvision->vid_buf.fmt.bytesperline; | 1399 | usbvision->vid_buf.fmt.bytesperline; |
1381 | } | 1400 | } |
1382 | else { | 1401 | else { |
1383 | frame = &usbvision->frame[usbvision->curFrameNum]; | 1402 | frame = usbvision->curFrame; |
1384 | f = frame->data + (frame->v4l2_linesize * frame->curline); | 1403 | f = frame->data + (frame->v4l2_linesize * frame->curline); |
1385 | } | 1404 | } |
1386 | 1405 | ||
@@ -1612,7 +1631,7 @@ static enum ParseState usbvision_parse_compress(struct usb_usbvision *usbvision, | |||
1612 | usbvision->vid_buf.fmt.bytesperline; | 1631 | usbvision->vid_buf.fmt.bytesperline; |
1613 | } | 1632 | } |
1614 | else { | 1633 | else { |
1615 | frame = &usbvision->frame[usbvision->curFrameNum]; | 1634 | frame = usbvision->curFrame; |
1616 | imageSize = frame->frmwidth * frame->frmheight; | 1635 | imageSize = frame->frmwidth * frame->frmheight; |
1617 | if ( (frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) || | 1636 | if ( (frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) || |
1618 | (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) ) | 1637 | (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) ) |
@@ -1833,7 +1852,7 @@ static enum ParseState usbvision_parse_lines_420(struct usb_usbvision *usbvision | |||
1833 | f_odd = f_even + usbvision->vid_buf.fmt.bytesperline * usbvision->stretch_height; | 1852 | f_odd = f_even + usbvision->vid_buf.fmt.bytesperline * usbvision->stretch_height; |
1834 | } | 1853 | } |
1835 | else { | 1854 | else { |
1836 | frame = &usbvision->frame[usbvision->curFrameNum]; | 1855 | frame = usbvision->curFrame; |
1837 | f_even = frame->data + (frame->v4l2_linesize * frame->curline); | 1856 | f_even = frame->data + (frame->v4l2_linesize * frame->curline); |
1838 | f_odd = f_even + frame->v4l2_linesize * usbvision->stretch_height; | 1857 | f_odd = f_even + frame->v4l2_linesize * usbvision->stretch_height; |
1839 | } | 1858 | } |
@@ -2088,17 +2107,17 @@ static void usbvision_parse_data(struct usb_usbvision *usbvision) | |||
2088 | struct usbvision_frame *frame; | 2107 | struct usbvision_frame *frame; |
2089 | enum ParseState newstate; | 2108 | enum ParseState newstate; |
2090 | long copylen = 0; | 2109 | long copylen = 0; |
2110 | unsigned long lock_flags; | ||
2091 | 2111 | ||
2092 | if (usbvision->overlay) { | 2112 | if (usbvision->overlay) { |
2093 | frame = &usbvision->overlay_frame; | 2113 | frame = &usbvision->overlay_frame; |
2094 | } | 2114 | } |
2095 | else { | 2115 | else { |
2096 | frame = &usbvision->frame[usbvision->curFrameNum]; | 2116 | frame = usbvision->curFrame; |
2097 | } | 2117 | } |
2098 | 2118 | ||
2099 | PDEBUG(DBG_PARSE, "parsing len=%d\n", scratch_len(usbvision)); | 2119 | PDEBUG(DBG_PARSE, "parsing len=%d\n", scratch_len(usbvision)); |
2100 | 2120 | ||
2101 | |||
2102 | while (1) { | 2121 | while (1) { |
2103 | 2122 | ||
2104 | newstate = ParseState_Out; | 2123 | newstate = ParseState_Out; |
@@ -2141,7 +2160,10 @@ static void usbvision_parse_data(struct usb_usbvision *usbvision) | |||
2141 | copylen = 0; | 2160 | copylen = 0; |
2142 | } | 2161 | } |
2143 | else { | 2162 | else { |
2144 | usbvision->curFrameNum = -1; | 2163 | spin_lock_irqsave(&usbvision->queue_lock, lock_flags); |
2164 | list_move_tail(&(frame->frame), &usbvision->outqueue); | ||
2165 | usbvision->curFrame = NULL; | ||
2166 | spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); | ||
2145 | } | 2167 | } |
2146 | usbvision->frame_num++; | 2168 | usbvision->frame_num++; |
2147 | 2169 | ||
@@ -2150,10 +2172,14 @@ static void usbvision_parse_data(struct usb_usbvision *usbvision) | |||
2150 | usbvision_osd_stats(usbvision, frame); | 2172 | usbvision_osd_stats(usbvision, frame); |
2151 | 2173 | ||
2152 | /* This will cause the process to request another frame. */ | 2174 | /* This will cause the process to request another frame. */ |
2153 | if (waitqueue_active(&frame->wq)) { | 2175 | if (waitqueue_active(&usbvision->wait_frame)) { |
2154 | wake_up_interruptible(&frame->wq); | 2176 | PDEBUG(DBG_PARSE, "Wake up !"); |
2177 | wake_up_interruptible(&usbvision->wait_frame); | ||
2155 | } | 2178 | } |
2156 | } | 2179 | } |
2180 | else | ||
2181 | frame->grabstate = FrameState_Grabbing; | ||
2182 | |||
2157 | 2183 | ||
2158 | /* Update the frame's uncompressed length. */ | 2184 | /* Update the frame's uncompressed length. */ |
2159 | frame->scanlength += copylen; | 2185 | frame->scanlength += copylen; |
@@ -2164,7 +2190,7 @@ static void usbvision_parse_data(struct usb_usbvision *usbvision) | |||
2164 | * Make all of the blocks of data contiguous | 2190 | * Make all of the blocks of data contiguous |
2165 | */ | 2191 | */ |
2166 | static int usbvision_compress_isochronous(struct usb_usbvision *usbvision, | 2192 | static int usbvision_compress_isochronous(struct usb_usbvision *usbvision, |
2167 | struct urb *urb) | 2193 | struct urb *urb) |
2168 | { | 2194 | { |
2169 | unsigned char *packet_data; | 2195 | unsigned char *packet_data; |
2170 | int i, totlen = 0; | 2196 | int i, totlen = 0; |
@@ -2246,51 +2272,70 @@ static int usbvision_compress_isochronous(struct usb_usbvision *usbvision, | |||
2246 | 2272 | ||
2247 | static void usbvision_isocIrq(struct urb *urb, struct pt_regs *regs) | 2273 | static void usbvision_isocIrq(struct urb *urb, struct pt_regs *regs) |
2248 | { | 2274 | { |
2249 | int errCode = 0; | 2275 | int errCode = 0; |
2250 | int len; | 2276 | int len; |
2251 | struct usb_usbvision *usbvision = urb->context; | 2277 | struct usb_usbvision *usbvision = urb->context; |
2252 | int i; | 2278 | int i; |
2253 | unsigned long startTime = jiffies; | 2279 | unsigned long startTime = jiffies; |
2254 | 2280 | struct usbvision_frame **f; | |
2255 | /* We don't want to do anything if we are about to be removed! */ | ||
2256 | if (!USBVISION_IS_OPERATIONAL(usbvision)) | ||
2257 | return; | ||
2258 | 2281 | ||
2259 | if (!usbvision->streaming) { | 2282 | /* We don't want to do anything if we are about to be removed! */ |
2260 | PDEBUG(DBG_IRQ, "oops, not streaming, but interrupt"); | 2283 | if (!USBVISION_IS_OPERATIONAL(usbvision)) |
2261 | return; | 2284 | return; |
2262 | } | ||
2263 | 2285 | ||
2264 | /* Copy the data received into our scratch buffer */ | 2286 | f = &usbvision->curFrame; |
2265 | len = usbvision_compress_isochronous(usbvision, urb); | ||
2266 | 2287 | ||
2267 | usbvision->isocUrbCount++; | 2288 | /* Manage streaming interruption */ |
2268 | usbvision->urb_length = len; | 2289 | if (usbvision->streaming == Stream_Interrupt) { |
2290 | usbvision->streaming = Stream_Off; | ||
2291 | if ((*f)) { | ||
2292 | (*f)->grabstate = FrameState_Ready; | ||
2293 | (*f)->scanstate = ScanState_Scanning; | ||
2294 | } | ||
2295 | PDEBUG(DBG_IRQ, "stream interrupted"); | ||
2296 | wake_up_interruptible(&usbvision->wait_stream); | ||
2297 | } | ||
2269 | 2298 | ||
2270 | for (i = 0; i < USBVISION_URB_FRAMES; i++) { | 2299 | /* Copy the data received into our scratch buffer */ |
2271 | urb->iso_frame_desc[i].status = 0; | 2300 | len = usbvision_compress_isochronous(usbvision, urb); |
2272 | urb->iso_frame_desc[i].actual_length = 0; | ||
2273 | } | ||
2274 | urb->status = 0; | ||
2275 | urb->dev = usbvision->dev; | ||
2276 | errCode = usb_submit_urb (urb, GFP_ATOMIC); | ||
2277 | 2301 | ||
2278 | /* Disable this warning. By design of the driver. */ | 2302 | usbvision->isocUrbCount++; |
2279 | // if(errCode) { | 2303 | usbvision->urb_length = len; |
2280 | // err("%s: usb_submit_urb failed: error %d", __FUNCTION__, errCode); | ||
2281 | // } | ||
2282 | 2304 | ||
2283 | /* If we collected enough data let's parse! */ | 2305 | if (usbvision->streaming == Stream_On) { |
2284 | if (scratch_len(usbvision) > USBVISION_HEADER_LENGTH) { /* 12 == header_length */ | 2306 | |
2285 | /*If we don't have a frame we're current working on, complain */ | 2307 | /* If we collected enough data let's parse! */ |
2286 | if ((usbvision->curFrameNum >= 0) || (usbvision->overlay)) | 2308 | if (scratch_len(usbvision) > USBVISION_HEADER_LENGTH) { /* 12 == header_length */ |
2287 | usbvision_parse_data(usbvision); | 2309 | /*If we don't have a frame we're current working on, complain */ |
2288 | else { | 2310 | if((!list_empty(&(usbvision->inqueue))) || (usbvision->overlay)) { |
2289 | PDEBUG(DBG_IRQ, "received data, but no one needs it"); | 2311 | if (!(*f)) { |
2290 | scratch_reset(usbvision); | 2312 | (*f) = list_entry(usbvision->inqueue.next,struct usbvision_frame, frame); |
2313 | } | ||
2314 | usbvision_parse_data(usbvision); | ||
2315 | } | ||
2316 | else { | ||
2317 | PDEBUG(DBG_IRQ, "received data, but no one needs it"); | ||
2318 | scratch_reset(usbvision); | ||
2319 | } | ||
2291 | } | 2320 | } |
2292 | } | 2321 | } |
2322 | |||
2293 | usbvision->timeInIrq += jiffies - startTime; | 2323 | usbvision->timeInIrq += jiffies - startTime; |
2324 | |||
2325 | for (i = 0; i < USBVISION_URB_FRAMES; i++) { | ||
2326 | urb->iso_frame_desc[i].status = 0; | ||
2327 | urb->iso_frame_desc[i].actual_length = 0; | ||
2328 | } | ||
2329 | |||
2330 | urb->status = 0; | ||
2331 | urb->dev = usbvision->dev; | ||
2332 | errCode = usb_submit_urb (urb, GFP_ATOMIC); | ||
2333 | |||
2334 | /* Disable this warning. By design of the driver. */ | ||
2335 | // if(errCode) { | ||
2336 | // err("%s: usb_submit_urb failed: error %d", __FUNCTION__, errCode); | ||
2337 | // } | ||
2338 | |||
2294 | return; | 2339 | return; |
2295 | } | 2340 | } |
2296 | 2341 | ||
@@ -2539,7 +2584,6 @@ static int attach_inform(struct i2c_client *client) | |||
2539 | struct usb_usbvision *usbvision; | 2584 | struct usb_usbvision *usbvision; |
2540 | struct tuner_setup tun_addr; | 2585 | struct tuner_setup tun_addr; |
2541 | int i; | 2586 | int i; |
2542 | v4l2_std_id stdId; | ||
2543 | 2587 | ||
2544 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) | 2588 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) |
2545 | usbvision = (struct usb_usbvision *)client->adapter->data; | 2589 | usbvision = (struct usb_usbvision *)client->adapter->data; |
@@ -2560,13 +2604,11 @@ static int attach_inform(struct i2c_client *client) | |||
2560 | tun_addr.type = usbvision->tuner_type; | 2604 | tun_addr.type = usbvision->tuner_type; |
2561 | tun_addr.addr = ADDR_UNSET; | 2605 | tun_addr.addr = ADDR_UNSET; |
2562 | client->driver->command(client,TUNER_SET_TYPE_ADDR, &tun_addr); | 2606 | client->driver->command(client,TUNER_SET_TYPE_ADDR, &tun_addr); |
2563 | 2607 | call_i2c_clients(usbvision, VIDIOC_INT_RESET, NULL); | |
2564 | call_i2c_clients(usbvision, VIDIOC_S_INPUT, &usbvision->input.index); | 2608 | call_i2c_clients(usbvision, VIDIOC_S_INPUT, &usbvision->ctl_input); |
2609 | call_i2c_clients(usbvision, VIDIOC_STREAMON, NULL); | ||
2565 | } | 2610 | } |
2566 | // FIXME : need to add a call VIDIOC_S_CTRL for each control | 2611 | call_i2c_clients(usbvision, VIDIOC_S_STD, &usbvision->tvnorm->id); |
2567 | /* call_i2c_clients(usbvision, DECODER_SET_PICTURE, &usbvision->vpic); */ | ||
2568 | stdId = usbvision->input.std; | ||
2569 | call_i2c_clients(usbvision, VIDIOC_S_STD, &stdId); | ||
2570 | 2612 | ||
2571 | PDEBUG(DBG_I2C, "usbvision[%d] attaches %s", usbvision->nr, client->name); | 2613 | PDEBUG(DBG_I2C, "usbvision[%d] attaches %s", usbvision->nr, client->name); |
2572 | 2614 | ||
@@ -2995,10 +3037,10 @@ static int usbvision_set_output(struct usb_usbvision *usbvision, int width, | |||
2995 | frameRate = FRAMERATE_MAX; | 3037 | frameRate = FRAMERATE_MAX; |
2996 | } | 3038 | } |
2997 | 3039 | ||
2998 | if (usbvision->input.std & V4L2_STD_625_50) { | 3040 | if (usbvision->tvnorm->id & V4L2_STD_625_50) { |
2999 | frameDrop = frameRate * 32 / 25 - 1; | 3041 | frameDrop = frameRate * 32 / 25 - 1; |
3000 | } | 3042 | } |
3001 | else if (usbvision->input.std & V4L2_STD_525_60) { | 3043 | else if (usbvision->tvnorm->id & V4L2_STD_525_60) { |
3002 | frameDrop = frameRate * 32 / 30 - 1; | 3044 | frameDrop = frameRate * 32 / 30 - 1; |
3003 | } | 3045 | } |
3004 | 3046 | ||
@@ -3022,6 +3064,40 @@ static int usbvision_set_output(struct usb_usbvision *usbvision, int width, | |||
3022 | 3064 | ||
3023 | 3065 | ||
3024 | /* | 3066 | /* |
3067 | * usbvision_empty_framequeues() | ||
3068 | * prepare queues for incoming and outgoing frames | ||
3069 | */ | ||
3070 | static void usbvision_empty_framequeues(struct usb_usbvision *usbvision) | ||
3071 | { | ||
3072 | u32 i; | ||
3073 | |||
3074 | INIT_LIST_HEAD(&(usbvision->inqueue)); | ||
3075 | INIT_LIST_HEAD(&(usbvision->outqueue)); | ||
3076 | |||
3077 | for (i = 0; i < USBVISION_NUMFRAMES; i++) { | ||
3078 | usbvision->frame[i].grabstate = FrameState_Unused; | ||
3079 | usbvision->frame[i].bytes_read = 0; | ||
3080 | } | ||
3081 | } | ||
3082 | |||
3083 | /* | ||
3084 | * usbvision_stream_interrupt() | ||
3085 | * stops streaming | ||
3086 | */ | ||
3087 | static int usbvision_stream_interrupt(struct usb_usbvision *usbvision) | ||
3088 | { | ||
3089 | int ret = 0; | ||
3090 | |||
3091 | /* stop reading from the device */ | ||
3092 | |||
3093 | usbvision->streaming = Stream_Interrupt; | ||
3094 | ret = wait_event_timeout(usbvision->wait_stream, | ||
3095 | (usbvision->streaming == Stream_Off), | ||
3096 | msecs_to_jiffies(USBVISION_NUMSBUF*USBVISION_URB_FRAMES)); | ||
3097 | return ret; | ||
3098 | } | ||
3099 | |||
3100 | /* | ||
3025 | * usbvision_set_compress_params() | 3101 | * usbvision_set_compress_params() |
3026 | * | 3102 | * |
3027 | */ | 3103 | */ |
@@ -3135,7 +3211,7 @@ static int usbvision_set_input(struct usb_usbvision *usbvision) | |||
3135 | } | 3211 | } |
3136 | 3212 | ||
3137 | 3213 | ||
3138 | if (usbvision->input.std & V4L2_STD_PAL) { | 3214 | if (usbvision->tvnorm->id & V4L2_STD_PAL) { |
3139 | value[0] = 0xC0; | 3215 | value[0] = 0xC0; |
3140 | value[1] = 0x02; //0x02C0 -> 704 Input video line length | 3216 | value[1] = 0x02; //0x02C0 -> 704 Input video line length |
3141 | value[2] = 0x20; | 3217 | value[2] = 0x20; |
@@ -3144,7 +3220,7 @@ static int usbvision_set_input(struct usb_usbvision *usbvision) | |||
3144 | value[5] = 0x00; //0x0060 -> 96 Input video h offset | 3220 | value[5] = 0x00; //0x0060 -> 96 Input video h offset |
3145 | value[6] = 0x16; | 3221 | value[6] = 0x16; |
3146 | value[7] = 0x00; //0x0016 -> 22 Input video v offset | 3222 | value[7] = 0x00; //0x0016 -> 22 Input video v offset |
3147 | } else if (usbvision->input.std & V4L2_STD_SECAM) { | 3223 | } else if (usbvision->tvnorm->id & V4L2_STD_SECAM) { |
3148 | value[0] = 0xC0; | 3224 | value[0] = 0xC0; |
3149 | value[1] = 0x02; //0x02C0 -> 704 Input video line length | 3225 | value[1] = 0x02; //0x02C0 -> 704 Input video line length |
3150 | value[2] = 0x20; | 3226 | value[2] = 0x20; |
@@ -3434,7 +3510,7 @@ static int usbvision_init_isoc(struct usb_usbvision *usbvision) | |||
3434 | if (!USBVISION_IS_OPERATIONAL(usbvision)) | 3510 | if (!USBVISION_IS_OPERATIONAL(usbvision)) |
3435 | return -EFAULT; | 3511 | return -EFAULT; |
3436 | 3512 | ||
3437 | usbvision->curFrameNum = -1; | 3513 | usbvision->curFrame = NULL; |
3438 | scratch_reset(usbvision); | 3514 | scratch_reset(usbvision); |
3439 | 3515 | ||
3440 | /* Alternate interface 1 is is the biggest frame size */ | 3516 | /* Alternate interface 1 is is the biggest frame size */ |
@@ -3503,7 +3579,7 @@ static int usbvision_init_isoc(struct usb_usbvision *usbvision) | |||
3503 | } | 3579 | } |
3504 | } | 3580 | } |
3505 | 3581 | ||
3506 | usbvision->streaming = 1; | 3582 | usbvision->streaming = Stream_On; |
3507 | PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x", __FUNCTION__, usbvision->video_endp); | 3583 | PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x", __FUNCTION__, usbvision->video_endp); |
3508 | return 0; | 3584 | return 0; |
3509 | } | 3585 | } |
@@ -3519,7 +3595,8 @@ static void usbvision_stop_isoc(struct usb_usbvision *usbvision) | |||
3519 | { | 3595 | { |
3520 | int bufIdx, errCode, regValue; | 3596 | int bufIdx, errCode, regValue; |
3521 | 3597 | ||
3522 | if (!usbvision->streaming || (usbvision->dev == NULL)) | 3598 | // FIXME : removed the streaming==Stream_Off. This field has not the same signification than before ! |
3599 | if (usbvision->dev == NULL) | ||
3523 | return; | 3600 | return; |
3524 | 3601 | ||
3525 | /* Unschedule all of the iso td's */ | 3602 | /* Unschedule all of the iso td's */ |
@@ -3530,9 +3607,8 @@ static void usbvision_stop_isoc(struct usb_usbvision *usbvision) | |||
3530 | } | 3607 | } |
3531 | 3608 | ||
3532 | 3609 | ||
3533 | PDEBUG(DBG_ISOC, "%s: streaming=0\n", __FUNCTION__); | 3610 | PDEBUG(DBG_ISOC, "%s: streaming=Stream_Off\n", __FUNCTION__); |
3534 | usbvision->streaming = 0; | 3611 | usbvision->streaming = Stream_Off; |
3535 | |||
3536 | 3612 | ||
3537 | if (!usbvision->remove_pending) { | 3613 | if (!usbvision->remove_pending) { |
3538 | 3614 | ||
@@ -3552,62 +3628,7 @@ static void usbvision_stop_isoc(struct usb_usbvision *usbvision) | |||
3552 | } | 3628 | } |
3553 | } | 3629 | } |
3554 | 3630 | ||
3555 | /* | 3631 | static int usbvision_muxsel(struct usb_usbvision *usbvision, int channel) |
3556 | * usbvision_new_frame() | ||
3557 | * | ||
3558 | */ | ||
3559 | static int usbvision_new_frame(struct usb_usbvision *usbvision, int framenum) | ||
3560 | { | ||
3561 | struct usbvision_frame *frame; | ||
3562 | int n; //byhec , width, height; | ||
3563 | |||
3564 | /* If we're not grabbing a frame right now and the other frame is */ | ||
3565 | /* ready to be grabbed into, then use it instead */ | ||
3566 | if (usbvision->curFrameNum != -1) | ||
3567 | return 0; | ||
3568 | |||
3569 | n = (framenum - 1 + USBVISION_NUMFRAMES) % USBVISION_NUMFRAMES; | ||
3570 | if (usbvision->frame[n].grabstate == FrameState_Ready) | ||
3571 | framenum = n; | ||
3572 | |||
3573 | frame = &usbvision->frame[framenum]; | ||
3574 | |||
3575 | frame->grabstate = FrameState_Grabbing; | ||
3576 | frame->scanstate = ScanState_Scanning; | ||
3577 | frame->scanlength = 0; /* Accumulated in usbvision_parse_data() */ | ||
3578 | usbvision->curFrameNum = framenum; | ||
3579 | |||
3580 | /* | ||
3581 | * Normally we would want to copy previous frame into the current one | ||
3582 | * before we even start filling it with data; this allows us to stop | ||
3583 | * filling at any moment; top portion of the frame will be new and | ||
3584 | * bottom portion will stay as it was in previous frame. If we don't | ||
3585 | * do that then missing chunks of video stream will result in flickering | ||
3586 | * portions of old data whatever it was before. | ||
3587 | * | ||
3588 | * If we choose not to copy previous frame (to, for example, save few | ||
3589 | * bus cycles - the frame can be pretty large!) then we have an option | ||
3590 | * to clear the frame before using. If we experience losses in this | ||
3591 | * mode then missing picture will be black (flickering). | ||
3592 | * | ||
3593 | * Finally, if user chooses not to clean the current frame before | ||
3594 | * filling it with data then the old data will be visible if we fail | ||
3595 | * to refill entire frame with new data. | ||
3596 | */ | ||
3597 | if (!(flags & FLAGS_SEPARATE_FRAMES)) { | ||
3598 | /* This copies previous frame into this one to mask losses */ | ||
3599 | memmove(frame->data, usbvision->frame[1 - framenum].data, | ||
3600 | MAX_FRAME_SIZE); | ||
3601 | } else { | ||
3602 | if (flags & FLAGS_CLEAN_FRAMES) { | ||
3603 | /*This provides a "clean" frame but slows things down */ | ||
3604 | memset(frame->data, 0, MAX_FRAME_SIZE); | ||
3605 | } | ||
3606 | } | ||
3607 | return 0; | ||
3608 | } | ||
3609 | |||
3610 | static int usbvision_muxsel(struct usb_usbvision *usbvision, int channel, int norm) | ||
3611 | { | 3632 | { |
3612 | int mode[4]; | 3633 | int mode[4]; |
3613 | int audio[]= {1, 0, 0, 0}; | 3634 | int audio[]= {1, 0, 0, 0}; |
@@ -3618,16 +3639,10 @@ static int usbvision_muxsel(struct usb_usbvision *usbvision, int channel, int no | |||
3618 | //channel 3 is additional video inputs to the device with audio channel 0 (line in) | 3639 | //channel 3 is additional video inputs to the device with audio channel 0 (line in) |
3619 | 3640 | ||
3620 | RESTRICT_TO_RANGE(channel, 0, usbvision->video_inputs); | 3641 | RESTRICT_TO_RANGE(channel, 0, usbvision->video_inputs); |
3621 | /* set the new video norm */ | 3642 | usbvision->ctl_input = channel; |
3622 | if (usbvision->input.std != norm) { | ||
3623 | v4l2_std_id video_command = norm; | ||
3624 | |||
3625 | route.input = SAA7115_COMPOSITE1; | 3643 | route.input = SAA7115_COMPOSITE1; |
3626 | call_i2c_clients(usbvision, VIDIOC_INT_S_VIDEO_ROUTING,&route); | 3644 | call_i2c_clients(usbvision, VIDIOC_INT_S_VIDEO_ROUTING,&route); |
3627 | call_i2c_clients(usbvision, VIDIOC_S_STD, &video_command); | 3645 | call_i2c_clients(usbvision, VIDIOC_S_INPUT, &usbvision->ctl_input); |
3628 | usbvision->input.std = norm; | ||
3629 | call_i2c_clients(usbvision, VIDIOC_S_INPUT, &usbvision->input.index); //set norm in tuner | ||
3630 | } | ||
3631 | 3646 | ||
3632 | // set the new channel | 3647 | // set the new channel |
3633 | // Regular USB TV Tuners -> channel: 0 = Television, 1 = Composite, 2 = S-Video | 3648 | // Regular USB TV Tuners -> channel: 0 = Television, 1 = Composite, 2 = S-Video |
@@ -3703,8 +3718,13 @@ static int usbvision_v4l2_open(struct inode *inode, struct file *file) | |||
3703 | errCode = -ENOMEM; | 3718 | errCode = -ENOMEM; |
3704 | } | 3719 | } |
3705 | else { | 3720 | else { |
3721 | spin_lock_init(&usbvision->queue_lock); | ||
3722 | init_waitqueue_head(&usbvision->wait_frame); | ||
3723 | init_waitqueue_head(&usbvision->wait_stream); | ||
3724 | |||
3706 | /* Allocate all buffers */ | 3725 | /* Allocate all buffers */ |
3707 | for (i = 0; i < USBVISION_NUMFRAMES; i++) { | 3726 | for (i = 0; i < USBVISION_NUMFRAMES; i++) { |
3727 | usbvision->frame[i].index = i; | ||
3708 | usbvision->frame[i].grabstate = FrameState_Unused; | 3728 | usbvision->frame[i].grabstate = FrameState_Unused; |
3709 | usbvision->frame[i].data = usbvision->fbuf + | 3729 | usbvision->frame[i].data = usbvision->fbuf + |
3710 | i * MAX_FRAME_SIZE; | 3730 | i * MAX_FRAME_SIZE; |
@@ -3804,6 +3824,9 @@ static int usbvision_v4l2_open(struct inode *inode, struct file *file) | |||
3804 | if (errCode) { | 3824 | if (errCode) { |
3805 | } | 3825 | } |
3806 | 3826 | ||
3827 | /* prepare queues */ | ||
3828 | usbvision_empty_framequeues(usbvision); | ||
3829 | |||
3807 | PDEBUG(DBG_IO, "success"); | 3830 | PDEBUG(DBG_IO, "success"); |
3808 | return errCode; | 3831 | return errCode; |
3809 | } | 3832 | } |
@@ -3875,6 +3898,8 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
3875 | if (!USBVISION_IS_OPERATIONAL(usbvision)) | 3898 | if (!USBVISION_IS_OPERATIONAL(usbvision)) |
3876 | return -EFAULT; | 3899 | return -EFAULT; |
3877 | 3900 | ||
3901 | // if (debug & DBG_IOCTL) v4l_printk_ioctl(cmd); | ||
3902 | |||
3878 | switch (cmd) { | 3903 | switch (cmd) { |
3879 | case UVIOCSREG: | 3904 | case UVIOCSREG: |
3880 | { | 3905 | { |
@@ -3914,7 +3939,20 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
3914 | case VIDIOC_QUERYCAP: | 3939 | case VIDIOC_QUERYCAP: |
3915 | { | 3940 | { |
3916 | struct v4l2_capability *vc=arg; | 3941 | struct v4l2_capability *vc=arg; |
3917 | *vc = usbvision->vcap; | 3942 | |
3943 | memset(vc, 0, sizeof(*vc)); | ||
3944 | strlcpy(vc->driver, "USBVision", sizeof(vc->driver)); | ||
3945 | strlcpy(vc->card, usbvision_device_data[usbvision->DevModel].ModelString, | ||
3946 | sizeof(vc->card)); | ||
3947 | strlcpy(vc->bus_info, usbvision->dev->dev.bus_id, | ||
3948 | sizeof(vc->bus_info)); | ||
3949 | vc->version = USBVISION_DRIVER_VERSION; | ||
3950 | vc->capabilities = V4L2_CAP_VIDEO_CAPTURE | | ||
3951 | V4L2_CAP_AUDIO | | ||
3952 | V4L2_CAP_READWRITE | | ||
3953 | V4L2_CAP_STREAMING | | ||
3954 | (dga ? (V4L2_FBUF_CAP_LIST_CLIPPING | V4L2_CAP_VIDEO_OVERLAY) : 0) | | ||
3955 | (usbvision->have_tuner ? V4L2_CAP_TUNER : 0); | ||
3918 | PDEBUG(DBG_IOCTL, "VIDIOC_QUERYCAP"); | 3956 | PDEBUG(DBG_IOCTL, "VIDIOC_QUERYCAP"); |
3919 | return 0; | 3957 | return 0; |
3920 | } | 3958 | } |
@@ -3975,38 +4013,24 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
3975 | } | 4013 | } |
3976 | case VIDIOC_ENUMSTD: | 4014 | case VIDIOC_ENUMSTD: |
3977 | { | 4015 | { |
3978 | struct v4l2_standard *vs = arg; | 4016 | struct v4l2_standard *e = arg; |
3979 | switch(vs->index) { | 4017 | unsigned int i; |
3980 | case 0: | 4018 | int ret; |
3981 | vs->id = V4L2_STD_PAL; | 4019 | |
3982 | strcpy(vs->name,"PAL"); | 4020 | i = e->index; |
3983 | vs->frameperiod.numerator = 1; | 4021 | if (i >= TVNORMS) |
3984 | vs->frameperiod.denominator = 25; | ||
3985 | vs->framelines = 625; | ||
3986 | break; | ||
3987 | case 1: | ||
3988 | vs->id = V4L2_STD_NTSC; | ||
3989 | strcpy(vs->name,"NTSC"); | ||
3990 | vs->frameperiod.numerator = 1001; | ||
3991 | vs->frameperiod.denominator = 30000; | ||
3992 | vs->framelines = 525; | ||
3993 | break; | ||
3994 | case 2: | ||
3995 | vs->id = V4L2_STD_SECAM; | ||
3996 | strcpy(vs->name,"SECAM"); | ||
3997 | vs->frameperiod.numerator = 1; | ||
3998 | vs->frameperiod.denominator = 25; | ||
3999 | vs->framelines = 625; | ||
4000 | break; | ||
4001 | default: | ||
4002 | return -EINVAL; | 4022 | return -EINVAL; |
4003 | } | 4023 | ret = v4l2_video_std_construct(e, tvnorms[e->index].id, |
4024 | tvnorms[e->index].name); | ||
4025 | e->index = i; | ||
4026 | if (ret < 0) | ||
4027 | return ret; | ||
4004 | return 0; | 4028 | return 0; |
4005 | } | 4029 | } |
4006 | case VIDIOC_G_INPUT: | 4030 | case VIDIOC_G_INPUT: |
4007 | { | 4031 | { |
4008 | int *input = arg; | 4032 | int *input = arg; |
4009 | *input = usbvision->input.index; | 4033 | *input = usbvision->ctl_input; |
4010 | return 0; | 4034 | return 0; |
4011 | } | 4035 | } |
4012 | case VIDIOC_S_INPUT: | 4036 | case VIDIOC_S_INPUT: |
@@ -4014,10 +4038,10 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
4014 | int *input = arg; | 4038 | int *input = arg; |
4015 | if ((*input >= usbvision->video_inputs) || (*input < 0) ) | 4039 | if ((*input >= usbvision->video_inputs) || (*input < 0) ) |
4016 | return -EINVAL; | 4040 | return -EINVAL; |
4017 | usbvision->input.index = *input; | 4041 | usbvision->ctl_input = *input; |
4018 | 4042 | ||
4019 | down(&usbvision->lock); | 4043 | down(&usbvision->lock); |
4020 | usbvision_muxsel(usbvision, usbvision->input.index, usbvision->input.std); | 4044 | usbvision_muxsel(usbvision, usbvision->ctl_input); |
4021 | usbvision_set_input(usbvision); | 4045 | usbvision_set_input(usbvision); |
4022 | usbvision_set_output(usbvision, usbvision->curwidth, usbvision->curheight); | 4046 | usbvision_set_output(usbvision, usbvision->curwidth, usbvision->curheight); |
4023 | up(&usbvision->lock); | 4047 | up(&usbvision->lock); |
@@ -4025,43 +4049,50 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
4025 | } | 4049 | } |
4026 | case VIDIOC_G_STD: | 4050 | case VIDIOC_G_STD: |
4027 | { | 4051 | { |
4028 | v4l2_std_id *std = arg; | 4052 | v4l2_std_id *id = arg; |
4029 | *std = usbvision->input.std; | 4053 | |
4030 | PDEBUG(DBG_IOCTL, "VIDIOC_G_STD std_id=%x", (unsigned)*std); | 4054 | *id = usbvision->tvnorm->id; |
4055 | |||
4056 | PDEBUG(DBG_IOCTL, "VIDIOC_G_STD std_id=%s", usbvision->tvnorm->name); | ||
4031 | return 0; | 4057 | return 0; |
4032 | } | 4058 | } |
4033 | case VIDIOC_S_STD: | 4059 | case VIDIOC_S_STD: |
4034 | { | 4060 | { |
4035 | v4l2_std_id *std = arg; | 4061 | v4l2_std_id *id = arg; |
4062 | unsigned int i; | ||
4063 | |||
4064 | for (i = 0; i < TVNORMS; i++) | ||
4065 | if (*id == tvnorms[i].id) | ||
4066 | break; | ||
4067 | if (i == TVNORMS) | ||
4068 | for (i = 0; i < TVNORMS; i++) | ||
4069 | if (*id & tvnorms[i].id) | ||
4070 | break; | ||
4071 | if (i == TVNORMS) | ||
4072 | return -EINVAL; | ||
4036 | 4073 | ||
4037 | down(&usbvision->lock); | 4074 | down(&usbvision->lock); |
4038 | usbvision_muxsel(usbvision, usbvision->input.index, *std); | 4075 | usbvision->tvnorm = &tvnorms[i]; |
4039 | usbvision_set_input(usbvision); | 4076 | |
4040 | usbvision_set_output(usbvision, usbvision->curwidth, usbvision->curheight); | 4077 | call_i2c_clients(usbvision, VIDIOC_S_STD, |
4078 | &usbvision->tvnorm->id); | ||
4079 | |||
4041 | up(&usbvision->lock); | 4080 | up(&usbvision->lock); |
4042 | 4081 | ||
4043 | usbvision->input.std = *std; | 4082 | PDEBUG(DBG_IOCTL, "VIDIOC_S_STD std_id=%s", usbvision->tvnorm->name); |
4044 | PDEBUG(DBG_IOCTL, "VIDIOC_S_STD std_id=%x", (unsigned)*std); | ||
4045 | return 0; | 4083 | return 0; |
4046 | } | 4084 | } |
4047 | case VIDIOC_G_TUNER: | 4085 | case VIDIOC_G_TUNER: |
4048 | { | 4086 | { |
4049 | struct v4l2_tuner *vt = arg; | 4087 | struct v4l2_tuner *vt = arg; |
4050 | struct v4l2_tuner status; | ||
4051 | 4088 | ||
4052 | if (!usbvision->have_tuner || vt->index) // Only tuner 0 | 4089 | if (!usbvision->have_tuner || vt->index) // Only tuner 0 |
4053 | return -EINVAL; | 4090 | return -EINVAL; |
4054 | strcpy(vt->name, "Television"); | 4091 | strcpy(vt->name, "Television"); |
4055 | vt->type = V4L2_TUNER_ANALOG_TV; | 4092 | /* Let clients fill in the remainder of this struct */ |
4056 | vt->capability = V4L2_TUNER_CAP_NORM; | 4093 | call_i2c_clients(usbvision,VIDIOC_G_TUNER,vt); |
4057 | vt->rangelow = 0; | 4094 | |
4058 | vt->rangehigh = ~0; | 4095 | PDEBUG(DBG_IOCTL, "VIDIOC_G_TUNER signal=%x, afc=%x",vt->signal,vt->afc); |
4059 | vt->audmode = V4L2_TUNER_MODE_MONO; | ||
4060 | vt->rxsubchans = V4L2_TUNER_SUB_MONO; | ||
4061 | call_i2c_clients(usbvision,VIDIOC_G_TUNER,&status); | ||
4062 | vt->signal = status.signal; | ||
4063 | |||
4064 | PDEBUG(DBG_IOCTL, "VIDIOC_G_TUNER"); | ||
4065 | return 0; | 4096 | return 0; |
4066 | } | 4097 | } |
4067 | case VIDIOC_S_TUNER: | 4098 | case VIDIOC_S_TUNER: |
@@ -4071,15 +4102,16 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
4071 | // Only no or one tuner for now | 4102 | // Only no or one tuner for now |
4072 | if (!usbvision->have_tuner || vt->index) | 4103 | if (!usbvision->have_tuner || vt->index) |
4073 | return -EINVAL; | 4104 | return -EINVAL; |
4074 | // FIXME vt->audmode Radio mode (STEREO/MONO/...) | 4105 | /* let clients handle this */ |
4075 | // vt->reserved Radio freq | 4106 | call_i2c_clients(usbvision,VIDIOC_S_TUNER,vt); |
4076 | // usbvision_muxsel(usbvision, vt->index, vt->mode); | 4107 | |
4077 | PDEBUG(DBG_IOCTL, "VIDIOC_S_TUNER"); | 4108 | PDEBUG(DBG_IOCTL, "VIDIOC_S_TUNER"); |
4078 | return 0; | 4109 | return 0; |
4079 | } | 4110 | } |
4080 | case VIDIOC_G_FREQUENCY: | 4111 | case VIDIOC_G_FREQUENCY: |
4081 | { | 4112 | { |
4082 | struct v4l2_frequency *freq = arg; | 4113 | struct v4l2_frequency *freq = arg; |
4114 | |||
4083 | freq->tuner = 0; // Only one tuner | 4115 | freq->tuner = 0; // Only one tuner |
4084 | freq->type = V4L2_TUNER_ANALOG_TV; | 4116 | freq->type = V4L2_TUNER_ANALOG_TV; |
4085 | freq->frequency = usbvision->freq; | 4117 | freq->frequency = usbvision->freq; |
@@ -4089,6 +4121,11 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
4089 | case VIDIOC_S_FREQUENCY: | 4121 | case VIDIOC_S_FREQUENCY: |
4090 | { | 4122 | { |
4091 | struct v4l2_frequency *freq = arg; | 4123 | struct v4l2_frequency *freq = arg; |
4124 | |||
4125 | // Only no or one tuner for now | ||
4126 | if (!usbvision->have_tuner || freq->tuner) | ||
4127 | return -EINVAL; | ||
4128 | |||
4092 | usbvision->freq = freq->frequency; | 4129 | usbvision->freq = freq->frequency; |
4093 | call_i2c_clients(usbvision, cmd, freq); | 4130 | call_i2c_clients(usbvision, cmd, freq); |
4094 | PDEBUG(DBG_IOCTL, "VIDIOC_S_FREQUENCY freq=0x%X", (unsigned)freq->frequency); | 4131 | PDEBUG(DBG_IOCTL, "VIDIOC_S_FREQUENCY freq=0x%X", (unsigned)freq->frequency); |
@@ -4149,11 +4186,27 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
4149 | case VIDIOC_REQBUFS: | 4186 | case VIDIOC_REQBUFS: |
4150 | { | 4187 | { |
4151 | struct v4l2_requestbuffers *vr = arg; | 4188 | struct v4l2_requestbuffers *vr = arg; |
4152 | // FIXME : normally we allocate the requested number of buffers. | 4189 | int ret; |
4153 | // this driver allocates statically the buffers. | 4190 | |
4154 | vr->count = 2; | 4191 | RESTRICT_TO_RANGE(vr->count,1,USBVISION_NUMFRAMES); |
4155 | if(vr->memory != V4L2_MEMORY_MMAP) | 4192 | |
4193 | // Check input validity : the user must do a VIDEO CAPTURE and MMAP method. | ||
4194 | if((vr->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) || | ||
4195 | (vr->memory != V4L2_MEMORY_MMAP)) | ||
4156 | return -EINVAL; | 4196 | return -EINVAL; |
4197 | |||
4198 | // FIXME : before this, we must control if buffers are still mapped. | ||
4199 | // Then interrupt streaming if so... | ||
4200 | if(usbvision->streaming == Stream_On) { | ||
4201 | if ((ret = usbvision_stream_interrupt(usbvision))) | ||
4202 | return ret; | ||
4203 | } | ||
4204 | |||
4205 | usbvision_empty_framequeues(usbvision); | ||
4206 | |||
4207 | usbvision->curFrame = NULL; | ||
4208 | |||
4209 | PDEBUG(DBG_IOCTL, "VIDIOC_REQBUFS count=%d",vr->count); | ||
4157 | return 0; | 4210 | return 0; |
4158 | } | 4211 | } |
4159 | case VIDIOC_QUERYBUF: | 4212 | case VIDIOC_QUERYBUF: |
@@ -4161,16 +4214,18 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
4161 | struct v4l2_buffer *vb = arg; | 4214 | struct v4l2_buffer *vb = arg; |
4162 | struct usbvision_frame *frame; | 4215 | struct usbvision_frame *frame; |
4163 | 4216 | ||
4164 | // FIXME : works only on VIDEO_CAPTURE MODE, MMAP. | 4217 | // FIXME : must control that buffers are mapped (VIDIOC_REQBUFS has been called) |
4218 | |||
4165 | if(vb->type != V4L2_CAP_VIDEO_CAPTURE) { | 4219 | if(vb->type != V4L2_CAP_VIDEO_CAPTURE) { |
4166 | return -EINVAL; | 4220 | return -EINVAL; |
4167 | } | 4221 | } |
4168 | if(vb->index>1) { | 4222 | if(vb->index>=USBVISION_NUMFRAMES) { |
4169 | return -EINVAL; | 4223 | return -EINVAL; |
4170 | } | 4224 | } |
4225 | // Updating the corresponding frame state | ||
4171 | vb->flags = 0; | 4226 | vb->flags = 0; |
4172 | frame = &usbvision->frame[vb->index]; | 4227 | frame = &usbvision->frame[vb->index]; |
4173 | if(frame->grabstate == FrameState_Grabbing) | 4228 | if(frame->grabstate >= FrameState_Ready) |
4174 | vb->flags |= V4L2_BUF_FLAG_QUEUED; | 4229 | vb->flags |= V4L2_BUF_FLAG_QUEUED; |
4175 | if(frame->grabstate >= FrameState_Done) | 4230 | if(frame->grabstate >= FrameState_Done) |
4176 | vb->flags |= V4L2_BUF_FLAG_DONE; | 4231 | vb->flags |= V4L2_BUF_FLAG_DONE; |
@@ -4183,119 +4238,115 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
4183 | else { | 4238 | else { |
4184 | vb->m.offset = MAX_FRAME_SIZE; | 4239 | vb->m.offset = MAX_FRAME_SIZE; |
4185 | } | 4240 | } |
4241 | vb->memory = V4L2_MEMORY_MMAP; | ||
4242 | vb->field = V4L2_FIELD_NONE; | ||
4186 | vb->length = MAX_FRAME_SIZE; | 4243 | vb->length = MAX_FRAME_SIZE; |
4187 | vb->timestamp = usbvision->frame[vb->index].timestamp; | 4244 | vb->timestamp = usbvision->frame[vb->index].timestamp; |
4188 | vb->sequence = usbvision->frame_num; | 4245 | vb->sequence = usbvision->frame[vb->index].sequence; |
4189 | return 0; | 4246 | return 0; |
4190 | } | 4247 | } |
4191 | case VIDIOC_QBUF: // VIDIOCMCAPTURE + VIDIOCSYNC | 4248 | case VIDIOC_QBUF: |
4192 | { | 4249 | { |
4193 | struct v4l2_buffer *vb = arg; | 4250 | struct v4l2_buffer *vb = arg; |
4194 | struct usbvision_frame *frame; | 4251 | struct usbvision_frame *frame; |
4252 | unsigned long lock_flags; | ||
4195 | 4253 | ||
4196 | // FIXME : works only on VIDEO_CAPTURE MODE, MMAP. | 4254 | // FIXME : works only on VIDEO_CAPTURE MODE, MMAP. |
4197 | if(vb->type != V4L2_CAP_VIDEO_CAPTURE) { | 4255 | if(vb->type != V4L2_CAP_VIDEO_CAPTURE) { |
4198 | return -EINVAL; | 4256 | return -EINVAL; |
4199 | } | 4257 | } |
4200 | if(vb->index>1) { | 4258 | if(vb->index>=USBVISION_NUMFRAMES) { |
4201 | return -EINVAL; | 4259 | return -EINVAL; |
4202 | } | 4260 | } |
4203 | 4261 | ||
4204 | frame = &usbvision->frame[vb->index]; | 4262 | frame = &usbvision->frame[vb->index]; |
4205 | 4263 | ||
4206 | if (frame->grabstate == FrameState_Grabbing) { | 4264 | if (frame->grabstate != FrameState_Unused) { |
4207 | return -EBUSY; | 4265 | return -EAGAIN; |
4208 | } | 4266 | } |
4209 | 4267 | ||
4210 | usbvision_set_output(usbvision, usbvision->curwidth, usbvision->curheight); | 4268 | /* Mark it as ready and enqueue frame */ |
4211 | |||
4212 | /* Mark it as ready */ | ||
4213 | frame->grabstate = FrameState_Ready; | 4269 | frame->grabstate = FrameState_Ready; |
4270 | frame->scanstate = ScanState_Scanning; | ||
4271 | frame->scanlength = 0; /* Accumulated in usbvision_parse_data() */ | ||
4272 | |||
4214 | vb->flags &= ~V4L2_BUF_FLAG_DONE; | 4273 | vb->flags &= ~V4L2_BUF_FLAG_DONE; |
4215 | 4274 | ||
4216 | /* set v4l2_format index */ | 4275 | /* set v4l2_format index */ |
4217 | frame->v4l2_format = usbvision->palette; | 4276 | frame->v4l2_format = usbvision->palette; |
4218 | PDEBUG(DBG_IOCTL, "VIDIOC_QBUF frame=%d",vb->index); | ||
4219 | 4277 | ||
4220 | return usbvision_new_frame(usbvision, vb->index); | 4278 | spin_lock_irqsave(&usbvision->queue_lock, lock_flags); |
4279 | list_add_tail(&usbvision->frame[vb->index].frame, &usbvision->inqueue); | ||
4280 | spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); | ||
4281 | |||
4282 | return 0; | ||
4221 | } | 4283 | } |
4222 | case VIDIOC_DQBUF: | 4284 | case VIDIOC_DQBUF: |
4223 | { | 4285 | { |
4224 | struct v4l2_buffer *vb = arg; | 4286 | struct v4l2_buffer *vb = arg; |
4225 | int errCode = 0; | 4287 | int ret; |
4288 | struct usbvision_frame *f; | ||
4289 | unsigned long lock_flags; | ||
4226 | 4290 | ||
4227 | DECLARE_WAITQUEUE(wait, current); | 4291 | if (vb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
4228 | // FIXME : not the proper way to get the last filled frame | ||
4229 | vb->index=-1; | ||
4230 | if(usbvision->curFrameNum != -1) vb->index=usbvision->curFrameNum; | ||
4231 | else { | ||
4232 | if(usbvision->frame[1].grabstate >= FrameState_Done) | ||
4233 | vb->index = 1; | ||
4234 | else if(usbvision->frame[0].grabstate >= FrameState_Done) | ||
4235 | vb->index = 0; | ||
4236 | // If no FRAME_DONE, look for a FRAME_GRABBING state. | ||
4237 | // See if a frame is in process (grabbing), then use it. | ||
4238 | if (vb->index == -1) { | ||
4239 | if (usbvision->frame[1].grabstate == FrameState_Grabbing) | ||
4240 | vb->index = 1; | ||
4241 | else if (usbvision->frame[0].grabstate == FrameState_Grabbing) | ||
4242 | vb->index = 0; | ||
4243 | } | ||
4244 | } | ||
4245 | if (vb->index == -1) | ||
4246 | return -EINVAL; | 4292 | return -EINVAL; |
4247 | 4293 | ||
4248 | PDEBUG(DBG_IOCTL, "VIDIOC_DQBUF frame=%d, grabstate=%d, curframeNum=%d", | 4294 | if (list_empty(&(usbvision->outqueue))) { |
4249 | vb->index, usbvision->frame[vb->index].grabstate,usbvision->curFrameNum); | 4295 | if (usbvision->streaming == Stream_Off) |
4250 | 4296 | return -EINVAL; | |
4251 | switch (usbvision->frame[vb->index].grabstate) { | 4297 | ret = wait_event_interruptible |
4252 | case FrameState_Unused: | 4298 | (usbvision->wait_frame, |
4253 | errCode = -EINVAL; | 4299 | !list_empty(&(usbvision->outqueue))); |
4254 | break; | 4300 | if (ret) |
4255 | case FrameState_Grabbing: | 4301 | return ret; |
4256 | add_wait_queue(&usbvision->frame[vb->index].wq, &wait); | ||
4257 | current->state = TASK_INTERRUPTIBLE; | ||
4258 | while (usbvision->frame[vb->index].grabstate == FrameState_Grabbing) { | ||
4259 | schedule(); | ||
4260 | if (signal_pending(current)) { | ||
4261 | remove_wait_queue(&usbvision->frame[vb->index].wq, &wait); | ||
4262 | current->state = TASK_RUNNING; | ||
4263 | return -EINTR; | ||
4264 | } | ||
4265 | } | ||
4266 | remove_wait_queue(&usbvision->frame[vb->index].wq, &wait); | ||
4267 | current->state = TASK_RUNNING; | ||
4268 | case FrameState_Ready: | ||
4269 | case FrameState_Error: | ||
4270 | case FrameState_Done: | ||
4271 | errCode = (usbvision->frame[vb->index].grabstate == FrameState_Error) ? -EIO : 0; | ||
4272 | vb->memory = V4L2_MEMORY_MMAP; | ||
4273 | vb->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE; | ||
4274 | vb->field = V4L2_FIELD_NONE; | ||
4275 | vb->sequence = usbvision->frame[vb->index].sequence; | ||
4276 | usbvision->frame[vb->index].grabstate = FrameState_Unused; | ||
4277 | break; | ||
4278 | } | 4302 | } |
4279 | 4303 | ||
4280 | usbvision->frame[vb->index].grabstate = FrameState_Unused; | 4304 | spin_lock_irqsave(&usbvision->queue_lock, lock_flags); |
4281 | return errCode; | 4305 | f = list_entry(usbvision->outqueue.next, |
4306 | struct usbvision_frame, frame); | ||
4307 | list_del(usbvision->outqueue.next); | ||
4308 | spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); | ||
4309 | |||
4310 | f->grabstate = FrameState_Unused; | ||
4311 | |||
4312 | vb->memory = V4L2_MEMORY_MMAP; | ||
4313 | vb->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE; | ||
4314 | vb->index = f->index; | ||
4315 | vb->sequence = f->sequence; | ||
4316 | |||
4317 | return 0; | ||
4282 | } | 4318 | } |
4283 | case VIDIOC_STREAMON: | 4319 | case VIDIOC_STREAMON: |
4284 | { | 4320 | { |
4285 | int b=V4L2_BUF_TYPE_VIDEO_CAPTURE; | 4321 | int b=V4L2_BUF_TYPE_VIDEO_CAPTURE; |
4322 | |||
4323 | if (list_empty(&usbvision->inqueue)) | ||
4324 | return -EINVAL; | ||
4325 | |||
4326 | usbvision->streaming = Stream_On; | ||
4327 | |||
4286 | call_i2c_clients(usbvision,VIDIOC_STREAMON , &b); | 4328 | call_i2c_clients(usbvision,VIDIOC_STREAMON , &b); |
4329 | |||
4330 | PDEBUG(DBG_IOCTL, "VIDIOC_STREAMON"); | ||
4331 | |||
4287 | return 0; | 4332 | return 0; |
4288 | } | 4333 | } |
4289 | case VIDIOC_STREAMOFF: | 4334 | case VIDIOC_STREAMOFF: |
4290 | { | 4335 | { |
4336 | int *type = arg; | ||
4291 | int b=V4L2_BUF_TYPE_VIDEO_CAPTURE; | 4337 | int b=V4L2_BUF_TYPE_VIDEO_CAPTURE; |
4292 | down(&usbvision->lock); | 4338 | |
4293 | // Stop all video streamings | 4339 | if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
4294 | call_i2c_clients(usbvision,VIDIOC_STREAMOFF , &b); | 4340 | return -EINVAL; |
4295 | usbvision->frame_num = -1; | 4341 | |
4296 | usbvision->frame[0].grabstate = FrameState_Unused; | 4342 | if(usbvision->streaming == Stream_On) { |
4297 | usbvision->frame[1].grabstate = FrameState_Unused; | 4343 | usbvision_stream_interrupt(usbvision); |
4298 | up(&usbvision->lock); | 4344 | // Stop all video streamings |
4345 | call_i2c_clients(usbvision,VIDIOC_STREAMOFF , &b); | ||
4346 | } | ||
4347 | usbvision_empty_framequeues(usbvision); | ||
4348 | |||
4349 | PDEBUG(DBG_IOCTL, "VIDIOC_STREAMOFF"); | ||
4299 | return 0; | 4350 | return 0; |
4300 | } | 4351 | } |
4301 | case VIDIOC_G_FBUF: | 4352 | case VIDIOC_G_FBUF: |
@@ -4361,6 +4412,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
4361 | case VIDIOC_ENUM_FMT: | 4412 | case VIDIOC_ENUM_FMT: |
4362 | { | 4413 | { |
4363 | struct v4l2_fmtdesc *vfd = arg; | 4414 | struct v4l2_fmtdesc *vfd = arg; |
4415 | |||
4364 | if ( (dga == 0) && | 4416 | if ( (dga == 0) && |
4365 | (vfd->type == V4L2_BUF_TYPE_VIDEO_OVERLAY) && | 4417 | (vfd->type == V4L2_BUF_TYPE_VIDEO_OVERLAY) && |
4366 | (usbvision->palette.format != V4L2_PIX_FMT_YVU420) && | 4418 | (usbvision->palette.format != V4L2_PIX_FMT_YVU420) && |
@@ -4539,7 +4591,7 @@ static ssize_t usbvision_v4l2_read(struct file *file, char *buf, | |||
4539 | int frmx = -1; | 4591 | int frmx = -1; |
4540 | int rc = 0; | 4592 | int rc = 0; |
4541 | struct usbvision_frame *frame; | 4593 | struct usbvision_frame *frame; |
4542 | 4594 | return -EINVAL; | |
4543 | PDEBUG(DBG_IO, "%s: %ld bytes, noblock=%d", __FUNCTION__, (unsigned long)count, noblock); | 4595 | PDEBUG(DBG_IO, "%s: %ld bytes, noblock=%d", __FUNCTION__, (unsigned long)count, noblock); |
4544 | 4596 | ||
4545 | if (!USBVISION_IS_OPERATIONAL(usbvision) || (buf == NULL)) | 4597 | if (!USBVISION_IS_OPERATIONAL(usbvision) || (buf == NULL)) |
@@ -4574,7 +4626,8 @@ static ssize_t usbvision_v4l2_read(struct file *file, char *buf, | |||
4574 | 4626 | ||
4575 | // If no frame is active, start one. | 4627 | // If no frame is active, start one. |
4576 | if (frmx == -1) | 4628 | if (frmx == -1) |
4577 | usbvision_new_frame(usbvision, frmx = 0); | 4629 | // FIXME: enqueue all inqueue... |
4630 | /* usbvision_new_frame(usbvision, frmx = 0); */ | ||
4578 | 4631 | ||
4579 | frame = &usbvision->frame[frmx]; | 4632 | frame = &usbvision->frame[frmx]; |
4580 | 4633 | ||
@@ -4584,7 +4637,7 @@ static ssize_t usbvision_v4l2_read(struct file *file, char *buf, | |||
4584 | goto usbvision_v4l2_read_done; | 4637 | goto usbvision_v4l2_read_done; |
4585 | } | 4638 | } |
4586 | PDEBUG(DBG_IO, "Waiting frame grabbing"); | 4639 | PDEBUG(DBG_IO, "Waiting frame grabbing"); |
4587 | rc = wait_event_interruptible(frame->wq, (frame->grabstate == FrameState_Done) || | 4640 | rc = wait_event_interruptible(usbvision->wait_frame, (frame->grabstate == FrameState_Done) || |
4588 | (frame->grabstate == FrameState_Error)); | 4641 | (frame->grabstate == FrameState_Error)); |
4589 | if (rc) { | 4642 | if (rc) { |
4590 | goto usbvision_v4l2_read_done; | 4643 | goto usbvision_v4l2_read_done; |
@@ -4592,9 +4645,10 @@ static ssize_t usbvision_v4l2_read(struct file *file, char *buf, | |||
4592 | 4645 | ||
4593 | if (frame->grabstate == FrameState_Error) { | 4646 | if (frame->grabstate == FrameState_Error) { |
4594 | frame->bytes_read = 0; | 4647 | frame->bytes_read = 0; |
4595 | if (usbvision_new_frame(usbvision, frmx)) { | 4648 | // FIXME: enqueue all inqueue... |
4596 | err("%s: usbvision_new_frame() failed", __FUNCTION__); | 4649 | /* if (usbvision_new_frame(usbvision, frmx)) { */ |
4597 | } | 4650 | /* err("%s: usbvision_new_frame() failed", __FUNCTION__); */ |
4651 | /* } */ | ||
4598 | goto restart; | 4652 | goto restart; |
4599 | } | 4653 | } |
4600 | 4654 | ||
@@ -4619,8 +4673,9 @@ static ssize_t usbvision_v4l2_read(struct file *file, char *buf, | |||
4619 | 4673 | ||
4620 | /* Mark it as available to be used again. */ | 4674 | /* Mark it as available to be used again. */ |
4621 | usbvision->frame[frmx].grabstate = FrameState_Unused; | 4675 | usbvision->frame[frmx].grabstate = FrameState_Unused; |
4622 | if (usbvision_new_frame(usbvision, frmx ? 0 : 1)) | 4676 | // FIXME enqueue another frame |
4623 | err("%s: usbvision_new_frame() failed", __FUNCTION__); | 4677 | /* if (usbvision_new_frame(usbvision, frmx ? 0 : 1)) */ |
4678 | /* err("%s: usbvision_new_frame() failed", __FUNCTION__); */ | ||
4624 | } | 4679 | } |
4625 | 4680 | ||
4626 | usbvision_v4l2_read_done: | 4681 | usbvision_v4l2_read_done: |
@@ -5198,7 +5253,7 @@ static int usbvision_vbi_ioctl(struct inode *inode, struct file *file, | |||
5198 | 5253 | ||
5199 | static void usbvision_configure_video(struct usb_usbvision *usbvision) | 5254 | static void usbvision_configure_video(struct usb_usbvision *usbvision) |
5200 | { | 5255 | { |
5201 | int model; | 5256 | int model,i; |
5202 | 5257 | ||
5203 | if (usbvision == NULL) | 5258 | if (usbvision == NULL) |
5204 | return; | 5259 | return; |
@@ -5215,17 +5270,26 @@ static void usbvision_configure_video(struct usb_usbvision *usbvision) | |||
5215 | 5270 | ||
5216 | memset(&usbvision->vcap, 0, sizeof(usbvision->vcap)); | 5271 | memset(&usbvision->vcap, 0, sizeof(usbvision->vcap)); |
5217 | strcpy(usbvision->vcap.driver, "USBVision"); | 5272 | strcpy(usbvision->vcap.driver, "USBVision"); |
5218 | usbvision->vcap.capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | | 5273 | strlcpy(usbvision->vcap.bus_info, usbvision->dev->dev.bus_id, |
5274 | sizeof(usbvision->vcap.bus_info)); | ||
5275 | usbvision->vcap.capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | | ||
5219 | (dga ? (V4L2_FBUF_CAP_LIST_CLIPPING | V4L2_CAP_VIDEO_OVERLAY) : 0) | | 5276 | (dga ? (V4L2_FBUF_CAP_LIST_CLIPPING | V4L2_CAP_VIDEO_OVERLAY) : 0) | |
5220 | (usbvision->have_tuner ? V4L2_CAP_TUNER : 0); | 5277 | (usbvision->have_tuner ? V4L2_CAP_TUNER : 0); |
5221 | usbvision->vcap.version = USBVISION_DRIVER_VERSION; /* version */ | 5278 | usbvision->vcap.version = USBVISION_DRIVER_VERSION; /* version */ |
5222 | 5279 | ||
5223 | usbvision->video_inputs = usbvision_device_data[model].VideoChannels; | ||
5224 | 5280 | ||
5225 | memset(&usbvision->input, 0, sizeof(usbvision->input)); | 5281 | for (i = 0; i < TVNORMS; i++) |
5226 | usbvision->input.tuner = 0; | 5282 | if (usbvision_device_data[model].VideoNorm == tvnorms[i].mode) |
5227 | usbvision->input.type = V4L2_INPUT_TYPE_TUNER|VIDEO_TYPE_CAMERA; | 5283 | break; |
5228 | usbvision->input.std = usbvision_device_data[model].VideoNorm; | 5284 | if (i == TVNORMS) |
5285 | i = 0; | ||
5286 | usbvision->tvnorm = &tvnorms[i]; /* set default norm */ | ||
5287 | call_i2c_clients(usbvision, VIDIOC_S_STD, | ||
5288 | &usbvision->tvnorm->id); | ||
5289 | |||
5290 | usbvision->video_inputs = usbvision_device_data[model].VideoChannels; | ||
5291 | usbvision->ctl_input = 0; | ||
5292 | /* usbvision_muxsel(usbvision, usbvision->ctl_input); */ | ||
5229 | 5293 | ||
5230 | /* This should be here to make i2c clients to be able to register */ | 5294 | /* This should be here to make i2c clients to be able to register */ |
5231 | usbvision_audio_off(usbvision); //first switch off audio | 5295 | usbvision_audio_off(usbvision); //first switch off audio |
@@ -5440,7 +5504,6 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision) | |||
5440 | static struct usb_usbvision *usbvision_alloc(struct usb_device *dev) | 5504 | static struct usb_usbvision *usbvision_alloc(struct usb_device *dev) |
5441 | { | 5505 | { |
5442 | struct usb_usbvision *usbvision; | 5506 | struct usb_usbvision *usbvision; |
5443 | int FrameIdx; | ||
5444 | 5507 | ||
5445 | if ((usbvision = kzalloc(sizeof(struct usb_usbvision), GFP_KERNEL)) == NULL) { | 5508 | if ((usbvision = kzalloc(sizeof(struct usb_usbvision), GFP_KERNEL)) == NULL) { |
5446 | goto err_exit; | 5509 | goto err_exit; |
@@ -5448,10 +5511,6 @@ static struct usb_usbvision *usbvision_alloc(struct usb_device *dev) | |||
5448 | 5511 | ||
5449 | usbvision->dev = dev; | 5512 | usbvision->dev = dev; |
5450 | 5513 | ||
5451 | for (FrameIdx = 0; FrameIdx < USBVISION_NUMFRAMES; FrameIdx++) { | ||
5452 | init_waitqueue_head(&usbvision->frame[FrameIdx].wq); | ||
5453 | } | ||
5454 | init_waitqueue_head(&usbvision->overlay_frame.wq); | ||
5455 | init_MUTEX(&usbvision->lock); /* to 1 == available */ | 5514 | init_MUTEX(&usbvision->lock); /* to 1 == available */ |
5456 | 5515 | ||
5457 | // prepare control urb for control messages during interrupts | 5516 | // prepare control urb for control messages during interrupts |
@@ -5460,7 +5519,7 @@ static struct usb_usbvision *usbvision_alloc(struct usb_device *dev) | |||
5460 | goto err_exit; | 5519 | goto err_exit; |
5461 | } | 5520 | } |
5462 | init_waitqueue_head(&usbvision->ctrlUrb_wq); | 5521 | init_waitqueue_head(&usbvision->ctrlUrb_wq); |
5463 | init_MUTEX(&usbvision->ctrlUrbLock); | 5522 | init_MUTEX(&usbvision->ctrlUrbLock); /* to 1 == available */ |
5464 | 5523 | ||
5465 | init_timer(&usbvision->powerOffTimer); | 5524 | init_timer(&usbvision->powerOffTimer); |
5466 | usbvision->powerOffTimer.data = (long) usbvision; | 5525 | usbvision->powerOffTimer.data = (long) usbvision; |
@@ -5536,7 +5595,6 @@ static int __devinit usbvision_probe(struct usb_interface *intf, const struct us | |||
5536 | 5595 | ||
5537 | PDEBUG(DBG_PROBE, "VID=%#04x, PID=%#04x, ifnum=%u", | 5596 | PDEBUG(DBG_PROBE, "VID=%#04x, PID=%#04x, ifnum=%u", |
5538 | dev->descriptor.idVendor, dev->descriptor.idProduct, ifnum); | 5597 | dev->descriptor.idVendor, dev->descriptor.idProduct, ifnum); |
5539 | |||
5540 | /* Is it an USBVISION video dev? */ | 5598 | /* Is it an USBVISION video dev? */ |
5541 | model = 0; | 5599 | model = 0; |
5542 | for(model = 0; usbvision_device_data[model].idVendor; model++) { | 5600 | for(model = 0; usbvision_device_data[model].idVendor; model++) { |
@@ -5655,6 +5713,9 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf) | |||
5655 | usb_put_dev(usbvision->dev); | 5713 | usb_put_dev(usbvision->dev); |
5656 | usbvision->dev = NULL; // USB device is no more | 5714 | usbvision->dev = NULL; // USB device is no more |
5657 | 5715 | ||
5716 | wake_up_interruptible(&usbvision->wait_frame); | ||
5717 | wake_up_interruptible(&usbvision->wait_stream); | ||
5718 | |||
5658 | up(&usbvision->lock); | 5719 | up(&usbvision->lock); |
5659 | 5720 | ||
5660 | if (usbvision->user) { | 5721 | if (usbvision->user) { |
diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c index 466e11f4584e..48afcd2aca3f 100644 --- a/drivers/media/video/usbvision/usbvision-i2c.c +++ b/drivers/media/video/usbvision/usbvision-i2c.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * I2C_ALGO_USB.C | 2 | * I2C_ALGO_USB.C |
3 | * i2c algorithm for USB-I2C Bridges | 3 | * i2c algorithm for USB-I2C Bridges |
4 | * | 4 | * |
@@ -39,7 +39,7 @@ | |||
39 | #include <linux/i2c.h> | 39 | #include <linux/i2c.h> |
40 | #include "usbvision-i2c.h" | 40 | #include "usbvision-i2c.h" |
41 | 41 | ||
42 | static int debug_i2c_usb = 0; | 42 | static int debug_i2c_usb = 0; |
43 | 43 | ||
44 | #if defined(module_param) // Showing parameters under SYSFS | 44 | #if defined(module_param) // Showing parameters under SYSFS |
45 | module_param (debug_i2c_usb, int, 0444); // debug_i2c_usb mode of the device driver | 45 | module_param (debug_i2c_usb, int, 0444); // debug_i2c_usb mode of the device driver |
@@ -108,7 +108,7 @@ static inline int usb_find_address(struct i2c_adapter *i2c_adap, | |||
108 | unsigned char *add) | 108 | unsigned char *add) |
109 | { | 109 | { |
110 | unsigned short flags = msg->flags; | 110 | unsigned short flags = msg->flags; |
111 | 111 | ||
112 | unsigned char addr; | 112 | unsigned char addr; |
113 | int ret; | 113 | int ret; |
114 | if ((flags & I2C_M_TEN)) { | 114 | if ((flags & I2C_M_TEN)) { |
@@ -205,8 +205,6 @@ static u32 usb_func(struct i2c_adapter *adap) | |||
205 | static struct i2c_algorithm i2c_usb_algo = { | 205 | static struct i2c_algorithm i2c_usb_algo = { |
206 | .master_xfer = usb_xfer, | 206 | .master_xfer = usb_xfer, |
207 | .smbus_xfer = NULL, | 207 | .smbus_xfer = NULL, |
208 | .slave_send = NULL, | ||
209 | .slave_recv = NULL, | ||
210 | .algo_control = algo_control, | 208 | .algo_control = algo_control, |
211 | .functionality = usb_func, | 209 | .functionality = usb_func, |
212 | }; | 210 | }; |
diff --git a/drivers/media/video/usbvision/usbvision.h b/drivers/media/video/usbvision/usbvision.h index 813b258f89c7..870c0cc81d84 100644 --- a/drivers/media/video/usbvision/usbvision.h +++ b/drivers/media/video/usbvision/usbvision.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * USBVISION.H | 2 | * USBVISION.H |
3 | * usbvision header file | 3 | * usbvision header file |
4 | * | 4 | * |
@@ -38,7 +38,7 @@ | |||
38 | #define USBVISION_SSPND_EN (1 << 1) | 38 | #define USBVISION_SSPND_EN (1 << 1) |
39 | #define USBVISION_RES2 (1 << 2) | 39 | #define USBVISION_RES2 (1 << 2) |
40 | #define USBVISION_PWR_VID (1 << 5) | 40 | #define USBVISION_PWR_VID (1 << 5) |
41 | #define USBVISION_E2_EN (1 << 7) | 41 | #define USBVISION_E2_EN (1 << 7) |
42 | #define USBVISION_CONFIG_REG 0x01 | 42 | #define USBVISION_CONFIG_REG 0x01 |
43 | #define USBVISION_ADRS_REG 0x02 | 43 | #define USBVISION_ADRS_REG 0x02 |
44 | #define USBVISION_ALTER_REG 0x03 | 44 | #define USBVISION_ALTER_REG 0x03 |
@@ -139,7 +139,7 @@ | |||
139 | #define USBVISION_MAX_ISOC_PACKET_SIZE 959 // NT1003 Specs Document says 1023 | 139 | #define USBVISION_MAX_ISOC_PACKET_SIZE 959 // NT1003 Specs Document says 1023 |
140 | 140 | ||
141 | #define USBVISION_NUM_HEADERMARKER 20 | 141 | #define USBVISION_NUM_HEADERMARKER 20 |
142 | #define USBVISION_NUMFRAMES 2 | 142 | #define USBVISION_NUMFRAMES 3 |
143 | #define USBVISION_NUMSBUF 2 | 143 | #define USBVISION_NUMSBUF 2 |
144 | 144 | ||
145 | #define USBVISION_POWEROFF_TIME 3 * (HZ) // 3 seconds | 145 | #define USBVISION_POWEROFF_TIME 3 * (HZ) // 3 seconds |
@@ -225,6 +225,13 @@ enum FrameState { | |||
225 | FrameState_Error, /* Something bad happened while processing */ | 225 | FrameState_Error, /* Something bad happened while processing */ |
226 | }; | 226 | }; |
227 | 227 | ||
228 | /* stream states */ | ||
229 | enum StreamState { | ||
230 | Stream_Off, | ||
231 | Stream_Interrupt, | ||
232 | Stream_On, | ||
233 | }; | ||
234 | |||
228 | enum IsocState { | 235 | enum IsocState { |
229 | IsocState_InFrame, /* Isoc packet is member of frame */ | 236 | IsocState_InFrame, /* Isoc packet is member of frame */ |
230 | IsocState_NoFrame, /* Isoc packet is not member of any frame */ | 237 | IsocState_NoFrame, /* Isoc packet is not member of any frame */ |
@@ -272,27 +279,36 @@ struct usbvision_frame_header { | |||
272 | __u16 frameHeight; /* 10 - 11 after endian correction*/ | 279 | __u16 frameHeight; /* 10 - 11 after endian correction*/ |
273 | }; | 280 | }; |
274 | 281 | ||
282 | /* tvnorms */ | ||
283 | struct usbvision_tvnorm { | ||
284 | char *name; | ||
285 | v4l2_std_id id; | ||
286 | /* mode for saa7113h */ | ||
287 | int mode; | ||
288 | }; | ||
289 | |||
275 | struct usbvision_frame { | 290 | struct usbvision_frame { |
276 | char *data; /* Frame buffer */ | 291 | char *data; /* Frame buffer */ |
277 | struct usbvision_frame_header isocHeader; /* Header from stream */ | 292 | struct usbvision_frame_header isocHeader; /* Header from stream */ |
278 | 293 | ||
279 | int width; /* Width application is expecting */ | 294 | int width; /* Width application is expecting */ |
280 | int height; /* Height */ | 295 | int height; /* Height */ |
281 | 296 | int index; /* Frame index */ | |
282 | int frmwidth; /* Width the frame actually is */ | 297 | int frmwidth; /* Width the frame actually is */ |
283 | int frmheight; /* Height */ | 298 | int frmheight; /* Height */ |
284 | 299 | ||
285 | volatile int grabstate; /* State of grabbing */ | 300 | volatile int grabstate; /* State of grabbing */ |
286 | int scanstate; /* State of scanning */ | 301 | int scanstate; /* State of scanning */ |
287 | 302 | ||
303 | struct list_head frame; | ||
304 | |||
288 | int curline; /* Line of frame we're working on */ | 305 | int curline; /* Line of frame we're working on */ |
289 | 306 | ||
290 | long scanlength; /* uncompressed, raw data length of frame */ | 307 | long scanlength; /* uncompressed, raw data length of frame */ |
291 | long bytes_read; /* amount of scanlength that has been read from data */ | 308 | long bytes_read; /* amount of scanlength that has been read from data */ |
292 | struct usbvision_v4l2_format_st v4l2_format; /* format the user needs*/ | 309 | struct usbvision_v4l2_format_st v4l2_format; /* format the user needs*/ |
293 | int v4l2_linesize; /* bytes for one videoline*/ | 310 | int v4l2_linesize; /* bytes for one videoline*/ |
294 | struct timeval timestamp; | 311 | struct timeval timestamp; |
295 | wait_queue_head_t wq; /* Processes waiting */ | ||
296 | int sequence; // How many video frames we send to user | 312 | int sequence; // How many video frames we send to user |
297 | }; | 313 | }; |
298 | 314 | ||
@@ -305,23 +321,23 @@ struct usbvision_frame { | |||
305 | #define USBVISION_I2C_CLIENTS_MAX 8 | 321 | #define USBVISION_I2C_CLIENTS_MAX 8 |
306 | 322 | ||
307 | struct usbvision_device_data_st { | 323 | struct usbvision_device_data_st { |
308 | int idVendor; | 324 | int idVendor; |
309 | int idProduct; | 325 | int idProduct; |
310 | int Interface; /* to handle special interface number like BELKIN and Hauppauge WinTV-USB II */ | 326 | int Interface; /* to handle special interface number like BELKIN and Hauppauge WinTV-USB II */ |
311 | int Codec; | 327 | int Codec; |
312 | int VideoChannels; | 328 | int VideoChannels; |
313 | __u64 VideoNorm; | 329 | __u64 VideoNorm; |
314 | int AudioChannels; | 330 | int AudioChannels; |
315 | int Radio; | 331 | int Radio; |
316 | int vbi; | 332 | int vbi; |
317 | int Tuner; | 333 | int Tuner; |
318 | int TunerType; | 334 | int TunerType; |
319 | int Vin_Reg1; | 335 | int Vin_Reg1; |
320 | int Vin_Reg2; | 336 | int Vin_Reg2; |
321 | int X_Offset; | 337 | int X_Offset; |
322 | int Y_Offset; | 338 | int Y_Offset; |
323 | int Dvi_yuv; | 339 | int Dvi_yuv; |
324 | char *ModelString; | 340 | char *ModelString; |
325 | }; | 341 | }; |
326 | 342 | ||
327 | /* Declared on usbvision-cards.c */ | 343 | /* Declared on usbvision-cards.c */ |
@@ -332,7 +348,7 @@ struct usb_usbvision { | |||
332 | struct video_device *vdev; /* Video Device */ | 348 | struct video_device *vdev; /* Video Device */ |
333 | struct video_device *rdev; /* Radio Device */ | 349 | struct video_device *rdev; /* Radio Device */ |
334 | struct video_device *vbi; /* VBI Device */ | 350 | struct video_device *vbi; /* VBI Device */ |
335 | struct video_audio audio_dev; /* Current audio params */ | 351 | struct video_audio audio_dev; /* Current audio params */ |
336 | 352 | ||
337 | /* i2c Declaration Section*/ | 353 | /* i2c Declaration Section*/ |
338 | struct i2c_adapter i2c_adap; | 354 | struct i2c_adapter i2c_adap; |
@@ -373,7 +389,7 @@ struct usb_usbvision { | |||
373 | int usbvision_used; /* Is this structure in use? */ | 389 | int usbvision_used; /* Is this structure in use? */ |
374 | int initialized; /* Had we already sent init sequence? */ | 390 | int initialized; /* Had we already sent init sequence? */ |
375 | int DevModel; /* What type of USBVISION device we got? */ | 391 | int DevModel; /* What type of USBVISION device we got? */ |
376 | int streaming; /* Are we streaming Isochronous? */ | 392 | enum StreamState streaming; /* Are we streaming Isochronous? */ |
377 | int last_error; /* What calamity struck us? */ | 393 | int last_error; /* What calamity struck us? */ |
378 | int curwidth; /* width of the frame the device is currently set to*/ | 394 | int curwidth; /* width of the frame the device is currently set to*/ |
379 | int curheight; /* height of the frame the device is currently set to*/ | 395 | int curheight; /* height of the frame the device is currently set to*/ |
@@ -382,7 +398,10 @@ struct usb_usbvision { | |||
382 | char *fbuf; /* Videodev buffer area for mmap*/ | 398 | char *fbuf; /* Videodev buffer area for mmap*/ |
383 | int max_frame_size; /* Bytes in one video frame */ | 399 | int max_frame_size; /* Bytes in one video frame */ |
384 | int fbuf_size; /* Videodev buffer size */ | 400 | int fbuf_size; /* Videodev buffer size */ |
385 | int curFrameNum; // number of current frame in frame buffer mode | 401 | spinlock_t queue_lock; /* spinlock for protecting mods on inqueue and outqueue */ |
402 | struct list_head inqueue, outqueue; /* queued frame list and ready to dequeue frame list */ | ||
403 | wait_queue_head_t wait_frame; /* Processes waiting */ | ||
404 | wait_queue_head_t wait_stream; /* Processes waiting */ | ||
386 | struct usbvision_frame *curFrame; // pointer to current frame, set by usbvision_find_header | 405 | struct usbvision_frame *curFrame; // pointer to current frame, set by usbvision_find_header |
387 | struct usbvision_frame frame[USBVISION_NUMFRAMES]; // frame buffer | 406 | struct usbvision_frame frame[USBVISION_NUMFRAMES]; // frame buffer |
388 | int curSbufNum; // number of current receiving sbuf | 407 | int curSbufNum; // number of current receiving sbuf |
@@ -397,20 +416,21 @@ struct usb_usbvision { | |||
397 | int scratch_headermarker_read_ptr; | 416 | int scratch_headermarker_read_ptr; |
398 | int scratch_headermarker_write_ptr; | 417 | int scratch_headermarker_write_ptr; |
399 | int isocstate; | 418 | int isocstate; |
400 | /* color controls */ | 419 | /* color controls */ |
401 | int saturation; | 420 | int saturation; |
402 | int hue; | 421 | int hue; |
403 | int brightness; | 422 | int brightness; |
404 | int contrast; | 423 | int contrast; |
405 | int depth; | 424 | int depth; |
406 | struct usbvision_v4l2_format_st palette; | 425 | struct usbvision_v4l2_format_st palette; |
407 | 426 | ||
408 | struct v4l2_capability vcap; /* Video capabilities */ | 427 | struct v4l2_capability vcap; /* Video capabilities */ |
409 | struct v4l2_input input; /* May be used for tuner support */ | 428 | unsigned int ctl_input; /* selected input */ |
429 | struct usbvision_tvnorm *tvnorm; /* selected tv norm */ | ||
410 | unsigned char video_endp; /* 0x82 for USBVISION devices based */ | 430 | unsigned char video_endp; /* 0x82 for USBVISION devices based */ |
411 | 431 | ||
412 | // Overlay stuff: | 432 | // Overlay stuff: |
413 | struct v4l2_framebuffer vid_buf; | 433 | struct v4l2_framebuffer vid_buf; |
414 | struct v4l2_format vid_win; | 434 | struct v4l2_format vid_win; |
415 | int vid_buf_valid; // Status: video buffer is valid (set) | 435 | int vid_buf_valid; // Status: video buffer is valid (set) |
416 | int vid_win_valid; // Status: video window is valid (set) | 436 | int vid_win_valid; // Status: video window is valid (set) |
@@ -435,8 +455,8 @@ struct usb_usbvision { | |||
435 | struct proc_dir_entry *proc_devdir; /* Per-device proc directory */ | 455 | struct proc_dir_entry *proc_devdir; /* Per-device proc directory */ |
436 | struct proc_dir_entry *proc_info; /* <minor#>/info entry */ | 456 | struct proc_dir_entry *proc_info; /* <minor#>/info entry */ |
437 | struct proc_dir_entry *proc_register; /* <minor#>/register entry */ | 457 | struct proc_dir_entry *proc_register; /* <minor#>/register entry */ |
438 | struct proc_dir_entry *proc_freq; /* <minor#>/freq entry */ | 458 | struct proc_dir_entry *proc_freq; /* <minor#>/freq entry */ |
439 | struct proc_dir_entry *proc_input; /* <minor#>/input entry */ | 459 | struct proc_dir_entry *proc_input; /* <minor#>/input entry */ |
440 | struct proc_dir_entry *proc_frame; /* <minor#>/frame entry */ | 460 | struct proc_dir_entry *proc_frame; /* <minor#>/frame entry */ |
441 | struct proc_dir_entry *proc_button; /* <minor#>/button entry */ | 461 | struct proc_dir_entry *proc_button; /* <minor#>/button entry */ |
442 | struct proc_dir_entry *proc_control; /* <minor#>/control entry */ | 462 | struct proc_dir_entry *proc_control; /* <minor#>/control entry */ |
@@ -463,3 +483,10 @@ struct usb_usbvision { | |||
463 | 483 | ||
464 | #endif /* __LINUX_USBVISION_H */ | 484 | #endif /* __LINUX_USBVISION_H */ |
465 | 485 | ||
486 | /* | ||
487 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
488 | * --------------------------------------------------------------------------- | ||
489 | * Local variables: | ||
490 | * c-basic-offset: 8 | ||
491 | * End: | ||
492 | */ | ||