blob: 9c475c600fc9c9a0d8a5f7a568dae7a88579ee4d [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
Devin Heitmuellerbf797162010-10-09 15:09:17 -03001119 if (dev->vbi_timeout_running == 0) {
1120 /* Handle case where caller tries to read without
1121 calling streamon first */
1122 dev->vbi_timeout_running = 1;
1123 mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
1124 }
1125
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001126 return videobuf_read_stream(&fh->vb_vbiq, buf, count, pos, 0,
1127 filp->f_flags & O_NONBLOCK);
1128 }
1129
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001130 return 0;
1131}
1132
1133static unsigned int au0828_v4l2_poll(struct file *filp, poll_table *wait)
1134{
1135 struct au0828_fh *fh = filp->private_data;
1136 struct au0828_dev *dev = fh->dev;
1137 int rc;
1138
1139 rc = check_dev(dev);
1140 if (rc < 0)
1141 return rc;
1142
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001143 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1144 if (!res_get(fh, AU0828_RESOURCE_VIDEO))
1145 return POLLERR;
1146 return videobuf_poll_stream(filp, &fh->vb_vidq, wait);
1147 } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
1148 if (!res_get(fh, AU0828_RESOURCE_VBI))
1149 return POLLERR;
1150 return videobuf_poll_stream(filp, &fh->vb_vbiq, wait);
1151 } else {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001152 return POLLERR;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001153 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001154}
1155
1156static int au0828_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
1157{
1158 struct au0828_fh *fh = filp->private_data;
1159 struct au0828_dev *dev = fh->dev;
1160 int rc;
1161
1162 rc = check_dev(dev);
1163 if (rc < 0)
1164 return rc;
1165
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001166 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1167 rc = videobuf_mmap_mapper(&fh->vb_vidq, vma);
1168 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1169 rc = videobuf_mmap_mapper(&fh->vb_vbiq, vma);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001170
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001171 return rc;
1172}
1173
1174static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd,
1175 struct v4l2_format *format)
1176{
1177 int ret;
1178 int width = format->fmt.pix.width;
1179 int height = format->fmt.pix.height;
1180 unsigned int maxwidth, maxheight;
1181
1182 maxwidth = 720;
1183 maxheight = 480;
1184
Devin Heitmueller62899a22009-03-15 18:48:52 -03001185 if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001186 return -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001187
1188 /* If they are demanding a format other than the one we support,
1189 bail out (tvtime asks for UYVY and then retries with YUYV) */
Devin Heitmueller62899a22009-03-15 18:48:52 -03001190 if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_UYVY)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001191 return -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001192
1193 /* format->fmt.pix.width only support 720 and height 480 */
Devin Heitmueller62899a22009-03-15 18:48:52 -03001194 if (width != 720)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001195 width = 720;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001196 if (height != 480)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001197 height = 480;
1198
1199 format->fmt.pix.width = width;
1200 format->fmt.pix.height = height;
1201 format->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
1202 format->fmt.pix.bytesperline = width * 2;
1203 format->fmt.pix.sizeimage = width * height * 2;
1204 format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
1205 format->fmt.pix.field = V4L2_FIELD_INTERLACED;
1206
Devin Heitmueller62899a22009-03-15 18:48:52 -03001207 if (cmd == VIDIOC_TRY_FMT)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001208 return 0;
1209
1210 /* maybe set new image format, driver current only support 720*480 */
1211 dev->width = width;
1212 dev->height = height;
1213 dev->frame_size = width * height * 2;
1214 dev->field_size = width * height;
1215 dev->bytesperline = width * 2;
1216
Devin Heitmueller62899a22009-03-15 18:48:52 -03001217 if (dev->stream_state == STREAM_ON) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001218 dprintk(1, "VIDIOC_SET_FMT: interrupting stream!\n");
Devin Heitmueller62899a22009-03-15 18:48:52 -03001219 ret = au0828_stream_interrupt(dev);
1220 if (ret != 0) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001221 dprintk(1, "error interrupting video stream!\n");
1222 return ret;
1223 }
1224 }
1225
1226 /* set au0828 interface0 to AS5 here again */
1227 ret = usb_set_interface(dev->usbdev, 0, 5);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001228 if (ret < 0) {
1229 printk(KERN_INFO "Au0828 can't set alt setting to 5!\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001230 return -EBUSY;
1231 }
1232
1233 au0828_analog_stream_enable(dev);
1234
1235 return 0;
1236}
1237
1238
1239static int vidioc_queryctrl(struct file *file, void *priv,
1240 struct v4l2_queryctrl *qc)
1241{
1242 struct au0828_fh *fh = priv;
1243 struct au0828_dev *dev = fh->dev;
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001244 v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, qc);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001245 if (qc->type)
1246 return 0;
1247 else
1248 return -EINVAL;
1249}
1250
1251static int vidioc_querycap(struct file *file, void *priv,
1252 struct v4l2_capability *cap)
1253{
1254 struct au0828_fh *fh = priv;
1255 struct au0828_dev *dev = fh->dev;
1256
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001257 strlcpy(cap->driver, "au0828", sizeof(cap->driver));
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001258 strlcpy(cap->card, dev->board.name, sizeof(cap->card));
Devin Heitmuellerb14667f2009-03-11 03:01:04 -03001259 strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001260
1261 cap->version = AU0828_VERSION_CODE;
1262
1263 /*set the device capabilities */
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001264 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001265 V4L2_CAP_VBI_CAPTURE |
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001266 V4L2_CAP_AUDIO |
1267 V4L2_CAP_READWRITE |
1268 V4L2_CAP_STREAMING |
1269 V4L2_CAP_TUNER;
1270 return 0;
1271}
1272
1273static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
1274 struct v4l2_fmtdesc *f)
1275{
Devin Heitmueller62899a22009-03-15 18:48:52 -03001276 if (f->index)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001277 return -EINVAL;
1278
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001279 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1280 strcpy(f->description, "Packed YUV2");
1281
1282 f->flags = 0;
1283 f->pixelformat = V4L2_PIX_FMT_UYVY;
1284
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001285 return 0;
1286}
1287
1288static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
1289 struct v4l2_format *f)
1290{
1291 struct au0828_fh *fh = priv;
1292 struct au0828_dev *dev = fh->dev;
1293
1294 f->fmt.pix.width = dev->width;
1295 f->fmt.pix.height = dev->height;
1296 f->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
1297 f->fmt.pix.bytesperline = dev->bytesperline;
1298 f->fmt.pix.sizeimage = dev->frame_size;
1299 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; /* NTSC/PAL */
1300 f->fmt.pix.field = V4L2_FIELD_INTERLACED;
1301 return 0;
1302}
1303
1304static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
1305 struct v4l2_format *f)
1306{
1307 struct au0828_fh *fh = priv;
1308 struct au0828_dev *dev = fh->dev;
1309
1310 return au0828_set_format(dev, VIDIOC_TRY_FMT, f);
1311}
1312
1313static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
1314 struct v4l2_format *f)
1315{
1316 struct au0828_fh *fh = priv;
1317 struct au0828_dev *dev = fh->dev;
1318 int rc;
1319
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001320 rc = check_dev(dev);
1321 if (rc < 0)
1322 return rc;
1323
1324 mutex_lock(&dev->lock);
1325
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001326 if (videobuf_queue_is_busy(&fh->vb_vidq)) {
Devin Heitmueller62899a22009-03-15 18:48:52 -03001327 printk(KERN_INFO "%s queue busy\n", __func__);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001328 rc = -EBUSY;
1329 goto out;
1330 }
1331
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001332 rc = au0828_set_format(dev, VIDIOC_S_FMT, f);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001333out:
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001334 mutex_unlock(&dev->lock);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001335 return rc;
1336}
1337
1338static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm)
1339{
1340 struct au0828_fh *fh = priv;
1341 struct au0828_dev *dev = fh->dev;
1342
1343 /* FIXME: when we support something other than NTSC, we are going to
1344 have to make the au0828 bridge adjust the size of its capture
1345 buffer, which is currently hardcoded at 720x480 */
1346
Hans Verkuilf41737e2009-04-01 03:52:39 -03001347 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, *norm);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001348 return 0;
1349}
1350
1351static int vidioc_enum_input(struct file *file, void *priv,
1352 struct v4l2_input *input)
1353{
1354 struct au0828_fh *fh = priv;
1355 struct au0828_dev *dev = fh->dev;
1356 unsigned int tmp;
1357
1358 static const char *inames[] = {
Devin Heitmueller3d622872009-03-15 17:48:26 -03001359 [AU0828_VMUX_UNDEFINED] = "Undefined",
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001360 [AU0828_VMUX_COMPOSITE] = "Composite",
1361 [AU0828_VMUX_SVIDEO] = "S-Video",
1362 [AU0828_VMUX_CABLE] = "Cable TV",
1363 [AU0828_VMUX_TELEVISION] = "Television",
1364 [AU0828_VMUX_DVB] = "DVB",
1365 [AU0828_VMUX_DEBUG] = "tv debug"
1366 };
1367
1368 tmp = input->index;
1369
Dan Carpenterf5e20c32010-03-28 08:21:18 -03001370 if (tmp >= AU0828_MAX_INPUT)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001371 return -EINVAL;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001372 if (AUVI_INPUT(tmp).type == 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001373 return -EINVAL;
1374
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001375 input->index = tmp;
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001376 strcpy(input->name, inames[AUVI_INPUT(tmp).type]);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001377 if ((AUVI_INPUT(tmp).type == AU0828_VMUX_TELEVISION) ||
1378 (AUVI_INPUT(tmp).type == AU0828_VMUX_CABLE))
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001379 input->type |= V4L2_INPUT_TYPE_TUNER;
1380 else
1381 input->type |= V4L2_INPUT_TYPE_CAMERA;
1382
1383 input->std = dev->vdev->tvnorms;
1384
1385 return 0;
1386}
1387
1388static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
1389{
1390 struct au0828_fh *fh = priv;
1391 struct au0828_dev *dev = fh->dev;
1392 *i = dev->ctrl_input;
1393 return 0;
1394}
1395
1396static int vidioc_s_input(struct file *file, void *priv, unsigned int index)
1397{
1398 struct au0828_fh *fh = priv;
1399 struct au0828_dev *dev = fh->dev;
1400 int i;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001401
Devin Heitmueller62899a22009-03-15 18:48:52 -03001402 dprintk(1, "VIDIOC_S_INPUT in function %s, input=%d\n", __func__,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001403 index);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001404 if (index >= AU0828_MAX_INPUT)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001405 return -EINVAL;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001406 if (AUVI_INPUT(index).type == 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001407 return -EINVAL;
1408 dev->ctrl_input = index;
1409
Devin Heitmueller62899a22009-03-15 18:48:52 -03001410 switch (AUVI_INPUT(index).type) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001411 case AU0828_VMUX_SVIDEO:
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001412 dev->input_type = AU0828_VMUX_SVIDEO;
1413 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001414 case AU0828_VMUX_COMPOSITE:
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001415 dev->input_type = AU0828_VMUX_COMPOSITE;
1416 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001417 case AU0828_VMUX_TELEVISION:
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001418 dev->input_type = AU0828_VMUX_TELEVISION;
1419 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001420 default:
Devin Heitmuellera1094c42009-03-15 17:43:13 -03001421 dprintk(1, "VIDIOC_S_INPUT unknown input type set [%d]\n",
1422 AUVI_INPUT(index).type);
1423 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001424 }
1425
Hans Verkuil5325b422009-04-02 11:26:22 -03001426 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing,
1427 AUVI_INPUT(index).vmux, 0, 0);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001428
1429 for (i = 0; i < AU0828_MAX_INPUT; i++) {
1430 int enable = 0;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001431 if (AUVI_INPUT(i).audio_setup == NULL)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001432 continue;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001433
1434 if (i == index)
1435 enable = 1;
1436 else
1437 enable = 0;
1438 if (enable) {
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001439 (AUVI_INPUT(i).audio_setup)(dev, enable);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001440 } else {
1441 /* Make sure we leave it turned on if some
1442 other input is routed to this callback */
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001443 if ((AUVI_INPUT(i).audio_setup) !=
1444 ((AUVI_INPUT(index).audio_setup))) {
1445 (AUVI_INPUT(i).audio_setup)(dev, enable);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001446 }
1447 }
1448 }
1449
Hans Verkuil5325b422009-04-02 11:26:22 -03001450 v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing,
1451 AUVI_INPUT(index).amux, 0, 0);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001452 return 0;
1453}
1454
1455static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
1456{
1457 struct au0828_fh *fh = priv;
1458 struct au0828_dev *dev = fh->dev;
1459 unsigned int index = a->index;
1460
Devin Heitmueller62899a22009-03-15 18:48:52 -03001461 if (a->index > 1)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001462 return -EINVAL;
1463
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001464 index = dev->ctrl_ainput;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001465 if (index == 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001466 strcpy(a->name, "Television");
1467 else
1468 strcpy(a->name, "Line in");
1469
1470 a->capability = V4L2_AUDCAP_STEREO;
1471 a->index = index;
1472 return 0;
1473}
1474
1475static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
1476{
1477 struct au0828_fh *fh = priv;
1478 struct au0828_dev *dev = fh->dev;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001479 if (a->index != dev->ctrl_ainput)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001480 return -EINVAL;
1481 return 0;
1482}
1483
1484static int vidioc_g_ctrl(struct file *file, void *priv,
1485 struct v4l2_control *ctrl)
1486{
1487 struct au0828_fh *fh = priv;
1488 struct au0828_dev *dev = fh->dev;
1489
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001490 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001491 return 0;
1492
1493}
1494
1495static int vidioc_s_ctrl(struct file *file, void *priv,
1496 struct v4l2_control *ctrl)
1497{
1498 struct au0828_fh *fh = priv;
1499 struct au0828_dev *dev = fh->dev;
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001500 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_ctrl, ctrl);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001501 return 0;
1502}
1503
1504static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
1505{
1506 struct au0828_fh *fh = priv;
1507 struct au0828_dev *dev = fh->dev;
1508
Devin Heitmueller62899a22009-03-15 18:48:52 -03001509 if (t->index != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001510 return -EINVAL;
1511
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001512 strcpy(t->name, "Auvitek tuner");
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001513 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001514 return 0;
1515}
1516
1517static int vidioc_s_tuner(struct file *file, void *priv,
1518 struct v4l2_tuner *t)
1519{
1520 struct au0828_fh *fh = priv;
1521 struct au0828_dev *dev = fh->dev;
1522
Devin Heitmueller62899a22009-03-15 18:48:52 -03001523 if (t->index != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001524 return -EINVAL;
1525
1526 t->type = V4L2_TUNER_ANALOG_TV;
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001527 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001528 dprintk(1, "VIDIOC_S_TUNER: signal = %x, afc = %x\n", t->signal,
1529 t->afc);
1530 return 0;
1531
1532}
1533
1534static int vidioc_g_frequency(struct file *file, void *priv,
1535 struct v4l2_frequency *freq)
1536{
1537 struct au0828_fh *fh = priv;
1538 struct au0828_dev *dev = fh->dev;
Devin Heitmuellerc8889232009-03-15 17:38:47 -03001539
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001540 freq->type = V4L2_TUNER_ANALOG_TV;
1541 freq->frequency = dev->ctrl_freq;
1542 return 0;
1543}
1544
1545static int vidioc_s_frequency(struct file *file, void *priv,
1546 struct v4l2_frequency *freq)
1547{
1548 struct au0828_fh *fh = priv;
1549 struct au0828_dev *dev = fh->dev;
1550
Devin Heitmueller62899a22009-03-15 18:48:52 -03001551 if (freq->tuner != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001552 return -EINVAL;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001553 if (freq->type != V4L2_TUNER_ANALOG_TV)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001554 return -EINVAL;
1555
1556 dev->ctrl_freq = freq->frequency;
1557
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001558 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, freq);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001559
1560 au0828_analog_stream_reset(dev);
1561
1562 return 0;
1563}
1564
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001565
1566/* RAW VBI ioctls */
1567
1568static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
1569 struct v4l2_format *format)
1570{
1571 struct au0828_fh *fh = priv;
1572 struct au0828_dev *dev = fh->dev;
1573
1574 format->fmt.vbi.samples_per_line = dev->vbi_width;
1575 format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
1576 format->fmt.vbi.offset = 0;
1577 format->fmt.vbi.flags = 0;
1578 format->fmt.vbi.sampling_rate = 6750000 * 4 / 2;
1579
1580 format->fmt.vbi.count[0] = dev->vbi_height;
1581 format->fmt.vbi.count[1] = dev->vbi_height;
1582 format->fmt.vbi.start[0] = 21;
1583 format->fmt.vbi.start[1] = 284;
1584
1585 return 0;
1586}
1587
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001588static int vidioc_g_chip_ident(struct file *file, void *priv,
1589 struct v4l2_dbg_chip_ident *chip)
1590{
1591 struct au0828_fh *fh = priv;
1592 struct au0828_dev *dev = fh->dev;
1593 chip->ident = V4L2_IDENT_NONE;
1594 chip->revision = 0;
1595
Devin Heitmuellerd9109be2009-03-11 03:00:58 -03001596 if (v4l2_chip_match_host(&chip->match)) {
1597 chip->ident = V4L2_IDENT_AU0828;
1598 return 0;
1599 }
1600
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001601 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_chip_ident, chip);
Devin Heitmuellerd9109be2009-03-11 03:00:58 -03001602 if (chip->ident == V4L2_IDENT_NONE)
1603 return -EINVAL;
1604
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001605 return 0;
1606}
1607
1608static int vidioc_cropcap(struct file *file, void *priv,
1609 struct v4l2_cropcap *cc)
1610{
1611 struct au0828_fh *fh = priv;
1612 struct au0828_dev *dev = fh->dev;
1613
Devin Heitmueller62899a22009-03-15 18:48:52 -03001614 if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001615 return -EINVAL;
1616
1617 cc->bounds.left = 0;
1618 cc->bounds.top = 0;
1619 cc->bounds.width = dev->width;
1620 cc->bounds.height = dev->height;
1621
1622 cc->defrect = cc->bounds;
1623
1624 cc->pixelaspect.numerator = 54;
1625 cc->pixelaspect.denominator = 59;
1626
1627 return 0;
1628}
1629
1630static int vidioc_streamon(struct file *file, void *priv,
1631 enum v4l2_buf_type type)
1632{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001633 struct au0828_fh *fh = priv;
1634 struct au0828_dev *dev = fh->dev;
1635 int rc = -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001636
1637 rc = check_dev(dev);
1638 if (rc < 0)
1639 return rc;
1640
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001641 if (unlikely(type != fh->type))
1642 return -EINVAL;
1643
1644 dprintk(1, "vidioc_streamon fh=%p t=%d fh->res=%d dev->res=%d\n",
1645 fh, type, fh->resources, dev->resources);
1646
1647 if (unlikely(!res_get(fh, get_ressource(fh))))
1648 return -EBUSY;
1649
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001650 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1651 au0828_analog_stream_enable(dev);
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001652 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001653 }
1654
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001655 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001656 rc = videobuf_streamon(&fh->vb_vidq);
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001657 dev->vid_timeout_running = 1;
1658 mod_timer(&dev->vid_timeout, jiffies + (HZ / 10));
1659 } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001660 rc = videobuf_streamon(&fh->vb_vbiq);
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001661 dev->vbi_timeout_running = 1;
1662 mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
1663 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001664
1665 return rc;
1666}
1667
1668static int vidioc_streamoff(struct file *file, void *priv,
1669 enum v4l2_buf_type type)
1670{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001671 struct au0828_fh *fh = priv;
1672 struct au0828_dev *dev = fh->dev;
1673 int rc;
1674 int i;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001675
1676 rc = check_dev(dev);
1677 if (rc < 0)
1678 return rc;
1679
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001680 if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
1681 fh->type != V4L2_BUF_TYPE_VBI_CAPTURE)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001682 return -EINVAL;
1683 if (type != fh->type)
1684 return -EINVAL;
1685
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001686 dprintk(1, "vidioc_streamoff fh=%p t=%d fh->res=%d dev->res=%d\n",
1687 fh, type, fh->resources, dev->resources);
1688
1689 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001690 dev->vid_timeout_running = 0;
1691 del_timer_sync(&dev->vid_timeout);
1692
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001693 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001694 rc = au0828_stream_interrupt(dev);
1695 if (rc != 0)
1696 return rc;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001697
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001698 for (i = 0; i < AU0828_MAX_INPUT; i++) {
1699 if (AUVI_INPUT(i).audio_setup == NULL)
1700 continue;
1701 (AUVI_INPUT(i).audio_setup)(dev, 0);
1702 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001703
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001704 videobuf_streamoff(&fh->vb_vidq);
1705 res_free(fh, AU0828_RESOURCE_VIDEO);
1706 } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001707 dev->vbi_timeout_running = 0;
1708 del_timer_sync(&dev->vbi_timeout);
1709
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001710 videobuf_streamoff(&fh->vb_vbiq);
1711 res_free(fh, AU0828_RESOURCE_VBI);
1712 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001713
1714 return 0;
1715}
1716
Mauro Carvalho Chehab80c6e352009-03-19 19:26:23 -03001717#ifdef CONFIG_VIDEO_ADV_DEBUG
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001718static int vidioc_g_register(struct file *file, void *priv,
1719 struct v4l2_dbg_register *reg)
1720{
1721 struct au0828_fh *fh = priv;
1722 struct au0828_dev *dev = fh->dev;
1723
1724 switch (reg->match.type) {
1725 case V4L2_CHIP_MATCH_I2C_DRIVER:
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001726 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001727 return 0;
1728 default:
1729 return -EINVAL;
1730 }
1731}
1732
1733static int vidioc_s_register(struct file *file, void *priv,
1734 struct v4l2_dbg_register *reg)
1735{
1736 struct au0828_fh *fh = priv;
1737 struct au0828_dev *dev = fh->dev;
1738
1739 switch (reg->match.type) {
1740 case V4L2_CHIP_MATCH_I2C_DRIVER:
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001741 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001742 return 0;
1743 default:
1744 return -EINVAL;
1745 }
1746 return 0;
1747}
Mauro Carvalho Chehab80c6e352009-03-19 19:26:23 -03001748#endif
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001749
1750static int vidioc_reqbufs(struct file *file, void *priv,
1751 struct v4l2_requestbuffers *rb)
1752{
1753 struct au0828_fh *fh = priv;
1754 struct au0828_dev *dev = fh->dev;
1755 int rc;
1756
1757 rc = check_dev(dev);
1758 if (rc < 0)
1759 return rc;
1760
Devin Heitmueller54ebb8b2011-01-23 19:12:27 -03001761 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1762 rc = videobuf_reqbufs(&fh->vb_vidq, rb);
1763 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1764 rc = videobuf_reqbufs(&fh->vb_vbiq, rb);
1765
1766 return rc;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001767}
1768
1769static int vidioc_querybuf(struct file *file, void *priv,
1770 struct v4l2_buffer *b)
1771{
1772 struct au0828_fh *fh = priv;
1773 struct au0828_dev *dev = fh->dev;
1774 int rc;
1775
1776 rc = check_dev(dev);
1777 if (rc < 0)
1778 return rc;
1779
Devin Heitmueller54ebb8b2011-01-23 19:12:27 -03001780 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1781 rc = videobuf_querybuf(&fh->vb_vidq, b);
1782 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1783 rc = videobuf_querybuf(&fh->vb_vbiq, b);
1784
1785 return rc;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001786}
1787
1788static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
1789{
1790 struct au0828_fh *fh = priv;
1791 struct au0828_dev *dev = fh->dev;
1792 int rc;
1793
1794 rc = check_dev(dev);
1795 if (rc < 0)
1796 return rc;
1797
Devin Heitmueller54ebb8b2011-01-23 19:12:27 -03001798 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1799 rc = videobuf_qbuf(&fh->vb_vidq, b);
1800 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1801 rc = videobuf_qbuf(&fh->vb_vbiq, b);
1802
1803 return rc;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001804}
1805
1806static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
1807{
1808 struct au0828_fh *fh = priv;
1809 struct au0828_dev *dev = fh->dev;
1810 int rc;
1811
1812 rc = check_dev(dev);
1813 if (rc < 0)
1814 return rc;
1815
1816 /* Workaround for a bug in the au0828 hardware design that sometimes
1817 results in the colorspace being inverted */
1818 if (dev->greenscreen_detected == 1) {
1819 dprintk(1, "Detected green frame. Resetting stream...\n");
1820 au0828_analog_stream_reset(dev);
1821 dev->greenscreen_detected = 0;
1822 }
1823
Devin Heitmueller54ebb8b2011-01-23 19:12:27 -03001824 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1825 rc = videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK);
1826 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1827 rc = videobuf_dqbuf(&fh->vb_vbiq, b, file->f_flags & O_NONBLOCK);
1828
1829 return rc;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001830}
1831
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001832static struct v4l2_file_operations au0828_v4l_fops = {
1833 .owner = THIS_MODULE,
1834 .open = au0828_v4l2_open,
1835 .release = au0828_v4l2_close,
1836 .read = au0828_v4l2_read,
1837 .poll = au0828_v4l2_poll,
1838 .mmap = au0828_v4l2_mmap,
1839 .ioctl = video_ioctl2,
1840};
1841
1842static const struct v4l2_ioctl_ops video_ioctl_ops = {
1843 .vidioc_querycap = vidioc_querycap,
1844 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1845 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1846 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1847 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001848 .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001849 .vidioc_s_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001850 .vidioc_g_audio = vidioc_g_audio,
1851 .vidioc_s_audio = vidioc_s_audio,
1852 .vidioc_cropcap = vidioc_cropcap,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001853 .vidioc_reqbufs = vidioc_reqbufs,
1854 .vidioc_querybuf = vidioc_querybuf,
1855 .vidioc_qbuf = vidioc_qbuf,
1856 .vidioc_dqbuf = vidioc_dqbuf,
1857 .vidioc_s_std = vidioc_s_std,
1858 .vidioc_enum_input = vidioc_enum_input,
1859 .vidioc_g_input = vidioc_g_input,
1860 .vidioc_s_input = vidioc_s_input,
1861 .vidioc_queryctrl = vidioc_queryctrl,
1862 .vidioc_g_ctrl = vidioc_g_ctrl,
1863 .vidioc_s_ctrl = vidioc_s_ctrl,
1864 .vidioc_streamon = vidioc_streamon,
1865 .vidioc_streamoff = vidioc_streamoff,
1866 .vidioc_g_tuner = vidioc_g_tuner,
1867 .vidioc_s_tuner = vidioc_s_tuner,
1868 .vidioc_g_frequency = vidioc_g_frequency,
1869 .vidioc_s_frequency = vidioc_s_frequency,
1870#ifdef CONFIG_VIDEO_ADV_DEBUG
1871 .vidioc_g_register = vidioc_g_register,
1872 .vidioc_s_register = vidioc_s_register,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001873#endif
Mauro Carvalho Chehab80c6e352009-03-19 19:26:23 -03001874 .vidioc_g_chip_ident = vidioc_g_chip_ident,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001875};
1876
1877static const struct video_device au0828_video_template = {
1878 .fops = &au0828_v4l_fops,
1879 .release = video_device_release,
1880 .ioctl_ops = &video_ioctl_ops,
Devin Heitmueller0ef210712009-03-11 03:00:53 -03001881 .tvnorms = V4L2_STD_NTSC_M,
1882 .current_norm = V4L2_STD_NTSC_M,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001883};
1884
1885/**************************************************************************/
1886
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001887int au0828_analog_register(struct au0828_dev *dev,
1888 struct usb_interface *interface)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001889{
1890 int retval = -ENOMEM;
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001891 struct usb_host_interface *iface_desc;
1892 struct usb_endpoint_descriptor *endpoint;
1893 int i;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001894
1895 dprintk(1, "au0828_analog_register called!\n");
1896
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001897 /* set au0828 usb interface0 to as5 */
1898 retval = usb_set_interface(dev->usbdev,
Devin Heitmueller62899a22009-03-15 18:48:52 -03001899 interface->cur_altsetting->desc.bInterfaceNumber, 5);
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001900 if (retval != 0) {
Devin Heitmueller62899a22009-03-15 18:48:52 -03001901 printk(KERN_INFO "Failure setting usb interface0 to as5\n");
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001902 return retval;
1903 }
1904
1905 /* Figure out which endpoint has the isoc interface */
1906 iface_desc = interface->cur_altsetting;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001907 for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001908 endpoint = &iface_desc->endpoint[i].desc;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001909 if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
1910 == USB_DIR_IN) &&
1911 ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
1912 == USB_ENDPOINT_XFER_ISOC)) {
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001913
1914 /* we find our isoc in endpoint */
1915 u16 tmp = le16_to_cpu(endpoint->wMaxPacketSize);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001916 dev->max_pkt_size = (tmp & 0x07ff) *
1917 (((tmp & 0x1800) >> 11) + 1);
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001918 dev->isoc_in_endpointaddr = endpoint->bEndpointAddress;
1919 }
1920 }
Devin Heitmueller62899a22009-03-15 18:48:52 -03001921 if (!(dev->isoc_in_endpointaddr)) {
1922 printk(KERN_INFO "Could not locate isoc endpoint\n");
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001923 kfree(dev);
1924 return -ENODEV;
1925 }
1926
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001927 init_waitqueue_head(&dev->open);
1928 spin_lock_init(&dev->slock);
1929 mutex_init(&dev->lock);
1930
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001931 /* init video dma queues */
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001932 INIT_LIST_HEAD(&dev->vidq.active);
1933 INIT_LIST_HEAD(&dev->vidq.queued);
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001934 INIT_LIST_HEAD(&dev->vbiq.active);
1935 INIT_LIST_HEAD(&dev->vbiq.queued);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001936
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001937 dev->vid_timeout.function = au0828_vid_buffer_timeout;
1938 dev->vid_timeout.data = (unsigned long) dev;
1939 init_timer(&dev->vid_timeout);
1940
1941 dev->vbi_timeout.function = au0828_vbi_buffer_timeout;
1942 dev->vbi_timeout.data = (unsigned long) dev;
1943 init_timer(&dev->vbi_timeout);
1944
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001945 dev->width = NTSC_STD_W;
1946 dev->height = NTSC_STD_H;
1947 dev->field_size = dev->width * dev->height;
1948 dev->frame_size = dev->field_size << 1;
1949 dev->bytesperline = dev->width << 1;
1950 dev->ctrl_ainput = 0;
1951
1952 /* allocate and fill v4l2 video struct */
1953 dev->vdev = video_device_alloc();
Devin Heitmueller62899a22009-03-15 18:48:52 -03001954 if (NULL == dev->vdev) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001955 dprintk(1, "Can't allocate video_device.\n");
1956 return -ENOMEM;
1957 }
1958
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001959 /* allocate the VBI struct */
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001960 dev->vbi_dev = video_device_alloc();
Devin Heitmueller62899a22009-03-15 18:48:52 -03001961 if (NULL == dev->vbi_dev) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001962 dprintk(1, "Can't allocate vbi_device.\n");
1963 kfree(dev->vdev);
1964 return -ENOMEM;
1965 }
1966
1967 /* Fill the video capture device struct */
1968 *dev->vdev = au0828_video_template;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001969 dev->vdev->parent = &dev->usbdev->dev;
1970 strcpy(dev->vdev->name, "au0828a video");
1971
1972 /* Setup the VBI device */
1973 *dev->vbi_dev = au0828_video_template;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001974 dev->vbi_dev->parent = &dev->usbdev->dev;
1975 strcpy(dev->vbi_dev->name, "au0828a vbi");
1976
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001977 /* Register the v4l2 device */
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001978 video_set_drvdata(dev->vdev, dev);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001979 retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1);
1980 if (retval != 0) {
1981 dprintk(1, "unable to register video device (error = %d).\n",
1982 retval);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001983 video_device_release(dev->vdev);
1984 return -ENODEV;
1985 }
1986
1987 /* Register the vbi device */
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001988 video_set_drvdata(dev->vbi_dev, dev);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001989 retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1);
1990 if (retval != 0) {
1991 dprintk(1, "unable to register vbi device (error = %d).\n",
1992 retval);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001993 video_device_release(dev->vbi_dev);
1994 video_device_release(dev->vdev);
1995 return -ENODEV;
1996 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001997
Devin Heitmueller62899a22009-03-15 18:48:52 -03001998 dprintk(1, "%s completed!\n", __func__);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001999
2000 return 0;
2001}
2002