blob: cf8fc627471313d00878f76dee51dc82beb28fe9 [file] [log] [blame]
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001/*
2 * Auvitek AU0828 USB Bridge (Analog video support)
3 *
4 * Copyright (C) 2009 Devin Heitmueller <dheitmueller@linuxtv.org>
5 * Copyright (C) 2005-2008 Auvitek International, Ltd.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * As published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301, USA.
21 */
22
23/* Developer Notes:
24 *
25 * VBI support is not yet working
26 * The hardware scaler supported is unimplemented
27 * AC97 audio support is unimplemented (only i2s audio mode)
28 *
29 */
30
31#include <linux/module.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090032#include <linux/slab.h>
Devin Heitmueller8b2f0792009-03-11 03:00:40 -030033#include <linux/init.h>
34#include <linux/device.h>
35#include <linux/suspend.h>
36#include <linux/version.h>
Devin Heitmueller8b2f0792009-03-11 03:00:40 -030037#include <media/v4l2-common.h>
38#include <media/v4l2-ioctl.h>
39#include <media/v4l2-chip-ident.h>
40#include <media/tuner.h>
41#include "au0828.h"
42#include "au0828-reg.h"
43
Devin Heitmueller8b2f0792009-03-11 03:00:40 -030044static DEFINE_MUTEX(au0828_sysfs_lock);
45
46#define AU0828_VERSION_CODE KERNEL_VERSION(0, 0, 1)
47
Devin Heitmueller8b2f0792009-03-11 03:00:40 -030048/* ------------------------------------------------------------------
49 Videobuf operations
50 ------------------------------------------------------------------*/
51
52static unsigned int isoc_debug;
53module_param(isoc_debug, int, 0644);
54MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]");
55
56#define au0828_isocdbg(fmt, arg...) \
57do {\
58 if (isoc_debug) { \
59 printk(KERN_INFO "au0828 %s :"fmt, \
60 __func__ , ##arg); \
61 } \
62 } while (0)
63
64static inline void print_err_status(struct au0828_dev *dev,
65 int packet, int status)
66{
67 char *errmsg = "Unknown";
68
69 switch (status) {
70 case -ENOENT:
71 errmsg = "unlinked synchronuously";
72 break;
73 case -ECONNRESET:
74 errmsg = "unlinked asynchronuously";
75 break;
76 case -ENOSR:
77 errmsg = "Buffer error (overrun)";
78 break;
79 case -EPIPE:
80 errmsg = "Stalled (device not responding)";
81 break;
82 case -EOVERFLOW:
83 errmsg = "Babble (bad cable?)";
84 break;
85 case -EPROTO:
86 errmsg = "Bit-stuff error (bad cable?)";
87 break;
88 case -EILSEQ:
89 errmsg = "CRC/Timeout (could be anything)";
90 break;
91 case -ETIME:
92 errmsg = "Device does not respond";
93 break;
94 }
95 if (packet < 0) {
96 au0828_isocdbg("URB status %d [%s].\n", status, errmsg);
97 } else {
98 au0828_isocdbg("URB packet %d, status %d [%s].\n",
99 packet, status, errmsg);
100 }
101}
102
103static int check_dev(struct au0828_dev *dev)
104{
105 if (dev->dev_state & DEV_DISCONNECTED) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300106 printk(KERN_INFO "v4l2 ioctl: device not present\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300107 return -ENODEV;
108 }
109
110 if (dev->dev_state & DEV_MISCONFIGURED) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300111 printk(KERN_INFO "v4l2 ioctl: device is misconfigured; "
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300112 "close and open it again\n");
113 return -EIO;
114 }
115 return 0;
116}
117
118/*
119 * IRQ callback, called by URB callback
120 */
121static void au0828_irq_callback(struct urb *urb)
122{
123 struct au0828_dmaqueue *dma_q = urb->context;
124 struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq);
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300125 unsigned long flags = 0;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300126 int rc, i;
127
128 switch (urb->status) {
129 case 0: /* success */
130 case -ETIMEDOUT: /* NAK */
131 break;
132 case -ECONNRESET: /* kill */
133 case -ENOENT:
134 case -ESHUTDOWN:
135 au0828_isocdbg("au0828_irq_callback called: status kill\n");
136 return;
137 default: /* unknown error */
138 au0828_isocdbg("urb completition error %d.\n", urb->status);
139 break;
140 }
141
142 /* Copy data from URB */
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300143 spin_lock_irqsave(&dev->slock, flags);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300144 rc = dev->isoc_ctl.isoc_copy(dev, urb);
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300145 spin_unlock_irqrestore(&dev->slock, flags);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300146
147 /* Reset urb buffers */
148 for (i = 0; i < urb->number_of_packets; i++) {
149 urb->iso_frame_desc[i].status = 0;
150 urb->iso_frame_desc[i].actual_length = 0;
151 }
152 urb->status = 0;
153
154 urb->status = usb_submit_urb(urb, GFP_ATOMIC);
155 if (urb->status) {
156 au0828_isocdbg("urb resubmit failed (error=%i)\n",
157 urb->status);
158 }
159}
160
161/*
162 * Stop and Deallocate URBs
163 */
164void au0828_uninit_isoc(struct au0828_dev *dev)
165{
166 struct urb *urb;
167 int i;
168
169 au0828_isocdbg("au0828: called au0828_uninit_isoc\n");
170
171 dev->isoc_ctl.nfields = -1;
172 for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
173 urb = dev->isoc_ctl.urb[i];
174 if (urb) {
175 if (!irqs_disabled())
176 usb_kill_urb(urb);
177 else
178 usb_unlink_urb(urb);
179
180 if (dev->isoc_ctl.transfer_buffer[i]) {
Daniel Mack997ea582010-04-12 13:17:25 +0200181 usb_free_coherent(dev->usbdev,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300182 urb->transfer_buffer_length,
183 dev->isoc_ctl.transfer_buffer[i],
184 urb->transfer_dma);
185 }
186 usb_free_urb(urb);
187 dev->isoc_ctl.urb[i] = NULL;
188 }
189 dev->isoc_ctl.transfer_buffer[i] = NULL;
190 }
191
192 kfree(dev->isoc_ctl.urb);
193 kfree(dev->isoc_ctl.transfer_buffer);
194
195 dev->isoc_ctl.urb = NULL;
196 dev->isoc_ctl.transfer_buffer = NULL;
197 dev->isoc_ctl.num_bufs = 0;
198}
199
200/*
201 * Allocate URBs and start IRQ
202 */
203int au0828_init_isoc(struct au0828_dev *dev, int max_packets,
204 int num_bufs, int max_pkt_size,
205 int (*isoc_copy) (struct au0828_dev *dev, struct urb *urb))
206{
207 struct au0828_dmaqueue *dma_q = &dev->vidq;
208 int i;
209 int sb_size, pipe;
210 struct urb *urb;
211 int j, k;
212 int rc;
213
214 au0828_isocdbg("au0828: called au0828_prepare_isoc\n");
215
216 /* De-allocates all pending stuff */
217 au0828_uninit_isoc(dev);
218
219 dev->isoc_ctl.isoc_copy = isoc_copy;
220 dev->isoc_ctl.num_bufs = num_bufs;
221
222 dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL);
223 if (!dev->isoc_ctl.urb) {
224 au0828_isocdbg("cannot alloc memory for usb buffers\n");
225 return -ENOMEM;
226 }
227
228 dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs,
229 GFP_KERNEL);
230 if (!dev->isoc_ctl.transfer_buffer) {
231 au0828_isocdbg("cannot allocate memory for usb transfer\n");
232 kfree(dev->isoc_ctl.urb);
233 return -ENOMEM;
234 }
235
236 dev->isoc_ctl.max_pkt_size = max_pkt_size;
237 dev->isoc_ctl.buf = NULL;
238
239 sb_size = max_packets * dev->isoc_ctl.max_pkt_size;
240
241 /* allocate urbs and transfer buffers */
242 for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
243 urb = usb_alloc_urb(max_packets, GFP_KERNEL);
244 if (!urb) {
245 au0828_isocdbg("cannot alloc isoc_ctl.urb %i\n", i);
246 au0828_uninit_isoc(dev);
247 return -ENOMEM;
248 }
249 dev->isoc_ctl.urb[i] = urb;
250
Daniel Mack997ea582010-04-12 13:17:25 +0200251 dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->usbdev,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300252 sb_size, GFP_KERNEL, &urb->transfer_dma);
253 if (!dev->isoc_ctl.transfer_buffer[i]) {
254 printk("unable to allocate %i bytes for transfer"
255 " buffer %i%s\n",
256 sb_size, i,
257 in_interrupt() ? " while in int" : "");
258 au0828_uninit_isoc(dev);
259 return -ENOMEM;
260 }
261 memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size);
262
263 pipe = usb_rcvisocpipe(dev->usbdev,
264 dev->isoc_in_endpointaddr),
265
266 usb_fill_int_urb(urb, dev->usbdev, pipe,
267 dev->isoc_ctl.transfer_buffer[i], sb_size,
268 au0828_irq_callback, dma_q, 1);
269
270 urb->number_of_packets = max_packets;
Devin Heitmuellerfadadb72009-03-22 23:42:26 -0300271 urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300272
273 k = 0;
274 for (j = 0; j < max_packets; j++) {
275 urb->iso_frame_desc[j].offset = k;
276 urb->iso_frame_desc[j].length =
277 dev->isoc_ctl.max_pkt_size;
278 k += dev->isoc_ctl.max_pkt_size;
279 }
280 }
281
282 init_waitqueue_head(&dma_q->wq);
283
284 /* submit urbs and enables IRQ */
285 for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
286 rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC);
287 if (rc) {
288 au0828_isocdbg("submit of urb %i failed (error=%i)\n",
289 i, rc);
290 au0828_uninit_isoc(dev);
291 return rc;
292 }
293 }
294
295 return 0;
296}
297
298/*
299 * Announces that a buffer were filled and request the next
300 */
301static inline void buffer_filled(struct au0828_dev *dev,
302 struct au0828_dmaqueue *dma_q,
303 struct au0828_buffer *buf)
304{
305 /* Advice that buffer was filled */
306 au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);
307
308 buf->vb.state = VIDEOBUF_DONE;
309 buf->vb.field_count++;
310 do_gettimeofday(&buf->vb.ts);
311
312 dev->isoc_ctl.buf = NULL;
313
314 list_del(&buf->vb.queue);
315 wake_up(&buf->vb.done);
316}
317
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300318static inline void vbi_buffer_filled(struct au0828_dev *dev,
319 struct au0828_dmaqueue *dma_q,
320 struct au0828_buffer *buf)
321{
322 /* Advice that buffer was filled */
323 au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);
324
325 buf->vb.state = VIDEOBUF_DONE;
326 buf->vb.field_count++;
327 do_gettimeofday(&buf->vb.ts);
328
329 dev->isoc_ctl.vbi_buf = NULL;
330
331 list_del(&buf->vb.queue);
332 wake_up(&buf->vb.done);
333}
334
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300335/*
336 * Identify the buffer header type and properly handles
337 */
338static void au0828_copy_video(struct au0828_dev *dev,
339 struct au0828_dmaqueue *dma_q,
340 struct au0828_buffer *buf,
341 unsigned char *p,
342 unsigned char *outp, unsigned long len)
343{
344 void *fieldstart, *startwrite, *startread;
345 int linesdone, currlinedone, offset, lencopy, remain;
346 int bytesperline = dev->width << 1; /* Assumes 16-bit depth @@@@ */
347
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300348 if (len == 0)
349 return;
350
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300351 if (dma_q->pos + len > buf->vb.size)
352 len = buf->vb.size - dma_q->pos;
353
354 startread = p;
355 remain = len;
356
357 /* Interlaces frame */
358 if (buf->top_field)
359 fieldstart = outp;
360 else
361 fieldstart = outp + bytesperline;
362
363 linesdone = dma_q->pos / bytesperline;
364 currlinedone = dma_q->pos % bytesperline;
365 offset = linesdone * bytesperline * 2 + currlinedone;
366 startwrite = fieldstart + offset;
367 lencopy = bytesperline - currlinedone;
368 lencopy = lencopy > remain ? remain : lencopy;
369
370 if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) {
371 au0828_isocdbg("Overflow of %zi bytes past buffer end (1)\n",
372 ((char *)startwrite + lencopy) -
373 ((char *)outp + buf->vb.size));
374 remain = (char *)outp + buf->vb.size - (char *)startwrite;
375 lencopy = remain;
376 }
377 if (lencopy <= 0)
378 return;
379 memcpy(startwrite, startread, lencopy);
380
381 remain -= lencopy;
382
383 while (remain > 0) {
384 startwrite += lencopy + bytesperline;
385 startread += lencopy;
386 if (bytesperline > remain)
387 lencopy = remain;
388 else
389 lencopy = bytesperline;
390
391 if ((char *)startwrite + lencopy > (char *)outp +
392 buf->vb.size) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300393 au0828_isocdbg("Overflow %zi bytes past buf end (2)\n",
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300394 ((char *)startwrite + lencopy) -
395 ((char *)outp + buf->vb.size));
396 lencopy = remain = (char *)outp + buf->vb.size -
397 (char *)startwrite;
398 }
399 if (lencopy <= 0)
400 break;
401
402 memcpy(startwrite, startread, lencopy);
403
404 remain -= lencopy;
405 }
406
407 if (offset > 1440) {
408 /* We have enough data to check for greenscreen */
Devin Heitmueller62899a22009-03-15 18:48:52 -0300409 if (outp[0] < 0x60 && outp[1440] < 0x60)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300410 dev->greenscreen_detected = 1;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300411 }
412
413 dma_q->pos += len;
414}
415
416/*
417 * video-buf generic routine to get the next available buffer
418 */
419static inline void get_next_buf(struct au0828_dmaqueue *dma_q,
420 struct au0828_buffer **buf)
421{
422 struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq);
423
424 if (list_empty(&dma_q->active)) {
425 au0828_isocdbg("No active queue to serve\n");
426 dev->isoc_ctl.buf = NULL;
427 *buf = NULL;
428 return;
429 }
430
431 /* Get the next buffer */
432 *buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue);
433 dev->isoc_ctl.buf = *buf;
434
435 return;
436}
437
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300438static void au0828_copy_vbi(struct au0828_dev *dev,
439 struct au0828_dmaqueue *dma_q,
440 struct au0828_buffer *buf,
441 unsigned char *p,
442 unsigned char *outp, unsigned long len)
443{
444 unsigned char *startwrite, *startread;
Dan Carpenterb5f59332010-07-23 07:09:20 -0300445 int bytesperline;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300446 int i, j = 0;
447
448 if (dev == NULL) {
449 au0828_isocdbg("dev is null\n");
450 return;
451 }
452
453 if (dma_q == NULL) {
454 au0828_isocdbg("dma_q is null\n");
455 return;
456 }
457 if (buf == NULL)
458 return;
459 if (p == NULL) {
460 au0828_isocdbg("p is null\n");
461 return;
462 }
463 if (outp == NULL) {
464 au0828_isocdbg("outp is null\n");
465 return;
466 }
467
Dan Carpenterb5f59332010-07-23 07:09:20 -0300468 bytesperline = dev->vbi_width;
469
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300470 if (dma_q->pos + len > buf->vb.size)
471 len = buf->vb.size - dma_q->pos;
472
473 startread = p;
474 startwrite = outp + (dma_q->pos / 2);
475
476 /* Make sure the bottom field populates the second half of the frame */
477 if (buf->top_field == 0)
478 startwrite += bytesperline * dev->vbi_height;
479
480 for (i = 0; i < len; i += 2)
481 startwrite[j++] = startread[i+1];
482
483 dma_q->pos += len;
484}
485
486
487/*
488 * video-buf generic routine to get the next available VBI buffer
489 */
490static inline void vbi_get_next_buf(struct au0828_dmaqueue *dma_q,
491 struct au0828_buffer **buf)
492{
493 struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vbiq);
494 char *outp;
495
496 if (list_empty(&dma_q->active)) {
497 au0828_isocdbg("No active queue to serve\n");
498 dev->isoc_ctl.vbi_buf = NULL;
499 *buf = NULL;
500 return;
501 }
502
503 /* Get the next buffer */
504 *buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue);
505 /* Cleans up buffer - Usefull for testing for frame/URB loss */
506 outp = videobuf_to_vmalloc(&(*buf)->vb);
507 memset(outp, 0x00, (*buf)->vb.size);
508
509 dev->isoc_ctl.vbi_buf = *buf;
510
511 return;
512}
513
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300514/*
515 * Controls the isoc copy of each urb packet
516 */
517static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
518{
519 struct au0828_buffer *buf;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300520 struct au0828_buffer *vbi_buf;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300521 struct au0828_dmaqueue *dma_q = urb->context;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300522 struct au0828_dmaqueue *vbi_dma_q = &dev->vbiq;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300523 unsigned char *outp = NULL;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300524 unsigned char *vbioutp = NULL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300525 int i, len = 0, rc = 1;
526 unsigned char *p;
527 unsigned char fbyte;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300528 unsigned int vbi_field_size;
529 unsigned int remain, lencopy;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300530
531 if (!dev)
532 return 0;
533
534 if ((dev->dev_state & DEV_DISCONNECTED) ||
535 (dev->dev_state & DEV_MISCONFIGURED))
536 return 0;
537
538 if (urb->status < 0) {
539 print_err_status(dev, -1, urb->status);
540 if (urb->status == -ENOENT)
541 return 0;
542 }
543
544 buf = dev->isoc_ctl.buf;
545 if (buf != NULL)
546 outp = videobuf_to_vmalloc(&buf->vb);
547
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300548 vbi_buf = dev->isoc_ctl.vbi_buf;
549 if (vbi_buf != NULL)
550 vbioutp = videobuf_to_vmalloc(&vbi_buf->vb);
551
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300552 for (i = 0; i < urb->number_of_packets; i++) {
553 int status = urb->iso_frame_desc[i].status;
554
555 if (status < 0) {
556 print_err_status(dev, i, status);
557 if (urb->iso_frame_desc[i].status != -EPROTO)
558 continue;
559 }
560
Devin Heitmueller62899a22009-03-15 18:48:52 -0300561 if (urb->iso_frame_desc[i].actual_length <= 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300562 continue;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300563
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300564 if (urb->iso_frame_desc[i].actual_length >
565 dev->max_pkt_size) {
566 au0828_isocdbg("packet bigger than packet size");
567 continue;
568 }
569
570 p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
571 fbyte = p[0];
572 len = urb->iso_frame_desc[i].actual_length - 4;
573 p += 4;
574
575 if (fbyte & 0x80) {
576 len -= 4;
577 p += 4;
578 au0828_isocdbg("Video frame %s\n",
579 (fbyte & 0x40) ? "odd" : "even");
Devin Heitmuellerbde3bb92010-07-05 13:05:16 -0300580 if (fbyte & 0x40) {
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300581 /* VBI */
582 if (vbi_buf != NULL)
583 vbi_buffer_filled(dev,
584 vbi_dma_q,
585 vbi_buf);
586 vbi_get_next_buf(vbi_dma_q, &vbi_buf);
587 if (vbi_buf == NULL)
588 vbioutp = NULL;
589 else
590 vbioutp = videobuf_to_vmalloc(
591 &vbi_buf->vb);
592
593 /* Video */
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300594 if (buf != NULL)
595 buffer_filled(dev, dma_q, buf);
596 get_next_buf(dma_q, &buf);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300597 if (buf == NULL)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300598 outp = NULL;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300599 else
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300600 outp = videobuf_to_vmalloc(&buf->vb);
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300601
602 /* As long as isoc traffic is arriving, keep
603 resetting the timer */
604 if (dev->vid_timeout_running)
605 mod_timer(&dev->vid_timeout,
606 jiffies + (HZ / 10));
607 if (dev->vbi_timeout_running)
608 mod_timer(&dev->vbi_timeout,
609 jiffies + (HZ / 10));
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300610 }
611
612 if (buf != NULL) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300613 if (fbyte & 0x40)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300614 buf->top_field = 1;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300615 else
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300616 buf->top_field = 0;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300617 }
618
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300619 if (vbi_buf != NULL) {
620 if (fbyte & 0x40)
621 vbi_buf->top_field = 1;
622 else
623 vbi_buf->top_field = 0;
624 }
625
626 dev->vbi_read = 0;
627 vbi_dma_q->pos = 0;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300628 dma_q->pos = 0;
629 }
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300630
631 vbi_field_size = dev->vbi_width * dev->vbi_height * 2;
632 if (dev->vbi_read < vbi_field_size) {
633 remain = vbi_field_size - dev->vbi_read;
634 if (len < remain)
635 lencopy = len;
636 else
637 lencopy = remain;
638
639 if (vbi_buf != NULL)
640 au0828_copy_vbi(dev, vbi_dma_q, vbi_buf, p,
641 vbioutp, len);
642
643 len -= lencopy;
644 p += lencopy;
645 dev->vbi_read += lencopy;
646 }
647
648 if (dev->vbi_read >= vbi_field_size && buf != NULL)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300649 au0828_copy_video(dev, dma_q, buf, p, outp, len);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300650 }
651 return rc;
652}
653
654static int
655buffer_setup(struct videobuf_queue *vq, unsigned int *count,
656 unsigned int *size)
657{
658 struct au0828_fh *fh = vq->priv_data;
659 *size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3;
660
661 if (0 == *count)
662 *count = AU0828_DEF_BUF;
663
664 if (*count < AU0828_MIN_BUF)
665 *count = AU0828_MIN_BUF;
666 return 0;
667}
668
669/* This is called *without* dev->slock held; please keep it that way */
670static void free_buffer(struct videobuf_queue *vq, struct au0828_buffer *buf)
671{
672 struct au0828_fh *fh = vq->priv_data;
673 struct au0828_dev *dev = fh->dev;
674 unsigned long flags = 0;
675 if (in_interrupt())
676 BUG();
677
678 /* We used to wait for the buffer to finish here, but this didn't work
679 because, as we were keeping the state as VIDEOBUF_QUEUED,
680 videobuf_queue_cancel marked it as finished for us.
681 (Also, it could wedge forever if the hardware was misconfigured.)
682
683 This should be safe; by the time we get here, the buffer isn't
684 queued anymore. If we ever start marking the buffers as
685 VIDEOBUF_ACTIVE, it won't be, though.
686 */
687 spin_lock_irqsave(&dev->slock, flags);
688 if (dev->isoc_ctl.buf == buf)
689 dev->isoc_ctl.buf = NULL;
690 spin_unlock_irqrestore(&dev->slock, flags);
691
692 videobuf_vmalloc_free(&buf->vb);
693 buf->vb.state = VIDEOBUF_NEEDS_INIT;
694}
695
696static int
697buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
698 enum v4l2_field field)
699{
700 struct au0828_fh *fh = vq->priv_data;
701 struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);
702 struct au0828_dev *dev = fh->dev;
703 int rc = 0, urb_init = 0;
704
705 buf->vb.size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3;
706
707 if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
708 return -EINVAL;
709
710 buf->vb.width = dev->width;
711 buf->vb.height = dev->height;
712 buf->vb.field = field;
713
714 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
715 rc = videobuf_iolock(vq, &buf->vb, NULL);
716 if (rc < 0) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300717 printk(KERN_INFO "videobuf_iolock failed\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300718 goto fail;
719 }
720 }
721
722 if (!dev->isoc_ctl.num_bufs)
723 urb_init = 1;
724
725 if (urb_init) {
726 rc = au0828_init_isoc(dev, AU0828_ISO_PACKETS_PER_URB,
727 AU0828_MAX_ISO_BUFS, dev->max_pkt_size,
728 au0828_isoc_copy);
729 if (rc < 0) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300730 printk(KERN_INFO "au0828_init_isoc failed\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300731 goto fail;
732 }
733 }
734
735 buf->vb.state = VIDEOBUF_PREPARED;
736 return 0;
737
738fail:
739 free_buffer(vq, buf);
740 return rc;
741}
742
743static void
744buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
745{
746 struct au0828_buffer *buf = container_of(vb,
747 struct au0828_buffer,
748 vb);
749 struct au0828_fh *fh = vq->priv_data;
750 struct au0828_dev *dev = fh->dev;
751 struct au0828_dmaqueue *vidq = &dev->vidq;
752
753 buf->vb.state = VIDEOBUF_QUEUED;
754 list_add_tail(&buf->vb.queue, &vidq->active);
755}
756
757static void buffer_release(struct videobuf_queue *vq,
758 struct videobuf_buffer *vb)
759{
760 struct au0828_buffer *buf = container_of(vb,
761 struct au0828_buffer,
762 vb);
763
764 free_buffer(vq, buf);
765}
766
767static struct videobuf_queue_ops au0828_video_qops = {
768 .buf_setup = buffer_setup,
769 .buf_prepare = buffer_prepare,
770 .buf_queue = buffer_queue,
771 .buf_release = buffer_release,
772};
773
774/* ------------------------------------------------------------------
775 V4L2 interface
776 ------------------------------------------------------------------*/
777
778static int au0828_i2s_init(struct au0828_dev *dev)
779{
780 /* Enable i2s mode */
781 au0828_writereg(dev, AU0828_AUDIOCTRL_50C, 0x01);
782 return 0;
783}
784
785/*
786 * Auvitek au0828 analog stream enable
787 * Please set interface0 to AS5 before enable the stream
788 */
789int au0828_analog_stream_enable(struct au0828_dev *d)
790{
791 dprintk(1, "au0828_analog_stream_enable called\n");
792 au0828_writereg(d, AU0828_SENSORCTRL_VBI_103, 0x00);
793 au0828_writereg(d, 0x106, 0x00);
794 /* set x position */
795 au0828_writereg(d, 0x110, 0x00);
796 au0828_writereg(d, 0x111, 0x00);
797 au0828_writereg(d, 0x114, 0xa0);
798 au0828_writereg(d, 0x115, 0x05);
799 /* set y position */
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300800 au0828_writereg(d, 0x112, 0x00);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300801 au0828_writereg(d, 0x113, 0x00);
802 au0828_writereg(d, 0x116, 0xf2);
803 au0828_writereg(d, 0x117, 0x00);
804 au0828_writereg(d, AU0828_SENSORCTRL_100, 0xb3);
805
806 return 0;
807}
808
809int au0828_analog_stream_disable(struct au0828_dev *d)
810{
811 dprintk(1, "au0828_analog_stream_disable called\n");
812 au0828_writereg(d, AU0828_SENSORCTRL_100, 0x0);
813 return 0;
814}
815
816void au0828_analog_stream_reset(struct au0828_dev *dev)
817{
818 dprintk(1, "au0828_analog_stream_reset called\n");
819 au0828_writereg(dev, AU0828_SENSORCTRL_100, 0x0);
820 mdelay(30);
821 au0828_writereg(dev, AU0828_SENSORCTRL_100, 0xb3);
822}
823
824/*
825 * Some operations needs to stop current streaming
826 */
827static int au0828_stream_interrupt(struct au0828_dev *dev)
828{
829 int ret = 0;
830
831 dev->stream_state = STREAM_INTERRUPT;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300832 if (dev->dev_state == DEV_DISCONNECTED)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300833 return -ENODEV;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300834 else if (ret) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300835 dev->dev_state = DEV_MISCONFIGURED;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300836 dprintk(1, "%s device is misconfigured!\n", __func__);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300837 return ret;
838 }
839 return 0;
840}
841
842/*
843 * au0828_release_resources
844 * unregister v4l2 devices
845 */
846void au0828_analog_unregister(struct au0828_dev *dev)
847{
848 dprintk(1, "au0828_release_resources called\n");
849 mutex_lock(&au0828_sysfs_lock);
850
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -0200851 if (dev->vdev)
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -0300852 video_unregister_device(dev->vdev);
853 if (dev->vbi_dev)
854 video_unregister_device(dev->vbi_dev);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300855
856 mutex_unlock(&au0828_sysfs_lock);
857}
858
859
860/* Usage lock check functions */
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300861static int res_get(struct au0828_fh *fh, unsigned int bit)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300862{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300863 struct au0828_dev *dev = fh->dev;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300864
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300865 if (fh->resources & bit)
866 /* have it already allocated */
867 return 1;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300868
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300869 /* is it free? */
870 mutex_lock(&dev->lock);
871 if (dev->resources & bit) {
872 /* no, someone else uses it */
873 mutex_unlock(&dev->lock);
874 return 0;
875 }
876 /* it's free, grab it */
877 fh->resources |= bit;
878 dev->resources |= bit;
879 dprintk(1, "res: get %d\n", bit);
880 mutex_unlock(&dev->lock);
881 return 1;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300882}
883
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300884static int res_check(struct au0828_fh *fh, unsigned int bit)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300885{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300886 return fh->resources & bit;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300887}
888
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300889static int res_locked(struct au0828_dev *dev, unsigned int bit)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300890{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300891 return dev->resources & bit;
892}
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300893
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300894static void res_free(struct au0828_fh *fh, unsigned int bits)
895{
896 struct au0828_dev *dev = fh->dev;
897
898 BUG_ON((fh->resources & bits) != bits);
899
900 mutex_lock(&dev->lock);
901 fh->resources &= ~bits;
902 dev->resources &= ~bits;
903 dprintk(1, "res: put %d\n", bits);
904 mutex_unlock(&dev->lock);
905}
906
907static int get_ressource(struct au0828_fh *fh)
908{
909 switch (fh->type) {
910 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
911 return AU0828_RESOURCE_VIDEO;
912 case V4L2_BUF_TYPE_VBI_CAPTURE:
913 return AU0828_RESOURCE_VBI;
914 default:
915 BUG();
916 return 0;
917 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300918}
919
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300920/* This function ensures that video frames continue to be delivered even if
921 the ITU-656 input isn't receiving any data (thereby preventing applications
922 such as tvtime from hanging) */
923void au0828_vid_buffer_timeout(unsigned long data)
924{
925 struct au0828_dev *dev = (struct au0828_dev *) data;
926 struct au0828_dmaqueue *dma_q = &dev->vidq;
927 struct au0828_buffer *buf;
928 unsigned char *vid_data;
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300929 unsigned long flags = 0;
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300930
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300931 spin_lock_irqsave(&dev->slock, flags);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300932
933 buf = dev->isoc_ctl.buf;
934 if (buf != NULL) {
935 vid_data = videobuf_to_vmalloc(&buf->vb);
936 memset(vid_data, 0x00, buf->vb.size); /* Blank green frame */
937 buffer_filled(dev, dma_q, buf);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300938 }
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300939 get_next_buf(dma_q, &buf);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300940
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300941 if (dev->vid_timeout_running == 1)
942 mod_timer(&dev->vid_timeout, jiffies + (HZ / 10));
943
944 spin_unlock_irqrestore(&dev->slock, flags);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300945}
946
947void au0828_vbi_buffer_timeout(unsigned long data)
948{
949 struct au0828_dev *dev = (struct au0828_dev *) data;
950 struct au0828_dmaqueue *dma_q = &dev->vbiq;
951 struct au0828_buffer *buf;
952 unsigned char *vbi_data;
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300953 unsigned long flags = 0;
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300954
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300955 spin_lock_irqsave(&dev->slock, flags);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300956
957 buf = dev->isoc_ctl.vbi_buf;
958 if (buf != NULL) {
959 vbi_data = videobuf_to_vmalloc(&buf->vb);
960 memset(vbi_data, 0x00, buf->vb.size);
961 vbi_buffer_filled(dev, dma_q, buf);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300962 }
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300963 vbi_get_next_buf(dma_q, &buf);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300964
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300965 if (dev->vbi_timeout_running == 1)
966 mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
967 spin_unlock_irqrestore(&dev->slock, flags);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300968}
969
970
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300971static int au0828_v4l2_open(struct file *filp)
972{
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300973 int ret = 0;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300974 struct video_device *vdev = video_devdata(filp);
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -0200975 struct au0828_dev *dev = video_drvdata(filp);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300976 struct au0828_fh *fh;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300977 int type;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300978
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300979 switch (vdev->vfl_type) {
980 case VFL_TYPE_GRABBER:
981 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
982 break;
983 case VFL_TYPE_VBI:
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -0200984 type = V4L2_BUF_TYPE_VBI_CAPTURE;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300985 break;
986 default:
987 return -EINVAL;
988 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300989
990 fh = kzalloc(sizeof(struct au0828_fh), GFP_KERNEL);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300991 if (NULL == fh) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300992 dprintk(1, "Failed allocate au0828_fh struct!\n");
993 return -ENOMEM;
994 }
995
996 fh->type = type;
997 fh->dev = dev;
998 filp->private_data = fh;
999
Devin Heitmueller62899a22009-03-15 18:48:52 -03001000 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001001 /* set au0828 interface0 to AS5 here again */
1002 ret = usb_set_interface(dev->usbdev, 0, 5);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001003 if (ret < 0) {
1004 printk(KERN_INFO "Au0828 can't set alternate to 5!\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001005 return -EBUSY;
1006 }
1007 dev->width = NTSC_STD_W;
1008 dev->height = NTSC_STD_H;
1009 dev->frame_size = dev->width * dev->height * 2;
1010 dev->field_size = dev->width * dev->height;
1011 dev->bytesperline = dev->width * 2;
1012
1013 au0828_analog_stream_enable(dev);
1014 au0828_analog_stream_reset(dev);
1015
1016 /* If we were doing ac97 instead of i2s, it would go here...*/
1017 au0828_i2s_init(dev);
1018
1019 dev->stream_state = STREAM_OFF;
1020 dev->dev_state |= DEV_INITIALIZED;
1021 }
1022
1023 dev->users++;
1024
1025 videobuf_queue_vmalloc_init(&fh->vb_vidq, &au0828_video_qops,
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001026 NULL, &dev->slock,
1027 V4L2_BUF_TYPE_VIDEO_CAPTURE,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001028 V4L2_FIELD_INTERLACED,
Hans Verkuil08bff032010-09-20 17:39:46 -03001029 sizeof(struct au0828_buffer), fh, NULL);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001030
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001031 /* VBI Setup */
1032 dev->vbi_width = 720;
1033 dev->vbi_height = 1;
1034 videobuf_queue_vmalloc_init(&fh->vb_vbiq, &au0828_vbi_qops,
1035 NULL, &dev->slock,
1036 V4L2_BUF_TYPE_VBI_CAPTURE,
1037 V4L2_FIELD_SEQ_TB,
Hans Verkuil08bff032010-09-20 17:39:46 -03001038 sizeof(struct au0828_buffer), fh, NULL);
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001039
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001040 return ret;
1041}
1042
1043static int au0828_v4l2_close(struct file *filp)
1044{
1045 int ret;
1046 struct au0828_fh *fh = filp->private_data;
1047 struct au0828_dev *dev = fh->dev;
1048
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001049 if (res_check(fh, AU0828_RESOURCE_VIDEO)) {
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001050 /* Cancel timeout thread in case they didn't call streamoff */
1051 dev->vid_timeout_running = 0;
1052 del_timer_sync(&dev->vid_timeout);
1053
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001054 videobuf_stop(&fh->vb_vidq);
1055 res_free(fh, AU0828_RESOURCE_VIDEO);
1056 }
1057
1058 if (res_check(fh, AU0828_RESOURCE_VBI)) {
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001059 /* Cancel timeout thread in case they didn't call streamoff */
1060 dev->vbi_timeout_running = 0;
1061 del_timer_sync(&dev->vbi_timeout);
1062
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001063 videobuf_stop(&fh->vb_vbiq);
1064 res_free(fh, AU0828_RESOURCE_VBI);
1065 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001066
Devin Heitmueller62899a22009-03-15 18:48:52 -03001067 if (dev->users == 1) {
Devin Heitmueller62899a22009-03-15 18:48:52 -03001068 if (dev->dev_state & DEV_DISCONNECTED) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001069 au0828_analog_unregister(dev);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001070 kfree(dev);
1071 return 0;
1072 }
1073
1074 au0828_analog_stream_disable(dev);
1075
1076 au0828_uninit_isoc(dev);
1077
Devin Heitmuellere4b8bc52009-05-06 20:54:00 -03001078 /* Save some power by putting tuner to sleep */
Laurent Pinchart622b8282009-10-05 10:48:17 -03001079 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);
Devin Heitmuellere4b8bc52009-05-06 20:54:00 -03001080
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001081 /* When close the device, set the usb intf0 into alt0 to free
1082 USB bandwidth */
1083 ret = usb_set_interface(dev->usbdev, 0, 0);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001084 if (ret < 0)
1085 printk(KERN_INFO "Au0828 can't set alternate to 0!\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001086 }
1087
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001088 videobuf_mmap_free(&fh->vb_vidq);
1089 videobuf_mmap_free(&fh->vb_vbiq);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001090 kfree(fh);
1091 dev->users--;
1092 wake_up_interruptible_nr(&dev->open, 1);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001093 return 0;
1094}
1095
1096static ssize_t au0828_v4l2_read(struct file *filp, char __user *buf,
1097 size_t count, loff_t *pos)
1098{
1099 struct au0828_fh *fh = filp->private_data;
1100 struct au0828_dev *dev = fh->dev;
1101 int rc;
1102
1103 rc = check_dev(dev);
1104 if (rc < 0)
1105 return rc;
1106
Devin Heitmueller62899a22009-03-15 18:48:52 -03001107 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001108 if (res_locked(dev, AU0828_RESOURCE_VIDEO))
1109 return -EBUSY;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001110
1111 return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0,
1112 filp->f_flags & O_NONBLOCK);
1113 }
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001114
1115 if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
1116 if (!res_get(fh, AU0828_RESOURCE_VBI))
1117 return -EBUSY;
1118
1119 return videobuf_read_stream(&fh->vb_vbiq, buf, count, pos, 0,
1120 filp->f_flags & O_NONBLOCK);
1121 }
1122
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001123 return 0;
1124}
1125
1126static unsigned int au0828_v4l2_poll(struct file *filp, poll_table *wait)
1127{
1128 struct au0828_fh *fh = filp->private_data;
1129 struct au0828_dev *dev = fh->dev;
1130 int rc;
1131
1132 rc = check_dev(dev);
1133 if (rc < 0)
1134 return rc;
1135
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001136 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1137 if (!res_get(fh, AU0828_RESOURCE_VIDEO))
1138 return POLLERR;
1139 return videobuf_poll_stream(filp, &fh->vb_vidq, wait);
1140 } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
1141 if (!res_get(fh, AU0828_RESOURCE_VBI))
1142 return POLLERR;
1143 return videobuf_poll_stream(filp, &fh->vb_vbiq, wait);
1144 } else {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001145 return POLLERR;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001146 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001147}
1148
1149static int au0828_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
1150{
1151 struct au0828_fh *fh = filp->private_data;
1152 struct au0828_dev *dev = fh->dev;
1153 int rc;
1154
1155 rc = check_dev(dev);
1156 if (rc < 0)
1157 return rc;
1158
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001159 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1160 rc = videobuf_mmap_mapper(&fh->vb_vidq, vma);
1161 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1162 rc = videobuf_mmap_mapper(&fh->vb_vbiq, vma);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001163
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001164 return rc;
1165}
1166
1167static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd,
1168 struct v4l2_format *format)
1169{
1170 int ret;
1171 int width = format->fmt.pix.width;
1172 int height = format->fmt.pix.height;
1173 unsigned int maxwidth, maxheight;
1174
1175 maxwidth = 720;
1176 maxheight = 480;
1177
Devin Heitmueller62899a22009-03-15 18:48:52 -03001178 if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001179 return -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001180
1181 /* If they are demanding a format other than the one we support,
1182 bail out (tvtime asks for UYVY and then retries with YUYV) */
Devin Heitmueller62899a22009-03-15 18:48:52 -03001183 if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_UYVY)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001184 return -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001185
1186 /* format->fmt.pix.width only support 720 and height 480 */
Devin Heitmueller62899a22009-03-15 18:48:52 -03001187 if (width != 720)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001188 width = 720;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001189 if (height != 480)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001190 height = 480;
1191
1192 format->fmt.pix.width = width;
1193 format->fmt.pix.height = height;
1194 format->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
1195 format->fmt.pix.bytesperline = width * 2;
1196 format->fmt.pix.sizeimage = width * height * 2;
1197 format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
1198 format->fmt.pix.field = V4L2_FIELD_INTERLACED;
1199
Devin Heitmueller62899a22009-03-15 18:48:52 -03001200 if (cmd == VIDIOC_TRY_FMT)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001201 return 0;
1202
1203 /* maybe set new image format, driver current only support 720*480 */
1204 dev->width = width;
1205 dev->height = height;
1206 dev->frame_size = width * height * 2;
1207 dev->field_size = width * height;
1208 dev->bytesperline = width * 2;
1209
Devin Heitmueller62899a22009-03-15 18:48:52 -03001210 if (dev->stream_state == STREAM_ON) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001211 dprintk(1, "VIDIOC_SET_FMT: interrupting stream!\n");
Devin Heitmueller62899a22009-03-15 18:48:52 -03001212 ret = au0828_stream_interrupt(dev);
1213 if (ret != 0) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001214 dprintk(1, "error interrupting video stream!\n");
1215 return ret;
1216 }
1217 }
1218
1219 /* set au0828 interface0 to AS5 here again */
1220 ret = usb_set_interface(dev->usbdev, 0, 5);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001221 if (ret < 0) {
1222 printk(KERN_INFO "Au0828 can't set alt setting to 5!\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001223 return -EBUSY;
1224 }
1225
1226 au0828_analog_stream_enable(dev);
1227
1228 return 0;
1229}
1230
1231
1232static int vidioc_queryctrl(struct file *file, void *priv,
1233 struct v4l2_queryctrl *qc)
1234{
1235 struct au0828_fh *fh = priv;
1236 struct au0828_dev *dev = fh->dev;
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001237 v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, qc);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001238 if (qc->type)
1239 return 0;
1240 else
1241 return -EINVAL;
1242}
1243
1244static int vidioc_querycap(struct file *file, void *priv,
1245 struct v4l2_capability *cap)
1246{
1247 struct au0828_fh *fh = priv;
1248 struct au0828_dev *dev = fh->dev;
1249
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001250 strlcpy(cap->driver, "au0828", sizeof(cap->driver));
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001251 strlcpy(cap->card, dev->board.name, sizeof(cap->card));
Devin Heitmuellerb14667f2009-03-11 03:01:04 -03001252 strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001253
1254 cap->version = AU0828_VERSION_CODE;
1255
1256 /*set the device capabilities */
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001257 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001258 V4L2_CAP_VBI_CAPTURE |
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001259 V4L2_CAP_AUDIO |
1260 V4L2_CAP_READWRITE |
1261 V4L2_CAP_STREAMING |
1262 V4L2_CAP_TUNER;
1263 return 0;
1264}
1265
1266static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
1267 struct v4l2_fmtdesc *f)
1268{
Devin Heitmueller62899a22009-03-15 18:48:52 -03001269 if (f->index)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001270 return -EINVAL;
1271
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001272 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1273 strcpy(f->description, "Packed YUV2");
1274
1275 f->flags = 0;
1276 f->pixelformat = V4L2_PIX_FMT_UYVY;
1277
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001278 return 0;
1279}
1280
1281static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
1282 struct v4l2_format *f)
1283{
1284 struct au0828_fh *fh = priv;
1285 struct au0828_dev *dev = fh->dev;
1286
1287 f->fmt.pix.width = dev->width;
1288 f->fmt.pix.height = dev->height;
1289 f->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
1290 f->fmt.pix.bytesperline = dev->bytesperline;
1291 f->fmt.pix.sizeimage = dev->frame_size;
1292 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; /* NTSC/PAL */
1293 f->fmt.pix.field = V4L2_FIELD_INTERLACED;
1294 return 0;
1295}
1296
1297static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
1298 struct v4l2_format *f)
1299{
1300 struct au0828_fh *fh = priv;
1301 struct au0828_dev *dev = fh->dev;
1302
1303 return au0828_set_format(dev, VIDIOC_TRY_FMT, f);
1304}
1305
1306static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
1307 struct v4l2_format *f)
1308{
1309 struct au0828_fh *fh = priv;
1310 struct au0828_dev *dev = fh->dev;
1311 int rc;
1312
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001313 rc = check_dev(dev);
1314 if (rc < 0)
1315 return rc;
1316
1317 mutex_lock(&dev->lock);
1318
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001319 if (videobuf_queue_is_busy(&fh->vb_vidq)) {
Devin Heitmueller62899a22009-03-15 18:48:52 -03001320 printk(KERN_INFO "%s queue busy\n", __func__);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001321 rc = -EBUSY;
1322 goto out;
1323 }
1324
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001325 rc = au0828_set_format(dev, VIDIOC_S_FMT, f);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001326out:
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001327 mutex_unlock(&dev->lock);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001328 return rc;
1329}
1330
1331static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm)
1332{
1333 struct au0828_fh *fh = priv;
1334 struct au0828_dev *dev = fh->dev;
1335
1336 /* FIXME: when we support something other than NTSC, we are going to
1337 have to make the au0828 bridge adjust the size of its capture
1338 buffer, which is currently hardcoded at 720x480 */
1339
Hans Verkuilf41737e2009-04-01 03:52:39 -03001340 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, *norm);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001341 return 0;
1342}
1343
1344static int vidioc_enum_input(struct file *file, void *priv,
1345 struct v4l2_input *input)
1346{
1347 struct au0828_fh *fh = priv;
1348 struct au0828_dev *dev = fh->dev;
1349 unsigned int tmp;
1350
1351 static const char *inames[] = {
Devin Heitmueller3d622872009-03-15 17:48:26 -03001352 [AU0828_VMUX_UNDEFINED] = "Undefined",
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001353 [AU0828_VMUX_COMPOSITE] = "Composite",
1354 [AU0828_VMUX_SVIDEO] = "S-Video",
1355 [AU0828_VMUX_CABLE] = "Cable TV",
1356 [AU0828_VMUX_TELEVISION] = "Television",
1357 [AU0828_VMUX_DVB] = "DVB",
1358 [AU0828_VMUX_DEBUG] = "tv debug"
1359 };
1360
1361 tmp = input->index;
1362
Dan Carpenterf5e20c32010-03-28 08:21:18 -03001363 if (tmp >= AU0828_MAX_INPUT)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001364 return -EINVAL;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001365 if (AUVI_INPUT(tmp).type == 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001366 return -EINVAL;
1367
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001368 input->index = tmp;
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001369 strcpy(input->name, inames[AUVI_INPUT(tmp).type]);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001370 if ((AUVI_INPUT(tmp).type == AU0828_VMUX_TELEVISION) ||
1371 (AUVI_INPUT(tmp).type == AU0828_VMUX_CABLE))
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001372 input->type |= V4L2_INPUT_TYPE_TUNER;
1373 else
1374 input->type |= V4L2_INPUT_TYPE_CAMERA;
1375
1376 input->std = dev->vdev->tvnorms;
1377
1378 return 0;
1379}
1380
1381static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
1382{
1383 struct au0828_fh *fh = priv;
1384 struct au0828_dev *dev = fh->dev;
1385 *i = dev->ctrl_input;
1386 return 0;
1387}
1388
1389static int vidioc_s_input(struct file *file, void *priv, unsigned int index)
1390{
1391 struct au0828_fh *fh = priv;
1392 struct au0828_dev *dev = fh->dev;
1393 int i;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001394
Devin Heitmueller62899a22009-03-15 18:48:52 -03001395 dprintk(1, "VIDIOC_S_INPUT in function %s, input=%d\n", __func__,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001396 index);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001397 if (index >= AU0828_MAX_INPUT)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001398 return -EINVAL;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001399 if (AUVI_INPUT(index).type == 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001400 return -EINVAL;
1401 dev->ctrl_input = index;
1402
Devin Heitmueller62899a22009-03-15 18:48:52 -03001403 switch (AUVI_INPUT(index).type) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001404 case AU0828_VMUX_SVIDEO:
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001405 dev->input_type = AU0828_VMUX_SVIDEO;
1406 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001407 case AU0828_VMUX_COMPOSITE:
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001408 dev->input_type = AU0828_VMUX_COMPOSITE;
1409 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001410 case AU0828_VMUX_TELEVISION:
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001411 dev->input_type = AU0828_VMUX_TELEVISION;
1412 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001413 default:
Devin Heitmuellera1094c42009-03-15 17:43:13 -03001414 dprintk(1, "VIDIOC_S_INPUT unknown input type set [%d]\n",
1415 AUVI_INPUT(index).type);
1416 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001417 }
1418
Hans Verkuil5325b422009-04-02 11:26:22 -03001419 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing,
1420 AUVI_INPUT(index).vmux, 0, 0);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001421
1422 for (i = 0; i < AU0828_MAX_INPUT; i++) {
1423 int enable = 0;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001424 if (AUVI_INPUT(i).audio_setup == NULL)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001425 continue;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001426
1427 if (i == index)
1428 enable = 1;
1429 else
1430 enable = 0;
1431 if (enable) {
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001432 (AUVI_INPUT(i).audio_setup)(dev, enable);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001433 } else {
1434 /* Make sure we leave it turned on if some
1435 other input is routed to this callback */
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001436 if ((AUVI_INPUT(i).audio_setup) !=
1437 ((AUVI_INPUT(index).audio_setup))) {
1438 (AUVI_INPUT(i).audio_setup)(dev, enable);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001439 }
1440 }
1441 }
1442
Hans Verkuil5325b422009-04-02 11:26:22 -03001443 v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing,
1444 AUVI_INPUT(index).amux, 0, 0);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001445 return 0;
1446}
1447
1448static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
1449{
1450 struct au0828_fh *fh = priv;
1451 struct au0828_dev *dev = fh->dev;
1452 unsigned int index = a->index;
1453
Devin Heitmueller62899a22009-03-15 18:48:52 -03001454 if (a->index > 1)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001455 return -EINVAL;
1456
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001457 index = dev->ctrl_ainput;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001458 if (index == 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001459 strcpy(a->name, "Television");
1460 else
1461 strcpy(a->name, "Line in");
1462
1463 a->capability = V4L2_AUDCAP_STEREO;
1464 a->index = index;
1465 return 0;
1466}
1467
1468static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
1469{
1470 struct au0828_fh *fh = priv;
1471 struct au0828_dev *dev = fh->dev;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001472 if (a->index != dev->ctrl_ainput)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001473 return -EINVAL;
1474 return 0;
1475}
1476
1477static int vidioc_g_ctrl(struct file *file, void *priv,
1478 struct v4l2_control *ctrl)
1479{
1480 struct au0828_fh *fh = priv;
1481 struct au0828_dev *dev = fh->dev;
1482
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001483 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001484 return 0;
1485
1486}
1487
1488static int vidioc_s_ctrl(struct file *file, void *priv,
1489 struct v4l2_control *ctrl)
1490{
1491 struct au0828_fh *fh = priv;
1492 struct au0828_dev *dev = fh->dev;
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001493 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_ctrl, ctrl);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001494 return 0;
1495}
1496
1497static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
1498{
1499 struct au0828_fh *fh = priv;
1500 struct au0828_dev *dev = fh->dev;
1501
Devin Heitmueller62899a22009-03-15 18:48:52 -03001502 if (t->index != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001503 return -EINVAL;
1504
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001505 strcpy(t->name, "Auvitek tuner");
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001506 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001507 return 0;
1508}
1509
1510static int vidioc_s_tuner(struct file *file, void *priv,
1511 struct v4l2_tuner *t)
1512{
1513 struct au0828_fh *fh = priv;
1514 struct au0828_dev *dev = fh->dev;
1515
Devin Heitmueller62899a22009-03-15 18:48:52 -03001516 if (t->index != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001517 return -EINVAL;
1518
1519 t->type = V4L2_TUNER_ANALOG_TV;
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001520 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001521 dprintk(1, "VIDIOC_S_TUNER: signal = %x, afc = %x\n", t->signal,
1522 t->afc);
1523 return 0;
1524
1525}
1526
1527static int vidioc_g_frequency(struct file *file, void *priv,
1528 struct v4l2_frequency *freq)
1529{
1530 struct au0828_fh *fh = priv;
1531 struct au0828_dev *dev = fh->dev;
Devin Heitmuellerc8889232009-03-15 17:38:47 -03001532
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001533 freq->type = V4L2_TUNER_ANALOG_TV;
1534 freq->frequency = dev->ctrl_freq;
1535 return 0;
1536}
1537
1538static int vidioc_s_frequency(struct file *file, void *priv,
1539 struct v4l2_frequency *freq)
1540{
1541 struct au0828_fh *fh = priv;
1542 struct au0828_dev *dev = fh->dev;
1543
Devin Heitmueller62899a22009-03-15 18:48:52 -03001544 if (freq->tuner != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001545 return -EINVAL;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001546 if (freq->type != V4L2_TUNER_ANALOG_TV)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001547 return -EINVAL;
1548
1549 dev->ctrl_freq = freq->frequency;
1550
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001551 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, freq);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001552
1553 au0828_analog_stream_reset(dev);
1554
1555 return 0;
1556}
1557
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001558
1559/* RAW VBI ioctls */
1560
1561static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
1562 struct v4l2_format *format)
1563{
1564 struct au0828_fh *fh = priv;
1565 struct au0828_dev *dev = fh->dev;
1566
1567 format->fmt.vbi.samples_per_line = dev->vbi_width;
1568 format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
1569 format->fmt.vbi.offset = 0;
1570 format->fmt.vbi.flags = 0;
1571 format->fmt.vbi.sampling_rate = 6750000 * 4 / 2;
1572
1573 format->fmt.vbi.count[0] = dev->vbi_height;
1574 format->fmt.vbi.count[1] = dev->vbi_height;
1575 format->fmt.vbi.start[0] = 21;
1576 format->fmt.vbi.start[1] = 284;
1577
1578 return 0;
1579}
1580
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001581static int vidioc_g_chip_ident(struct file *file, void *priv,
1582 struct v4l2_dbg_chip_ident *chip)
1583{
1584 struct au0828_fh *fh = priv;
1585 struct au0828_dev *dev = fh->dev;
1586 chip->ident = V4L2_IDENT_NONE;
1587 chip->revision = 0;
1588
Devin Heitmuellerd9109be2009-03-11 03:00:58 -03001589 if (v4l2_chip_match_host(&chip->match)) {
1590 chip->ident = V4L2_IDENT_AU0828;
1591 return 0;
1592 }
1593
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001594 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_chip_ident, chip);
Devin Heitmuellerd9109be2009-03-11 03:00:58 -03001595 if (chip->ident == V4L2_IDENT_NONE)
1596 return -EINVAL;
1597
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001598 return 0;
1599}
1600
1601static int vidioc_cropcap(struct file *file, void *priv,
1602 struct v4l2_cropcap *cc)
1603{
1604 struct au0828_fh *fh = priv;
1605 struct au0828_dev *dev = fh->dev;
1606
Devin Heitmueller62899a22009-03-15 18:48:52 -03001607 if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001608 return -EINVAL;
1609
1610 cc->bounds.left = 0;
1611 cc->bounds.top = 0;
1612 cc->bounds.width = dev->width;
1613 cc->bounds.height = dev->height;
1614
1615 cc->defrect = cc->bounds;
1616
1617 cc->pixelaspect.numerator = 54;
1618 cc->pixelaspect.denominator = 59;
1619
1620 return 0;
1621}
1622
1623static int vidioc_streamon(struct file *file, void *priv,
1624 enum v4l2_buf_type type)
1625{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001626 struct au0828_fh *fh = priv;
1627 struct au0828_dev *dev = fh->dev;
1628 int rc = -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001629
1630 rc = check_dev(dev);
1631 if (rc < 0)
1632 return rc;
1633
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001634 if (unlikely(type != fh->type))
1635 return -EINVAL;
1636
1637 dprintk(1, "vidioc_streamon fh=%p t=%d fh->res=%d dev->res=%d\n",
1638 fh, type, fh->resources, dev->resources);
1639
1640 if (unlikely(!res_get(fh, get_ressource(fh))))
1641 return -EBUSY;
1642
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001643 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1644 au0828_analog_stream_enable(dev);
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001645 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001646 }
1647
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001648 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001649 rc = videobuf_streamon(&fh->vb_vidq);
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001650 dev->vid_timeout_running = 1;
1651 mod_timer(&dev->vid_timeout, jiffies + (HZ / 10));
1652 } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001653 rc = videobuf_streamon(&fh->vb_vbiq);
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001654 dev->vbi_timeout_running = 1;
1655 mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
1656 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001657
1658 return rc;
1659}
1660
1661static int vidioc_streamoff(struct file *file, void *priv,
1662 enum v4l2_buf_type type)
1663{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001664 struct au0828_fh *fh = priv;
1665 struct au0828_dev *dev = fh->dev;
1666 int rc;
1667 int i;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001668
1669 rc = check_dev(dev);
1670 if (rc < 0)
1671 return rc;
1672
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001673 if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
1674 fh->type != V4L2_BUF_TYPE_VBI_CAPTURE)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001675 return -EINVAL;
1676 if (type != fh->type)
1677 return -EINVAL;
1678
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001679 dprintk(1, "vidioc_streamoff fh=%p t=%d fh->res=%d dev->res=%d\n",
1680 fh, type, fh->resources, dev->resources);
1681
1682 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001683 dev->vid_timeout_running = 0;
1684 del_timer_sync(&dev->vid_timeout);
1685
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001686 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001687 rc = au0828_stream_interrupt(dev);
1688 if (rc != 0)
1689 return rc;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001690
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001691 for (i = 0; i < AU0828_MAX_INPUT; i++) {
1692 if (AUVI_INPUT(i).audio_setup == NULL)
1693 continue;
1694 (AUVI_INPUT(i).audio_setup)(dev, 0);
1695 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001696
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001697 videobuf_streamoff(&fh->vb_vidq);
1698 res_free(fh, AU0828_RESOURCE_VIDEO);
1699 } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001700 dev->vbi_timeout_running = 0;
1701 del_timer_sync(&dev->vbi_timeout);
1702
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001703 videobuf_streamoff(&fh->vb_vbiq);
1704 res_free(fh, AU0828_RESOURCE_VBI);
1705 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001706
1707 return 0;
1708}
1709
Mauro Carvalho Chehab80c6e352009-03-19 19:26:23 -03001710#ifdef CONFIG_VIDEO_ADV_DEBUG
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001711static int vidioc_g_register(struct file *file, void *priv,
1712 struct v4l2_dbg_register *reg)
1713{
1714 struct au0828_fh *fh = priv;
1715 struct au0828_dev *dev = fh->dev;
1716
1717 switch (reg->match.type) {
1718 case V4L2_CHIP_MATCH_I2C_DRIVER:
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001719 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001720 return 0;
1721 default:
1722 return -EINVAL;
1723 }
1724}
1725
1726static int vidioc_s_register(struct file *file, void *priv,
1727 struct v4l2_dbg_register *reg)
1728{
1729 struct au0828_fh *fh = priv;
1730 struct au0828_dev *dev = fh->dev;
1731
1732 switch (reg->match.type) {
1733 case V4L2_CHIP_MATCH_I2C_DRIVER:
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001734 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001735 return 0;
1736 default:
1737 return -EINVAL;
1738 }
1739 return 0;
1740}
Mauro Carvalho Chehab80c6e352009-03-19 19:26:23 -03001741#endif
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001742
1743static int vidioc_reqbufs(struct file *file, void *priv,
1744 struct v4l2_requestbuffers *rb)
1745{
1746 struct au0828_fh *fh = priv;
1747 struct au0828_dev *dev = fh->dev;
1748 int rc;
1749
1750 rc = check_dev(dev);
1751 if (rc < 0)
1752 return rc;
1753
1754 return videobuf_reqbufs(&fh->vb_vidq, rb);
1755}
1756
1757static int vidioc_querybuf(struct file *file, void *priv,
1758 struct v4l2_buffer *b)
1759{
1760 struct au0828_fh *fh = priv;
1761 struct au0828_dev *dev = fh->dev;
1762 int rc;
1763
1764 rc = check_dev(dev);
1765 if (rc < 0)
1766 return rc;
1767
1768 return videobuf_querybuf(&fh->vb_vidq, b);
1769}
1770
1771static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
1772{
1773 struct au0828_fh *fh = priv;
1774 struct au0828_dev *dev = fh->dev;
1775 int rc;
1776
1777 rc = check_dev(dev);
1778 if (rc < 0)
1779 return rc;
1780
1781 return videobuf_qbuf(&fh->vb_vidq, b);
1782}
1783
1784static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
1785{
1786 struct au0828_fh *fh = priv;
1787 struct au0828_dev *dev = fh->dev;
1788 int rc;
1789
1790 rc = check_dev(dev);
1791 if (rc < 0)
1792 return rc;
1793
1794 /* Workaround for a bug in the au0828 hardware design that sometimes
1795 results in the colorspace being inverted */
1796 if (dev->greenscreen_detected == 1) {
1797 dprintk(1, "Detected green frame. Resetting stream...\n");
1798 au0828_analog_stream_reset(dev);
1799 dev->greenscreen_detected = 0;
1800 }
1801
1802 return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK);
1803}
1804
1805#ifdef CONFIG_VIDEO_V4L1_COMPAT
1806static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
1807{
1808 struct au0828_fh *fh = priv;
1809
1810 return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8);
1811}
1812#endif
1813
1814static struct v4l2_file_operations au0828_v4l_fops = {
1815 .owner = THIS_MODULE,
1816 .open = au0828_v4l2_open,
1817 .release = au0828_v4l2_close,
1818 .read = au0828_v4l2_read,
1819 .poll = au0828_v4l2_poll,
1820 .mmap = au0828_v4l2_mmap,
1821 .ioctl = video_ioctl2,
1822};
1823
1824static const struct v4l2_ioctl_ops video_ioctl_ops = {
1825 .vidioc_querycap = vidioc_querycap,
1826 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1827 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1828 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1829 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001830 .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001831 .vidioc_s_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001832 .vidioc_g_audio = vidioc_g_audio,
1833 .vidioc_s_audio = vidioc_s_audio,
1834 .vidioc_cropcap = vidioc_cropcap,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001835 .vidioc_reqbufs = vidioc_reqbufs,
1836 .vidioc_querybuf = vidioc_querybuf,
1837 .vidioc_qbuf = vidioc_qbuf,
1838 .vidioc_dqbuf = vidioc_dqbuf,
1839 .vidioc_s_std = vidioc_s_std,
1840 .vidioc_enum_input = vidioc_enum_input,
1841 .vidioc_g_input = vidioc_g_input,
1842 .vidioc_s_input = vidioc_s_input,
1843 .vidioc_queryctrl = vidioc_queryctrl,
1844 .vidioc_g_ctrl = vidioc_g_ctrl,
1845 .vidioc_s_ctrl = vidioc_s_ctrl,
1846 .vidioc_streamon = vidioc_streamon,
1847 .vidioc_streamoff = vidioc_streamoff,
1848 .vidioc_g_tuner = vidioc_g_tuner,
1849 .vidioc_s_tuner = vidioc_s_tuner,
1850 .vidioc_g_frequency = vidioc_g_frequency,
1851 .vidioc_s_frequency = vidioc_s_frequency,
1852#ifdef CONFIG_VIDEO_ADV_DEBUG
1853 .vidioc_g_register = vidioc_g_register,
1854 .vidioc_s_register = vidioc_s_register,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001855#endif
Mauro Carvalho Chehab80c6e352009-03-19 19:26:23 -03001856 .vidioc_g_chip_ident = vidioc_g_chip_ident,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001857#ifdef CONFIG_VIDEO_V4L1_COMPAT
1858 .vidiocgmbuf = vidiocgmbuf,
1859#endif
1860};
1861
1862static const struct video_device au0828_video_template = {
1863 .fops = &au0828_v4l_fops,
1864 .release = video_device_release,
1865 .ioctl_ops = &video_ioctl_ops,
Devin Heitmueller0ef210712009-03-11 03:00:53 -03001866 .tvnorms = V4L2_STD_NTSC_M,
1867 .current_norm = V4L2_STD_NTSC_M,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001868};
1869
1870/**************************************************************************/
1871
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001872int au0828_analog_register(struct au0828_dev *dev,
1873 struct usb_interface *interface)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001874{
1875 int retval = -ENOMEM;
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001876 struct usb_host_interface *iface_desc;
1877 struct usb_endpoint_descriptor *endpoint;
1878 int i;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001879
1880 dprintk(1, "au0828_analog_register called!\n");
1881
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001882 /* set au0828 usb interface0 to as5 */
1883 retval = usb_set_interface(dev->usbdev,
Devin Heitmueller62899a22009-03-15 18:48:52 -03001884 interface->cur_altsetting->desc.bInterfaceNumber, 5);
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001885 if (retval != 0) {
Devin Heitmueller62899a22009-03-15 18:48:52 -03001886 printk(KERN_INFO "Failure setting usb interface0 to as5\n");
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001887 return retval;
1888 }
1889
1890 /* Figure out which endpoint has the isoc interface */
1891 iface_desc = interface->cur_altsetting;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001892 for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001893 endpoint = &iface_desc->endpoint[i].desc;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001894 if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
1895 == USB_DIR_IN) &&
1896 ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
1897 == USB_ENDPOINT_XFER_ISOC)) {
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001898
1899 /* we find our isoc in endpoint */
1900 u16 tmp = le16_to_cpu(endpoint->wMaxPacketSize);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001901 dev->max_pkt_size = (tmp & 0x07ff) *
1902 (((tmp & 0x1800) >> 11) + 1);
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001903 dev->isoc_in_endpointaddr = endpoint->bEndpointAddress;
1904 }
1905 }
Devin Heitmueller62899a22009-03-15 18:48:52 -03001906 if (!(dev->isoc_in_endpointaddr)) {
1907 printk(KERN_INFO "Could not locate isoc endpoint\n");
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001908 kfree(dev);
1909 return -ENODEV;
1910 }
1911
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001912 init_waitqueue_head(&dev->open);
1913 spin_lock_init(&dev->slock);
1914 mutex_init(&dev->lock);
1915
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001916 /* init video dma queues */
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001917 INIT_LIST_HEAD(&dev->vidq.active);
1918 INIT_LIST_HEAD(&dev->vidq.queued);
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001919 INIT_LIST_HEAD(&dev->vbiq.active);
1920 INIT_LIST_HEAD(&dev->vbiq.queued);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001921
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001922 dev->vid_timeout.function = au0828_vid_buffer_timeout;
1923 dev->vid_timeout.data = (unsigned long) dev;
1924 init_timer(&dev->vid_timeout);
1925
1926 dev->vbi_timeout.function = au0828_vbi_buffer_timeout;
1927 dev->vbi_timeout.data = (unsigned long) dev;
1928 init_timer(&dev->vbi_timeout);
1929
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001930 dev->width = NTSC_STD_W;
1931 dev->height = NTSC_STD_H;
1932 dev->field_size = dev->width * dev->height;
1933 dev->frame_size = dev->field_size << 1;
1934 dev->bytesperline = dev->width << 1;
1935 dev->ctrl_ainput = 0;
1936
1937 /* allocate and fill v4l2 video struct */
1938 dev->vdev = video_device_alloc();
Devin Heitmueller62899a22009-03-15 18:48:52 -03001939 if (NULL == dev->vdev) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001940 dprintk(1, "Can't allocate video_device.\n");
1941 return -ENOMEM;
1942 }
1943
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001944 /* allocate the VBI struct */
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001945 dev->vbi_dev = video_device_alloc();
Devin Heitmueller62899a22009-03-15 18:48:52 -03001946 if (NULL == dev->vbi_dev) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001947 dprintk(1, "Can't allocate vbi_device.\n");
1948 kfree(dev->vdev);
1949 return -ENOMEM;
1950 }
1951
1952 /* Fill the video capture device struct */
1953 *dev->vdev = au0828_video_template;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001954 dev->vdev->parent = &dev->usbdev->dev;
1955 strcpy(dev->vdev->name, "au0828a video");
1956
1957 /* Setup the VBI device */
1958 *dev->vbi_dev = au0828_video_template;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001959 dev->vbi_dev->parent = &dev->usbdev->dev;
1960 strcpy(dev->vbi_dev->name, "au0828a vbi");
1961
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001962 /* Register the v4l2 device */
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001963 video_set_drvdata(dev->vdev, dev);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001964 retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1);
1965 if (retval != 0) {
1966 dprintk(1, "unable to register video device (error = %d).\n",
1967 retval);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001968 video_device_release(dev->vdev);
1969 return -ENODEV;
1970 }
1971
1972 /* Register the vbi device */
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001973 video_set_drvdata(dev->vbi_dev, dev);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001974 retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1);
1975 if (retval != 0) {
1976 dprintk(1, "unable to register vbi device (error = %d).\n",
1977 retval);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001978 video_device_release(dev->vbi_dev);
1979 video_device_release(dev->vdev);
1980 return -ENODEV;
1981 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001982
Devin Heitmueller62899a22009-03-15 18:48:52 -03001983 dprintk(1, "%s completed!\n", __func__);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001984
1985 return 0;
1986}
1987